summaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/Kconfig185
-rw-r--r--drivers/ide/Makefile62
-rw-r--r--drivers/ide/arm/Makefile4
-rw-r--r--drivers/ide/arm/bast-ide.c23
-rw-r--r--drivers/ide/arm/icside.c100
-rw-r--r--drivers/ide/arm/ide_arm.c17
-rw-r--r--drivers/ide/arm/rapide.c41
-rw-r--r--drivers/ide/cris/Makefile2
-rw-r--r--drivers/ide/cris/ide-cris.c64
-rw-r--r--drivers/ide/h8300/Makefile2
-rw-r--r--drivers/ide/h8300/ide-h8300.c28
-rw-r--r--drivers/ide/ide-acpi.c116
-rw-r--r--drivers/ide/ide-cd.c2389
-rw-r--r--drivers/ide/ide-cd.h705
-rw-r--r--drivers/ide/ide-cd_ioctl.c475
-rw-r--r--drivers/ide/ide-cd_verbose.c359
-rw-r--r--drivers/ide/ide-disk.c479
-rw-r--r--drivers/ide/ide-dma.c328
-rw-r--r--drivers/ide/ide-floppy.c1665
-rw-r--r--drivers/ide/ide-generic.c8
-rw-r--r--drivers/ide/ide-io.c366
-rw-r--r--drivers/ide/ide-iops.c204
-rw-r--r--drivers/ide/ide-lib.c288
-rw-r--r--drivers/ide/ide-pnp.c33
-rw-r--r--drivers/ide/ide-probe.c707
-rw-r--r--drivers/ide/ide-proc.c21
-rw-r--r--drivers/ide/ide-scan-pci.c116
-rw-r--r--drivers/ide/ide-tape.c1459
-rw-r--r--drivers/ide/ide-taskfile.c643
-rw-r--r--drivers/ide/ide-timing.h2
-rw-r--r--drivers/ide/ide.c422
-rw-r--r--drivers/ide/legacy/Makefile19
-rw-r--r--drivers/ide/legacy/ali14xx.c38
-rw-r--r--drivers/ide/legacy/buddha.c46
-rw-r--r--drivers/ide/legacy/dtc2278.c41
-rw-r--r--drivers/ide/legacy/falconide.c25
-rw-r--r--drivers/ide/legacy/gayle.c45
-rw-r--r--drivers/ide/legacy/ht6560b.c55
-rw-r--r--drivers/ide/legacy/ide-cs.c31
-rw-r--r--drivers/ide/legacy/ide_platform.c77
-rw-r--r--drivers/ide/legacy/macide.c52
-rw-r--r--drivers/ide/legacy/q40ide.c26
-rw-r--r--drivers/ide/legacy/qd65xx.c74
-rw-r--r--drivers/ide/legacy/qd65xx.h2
-rw-r--r--drivers/ide/legacy/umc8672.c31
-rw-r--r--drivers/ide/mips/au1xxx-ide.c110
-rw-r--r--drivers/ide/mips/swarm.c3
-rw-r--r--drivers/ide/pci/Makefile4
-rw-r--r--drivers/ide/pci/aec62xx.c59
-rw-r--r--drivers/ide/pci/alim15x3.c34
-rw-r--r--drivers/ide/pci/amd74xx.c303
-rw-r--r--drivers/ide/pci/atiixp.c109
-rw-r--r--drivers/ide/pci/cmd640.c49
-rw-r--r--drivers/ide/pci/cmd64x.c151
-rw-r--r--drivers/ide/pci/cs5520.c44
-rw-r--r--drivers/ide/pci/cs5530.c13
-rw-r--r--drivers/ide/pci/cs5535.c14
-rw-r--r--drivers/ide/pci/cy82c693.c70
-rw-r--r--drivers/ide/pci/delkin_cb.c45
-rw-r--r--drivers/ide/pci/generic.c12
-rw-r--r--drivers/ide/pci/hpt34x.c25
-rw-r--r--drivers/ide/pci/hpt366.c390
-rw-r--r--drivers/ide/pci/it8213.c48
-rw-r--r--drivers/ide/pci/it821x.c98
-rw-r--r--drivers/ide/pci/jmicron.c14
-rw-r--r--drivers/ide/pci/ns87415.c24
-rw-r--r--drivers/ide/pci/opti621.c17
-rw-r--r--drivers/ide/pci/pdc202xx_new.c96
-rw-r--r--drivers/ide/pci/pdc202xx_old.c67
-rw-r--r--drivers/ide/pci/piix.c83
-rw-r--r--drivers/ide/pci/rz1000.c14
-rw-r--r--drivers/ide/pci/sc1200.c201
-rw-r--r--drivers/ide/pci/scc_pata.c37
-rw-r--r--drivers/ide/pci/serverworks.c75
-rw-r--r--drivers/ide/pci/sgiioc4.c89
-rw-r--r--drivers/ide/pci/siimage.c171
-rw-r--r--drivers/ide/pci/sis5513.c135
-rw-r--r--drivers/ide/pci/sl82c105.c136
-rw-r--r--drivers/ide/pci/slc90e66.c47
-rw-r--r--drivers/ide/pci/tc86c001.c32
-rw-r--r--drivers/ide/pci/triflex.c11
-rw-r--r--drivers/ide/pci/trm290.c97
-rw-r--r--drivers/ide/pci/via82cxxx.c26
-rw-r--r--drivers/ide/ppc/Makefile3
-rw-r--r--drivers/ide/ppc/mpc8xx.c20
-rw-r--r--drivers/ide/ppc/pmac.c217
-rw-r--r--drivers/ide/setup-pci.c330
87 files changed, 5977 insertions, 9421 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 6eaece96524..45b26ed351c 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -152,9 +152,22 @@ config BLK_DEV_IDEDISK
If unsure, say Y.
config IDEDISK_MULTI_MODE
- bool "Use multi-mode by default"
- help
- If you get this error, try to say Y here:
+ bool "Use multiple sector mode for Programmed Input/Output by default"
+ help
+ This setting is irrelevant for most IDE disks, with direct memory
+ access, to which multiple sector mode does not apply. Multiple sector
+ mode is a feature of most modern IDE hard drives, permitting the
+ transfer of multiple sectors per Programmed Input/Output interrupt,
+ rather than the usual one sector per interrupt. When this feature is
+ enabled, it can reduce operating system overhead for disk Programmed
+ Input/Output. On some systems, it also can increase the data
+ throughput of Programmed Input/Output. Some drives, however, seemed
+ to run slower with multiple sector mode enabled. Some drives claimed
+ to support multiple sector mode, but lost data at some settings.
+ Under rare circumstances, such failures could result in massive
+ filesystem corruption.
+
+ If you get the following error, try to say Y here:
hda: set_multmode: status=0x51 { DriveReady SeekComplete Error }
hda: set_multmode: error=0x04 { DriveStatusError }
@@ -190,16 +203,20 @@ config BLK_DEV_IDECD
CD-ROM drive, you can say N to all other CD-ROM options, but be sure
to say Y or M to "ISO 9660 CD-ROM file system support".
- Note that older versions of LILO (LInux LOader) cannot properly deal
- with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from
- <http://lilo.go.dyndns.org/>.
-
To compile this driver as a module, choose M here: the
module will be called ide-cd.
+config BLK_DEV_IDECD_VERBOSE_ERRORS
+ bool "Verbose error logging for IDE/ATAPI CDROM driver" if EMBEDDED
+ depends on BLK_DEV_IDECD
+ default y
+ help
+ Turn this on to have the driver print out the meanings of the
+ ATAPI error codes. This will use up additional 8kB of kernel-space
+ memory, though.
+
config BLK_DEV_IDETAPE
- tristate "Include IDE/ATAPI TAPE support (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ tristate "Include IDE/ATAPI TAPE support"
help
If you have an IDE tape drive using the ATAPI protocol, say Y.
ATAPI is a newer protocol used by IDE tape and CD-ROM drives,
@@ -304,7 +321,6 @@ comment "IDE chipset support/bugfixes"
config IDE_GENERIC
tristate "generic/default IDE chipset support"
- default H8300
help
If unsure, say N.
@@ -317,7 +333,7 @@ config BLK_DEV_PLATFORM
If unsure, say N.
config BLK_DEV_CMD640
- bool "CMD640 chipset bugfix/support"
+ tristate "CMD640 chipset bugfix/support"
depends on X86
---help---
The CMD-Technologies CMD640 IDE chip is used on many common 486 and
@@ -351,9 +367,8 @@ config BLK_DEV_CMD640_ENHANCED
Otherwise say N.
config BLK_DEV_IDEPNP
- bool "PNP EIDE support"
+ tristate "PNP EIDE support"
depends on PNP
- select IDE_GENERIC
help
If you have a PnP (Plug and Play) compatible EIDE card and
would like the kernel to automatically detect and activate
@@ -366,23 +381,25 @@ comment "PCI IDE chipsets support"
config BLK_DEV_IDEPCI
bool
-config IDEPCI_SHARE_IRQ
- bool "Sharing PCI IDE interrupts support"
- depends on BLK_DEV_IDEPCI
+config IDEPCI_PCIBUS_ORDER
+ bool "Probe IDE PCI devices in the PCI bus order (DEPRECATED)"
+ depends on BLK_DEV_IDE=y && BLK_DEV_IDEPCI
+ default y
help
- Some ATA/IDE chipsets have hardware support which allows for
- sharing a single IRQ with other cards. To enable support for
- this in the ATA/IDE driver, say Y here.
+ Probe IDE PCI devices in the order in which they appear on the
+ PCI bus (i.e. 00:1f.1 PCI device before 02:01.0 PCI device)
+ instead of the order in which IDE PCI host drivers are loaded.
- It is safe to say Y to this question, in most cases.
- If unsure, say N.
+ Please note that this method of assuring stable naming of
+ IDE devices is unreliable and use other means for achieving
+ it (i.e. udev).
-config IDEPCI_PCIBUS_ORDER
- def_bool BLK_DEV_IDE=y && BLK_DEV_IDEPCI
+ If in doubt, say N.
+# TODO: split it on per host driver config options (or module parameters)
config BLK_DEV_OFFBOARD
- bool "Boot off-board chipsets first support"
- depends on BLK_DEV_IDEPCI
+ bool "Boot off-board chipsets first support (DEPRECATED)"
+ depends on BLK_DEV_IDEPCI && (BLK_DEV_AEC62XX || BLK_DEV_GENERIC || BLK_DEV_HPT34X || BLK_DEV_HPT366 || BLK_DEV_PDC202XX_NEW || BLK_DEV_PDC202XX_OLD || BLK_DEV_TC86C001)
help
Normally, IDE controllers built into the motherboard (on-board
controllers) are assigned to ide0 and ide1 while those on add-in PCI
@@ -401,6 +418,10 @@ config BLK_DEV_OFFBOARD
Note that, if you do this, the order of the hd* devices will be
rearranged which may require modification of fstab and other files.
+ Please also note that this method of assuring stable naming of
+ IDE devices is unreliable and use other means for achieving it
+ (i.e. udev).
+
If in doubt, say N.
config BLK_DEV_GENERIC
@@ -474,6 +495,7 @@ config WDC_ALI15X3
config BLK_DEV_AMD74XX
tristate "AMD and nVidia IDE support"
+ depends on !ARM
select BLK_DEV_IDEDMA_PCI
help
This driver adds explicit support for AMD-7xx and AMD-8111 chips
@@ -603,8 +625,8 @@ config BLK_DEV_SC1200
tristate "National SCx200 chipset support"
select BLK_DEV_IDEDMA_PCI
help
- This driver adds support for the built in IDE on the National
- SCx200 series of embedded x86 "Geode" systems
+ This driver adds support for the on-board IDE controller on the
+ National SCx200 series of embedded x86 "Geode" systems.
config BLK_DEV_PIIX
tristate "Intel PIIXn chipsets support"
@@ -693,7 +715,6 @@ config BLK_DEV_SVWKS
config BLK_DEV_SGIIOC4
tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
- select IDEPCI_SHARE_IRQ
select BLK_DEV_IDEDMA_PCI
help
This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
@@ -780,22 +801,22 @@ config BLK_DEV_CELLEB
depends on PPC_CELLEB
select BLK_DEV_IDEDMA_PCI
help
- This driver provides support for the built-in IDE controller on
+ This driver provides support for the on-board IDE controller on
Toshiba Cell Reference Board.
If unsure, say Y.
endif
config BLK_DEV_IDE_PMAC
- bool "Builtin PowerMac IDE support"
+ tristate "PowerMac on-board IDE support"
depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
help
- This driver provides support for the built-in IDE controller on
+ This driver provides support for the on-board IDE controller on
most of the recent Apple Power Macintoshes and PowerBooks.
If unsure, say Y.
config BLK_DEV_IDE_PMAC_ATA100FIRST
- bool "Probe internal ATA/100 (Kauai) first"
+ bool "Probe on-board ATA/100 (Kauai) first"
depends on BLK_DEV_IDE_PMAC
help
This option will cause the ATA/100 controller found in UniNorth2
@@ -810,7 +831,7 @@ config BLK_DEV_IDEDMA_PMAC
depends on BLK_DEV_IDE_PMAC
select BLK_DEV_IDEDMA_PCI
help
- This option allows the driver for the built-in IDE controller on
+ This option allows the driver for the on-board IDE controller on
Power Macintoshes and PowerBooks to use DMA (direct memory access)
to transfer data to and from memory. Saying Y is safe and improves
performance.
@@ -841,8 +862,9 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
depends on BLK_DEV_IDE_AU1XXX
config IDE_ARM
- def_bool ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
- select IDE_GENERIC
+ tristate "ARM IDE support"
+ depends on ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
+ default y
config BLK_DEV_IDE_ICSIDE
tristate "ICS IDE interface support"
@@ -873,14 +895,54 @@ config BLK_DEV_IDE_BAST
Say Y here if you want to support the onboard IDE channels on the
Simtec BAST or the Thorcom VR1000
+config ETRAX_IDE
+ tristate "ETRAX IDE support"
+ depends on CRIS && BROKEN
+ select BLK_DEV_IDEDMA
+ help
+ Enables the ETRAX IDE driver.
+
+ You can't use parallel ports or SCSI ports at the same time.
+
+config ETRAX_IDE_DELAY
+ int "Delay for drives to regain consciousness"
+ depends on ETRAX_IDE && ETRAX_ARCH_V10
+ default 15
+ help
+ Number of seconds to wait for IDE drives to spin up after an IDE
+ reset.
+
+choice
+ prompt "IDE reset pin"
+ depends on ETRAX_IDE && ETRAX_ARCH_V10
+ default ETRAX_IDE_PB7_RESET
+
+config ETRAX_IDE_PB7_RESET
+ bool "Port_PB_Bit_7"
+ help
+ IDE reset on pin 7 on port B
+
+config ETRAX_IDE_G27_RESET
+ bool "Port_G_Bit_27"
+ help
+ IDE reset on pin 27 on port G
+
+endchoice
+
+config IDE_H8300
+ tristate "H8300 IDE support"
+ depends on H8300
+ default y
+ help
+ Enables the H8300 IDE driver.
+
config BLK_DEV_GAYLE
- bool "Amiga Gayle IDE interface support"
+ tristate "Amiga Gayle IDE interface support"
depends on AMIGA
- select IDE_GENERIC
help
This is the IDE driver for the Amiga Gayle IDE interface. It supports
both the `A1200 style' and `A4000 style' of the Gayle IDE interface,
- This includes builtin IDE interfaces on some Amiga models (A600,
+ This includes on-board IDE interfaces on some Amiga models (A600,
A1200, A4000, and A4000T), and IDE interfaces on the Zorro expansion
bus (M-Tech E-Matrix 530 expansion card).
Say Y if you have an Amiga with a Gayle IDE interface and want to use
@@ -894,10 +956,10 @@ config BLK_DEV_IDEDOUBLER
depends on BLK_DEV_GAYLE && EXPERIMENTAL
---help---
This driver provides support for the so-called `IDE doublers' (made
- by various manufacturers, e.g. Eyetech) that can be connected to the
- builtin IDE interface of some Amiga models. Using such an IDE
- doubler, you can connect up to four instead of two IDE devices on
- the Amiga's builtin IDE interface.
+ by various manufacturers, e.g. Eyetech) that can be connected to
+ the on-board IDE interface of some Amiga models. Using such an IDE
+ doubler, you can connect up to four instead of two IDE devices to
+ the Amiga's on-board IDE interface.
Note that the normal Amiga Gayle IDE driver may not work correctly
if you have an IDE doubler and don't enable this driver!
@@ -906,55 +968,50 @@ config BLK_DEV_IDEDOUBLER
runtime using the "ide=doubler" kernel boot parameter.
config BLK_DEV_BUDDHA
- bool "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)"
+ tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)"
depends on ZORRO && EXPERIMENTAL
- select IDE_GENERIC
help
- This is the IDE driver for the IDE interfaces on the Buddha,
- Catweasel and X-Surf expansion boards. It supports up to two interfaces
- on the Buddha, three on the Catweasel and two on the X-Surf.
+ This is the IDE driver for the IDE interfaces on the Buddha, Catweasel
+ and X-Surf expansion boards. It supports up to two interfaces on the
+ Buddha, three on the Catweasel and two on the X-Surf.
Say Y if you have a Buddha or Catweasel expansion board and want to
use IDE devices (hard disks, CD-ROM drives, etc.) that are connected
to one of its IDE interfaces.
config BLK_DEV_FALCON_IDE
- bool "Falcon IDE interface support"
+ tristate "Falcon IDE interface support"
depends on ATARI
- select IDE_GENERIC
help
- This is the IDE driver for the builtin IDE interface on the Atari
+ This is the IDE driver for the on-board IDE interface on the Atari
Falcon. Say Y if you have a Falcon and want to use IDE devices (hard
- disks, CD-ROM drives, etc.) that are connected to the builtin IDE
+ disks, CD-ROM drives, etc.) that are connected to the on-board IDE
interface.
config BLK_DEV_MAC_IDE
- bool "Macintosh Quadra/Powerbook IDE interface support"
+ tristate "Macintosh Quadra/Powerbook IDE interface support"
depends on MAC
- select IDE_GENERIC
help
- This is the IDE driver for the builtin IDE interface on some m68k
+ This is the IDE driver for the on-board IDE interface on some m68k
Macintosh models. It supports both the `Quadra style' (used in
Quadra/ Centris 630 and Performa 588 models) and `Powerbook style'
(used in the Powerbook 150 and 190 models) IDE interface.
Say Y if you have such an Macintosh model and want to use IDE
devices (hard disks, CD-ROM drives, etc.) that are connected to the
- builtin IDE interface.
+ on-board IDE interface.
config BLK_DEV_Q40IDE
- bool "Q40/Q60 IDE interface support"
+ tristate "Q40/Q60 IDE interface support"
depends on Q40
- select IDE_GENERIC
help
Enable the on-board IDE controller in the Q40/Q60. This should
normally be on; disable it only if you are running a custom hard
drive subsystem through an expansion card.
config BLK_DEV_MPC8xx_IDE
- bool "MPC8xx IDE support"
- depends on 8xx && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
- select IDE_GENERIC
+ tristate "MPC8xx IDE support"
+ depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
help
This option provides support for IDE on Motorola MPC8xx Systems.
Please see 'Type of MPC8xx IDE interface' for details.
@@ -1013,8 +1070,8 @@ config BLK_DEV_ALI14XX
boot parameter. It enables support for the secondary IDE interface
of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
I/O speeds to be set as well. See the files
- <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c> for
- more info.
+ <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c>
+ for more info.
config BLK_DEV_DTC2278
tristate "DTC-2278 support"
@@ -1039,8 +1096,8 @@ config BLK_DEV_QD65XX
help
This driver is enabled at runtime using the "qd65xx.probe" kernel
boot parameter. It permits faster I/O speeds to be set. See the
- <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> for
- more info.
+ <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c>
+ for more info.
config BLK_DEV_UMC8672
tristate "UMC-8672 support"
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 75dc6969e0a..a4a4323be91 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -7,48 +7,60 @@
# Note : at this point, these files are compiled on all systems.
# In the future, some of these should be built conditionally.
#
-# First come modules that register themselves with the core
+# link order is important here
EXTRA_CFLAGS += -Idrivers/ide
-obj-$(CONFIG_BLK_DEV_IDE) += pci/
-
ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o
-ide-core-$(CONFIG_BLK_DEV_CMD640) += pci/cmd640.o
-
-# Core IDE code - must come before legacy
+# core IDE code
ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o
-ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
-# built-in only drivers from arm/
-ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o
+obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o
-# built-in only drivers from legacy/
-ide-core-$(CONFIG_BLK_DEV_BUDDHA) += legacy/buddha.o
-ide-core-$(CONFIG_BLK_DEV_FALCON_IDE) += legacy/falconide.o
-ide-core-$(CONFIG_BLK_DEV_GAYLE) += legacy/gayle.o
-ide-core-$(CONFIG_BLK_DEV_MAC_IDE) += legacy/macide.o
-ide-core-$(CONFIG_BLK_DEV_Q40IDE) += legacy/q40ide.o
+ifeq ($(CONFIG_IDE_ARM), y)
+ ide-arm-core-y += arm/ide_arm.o
+ obj-y += ide-arm-core.o
+endif
-# built-in only drivers from ppc/
-ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o
-ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o
+obj-$(CONFIG_BLK_DEV_IDE) += legacy/ pci/
-# built-in only drivers from h8300/
-ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o
+obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o
-obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o
+ifeq ($(CONFIG_BLK_DEV_CMD640), y)
+ cmd640-core-y += pci/cmd640.o
+ obj-y += cmd640-core.o
+endif
+
+obj-$(CONFIG_BLK_DEV_IDE) += cris/ ppc/
+obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
+obj-$(CONFIG_IDE_H8300) += h8300/
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
+ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
+
obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o
-obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o
+obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o
obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
-obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ mips/
-obj-$(CONFIG_BLK_DEV_HD) += legacy/
-obj-$(CONFIG_ETRAX_IDE) += cris/
+ifeq ($(CONFIG_BLK_DEV_IDECS), y)
+ ide-cs-core-y += legacy/ide-cs.o
+ obj-y += ide-cs-core.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
+ ide-platform-core-y += legacy/ide_platform.o
+ obj-y += ide-platform-core.o
+endif
+
+obj-$(CONFIG_BLK_DEV_IDE) += arm/ mips/
+
+# old hd driver must be last
+ifeq ($(CONFIG_BLK_DEV_HD), y)
+ hd-core-y += legacy/hd.o
+ obj-y += hd-core.o
+endif
diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
index 6a78f0755f2..5f63ad21686 100644
--- a/drivers/ide/arm/Makefile
+++ b/drivers/ide/arm/Makefile
@@ -3,4 +3,8 @@ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o
+ifeq ($(CONFIG_IDE_ARM), m)
+ obj-m += ide_arm.o
+endif
+
EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
index 48db6167bb9..0e7574c0ee6 100644
--- a/drivers/ide/arm/bast-ide.c
+++ b/drivers/ide/arm/bast-ide.c
@@ -1,5 +1,4 @@
-/* linux/drivers/ide/arm/bast-ide.c
- *
+/*
* Copyright (c) 2003-2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
@@ -29,8 +28,10 @@ static int __init
bastide_register(unsigned int base, unsigned int aux, int irq,
ide_hwif_t **hwif)
{
+ ide_hwif_t *hwif;
hw_regs_t hw;
int i;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
memset(&hw, 0, sizeof(hw));
@@ -45,8 +46,24 @@ bastide_register(unsigned int base, unsigned int aux, int irq,
hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
hw.irq = irq;
- ide_register_hw(&hw, NULL, 0, hwif);
+ hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif == NULL)
+ goto out;
+
+ i = hwif->index;
+
+ if (hwif->present)
+ ide_unregister(i, 0, 0);
+ else if (!hwif->hold)
+ ide_init_port_data(hwif, i);
+
+ ide_init_port_hw(hwif, &hw);
+ hwif->quirkproc = NULL;
+
+ idx[0] = i;
+ ide_device_add(idx, NULL);
+out:
return 0;
}
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 93f71fcfc04..fb00f3827ec 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/arm/icside.c
- *
* Copyright (c) 1996-2004 Russell King.
*
* Please note that this platform does not support 32-bit IDE IO.
@@ -71,8 +69,6 @@ struct icside_state {
void __iomem *irq_port;
void __iomem *ioc_base;
unsigned int type;
- /* parent device... until the IDE core gets one of its own */
- struct device *dev;
ide_hwif_t *hwif[2];
};
@@ -206,23 +202,6 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
* interfaces use the same IRQ, which should guarantee this.
*/
-static void icside_build_sglist(ide_drive_t *drive, struct request *rq)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct icside_state *state = hwif->hwif_data;
- struct scatterlist *sg = hwif->sg_table;
-
- ide_map_sg(drive, rq);
-
- if (rq_data_dir(rq) == READ)
- hwif->sg_dma_direction = DMA_FROM_DEVICE;
- else
- hwif->sg_dma_direction = DMA_TO_DEVICE;
-
- hwif->sg_nents = dma_map_sg(state->dev, sg, hwif->sg_nents,
- hwif->sg_dma_direction);
-}
-
/*
* Configure the IOMD to give the appropriate timings for the transfer
* mode being requested. We take the advice of the ATA standards, and
@@ -272,8 +251,6 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
case XFER_SW_DMA_0:
cycle_time = 480;
break;
- default:
- return;
}
/*
@@ -289,56 +266,39 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
}
-static void icside_dma_host_off(ide_drive_t *drive)
+static void icside_dma_host_set(ide_drive_t *drive, int on)
{
}
-static void icside_dma_off_quietly(ide_drive_t *drive)
-{
- drive->using_dma = 0;
-}
-
-static void icside_dma_host_on(ide_drive_t *drive)
-{
-}
-
-static int icside_dma_on(ide_drive_t *drive)
-{
- drive->using_dma = 1;
-
- return 0;
-}
-
static int icside_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct icside_state *state = hwif->hwif_data;
+ struct expansion_card *ec = ECARD_DEV(hwif->dev);
drive->waiting_for_dma = 0;
- disable_dma(ECARD_DEV(state->dev)->dma);
+ disable_dma(ec->dma);
/* Teardown mappings after DMA has completed. */
- dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents,
- hwif->sg_dma_direction);
+ ide_destroy_dmatable(drive);
- return get_dma_residue(ECARD_DEV(state->dev)->dma) != 0;
+ return get_dma_residue(ec->dma) != 0;
}
static void icside_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct icside_state *state = hwif->hwif_data;
+ struct expansion_card *ec = ECARD_DEV(hwif->dev);
/* We can not enable DMA on both channels simultaneously. */
- BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
- enable_dma(ECARD_DEV(state->dev)->dma);
+ BUG_ON(dma_channel_active(ec->dma));
+ enable_dma(ec->dma);
}
static int icside_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct icside_state *state = hwif->hwif_data;
+ struct expansion_card *ec = ECARD_DEV(hwif->dev);
struct request *rq = hwif->hwgroup->rq;
unsigned int dma_mode;
@@ -350,9 +310,9 @@ static int icside_dma_setup(ide_drive_t *drive)
/*
* We can not enable DMA on both channels.
*/
- BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
+ BUG_ON(dma_channel_active(ec->dma));
- icside_build_sglist(drive, rq);
+ hwif->sg_nents = ide_build_sglist(drive, rq);
/*
* Ensure that we have the right interrupt routed.
@@ -367,14 +327,14 @@ static int icside_dma_setup(ide_drive_t *drive)
/*
* Select the correct timing for this drive.
*/
- set_dma_speed(ECARD_DEV(state->dev)->dma, drive->drive_data);
+ set_dma_speed(ec->dma, drive->drive_data);
/*
* Tell the DMA engine about the SG table and
* data direction.
*/
- set_dma_sg(ECARD_DEV(state->dev)->dma, hwif->sg_table, hwif->sg_nents);
- set_dma_mode(ECARD_DEV(state->dev)->dma, dma_mode);
+ set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents);
+ set_dma_mode(ec->dma, dma_mode);
drive->waiting_for_dma = 1;
@@ -417,17 +377,11 @@ static void icside_dma_lost_irq(ide_drive_t *drive)
static void icside_dma_init(ide_hwif_t *hwif)
{
- hwif->mwdma_mask = 7; /* MW0..2 */
- hwif->swdma_mask = 7; /* SW0..2 */
-
hwif->dmatable_cpu = NULL;
hwif->dmatable_dma = 0;
hwif->set_dma_mode = icside_set_dma_mode;
- hwif->dma_host_off = icside_dma_host_off;
- hwif->dma_off_quietly = icside_dma_off_quietly;
- hwif->dma_host_on = icside_dma_host_on;
- hwif->ide_dma_on = icside_dma_on;
+ hwif->dma_host_set = icside_dma_host_set;
hwif->dma_setup = icside_dma_setup;
hwif->dma_exec_cmd = icside_dma_exec_cmd;
hwif->dma_start = icside_dma_start;
@@ -465,6 +419,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
hwif->noprobe = 0;
hwif->chipset = ide_acorn;
hwif->gendev.parent = &ec->dev;
+ hwif->dev = &ec->dev;
}
return hwif;
@@ -501,11 +456,19 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
idx[0] = hwif->index;
- ide_device_add(idx);
+ ide_device_add(idx, NULL);
return 0;
}
+static const struct ide_port_info icside_v6_port_info __initdata = {
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+ IDE_HFLAG_NO_AUTOTUNE,
+ .mwdma_mask = ATA_MWDMA2,
+ .swdma_mask = ATA_SWDMA2,
+};
+
static int __init
icside_register_v6(struct icside_state *state, struct expansion_card *ec)
{
@@ -514,6 +477,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
unsigned int sel = 0;
int ret;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ struct ide_port_info d = icside_v6_port_info;
ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!ioc_base) {
@@ -563,30 +527,25 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
state->hwif[1] = mate;
hwif->maskproc = icside_maskproc;
- hwif->channel = 0;
hwif->hwif_data = state;
- hwif->mate = mate;
- hwif->serialized = 1;
hwif->config_data = (unsigned long)ioc_base;
hwif->select_data = sel;
mate->maskproc = icside_maskproc;
- mate->channel = 1;
mate->hwif_data = state;
- mate->mate = hwif;
- mate->serialized = 1;
mate->config_data = (unsigned long)ioc_base;
mate->select_data = sel | 1;
if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
icside_dma_init(hwif);
icside_dma_init(mate);
- }
+ } else
+ d.mwdma_mask = d.swdma_mask = 0;
idx[0] = hwif->index;
idx[1] = mate->index;
- ide_device_add(idx);
+ ide_device_add(idx, &d);
return 0;
@@ -612,7 +571,6 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
}
state->type = ICS_TYPE_NOTYPE;
- state->dev = &ec->dev;
idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (idmem) {
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
index 8957cbadf5c..43a70e91363 100644
--- a/drivers/ide/arm/ide_arm.c
+++ b/drivers/ide/arm/ide_arm.c
@@ -24,12 +24,25 @@
# define IDE_ARM_IRQ IRQ_HARDDISK
#endif
-void __init ide_arm_init(void)
+static int __init ide_arm_init(void)
{
+ ide_hwif_t *hwif;
hw_regs_t hw;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
hw.irq = IDE_ARM_IRQ;
- ide_register_hw(&hw, NULL, 1, NULL);
+
+ hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif) {
+ ide_init_port_hw(hwif, &hw);
+ idx[0] = hwif->index;
+
+ ide_device_add(idx, NULL);
+ }
+
+ return 0;
}
+
+module_init(ide_arm_init);
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 0775a3afef4..efba00d2fc3 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/arm/rapide.c
- *
* Copyright (c) 1996-2002 Russell King.
*/
@@ -13,26 +11,18 @@
#include <asm/ecard.h>
-static ide_hwif_t *
-rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq)
+static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
+ void __iomem *ctrl, unsigned int sz, int irq)
{
unsigned long port = (unsigned long)base;
- ide_hwif_t *hwif = ide_find_port(port);
int i;
- if (hwif == NULL)
- goto out;
-
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hwif->io_ports[i] = port;
+ hw->io_ports[i] = port;
port += sz;
}
- hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
- hwif->irq = irq;
- hwif->mmio = 1;
- default_hwif_mmiops(hwif);
-out:
- return hwif;
+ hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
+ hw->irq = irq;
}
static int __devinit
@@ -42,6 +32,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
void __iomem *base;
int ret;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw;
ret = ecard_request_resources(ec);
if (ret)
@@ -53,15 +44,21 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
goto release;
}
- hwif = rapide_locate_hwif(base, base + 0x818, 1 << 6, ec->irq);
+ hwif = ide_find_port((unsigned long)base);
if (hwif) {
- hwif->hwif_data = base;
- hwif->gendev.parent = &ec->dev;
- hwif->noprobe = 0;
+ memset(&hw, 0, sizeof(hw));
+ rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
+ hw.chipset = ide_generic;
+ hw.dev = &ec->dev;
+
+ ide_init_port_hw(hwif, &hw);
+
+ hwif->mmio = 1;
+ default_hwif_mmiops(hwif);
idx[0] = hwif->index;
- ide_device_add(idx);
+ ide_device_add(idx, NULL);
ecard_set_drvdata(ec, hwif);
goto out;
@@ -79,8 +76,8 @@ static void __devexit rapide_remove(struct expansion_card *ec)
ecard_set_drvdata(ec, NULL);
- /* there must be a better way */
- ide_unregister(hwif - ide_hwifs);
+ ide_unregister(hwif->index, 0, 0);
+
ecard_release_resources(ec);
}
diff --git a/drivers/ide/cris/Makefile b/drivers/ide/cris/Makefile
index 6176e8d6b2e..20b95960531 100644
--- a/drivers/ide/cris/Makefile
+++ b/drivers/ide/cris/Makefile
@@ -1,3 +1,3 @@
EXTRA_CFLAGS += -Idrivers/ide
-obj-y += ide-cris.o
+obj-$(CONFIG_IDE_ETRAX) += ide-cris.o
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index e196aefa207..00587a8c2ba 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -1,5 +1,4 @@
-/* $Id: cris-ide-driver.patch,v 1.1 2005/06/29 21:39:07 akpm Exp $
- *
+/*
* Etrax specific IDE functions, like init and PIO-mode setting etc.
* Almost the entire ide.c is used for the rest of the Etrax ATA driver.
* Copyright (c) 2000-2005 Axis Communications AB
@@ -673,9 +672,8 @@ static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int);
static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int);
static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int);
-static int cris_dma_on (ide_drive_t *drive);
-static void cris_dma_off(ide_drive_t *drive)
+static void cris_dma_host_set(ide_drive_t *drive, int on)
{
}
@@ -747,9 +745,6 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
strobe = ATA_DMA2_STROBE;
hold = ATA_DMA2_HOLD;
break;
- default:
- BUG();
- break;
}
if (speed >= XFER_UDMA_0)
@@ -758,13 +753,20 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
cris_ide_set_speed(TYPE_DMA, 0, strobe, hold);
}
-void __init
-init_e100_ide (void)
+static const struct ide_port_info cris_port_info __initdata = {
+ .chipset = ide_etrax100,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_NO_DMA, /* no SFF-style DMA */
+ .pio_mask = ATA_PIO4,
+ .udma_mask = cris_ultra_mask,
+ .mwdma_mask = ATA_MWDMA2,
+};
+
+static int __init init_e100_ide(void)
{
hw_regs_t hw;
- int ide_offsets[IDE_NR_PORTS];
- int h;
- int i;
+ int ide_offsets[IDE_NR_PORTS], h, i;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
printk("ide: ETRAX FS built-in ATA DMA controller\n");
@@ -774,23 +776,26 @@ init_e100_ide (void)
/* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
ide_offsets[IDE_CONTROL_OFFSET] = cris_ide_reg_addr(6, 1, 0);
- /* first fill in some stuff in the ide_hwifs fields */
+ for (h = 0; h < 4; h++) {
+ ide_hwif_t *hwif = NULL;
- for(h = 0; h < MAX_HWIFS; h++) {
- ide_hwif_t *hwif = &ide_hwifs[h];
ide_setup_ports(&hw, cris_ide_base_address(h),
ide_offsets,
0, 0, cris_ide_ack_intr,
ide_default_irq(0));
- ide_register_hw(&hw, NULL, 1, &hwif);
+ hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif == NULL)
+ continue;
+ ide_init_port_data(hwif, hwif->index);
+ ide_init_port_hw(hwif, &hw);
hwif->mmio = 1;
- hwif->chipset = ide_etrax100;
hwif->set_pio_mode = &cris_set_pio_mode;
hwif->set_dma_mode = &cris_set_dma_mode;
hwif->ata_input_data = &cris_ide_input_data;
hwif->ata_output_data = &cris_ide_output_data;
hwif->atapi_input_bytes = &cris_atapi_input_bytes;
hwif->atapi_output_bytes = &cris_atapi_output_bytes;
+ hwif->dma_host_set = &cris_dma_host_set;
hwif->ide_dma_end = &cris_dma_end;
hwif->dma_setup = &cris_dma_setup;
hwif->dma_exec_cmd = &cris_dma_exec_cmd;
@@ -801,16 +806,9 @@ init_e100_ide (void)
hwif->OUTBSYNC = &cris_ide_outbsync;
hwif->INB = &cris_ide_inb;
hwif->INW = &cris_ide_inw;
- hwif->dma_host_off = &cris_dma_off;
- hwif->dma_host_on = &cris_dma_on;
- hwif->dma_off_quietly = &cris_dma_off;
hwif->cbl = ATA_CBL_PATA40;
- hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
- hwif->pio_mask = ATA_PIO4,
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
- hwif->ultra_mask = cris_ultra_mask;
- hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
+
+ idx[h] = hwif->index;
}
/* Reset pulse */
@@ -823,14 +821,12 @@ init_e100_ide (void)
cris_ide_set_speed(TYPE_PIO, ATA_PIO4_SETUP, ATA_PIO4_STROBE, ATA_PIO4_HOLD);
cris_ide_set_speed(TYPE_DMA, 0, ATA_DMA2_STROBE, ATA_DMA2_HOLD);
cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0);
-}
-static int cris_dma_on (ide_drive_t *drive)
-{
+ ide_device_add(idx, &cris_port_info);
+
return 0;
}
-
static cris_dma_descr_type mydescr __attribute__ ((__aligned__(16)));
/*
@@ -1038,11 +1034,7 @@ static int cris_dma_setup(ide_drive_t *drive)
static void cris_dma_exec_cmd(ide_drive_t *drive, u8 command)
{
- /* set the irq handler which will finish the request when DMA is done */
- ide_set_handler(drive, &cris_dma_intr, WAIT_CMD, NULL);
-
- /* issue cmd to drive */
- cris_ide_outb(command, IDE_COMMAND_REG);
+ ide_execute_command(drive, command, &cris_dma_intr, WAIT_CMD, NULL);
}
static void cris_dma_start(ide_drive_t *drive)
@@ -1062,3 +1054,5 @@ static void cris_dma_start(ide_drive_t *drive)
LED_DISK_READ(1);
}
}
+
+module_init(init_e100_ide);
diff --git a/drivers/ide/h8300/Makefile b/drivers/ide/h8300/Makefile
new file mode 100644
index 00000000000..5eba16f423f
--- /dev/null
+++ b/drivers/ide/h8300/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_IDE_H8300) += ide-h8300.o
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index 4a49b5c59ac..520aec07570 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -1,5 +1,4 @@
/*
- * drivers/ide/h8300/ide-h8300.c
* H8/300 generic IDE interface
*/
@@ -84,11 +83,12 @@ static inline void hwif_setup(ide_hwif_t *hwif)
hwif->INSL = NULL;
}
-void __init h8300_ide_init(void)
+static int __init h8300_ide_init(void)
{
hw_regs_t hw;
ide_hwif_t *hwif;
- int idx;
+ int index;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
goto out_busy;
@@ -100,16 +100,28 @@ void __init h8300_ide_init(void)
hw_setup(&hw);
/* register if */
- idx = ide_register_hw(&hw, NULL, 1, &hwif);
- if (idx == -1) {
+ hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif == NULL) {
printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
- return;
+ return -ENOENT;
}
+ index = hwif->index;
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
hwif_setup(hwif);
- printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", idx);
- return;
+ printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index);
+
+ idx[0] = index;
+
+ ide_device_add(idx, NULL);
+
+ return 0;
out_busy:
printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
+
+ return -EBUSY;
}
+
+module_init(h8300_ide_init);
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 89df48fdc69..25aaeae1e83 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -1,5 +1,4 @@
/*
- * ide-acpi.c
* Provides ACPI support for IDE drives.
*
* Copyright (C) 2005 Intel Corp.
@@ -16,6 +15,7 @@
#include <acpi/acpi.h>
#include <linux/ide.h>
#include <linux/pci.h>
+#include <linux/dmi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acnames.h>
@@ -39,7 +39,6 @@ struct GTM_buffer {
};
struct ide_acpi_drive_link {
- ide_drive_t *drive;
acpi_handle obj_handle;
u8 idbuff[512];
};
@@ -65,6 +64,39 @@ extern int ide_noacpi;
extern int ide_noacpitfs;
extern int ide_noacpionboot;
+static bool ide_noacpi_psx;
+static int no_acpi_psx(const struct dmi_system_id *id)
+{
+ ide_noacpi_psx = true;
+ printk(KERN_NOTICE"%s detected - disable ACPI _PSx.\n", id->ident);
+ return 0;
+}
+
+static const struct dmi_system_id ide_acpi_dmi_table[] = {
+ /* Bug 9673. */
+ /* We should check if this is because ACPI NVS isn't save/restored. */
+ {
+ .callback = no_acpi_psx,
+ .ident = "HP nx9005",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies Ltd."),
+ DMI_MATCH(DMI_BIOS_VERSION, "KAM1.60")
+ },
+ },
+
+ { } /* terminate list */
+};
+
+static int ide_acpi_blacklist(void)
+{
+ static int done;
+ if (done)
+ return 0;
+ done = 1;
+ dmi_check_system(ide_acpi_dmi_table);
+ return 0;
+}
+
/**
* ide_get_dev_handle - finds acpi_handle and PCI device.function
* @dev: device to locate
@@ -247,16 +279,6 @@ static int do_drive_get_GTF(ide_drive_t *drive,
port = hwif->channel ? drive->dn - 2: drive->dn;
- if (!drive->acpidata) {
- if (port == 0) {
- drive->acpidata = &hwif->acpidata->master;
- hwif->acpidata->master.drive = drive;
- } else {
- drive->acpidata = &hwif->acpidata->slave;
- hwif->acpidata->slave.drive = drive;
- }
- }
-
DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
hwif->name, dev->bus_id, port, hwif->channel);
@@ -349,27 +371,19 @@ static int taskfile_load_raw(ide_drive_t *drive,
gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
memset(&args, 0, sizeof(ide_task_t));
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.data_phase = TASKFILE_NO_DATA;
- args.handler = &task_no_data_intr;
/* convert gtf to IDE Taskfile */
- args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */
- args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */
- args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */
- args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */
- args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */
- args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */
- args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */
+ memcpy(&args.tf_array[7], &gtf->tfa, 7);
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
if (ide_noacpitfs) {
DEBPRINT("_GTF execution disabled\n");
return err;
}
- err = ide_raw_taskfile(drive, &args, NULL);
+ err = ide_no_data_taskfile(drive, &args);
if (err)
- printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n",
+ printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
__FUNCTION__, err);
return err;
@@ -469,7 +483,6 @@ int ide_acpi_exec_tfs(ide_drive_t *drive)
return ret;
}
-EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs);
/**
* ide_acpi_get_timing - get the channel (controller) timings
@@ -555,7 +568,6 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
kfree(output.pointer);
}
-EXPORT_SYMBOL_GPL(ide_acpi_get_timing);
/**
* ide_acpi_push_timing - set the channel (controller) timings
@@ -609,7 +621,6 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
}
DEBPRINT("_STM status: %d\n", status);
}
-EXPORT_SYMBOL_GPL(ide_acpi_push_timing);
/**
* ide_acpi_set_state - set the channel power state
@@ -623,7 +634,7 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
{
int unit;
- if (ide_noacpi)
+ if (ide_noacpi || ide_noacpi_psx)
return;
DEBPRINT("ENTER:\n");
@@ -663,10 +674,7 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
*/
void ide_acpi_init(ide_hwif_t *hwif)
{
- int unit;
- int err;
- struct ide_acpi_drive_link *master;
- struct ide_acpi_drive_link *slave;
+ ide_acpi_blacklist();
hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL);
if (!hwif->acpidata)
@@ -677,40 +685,38 @@ void ide_acpi_init(ide_hwif_t *hwif)
DEBPRINT("no ACPI object for %s found\n", hwif->name);
kfree(hwif->acpidata);
hwif->acpidata = NULL;
- return;
}
+}
+
+void ide_acpi_port_init_devices(ide_hwif_t *hwif)
+{
+ ide_drive_t *drive;
+ int i, err;
+
+ if (hwif->acpidata == NULL)
+ return;
/*
* The ACPI spec mandates that we send information
* for both drives, regardless whether they are connected
* or not.
*/
- hwif->acpidata->master.drive = &hwif->drives[0];
hwif->drives[0].acpidata = &hwif->acpidata->master;
- master = &hwif->acpidata->master;
-
- hwif->acpidata->slave.drive = &hwif->drives[1];
hwif->drives[1].acpidata = &hwif->acpidata->slave;
- slave = &hwif->acpidata->slave;
-
/*
* Send IDENTIFY for each drive
*/
- if (master->drive->present) {
- err = taskfile_lib_get_identify(master->drive, master->idbuff);
- if (err) {
- DEBPRINT("identify device %s failed (%d)\n",
- master->drive->name, err);
- }
- }
+ for (i = 0; i < MAX_DRIVES; i++) {
+ drive = &hwif->drives[i];
- if (slave->drive->present) {
- err = taskfile_lib_get_identify(slave->drive, slave->idbuff);
- if (err) {
+ if (!drive->present)
+ continue;
+
+ err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
+ if (err)
DEBPRINT("identify device %s failed (%d)\n",
- slave->drive->name, err);
- }
+ drive->name, err);
}
if (ide_noacpionboot) {
@@ -726,13 +732,11 @@ void ide_acpi_init(ide_hwif_t *hwif)
ide_acpi_get_timing(hwif);
ide_acpi_push_timing(hwif);
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
+ for (i = 0; i < MAX_DRIVES; i++) {
+ drive = &hwif->drives[i];
- if (drive->present) {
+ if (drive->present)
/* Execute ACPI startup code */
ide_acpi_exec_tfs(drive);
- }
}
}
-EXPORT_SYMBOL_GPL(ide_acpi_init);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 57a5f63d6ae..ee4d458e2bb 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1,14 +1,14 @@
/*
- * linux/drivers/ide/ide-cd.c
+ * ATAPI CD-ROM driver.
*
- * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
- * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov>
+ * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
+ * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005, 2007 Bartlomiej Zolnierkiewicz
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
- * ATAPI CD-ROM driver. To be used with ide.c.
* See Documentation/cdrom/ide-cd for usage information.
*
* Suggestions are welcome. Patches that work are more welcome though. ;-)
@@ -19,287 +19,11 @@
* ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
* ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
*
- * Drives that deviate from these standards will be accommodated 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...
- *
- * ----------------------------------
- * TO DO LIST:
- * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
- * boot
- *
- * ----------------------------------
- * 1.00 Oct 31, 1994 -- Initial version.
- * 1.01 Nov 2, 1994 -- Fixed problem with starting request in
- * cdrom_check_status.
- * 1.03 Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks)
- * (from mlord) -- minor changes to cdrom_setup()
- * -- renamed ide_dev_s to ide_drive_t, enable irq on command
- * 2.00 Nov 27, 1994 -- Generalize packet command interface;
- * add audio ioctls.
- * 2.01 Dec 3, 1994 -- Rework packet command interface to handle devices
- * which send an interrupt when ready for a command.
- * 2.02 Dec 11, 1994 -- Cache the TOC in the driver.
- * Don't use SCMD_PLAYAUDIO_TI; it's not included
- * in the current version of ATAPI.
- * Try to use LBA instead of track or MSF addressing
- * when possible.
- * Don't wait for READY_STAT.
- * 2.03 Jan 10, 1995 -- Rewrite block read routines to handle block sizes
- * other than 2k and to move multiple sectors in a
- * single transaction.
- * 2.04 Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives.
- * Thanks to Nick Saw <cwsaw@pts7.pts.mot.com> for
- * help in figuring this out. Ditto for Acer and
- * Aztech drives, which seem to have the same problem.
- * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml
- * 2.05 Jun 8, 1995 -- Don't attempt to retry after an illegal request
- * or data protect error.
- * Use HWIF and DEV_HWIF macros as in ide.c.
- * Always try to do a request_sense after
- * a failed command.
- * Include an option to give textual descriptions
- * of ATAPI errors.
- * Fix a bug in handling the sector cache which
- * showed up if the drive returned data in 512 byte
- * blocks (like Pioneer drives). Thanks to
- * Richard Hirst <srh@gpt.co.uk> for diagnosing this.
- * Properly supply the page number field in the
- * MODE_SELECT command.
- * PLAYAUDIO12 is broken on the Aztech; work around it.
- * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c
- * (my apologies to Scott, but now ide-cd.c is independent)
- * 3.00 Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl.
- * Implement CDROMREADAUDIO ioctl (UNTESTED).
- * Use input_ide_data() and output_ide_data().
- * Add door locking.
- * Fix usage count leak in cdrom_open, which happened
- * when a read-write mount was attempted.
- * Try to load the disk on open.
- * Implement CDROMEJECT_SW ioctl (off by default).
- * Read total cdrom capacity during open.
- * Rearrange logic in cdrom_decode_status. Issue
- * request sense commands for failed packet commands
- * from here instead of from cdrom_queue_packet_command.
- * Fix a race condition in retrieving error information.
- * Suppress printing normal unit attention errors and
- * some drive not ready errors.
- * Implement CDROMVOLREAD ioctl.
- * Implement CDROMREADMODE1/2 ioctls.
- * Fix race condition in setting up interrupt handlers
- * when the `serialize' option is used.
- * 3.01 Sep 2, 1995 -- Fix ordering of reenabling interrupts in
- * cdrom_queue_request.
- * Another try at using ide_[input,output]_data.
- * 3.02 Sep 16, 1995 -- Stick total disk capacity in partition table as well.
- * Make VERBOSE_IDE_CD_ERRORS dump failed command again.
- * Dump out more information for ILLEGAL REQUEST errs.
- * Fix handling of errors occurring before the
- * packet command is transferred.
- * Fix transfers with odd bytelengths.
- * 3.03 Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
- * `DCI-2S10' drives are broken too.
- * 3.04 Nov 20, 1995 -- So are Vertos drives.
- * 3.05 Dec 1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c
- * 3.06 Dec 16, 1995 -- Add support needed for partitions.
- * More workarounds for Vertos bugs (based on patches
- * from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>).
- * Try to eliminate byteorder assumptions.
- * Use atapi_cdrom_subchnl struct definition.
- * Add STANDARD_ATAPI compilation option.
- * 3.07 Jan 29, 1996 -- More twiddling for broken drives: Sony 55D,
- * Vertos 300.
- * Add NO_DOOR_LOCKING configuration option.
- * Handle drive_cmd requests w/NULL args (for hdparm -t).
- * Work around sporadic Sony55e audio play problem.
- * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
- * problem with "hde=cdrom" with no drive present. -ml
- * 3.08 Mar 6, 1996 -- More Vertos workarounds.
- * 3.09 Apr 5, 1996 -- Add CDROMCLOSETRAY ioctl.
- * Switch to using MSF addressing for audio commands.
- * Reformat to match kernel tabbing style.
- * Add CDROM_GET_UPC ioctl.
- * 3.10 Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
- * 3.11 Apr 29, 1996 -- Patch from Heiko Eißfeldt <heiko@colossus.escape.de>
- * to remove redundant verify_area calls.
- * 3.12 May 7, 1996 -- Rudimentary changer support. Based on patches
- * from Gerhard Zuber <zuber@berlin.snafu.de>.
- * Let open succeed even if there's no loaded disc.
- * 3.13 May 19, 1996 -- Fixes for changer code.
- * 3.14 May 29, 1996 -- Add work-around for Vertos 600.
- * (From Hennus Bergman <hennus@sky.ow.nl>.)
- * 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers
- * from Ben Galliart <bgallia@luc.edu> with
- * special help from Jeff Lightfoot
- * <jeffml@pobox.com>
- * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
- * 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
- * 3.17 Sep 17, 1996 -- Tweak audio reads for some drives.
- * Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC.
- * 3.18 Oct 31, 1996 -- Added module and DMA support.
- *
- *
- * 4.00 Nov 5, 1996 -- New ide-cd maintainer,
- * Erik B. Andersen <andersee@debian.org>
- * -- Newer Creative drives don't always set the error
- * register correctly. Make sure we see media changes
- * regardless.
- * -- Integrate with generic cdrom driver.
- * -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on
- * a patch from Ciro Cattuto <>.
- * -- Call set_device_ro.
- * -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE
- * ioctls, based on patch by Erik Andersen
- * -- Add some probes of drive capability during setup.
- *
- * 4.01 Nov 11, 1996 -- Split into ide-cd.c and ide-cd.h
- * -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE
- * ioctls in favor of a generalized approach
- * using the generic cdrom driver.
- * -- Fully integrated with the 2.1.X kernel.
- * -- Other stuff that I forgot (lots of changes)
- *
- * 4.02 Dec 01, 1996 -- Applied patch from Gadi Oxman <gadio@netvision.net.il>
- * to fix the drive door locking problems.
- *
- * 4.03 Dec 04, 1996 -- Added DSC overlap support.
- * 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch
- * by Ales Makarov (xmakarov@sun.felk.cvut.cz)
- *
- * 4.05 Nov 20, 1997 -- Modified to print more drive info on init
- * Minor other changes
- * Fix errors on CDROMSTOP (If you have a "Dolphin",
- * you must define IHAVEADOLPHIN)
- * Added identifier so new Sanyo CD-changer works
- * Better detection if door locking isn't supported
- *
- * 4.06 Dec 17, 1997 -- fixed endless "tray open" messages -ml
- * 4.07 Dec 17, 1997 -- fallback to set pc->stat on "tray open"
- * 4.08 Dec 18, 1997 -- spew less noise when tray is empty
- * -- fix speed display for ACER 24X, 18X
- * 4.09 Jan 04, 1998 -- fix handling of the last block so we return
- * an end of file instead of an I/O error (Gadi)
- * 4.10 Jan 24, 1998 -- fixed a bug so now changers can change to a new
- * slot when there is no disc in the current slot.
- * -- Fixed a memory leak where info->changer_info was
- * malloc'ed but never free'd when closing the device.
- * -- Cleaned up the global namespace a bit by making more
- * functions static that should already have been.
- * 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl
- * based on a patch for 2.0.33 by Jelle Foks
- * <jelle@scintilla.utwente.nl>, a patch for 2.0.33
- * by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI
- * version, and my own efforts. -erik
- * -- Fixed a stupid bug which egcs was kind enough to
- * inform me of where "Illegal mode for this track"
- * was never returned due to a comparison on data
- * types of limited range.
- * 4.12 Mar 29, 1998 -- Fixed bug in CDROM_SELECT_SPEED so write speed is
- * now set ionly for CD-R and CD-RW drives. I had
- * removed this support because it produced errors.
- * It produced errors _only_ for non-writers. duh.
- * 4.13 May 05, 1998 -- Suppress useless "in progress of becoming ready"
- * messages, since this is not an error.
- * -- Change error messages to be const
- * -- Remove a "\t" which looks ugly in the syslogs
- * 4.14 July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
- * since the .pdf version doesn't seem to work...
- * -- Updated the TODO list to something more current.
- *
- * 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess,
- * patch thanks to "Eddie C. Dost" <ecd@skynet.be>
- *
- * 4.50 Oct 19, 1998 -- New maintainers!
- * Jens Axboe <axboe@image.dk>
- * Chris Zwilling <chris@cloudnet.com>
- *
- * 4.51 Dec 23, 1998 -- Jens Axboe <axboe@image.dk>
- * - ide_cdrom_reset enabled since the ide subsystem
- * handles resets fine now. <axboe@image.dk>
- * - Transfer size fix for Samsung CD-ROMs, thanks to
- * "Ville Hallik" <ville.hallik@mail.ee>.
- * - other minor stuff.
- *
- * 4.52 Jan 19, 1999 -- Jens Axboe <axboe@image.dk>
- * - Detect DVD-ROM/RAM drives
- *
- * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar
- * drive in transfer size limit.
- * - Fix the I/O error when doing eject without a medium
- * loaded on some drives.
- * - CDROMREADMODE2 is now implemented through
- * CDROMREADRAW, since many drives don't support
- * MODE2 (even though ATAPI 2.6 says they must).
- * - Added ignore parameter to ide-cd (as a module), eg
- * insmod ide-cd ignore='hda hdb'
- * 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 occurred.
- * - Moved all the CDROMREADx ioctls to the Uniform layer.
- * - Heiko Eißfeldt <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
- *
- * 4.57 Apr 7, 2000 - Fixed sense reporting.
- * - Fixed possible oops in ide_cdrom_get_last_session()
- * - Fix locking mania and make ide_cdrom_reset relock
- * - Stop spewing errors to log when magicdev polls with
- * TEST_UNIT_READY on some drives.
- * - Various fixes from Tobias Ringstrom:
- * tray if it was locked prior to the reset.
- * - cdrom_read_capacity returns one frame too little.
- * - Fix real capacity reporting.
- *
- * 4.58 May 1, 2000 - Clean up ACER50 stuff.
- * - Fix small problem with ide_cdrom_capacity
- *
- * 4.59 Aug 11, 2000 - Fix changer problem in cdrom_read_toc, we weren't
- * correctly sensing a disc change.
- * - Rearranged some code
- * - Use extended sense on drives that support it for
- * correctly reporting tray status -- from
- * Michael D Johnson <johnsom@orst.edu>
- * 4.60 Dec 17, 2003 - Add mt rainier support
- * - Bump timeout for packet commands, matches sr
- * - Odd stuff
- * 4.61 Jan 22, 2004 - support hardware sector sizes other than 2kB,
- * Pascal Schmidt <der.eremit@email.de>
- *
- *************************************************************************/
-
-#define IDECD_VERSION "4.61"
+ * For historical changelog please see:
+ * Documentation/ide/ChangeLog.ide-cd.1994-2004
+ */
+
+#define IDECD_VERSION "5.00"
#include <linux/module.h>
#include <linux/types.h>
@@ -313,6 +37,7 @@
#include <linux/ide.h>
#include <linux/completion.h>
#include <linux/mutex.h>
+#include <linux/bcd.h>
#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
@@ -360,11 +85,11 @@ static void ide_cd_put(struct cdrom_info *cd)
buffers. */
static void cdrom_saw_media_change (ide_drive_t *drive)
{
- struct cdrom_info *info = drive->driver_data;
-
- CDROM_STATE_FLAGS (drive)->media_changed = 1;
- CDROM_STATE_FLAGS (drive)->toc_valid = 0;
- info->nsectors_buffered = 0;
+ struct cdrom_info *cd = drive->driver_data;
+
+ cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
+ cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+ cd->nsectors_buffered = 0;
}
static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -465,134 +190,14 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
}
}
}
-#if VERBOSE_IDE_CD_ERRORS
- {
- int i;
- const char *s = "bad sense key!";
- char buf[80];
-
- printk ("ATAPI device %s:\n", drive->name);
- if (sense->error_code==0x70)
- printk(" Error: ");
- else if (sense->error_code==0x71)
- printk(" Deferred Error: ");
- else if (sense->error_code == 0x7f)
- printk(" Vendor-specific Error: ");
- else
- printk(" Unknown Error Type: ");
-
- if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
- s = sense_key_texts[sense->sense_key];
-
- printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
-
- if (sense->asc == 0x40) {
- sprintf(buf, "Diagnostic failure on component 0x%02x",
- sense->ascq);
- s = buf;
- } else {
- int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
- unsigned long key = (sense->sense_key << 16);
- key |= (sense->asc << 8);
- if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
- key |= sense->ascq;
- s = NULL;
-
- while (hi > lo) {
- mid = (lo + hi) / 2;
- if (sense_data_texts[mid].asc_ascq == key ||
- sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
- s = sense_data_texts[mid].text;
- break;
- }
- else if (sense_data_texts[mid].asc_ascq > key)
- hi = mid;
- else
- lo = mid+1;
- }
- }
-
- if (s == NULL) {
- if (sense->asc > 0x80)
- s = "(vendor-specific error)";
- else
- s = "(reserved error code)";
- }
-
- printk(KERN_ERR " %s -- (asc=0x%02x, ascq=0x%02x)\n",
- s, sense->asc, sense->ascq);
-
- if (failed_command != NULL) {
-
- int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
- s = NULL;
-
- while (hi > lo) {
- mid = (lo + hi) / 2;
- if (packet_command_texts[mid].packet_command ==
- failed_command->cmd[0]) {
- s = packet_command_texts[mid].text;
- break;
- }
- if (packet_command_texts[mid].packet_command >
- failed_command->cmd[0])
- hi = mid;
- else
- lo = mid+1;
- }
-
- printk (KERN_ERR " The failed \"%s\" packet command was: \n \"", s);
- for (i=0; i<sizeof (failed_command->cmd); i++)
- printk ("%02x ", failed_command->cmd[i]);
- printk ("\"\n");
- }
-
- /* The SKSV bit specifies validity of the sense_key_specific
- * in the next two commands. It is bit 7 of the first byte.
- * In the case of NOT_READY, if SKSV is set the drive can
- * give us nice ETA readings.
- */
- if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
- int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
- printk(KERN_ERR " Command is %02d%% complete\n", progress / 0xffff);
-
- }
-
- if (sense->sense_key == ILLEGAL_REQUEST &&
- (sense->sks[0] & 0x80) != 0) {
- printk(KERN_ERR " Error in %s byte %d",
- (sense->sks[0] & 0x40) != 0 ?
- "command packet" : "command data",
- (sense->sks[1] << 8) + sense->sks[2]);
- if ((sense->sks[0] & 0x40) != 0)
- printk (" bit %d", sense->sks[0] & 0x07);
-
- printk ("\n");
- }
- }
-
-#else /* not VERBOSE_IDE_CD_ERRORS */
-
- /* Suppress printing unit attention and `in progress of becoming ready'
- errors when we're not being verbose. */
-
- if (sense->sense_key == UNIT_ATTENTION ||
- (sense->sense_key == NOT_READY && (sense->asc == 4 ||
- sense->asc == 0x3a)))
- return;
-
- printk(KERN_ERR "%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n",
- drive->name,
- sense->error_code, sense->sense_key,
- sense->asc, sense->ascq);
-#endif /* not VERBOSE_IDE_CD_ERRORS */
+ ide_cd_log_error(drive->name, failed_command, sense);
}
/*
* Initialize a ide-cd packet command request
*/
-static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq)
+void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
{
struct cdrom_info *cd = drive->driver_data;
@@ -611,7 +216,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
sense = &info->sense_data;
/* stuff the sense request in front of our current request */
- cdrom_prepare_request(drive, rq);
+ ide_cd_init_rq(drive, rq);
rq->data = sense;
rq->cmd[0] = GPCMD_REQUEST_SENSE;
@@ -655,9 +260,9 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
BUG();
} else {
spin_lock_irqsave(&ide_lock, flags);
- end_that_request_chunk(failed, 0,
- failed->data_len);
- end_that_request_last(failed, 0);
+ if (__blk_end_request(failed, -EIO,
+ failed->data_len))
+ BUG();
spin_unlock_irqrestore(&ide_lock, flags);
}
} else
@@ -718,7 +323,6 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
/* All other functions, except for READ. */
- unsigned long flags;
/*
* if we have an error, pass back CHECK_CONDITION as the
@@ -756,15 +360,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
* remove failed request completely and end it when the
* request sense has completed
*/
- if (stat & ERR_STAT) {
- spin_lock_irqsave(&ide_lock, flags);
- blkdev_dequeue_request(rq);
- HWGROUP(drive)->rq = NULL;
- spin_unlock_irqrestore(&ide_lock, flags);
-
- cdrom_queue_request_sense(drive, rq->sense, rq);
- } else
- cdrom_end_request(drive, 0);
+ goto end_request;
} else if (blk_fs_request(rq)) {
int do_end_request = 0;
@@ -844,23 +440,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
sense data. We need this in order to perform end of media
processing */
- if (do_end_request) {
- if (stat & ERR_STAT) {
- unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
- blkdev_dequeue_request(rq);
- HWGROUP(drive)->rq = NULL;
- spin_unlock_irqrestore(&ide_lock, flags);
+ if (do_end_request)
+ goto end_request;
- cdrom_queue_request_sense(drive, rq->sense, rq);
- } else
- cdrom_end_request(drive, 0);
- } else {
- /* If we got a CHECK_CONDITION status,
- queue a request sense command. */
- if (stat & ERR_STAT)
- cdrom_queue_request_sense(drive, NULL, NULL);
- }
+ /*
+ * If we got a CHECK_CONDITION status,
+ * queue a request sense command.
+ */
+ if (stat & ERR_STAT)
+ cdrom_queue_request_sense(drive, NULL, NULL);
} else {
blk_dump_rq_flags(rq, "ide-cd: bad rq");
cdrom_end_request(drive, 0);
@@ -868,6 +456,21 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
/* Retry, or handle the next request. */
return 1;
+
+end_request:
+ if (stat & ERR_STAT) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&ide_lock, flags);
+ blkdev_dequeue_request(rq);
+ HWGROUP(drive)->rq = NULL;
+ spin_unlock_irqrestore(&ide_lock, flags);
+
+ cdrom_queue_request_sense(drive, rq->sense, rq);
+ } else
+ cdrom_end_request(drive, 0);
+
+ return 1;
}
static int cdrom_timer_expiry(ide_drive_t *drive)
@@ -917,21 +520,15 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
return startstop;
+ /* FIXME: for Virtual DMA we must check harder */
if (info->dma)
info->dma = !hwif->dma_setup(drive);
/* Set up the controller registers. */
- /* FIXME: for Virtual DMA we must check harder */
- HWIF(drive)->OUTB(info->dma, IDE_FEATURE_REG);
- HWIF(drive)->OUTB(0, IDE_IREASON_REG);
- HWIF(drive)->OUTB(0, IDE_SECTOR_REG);
-
- HWIF(drive)->OUTB(xferlen & 0xff, IDE_BCOUNTL_REG);
- HWIF(drive)->OUTB(xferlen >> 8 , IDE_BCOUNTH_REG);
- if (IDE_CONTROL_REG)
- HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
-
- if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
+ IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
+
+ if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
/* waiting for CDB interrupt, not DMA yet. */
if (info->dma)
drive->waiting_for_dma = 0;
@@ -957,10 +554,6 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
by cdrom_start_packet_command.
HANDLER is the interrupt handler to call when the command completes
or there's data ready. */
-/*
- * changed 5 parameters to 3 for dvd-ram
- * struct packet_command *pc; now packet_command_t *pc;
- */
#define ATAPI_MIN_CDB_BYTES 12
static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
struct request *rq,
@@ -971,7 +564,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop;
- if (CDROM_CONFIG_FLAGS(drive)->drq_interrupt) {
+ if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
/* Here we should have been called after receiving an interrupt
from the device. DRQ should how be set. */
@@ -1011,6 +604,25 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
* Block read functions.
*/
+static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
+{
+ while (len > 0) {
+ int dum = 0;
+ xf(drive, &dum, sizeof(dum));
+ len -= sizeof(dum);
+ }
+}
+
+static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
+{
+ while (nsects > 0) {
+ static char dum[SECTOR_SIZE];
+
+ drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum));
+ nsects--;
+ }
+}
+
/*
* Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
* buffer. Once the first sector is added, any subsequent sectors are
@@ -1049,11 +661,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
}
/* Throw away any remaining data. */
- while (sectors_to_transfer > 0) {
- static char dum[SECTOR_SIZE];
- HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
- --sectors_to_transfer;
- }
+ ide_cd_drain_data(drive, sectors_to_transfer);
}
/*
@@ -1062,23 +670,25 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
* ok; nonzero if the request has been terminated.
*/
static
-int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
+int ide_cd_check_ireason(ide_drive_t *drive, int len, int ireason, int rw)
{
- if (ireason == 2)
+ /*
+ * ireason == 0: the drive wants to receive data from us
+ * ireason == 2: the drive is expecting to transfer data to us
+ */
+ if (ireason == (!rw << 1))
return 0;
- else if (ireason == 0) {
- /* Whoops... The drive is expecting to receive data from us! */
- printk(KERN_ERR "%s: read_intr: Drive wants to transfer data the "
- "wrong way!\n", drive->name);
-
- /* Throw some data at the drive so it doesn't hang
- and quit this request. */
- while (len > 0) {
- int dum = 0;
- HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof (dum));
- len -= sizeof (dum);
- }
- } else if (ireason == 1) {
+ else if (ireason == (rw << 1)) {
+ ide_hwif_t *hwif = drive->hwif;
+ xfer_func_t *xf;
+
+ /* Whoops... */
+ printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
+ drive->name, __FUNCTION__);
+
+ xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
+ ide_cd_pad_transfer(drive, xf, len);
+ } else if (rw == 0 && ireason == 1) {
/* Some drives (ASUS) seem to tell us that status
* info is available. just get it and ignore.
*/
@@ -1086,8 +696,8 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
return 0;
} else {
/* Drive wants a command packet, or invalid ireason... */
- printk(KERN_ERR "%s: read_intr: bad interrupt reason %x\n", drive->name,
- ireason);
+ printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
+ drive->name, __FUNCTION__, ireason);
}
cdrom_end_request(drive, 0);
@@ -1095,134 +705,28 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
}
/*
- * Interrupt routine. Called when a read request has completed.
+ * Assume that the drive will always provide data in multiples of at least
+ * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise.
*/
-static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
+static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
{
- int stat;
- int ireason, len, sectors_to_transfer, nskip;
- struct cdrom_info *info = drive->driver_data;
- u8 lowcyl = 0, highcyl = 0;
- int dma = info->dma, dma_error = 0;
-
- struct request *rq = HWGROUP(drive)->rq;
-
- /*
- * handle dma case
- */
- if (dma) {
- info->dma = 0;
- if ((dma_error = HWIF(drive)->ide_dma_end(drive)))
- ide_dma_off(drive);
- }
-
- if (cdrom_decode_status(drive, 0, &stat))
- return ide_stopped;
-
- if (dma) {
- if (!dma_error) {
- ide_end_request(drive, 1, rq->nr_sectors);
- return ide_stopped;
- } else
- return ide_error(drive, "dma error", stat);
- }
-
- /* Read the interrupt reason and the transfer length. */
- ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
- lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
- highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
-
- len = lowcyl + (256 * highcyl);
-
- /* If DRQ is clear, the command has completed. */
- if ((stat & DRQ_STAT) == 0) {
- /* If we're not done filling the current buffer, complain.
- Otherwise, complete the command normally. */
- if (rq->current_nr_sectors > 0) {
- printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
- drive->name, rq->current_nr_sectors);
- rq->cmd_flags |= REQ_FAILED;
- cdrom_end_request(drive, 0);
- } else
- cdrom_end_request(drive, 1);
- return ide_stopped;
- }
-
- /* Check that the drive is expecting to do the same thing we are. */
- if (cdrom_read_check_ireason (drive, len, ireason))
- return ide_stopped;
-
- /* Assume that the drive will always provide data in multiples
- of at least SECTOR_SIZE, as it gets hairy to keep track
- of the transfers otherwise. */
- if ((len % SECTOR_SIZE) != 0) {
- printk (KERN_ERR "%s: cdrom_read_intr: Bad transfer size %d\n",
- drive->name, len);
- if (CDROM_CONFIG_FLAGS(drive)->limit_nframes)
- printk (KERN_ERR " This drive is not supported by this version of the driver\n");
- else {
- printk (KERN_ERR " Trying to limit transfer sizes\n");
- CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
- }
- cdrom_end_request(drive, 0);
- return ide_stopped;
- }
-
- /* The number of sectors we need to read from the drive. */
- sectors_to_transfer = len / SECTOR_SIZE;
-
- /* First, figure out if we need to bit-bucket
- any of the leading sectors. */
- nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer);
-
- while (nskip > 0) {
- /* We need to throw away a sector. */
- static char dum[SECTOR_SIZE];
- HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
+ struct cdrom_info *cd = drive->driver_data;
- --rq->current_nr_sectors;
- --nskip;
- --sectors_to_transfer;
- }
+ if ((len % SECTOR_SIZE) == 0)
+ return 0;
- /* Now loop while we still have data to read from the drive. */
- while (sectors_to_transfer > 0) {
- int this_transfer;
+ printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
+ drive->name, __FUNCTION__, len);
- /* If we've filled the present buffer but there's another
- chained buffer after it, move on. */
- if (rq->current_nr_sectors == 0 && rq->nr_sectors)
- cdrom_end_request(drive, 1);
-
- /* If the buffers are full, cache the rest of the data in our
- internal buffer. */
- if (rq->current_nr_sectors == 0) {
- cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
- sectors_to_transfer = 0;
- } else {
- /* Transfer data to the buffers.
- Figure out how many sectors we can transfer
- to the current buffer. */
- this_transfer = min_t(int, sectors_to_transfer,
- rq->current_nr_sectors);
-
- /* Read this_transfer sectors
- into the current buffer. */
- while (this_transfer > 0) {
- HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
- rq->buffer += SECTOR_SIZE;
- --rq->nr_sectors;
- --rq->current_nr_sectors;
- ++rq->sector;
- --this_transfer;
- --sectors_to_transfer;
- }
- }
+ if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
+ printk(KERN_ERR " This drive is not supported by "
+ "this version of the driver\n");
+ else {
+ printk(KERN_ERR " Trying to limit transfer sizes\n");
+ cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
}
- /* Done moving data! Wait for another interrupt. */
- ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL);
- return ide_started;
+ return 1;
}
/*
@@ -1284,48 +788,58 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
return 0;
}
+static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
+
/*
- * Routine to send a read packet command to the drive.
- * This is usually called directly from cdrom_start_read.
+ * Routine to send a read/write packet command to the drive.
+ * This is usually called directly from cdrom_start_{read,write}().
* However, for drq_interrupt devices, it is called from an interrupt
* when the drive is ready to accept the command.
*/
-static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
+static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
- unsigned short sectors_per_frame;
- int nskip;
- sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+ if (rq_data_dir(rq) == READ) {
+ unsigned short sectors_per_frame =
+ queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+ int nskip = rq->sector & (sectors_per_frame - 1);
- /* If the requested sector doesn't start on a cdrom block boundary,
- we must adjust the start of the transfer so that it does,
- and remember to skip the first few sectors.
- If the CURRENT_NR_SECTORS field is larger than the size
- of the buffer, it will mean that we're to skip a number
- of sectors equal to the amount by which CURRENT_NR_SECTORS
- is larger than the buffer size. */
- nskip = rq->sector & (sectors_per_frame - 1);
- if (nskip > 0) {
- /* Sanity check... */
- if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) &&
- (rq->sector & (sectors_per_frame - 1))) {
- printk(KERN_ERR "%s: cdrom_start_read_continuation: buffer botch (%u)\n",
- drive->name, rq->current_nr_sectors);
- cdrom_end_request(drive, 0);
- return ide_stopped;
+ /*
+ * If the requested sector doesn't start on a frame boundary,
+ * we must adjust the start of the transfer so that it does,
+ * and remember to skip the first few sectors.
+ *
+ * If the rq->current_nr_sectors field is larger than the size
+ * of the buffer, it will mean that we're to skip a number of
+ * sectors equal to the amount by which rq->current_nr_sectors
+ * is larger than the buffer size.
+ */
+ if (nskip > 0) {
+ /* Sanity check... */
+ if (rq->current_nr_sectors !=
+ bio_cur_sectors(rq->bio)) {
+ printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
+ drive->name, __FUNCTION__,
+ rq->current_nr_sectors);
+ cdrom_end_request(drive, 0);
+ return ide_stopped;
+ }
+ rq->current_nr_sectors += nskip;
}
- rq->current_nr_sectors += nskip;
}
-
+#if 0
+ else
+ /* the immediate bit */
+ rq->cmd[1] = 1 << 3;
+#endif
/* Set up the command */
rq->timeout = ATAPI_WAIT_PC;
/* Send the command to the drive and return. */
- return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr);
+ return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
-
#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
#define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */
@@ -1338,7 +852,8 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
if (cdrom_decode_status(drive, 0, &stat))
return ide_stopped;
- CDROM_CONFIG_FLAGS(drive)->seeking = 1;
+
+ info->cd_flags |= IDE_CD_FLAG_SEEKING;
if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
if (--retry == 0) {
@@ -1394,184 +909,25 @@ static void restore_request (struct request *rq)
rq->q->prep_rq_fn(rq->q, rq);
}
-/*
- * Start a read request from the CD-ROM.
- */
-static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
-{
- struct cdrom_info *info = drive->driver_data;
- struct request *rq = HWGROUP(drive)->rq;
- unsigned short sectors_per_frame;
-
- sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-
- /* We may be retrying this request after an error. Fix up
- any weirdness which might be present in the request packet. */
- restore_request(rq);
-
- /* Satisfy whatever we can of this request from our cached sector. */
- if (cdrom_read_from_buffer(drive))
- return ide_stopped;
-
- /* Clear the local sector buffer. */
- info->nsectors_buffered = 0;
-
- /* use dma, if possible. */
- info->dma = drive->using_dma;
- if ((rq->sector & (sectors_per_frame - 1)) ||
- (rq->nr_sectors & (sectors_per_frame - 1)))
- info->dma = 0;
-
- /* Start sending the read request to the drive. */
- return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
-}
-
/****************************************************************************
* Execute all other packet commands.
*/
-/* Interrupt routine for packet command completion. */
-static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
+static void ide_cd_request_sense_fixup(struct request *rq)
{
- int ireason, len, thislen;
- struct request *rq = HWGROUP(drive)->rq;
- u8 lowcyl = 0, highcyl = 0;
- int stat;
-
- /* Check for errors. */
- if (cdrom_decode_status(drive, 0, &stat))
- return ide_stopped;
-
- /* Read the interrupt reason and the transfer length. */
- ireason = HWIF(drive)->INB(IDE_IREASON_REG);
- lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
- highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
-
- len = lowcyl + (256 * highcyl);
-
- /* If DRQ is clear, the command has completed.
- Complain if we still have data left to transfer. */
- if ((stat & DRQ_STAT) == 0) {
- /* Some of the trailing request sense fields are optional, and
- some drives don't send them. Sigh. */
- if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
- rq->data_len > 0 &&
- rq->data_len <= 5) {
- while (rq->data_len > 0) {
- *(unsigned char *)rq->data++ = 0;
- --rq->data_len;
- }
- }
-
- if (rq->data_len == 0)
- cdrom_end_request(drive, 1);
- else {
- /* Comment this out, because this always happens
- right after a reset occurs, and it is annoying to
- always print expected stuff. */
- /*
- printk ("%s: cdrom_pc_intr: data underrun %d\n",
- drive->name, pc->buflen);
- */
- rq->cmd_flags |= REQ_FAILED;
- cdrom_end_request(drive, 0);
- }
- return ide_stopped;
- }
-
- /* Figure out how much data to transfer. */
- thislen = rq->data_len;
- if (thislen > len) thislen = len;
-
- /* The drive wants to be written to. */
- if ((ireason & 3) == 0) {
- if (!rq->data) {
- blk_dump_rq_flags(rq, "cdrom_pc_intr, write");
- goto confused;
- }
- /* Transfer the data. */
- HWIF(drive)->atapi_output_bytes(drive, rq->data, thislen);
-
- /* If we haven't moved enough data to satisfy the drive,
- add some padding. */
- while (len > thislen) {
- int dum = 0;
- HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum));
- len -= sizeof(dum);
- }
-
- /* Keep count of how much data we've moved. */
- rq->data += thislen;
- rq->data_len -= thislen;
- }
-
- /* Same drill for reading. */
- else if ((ireason & 3) == 2) {
- if (!rq->data) {
- blk_dump_rq_flags(rq, "cdrom_pc_intr, write");
- goto confused;
- }
- /* Transfer the data. */
- HWIF(drive)->atapi_input_bytes(drive, rq->data, thislen);
-
- /* If we haven't moved enough data to satisfy the drive,
- add some padding. */
- while (len > thislen) {
- int dum = 0;
- HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum));
- len -= sizeof(dum);
+ /*
+ * Some of the trailing request sense fields are optional,
+ * and some drives don't send them. Sigh.
+ */
+ if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
+ rq->data_len > 0 && rq->data_len <= 5)
+ while (rq->data_len > 0) {
+ *(u8 *)rq->data++ = 0;
+ --rq->data_len;
}
-
- /* Keep count of how much data we've moved. */
- rq->data += thislen;
- rq->data_len -= thislen;
-
- if (blk_sense_request(rq))
- rq->sense_len += thislen;
- } else {
-confused:
- printk (KERN_ERR "%s: cdrom_pc_intr: The drive "
- "appears confused (ireason = 0x%02x). "
- "Trying to recover by ending request.\n",
- drive->name, ireason);
- rq->cmd_flags |= REQ_FAILED;
- cdrom_end_request(drive, 0);
- return ide_stopped;
- }
-
- /* Now we wait for another interrupt. */
- ide_set_handler(drive, &cdrom_pc_intr, ATAPI_WAIT_PC, cdrom_timer_expiry);
- return ide_started;
-}
-
-static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
-
- if (!rq->timeout)
- rq->timeout = ATAPI_WAIT_PC;
-
- /* Send the command to the drive and return. */
- return cdrom_transfer_packet_command(drive, rq, &cdrom_pc_intr);
-}
-
-
-static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
-{
- int len;
- struct request *rq = HWGROUP(drive)->rq;
- struct cdrom_info *info = drive->driver_data;
-
- info->dma = 0;
- rq->cmd_flags &= ~REQ_FAILED;
- len = rq->data_len;
-
- /* Start sending the command to the drive. */
- return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation);
}
-
-static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
+int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
{
struct request_sense sense;
int retries = 10;
@@ -1620,84 +976,37 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
}
/*
- * Write handling
+ * Called from blk_end_request_callback() after the data of the request
+ * is completed and before the request is completed.
+ * By returning value '1', blk_end_request_callback() returns immediately
+ * without completing the request.
*/
-static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
+static int cdrom_newpc_intr_dummy_cb(struct request *rq)
{
- /* Two notes about IDE interrupt reason here - 0 means that
- * the drive wants to receive data from us, 2 means that
- * the drive is expecting to transfer data to us.
- */
- if (ireason == 0)
- return 0;
- else if (ireason == 2) {
- /* Whoops... The drive wants to send data. */
- printk(KERN_ERR "%s: write_intr: wrong transfer direction!\n",
- drive->name);
-
- while (len > 0) {
- int dum = 0;
- HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum));
- len -= sizeof(dum);
- }
- } else {
- /* Drive wants a command packet, or invalid ireason... */
- printk(KERN_ERR "%s: write_intr: bad interrupt reason %x\n",
- drive->name, ireason);
- }
-
- cdrom_end_request(drive, 0);
return 1;
}
-static void post_transform_command(struct request *req)
-{
- u8 *c = req->cmd;
- char *ibuf;
-
- if (!blk_pc_request(req))
- return;
-
- if (req->bio)
- ibuf = bio_data(req->bio);
- else
- ibuf = req->data;
-
- if (!ibuf)
- return;
-
- /*
- * set ansi-revision and response data as atapi
- */
- if (c[0] == GPCMD_INQUIRY) {
- ibuf[2] |= 2;
- ibuf[3] = (ibuf[3] & 0xf0) | 2;
- }
-}
-
-typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
-
-/*
- * best way to deal with dma that is not sector aligned right now... note
- * that in this path we are not using ->data or ->buffer at all. this irs
- * can replace cdrom_pc_intr, cdrom_read_intr, and cdrom_write_intr in the
- * future.
- */
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
struct request *rq = HWGROUP(drive)->rq;
- int dma_error, dma, stat, ireason, len, thislen;
- u8 lowcyl, highcyl;
xfer_func_t *xferfunc;
- unsigned long flags;
+ ide_expiry_t *expiry = NULL;
+ int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
+ int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
+ unsigned int timeout;
+ u8 lowcyl, highcyl;
/* Check for errors. */
- dma_error = 0;
dma = info->dma;
if (dma) {
info->dma = 0;
dma_error = HWIF(drive)->ide_dma_end(drive);
+ if (dma_error) {
+ printk(KERN_ERR "%s: DMA %s error\n", drive->name,
+ write ? "write" : "read");
+ ide_dma_off(drive);
+ }
}
if (cdrom_decode_status(drive, 0, &stat))
@@ -1707,14 +1016,12 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
* using dma, transfer is complete now
*/
if (dma) {
- if (dma_error) {
- printk(KERN_ERR "ide-cd: dma error\n");
- ide_dma_off(drive);
+ if (dma_error)
return ide_error(drive, "dma error", stat);
+ if (blk_fs_request(rq)) {
+ ide_end_request(drive, 1, rq->nr_sectors);
+ return ide_stopped;
}
-
- end_that_request_chunk(rq, 1, rq->data_len);
- rq->data_len = 0;
goto end_request;
}
@@ -1726,54 +1033,120 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
len = lowcyl + (256 * highcyl);
- thislen = rq->data_len;
+
+ thislen = blk_fs_request(rq) ? len : rq->data_len;
if (thislen > len)
thislen = len;
/*
* If DRQ is clear, the command has completed.
*/
- if ((stat & DRQ_STAT) == 0)
+ if ((stat & DRQ_STAT) == 0) {
+ if (blk_fs_request(rq)) {
+ /*
+ * If we're not done reading/writing, complain.
+ * Otherwise, complete the command normally.
+ */
+ uptodate = 1;
+ if (rq->current_nr_sectors > 0) {
+ printk(KERN_ERR "%s: %s: data underrun "
+ "(%d blocks)\n",
+ drive->name, __FUNCTION__,
+ rq->current_nr_sectors);
+ if (!write)
+ rq->cmd_flags |= REQ_FAILED;
+ uptodate = 0;
+ }
+ cdrom_end_request(drive, uptodate);
+ return ide_stopped;
+ } else if (!blk_pc_request(rq)) {
+ ide_cd_request_sense_fixup(rq);
+ /* Complain if we still have data left to transfer. */
+ uptodate = rq->data_len ? 0 : 1;
+ }
goto end_request;
+ }
/*
* check which way to transfer data
*/
- if (rq_data_dir(rq) == WRITE) {
- /*
- * write to drive
- */
- if (cdrom_write_check_ireason(drive, len, ireason))
+ if (blk_fs_request(rq) || blk_pc_request(rq)) {
+ if (ide_cd_check_ireason(drive, len, ireason, write))
return ide_stopped;
- xferfunc = HWIF(drive)->atapi_output_bytes;
- } else {
- /*
- * read from drive
- */
- if (cdrom_read_check_ireason(drive, len, ireason))
- return ide_stopped;
+ if (blk_fs_request(rq) && write == 0) {
+ int nskip;
+
+ if (ide_cd_check_transfer_size(drive, len)) {
+ cdrom_end_request(drive, 0);
+ return ide_stopped;
+ }
+
+ /*
+ * First, figure out if we need to bit-bucket
+ * any of the leading sectors.
+ */
+ nskip = min_t(int, rq->current_nr_sectors
+ - bio_cur_sectors(rq->bio),
+ thislen >> 9);
+ if (nskip > 0) {
+ ide_cd_drain_data(drive, nskip);
+ rq->current_nr_sectors -= nskip;
+ thislen -= (nskip << 9);
+ }
+ }
+ }
+ if (ireason == 0) {
+ write = 1;
+ xferfunc = HWIF(drive)->atapi_output_bytes;
+ } else if (ireason == 2 || (ireason == 1 &&
+ (blk_fs_request(rq) || blk_pc_request(rq)))) {
+ write = 0;
xferfunc = HWIF(drive)->atapi_input_bytes;
+ } else {
+ printk(KERN_ERR "%s: %s: The drive "
+ "appears confused (ireason = 0x%02x). "
+ "Trying to recover by ending request.\n",
+ drive->name, __FUNCTION__, ireason);
+ goto end_request;
}
/*
* transfer data
*/
while (thislen > 0) {
- int blen = blen = rq->data_len;
- char *ptr = rq->data;
+ u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
+ int blen = rq->data_len;
/*
* bio backed?
*/
if (rq->bio) {
- ptr = bio_data(rq->bio);
- blen = bio_iovec(rq->bio)->bv_len;
+ if (blk_fs_request(rq)) {
+ ptr = rq->buffer;
+ blen = rq->current_nr_sectors << 9;
+ } else {
+ ptr = bio_data(rq->bio);
+ blen = bio_iovec(rq->bio)->bv_len;
+ }
}
if (!ptr) {
- printk(KERN_ERR "%s: confused, missing data\n", drive->name);
+ if (blk_fs_request(rq) && !write)
+ /*
+ * If the buffers are full, cache the rest
+ * of the data in our internal buffer.
+ */
+ cdrom_buffer_sectors(drive, rq->sector,
+ thislen >> 9);
+ else {
+ printk(KERN_ERR "%s: confused, missing data\n",
+ drive->name);
+ blk_dump_rq_flags(rq, rq_data_dir(rq)
+ ? "cdrom_newpc_intr, write"
+ : "cdrom_newpc_intr, read");
+ }
break;
}
@@ -1784,186 +1157,117 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
thislen -= blen;
len -= blen;
- rq->data_len -= blen;
-
- if (rq->bio)
- end_that_request_chunk(rq, 1, blen);
- else
- rq->data += blen;
- }
-
- /*
- * pad, if necessary
- */
- if (len > 0) {
- while (len > 0) {
- int pad = 0;
-
- xferfunc(drive, &pad, sizeof(pad));
- len -= sizeof(pad);
- }
- }
-
- BUG_ON(HWGROUP(drive)->handler != NULL);
-
- ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL);
- return ide_started;
-
-end_request:
- if (!rq->data_len)
- post_transform_command(rq);
-
- spin_lock_irqsave(&ide_lock, flags);
- blkdev_dequeue_request(rq);
- end_that_request_last(rq, 1);
- HWGROUP(drive)->rq = NULL;
- spin_unlock_irqrestore(&ide_lock, flags);
- return ide_stopped;
-}
-static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
-{
- int stat, ireason, len, sectors_to_transfer, uptodate;
- struct cdrom_info *info = drive->driver_data;
- int dma_error = 0, dma = info->dma;
- u8 lowcyl = 0, highcyl = 0;
+ if (blk_fs_request(rq)) {
+ rq->buffer += blen;
+ rq->nr_sectors -= (blen >> 9);
+ rq->current_nr_sectors -= (blen >> 9);
+ rq->sector += (blen >> 9);
- struct request *rq = HWGROUP(drive)->rq;
+ if (rq->current_nr_sectors == 0 && rq->nr_sectors)
+ cdrom_end_request(drive, 1);
+ } else {
+ rq->data_len -= blen;
- /* Check for errors. */
- if (dma) {
- info->dma = 0;
- if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {
- printk(KERN_ERR "ide-cd: write dma error\n");
- ide_dma_off(drive);
+ /*
+ * The request can't be completed until DRQ is cleared.
+ * So complete the data, but don't complete the request
+ * using the dummy function for the callback feature
+ * of blk_end_request_callback().
+ */
+ if (rq->bio)
+ blk_end_request_callback(rq, 0, blen,
+ cdrom_newpc_intr_dummy_cb);
+ else
+ rq->data += blen;
}
}
- if (cdrom_decode_status(drive, 0, &stat))
- return ide_stopped;
+ if (write && blk_sense_request(rq))
+ rq->sense_len += thislen;
/*
- * using dma, transfer is complete now
+ * pad, if necessary
*/
- if (dma) {
- if (dma_error)
- return ide_error(drive, "dma error", stat);
+ if (!blk_fs_request(rq) && len > 0)
+ ide_cd_pad_transfer(drive, xferfunc, len);
- ide_end_request(drive, 1, rq->nr_sectors);
- return ide_stopped;
+ if (blk_pc_request(rq)) {
+ timeout = rq->timeout;
+ } else {
+ timeout = ATAPI_WAIT_PC;
+ if (!blk_fs_request(rq))
+ expiry = cdrom_timer_expiry;
}
- /* Read the interrupt reason and the transfer length. */
- ireason = HWIF(drive)->INB(IDE_IREASON_REG);
- lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
- highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
+ ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
+ return ide_started;
- len = lowcyl + (256 * highcyl);
+end_request:
+ if (blk_pc_request(rq)) {
+ unsigned long flags;
- /* If DRQ is clear, the command has completed. */
- if ((stat & DRQ_STAT) == 0) {
- /* If we're not done writing, complain.
- * Otherwise, complete the command normally.
- */
- uptodate = 1;
- if (rq->current_nr_sectors > 0) {
- printk(KERN_ERR "%s: write_intr: data underrun (%d blocks)\n",
- drive->name, rq->current_nr_sectors);
- uptodate = 0;
- }
+ spin_lock_irqsave(&ide_lock, flags);
+ if (__blk_end_request(rq, 0, rq->data_len))
+ BUG();
+ HWGROUP(drive)->rq = NULL;
+ spin_unlock_irqrestore(&ide_lock, flags);
+ } else {
+ if (!uptodate)
+ rq->cmd_flags |= REQ_FAILED;
cdrom_end_request(drive, uptodate);
- return ide_stopped;
}
+ return ide_stopped;
+}
- /* Check that the drive is expecting to do the same thing we are. */
- if (cdrom_write_check_ireason(drive, len, ireason))
- return ide_stopped;
-
- sectors_to_transfer = len / SECTOR_SIZE;
-
- /*
- * now loop and write out the data
- */
- while (sectors_to_transfer > 0) {
- int this_transfer;
-
- if (!rq->current_nr_sectors) {
- printk(KERN_ERR "ide-cd: write_intr: oops\n");
- break;
- }
+static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
+{
+ struct cdrom_info *cd = drive->driver_data;
+ int write = rq_data_dir(rq) == WRITE;
+ unsigned short sectors_per_frame =
+ queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+ if (write) {
/*
- * Figure out how many sectors we can transfer
+ * disk has become write protected
*/
- this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors);
-
- while (this_transfer > 0) {
- HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
- rq->buffer += SECTOR_SIZE;
- --rq->nr_sectors;
- --rq->current_nr_sectors;
- ++rq->sector;
- --this_transfer;
- --sectors_to_transfer;
+ if (cd->disk->policy) {
+ cdrom_end_request(drive, 0);
+ return ide_stopped;
}
-
+ } else {
/*
- * current buffer complete, move on
+ * We may be retrying this request after an error. Fix up any
+ * weirdness which might be present in the request packet.
*/
- if (rq->current_nr_sectors == 0 && rq->nr_sectors)
- cdrom_end_request(drive, 1);
- }
-
- /* re-arm handler */
- ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL);
- return ide_started;
-}
-
-static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
+ restore_request(rq);
-#if 0 /* the immediate bit */
- rq->cmd[1] = 1 << 3;
-#endif
- rq->timeout = ATAPI_WAIT_PC;
-
- return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr);
-}
-
-static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
-{
- struct cdrom_info *info = drive->driver_data;
- struct gendisk *g = info->disk;
- unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+ /* Satisfy whatever we can of this request from our cache. */
+ if (cdrom_read_from_buffer(drive))
+ return ide_stopped;
+ }
/*
- * writes *must* be hardware frame aligned
+ * use DMA, if possible / writes *must* be hardware frame aligned
*/
if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
(rq->sector & (sectors_per_frame - 1))) {
- cdrom_end_request(drive, 0);
- return ide_stopped;
- }
-
- /*
- * disk has become write protected
- */
- if (g->policy) {
- cdrom_end_request(drive, 0);
- return ide_stopped;
- }
-
- info->nsectors_buffered = 0;
+ if (write) {
+ cdrom_end_request(drive, 0);
+ return ide_stopped;
+ }
+ cd->dma = 0;
+ } else
+ cd->dma = drive->using_dma;
- /* use dma, if possible. we don't need to check more, since we
- * know that the transfer is always (at least!) frame aligned */
- info->dma = drive->using_dma ? 1 : 0;
+ /* Clear the local sector buffer. */
+ cd->nsectors_buffered = 0;
- info->devinfo.media_written = 1;
+ if (write)
+ cd->devinfo.media_written = 1;
- /* Start sending the write request to the drive. */
- return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
+ /* Start sending the read/write request to the drive. */
+ return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
}
static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
@@ -1980,7 +1284,10 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
struct cdrom_info *info = drive->driver_data;
- rq->cmd_flags |= REQ_QUIET;
+ if (blk_pc_request(rq))
+ rq->cmd_flags |= REQ_QUIET;
+ else
+ rq->cmd_flags &= ~REQ_FAILED;
info->dma = 0;
@@ -2017,7 +1324,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
struct cdrom_info *info = drive->driver_data;
if (blk_fs_request(rq)) {
- if (CDROM_CONFIG_FLAGS(drive)->seeking) {
+ if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
unsigned long elapsed = jiffies - info->start_seek;
int stat = HWIF(drive)->INB(IDE_STATUS_REG);
@@ -2028,22 +1335,16 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
}
printk (KERN_ERR "%s: DSC timeout\n", drive->name);
}
- CDROM_CONFIG_FLAGS(drive)->seeking = 0;
+ info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
}
if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
action = cdrom_start_seek(drive, block);
- } else {
- if (rq_data_dir(rq) == READ)
- action = cdrom_start_read(drive, block);
- else
- action = cdrom_start_write(drive, rq);
- }
+ } else
+ action = cdrom_start_rw(drive, rq);
info->last_block = block;
return action;
- } else if (rq->cmd_type == REQ_TYPE_SENSE ||
+ } else if (blk_sense_request(rq) || blk_pc_request(rq) ||
rq->cmd_type == REQ_TYPE_ATA_PC) {
- return cdrom_do_packet_command(drive);
- } else if (blk_pc_request(rq)) {
return cdrom_do_block_pc(drive, rq);
} else if (blk_special_request(rq)) {
/*
@@ -2070,141 +1371,33 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
* can also be NULL, in which case no sense information is returned.
*/
-#if ! STANDARD_ATAPI
-static inline
-int bin2bcd (int x)
-{
- return (x%10) | ((x/10) << 4);
-}
-
-
-static inline
-int bcd2bin (int x)
-{
- return (x >> 4) * 10 + (x & 0x0f);
-}
-
static
void msf_from_bcd (struct atapi_msf *msf)
{
- msf->minute = bcd2bin (msf->minute);
- msf->second = bcd2bin (msf->second);
- msf->frame = bcd2bin (msf->frame);
-}
-
-#endif /* not STANDARD_ATAPI */
-
-
-static inline
-void lba_to_msf (int lba, byte *m, byte *s, byte *f)
-{
- lba += CD_MSF_OFFSET;
- lba &= 0xffffff; /* negative lbas use only 24 bits */
- *m = lba / (CD_SECS * CD_FRAMES);
- lba %= (CD_SECS * CD_FRAMES);
- *s = lba / CD_FRAMES;
- *f = lba % CD_FRAMES;
-}
-
-
-static inline
-int msf_to_lba (byte m, byte s, byte f)
-{
- return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
+ msf->minute = BCD2BIN(msf->minute);
+ msf->second = BCD2BIN(msf->second);
+ msf->frame = BCD2BIN(msf->frame);
}
-static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
+int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
{
struct request req;
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
- cdrom_prepare_request(drive, &req);
+ ide_cd_init_rq(drive, &req);
req.sense = sense;
req.cmd[0] = GPCMD_TEST_UNIT_READY;
req.cmd_flags |= REQ_QUIET;
-#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 */
-
+ /*
+ * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
+ * switch CDs instead of supporting the LOAD_UNLOAD opcode.
+ */
req.cmd[7] = cdi->sanyo_slot % 3;
-#endif /* not STANDARD_ATAPI */
- return cdrom_queue_packet_command(drive, &req);
-}
-
-
-/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
-static int
-cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
-{
- struct request_sense my_sense;
- struct request req;
- int stat;
-
- if (sense == NULL)
- sense = &my_sense;
-
- /* If the drive cannot lock the door, just pretend. */
- if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
- stat = 0;
- } else {
- cdrom_prepare_request(drive, &req);
- req.sense = sense;
- req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
- req.cmd[4] = lockflag ? 1 : 0;
- stat = cdrom_queue_packet_command(drive, &req);
- }
-
- /* If we got an illegal field error, the drive
- probably cannot lock the door. */
- if (stat != 0 &&
- sense->sense_key == ILLEGAL_REQUEST &&
- (sense->asc == 0x24 || sense->asc == 0x20)) {
- printk (KERN_ERR "%s: door locking not supported\n",
- drive->name);
- CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
- stat = 0;
- }
-
- /* no medium, that's alright. */
- if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
- stat = 0;
-
- if (stat == 0)
- CDROM_STATE_FLAGS(drive)->door_locked = lockflag;
-
- return stat;
-}
-
-
-/* Eject the disk if EJECTFLAG is 0.
- If EJECTFLAG is 1, try to reload the disk. */
-static int cdrom_eject(ide_drive_t *drive, int ejectflag,
- struct request_sense *sense)
-{
- struct request req;
- char loej = 0x02;
-
- 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;
-
- cdrom_prepare_request(drive, &req);
-
- /* only tell drive to close tray if open, if it can do that */
- if (ejectflag && !CDROM_CONFIG_FLAGS(drive)->close_tray)
- loej = 0;
-
- req.sense = sense;
- req.cmd[0] = GPCMD_START_STOP_UNIT;
- req.cmd[4] = loej | (ejectflag != 0);
- return cdrom_queue_packet_command(drive, &req);
+ return ide_cd_queue_pc(drive, &req);
}
static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -2219,7 +1412,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
int stat;
struct request req;
- cdrom_prepare_request(drive, &req);
+ ide_cd_init_rq(drive, &req);
req.sense = sense;
req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
@@ -2227,7 +1420,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
req.data_len = sizeof(capbuf);
req.cmd_flags |= REQ_QUIET;
- stat = cdrom_queue_packet_command(drive, &req);
+ stat = ide_cd_queue_pc(drive, &req);
if (stat == 0) {
*capacity = 1 + be32_to_cpu(capbuf.lba);
*sectors_per_frame =
@@ -2243,7 +1436,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
{
struct request req;
- cdrom_prepare_request(drive, &req);
+ ide_cd_init_rq(drive, &req);
req.sense = sense;
req.data = buf;
@@ -2258,12 +1451,11 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
if (msf_flag)
req.cmd[1] = 2;
- return cdrom_queue_packet_command(drive, &req);
+ return ide_cd_queue_pc(drive, &req);
}
-
/* Try to read the entire TOC for the disk into our internal buffer. */
-static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
{
int stat, ntracks, i;
struct cdrom_info *info = drive->driver_data;
@@ -2290,7 +1482,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
If it is, just return. */
(void) cdrom_check_status(drive, sense);
- if (CDROM_STATE_FLAGS(drive)->toc_valid)
+ if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
return 0;
/* Try to get the total cdrom capacity and sector size. */
@@ -2312,12 +1504,10 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
- toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
- toc->hdr.last_track = bcd2bin(toc->hdr.last_track);
+ if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
+ toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
}
-#endif /* not STANDARD_ATAPI */
ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
if (ntracks <= 0)
@@ -2349,16 +1539,13 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
(ntracks + 1) *
sizeof(struct atapi_toc_entry),
sense);
- if (stat) {
+ 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 */
- {
+
+ if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
+ toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
+ } else {
toc->hdr.first_track = CDROM_LEADOUT;
toc->hdr.last_track = CDROM_LEADOUT;
}
@@ -2369,21 +1556,17 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
- toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
- toc->hdr.last_track = bcd2bin(toc->hdr.last_track);
+ if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
+ toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
}
-#endif /* not STANDARD_ATAPI */
- for (i=0; i<=ntracks; i++) {
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
- if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd)
- toc->ent[i].track = bcd2bin(toc->ent[i].track);
+ for (i = 0; i <= ntracks; i++) {
+ if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+ if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
+ toc->ent[i].track = BCD2BIN(toc->ent[i].track);
msf_from_bcd(&toc->ent[i].addr.msf);
}
-#endif /* not STANDARD_ATAPI */
toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
toc->ent[i].addr.msf.second,
toc->ent[i].addr.msf.frame);
@@ -2403,8 +1586,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
}
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
+ if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
/* Re-read multisession information using MSF format */
stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
sizeof(ms_tmp), sense);
@@ -2416,7 +1598,6 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
ms_tmp.ent.addr.msf.second,
ms_tmp.ent.addr.msf.frame);
}
-#endif /* not STANDARD_ATAPI */
toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
@@ -2429,278 +1610,22 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
}
/* Remember that we've read this stuff. */
- CDROM_STATE_FLAGS(drive)->toc_valid = 1;
-
- return 0;
-}
-
-
-static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
- int buflen, struct request_sense *sense)
-{
- struct request req;
-
- cdrom_prepare_request(drive, &req);
-
- req.sense = sense;
- req.data = buf;
- req.data_len = buflen;
- req.cmd[0] = GPCMD_READ_SUBCHANNEL;
- req.cmd[1] = 2; /* MSF addressing */
- req.cmd[2] = 0x40; /* request subQ data */
- req.cmd[3] = format;
- req.cmd[7] = (buflen >> 8);
- req.cmd[8] = (buflen & 0xff);
- return cdrom_queue_packet_command(drive, &req);
-}
-
-/* ATAPI cdrom drives are free to select the speed you request or any slower
- rate :-( Requesting too fast a speed will _not_ produce an error. */
-static int cdrom_select_speed(ide_drive_t *drive, int speed,
- struct request_sense *sense)
-{
- struct request req;
- cdrom_prepare_request(drive, &req);
-
- req.sense = sense;
- if (speed == 0)
- speed = 0xffff; /* set to max */
- else
- speed *= 177; /* Nx to kbytes/s */
-
- req.cmd[0] = GPCMD_SET_SPEED;
- /* Read Drive speed in kbytes/second MSB */
- req.cmd[2] = (speed >> 8) & 0xff;
- /* Read Drive speed in kbytes/second LSB */
- req.cmd[3] = speed & 0xff;
- if (CDROM_CONFIG_FLAGS(drive)->cd_r ||
- CDROM_CONFIG_FLAGS(drive)->cd_rw ||
- CDROM_CONFIG_FLAGS(drive)->dvd_r) {
- /* Write Drive speed in kbytes/second MSB */
- req.cmd[4] = (speed >> 8) & 0xff;
- /* Write Drive speed in kbytes/second LSB */
- req.cmd[5] = speed & 0xff;
- }
-
- return cdrom_queue_packet_command(drive, &req);
-}
-
-static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
-{
- struct request_sense sense;
- struct request req;
-
- cdrom_prepare_request(drive, &req);
-
- req.sense = &sense;
- req.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
- lba_to_msf(lba_start, &req.cmd[3], &req.cmd[4], &req.cmd[5]);
- lba_to_msf(lba_end-1, &req.cmd[6], &req.cmd[7], &req.cmd[8]);
-
- return cdrom_queue_packet_command(drive, &req);
-}
-
-static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
- struct atapi_toc_entry **ent)
-{
- struct cdrom_info *info = drive->driver_data;
- struct atapi_toc *toc = info->toc;
- int ntracks;
-
- /*
- * don't serve cached data, if the toc isn't valid
- */
- if (!CDROM_STATE_FLAGS(drive)->toc_valid)
- return -EINVAL;
-
- /* 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 ||
- track > toc->hdr.last_track)
- return -EINVAL;
- else
- *ent = &toc->ent[track - toc->hdr.first_track];
+ info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
return 0;
}
-/* the generic packet interface to cdrom.c */
-static int ide_cdrom_packet(struct cdrom_device_info *cdi,
- struct packet_command *cgc)
-{
- struct request req;
- ide_drive_t *drive = cdi->handle;
-
- if (cgc->timeout <= 0)
- cgc->timeout = ATAPI_WAIT_PC;
-
- /* here we queue the commands from the uniform CD-ROM
- layer. the packet must be complete, as we do not
- touch it at all. */
- cdrom_prepare_request(drive, &req);
- memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
- if (cgc->sense)
- memset(cgc->sense, 0, sizeof(struct request_sense));
- req.data = cgc->buffer;
- req.data_len = cgc->buflen;
- req.timeout = cgc->timeout;
-
- if (cgc->quiet)
- req.cmd_flags |= REQ_QUIET;
-
- req.sense = cgc->sense;
- cgc->stat = cdrom_queue_packet_command(drive, &req);
- if (!cgc->stat)
- cgc->buflen -= req.data_len;
- return cgc->stat;
-}
-
-static
-int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg)
-
-{
- ide_drive_t *drive = cdi->handle;
- struct cdrom_info *info = drive->driver_data;
- int stat;
-
- switch (cmd) {
- /*
- * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
- * atapi doesn't support it
- */
- case CDROMPLAYTRKIND: {
- unsigned long lba_start, lba_end;
- struct cdrom_ti *ti = arg;
- struct atapi_toc_entry *first_toc, *last_toc;
-
- stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
- if (stat)
- return stat;
-
- stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
- 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_audio(drive, lba_start, lba_end);
- }
-
- case CDROMREADTOCHDR: {
- struct cdrom_tochdr *tochdr = arg;
- struct atapi_toc *toc;
-
- /* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc(drive, NULL);
- if (stat)
- return stat;
-
- toc = info->toc;
- tochdr->cdth_trk0 = toc->hdr.first_track;
- tochdr->cdth_trk1 = toc->hdr.last_track;
-
- return 0;
- }
-
- case CDROMREADTOCENTRY: {
- struct cdrom_tocentry *tocentry = arg;
- struct atapi_toc_entry *toce;
-
- stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce);
- if (stat)
- return stat;
-
- tocentry->cdte_ctrl = toce->control;
- tocentry->cdte_adr = toce->adr;
- 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;
- }
-
- default:
- return -EINVAL;
- }
-}
-
-static
-int ide_cdrom_reset (struct cdrom_device_info *cdi)
-{
- ide_drive_t *drive = cdi->handle;
- struct request_sense sense;
- struct request req;
- int ret;
-
- cdrom_prepare_request(drive, &req);
- req.cmd_type = REQ_TYPE_SPECIAL;
- req.cmd_flags = REQ_QUIET;
- ret = ide_do_drive_cmd(drive, &req, ide_wait);
-
- /*
- * A reset will unlock the door. If it was previously locked,
- * lock it again.
- */
- if (CDROM_STATE_FLAGS(drive)->door_locked)
- (void) cdrom_lockdoor(drive, 1, &sense);
-
- return ret;
-}
-
-
-static
-int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
-{
- ide_drive_t *drive = cdi->handle;
- struct request_sense sense;
-
- if (position) {
- int stat = cdrom_lockdoor(drive, 0, &sense);
- if (stat)
- return stat;
- }
-
- return cdrom_eject(drive, !position, &sense);
-}
-
-static
-int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
-{
- ide_drive_t *drive = cdi->handle;
- return cdrom_lockdoor(drive, lock, NULL);
-}
-
-static
-int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
+int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
{
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
struct packet_command cgc;
- int stat, attempts = 3, size = sizeof(*cap);
+ int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
- /*
- * ACER50 (and others?) require the full spec length mode sense
- * page capabilities size, but older drives break.
- */
- if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
- !strcmp(drive->id->model, "WPI CDS-32X")))
- size -= sizeof(cap->pad);
+ if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
+ size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
- init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
+ init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
if (!stat)
@@ -2709,177 +1634,33 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_pag
return stat;
}
-static
-void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page *cap)
-{
- /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
- if (!drive->id->model[0] &&
- !strncmp(drive->id->fw_rev, "241N", 4)) {
- CDROM_STATE_FLAGS(drive)->current_speed =
- (((unsigned int)cap->curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS(drive)->max_speed =
- (((unsigned int)cap->maxspeed) + (176/2)) / 176;
- } else {
- CDROM_STATE_FLAGS(drive)->current_speed =
- (ntohs(cap->curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS(drive)->max_speed =
- (ntohs(cap->maxspeed) + (176/2)) / 176;
- }
-}
-
-static
-int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
-{
- ide_drive_t *drive = cdi->handle;
- struct request_sense sense;
- struct atapi_capabilities_page cap;
- int stat;
-
- if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0)
- return stat;
-
- if (!ide_cdrom_get_capabilities(drive, &cap)) {
- ide_cdrom_update_speed(drive, &cap);
- cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed;
- }
- return 0;
-}
-
-/*
- * add logic to try GET_EVENT command first to check for media and tray
- * status. this should be supported by newer cd-r/w and all DVD etc
- * drives
- */
-static
-int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
+void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
{
- ide_drive_t *drive = cdi->handle;
- struct media_event_desc med;
- struct request_sense sense;
- int stat;
-
- if (slot_nr != CDSL_CURRENT)
- return -EINVAL;
-
- stat = cdrom_check_status(drive, &sense);
- if (!stat || sense.sense_key == UNIT_ATTENTION)
- return CDS_DISC_OK;
-
- if (!cdrom_get_media_event(cdi, &med)) {
- if (med.media_present)
- return CDS_DISC_OK;
- else if (med.door_open)
- return CDS_TRAY_OPEN;
- else
- return CDS_NO_DISC;
- }
-
- if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
- return CDS_DISC_OK;
-
- /*
- * If not using Mt Fuji extended media tray reports,
- * just return TRAY_OPEN since ATAPI doesn't provide
- * any other way to detect this...
- */
- if (sense.sense_key == NOT_READY) {
- if (sense.asc == 0x3a && sense.ascq == 1)
- return CDS_NO_DISC;
- else
- return CDS_TRAY_OPEN;
- }
- return CDS_DRIVE_NOT_READY;
-}
-
-static
-int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
- struct cdrom_multisession *ms_info)
-{
- struct atapi_toc *toc;
- ide_drive_t *drive = cdi->handle;
- struct cdrom_info *info = drive->driver_data;
- struct request_sense sense;
- int ret;
-
- if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL)
- if ((ret = cdrom_read_toc(drive, &sense)))
- return ret;
-
- toc = info->toc;
- ms_info->addr.lba = toc->last_session_lba;
- ms_info->xa_flag = toc->xa_flag;
-
- return 0;
-}
-
-static
-int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
- struct cdrom_mcn *mcn_info)
-{
- int stat;
- char mcnbuf[24];
- ide_drive_t *drive = cdi->handle;
-
-/* get MCN */
- if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
- return stat;
-
- memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
- sizeof (mcn_info->medium_catalog_number)-1);
- mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1]
- = '\0';
-
- return 0;
-}
-
-
+ struct cdrom_info *cd = drive->driver_data;
+ u16 curspeed, maxspeed;
-/****************************************************************************
- * Other driver requests (open, close, check media change).
- */
+ curspeed = *(u16 *)&buf[8 + 14];
+ maxspeed = *(u16 *)&buf[8 + 8];
-static
-int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
- int slot_nr)
-{
- ide_drive_t *drive = cdi->handle;
- int retval;
-
- if (slot_nr == CDSL_CURRENT) {
- (void) cdrom_check_status(drive, NULL);
- retval = CDROM_STATE_FLAGS(drive)->media_changed;
- CDROM_STATE_FLAGS(drive)->media_changed = 0;
- return retval;
+ if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
+ curspeed = le16_to_cpu(curspeed);
+ maxspeed = le16_to_cpu(maxspeed);
} else {
- return -EINVAL;
+ curspeed = be16_to_cpu(curspeed);
+ maxspeed = be16_to_cpu(maxspeed);
}
-}
-
-
-static
-int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
-{
- return 0;
-}
-
-/*
- * Close down the device. Invalidate all cached blocks.
- */
-static
-void ide_cdrom_release_real (struct cdrom_device_info *cdi)
-{
- ide_drive_t *drive = cdi->handle;
-
- if (!cdi->use_count)
- CDROM_STATE_FLAGS(drive)->toc_valid = 0;
+ cd->current_speed = (curspeed + (176/2)) / 176;
+ cd->max_speed = (maxspeed + (176/2)) / 176;
}
+#define IDE_CD_CAPABILITIES \
+ (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_DRIVE_STATUS | CDC_CD_R | \
+ CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \
+ CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM)
-
-/****************************************************************************
- * Device initialization.
- */
static struct cdrom_device_ops ide_cdrom_dops = {
.open = ide_cdrom_open_real,
.release = ide_cdrom_release_real,
@@ -2892,14 +1673,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
.get_mcn = ide_cdrom_get_mcn,
.reset = ide_cdrom_reset,
.audio_ioctl = ide_cdrom_audio_ioctl,
- .capability = 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_DRIVE_STATUS | CDC_CD_R |
- CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
- CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW |
- CDC_MRW_W | CDC_RAM,
+ .capability = IDE_CD_CAPABILITIES,
.generic_packet = ide_cdrom_packet,
};
@@ -2909,33 +1683,13 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
struct cdrom_device_info *devinfo = &info->devinfo;
devinfo->ops = &ide_cdrom_dops;
- devinfo->mask = 0;
- devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed;
+ devinfo->speed = info->current_speed;
devinfo->capacity = nslots;
devinfo->handle = 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;
- if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
- devinfo->mask |= CDC_MO_DRIVE;
- if (!CDROM_CONFIG_FLAGS(drive)->ram)
- devinfo->mask |= CDC_RAM;
+
+ if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
+ devinfo->mask |= CDC_SELECT_SPEED;
devinfo->disk = info->disk;
return register_cdrom(devinfo);
@@ -2944,22 +1698,25 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
static
int ide_cdrom_probe_capabilities (ide_drive_t *drive)
{
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *cdi = &info->devinfo;
- struct atapi_capabilities_page cap;
+ struct cdrom_info *cd = drive->driver_data;
+ struct cdrom_device_info *cdi = &cd->devinfo;
+ u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
+ mechtype_t mechtype;
int nslots = 1;
+ cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
+ CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
+ CDC_MO_DRIVE | CDC_RAM);
+
if (drive->media == ide_optical) {
- CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
- CDROM_CONFIG_FLAGS(drive)->ram = 1;
+ cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
return nslots;
}
- if (CDROM_CONFIG_FLAGS(drive)->nec260 ||
- !strcmp(drive->id->model,"STINGRAY 8422 IDE 8X CD-ROM 7-27-95")) {
- CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
- CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
+ if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
+ cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ cdi->mask &= ~CDC_PLAY_AUDIO;
return nslots;
}
@@ -2973,88 +1730,66 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
cdi->handle = drive;
cdi->ops = &ide_cdrom_dops;
- if (ide_cdrom_get_capabilities(drive, &cap))
+ if (ide_cdrom_get_capabilities(drive, buf))
return 0;
- if (cap.lock == 0)
- CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
- if (cap.eject)
- CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
- if (cap.cd_r_write)
- CDROM_CONFIG_FLAGS(drive)->cd_r = 1;
- if (cap.cd_rw_write) {
- CDROM_CONFIG_FLAGS(drive)->cd_rw = 1;
- CDROM_CONFIG_FLAGS(drive)->ram = 1;
- }
- if (cap.test_write)
- CDROM_CONFIG_FLAGS(drive)->test_write = 1;
- if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
- CDROM_CONFIG_FLAGS(drive)->dvd = 1;
- if (cap.dvd_ram_write) {
- CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1;
- CDROM_CONFIG_FLAGS(drive)->ram = 1;
- }
- if (cap.dvd_r_write)
- CDROM_CONFIG_FLAGS(drive)->dvd_r = 1;
- if (cap.audio_play)
- CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
- if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup)
- CDROM_CONFIG_FLAGS(drive)->close_tray = 0;
-
- /* Some drives used by Apple don't advertise audio play
- * but they do support reading TOC & audio datas
- */
- if (strcmp(drive->id->model, "MATSHITADVD-ROM SR-8187") == 0 ||
- strcmp(drive->id->model, "MATSHITADVD-ROM SR-8186") == 0 ||
- strcmp(drive->id->model, "MATSHITADVD-ROM SR-8176") == 0 ||
- strcmp(drive->id->model, "MATSHITADVD-ROM SR-8174") == 0)
- CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
+ if ((buf[8 + 6] & 0x01) == 0)
+ cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+ if (buf[8 + 6] & 0x08)
+ cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ if (buf[8 + 3] & 0x01)
+ cdi->mask &= ~CDC_CD_R;
+ if (buf[8 + 3] & 0x02)
+ cdi->mask &= ~(CDC_CD_RW | CDC_RAM);
+ if (buf[8 + 2] & 0x38)
+ cdi->mask &= ~CDC_DVD;
+ if (buf[8 + 3] & 0x20)
+ cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
+ if (buf[8 + 3] & 0x10)
+ cdi->mask &= ~CDC_DVD_R;
+ if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
+ cdi->mask &= ~CDC_PLAY_AUDIO;
+
+ mechtype = buf[8 + 6] >> 5;
+ if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
+ cdi->mask |= CDC_CLOSE_TRAY;
-#if ! STANDARD_ATAPI
if (cdi->sanyo_slot > 0) {
- CDROM_CONFIG_FLAGS(drive)->is_changer = 1;
+ cdi->mask &= ~CDC_SELECT_DISC;
nslots = 3;
+ } else if (mechtype == mechtype_individual_changer ||
+ mechtype == mechtype_cartridge_changer) {
+ nslots = cdrom_number_of_slots(cdi);
+ if (nslots > 1)
+ cdi->mask &= ~CDC_SELECT_DISC;
}
- else
-#endif /* not STANDARD_ATAPI */
- if (cap.mechtype == mechtype_individual_changer ||
- cap.mechtype == mechtype_cartridge_changer) {
- if ((nslots = cdrom_number_of_slots(cdi)) > 1) {
- CDROM_CONFIG_FLAGS(drive)->is_changer = 1;
- CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 1;
- }
- }
+ ide_cdrom_update_speed(drive, buf);
- ide_cdrom_update_speed(drive, &cap);
- /* don't print speed if the drive reported 0.
- */
printk(KERN_INFO "%s: ATAPI", drive->name);
- if (CDROM_CONFIG_FLAGS(drive)->max_speed)
- printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
- printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
- if (CDROM_CONFIG_FLAGS(drive)->dvd_r|CDROM_CONFIG_FLAGS(drive)->dvd_ram)
- printk(" DVD%s%s",
- (CDROM_CONFIG_FLAGS(drive)->dvd_r)? "-R" : "",
- (CDROM_CONFIG_FLAGS(drive)->dvd_ram)? "-RAM" : "");
+ /* don't print speed if the drive reported 0 */
+ if (cd->max_speed)
+ printk(KERN_CONT " %dX", cd->max_speed);
- if (CDROM_CONFIG_FLAGS(drive)->cd_r|CDROM_CONFIG_FLAGS(drive)->cd_rw)
- printk(" CD%s%s",
- (CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "",
- (CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : "");
+ printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM");
- if (CDROM_CONFIG_FLAGS(drive)->is_changer)
- printk(" changer w/%d slots", nslots);
- else
- printk(" drive");
+ if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
+ printk(KERN_CONT " DVD%s%s",
+ (cdi->mask & CDC_DVD_R) ? "" : "-R",
+ (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM");
- printk(", %dkB Cache", be16_to_cpu(cap.buffer_size));
+ if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
+ printk(KERN_CONT " CD%s%s",
+ (cdi->mask & CDC_CD_R) ? "" : "-R",
+ (cdi->mask & CDC_CD_RW) ? "" : "/RW");
- if (drive->using_dma)
- ide_dma_verbose(drive);
+ if ((cdi->mask & CDC_SELECT_DISC) == 0)
+ printk(KERN_CONT " changer w/%d slots", nslots);
+ else
+ printk(KERN_CONT " drive");
- printk("\n");
+ printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
return nslots;
}
@@ -3147,11 +1882,74 @@ static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
return 0;
}
+struct cd_list_entry {
+ const char *id_model;
+ const char *id_firmware;
+ unsigned int cd_flags;
+};
+
+static const struct cd_list_entry ide_cd_quirks_list[] = {
+ /* Limit transfer size per interrupt. */
+ { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
+ { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
+ /* SCR-3231 doesn't support the SET_CD_SPEED command. */
+ { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT },
+ /* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
+ { "NEC CD-ROM DRIVE:260", "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
+ IDE_CD_FLAG_PRE_ATAPI12, },
+ /* Vertos 300, some versions of this drive like to talk BCD. */
+ { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, },
+ /* Vertos 600 ESD. */
+ { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, },
+ /*
+ * Sanyo 3 CD changer uses a non-standard command for CD changing
+ * (by default standard ATAPI support for CD changers is used).
+ */
+ { "CD-ROM CDR-C3 G", NULL, IDE_CD_FLAG_SANYO_3CD },
+ { "CD-ROM CDR-C3G", NULL, IDE_CD_FLAG_SANYO_3CD },
+ { "CD-ROM CDR_C36", NULL, IDE_CD_FLAG_SANYO_3CD },
+ /* Stingray 8X CD-ROM. */
+ { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
+ /*
+ * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
+ * mode sense page capabilities size, but older drives break.
+ */
+ { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
+ { "WPI CDS-32X", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
+ /* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
+ { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS },
+ /*
+ * Some drives used by Apple don't advertise audio play
+ * but they do support reading TOC & audio datas.
+ */
+ { "MATSHITADVD-ROM SR-8187", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8186", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8176", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8174", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
+ { NULL, NULL, 0 }
+};
+
+static unsigned int ide_cd_flags(struct hd_driveid *id)
+{
+ const struct cd_list_entry *cle = ide_cd_quirks_list;
+
+ while (cle->id_model) {
+ if (strcmp(cle->id_model, id->model) == 0 &&
+ (cle->id_firmware == NULL ||
+ strstr(id->fw_rev, cle->id_firmware)))
+ return cle->cd_flags;
+ cle++;
+ }
+
+ return 0;
+}
+
static
int ide_cdrom_setup (ide_drive_t *drive)
{
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *cdi = &info->devinfo;
+ struct cdrom_info *cd = drive->driver_data;
+ struct cdrom_device_info *cdi = &cd->devinfo;
+ struct hd_driveid *id = drive->id;
int nslots;
blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
@@ -3162,101 +1960,21 @@ int ide_cdrom_setup (ide_drive_t *drive)
drive->special.all = 0;
- CDROM_STATE_FLAGS(drive)->media_changed = 1;
- CDROM_STATE_FLAGS(drive)->toc_valid = 0;
- CDROM_STATE_FLAGS(drive)->door_locked = 0;
+ cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
+ ide_cd_flags(id);
-#if NO_DOOR_LOCKING
- CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
-#else
- CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0;
-#endif
+ if ((id->config & 0x0060) == 0x20)
+ cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
- CDROM_CONFIG_FLAGS(drive)->drq_interrupt = ((drive->id->config & 0x0060) == 0x20);
- CDROM_CONFIG_FLAGS(drive)->is_changer = 0;
- CDROM_CONFIG_FLAGS(drive)->cd_r = 0;
- CDROM_CONFIG_FLAGS(drive)->cd_rw = 0;
- 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_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;
- /* a testament to the nice quality of Samsung drives... */
- if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
- CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
- else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
- CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
- /* the 3231 model does not support the SET_CD_SPEED command */
- else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231"))
- cdi->mask |= CDC_SELECT_SPEED;
-
-#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 */
- cdi->sanyo_slot = 0;
-
- CDROM_CONFIG_FLAGS(drive)->nec260 = 0;
- CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 0;
- CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 0;
- CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 0;
- CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 0;
-
- if (strcmp (drive->id->model, "V003S0DS") == 0 &&
- drive->id->fw_rev[4] == '1' &&
- drive->id->fw_rev[6] <= '2') {
- /* Vertos 300.
- Some versions of this drive like to talk BCD. */
- CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
- CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
- CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
- CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
- }
-
- else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
- drive->id->fw_rev[4] == '1' &&
- drive->id->fw_rev[6] <= '2') {
- /* Vertos 600 ESD. */
- CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
- }
- else if (strcmp(drive->id->model, "NEC CD-ROM DRIVE:260") == 0 &&
- strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
- /* Old NEC260 (not R).
- This drive was released before the 1.2 version
- of the spec. */
- CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
- CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
- CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
- CDROM_CONFIG_FLAGS(drive)->nec260 = 1;
- }
- else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 &&
- strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
- /* Wearnes */
- CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
- CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
- }
- /* Sanyo 3 CD changer uses a non-standard command
- for CD changing */
- else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
- (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 */
- cdi->sanyo_slot = 3;
- }
-#endif /* not STANDARD_ATAPI */
-
- info->toc = NULL;
- info->buffer = NULL;
- info->sector_buffered = 0;
- info->nsectors_buffered = 0;
- info->changer_info = NULL;
- info->last_block = 0;
- info->start_seek = 0;
+ if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
+ id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
+ cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
+ IDE_CD_FLAG_TOCADDR_AS_BCD);
+ else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
+ id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
+ cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
+ else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+ cdi->sanyo_slot = 3; /* 3 => use CD in slot 0 */
nslots = ide_cdrom_probe_capabilities (drive);
@@ -3271,7 +1989,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
if (ide_cdrom_register(drive, nslots)) {
printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
- info->devinfo.handle = NULL;
+ cd->devinfo.handle = NULL;
return 1;
}
ide_cdrom_add_settings(drive);
@@ -3311,7 +2029,6 @@ static void ide_cd_release(struct kref *kref)
kfree(info->buffer);
kfree(info->toc);
- kfree(info->changer_info);
if (devinfo->handle == drive && unregister_cdrom(devinfo))
printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
"driver.\n", __FUNCTION__, drive->name);
@@ -3467,7 +2184,9 @@ static int idecd_revalidate_disk(struct gendisk *disk)
{
struct cdrom_info *info = ide_cd_g(disk);
struct request_sense sense;
- cdrom_read_toc(info->drive, &sense);
+
+ ide_cd_read_toc(info->drive, &sense);
+
return 0;
}
@@ -3537,19 +2256,12 @@ static int ide_cd_probe(ide_drive_t *drive)
g->driverfs_dev = &drive->gendev;
g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
if (ide_cdrom_setup(drive)) {
- struct cdrom_device_info *devinfo = &info->devinfo;
ide_proc_unregister_driver(drive, &ide_cdrom_driver);
- kfree(info->buffer);
- kfree(info->toc);
- kfree(info->changer_info);
- if (devinfo->handle == drive && unregister_cdrom(devinfo))
- printk (KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
- kfree(info);
- drive->driver_data = NULL;
+ ide_cd_release(&info->kref);
goto failed;
}
- cdrom_read_toc(drive, &sense);
+ ide_cd_read_toc(drive, &sense);
g->fops = &idecd_ops;
g->flags |= GENHD_FL_REMOVABLE;
add_disk(g);
@@ -3572,6 +2284,7 @@ static int __init ide_cdrom_init(void)
}
MODULE_ALIAS("ide:*m-cdrom*");
+MODULE_ALIAS("ide-cd");
module_init(ide_cdrom_init);
module_exit(ide_cdrom_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 228b29c5d2e..22e3751a681 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/ide_cd.h
- *
* Copyright (C) 1996-98 Erik Andersen
* Copyright (C) 1998-2000 Jens Axboe
*/
@@ -10,31 +8,6 @@
#include <linux/cdrom.h>
#include <asm/byteorder.h>
-/* Turn this on to have the driver print out the meanings of the
- ATAPI error codes. This will use up additional kernel-space
- memory, though. */
-
-#ifndef VERBOSE_IDE_CD_ERRORS
-#define VERBOSE_IDE_CD_ERRORS 1
-#endif
-
-
-/* Turning this on will remove code to work around various nonstandard
- ATAPI implementations. If you know your drive follows the standard,
- this will give you a slightly smaller kernel. */
-
-#ifndef STANDARD_ATAPI
-#define STANDARD_ATAPI 0
-#endif
-
-
-/* Turning this on will disable the door-locking functionality.
- This is apparently needed for supermount. */
-
-#ifndef NO_DOOR_LOCKING
-#define NO_DOOR_LOCKING 0
-#endif
-
/*
* typical timeout for packet command
*/
@@ -49,67 +22,47 @@
#endif
#define SECTORS_PER_FRAME (CD_FRAMESIZE >> SECTOR_BITS)
#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32)
-#define SECTORS_BUFFER (SECTOR_BUFFER_SIZE >> SECTOR_BITS)
-#define SECTORS_MAX (131072 >> SECTOR_BITS)
-
-#define BLOCKS_PER_FRAME (CD_FRAMESIZE / BLOCK_SIZE)
-
-/* special command codes for strategy routine. */
-#define PACKET_COMMAND 4315
-#define REQUEST_SENSE_COMMAND 4316
-#define RESET_DRIVE_COMMAND 4317
-
-
-/* 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-R */
- __u8 dvd_ram : 1; /* Drive can write DVD-RAM */
- __u8 ram : 1; /* generic WRITE (dvd-ram/mrw) */
- __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 writing : 1; /* pseudo write in progress */
- __u8 mo_drive : 1; /* drive is an MO device */
- __u8 reserved : 2;
- byte max_speed; /* Max speed of the drive */
-};
-#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
-
-/* State flags. These give information about the current state of the
- drive, and will change during normal operation. */
-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 writing : 1; /* the drive is currently writing */
- __u8 reserved : 4;
- byte current_speed; /* Current speed of the drive */
+/* Capabilities Page size including 8 bytes of Mode Page Header */
+#define ATAPI_CAPABILITIES_PAGE_SIZE (8 + 20)
+#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE 4
+
+enum {
+ /* Device sends an interrupt when ready for a packet command. */
+ IDE_CD_FLAG_DRQ_INTERRUPT = (1 << 0),
+ /* Drive cannot lock the door. */
+ IDE_CD_FLAG_NO_DOORLOCK = (1 << 1),
+ /* Drive cannot eject the disc. */
+ IDE_CD_FLAG_NO_EJECT = (1 << 2),
+ /* Drive is a pre ATAPI 1.2 drive. */
+ IDE_CD_FLAG_PRE_ATAPI12 = (1 << 3),
+ /* TOC addresses are in BCD. */
+ IDE_CD_FLAG_TOCADDR_AS_BCD = (1 << 4),
+ /* TOC track numbers are in BCD. */
+ IDE_CD_FLAG_TOCTRACKS_AS_BCD = (1 << 5),
+ /*
+ * Drive does not provide data in multiples of SECTOR_SIZE
+ * when more than one interrupt is needed.
+ */
+ IDE_CD_FLAG_LIMIT_NFRAMES = (1 << 6),
+ /* Seeking in progress. */
+ IDE_CD_FLAG_SEEKING = (1 << 7),
+ /* Driver has noticed a media change. */
+ IDE_CD_FLAG_MEDIA_CHANGED = (1 << 8),
+ /* Saved TOC information is current. */
+ IDE_CD_FLAG_TOC_VALID = (1 << 9),
+ /* We think that the drive door is locked. */
+ IDE_CD_FLAG_DOOR_LOCKED = (1 << 10),
+ /* SET_CD_SPEED command is unsupported. */
+ IDE_CD_FLAG_NO_SPEED_SELECT = (1 << 11),
+ IDE_CD_FLAG_VERTOS_300_SSD = (1 << 12),
+ IDE_CD_FLAG_VERTOS_600_ESD = (1 << 13),
+ IDE_CD_FLAG_SANYO_3CD = (1 << 14),
+ IDE_CD_FLAG_FULL_CAPS_PAGE = (1 << 15),
+ IDE_CD_FLAG_PLAY_AUDIO_OK = (1 << 16),
+ IDE_CD_FLAG_LE_SPEED_FIELDS = (1 << 17),
};
-#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
-
/* Structure of a MSF cdrom address. */
struct atapi_msf {
byte reserved;
@@ -154,310 +107,6 @@ struct atapi_toc {
/* One extra for the leadout. */
};
-
-/* This structure is annoyingly close to, but not identical with,
- the cdrom_subchnl structure from cdrom.h. */
-struct atapi_cdrom_subchnl {
- u_char acdsc_reserved;
- u_char acdsc_audiostatus;
- u_short acdsc_length;
- u_char acdsc_format;
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- u_char acdsc_ctrl: 4;
- u_char acdsc_adr: 4;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- u_char acdsc_adr: 4;
- u_char acdsc_ctrl: 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
- u_char acdsc_trk;
- u_char acdsc_ind;
- union {
- struct atapi_msf msf;
- int lba;
- } acdsc_absaddr;
- union {
- struct atapi_msf msf;
- int lba;
- } acdsc_reladdr;
-};
-
-
-
-/* This should probably go into cdrom.h along with the other
- * generic stuff now in the Mt. Fuji spec.
- */
-struct atapi_capabilities_page {
- struct mode_page_header header;
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 parameters_saveable : 1;
- __u8 reserved1 : 1;
- __u8 page_code : 6;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 page_code : 6;
- __u8 reserved1 : 1;
- __u8 parameters_saveable : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
- byte page_length;
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved2 : 2;
- /* Drive supports reading of DVD-RAM discs */
- __u8 dvd_ram_read : 1;
- /* Drive supports reading of DVD-R discs */
- __u8 dvd_r_read : 1;
- /* Drive supports reading of DVD-ROM discs */
- __u8 dvd_rom : 1;
- /* Drive supports reading CD-R discs with addressing method 2 */
- __u8 method2 : 1; /* reserved in 1.2 */
- /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_read : 1; /* reserved in 1.2 */
- /* Drive supports read from CD-R discs (orange book, part II) */
- __u8 cd_r_read : 1; /* reserved in 1.2 */
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- /* Drive supports read from CD-R discs (orange book, part II) */
- __u8 cd_r_read : 1; /* reserved in 1.2 */
- /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_read : 1; /* reserved in 1.2 */
- /* Drive supports reading CD-R discs with addressing method 2 */
- __u8 method2 : 1;
- /* Drive supports reading of DVD-ROM discs */
- __u8 dvd_rom : 1;
- /* Drive supports reading of DVD-R discs */
- __u8 dvd_r_read : 1;
- /* Drive supports reading of DVD-RAM discs */
- __u8 dvd_ram_read : 1;
- __u8 reserved2 : 2;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved3 : 2;
- /* Drive can write DVD-RAM discs */
- __u8 dvd_ram_write : 1;
- /* Drive can write DVD-R discs */
- __u8 dvd_r_write : 1;
- __u8 reserved3a : 1;
- /* Drive can fake writes */
- __u8 test_write : 1;
- /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_write : 1; /* reserved in 1.2 */
- /* Drive supports write to CD-R discs (orange book, part II) */
- __u8 cd_r_write : 1; /* reserved in 1.2 */
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- /* Drive can write to CD-R discs (orange book, part II) */
- __u8 cd_r_write : 1; /* reserved in 1.2 */
- /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_write : 1; /* reserved in 1.2 */
- /* Drive can fake writes */
- __u8 test_write : 1;
- __u8 reserved3a : 1;
- /* Drive can write DVD-R discs */
- __u8 dvd_r_write : 1;
- /* Drive can write DVD-RAM discs */
- __u8 dvd_ram_write : 1;
- __u8 reserved3 : 2;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved4 : 1;
- /* Drive can read multisession discs. */
- __u8 multisession : 1;
- /* Drive can read mode 2, form 2 data. */
- __u8 mode2_form2 : 1;
- /* Drive can read mode 2, form 1 (XA) data. */
- __u8 mode2_form1 : 1;
- /* Drive supports digital output on port 2. */
- __u8 digport2 : 1;
- /* Drive supports digital output on port 1. */
- __u8 digport1 : 1;
- /* Drive can deliver a composite audio/video data stream. */
- __u8 composite : 1;
- /* Drive supports audio play operations. */
- __u8 audio_play : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- /* Drive supports audio play operations. */
- __u8 audio_play : 1;
- /* Drive can deliver a composite audio/video data stream. */
- __u8 composite : 1;
- /* Drive supports digital output on port 1. */
- __u8 digport1 : 1;
- /* Drive supports digital output on port 2. */
- __u8 digport2 : 1;
- /* Drive can read mode 2, form 1 (XA) data. */
- __u8 mode2_form1 : 1;
- /* Drive can read mode 2, form 2 data. */
- __u8 mode2_form2 : 1;
- /* Drive can read multisession discs. */
- __u8 multisession : 1;
- __u8 reserved4 : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved5 : 1;
- /* Drive can return Media Catalog Number (UPC) info. */
- __u8 upc : 1;
- /* Drive can return International Standard Recording Code info. */
- __u8 isrc : 1;
- /* Drive supports C2 error pointers. */
- __u8 c2_pointers : 1;
- /* R-W data will be returned deinterleaved and error corrected. */
- __u8 rw_corr : 1;
- /* Subchannel reads can return combined R-W information. */
- __u8 rw_supported : 1;
- /* Drive can continue a read cdda operation from a loss of streaming.*/
- __u8 cdda_accurate : 1;
- /* Drive can read Red Book audio data. */
- __u8 cdda : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- /* Drive can read Red Book audio data. */
- __u8 cdda : 1;
- /* Drive can continue a read cdda operation from a loss of streaming.*/
- __u8 cdda_accurate : 1;
- /* Subchannel reads can return combined R-W information. */
- __u8 rw_supported : 1;
- /* R-W data will be returned deinterleaved and error corrected. */
- __u8 rw_corr : 1;
- /* Drive supports C2 error pointers. */
- __u8 c2_pointers : 1;
- /* Drive can return International Standard Recording Code info. */
- __u8 isrc : 1;
- /* Drive can return Media Catalog Number (UPC) info. */
- __u8 upc : 1;
- __u8 reserved5 : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- /* Drive mechanism types. */
- mechtype_t mechtype : 3;
- __u8 reserved6 : 1;
- /* Drive can eject a disc or changer cartridge. */
- __u8 eject : 1;
- /* State of prevent/allow jumper. */
- __u8 prevent_jumper : 1;
- /* Present state of door lock. */
- __u8 lock_state : 1;
- /* Drive can lock the door. */
- __u8 lock : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-
- /* Drive can lock the door. */
- __u8 lock : 1;
- /* Present state of door lock. */
- __u8 lock_state : 1;
- /* State of prevent/allow jumper. */
- __u8 prevent_jumper : 1;
- /* Drive can eject a disc or changer cartridge. */
- __u8 eject : 1;
- __u8 reserved6 : 1;
- /* Drive mechanism types. */
- mechtype_t mechtype : 3;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved7 : 4;
- /* Drive supports software slot selection. */
- __u8 sss : 1; /* reserved in 1.2 */
- /* Changer can report exact contents of slots. */
- __u8 disc_present : 1; /* reserved in 1.2 */
- /* Audio for each channel can be muted independently. */
- __u8 separate_mute : 1;
- /* Audio level for each channel can be controlled independently. */
- __u8 separate_volume : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-
- /* Audio level for each channel can be controlled independently. */
- __u8 separate_volume : 1;
- /* Audio for each channel can be muted independently. */
- __u8 separate_mute : 1;
- /* Changer can report exact contents of slots. */
- __u8 disc_present : 1; /* reserved in 1.2 */
- /* Drive supports software slot selection. */
- __u8 sss : 1; /* reserved in 1.2 */
- __u8 reserved7 : 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
- /* Note: the following four fields are returned in big-endian form. */
- /* Maximum speed (in kB/s). */
- unsigned short maxspeed;
- /* Number of discrete volume levels. */
- unsigned short n_vol_levels;
- /* Size of cache in drive, in kB. */
- unsigned short buffer_size;
- /* Current speed (in kB/s). */
- unsigned short curspeed;
- char pad[4];
-};
-
-
-struct atapi_mechstat_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 fault : 1;
- __u8 changer_state : 2;
- __u8 curslot : 5;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 curslot : 5;
- __u8 changer_state : 2;
- __u8 fault : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 mech_state : 3;
- __u8 door_open : 1;
- __u8 reserved1 : 4;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 reserved1 : 4;
- __u8 door_open : 1;
- __u8 mech_state : 3;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
- byte curlba[3];
- byte nslots;
- __u16 slot_tablelen;
-};
-
-
-struct atapi_slot {
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 disc_present : 1;
- __u8 reserved1 : 6;
- __u8 change : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 change : 1;
- __u8 reserved1 : 6;
- __u8 disc_present : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
- byte reserved2[3];
-};
-
-struct atapi_changer_info {
- struct atapi_mechstat_header hdr;
- struct atapi_slot slots[0];
-};
-
/* Extra per-device info for cdrom drives. */
struct cdrom_info {
ide_drive_t *drive;
@@ -482,11 +131,11 @@ struct cdrom_info {
int dma;
unsigned long last_block;
unsigned long start_seek;
- /* Buffer to hold mechanism status and changer slot table. */
- struct atapi_changer_info *changer_info;
- struct ide_cd_config_flags config_flags;
- struct ide_cd_state_flags state_flags;
+ unsigned int cd_flags;
+
+ u8 max_speed; /* Max speed of the drive. */
+ u8 current_speed; /* Current speed of the drive. */
/* Per-device info needed by cdrom.c generic driver. */
struct cdrom_device_info devinfo;
@@ -494,250 +143,30 @@ struct cdrom_info {
unsigned long write_timeout;
};
-/****************************************************************************
- * Descriptions of ATAPI error codes.
- */
-
-/* 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 BLANK_CHECK 0x08
-#define ABORTED_COMMAND 0x0b
-#define MISCOMPARE 0x0e
-
-
-
-/* This stuff should be in cdrom.h, since it is now generic... */
-#if VERBOSE_IDE_CD_ERRORS
-
- /* The generic packet command opcodes for CD/DVD Logical Units,
- * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-static 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. */
-static const char * const sense_key_texts[16] = {
- "No sense data",
- "Recovered error",
- "Not ready",
- "Medium error",
- "Hardware error",
- "Illegal request",
- "Unit attention",
- "Data protect",
- "Blank check",
- "(reserved)",
- "(reserved)",
- "Aborted command",
- "(reserved)",
- "(reserved)",
- "Miscompare",
- "(reserved)",
-};
-
-/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-static const struct {
- unsigned long asc_ascq;
- const char * const text;
-} sense_data_texts[] = {
- { 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" },
- { 0x010c0a, "Write error - padding blocks added" },
- { 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" },
- { 0x017301, "Power calibration area almost full" },
- { 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, "Logical unit not ready - format in progress" },
- { 0x020407, "Logical unit not ready - operation in progress" },
- { 0x020408, "Logical unit not ready - long write in progress" },
- { 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" },
- { 0x030300, "Peripheral device write fault" },
- { 0x030301, "No write current" },
- { 0x030302, "Excessive write errors" },
- { 0x030c00, "Write error" },
- { 0x030c01, "Write error - Recovered with auto reallocation" },
- { 0x030c02, "Write error - auto reallocation failed" },
- { 0x030c03, "Write error - recommend reassignment" },
- { 0x030c04, "Compression check miscompare error" },
- { 0x030c05, "Data expansion occurred during compress" },
- { 0x030c06, "Block not compressible" },
- { 0x030c07, "Write error - recovery needed" },
- { 0x030c08, "Write error - recovery failed" },
- { 0x030c09, "Write error - loss of streaming" },
- { 0x031100, "Unrecovered read error" },
- { 0x031106, "CIRC unrecovered error" },
- { 0x033101, "Format command failed" },
- { 0x033200, "No defect spare location available" },
- { 0x033201, "Defect list update failure" },
- { 0x035100, "Erase failure" },
- { 0x037200, "Session fixation error" },
- { 0x037201, "Session fixation error writin lead-in" },
- { 0x037202, "Session fixation error writin lead-out" },
- { 0x037300, "CD control error" },
- { 0x037302, "Power calibration area is full" },
- { 0x037303, "Power calibration area error" },
- { 0x037304, "Program memory area / RMA update failure" },
- { 0x037305, "Program memory area / RMA is full" },
- { 0x037306, "Program memory area / RMA is (almost) full" },
-
- { 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" },
- { 0x052100, "Logical block address out of range" },
- { 0x052102, "Invalid address for write" },
- { 0x052400, "Invalid field in command packet" },
- { 0x052600, "Invalid field in parameter list" },
- { 0x052601, "Parameter not supported" },
- { 0x052602, "Parameter value invalid" },
- { 0x052700, "Write protected media" },
- { 0x052c00, "Command sequence error" },
- { 0x052c03, "Current program area is not empty" },
- { 0x052c04, "Current program area is empty" },
- { 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" },
- { 0x056f03, "Read of scrambled sector without authentication" },
- { 0x056f04, "Media region code is mismatched to logical unit" },
- { 0x056f05, "Drive region must be permanent / region reset count error" },
- { 0x057203, "Session fixation error - incomplete track in session" },
- { 0x057204, "Empty or partially written reserved track" },
- { 0x057205, "No more RZONE reservations are allowed" },
- { 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
-
+/* ide-cd_verbose.c */
+void ide_cd_log_error(const char *, struct request *, struct request_sense *);
+
+/* ide-cd.c functions used by ide-cd_ioctl.c */
+void ide_cd_init_rq(ide_drive_t *, struct request *);
+int ide_cd_queue_pc(ide_drive_t *, struct request *);
+int ide_cd_read_toc(ide_drive_t *, struct request_sense *);
+int ide_cdrom_get_capabilities(ide_drive_t *, u8 *);
+void ide_cdrom_update_speed(ide_drive_t *, u8 *);
+int cdrom_check_status(ide_drive_t *, struct request_sense *);
+
+/* ide-cd_ioctl.c */
+int ide_cdrom_open_real(struct cdrom_device_info *, int);
+void ide_cdrom_release_real(struct cdrom_device_info *);
+int ide_cdrom_drive_status(struct cdrom_device_info *, int);
+int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int);
+int ide_cdrom_tray_move(struct cdrom_device_info *, int);
+int ide_cdrom_lock_door(struct cdrom_device_info *, int);
+int ide_cdrom_select_speed(struct cdrom_device_info *, int);
+int ide_cdrom_get_last_session(struct cdrom_device_info *,
+ struct cdrom_multisession *);
+int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *);
+int ide_cdrom_reset(struct cdrom_device_info *cdi);
+int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
+int ide_cdrom_packet(struct cdrom_device_info *, struct packet_command *);
#endif /* _IDE_CD_H */
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
new file mode 100644
index 00000000000..b68284de4e8
--- /dev/null
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -0,0 +1,475 @@
+/*
+ * cdrom.c IOCTLs handling for ide-cd driver.
+ *
+ * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov>
+ * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
+ * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
+ */
+
+#include <linux/kernel.h>
+#include <linux/cdrom.h>
+#include <linux/ide.h>
+#include <scsi/scsi.h>
+
+#include "ide-cd.h"
+
+/****************************************************************************
+ * Other driver requests (open, close, check media change).
+ */
+int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose)
+{
+ return 0;
+}
+
+/*
+ * Close down the device. Invalidate all cached blocks.
+ */
+void ide_cdrom_release_real(struct cdrom_device_info *cdi)
+{
+ ide_drive_t *drive = cdi->handle;
+ struct cdrom_info *cd = drive->driver_data;
+
+ if (!cdi->use_count)
+ cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+}
+
+/*
+ * add logic to try GET_EVENT command first to check for media and tray
+ * status. this should be supported by newer cd-r/w and all DVD etc
+ * drives
+ */
+int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+{
+ ide_drive_t *drive = cdi->handle;
+ struct media_event_desc med;
+ struct request_sense sense;
+ int stat;
+
+ if (slot_nr != CDSL_CURRENT)
+ return -EINVAL;
+
+ stat = cdrom_check_status(drive, &sense);
+ if (!stat || sense.sense_key == UNIT_ATTENTION)
+ return CDS_DISC_OK;
+
+ if (!cdrom_get_media_event(cdi, &med)) {
+ if (med.media_present)
+ return CDS_DISC_OK;
+ else if (med.door_open)
+ return CDS_TRAY_OPEN;
+ else
+ return CDS_NO_DISC;
+ }
+
+ if (sense.sense_key == NOT_READY && sense.asc == 0x04
+ && sense.ascq == 0x04)
+ return CDS_DISC_OK;
+
+ /*
+ * If not using Mt Fuji extended media tray reports,
+ * just return TRAY_OPEN since ATAPI doesn't provide
+ * any other way to detect this...
+ */
+ if (sense.sense_key == NOT_READY) {
+ if (sense.asc == 0x3a && sense.ascq == 1)
+ return CDS_NO_DISC;
+ else
+ return CDS_TRAY_OPEN;
+ }
+ return CDS_DRIVE_NOT_READY;
+}
+
+int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
+ int slot_nr)
+{
+ ide_drive_t *drive = cdi->handle;
+ struct cdrom_info *cd = drive->driver_data;
+ int retval;
+
+ if (slot_nr == CDSL_CURRENT) {
+ (void) cdrom_check_status(drive, NULL);
+ retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
+ cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
+ return retval;
+ } else {
+ return -EINVAL;
+ }
+}
+
+/* Eject the disk if EJECTFLAG is 0.
+ If EJECTFLAG is 1, try to reload the disk. */
+static
+int cdrom_eject(ide_drive_t *drive, int ejectflag,
+ struct request_sense *sense)
+{
+ struct cdrom_info *cd = drive->driver_data;
+ struct cdrom_device_info *cdi = &cd->devinfo;
+ struct request req;
+ char loej = 0x02;
+
+ if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
+ return -EDRIVE_CANT_DO_THIS;
+
+ /* reload fails on some drives, if the tray is locked */
+ if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
+ return 0;
+
+ ide_cd_init_rq(drive, &req);
+
+ /* only tell drive to close tray if open, if it can do that */
+ if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY))
+ loej = 0;
+
+ req.sense = sense;
+ req.cmd[0] = GPCMD_START_STOP_UNIT;
+ req.cmd[4] = loej | (ejectflag != 0);
+
+ return ide_cd_queue_pc(drive, &req);
+}
+
+/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
+static
+int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
+ struct request_sense *sense)
+{
+ struct cdrom_info *cd = drive->driver_data;
+ struct request_sense my_sense;
+ struct request req;
+ int stat;
+
+ if (sense == NULL)
+ sense = &my_sense;
+
+ /* If the drive cannot lock the door, just pretend. */
+ if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
+ stat = 0;
+ } else {
+ ide_cd_init_rq(drive, &req);
+ req.sense = sense;
+ req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
+ req.cmd[4] = lockflag ? 1 : 0;
+ stat = ide_cd_queue_pc(drive, &req);
+ }
+
+ /* If we got an illegal field error, the drive
+ probably cannot lock the door. */
+ if (stat != 0 &&
+ sense->sense_key == ILLEGAL_REQUEST &&
+ (sense->asc == 0x24 || sense->asc == 0x20)) {
+ printk(KERN_ERR "%s: door locking not supported\n",
+ drive->name);
+ cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+ stat = 0;
+ }
+
+ /* no medium, that's alright. */
+ if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
+ stat = 0;
+
+ if (stat == 0) {
+ if (lockflag)
+ cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
+ else
+ cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
+ }
+
+ return stat;
+}
+
+int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position)
+{
+ ide_drive_t *drive = cdi->handle;
+ struct request_sense sense;
+
+ if (position) {
+ int stat = ide_cd_lockdoor(drive, 0, &sense);
+
+ if (stat)
+ return stat;
+ }
+
+ return cdrom_eject(drive, !position, &sense);
+}
+
+int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock)
+{
+ ide_drive_t *drive = cdi->handle;
+
+ return ide_cd_lockdoor(drive, lock, NULL);
+}
+
+/*
+ * ATAPI devices are free to select the speed you request or any slower
+ * rate. :-( Requesting too fast a speed will _not_ produce an error.
+ */
+int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
+{
+ ide_drive_t *drive = cdi->handle;
+ struct cdrom_info *cd = drive->driver_data;
+ struct request rq;
+ struct request_sense sense;
+ u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
+ int stat;
+
+ ide_cd_init_rq(drive, &rq);
+
+ rq.sense = &sense;
+
+ if (speed == 0)
+ speed = 0xffff; /* set to max */
+ else
+ speed *= 177; /* Nx to kbytes/s */
+
+ rq.cmd[0] = GPCMD_SET_SPEED;
+ /* Read Drive speed in kbytes/second MSB/LSB */
+ rq.cmd[2] = (speed >> 8) & 0xff;
+ rq.cmd[3] = speed & 0xff;
+ if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) !=
+ (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) {
+ /* Write Drive speed in kbytes/second MSB/LSB */
+ rq.cmd[4] = (speed >> 8) & 0xff;
+ rq.cmd[5] = speed & 0xff;
+ }
+
+ stat = ide_cd_queue_pc(drive, &rq);
+
+ if (!ide_cdrom_get_capabilities(drive, buf)) {
+ ide_cdrom_update_speed(drive, buf);
+ cdi->speed = cd->current_speed;
+ }
+
+ return 0;
+}
+
+int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
+ struct cdrom_multisession *ms_info)
+{
+ struct atapi_toc *toc;
+ ide_drive_t *drive = cdi->handle;
+ struct cdrom_info *info = drive->driver_data;
+ struct request_sense sense;
+ int ret;
+
+ if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
+ ret = ide_cd_read_toc(drive, &sense);
+ if (ret)
+ return ret;
+ }
+
+ toc = info->toc;
+ ms_info->addr.lba = toc->last_session_lba;
+ ms_info->xa_flag = toc->xa_flag;
+
+ return 0;
+}
+
+int ide_cdrom_get_mcn(struct cdrom_device_info *cdi,
+ struct cdrom_mcn *mcn_info)
+{
+ ide_drive_t *drive = cdi->handle;
+ int stat, mcnlen;
+ struct request rq;
+ char buf[24];
+
+ ide_cd_init_rq(drive, &rq);
+
+ rq.data = buf;
+ rq.data_len = sizeof(buf);
+
+ rq.cmd[0] = GPCMD_READ_SUBCHANNEL;
+ rq.cmd[1] = 2; /* MSF addressing */
+ rq.cmd[2] = 0x40; /* request subQ data */
+ rq.cmd[3] = 2; /* format */
+ rq.cmd[8] = sizeof(buf);
+
+ stat = ide_cd_queue_pc(drive, &rq);
+ if (stat)
+ return stat;
+
+ mcnlen = sizeof(mcn_info->medium_catalog_number) - 1;
+ memcpy(mcn_info->medium_catalog_number, buf + 9, mcnlen);
+ mcn_info->medium_catalog_number[mcnlen] = '\0';
+
+ return 0;
+}
+
+int ide_cdrom_reset(struct cdrom_device_info *cdi)
+{
+ ide_drive_t *drive = cdi->handle;
+ struct cdrom_info *cd = drive->driver_data;
+ struct request_sense sense;
+ struct request req;
+ int ret;
+
+ ide_cd_init_rq(drive, &req);
+ req.cmd_type = REQ_TYPE_SPECIAL;
+ req.cmd_flags = REQ_QUIET;
+ ret = ide_do_drive_cmd(drive, &req, ide_wait);
+
+ /*
+ * A reset will unlock the door. If it was previously locked,
+ * lock it again.
+ */
+ if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
+ (void)ide_cd_lockdoor(drive, 1, &sense);
+
+ return ret;
+}
+
+static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
+ struct atapi_toc_entry **ent)
+{
+ struct cdrom_info *info = drive->driver_data;
+ struct atapi_toc *toc = info->toc;
+ int ntracks;
+
+ /*
+ * don't serve cached data, if the toc isn't valid
+ */
+ if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
+ return -EINVAL;
+
+ /* 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 || track > toc->hdr.last_track)
+ return -EINVAL;
+ else
+ *ent = &toc->ent[track - toc->hdr.first_track];
+
+ return 0;
+}
+
+static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
+{
+ struct cdrom_ti *ti = arg;
+ struct atapi_toc_entry *first_toc, *last_toc;
+ unsigned long lba_start, lba_end;
+ int stat;
+ struct request rq;
+ struct request_sense sense;
+
+ stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
+ if (stat)
+ return stat;
+
+ stat = ide_cd_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
+ 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;
+
+ ide_cd_init_rq(drive, &rq);
+
+ rq.sense = &sense;
+ rq.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
+ lba_to_msf(lba_start, &rq.cmd[3], &rq.cmd[4], &rq.cmd[5]);
+ lba_to_msf(lba_end - 1, &rq.cmd[6], &rq.cmd[7], &rq.cmd[8]);
+
+ return ide_cd_queue_pc(drive, &rq);
+}
+
+static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
+{
+ struct cdrom_info *cd = drive->driver_data;
+ struct cdrom_tochdr *tochdr = arg;
+ struct atapi_toc *toc;
+ int stat;
+
+ /* Make sure our saved TOC is valid. */
+ stat = ide_cd_read_toc(drive, NULL);
+ if (stat)
+ return stat;
+
+ toc = cd->toc;
+ tochdr->cdth_trk0 = toc->hdr.first_track;
+ tochdr->cdth_trk1 = toc->hdr.last_track;
+
+ return 0;
+}
+
+static int ide_cd_read_tocentry(ide_drive_t *drive, void *arg)
+{
+ struct cdrom_tocentry *tocentry = arg;
+ struct atapi_toc_entry *toce;
+ int stat;
+
+ stat = ide_cd_get_toc_entry(drive, tocentry->cdte_track, &toce);
+ if (stat)
+ return stat;
+
+ tocentry->cdte_ctrl = toce->control;
+ tocentry->cdte_adr = toce->adr;
+ 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;
+}
+
+int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi,
+ unsigned int cmd, void *arg)
+{
+ ide_drive_t *drive = cdi->handle;
+
+ switch (cmd) {
+ /*
+ * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
+ * atapi doesn't support it
+ */
+ case CDROMPLAYTRKIND:
+ return ide_cd_fake_play_trkind(drive, arg);
+ case CDROMREADTOCHDR:
+ return ide_cd_read_tochdr(drive, arg);
+ case CDROMREADTOCENTRY:
+ return ide_cd_read_tocentry(drive, arg);
+ default:
+ return -EINVAL;
+ }
+}
+
+/* the generic packet interface to cdrom.c */
+int ide_cdrom_packet(struct cdrom_device_info *cdi,
+ struct packet_command *cgc)
+{
+ struct request req;
+ ide_drive_t *drive = cdi->handle;
+
+ if (cgc->timeout <= 0)
+ cgc->timeout = ATAPI_WAIT_PC;
+
+ /* here we queue the commands from the uniform CD-ROM
+ layer. the packet must be complete, as we do not
+ touch it at all. */
+ ide_cd_init_rq(drive, &req);
+ memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
+ if (cgc->sense)
+ memset(cgc->sense, 0, sizeof(struct request_sense));
+ req.data = cgc->buffer;
+ req.data_len = cgc->buflen;
+ req.timeout = cgc->timeout;
+
+ if (cgc->quiet)
+ req.cmd_flags |= REQ_QUIET;
+
+ req.sense = cgc->sense;
+ cgc->stat = ide_cd_queue_pc(drive, &req);
+ if (!cgc->stat)
+ cgc->buflen -= req.data_len;
+ return cgc->stat;
+}
diff --git a/drivers/ide/ide-cd_verbose.c b/drivers/ide/ide-cd_verbose.c
new file mode 100644
index 00000000000..6ed7ca07133
--- /dev/null
+++ b/drivers/ide/ide-cd_verbose.c
@@ -0,0 +1,359 @@
+/*
+ * Verbose error logging for ATAPI CD/DVD devices.
+ *
+ * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov>
+ * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
+ * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
+ */
+
+#include <linux/kernel.h>
+#include <linux/blkdev.h>
+#include <linux/cdrom.h>
+#include <scsi/scsi.h>
+
+#ifndef CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS
+void ide_cd_log_error(const char *name, struct request *failed_command,
+ struct request_sense *sense)
+{
+ /* Suppress printing unit attention and `in progress of becoming ready'
+ errors when we're not being verbose. */
+ if (sense->sense_key == UNIT_ATTENTION ||
+ (sense->sense_key == NOT_READY && (sense->asc == 4 ||
+ sense->asc == 0x3a)))
+ return;
+
+ printk(KERN_ERR "%s: error code: 0x%02x sense_key: 0x%02x "
+ "asc: 0x%02x ascq: 0x%02x\n",
+ name, sense->error_code, sense->sense_key,
+ sense->asc, sense->ascq);
+}
+#else
+/* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+static 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. */
+static const char * const sense_key_texts[16] = {
+ "No sense data",
+ "Recovered error",
+ "Not ready",
+ "Medium error",
+ "Hardware error",
+ "Illegal request",
+ "Unit attention",
+ "Data protect",
+ "Blank check",
+ "(reserved)",
+ "(reserved)",
+ "Aborted command",
+ "(reserved)",
+ "(reserved)",
+ "Miscompare",
+ "(reserved)",
+};
+
+/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+static const struct {
+ unsigned long asc_ascq;
+ const char * const text;
+} sense_data_texts[] = {
+ { 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" },
+ { 0x010c0a, "Write error - padding blocks added" },
+ { 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" },
+ { 0x017301, "Power calibration area almost full" },
+ { 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, "Logical unit not ready - format in progress" },
+ { 0x020407, "Logical unit not ready - operation in progress" },
+ { 0x020408, "Logical unit not ready - long write in progress" },
+ { 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" },
+ { 0x030300, "Peripheral device write fault" },
+ { 0x030301, "No write current" },
+ { 0x030302, "Excessive write errors" },
+ { 0x030c00, "Write error" },
+ { 0x030c01, "Write error - Recovered with auto reallocation" },
+ { 0x030c02, "Write error - auto reallocation failed" },
+ { 0x030c03, "Write error - recommend reassignment" },
+ { 0x030c04, "Compression check miscompare error" },
+ { 0x030c05, "Data expansion occurred during compress" },
+ { 0x030c06, "Block not compressible" },
+ { 0x030c07, "Write error - recovery needed" },
+ { 0x030c08, "Write error - recovery failed" },
+ { 0x030c09, "Write error - loss of streaming" },
+ { 0x031100, "Unrecovered read error" },
+ { 0x031106, "CIRC unrecovered error" },
+ { 0x033101, "Format command failed" },
+ { 0x033200, "No defect spare location available" },
+ { 0x033201, "Defect list update failure" },
+ { 0x035100, "Erase failure" },
+ { 0x037200, "Session fixation error" },
+ { 0x037201, "Session fixation error writin lead-in" },
+ { 0x037202, "Session fixation error writin lead-out" },
+ { 0x037300, "CD control error" },
+ { 0x037302, "Power calibration area is full" },
+ { 0x037303, "Power calibration area error" },
+ { 0x037304, "Program memory area / RMA update failure" },
+ { 0x037305, "Program memory area / RMA is full" },
+ { 0x037306, "Program memory area / RMA is (almost) full" },
+ { 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" },
+ { 0x052100, "Logical block address out of range" },
+ { 0x052102, "Invalid address for write" },
+ { 0x052400, "Invalid field in command packet" },
+ { 0x052600, "Invalid field in parameter list" },
+ { 0x052601, "Parameter not supported" },
+ { 0x052602, "Parameter value invalid" },
+ { 0x052700, "Write protected media" },
+ { 0x052c00, "Command sequence error" },
+ { 0x052c03, "Current program area is not empty" },
+ { 0x052c04, "Current program area is empty" },
+ { 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" },
+ { 0x056f03, "Read of scrambled sector without authentication" },
+ { 0x056f04, "Media region code is mismatched to logical unit" },
+ { 0x056f05, "Drive region must be permanent"
+ " / region reset count error" },
+ { 0x057203, "Session fixation error - incomplete track in session" },
+ { 0x057204, "Empty or partially written reserved track" },
+ { 0x057205, "No more RZONE reservations are allowed" },
+ { 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" },
+};
+
+void ide_cd_log_error(const char *name, struct request *failed_command,
+ struct request_sense *sense)
+{
+ int i;
+ const char *s = "bad sense key!";
+ char buf[80];
+
+ printk(KERN_ERR "ATAPI device %s:\n", name);
+ if (sense->error_code == 0x70)
+ printk(KERN_CONT " Error: ");
+ else if (sense->error_code == 0x71)
+ printk(" Deferred Error: ");
+ else if (sense->error_code == 0x7f)
+ printk(KERN_CONT " Vendor-specific Error: ");
+ else
+ printk(KERN_CONT " Unknown Error Type: ");
+
+ if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
+ s = sense_key_texts[sense->sense_key];
+
+ printk(KERN_CONT "%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
+
+ if (sense->asc == 0x40) {
+ sprintf(buf, "Diagnostic failure on component 0x%02x",
+ sense->ascq);
+ s = buf;
+ } else {
+ int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
+ unsigned long key = (sense->sense_key << 16);
+
+ key |= (sense->asc << 8);
+ if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
+ key |= sense->ascq;
+ s = NULL;
+
+ while (hi > lo) {
+ mid = (lo + hi) / 2;
+ if (sense_data_texts[mid].asc_ascq == key ||
+ sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
+ s = sense_data_texts[mid].text;
+ break;
+ } else if (sense_data_texts[mid].asc_ascq > key)
+ hi = mid;
+ else
+ lo = mid + 1;
+ }
+ }
+
+ if (s == NULL) {
+ if (sense->asc > 0x80)
+ s = "(vendor-specific error)";
+ else
+ s = "(reserved error code)";
+ }
+
+ printk(KERN_ERR " %s -- (asc=0x%02x, ascq=0x%02x)\n",
+ s, sense->asc, sense->ascq);
+
+ if (failed_command != NULL) {
+ int lo = 0, mid, hi = ARRAY_SIZE(packet_command_texts);
+ s = NULL;
+
+ while (hi > lo) {
+ mid = (lo + hi) / 2;
+ if (packet_command_texts[mid].packet_command ==
+ failed_command->cmd[0]) {
+ s = packet_command_texts[mid].text;
+ break;
+ }
+ if (packet_command_texts[mid].packet_command >
+ failed_command->cmd[0])
+ hi = mid;
+ else
+ lo = mid + 1;
+ }
+
+ printk(KERN_ERR " The failed \"%s\" packet command "
+ "was: \n \"", s);
+ for (i = 0; i < sizeof(failed_command->cmd); i++)
+ printk(KERN_CONT "%02x ", failed_command->cmd[i]);
+ printk(KERN_CONT "\"\n");
+ }
+
+ /* The SKSV bit specifies validity of the sense_key_specific
+ * in the next two commands. It is bit 7 of the first byte.
+ * In the case of NOT_READY, if SKSV is set the drive can
+ * give us nice ETA readings.
+ */
+ if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
+ int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
+
+ printk(KERN_ERR " Command is %02d%% complete\n",
+ progress / 0xffff);
+ }
+
+ if (sense->sense_key == ILLEGAL_REQUEST &&
+ (sense->sks[0] & 0x80) != 0) {
+ printk(KERN_ERR " Error in %s byte %d",
+ (sense->sks[0] & 0x40) != 0 ?
+ "command packet" : "command data",
+ (sense->sks[1] << 8) + sense->sks[2]);
+
+ if ((sense->sks[0] & 0x40) != 0)
+ printk(KERN_CONT " bit %d", sense->sks[0] & 0x07);
+
+ printk(KERN_CONT "\n");
+ }
+}
+#endif
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 00123d99527..3c69822507e 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1,10 +1,9 @@
/*
- * linux/drivers/ide/ide-disk.c Version 1.18 Mar 05, 2003
- *
- * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- * Copyright (C) 1998-2002 Linux ATA Development
- * Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2003 Red Hat <alan@redhat.com>
+ * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
+ * Copyright (C) 1998-2002 Linux ATA Development
+ * Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2003 Red Hat <alan@redhat.com>
+ * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
*/
/*
@@ -13,32 +12,6 @@
* and Andre Hedrick <andre@linux-ide.org>
*
* This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
- *
- * Version 1.00 move disk only code from ide.c to ide-disk.c
- * support optional byte-swapping of all data
- * Version 1.01 fix previous byte-swapping code
- * Version 1.02 remove ", LBA" from drive identification msgs
- * Version 1.03 fix display of id->buf_size for big-endian
- * Version 1.04 add /proc configurable settings and S.M.A.R.T support
- * Version 1.05 add capacity support for ATA3 >= 8GB
- * Version 1.06 get boot-up messages to show full cyl count
- * Version 1.07 disable door-locking if it fails
- * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB,
- * process of adding new ATA4 compliance.
- * fixed problems in allowing fdisk to see
- * the entire disk.
- * Version 1.09 added increment of rq->sector in ide_multwrite
- * added UDMA 3/4 reporting
- * Version 1.10 request queue changes, Ultra DMA 100
- * Version 1.11 added 48-bit lba
- * Version 1.12 adding taskfile io access method
- * Version 1.13 added standby and flush-cache for notifier
- * Version 1.14 added acoustic-wcache
- * Version 1.15 convert all calls to ide_raw_taskfile
- * since args will return register content.
- * Version 1.16 added suspend-resume-checkpower
- * Version 1.17 do flush on standby, do flush on ATA < ATA6
- * fix wcache setup.
*/
#define IDEDISK_VERSION "1.18"
@@ -155,6 +128,50 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
return 0; /* lba_capacity value may be bad */
}
+static const u8 ide_rw_cmds[] = {
+ WIN_MULTREAD,
+ WIN_MULTWRITE,
+ WIN_MULTREAD_EXT,
+ WIN_MULTWRITE_EXT,
+ WIN_READ,
+ WIN_WRITE,
+ WIN_READ_EXT,
+ WIN_WRITE_EXT,
+ WIN_READDMA,
+ WIN_WRITEDMA,
+ WIN_READDMA_EXT,
+ WIN_WRITEDMA_EXT,
+};
+
+static const u8 ide_data_phases[] = {
+ TASKFILE_MULTI_IN,
+ TASKFILE_MULTI_OUT,
+ TASKFILE_IN,
+ TASKFILE_OUT,
+ TASKFILE_IN_DMA,
+ TASKFILE_OUT_DMA,
+};
+
+static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
+{
+ u8 index, lba48, write;
+
+ lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
+ write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
+
+ if (dma)
+ index = drive->vdma ? 4 : 8;
+ else
+ index = drive->mult_count ? 0 : 4;
+
+ task->tf.command = ide_rw_cmds[index + lba48 + write];
+
+ if (dma)
+ index = 8; /* fixup index */
+
+ task->data_phase = ide_data_phases[index / 2 + write];
+}
+
/*
* __ide_do_rw_disk() issues READ and WRITE commands to a disk,
* using LBA if supported, or CHS otherwise, to address sectors.
@@ -163,11 +180,11 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
{
ide_hwif_t *hwif = HWIF(drive);
unsigned int dma = drive->using_dma;
+ u16 nsectors = (u16)rq->nr_sectors;
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
- task_ioreg_t command = WIN_NOP;
- ata_nsector_t nsectors;
-
- nsectors.all = (u16) rq->nr_sectors;
+ ide_task_t task;
+ struct ide_taskfile *tf = &task.tf;
+ ide_startstop_t rc;
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
if (block + rq->nr_sectors > 1ULL << 28)
@@ -181,121 +198,71 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
ide_map_sg(drive, rq);
}
- if (IDE_CONTROL_REG)
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
-
- /* FIXME: SELECT_MASK(drive, 0) ? */
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */
+ task.tf_flags |= (IDE_TFLAG_TF | IDE_TFLAG_DEVICE);
if (drive->select.b.lba) {
if (lba48) {
- task_ioreg_t tasklets[10];
-
pr_debug("%s: LBA=0x%012llx\n", drive->name,
(unsigned long long)block);
- tasklets[0] = 0;
- tasklets[1] = 0;
- tasklets[2] = nsectors.b.low;
- tasklets[3] = nsectors.b.high;
- tasklets[4] = (task_ioreg_t) block;
- tasklets[5] = (task_ioreg_t) (block>>8);
- tasklets[6] = (task_ioreg_t) (block>>16);
- tasklets[7] = (task_ioreg_t) (block>>24);
- if (sizeof(block) == 4) {
- tasklets[8] = (task_ioreg_t) 0;
- tasklets[9] = (task_ioreg_t) 0;
- } else {
- tasklets[8] = (task_ioreg_t)((u64)block >> 32);
- tasklets[9] = (task_ioreg_t)((u64)block >> 40);
+ tf->hob_nsect = (nsectors >> 8) & 0xff;
+ tf->hob_lbal = (u8)(block >> 24);
+ if (sizeof(block) != 4) {
+ tf->hob_lbam = (u8)((u64)block >> 32);
+ tf->hob_lbah = (u8)((u64)block >> 40);
}
-#ifdef DEBUG
- printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
- drive->name, tasklets[3], tasklets[2],
- tasklets[9], tasklets[8], tasklets[7],
- tasklets[6], tasklets[5], tasklets[4]);
-#endif
- hwif->OUTB(tasklets[1], IDE_FEATURE_REG);
- hwif->OUTB(tasklets[3], IDE_NSECTOR_REG);
- hwif->OUTB(tasklets[7], IDE_SECTOR_REG);
- hwif->OUTB(tasklets[8], IDE_LCYL_REG);
- hwif->OUTB(tasklets[9], IDE_HCYL_REG);
-
- hwif->OUTB(tasklets[0], IDE_FEATURE_REG);
- hwif->OUTB(tasklets[2], IDE_NSECTOR_REG);
- hwif->OUTB(tasklets[4], IDE_SECTOR_REG);
- hwif->OUTB(tasklets[5], IDE_LCYL_REG);
- hwif->OUTB(tasklets[6], IDE_HCYL_REG);
- hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG);
+
+ tf->nsect = nsectors & 0xff;
+ tf->lbal = (u8) block;
+ tf->lbam = (u8)(block >> 8);
+ tf->lbah = (u8)(block >> 16);
+
+ task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
} else {
- hwif->OUTB(0x00, IDE_FEATURE_REG);
- hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
- hwif->OUTB(block, IDE_SECTOR_REG);
- hwif->OUTB(block>>=8, IDE_LCYL_REG);
- hwif->OUTB(block>>=8, IDE_HCYL_REG);
- hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
+ tf->nsect = nsectors & 0xff;
+ tf->lbal = block;
+ tf->lbam = block >>= 8;
+ tf->lbah = block >>= 8;
+ tf->device = (block >> 8) & 0xf;
}
} else {
unsigned int sect,head,cyl,track;
track = (int)block / drive->sect;
sect = (int)block % drive->sect + 1;
- hwif->OUTB(sect, IDE_SECTOR_REG);
head = track % drive->head;
cyl = track / drive->head;
pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
- hwif->OUTB(0x00, IDE_FEATURE_REG);
- hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
- hwif->OUTB(cyl, IDE_LCYL_REG);
- hwif->OUTB(cyl>>8, IDE_HCYL_REG);
- hwif->OUTB(head|drive->select.all,IDE_SELECT_REG);
+ tf->nsect = nsectors & 0xff;
+ tf->lbal = sect;
+ tf->lbam = cyl;
+ tf->lbah = cyl >> 8;
+ tf->device = head;
}
- if (dma) {
- if (!hwif->dma_setup(drive)) {
- if (rq_data_dir(rq)) {
- command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
- if (drive->vdma)
- command = lba48 ? WIN_WRITE_EXT: WIN_WRITE;
- } else {
- command = lba48 ? WIN_READDMA_EXT : WIN_READDMA;
- if (drive->vdma)
- command = lba48 ? WIN_READ_EXT: WIN_READ;
- }
- hwif->dma_exec_cmd(drive, command);
- hwif->dma_start(drive);
- return ide_started;
- }
- /* fallback to PIO */
- ide_init_sg_cmd(drive, rq);
- }
+ if (rq_data_dir(rq))
+ task.tf_flags |= IDE_TFLAG_WRITE;
- if (rq_data_dir(rq) == READ) {
+ ide_tf_set_cmd(drive, &task, dma);
+ if (!dma)
+ hwif->data_phase = task.data_phase;
+ task.rq = rq;
- if (drive->mult_count) {
- hwif->data_phase = TASKFILE_MULTI_IN;
- command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;
- } else {
- hwif->data_phase = TASKFILE_IN;
- command = lba48 ? WIN_READ_EXT : WIN_READ;
- }
-
- ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL);
- return ide_started;
- } else {
- if (drive->mult_count) {
- hwif->data_phase = TASKFILE_MULTI_OUT;
- command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
- } else {
- hwif->data_phase = TASKFILE_OUT;
- command = lba48 ? WIN_WRITE_EXT : WIN_WRITE;
- }
+ rc = do_rw_taskfile(drive, &task);
- /* FIXME: ->OUTBSYNC ? */
- hwif->OUTB(command, IDE_COMMAND_REG);
-
- return pre_task_out_intr(drive, rq);
+ if (rc == ide_stopped && dma) {
+ /* fallback to PIO */
+ task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
+ ide_tf_set_cmd(drive, &task, 0);
+ hwif->data_phase = task.data_phase;
+ ide_init_sg_cmd(drive, rq);
+ rc = do_rw_taskfile(drive, &task);
}
+
+ return rc;
}
/*
@@ -333,57 +300,29 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
* Queries for true maximum capacity of the drive.
* Returns maximum LBA address (> 0) of the drive, 0 if failed.
*/
-static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
+static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
{
ide_task_t args;
- unsigned long addr = 0;
+ struct ide_taskfile *tf = &args.tf;
+ u64 addr = 0;
/* Create IDE/ATA command request structure */
memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
+ if (lba48)
+ tf->command = WIN_READ_NATIVE_MAX_EXT;
+ else
+ tf->command = WIN_READ_NATIVE_MAX;
+ tf->device = ATA_LBA;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ if (lba48)
+ args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
/* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
+ ide_no_data_taskfile(drive, &args);
/* if OK, compute maximum address value */
- if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
- addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
- | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16)
- | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8)
- | ((args.tfRegister[IDE_SECTOR_OFFSET] ));
- addr++; /* since the return value is (maxlba - 1), we add 1 */
- }
- return addr;
-}
+ if ((tf->status & 0x01) == 0)
+ addr = ide_get_lba_addr(tf, lba48) + 1;
-static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
-{
- ide_task_t args;
- unsigned long long addr = 0;
-
- /* Create IDE/ATA command request structure */
- memset(&args, 0, sizeof(ide_task_t));
-
- args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
-
- /* if OK, compute maximum address value */
- if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
- u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
- (args.hobRegister[IDE_LCYL_OFFSET] << 8) |
- args.hobRegister[IDE_SECTOR_OFFSET];
- u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
- ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
- (args.tfRegister[IDE_SECTOR_OFFSET]);
- addr = ((__u64)high << 24) | low;
- addr++; /* since the return value is (maxlba - 1), we add 1 */
- }
return addr;
}
@@ -391,67 +330,37 @@ static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive
* Sets maximum virtual LBA address of the drive.
* Returns new maximum virtual LBA address (> 0) or 0 on failure.
*/
-static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
+static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
{
ide_task_t args;
- unsigned long addr_set = 0;
-
- addr_req--;
- /* Create IDE/ATA command request structure */
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff);
- args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff);
- args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff);
- args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
- /* if OK, read new maximum address value */
- if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
- addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
- | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16)
- | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8)
- | ((args.tfRegister[IDE_SECTOR_OFFSET] ));
- addr_set++;
- }
- return addr_set;
-}
-
-static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
-{
- ide_task_t args;
- unsigned long long addr_set = 0;
+ struct ide_taskfile *tf = &args.tf;
+ u64 addr_set = 0;
addr_req--;
/* Create IDE/ATA command request structure */
memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff);
- args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff);
- args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff);
- args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT;
- args.hobRegister[IDE_SECTOR_OFFSET] = (addr_req >>= 8) & 0xff;
- args.hobRegister[IDE_LCYL_OFFSET] = (addr_req >>= 8) & 0xff;
- args.hobRegister[IDE_HCYL_OFFSET] = (addr_req >>= 8) & 0xff;
- args.hobRegister[IDE_SELECT_OFFSET] = 0x40;
- args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
+ tf->lbal = (addr_req >> 0) & 0xff;
+ tf->lbam = (addr_req >>= 8) & 0xff;
+ tf->lbah = (addr_req >>= 8) & 0xff;
+ if (lba48) {
+ tf->hob_lbal = (addr_req >>= 8) & 0xff;
+ tf->hob_lbam = (addr_req >>= 8) & 0xff;
+ tf->hob_lbah = (addr_req >>= 8) & 0xff;
+ tf->command = WIN_SET_MAX_EXT;
+ } else {
+ tf->device = (addr_req >>= 8) & 0x0f;
+ tf->command = WIN_SET_MAX;
+ }
+ tf->device |= ATA_LBA;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ if (lba48)
+ args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
/* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
+ ide_no_data_taskfile(drive, &args);
/* if OK, compute maximum address value */
- if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
- u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
- (args.hobRegister[IDE_LCYL_OFFSET] << 8) |
- args.hobRegister[IDE_SECTOR_OFFSET];
- u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
- ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
- (args.tfRegister[IDE_SECTOR_OFFSET]);
- addr_set = ((__u64)high << 24) | low;
- addr_set++;
- }
+ if ((tf->status & 0x01) == 0)
+ addr_set = ide_get_lba_addr(tf, lba48) + 1;
+
return addr_set;
}
@@ -497,10 +406,8 @@ static void idedisk_check_hpa(ide_drive_t *drive)
int lba48 = idedisk_supports_lba48(drive->id);
capacity = drive->capacity64;
- if (lba48)
- set_max = idedisk_read_native_max_address_ext(drive);
- else
- set_max = idedisk_read_native_max_address(drive);
+
+ set_max = idedisk_read_native_max_address(drive, lba48);
if (ide_in_drive_list(drive->id, hpa_list)) {
/*
@@ -521,10 +428,8 @@ static void idedisk_check_hpa(ide_drive_t *drive)
capacity, sectors_to_MB(capacity),
set_max, sectors_to_MB(set_max));
- if (lba48)
- set_max = idedisk_set_max_address_ext(drive, set_max);
- else
- set_max = idedisk_set_max_address(drive, set_max);
+ set_max = idedisk_set_max_address(drive, set_max, lba48);
+
if (set_max) {
drive->capacity64 = set_max;
printk(KERN_INFO "%s: Host Protected Area disabled.\n",
@@ -582,32 +487,32 @@ static sector_t idedisk_capacity (ide_drive_t *drive)
static int smart_enable(ide_drive_t *drive)
{
ide_task_t args;
+ struct ide_taskfile *tf = &args.tf;
memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_FEATURE_OFFSET] = SMART_ENABLE;
- args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
- args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- return ide_raw_taskfile(drive, &args, NULL);
+ tf->feature = SMART_ENABLE;
+ tf->lbam = SMART_LCYL_PASS;
+ tf->lbah = SMART_HCYL_PASS;
+ tf->command = WIN_SMART;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ return ide_no_data_taskfile(drive, &args);
}
static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
{
ide_task_t args;
+ struct ide_taskfile *tf = &args.tf;
memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_FEATURE_OFFSET] = sub_cmd;
- args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
- args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
- args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART;
- args.command_type = IDE_DRIVE_TASK_IN;
- args.data_phase = TASKFILE_IN;
- args.handler = &task_in_intr;
+ tf->feature = sub_cmd;
+ tf->nsect = 0x01;
+ tf->lbam = SMART_LCYL_PASS;
+ tf->lbah = SMART_HCYL_PASS;
+ tf->command = WIN_SMART;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ args.data_phase = TASKFILE_IN;
(void) smart_enable(drive);
- return ide_raw_taskfile(drive, &args, buf);
+ return ide_raw_taskfile(drive, &args, buf, 1);
}
static int proc_idedisk_read_cache
@@ -685,19 +590,20 @@ static ide_proc_entry_t idedisk_proc[] = {
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
+ ide_task_t task;
- memset(rq->cmd, 0, sizeof(rq->cmd));
-
+ memset(&task, 0, sizeof(task));
if (ide_id_has_flush_cache_ext(drive->id) &&
(drive->capacity64 >= (1UL << 28)))
- rq->cmd[0] = WIN_FLUSH_CACHE_EXT;
+ task.tf.command = WIN_FLUSH_CACHE_EXT;
else
- rq->cmd[0] = WIN_FLUSH_CACHE;
+ task.tf.command = WIN_FLUSH_CACHE;
+ task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
+ task.data_phase = TASKFILE_NO_DATA;
-
- rq->cmd_type = REQ_TYPE_ATA_TASK;
+ rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
rq->cmd_flags |= REQ_SOFTBARRIER;
- rq->buffer = rq->cmd;
+ rq->special = &task;
}
/*
@@ -713,8 +619,10 @@ static int set_multcount(ide_drive_t *drive, int arg)
if (drive->special.b.set_multmode)
return -EBUSY;
+
ide_init_drive_cmd (&rq);
- rq.cmd_type = REQ_TYPE_ATA_CMD;
+ rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+
drive->mult_req = arg;
drive->special.b.set_multmode = 1;
(void) ide_do_drive_cmd (drive, &rq, ide_wait);
@@ -779,12 +687,11 @@ static int write_cache(ide_drive_t *drive, int arg)
if (ide_id_has_flush_cache(drive->id)) {
memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ?
+ args.tf.feature = arg ?
SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- err = ide_raw_taskfile(drive, &args, NULL);
+ args.tf.command = WIN_SETFEATURES;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ err = ide_no_data_taskfile(drive, &args);
if (err == 0)
drive->wcache = arg;
}
@@ -800,12 +707,11 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
memset(&args, 0, sizeof(ide_task_t));
if (ide_id_has_flush_cache_ext(drive->id))
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
+ args.tf.command = WIN_FLUSH_CACHE_EXT;
else
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- return ide_raw_taskfile(drive, &args, NULL);
+ args.tf.command = WIN_FLUSH_CACHE;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ return ide_no_data_taskfile(drive, &args);
}
static int set_acoustic (ide_drive_t *drive, int arg)
@@ -816,13 +722,11 @@ static int set_acoustic (ide_drive_t *drive, int arg)
return -EINVAL;
memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM :
- SETFEATURES_DIS_AAM;
- args.tfRegister[IDE_NSECTOR_OFFSET] = arg;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- ide_raw_taskfile(drive, &args, NULL);
+ args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
+ args.tf.nsect = arg;
+ args.tf.command = WIN_SETFEATURES;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ ide_no_data_taskfile(drive, &args);
drive->acoustic = arg;
return 0;
}
@@ -858,7 +762,6 @@ static void idedisk_add_settings(ide_drive_t *drive)
ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing);
- ide_add_setting(drive, "bswap", SETTING_READ, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL);
ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount);
ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr);
ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL);
@@ -961,11 +864,8 @@ static void idedisk_setup (ide_drive_t *drive)
if (id->buf_size)
printk (" w/%dKiB Cache", id->buf_size/2);
- printk(", CHS=%d/%d/%d",
- drive->bios_cyl, drive->bios_head, drive->bios_sect);
- if (drive->using_dma)
- ide_dma_verbose(drive);
- printk("\n");
+ printk(KERN_CONT ", CHS=%d/%d/%d\n",
+ drive->bios_cyl, drive->bios_head, drive->bios_sect);
/* write cache enabled? */
if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5)))
@@ -1070,6 +970,17 @@ static ide_driver_t idedisk_driver = {
#endif
};
+static int idedisk_set_doorlock(ide_drive_t *drive, int on)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+ return ide_no_data_taskfile(drive, &task);
+}
+
static int idedisk_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
@@ -1084,18 +995,13 @@ static int idedisk_open(struct inode *inode, struct file *filp)
idkp->openers++;
if (drive->removable && idkp->openers == 1) {
- ide_task_t args;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
check_disk_change(inode->i_bdev);
/*
* Ignore the return code from door_lock,
* since the open() has already succeeded,
* and the door_lock is irrelevant at this point.
*/
- if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
+ if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
drive->doorlocking = 0;
}
return 0;
@@ -1111,12 +1017,7 @@ static int idedisk_release(struct inode *inode, struct file *filp)
ide_cacheflush_p(drive);
if (drive->removable && idkp->openers == 1) {
- ide_task_t args;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
+ if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
drive->doorlocking = 0;
}
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 428f7a8a00b..3cf59f2c392 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -1,15 +1,13 @@
/*
- * linux/drivers/ide/ide-dma.c Version 4.10 June 9, 2000
+ * Copyright (C) 1995-1998 Mark Lord
+ * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2004, 2007 Bartlomiej Zolnierkiewicz
*
- * Copyright (c) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* May be copied or modified under the terms of the GNU General Public License
*/
/*
* Special Thanks to Mark for his Six years of work.
- *
- * Copyright (c) 1995-1998 Mark Lord
- * May be copied or modified under the terms of the GNU General Public License
*/
/*
@@ -85,6 +83,7 @@
#include <linux/ide.h>
#include <linux/delay.h>
#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -130,6 +129,7 @@ static const struct drive_list_entry drive_blacklist [] = {
{ "_NEC DV5800A", NULL },
{ "SAMSUNG CD-ROM SN-124", "N001" },
{ "Seagate STT20000A", NULL },
+ { "CD-ROM CDR_U200", "1.09" },
{ NULL , NULL }
};
@@ -152,13 +152,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
if (!dma_stat) {
struct request *rq = HWGROUP(drive)->rq;
- if (rq->rq_disk) {
- ide_driver_t *drv;
-
- drv = *(ide_driver_t **)rq->rq_disk->private_data;
- drv->end_request(drive, 1, rq->nr_sectors);
- } else
- ide_end_request(drive, 1, rq->nr_sectors);
+ task_end_request(drive, rq, stat);
return ide_stopped;
}
printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
@@ -174,16 +168,15 @@ static int ide_dma_good_drive(ide_drive_t *drive)
return ide_in_drive_list(drive->id, drive_whitelist);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
/**
* ide_build_sglist - map IDE scatter gather for DMA I/O
* @drive: the drive to build the DMA table for
* @rq: the request holding the sg list
*
- * Perform the PCI mapping magic necessary to access the source or
- * target buffers of a request via PCI DMA. The lower layers of the
+ * Perform the DMA mapping magic necessary to access the source or
+ * target buffers of a request via DMA. The lower layers of the
* kernel provide the necessary cache management so that we can
- * operate in a portable fashion
+ * operate in a portable fashion.
*/
int ide_build_sglist(ide_drive_t *drive, struct request *rq)
@@ -191,20 +184,20 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
ide_hwif_t *hwif = HWIF(drive);
struct scatterlist *sg = hwif->sg_table;
- BUG_ON((rq->cmd_type == REQ_TYPE_ATA_TASKFILE) && rq->nr_sectors > 256);
-
ide_map_sg(drive, rq);
if (rq_data_dir(rq) == READ)
- hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+ hwif->sg_dma_direction = DMA_FROM_DEVICE;
else
- hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+ hwif->sg_dma_direction = DMA_TO_DEVICE;
- return pci_map_sg(hwif->pci_dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
+ return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
+ hwif->sg_dma_direction);
}
EXPORT_SYMBOL_GPL(ide_build_sglist);
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
/**
* ide_build_dmatable - build IDE DMA table
*
@@ -289,16 +282,17 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
*--table |= cpu_to_le32(0x80000000);
return count;
}
+
printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
+
use_pio_instead:
- pci_unmap_sg(hwif->pci_dev,
- hwif->sg_table,
- hwif->sg_nents,
- hwif->sg_dma_direction);
+ ide_destroy_dmatable(drive);
+
return 0; /* revert to PIO for this request */
}
EXPORT_SYMBOL_GPL(ide_build_dmatable);
+#endif
/**
* ide_destroy_dmatable - clean up DMA mapping
@@ -313,15 +307,15 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
void ide_destroy_dmatable (ide_drive_t *drive)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
- struct scatterlist *sg = HWIF(drive)->sg_table;
- int nents = HWIF(drive)->sg_nents;
+ ide_hwif_t *hwif = drive->hwif;
- pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
+ dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
+ hwif->sg_dma_direction);
}
EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
/**
* config_drive_for_dma - attempt to activate IDE DMA
* @drive: the drive to place in DMA mode
@@ -340,7 +334,7 @@ static int config_drive_for_dma (ide_drive_t *drive)
if (drive->media != ide_disk) {
if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
- return -1;
+ return 0;
}
/*
@@ -407,23 +401,29 @@ static int dma_timer_expiry (ide_drive_t *drive)
}
/**
- * ide_dma_host_off - Generic DMA kill
+ * ide_dma_host_set - Enable/disable DMA on a host
* @drive: drive to control
*
- * Perform the generic IDE controller DMA off operation. This
- * works for most IDE bus mastering controllers
+ * Enable/disable DMA on an IDE controller following generic
+ * bus-mastering IDE controller behaviour.
*/
-void ide_dma_host_off(ide_drive_t *drive)
+void ide_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = HWIF(drive);
u8 unit = (drive->select.b.unit & 0x01);
u8 dma_stat = hwif->INB(hwif->dma_status);
- hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status);
+ if (on)
+ dma_stat |= (1 << (5 + unit));
+ else
+ dma_stat &= ~(1 << (5 + unit));
+
+ hwif->OUTB(dma_stat, hwif->dma_status);
}
-EXPORT_SYMBOL(ide_dma_host_off);
+EXPORT_SYMBOL_GPL(ide_dma_host_set);
+#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
/**
* ide_dma_off_quietly - Generic DMA kill
@@ -437,11 +437,10 @@ void ide_dma_off_quietly(ide_drive_t *drive)
drive->using_dma = 0;
ide_toggle_bounce(drive, 0);
- drive->hwif->dma_host_off(drive);
+ drive->hwif->dma_host_set(drive, 0);
}
EXPORT_SYMBOL(ide_dma_off_quietly);
-#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
/**
* ide_dma_off - disable DMA on a device
@@ -454,56 +453,27 @@ EXPORT_SYMBOL(ide_dma_off_quietly);
void ide_dma_off(ide_drive_t *drive)
{
printk(KERN_INFO "%s: DMA disabled\n", drive->name);
- drive->hwif->dma_off_quietly(drive);
+ ide_dma_off_quietly(drive);
}
EXPORT_SYMBOL(ide_dma_off);
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-/**
- * ide_dma_host_on - Enable DMA on a host
- * @drive: drive to enable for DMA
- *
- * Enable DMA on an IDE controller following generic bus mastering
- * IDE controller behaviour
- */
-
-void ide_dma_host_on(ide_drive_t *drive)
-{
- if (drive->using_dma) {
- ide_hwif_t *hwif = HWIF(drive);
- u8 unit = (drive->select.b.unit & 0x01);
- u8 dma_stat = hwif->INB(hwif->dma_status);
-
- hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status);
- }
-}
-
-EXPORT_SYMBOL(ide_dma_host_on);
-
/**
- * __ide_dma_on - Enable DMA on a device
+ * ide_dma_on - Enable DMA on a device
* @drive: drive to enable DMA on
*
* Enable IDE DMA for a device on this IDE controller.
*/
-
-int __ide_dma_on (ide_drive_t *drive)
-{
- /* consult the list of known "bad" drives */
- if (__ide_dma_bad_drive(drive))
- return 1;
+void ide_dma_on(ide_drive_t *drive)
+{
drive->using_dma = 1;
ide_toggle_bounce(drive, 1);
- drive->hwif->dma_host_on(drive);
-
- return 0;
+ drive->hwif->dma_host_set(drive, 1);
}
-EXPORT_SYMBOL(__ide_dma_on);
-
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
/**
* ide_dma_setup - begin a DMA phase
* @drive: target device
@@ -610,12 +580,6 @@ static int __ide_dma_test_irq(ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
u8 dma_stat = hwif->INB(hwif->dma_status);
-#if 0 /* do not set unless you know what you are doing */
- if (dma_stat & 4) {
- u8 stat = hwif->INB(IDE_STATUS_REG);
- hwif->OUTB(hwif->dma_status, dma_stat & 0xE4);
- }
-#endif
/* return 1 if INTR asserted */
if ((dma_stat & 4) == 4)
return 1;
@@ -752,15 +716,19 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
mode = XFER_MW_DMA_1;
}
- printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode);
+ mode = min(mode, req_mode);
+
+ printk(KERN_INFO "%s: %s mode selected\n", drive->name,
+ mode ? ide_xfer_verbose(mode) : "no DMA");
- return min(mode, req_mode);
+ return mode;
}
EXPORT_SYMBOL_GPL(ide_find_dma_mode);
static int ide_tune_dma(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
u8 speed;
if (noautodma || drive->nodma || (drive->id->capability & 1) == 0)
@@ -770,15 +738,24 @@ static int ide_tune_dma(ide_drive_t *drive)
if (__ide_dma_bad_drive(drive))
return 0;
- if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
+ if (ide_id_dma_bug(drive))
+ return 0;
+
+ if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
return config_drive_for_dma(drive);
speed = ide_max_dma_mode(drive);
- if (!speed)
- return 0;
+ if (!speed) {
+ /* is this really correct/needed? */
+ if ((hwif->host_flags & IDE_HFLAG_CY82C693) &&
+ ide_dma_good_drive(drive))
+ return 1;
+ else
+ return 0;
+ }
- if (drive->hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
return 0;
if (ide_set_dma_mode(drive, speed))
@@ -804,79 +781,62 @@ static int ide_dma_check(ide_drive_t *drive)
return vdma ? 0 : -1;
}
-void ide_dma_verbose(ide_drive_t *drive)
+int ide_id_dma_bug(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
+ struct hd_driveid *id = drive->id;
if (id->field_valid & 4) {
if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))
- goto bug_dma_off;
- if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) {
- if (((id->dma_ultra >> 11) & 0x1F) &&
- eighty_ninty_three(drive)) {
- if ((id->dma_ultra >> 15) & 1) {
- printk(", UDMA(mode 7)");
- } else if ((id->dma_ultra >> 14) & 1) {
- printk(", UDMA(133)");
- } else if ((id->dma_ultra >> 13) & 1) {
- printk(", UDMA(100)");
- } else if ((id->dma_ultra >> 12) & 1) {
- printk(", UDMA(66)");
- } else if ((id->dma_ultra >> 11) & 1) {
- printk(", UDMA(44)");
- } else
- goto mode_two;
- } else {
- mode_two:
- if ((id->dma_ultra >> 10) & 1) {
- printk(", UDMA(33)");
- } else if ((id->dma_ultra >> 9) & 1) {
- printk(", UDMA(25)");
- } else if ((id->dma_ultra >> 8) & 1) {
- printk(", UDMA(16)");
- }
- }
- } else {
- printk(", (U)DMA"); /* Can be BIOS-enabled! */
- }
+ goto err_out;
} else if (id->field_valid & 2) {
if ((id->dma_mword >> 8) && (id->dma_1word >> 8))
- goto bug_dma_off;
- printk(", DMA");
- } else if (id->field_valid & 1) {
- goto bug_dma_off;
+ goto err_out;
}
- return;
-bug_dma_off:
- printk(", BUG DMA OFF");
- hwif->dma_off_quietly(drive);
- return;
+ return 0;
+err_out:
+ printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name);
+ return 1;
}
-EXPORT_SYMBOL(ide_dma_verbose);
-
int ide_set_dma(ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
int rc;
+ /*
+ * Force DMAing for the beginning of the check.
+ * Some chipsets appear to do interesting
+ * things, if not checked and cleared.
+ * PARANOIA!!!
+ */
+ ide_dma_off_quietly(drive);
+
rc = ide_dma_check(drive);
+ if (rc)
+ return rc;
- switch(rc) {
- case -1: /* DMA needs to be disabled */
- hwif->dma_off_quietly(drive);
- return -1;
- case 0: /* DMA needs to be enabled */
- return hwif->ide_dma_on(drive);
- case 1: /* DMA setting cannot be changed */
- break;
- default:
- BUG();
- break;
- }
+ ide_dma_on(drive);
+
+ return 0;
+}
+
+void ide_check_dma_crc(ide_drive_t *drive)
+{
+ u8 mode;
- return rc;
+ ide_dma_off_quietly(drive);
+ drive->crc_count = 0;
+ mode = drive->current_speed;
+ /*
+ * Don't try non Ultra-DMA modes without iCRC's. Force the
+ * device to PIO and make the user enable SWDMA/MWDMA modes.
+ */
+ if (mode > XFER_UDMA_0 && mode <= XFER_UDMA_7)
+ mode--;
+ else
+ mode = XFER_PIO_4;
+ ide_set_xfer_rate(drive, mode);
+ if (drive->current_speed >= XFER_SW_DMA_0)
+ ide_dma_on(drive);
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -904,10 +864,10 @@ EXPORT_SYMBOL(ide_dma_timeout);
static void ide_release_dma_engine(ide_hwif_t *hwif)
{
if (hwif->dmatable_cpu) {
- pci_free_consistent(hwif->pci_dev,
- PRD_ENTRIES * PRD_BYTES,
- hwif->dmatable_cpu,
- hwif->dmatable_dma);
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+
+ pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
+ hwif->dmatable_cpu, hwif->dmatable_dma);
hwif->dmatable_cpu = NULL;
}
}
@@ -935,7 +895,9 @@ int ide_release_dma(ide_hwif_t *hwif)
static int ide_allocate_dma_engine(ide_hwif_t *hwif)
{
- hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+
+ hwif->dmatable_cpu = pci_alloc_consistent(pdev,
PRD_ENTRIES * PRD_BYTES,
&hwif->dmatable_dma);
@@ -948,19 +910,19 @@ static int ide_allocate_dma_engine(ide_hwif_t *hwif)
return 1;
}
-static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base)
{
printk(KERN_INFO " %s: MMIO-DMA ", hwif->name);
return 0;
}
-static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base)
{
printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx",
- hwif->name, base, base + ports - 1);
+ hwif->name, base, base + 7);
- if (!request_region(base, ports, hwif->name)) {
+ if (!request_region(base, 8, hwif->name)) {
printk(" -- Error, ports in use.\n");
return 1;
}
@@ -972,7 +934,7 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
if (!request_region(hwif->extra_base,
hwif->cds->extra, hwif->cds->name)) {
printk(" -- Error, extra ports in use.\n");
- release_region(base, ports);
+ release_region(base, 8);
return 1;
}
hwif->extra_ports = hwif->cds->extra;
@@ -982,17 +944,19 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
return 0;
}
-static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base)
{
if (hwif->mmio)
- return ide_mapped_mmio_dma(hwif, base,ports);
+ return ide_mapped_mmio_dma(hwif, base);
- return ide_iomio_dma(hwif, base, ports);
+ return ide_iomio_dma(hwif, base);
}
-void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
+void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
{
- if (ide_dma_iobase(hwif, base, num_ports))
+ u8 dma_stat;
+
+ if (ide_dma_iobase(hwif, base))
return;
if (ide_allocate_dma_engine(hwif)) {
@@ -1002,30 +966,19 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
hwif->dma_base = base;
- if (hwif->mate)
- hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base;
- else
- hwif->dma_master = base;
-
- if (!(hwif->dma_command))
- hwif->dma_command = hwif->dma_base;
- if (!(hwif->dma_vendor1))
- hwif->dma_vendor1 = (hwif->dma_base + 1);
- if (!(hwif->dma_status))
- hwif->dma_status = (hwif->dma_base + 2);
- if (!(hwif->dma_vendor3))
- hwif->dma_vendor3 = (hwif->dma_base + 3);
- if (!(hwif->dma_prdtable))
- hwif->dma_prdtable = (hwif->dma_base + 4);
-
- if (!hwif->dma_off_quietly)
- hwif->dma_off_quietly = &ide_dma_off_quietly;
- if (!hwif->dma_host_off)
- hwif->dma_host_off = &ide_dma_host_off;
- if (!hwif->ide_dma_on)
- hwif->ide_dma_on = &__ide_dma_on;
- if (!hwif->dma_host_on)
- hwif->dma_host_on = &ide_dma_host_on;
+ if (!hwif->dma_command)
+ hwif->dma_command = hwif->dma_base + 0;
+ if (!hwif->dma_vendor1)
+ hwif->dma_vendor1 = hwif->dma_base + 1;
+ if (!hwif->dma_status)
+ hwif->dma_status = hwif->dma_base + 2;
+ if (!hwif->dma_vendor3)
+ hwif->dma_vendor3 = hwif->dma_base + 3;
+ if (!hwif->dma_prdtable)
+ hwif->dma_prdtable = hwif->dma_base + 4;
+
+ if (!hwif->dma_host_set)
+ hwif->dma_host_set = &ide_dma_host_set;
if (!hwif->dma_setup)
hwif->dma_setup = &ide_dma_setup;
if (!hwif->dma_exec_cmd)
@@ -1041,15 +994,10 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
if (!hwif->dma_lost_irq)
hwif->dma_lost_irq = &ide_dma_lost_irq;
- if (hwif->chipset != ide_trm290) {
- u8 dma_stat = hwif->INB(hwif->dma_status);
- printk(", BIOS settings: %s:%s, %s:%s",
- hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
- hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
- }
- printk("\n");
-
- BUG_ON(!hwif->dma_master);
+ dma_stat = hwif->INB(hwif->dma_status);
+ printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n",
+ hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO",
+ hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO");
}
EXPORT_SYMBOL_GPL(ide_setup_dma);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 04a357808f2..f8fe6ee128f 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1,15 +1,9 @@
/*
- * linux/drivers/ide/ide-floppy.c Version 0.99 Feb 24 2002
- *
- * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
- * Copyright (C) 2000 - 2002 Paul Bristow <paul@paulbristow.net>
- */
-
-/*
* IDE ATAPI floppy driver.
*
- * The driver currently doesn't have any fancy features, just the bare
- * minimum read/write support.
+ * Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 2000-2002 Paul Bristow <paul@paulbristow.net>
+ * Copyright (C) 2005 Bartlomiej Zolnierkiewicz
*
* This driver supports the following IDE floppy drives:
*
@@ -17,70 +11,11 @@
* Iomega Zip 100/250
* Iomega PC Card Clik!/PocketZip
*
- * Many thanks to Lode Leroy <Lode.Leroy@www.ibase.be>, who tested so many
- * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive.
- *
- * Ver 0.1 Oct 17 96 Initial test version, mostly based on ide-tape.c.
- * Ver 0.2 Oct 31 96 Minor changes.
- * Ver 0.3 Dec 2 96 Fixed error recovery bug.
- * Ver 0.4 Jan 26 97 Add support for the HDIO_GETGEO ioctl.
- * Ver 0.5 Feb 21 97 Add partitions support.
- * Use the minimum of the LBA and CHS capacities.
- * Avoid hwgroup->rq == NULL on the last irq.
- * Fix potential null dereferencing with DEBUG_LOG.
- * Ver 0.8 Dec 7 97 Increase irq timeout from 10 to 50 seconds.
- * Add media write-protect detection.
- * 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.
- * Ver 0.9.sv Jan 6 01 Sam Varshavchik <mrsam@courier-mta.com>
- * Implement low level formatting. Reimplemented
- * IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp
- * bit. My LS-120 drive barfs on
- * IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me.
- * Compromise by not reporting a failure to get this
- * mode page. Implemented four IOCTLs in order to
- * implement formatting. IOCTls begin with 0x4600,
- * 0x46 is 'F' as in Format.
- * Jan 9 01 Userland option to select format verify.
- * Added PC_SUPPRESS_ERROR flag - some idefloppy drives
- * do not implement IDEFLOPPY_CAPABILITIES_PAGE, and
- * return a sense error. Suppress error reporting in
- * this particular case in order to avoid spurious
- * errors in syslog. The culprit is
- * idefloppy_get_capability_page(), so move it to
- * idefloppy_begin_format() so that it's not used
- * unless absolutely necessary.
- * If drive does not support format progress indication
- * monitor the dsc bit in the status register.
- * Also, O_NDELAY on open will allow the device to be
- * opened without a disk available. This can be used to
- * open an unformatted disk, or get the device capacity.
- * Ver 0.91 Dec 11 99 Added IOMEGA Clik! drive support by
- * <paul@paulbristow.net>
- * Ver 0.92 Oct 22 00 Paul Bristow became official maintainer for this
- * driver. Included Powerbook internal zip kludge.
- * Ver 0.93 Oct 24 00 Fixed bugs for Clik! drive
- * no disk on insert and disk change now works
- * Ver 0.94 Oct 27 00 Tidied up to remove strstr(Clik) everywhere
- * Ver 0.95 Nov 7 00 Brought across to kernel 2.4
- * Ver 0.96 Jan 7 01 Actually in line with release version of 2.4.0
- * including set_bit patch from Rusty Russell
- * Ver 0.97 Jul 22 01 Merge 0.91-0.96 onto 0.9.sv for ac series
- * Ver 0.97.sv Aug 3 01 Backported from 2.4.7-ac3
- * Ver 0.98 Oct 26 01 Split idefloppy_transfer_pc into two pieces to
- * fix a lost interrupt problem. It appears the busy
- * bit was being deasserted by my IOMEGA ATAPI ZIP 100
- * drive before the drive was actually ready.
- * Ver 0.98a Oct 29 01 Expose delay value so we can play.
- * Ver 0.99 Feb 24 02 Remove duplicate code, modify clik! detection code
- * to support new PocketZip drives
+ * For a historical changelog see
+ * Documentation/ide/ChangeLog.ide-floppy.1996-2002
*/
-#define IDEFLOPPY_VERSION "0.99.newide"
+#define IDEFLOPPY_VERSION "1.00"
#include <linux/module.h>
#include <linux/types.h>
@@ -102,179 +37,91 @@
#include <scsi/scsi_ioctl.h>
#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/irq.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
#include <asm/unaligned.h>
-/*
- * The following are used to debug the driver.
- */
+/* define to see debug info */
#define IDEFLOPPY_DEBUG_LOG 0
-#define IDEFLOPPY_DEBUG_INFO 0
-#define IDEFLOPPY_DEBUG_BUGS 1
/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
-#define IDEFLOPPY_DEBUG( fmt, args... )
+#define IDEFLOPPY_DEBUG(fmt, args...)
#if IDEFLOPPY_DEBUG_LOG
-#define debug_log printk
+#define debug_log(fmt, args...) \
+ printk(KERN_INFO "ide-floppy: " fmt, ## args)
#else
-#define debug_log(fmt, args... ) do {} while(0)
+#define debug_log(fmt, args...) do {} while (0)
#endif
-/*
- * Some drives require a longer irq timeout.
- */
+/* Some drives require a longer irq timeout. */
#define IDEFLOPPY_WAIT_CMD (5 * WAIT_CMD)
/*
- * After each failed packet command we issue a request sense command
- * and retry the packet command IDEFLOPPY_MAX_PC_RETRIES times.
+ * After each failed packet command we issue a request sense command and retry
+ * the packet command IDEFLOPPY_MAX_PC_RETRIES times.
*/
#define IDEFLOPPY_MAX_PC_RETRIES 3
/*
- * With each packet command, we allocate a buffer of
- * IDEFLOPPY_PC_BUFFER_SIZE bytes.
+ * With each packet command, we allocate a buffer of IDEFLOPPY_PC_BUFFER_SIZE
+ * bytes.
*/
#define IDEFLOPPY_PC_BUFFER_SIZE 256
/*
- * In various places in the driver, we need to allocate storage
- * for packet commands and requests, which will remain valid while
- * we leave the driver to wait for an interrupt or a timeout event.
+ * In various places in the driver, we need to allocate storage for packet
+ * commands and requests, which will remain valid while we leave the driver to
+ * wait for an interrupt or a timeout event.
*/
#define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES)
-/*
- * Our view of a packet command.
- */
typedef struct idefloppy_packet_command_s {
u8 c[12]; /* Actual packet bytes */
- int retries; /* On each retry, we increment retries */
+ int retries; /* On each retry, we increment
+ retries */
int error; /* Error code */
int request_transfer; /* Bytes to transfer */
int actually_transferred; /* Bytes actually transferred */
int buffer_size; /* Size of our data buffer */
- int b_count; /* Missing/Available data on the current buffer */
+ int b_count; /* Missing/Available data on
+ the current buffer */
struct request *rq; /* The corresponding request */
u8 *buffer; /* Data buffer */
- u8 *current_position; /* Pointer into the above buffer */
- void (*callback) (ide_drive_t *); /* Called when this packet command is completed */
+ u8 *current_position; /* Pointer into above buffer */
+ void (*callback) (ide_drive_t *); /* Called when this packet
+ command is completed */
u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */
- unsigned long flags; /* Status/Action bit flags: long for set_bit */
+ unsigned long flags; /* Status/Action bit flags: long
+ for set_bit */
} idefloppy_pc_t;
-/*
- * Packet command flag bits.
- */
-#define PC_ABORT 0 /* Set when an error is considered normal - We won't retry */
-#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */
-#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */
-#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */
-#define PC_WRITING 5 /* Data direction */
-
-#define PC_SUPPRESS_ERROR 6 /* Suppress error reporting */
-
-/*
- * Removable Block Access Capabilities Page
- */
-typedef struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned page_code :6; /* Page code - Should be 0x1b */
- unsigned reserved1_6 :1; /* Reserved */
- unsigned ps :1; /* Should be 0 */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned ps :1; /* Should be 0 */
- unsigned reserved1_6 :1; /* Reserved */
- unsigned page_code :6; /* Page code - Should be 0x1b */
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- u8 page_length; /* Page Length - Should be 0xa */
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned reserved2 :6;
- unsigned srfp :1; /* Supports reporting progress of format */
- unsigned sflp :1; /* System floppy type device */
- unsigned tlun :3; /* Total logical units supported by the device */
- unsigned reserved3 :3;
- unsigned sml :1; /* Single / Multiple lun supported */
- unsigned ncd :1; /* Non cd optical device */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned sflp :1; /* System floppy type device */
- unsigned srfp :1; /* Supports reporting progress of format */
- unsigned reserved2 :6;
- unsigned ncd :1; /* Non cd optical device */
- unsigned sml :1; /* Single / Multiple lun supported */
- unsigned reserved3 :3;
- unsigned tlun :3; /* Total logical units supported by the device */
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- u8 reserved[8];
-} idefloppy_capabilities_page_t;
-
-/*
- * Flexible disk page.
- */
-typedef struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned page_code :6; /* Page code - Should be 0x5 */
- unsigned reserved1_6 :1; /* Reserved */
- unsigned ps :1; /* The device is capable of saving the page */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned ps :1; /* The device is capable of saving the page */
- unsigned reserved1_6 :1; /* Reserved */
- unsigned page_code :6; /* Page code - Should be 0x5 */
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- u8 page_length; /* Page Length - Should be 0x1e */
- u16 transfer_rate; /* In kilobits per second */
- u8 heads, sectors; /* Number of heads, Number of sectors per track */
- u16 sector_size; /* Byes per sector */
- u16 cyls; /* Number of cylinders */
- u8 reserved10[10];
- u8 motor_delay; /* Motor off delay */
- u8 reserved21[7];
- u16 rpm; /* Rotations per minute */
- u8 reserved30[2];
-} idefloppy_flexible_disk_page_t;
-
-/*
- * Format capacity
- */
-typedef struct {
- u8 reserved[3];
- u8 length; /* Length of the following descriptors in bytes */
-} idefloppy_capacity_header_t;
-
-typedef struct {
- u32 blocks; /* Number of blocks */
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned dc :2; /* Descriptor Code */
- unsigned reserved :6;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned reserved :6;
- unsigned dc :2; /* Descriptor Code */
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- u8 length_msb; /* Block Length (MSB)*/
- u16 length; /* Block Length */
-} idefloppy_capacity_descriptor_t;
+/* Packet command flag bits. */
+enum {
+ /* 1 when we prefer to use DMA if possible */
+ PC_FLAG_DMA_RECOMMENDED = (1 << 0),
+ /* 1 while DMA in progress */
+ PC_FLAG_DMA_IN_PROGRESS = (1 << 1),
+ /* 1 when encountered problem during DMA */
+ PC_FLAG_DMA_ERROR = (1 << 2),
+ /* Data direction */
+ PC_FLAG_WRITING = (1 << 3),
+ /* Suppress error reporting */
+ PC_FLAG_SUPPRESS_ERROR = (1 << 4),
+};
+/* format capacities descriptor codes */
#define CAPACITY_INVALID 0x00
#define CAPACITY_UNFORMATTED 0x01
#define CAPACITY_CURRENT 0x02
#define CAPACITY_NO_CARTRIDGE 0x03
/*
- * Most of our global data which we need to save even as we leave the
- * driver due to an interrupt or a timer event is stored in a variable
- * of type idefloppy_floppy_t, defined below.
+ * Most of our global data which we need to save even as we leave the driver
+ * due to an interrupt or a timer event is stored in a variable of type
+ * idefloppy_floppy_t, defined below.
*/
typedef struct ide_floppy_obj {
ide_drive_t *drive;
@@ -295,23 +142,19 @@ typedef struct ide_floppy_obj {
/* We implement a circular array */
int rq_stack_index;
- /*
- * Last error information
- */
+ /* Last error information */
u8 sense_key, asc, ascq;
/* delay this long before sending packet command */
u8 ticks;
int progress_indication;
- /*
- * Device information
- */
+ /* Device information */
/* Current format */
int blocks, block_size, bs_factor;
- /* Last format capacity */
- idefloppy_capacity_descriptor_t capacity;
+ /* Last format capacity descriptor */
+ u8 cap_desc[8];
/* Copy of the flexible disk page */
- idefloppy_flexible_disk_page_t flexible_disk_page;
+ u8 flexible_disk_page[32];
/* Write protect */
int wp;
/* Supports format progress report */
@@ -322,85 +165,40 @@ typedef struct ide_floppy_obj {
#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
-/*
- * Floppy flag bits values.
- */
-#define IDEFLOPPY_DRQ_INTERRUPT 0 /* DRQ interrupt device */
-#define IDEFLOPPY_MEDIA_CHANGED 1 /* Media may have changed */
-#define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */
-#define IDEFLOPPY_FORMAT_IN_PROGRESS 3 /* Format in progress */
-#define IDEFLOPPY_CLIK_DRIVE 4 /* Avoid commands not supported in Clik drive */
-#define IDEFLOPPY_ZIP_DRIVE 5 /* Requires BH algorithm for packets */
-
-/*
- * ATAPI floppy drive packet commands
- */
-#define IDEFLOPPY_FORMAT_UNIT_CMD 0x04
-#define IDEFLOPPY_INQUIRY_CMD 0x12
-#define IDEFLOPPY_MODE_SELECT_CMD 0x55
-#define IDEFLOPPY_MODE_SENSE_CMD 0x5a
-#define IDEFLOPPY_READ10_CMD 0x28
-#define IDEFLOPPY_READ12_CMD 0xa8
-#define IDEFLOPPY_READ_CAPACITY_CMD 0x23
-#define IDEFLOPPY_REQUEST_SENSE_CMD 0x03
-#define IDEFLOPPY_PREVENT_REMOVAL_CMD 0x1e
-#define IDEFLOPPY_SEEK_CMD 0x2b
-#define IDEFLOPPY_START_STOP_CMD 0x1b
-#define IDEFLOPPY_TEST_UNIT_READY_CMD 0x00
-#define IDEFLOPPY_VERIFY_CMD 0x2f
-#define IDEFLOPPY_WRITE10_CMD 0x2a
-#define IDEFLOPPY_WRITE12_CMD 0xaa
-#define IDEFLOPPY_WRITE_VERIFY_CMD 0x2e
+/* Floppy flag bits values. */
+enum {
+ /* DRQ interrupt device */
+ IDEFLOPPY_FLAG_DRQ_INTERRUPT = (1 << 0),
+ /* Media may have changed */
+ IDEFLOPPY_FLAG_MEDIA_CHANGED = (1 << 1),
+ /* Format in progress */
+ IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS = (1 << 2),
+ /* Avoid commands not supported in Clik drive */
+ IDEFLOPPY_FLAG_CLIK_DRIVE = (1 << 3),
+ /* Requires BH algorithm for packets */
+ IDEFLOPPY_FLAG_ZIP_DRIVE = (1 << 4),
+};
-/*
- * Defines for the mode sense command
- */
+/* Defines for the MODE SENSE command */
#define MODE_SENSE_CURRENT 0x00
#define MODE_SENSE_CHANGEABLE 0x01
-#define MODE_SENSE_DEFAULT 0x02
+#define MODE_SENSE_DEFAULT 0x02
#define MODE_SENSE_SAVED 0x03
-/*
- * IOCTLs used in low-level formatting.
- */
-
+/* IOCTLs used in low-level formatting. */
#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600
#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601
#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602
#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603
-#if 0
-/*
- * Special requests for our block device strategy routine.
- */
-#define IDEFLOPPY_FIRST_RQ 90
-
-/*
- * IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue.
- */
-#define IDEFLOPPY_PC_RQ 90
-
-#define IDEFLOPPY_LAST_RQ 90
-
-/*
- * A macro which can be used to check if a given request command
- * originated in the driver or in the buffer cache layer.
- */
-#define IDEFLOPPY_RQ_CMD(cmd) ((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ))
-
-#endif
-
-/*
- * Error codes which are returned in rq->errors to the higher part
- * of the driver.
- */
+/* Error code returned in rq->errors to the higher part of the driver. */
#define IDEFLOPPY_ERROR_GENERAL 101
/*
- * The following is used to format the general configuration word of
- * the ATAPI IDENTIFY DEVICE command.
+ * The following is used to format the general configuration word of the
+ * ATAPI IDENTIFY DEVICE command.
*/
-struct idefloppy_id_gcw {
+struct idefloppy_id_gcw {
#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned packet_size :2; /* Packet Size */
unsigned reserved234 :3; /* Reserved */
@@ -423,103 +221,12 @@ struct idefloppy_id_gcw {
};
/*
- * INQUIRY packet command - Data Format
- */
-typedef struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned device_type :5; /* Peripheral Device Type */
- unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */
- unsigned reserved1_6t0 :7; /* Reserved */
- unsigned rmb :1; /* Removable Medium Bit */
- unsigned ansi_version :3; /* ANSI Version */
- unsigned ecma_version :3; /* ECMA Version */
- unsigned iso_version :2; /* ISO Version */
- unsigned response_format :4; /* Response Data Format */
- unsigned reserved3_45 :2; /* Reserved */
- unsigned reserved3_6 :1; /* TrmIOP - Reserved */
- unsigned reserved3_7 :1; /* AENC - Reserved */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */
- unsigned device_type :5; /* Peripheral Device Type */
- unsigned rmb :1; /* Removable Medium Bit */
- unsigned reserved1_6t0 :7; /* Reserved */
- unsigned iso_version :2; /* ISO Version */
- unsigned ecma_version :3; /* ECMA Version */
- unsigned ansi_version :3; /* ANSI Version */
- unsigned reserved3_7 :1; /* AENC - Reserved */
- unsigned reserved3_6 :1; /* TrmIOP - Reserved */
- unsigned reserved3_45 :2; /* Reserved */
- unsigned response_format :4; /* Response Data Format */
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- u8 additional_length; /* Additional Length (total_length-4) */
- u8 rsv5, rsv6, rsv7; /* Reserved */
- u8 vendor_id[8]; /* Vendor Identification */
- u8 product_id[16]; /* Product Identification */
- u8 revision_level[4]; /* Revision Level */
- u8 vendor_specific[20]; /* Vendor Specific - Optional */
- u8 reserved56t95[40]; /* Reserved - Optional */
- /* Additional information may be returned */
-} idefloppy_inquiry_result_t;
-
-/*
- * REQUEST SENSE packet command result - Data Format.
- */
-typedef struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned error_code :7; /* Current error (0x70) */
- unsigned valid :1; /* The information field conforms to SFF-8070i */
- u8 reserved1 :8; /* Reserved */
- unsigned sense_key :4; /* Sense Key */
- unsigned reserved2_4 :1; /* Reserved */
- unsigned ili :1; /* Incorrect Length Indicator */
- unsigned reserved2_67 :2;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned valid :1; /* The information field conforms to SFF-8070i */
- unsigned error_code :7; /* Current error (0x70) */
- u8 reserved1 :8; /* Reserved */
- unsigned reserved2_67 :2;
- unsigned ili :1; /* Incorrect Length Indicator */
- unsigned reserved2_4 :1; /* Reserved */
- unsigned sense_key :4; /* Sense Key */
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- u32 information __attribute__ ((packed));
- u8 asl; /* Additional sense length (n-7) */
- u32 command_specific; /* Additional command specific information */
- u8 asc; /* Additional Sense Code */
- u8 ascq; /* Additional Sense Code Qualifier */
- u8 replaceable_unit_code; /* Field Replaceable Unit Code */
- u8 sksv[3];
- u8 pad[2]; /* Padding to 20 bytes */
-} idefloppy_request_sense_result_t;
-
-/*
- * Pages of the SELECT SENSE / MODE SENSE packet commands.
+ * Pages of the SELECT SENSE / MODE SENSE packet commands.
+ * See SFF-8070i spec.
*/
#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b
#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05
-/*
- * Mode Parameter Header for the MODE SENSE packet command
- */
-typedef struct {
- u16 mode_data_length; /* Length of the following data transfer */
- u8 medium_type; /* Medium Type */
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned reserved3 :7;
- unsigned wp :1; /* Write protect */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned wp :1; /* Write protect */
- unsigned reserved3 :7;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- u8 reserved[4];
-} idefloppy_mode_parameter_header_t;
-
static DEFINE_MUTEX(idefloppy_ref_mutex);
#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
@@ -539,39 +246,35 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
return floppy;
}
-static void ide_floppy_release(struct kref *);
+static void idefloppy_cleanup_obj(struct kref *);
static void ide_floppy_put(struct ide_floppy_obj *floppy)
{
mutex_lock(&idefloppy_ref_mutex);
- kref_put(&floppy->kref, ide_floppy_release);
+ kref_put(&floppy->kref, idefloppy_cleanup_obj);
mutex_unlock(&idefloppy_ref_mutex);
}
/*
- * Too bad. The drive wants to send us data which we are not ready to accept.
- * Just throw it away.
+ * Too bad. The drive wants to send us data which we are not ready to accept.
+ * Just throw it away.
*/
-static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount)
+static void idefloppy_discard_data(ide_drive_t *drive, unsigned int bcount)
{
while (bcount--)
(void) HWIF(drive)->INB(IDE_DATA_REG);
}
-#if IDEFLOPPY_DEBUG_BUGS
-static void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount)
+static void idefloppy_write_zeros(ide_drive_t *drive, unsigned int bcount)
{
while (bcount--)
HWIF(drive)->OUTB(0, IDE_DATA_REG);
}
-#endif /* IDEFLOPPY_DEBUG_BUGS */
/*
- * idefloppy_do_end_request is used to finish servicing a request.
- *
- * For read/write requests, we will call ide_end_request to pass to the
- * next buffer.
+ * Used to finish servicing a request. For read/write requests, we will call
+ * ide_end_request to pass to the next buffer.
*/
static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
{
@@ -579,12 +282,12 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
struct request *rq = HWGROUP(drive)->rq;
int error;
- debug_log(KERN_INFO "Reached idefloppy_end_request\n");
+ debug_log("Reached %s\n", __func__);
switch (uptodate) {
- case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
- case 1: error = 0; break;
- default: error = uptodate;
+ case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
+ case 1: error = 0; break;
+ default: error = uptodate;
}
if (error)
floppy->failed_pc = NULL;
@@ -602,39 +305,8 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
return 0;
}
-static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
-{
- struct request *rq = pc->rq;
- struct bio_vec *bvec;
- struct req_iterator iter;
- unsigned long flags;
- char *data;
- int count, done = 0;
-
- rq_for_each_segment(bvec, rq, iter) {
- if (!bcount)
- break;
-
- count = min(bvec->bv_len, bcount);
-
- data = bvec_kmap_irq(bvec, &flags);
- drive->hwif->atapi_input_bytes(drive, data, count);
- bvec_kunmap_irq(data, &flags);
-
- bcount -= count;
- pc->b_count += count;
- done += count;
- }
-
- idefloppy_do_end_request(drive, 1, done >> 9);
-
- if (bcount) {
- printk(KERN_ERR "%s: leftover data in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount);
- idefloppy_discard_data(drive, bcount);
- }
-}
-
-static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
+static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
+ unsigned int bcount, int direction)
{
struct request *rq = pc->rq;
struct req_iterator iter;
@@ -650,7 +322,10 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
count = min(bvec->bv_len, bcount);
data = bvec_kmap_irq(bvec, &flags);
- drive->hwif->atapi_output_bytes(drive, data, count);
+ if (direction)
+ drive->hwif->atapi_output_bytes(drive, data, count);
+ else
+ drive->hwif->atapi_input_bytes(drive, data, count);
bvec_kunmap_irq(data, &flags);
bcount -= count;
@@ -660,15 +335,18 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
idefloppy_do_end_request(drive, 1, done >> 9);
-#if IDEFLOPPY_DEBUG_BUGS
if (bcount) {
- printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
- idefloppy_write_zeros(drive, bcount);
+ printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
+ drive->name, __func__, bcount);
+ if (direction)
+ idefloppy_write_zeros(drive, bcount);
+ else
+ idefloppy_discard_data(drive, bcount);
+
}
-#endif
}
-static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
+static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc)
{
struct request *rq = pc->rq;
struct bio *bio = rq->bio;
@@ -678,11 +356,12 @@ static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
}
/*
- * idefloppy_queue_pc_head generates a new packet command request in front
- * of the request queue, before the current request, so that it will be
- * processed immediately, on the next pass through the driver.
+ * Generate a new packet command request in front of the request queue, before
+ * the current request so that it will be processed immediately, on the next
+ * pass through the driver.
*/
-static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq)
+static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc,
+ struct request *rq)
{
struct ide_floppy_obj *floppy = drive->driver_data;
@@ -693,16 +372,16 @@ static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struc
(void) ide_do_drive_cmd(drive, rq, ide_preempt);
}
-static idefloppy_pc_t *idefloppy_next_pc_storage (ide_drive_t *drive)
+static idefloppy_pc_t *idefloppy_next_pc_storage(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK)
- floppy->pc_stack_index=0;
+ floppy->pc_stack_index = 0;
return (&floppy->pc_stack[floppy->pc_stack_index++]);
}
-static struct request *idefloppy_next_rq_storage (ide_drive_t *drive)
+static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
@@ -711,60 +390,53 @@ static struct request *idefloppy_next_rq_storage (ide_drive_t *drive)
return (&floppy->rq_stack[floppy->rq_stack_index++]);
}
-/*
- * idefloppy_analyze_error is called on each failed packet command retry
- * to analyze the request sense.
- */
-static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_result_t *result)
+static void idefloppy_request_sense_callback(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
+ u8 *buf = floppy->pc->buffer;
- floppy->sense_key = result->sense_key;
- floppy->asc = result->asc;
- floppy->ascq = result->ascq;
- floppy->progress_indication = result->sksv[0] & 0x80 ?
- (u16)get_unaligned((u16 *)(result->sksv+1)):0x10000;
- if (floppy->failed_pc)
- debug_log(KERN_INFO "ide-floppy: pc = %x, sense key = %x, "
- "asc = %x, ascq = %x\n", floppy->failed_pc->c[0],
- result->sense_key, result->asc, result->ascq);
- else
- debug_log(KERN_INFO "ide-floppy: sense key = %x, asc = %x, "
- "ascq = %x\n", result->sense_key,
- result->asc, result->ascq);
-}
-
-static void idefloppy_request_sense_callback (ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ debug_log("Reached %s\n", __func__);
- debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
-
if (!floppy->pc->error) {
- idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer);
+ floppy->sense_key = buf[2] & 0x0F;
+ floppy->asc = buf[12];
+ floppy->ascq = buf[13];
+ floppy->progress_indication = buf[15] & 0x80 ?
+ (u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
+
+ if (floppy->failed_pc)
+ debug_log("pc = %x, sense key = %x, asc = %x,"
+ " ascq = %x\n",
+ floppy->failed_pc->c[0],
+ floppy->sense_key,
+ floppy->asc,
+ floppy->ascq);
+ else
+ debug_log("sense key = %x, asc = %x, ascq = %x\n",
+ floppy->sense_key,
+ floppy->asc,
+ floppy->ascq);
+
+
idefloppy_do_end_request(drive, 1, 0);
} else {
- printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n");
+ printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting"
+ " request!\n");
idefloppy_do_end_request(drive, 0, 0);
}
}
-/*
- * General packet command callback function.
- */
-static void idefloppy_pc_callback (ide_drive_t *drive)
+/* General packet command callback function. */
+static void idefloppy_pc_callback(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
-
- debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
+
+ debug_log("Reached %s\n", __func__);
idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);
}
-/*
- * idefloppy_init_pc initializes a packet command.
- */
-static void idefloppy_init_pc (idefloppy_pc_t *pc)
+static void idefloppy_init_pc(idefloppy_pc_t *pc)
{
memset(pc->c, 0, 12);
pc->retries = 0;
@@ -775,76 +447,75 @@ static void idefloppy_init_pc (idefloppy_pc_t *pc)
pc->callback = &idefloppy_pc_callback;
}
-static void idefloppy_create_request_sense_cmd (idefloppy_pc_t *pc)
+static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc)
{
- idefloppy_init_pc(pc);
- pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD;
+ idefloppy_init_pc(pc);
+ pc->c[0] = GPCMD_REQUEST_SENSE;
pc->c[4] = 255;
pc->request_transfer = 18;
pc->callback = &idefloppy_request_sense_callback;
}
/*
- * idefloppy_retry_pc is called when an error was detected during the
- * last packet command. We queue a request sense packet command in
- * the head of the request list.
+ * Called when an error was detected during the last packet command. We queue a
+ * request sense packet command in the head of the request list.
*/
-static void idefloppy_retry_pc (ide_drive_t *drive)
+static void idefloppy_retry_pc(ide_drive_t *drive)
{
idefloppy_pc_t *pc;
struct request *rq;
- atapi_error_t error;
- error.all = HWIF(drive)->INB(IDE_ERROR_REG);
+ (void)drive->hwif->INB(IDE_ERROR_REG);
pc = idefloppy_next_pc_storage(drive);
rq = idefloppy_next_rq_storage(drive);
idefloppy_create_request_sense_cmd(pc);
idefloppy_queue_pc_head(drive, pc, rq);
}
-/*
- * idefloppy_pc_intr is the usual interrupt handler which will be called
- * during a packet command.
- */
+/* The usual interrupt handler called during a packet command. */
static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
- atapi_status_t status;
- atapi_bcount_t bcount;
- atapi_ireason_t ireason;
+ ide_hwif_t *hwif = drive->hwif;
idefloppy_pc_t *pc = floppy->pc;
struct request *rq = pc->rq;
+ xfer_func_t *xferfunc;
unsigned int temp;
-
- debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",
- __FUNCTION__);
-
- if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
- if (HWIF(drive)->ide_dma_end(drive)) {
- set_bit(PC_DMA_ERROR, &pc->flags);
+ int dma_error = 0;
+ u16 bcount;
+ u8 stat, ireason;
+
+ debug_log("Reached %s interrupt handler\n", __func__);
+
+ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
+ dma_error = hwif->ide_dma_end(drive);
+ if (dma_error) {
+ printk(KERN_ERR "%s: DMA %s error\n", drive->name,
+ rq_data_dir(rq) ? "write" : "read");
+ pc->flags |= PC_FLAG_DMA_ERROR;
} else {
pc->actually_transferred = pc->request_transfer;
idefloppy_update_buffers(drive, pc);
}
- debug_log(KERN_INFO "ide-floppy: DMA finished\n");
+ debug_log("DMA finished\n");
}
/* Clear the interrupt */
- status.all = HWIF(drive)->INB(IDE_STATUS_REG);
+ stat = drive->hwif->INB(IDE_STATUS_REG);
- if (!status.b.drq) { /* No more interrupts */
- debug_log(KERN_INFO "Packet command completed, %d bytes "
- "transferred\n", pc->actually_transferred);
- clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+ /* No more interrupts */
+ if ((stat & DRQ_STAT) == 0) {
+ debug_log("Packet command completed, %d bytes transferred\n",
+ pc->actually_transferred);
+ pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
local_irq_enable_in_hardirq();
- if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {
+ if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
/* Error detected */
- debug_log(KERN_INFO "ide-floppy: %s: I/O error\n",
- drive->name);
+ debug_log("%s: I/O error\n", drive->name);
rq->errors++;
- if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
+ if (pc->c[0] == GPCMD_REQUEST_SENSE) {
printk(KERN_ERR "ide-floppy: I/O error in "
"request sense command\n");
return ide_do_reset(drive);
@@ -862,7 +533,8 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
return ide_stopped;
}
- if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
+ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
+ pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
printk(KERN_ERR "ide-floppy: The floppy wants to issue "
"more interrupts in DMA mode\n");
ide_dma_off(drive);
@@ -870,67 +542,60 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
}
/* Get the number of bytes to transfer */
- bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG);
- bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG);
+ bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
+ hwif->INB(IDE_BCOUNTL_REG);
/* on this interrupt */
- ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
+ ireason = hwif->INB(IDE_IREASON_REG);
- if (ireason.b.cod) {
- printk(KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");
+ if (ireason & CD) {
+ printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
return ide_do_reset(drive);
}
- if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
+ if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
/* Hopefully, we will never get here */
printk(KERN_ERR "ide-floppy: We wanted to %s, ",
- ireason.b.io ? "Write":"Read");
+ (ireason & IO) ? "Write" : "Read");
printk(KERN_ERR "but the floppy wants us to %s !\n",
- ireason.b.io ? "Read":"Write");
+ (ireason & IO) ? "Read" : "Write");
return ide_do_reset(drive);
}
- if (!test_bit(PC_WRITING, &pc->flags)) {
+ if (!(pc->flags & PC_FLAG_WRITING)) {
/* Reading - Check that we have enough space */
- temp = pc->actually_transferred + bcount.all;
+ temp = pc->actually_transferred + bcount;
if (temp > pc->request_transfer) {
if (temp > pc->buffer_size) {
printk(KERN_ERR "ide-floppy: The floppy wants "
"to send us more data than expected "
"- discarding data\n");
- idefloppy_discard_data(drive,bcount.all);
- BUG_ON(HWGROUP(drive)->handler != NULL);
+ idefloppy_discard_data(drive, bcount);
+
ide_set_handler(drive,
&idefloppy_pc_intr,
IDEFLOPPY_WAIT_CMD,
NULL);
return ide_started;
}
- debug_log(KERN_NOTICE "ide-floppy: The floppy wants to "
- "send us more data than expected - "
- "allowing transfer\n");
+ debug_log("The floppy wants to send us more data than"
+ " expected - allowing transfer\n");
}
}
- if (test_bit(PC_WRITING, &pc->flags)) {
- if (pc->buffer != NULL)
- /* Write the current buffer */
- HWIF(drive)->atapi_output_bytes(drive,
- pc->current_position,
- bcount.all);
- else
- idefloppy_output_buffers(drive, pc, bcount.all);
- } else {
- if (pc->buffer != NULL)
- /* Read the current buffer */
- HWIF(drive)->atapi_input_bytes(drive,
- pc->current_position,
- bcount.all);
- else
- idefloppy_input_buffers(drive, pc, bcount.all);
- }
+ if (pc->flags & PC_FLAG_WRITING)
+ xferfunc = hwif->atapi_output_bytes;
+ else
+ xferfunc = hwif->atapi_input_bytes;
+
+ if (pc->buffer)
+ xferfunc(drive, pc->current_position, bcount);
+ else
+ ide_floppy_io_buffers(drive, pc, bcount,
+ !!(pc->flags & PC_FLAG_WRITING));
+
/* Update the current position */
- pc->actually_transferred += bcount.all;
- pc->current_position += bcount.all;
+ pc->actually_transferred += bcount;
+ pc->current_position += bcount;
- BUG_ON(HWGROUP(drive)->handler != NULL);
- ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */
+ /* And set the interrupt handler again */
+ ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
return ide_started;
}
@@ -939,24 +604,24 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
* It fails at high speeds on the Iomega ZIP drive, so there's a slower version
* for that drive below. The algorithm is chosen based on drive type
*/
-static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
+static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
{
ide_startstop_t startstop;
idefloppy_floppy_t *floppy = drive->driver_data;
- atapi_ireason_t ireason;
+ u8 ireason;
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk(KERN_ERR "ide-floppy: Strange, packet command "
"initiated yet DRQ isn't asserted\n");
return startstop;
}
- ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
- if (!ireason.b.cod || ireason.b.io) {
+ ireason = drive->hwif->INB(IDE_IREASON_REG);
+ if ((ireason & CD) == 0 || (ireason & IO)) {
printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
"issuing a packet command\n");
return ide_do_reset(drive);
}
- BUG_ON(HWGROUP(drive)->handler != NULL);
+
/* Set the interrupt routine */
ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
/* Send the actual packet */
@@ -966,18 +631,16 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
/*
- * What we have here is a classic case of a top half / bottom half
- * interrupt service routine. In interrupt mode, the device sends
- * an interrupt to signal it's ready to receive a packet. However,
- * we need to delay about 2-3 ticks before issuing the packet or we
- * gets in trouble.
+ * What we have here is a classic case of a top half / bottom half interrupt
+ * service routine. In interrupt mode, the device sends an interrupt to signal
+ * that it is ready to receive a packet. However, we need to delay about 2-3
+ * ticks before issuing the packet or we gets in trouble.
*
- * So, follow carefully. transfer_pc1 is called as an interrupt (or
- * directly). In either case, when the device says it's ready for a
- * packet, we schedule the packet transfer to occur about 2-3 ticks
- * later in transfer_pc2.
+ * So, follow carefully. transfer_pc1 is called as an interrupt (or directly).
+ * In either case, when the device says it's ready for a packet, we schedule
+ * the packet transfer to occur about 2-3 ticks later in transfer_pc2.
*/
-static int idefloppy_transfer_pc2 (ide_drive_t *drive)
+static int idefloppy_transfer_pc2(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
@@ -987,24 +650,24 @@ static int idefloppy_transfer_pc2 (ide_drive_t *drive)
return IDEFLOPPY_WAIT_CMD;
}
-static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
+static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
ide_startstop_t startstop;
- atapi_ireason_t ireason;
+ u8 ireason;
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk(KERN_ERR "ide-floppy: Strange, packet command "
"initiated yet DRQ isn't asserted\n");
return startstop;
}
- ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
- if (!ireason.b.cod || ireason.b.io) {
+ ireason = drive->hwif->INB(IDE_IREASON_REG);
+ if ((ireason & CD) == 0 || (ireason & IO)) {
printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
"while issuing a packet command\n");
return ide_do_reset(drive);
}
- /*
+ /*
* The following delay solves a problem with ATAPI Zip 100 drives
* where the Busy flag was apparently being deasserted before the
* unit was ready to receive data. This was happening on a
@@ -1012,112 +675,82 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
* 40 and 50msec work well. idefloppy_pc_intr will not be actually
* used until after the packet is moved in about 50 msec.
*/
- BUG_ON(HWGROUP(drive)->handler != NULL);
- ide_set_handler(drive,
- &idefloppy_pc_intr, /* service routine for packet command */
- floppy->ticks, /* wait this long before "failing" */
- &idefloppy_transfer_pc2); /* fail == transfer_pc2 */
+
+ ide_set_handler(drive, &idefloppy_pc_intr, floppy->ticks,
+ &idefloppy_transfer_pc2);
return ide_started;
}
-/**
- * idefloppy_should_report_error()
- *
- * Supresses error messages resulting from Medium not present
- */
-static inline int idefloppy_should_report_error(idefloppy_floppy_t *floppy)
+static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
+ idefloppy_pc_t *pc)
{
+ /* supress error messages resulting from Medium not present */
if (floppy->sense_key == 0x02 &&
floppy->asc == 0x3a &&
floppy->ascq == 0x00)
- return 0;
- return 1;
+ return;
+
+ printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, "
+ "asc = %2x, ascq = %2x\n",
+ floppy->drive->name, pc->c[0], floppy->sense_key,
+ floppy->asc, floppy->ascq);
+
}
-/*
- * Issue a packet command
- */
-static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
+static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ idefloppy_pc_t *pc)
{
idefloppy_floppy_t *floppy = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
- atapi_feature_t feature;
- atapi_bcount_t bcount;
ide_handler_t *pkt_xfer_routine;
-
-#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone
- and have lived on another thread's stack; that stack may have become
- unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */
-#if IDEFLOPPY_DEBUG_BUGS
- if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&
- pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
- printk(KERN_ERR "ide-floppy: possible ide-floppy.c bug - "
- "Two request sense in serial were issued\n");
- }
-#endif /* IDEFLOPPY_DEBUG_BUGS */
-#endif
+ u16 bcount;
+ u8 dma;
if (floppy->failed_pc == NULL &&
- pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)
+ pc->c[0] != GPCMD_REQUEST_SENSE)
floppy->failed_pc = pc;
/* Set the current packet command */
floppy->pc = pc;
- if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES ||
- test_bit(PC_ABORT, &pc->flags)) {
- /*
- * We will "abort" retrying a packet command in case
- * a legitimate error code was received.
- */
- if (!test_bit(PC_ABORT, &pc->flags)) {
- if (!test_bit(PC_SUPPRESS_ERROR, &pc->flags)) {
- if (idefloppy_should_report_error(floppy))
- printk(KERN_ERR "ide-floppy: %s: I/O error, "
- "pc = %2x, key = %2x, "
- "asc = %2x, ascq = %2x\n",
- drive->name, pc->c[0],
- floppy->sense_key,
- floppy->asc, floppy->ascq);
- }
- /* Giving up */
- pc->error = IDEFLOPPY_ERROR_GENERAL;
- }
+ if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
+ if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
+ ide_floppy_report_error(floppy, pc);
+ /* Giving up */
+ pc->error = IDEFLOPPY_ERROR_GENERAL;
+
floppy->failed_pc = NULL;
pc->callback(drive);
return ide_stopped;
}
- debug_log(KERN_INFO "Retry number - %d\n",pc->retries);
+ debug_log("Retry number - %d\n", pc->retries);
pc->retries++;
/* We haven't transferred any data yet */
pc->actually_transferred = 0;
pc->current_position = pc->buffer;
- bcount.all = min(pc->request_transfer, 63 * 1024);
+ bcount = min(pc->request_transfer, 63 * 1024);
- if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags))
+ if (pc->flags & PC_FLAG_DMA_ERROR) {
+ pc->flags &= ~PC_FLAG_DMA_ERROR;
ide_dma_off(drive);
+ }
+ dma = 0;
- feature.all = 0;
-
- if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
- feature.b.dma = !hwif->dma_setup(drive);
+ if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
+ dma = !hwif->dma_setup(drive);
- if (IDE_CONTROL_REG)
- HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
- /* Use PIO/DMA */
- HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG);
- HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
- HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
- HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
+ IDE_TFLAG_OUT_DEVICE, bcount, dma);
- if (feature.b.dma) { /* Begin DMA, if necessary */
- set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+ if (dma) {
+ /* Begin DMA, if necessary */
+ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
hwif->dma_start(drive);
}
/* Can we transfer the packet when we get the interrupt or wait? */
- if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) {
+ if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE) {
/* wait */
pkt_xfer_routine = &idefloppy_transfer_pc1;
} else {
@@ -1125,7 +758,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
pkt_xfer_routine = &idefloppy_transfer_pc;
}
- if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
+ if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) {
/* Issue the packet command */
ide_execute_command(drive, WIN_PACKETCMD,
pkt_xfer_routine,
@@ -1139,38 +772,37 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
}
}
-static void idefloppy_rw_callback (ide_drive_t *drive)
+static void idefloppy_rw_callback(ide_drive_t *drive)
{
- debug_log(KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
+ debug_log("Reached %s\n", __func__);
idefloppy_do_end_request(drive, 1, 0);
return;
}
-static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent)
+static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
{
- debug_log(KERN_INFO "ide-floppy: creating prevent removal command, "
- "prevent = %d\n", prevent);
+ debug_log("creating prevent removal command, prevent = %d\n", prevent);
idefloppy_init_pc(pc);
- pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD;
+ pc->c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
pc->c[4] = prevent;
}
-static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc)
+static void idefloppy_create_read_capacity_cmd(idefloppy_pc_t *pc)
{
idefloppy_init_pc(pc);
- pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD;
+ pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
pc->c[7] = 255;
pc->c[8] = 255;
pc->request_transfer = 255;
}
-static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l,
+static void idefloppy_create_format_unit_cmd(idefloppy_pc_t *pc, int b, int l,
int flags)
{
idefloppy_init_pc(pc);
- pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD;
+ pc->c[0] = GPCMD_FORMAT_UNIT;
pc->c[1] = 0x17;
memset(pc->buffer, 0, 12);
@@ -1181,83 +813,79 @@ static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l,
pc->buffer[1] ^= 0x20; /* ... turn off DCRT bit */
pc->buffer[3] = 8;
- put_unaligned(htonl(b), (unsigned int *)(&pc->buffer[4]));
- put_unaligned(htonl(l), (unsigned int *)(&pc->buffer[8]));
- pc->buffer_size=12;
- set_bit(PC_WRITING, &pc->flags);
+ put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buffer[4]));
+ put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buffer[8]));
+ pc->buffer_size = 12;
+ pc->flags |= PC_FLAG_WRITING;
}
-/*
- * A mode sense command is used to "sense" floppy parameters.
- */
-static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, u8 page_code, u8 type)
+/* A mode sense command is used to "sense" floppy parameters. */
+static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code,
+ u8 type)
{
- u16 length = sizeof(idefloppy_mode_parameter_header_t);
-
+ u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
+
idefloppy_init_pc(pc);
- pc->c[0] = IDEFLOPPY_MODE_SENSE_CMD;
+ pc->c[0] = GPCMD_MODE_SENSE_10;
pc->c[1] = 0;
pc->c[2] = page_code + (type << 6);
switch (page_code) {
- case IDEFLOPPY_CAPABILITIES_PAGE:
- length += 12;
- break;
- case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
- length += 32;
- break;
- default:
- printk(KERN_ERR "ide-floppy: unsupported page code "
+ case IDEFLOPPY_CAPABILITIES_PAGE:
+ length += 12;
+ break;
+ case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
+ length += 32;
+ break;
+ default:
+ printk(KERN_ERR "ide-floppy: unsupported page code "
"in create_mode_sense_cmd\n");
}
- put_unaligned(htons(length), (u16 *) &pc->c[7]);
+ put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
pc->request_transfer = length;
}
-static void idefloppy_create_start_stop_cmd (idefloppy_pc_t *pc, int start)
+static void idefloppy_create_start_stop_cmd(idefloppy_pc_t *pc, int start)
{
idefloppy_init_pc(pc);
- pc->c[0] = IDEFLOPPY_START_STOP_CMD;
+ pc->c[0] = GPCMD_START_STOP_UNIT;
pc->c[4] = start;
}
static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc)
{
idefloppy_init_pc(pc);
- pc->c[0] = IDEFLOPPY_TEST_UNIT_READY_CMD;
+ pc->c[0] = GPCMD_TEST_UNIT_READY;
}
-static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq, unsigned long sector)
+static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
+ idefloppy_pc_t *pc, struct request *rq,
+ unsigned long sector)
{
int block = sector / floppy->bs_factor;
int blocks = rq->nr_sectors / floppy->bs_factor;
int cmd = rq_data_dir(rq);
- debug_log("create_rw1%d_cmd: block == %d, blocks == %d\n",
- 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags),
+ debug_log("create_rw10_cmd: block == %d, blocks == %d\n",
block, blocks);
idefloppy_init_pc(pc);
- if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) {
- pc->c[0] = cmd == READ ? IDEFLOPPY_READ12_CMD : IDEFLOPPY_WRITE12_CMD;
- put_unaligned(htonl(blocks), (unsigned int *) &pc->c[6]);
- } else {
- pc->c[0] = cmd == READ ? IDEFLOPPY_READ10_CMD : IDEFLOPPY_WRITE10_CMD;
- put_unaligned(htons(blocks), (unsigned short *) &pc->c[7]);
- }
- put_unaligned(htonl(block), (unsigned int *) &pc->c[2]);
+ pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
+ put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
+ put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
+
pc->callback = &idefloppy_rw_callback;
pc->rq = rq;
pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
if (rq->cmd_flags & REQ_RW)
- set_bit(PC_WRITING, &pc->flags);
+ pc->flags |= PC_FLAG_WRITING;
pc->buffer = NULL;
pc->request_transfer = pc->buffer_size = blocks * floppy->block_size;
- set_bit(PC_DMA_RECOMMENDED, &pc->flags);
+ pc->flags |= PC_FLAG_DMA_RECOMMENDED;
}
-static void
-idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
+static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
+ idefloppy_pc_t *pc, struct request *rq)
{
idefloppy_init_pc(pc);
pc->callback = &idefloppy_rw_callback;
@@ -1265,11 +893,10 @@ idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct req
pc->rq = rq;
pc->b_count = rq->data_len;
if (rq->data_len && rq_data_dir(rq) == WRITE)
- set_bit(PC_WRITING, &pc->flags);
+ pc->flags |= PC_FLAG_WRITING;
pc->buffer = rq->data;
if (rq->bio)
- set_bit(PC_DMA_RECOMMENDED, &pc->flags);
-
+ pc->flags |= PC_FLAG_DMA_RECOMMENDED;
/*
* possibly problematic, doesn't look like ide-floppy correctly
* handled scattered requests if dma fails...
@@ -1277,30 +904,23 @@ idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct req
pc->request_transfer = pc->buffer_size = rq->data_len;
}
-/*
- * idefloppy_do_request is our request handling function.
- */
-static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, sector_t block_s)
+static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+ struct request *rq, sector_t block_s)
{
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t *pc;
unsigned long block = (unsigned long)block_s;
- debug_log(KERN_INFO "dev: %s, flags: %lx, errors: %d\n",
+ debug_log("dev: %s, cmd_type: %x, errors: %d\n",
rq->rq_disk ? rq->rq_disk->disk_name : "?",
- rq->flags, rq->errors);
- debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
+ rq->cmd_type, rq->errors);
+ debug_log("sector: %ld, nr_sectors: %ld, "
"current_nr_sectors: %d\n", (long)rq->sector,
rq->nr_sectors, rq->current_nr_sectors);
if (rq->errors >= ERROR_MAX) {
- if (floppy->failed_pc != NULL) {
- if (idefloppy_should_report_error(floppy))
- printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x,"
- " key = %2x, asc = %2x, ascq = %2x\n",
- drive->name, floppy->failed_pc->c[0],
- floppy->sense_key, floppy->asc, floppy->ascq);
- }
+ if (floppy->failed_pc)
+ ide_floppy_report_error(floppy, floppy->failed_pc);
else
printk(KERN_ERR "ide-floppy: %s: I/O error\n",
drive->name);
@@ -1310,8 +930,8 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
if (blk_fs_request(rq)) {
if (((long)rq->sector % floppy->bs_factor) ||
(rq->nr_sectors % floppy->bs_factor)) {
- printk("%s: unsupported r/w request size\n",
- drive->name);
+ printk(KERN_ERR "%s: unsupported r/w request size\n",
+ drive->name);
idefloppy_do_end_request(drive, 0, 0);
return ide_stopped;
}
@@ -1334,15 +954,15 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
}
/*
- * idefloppy_queue_pc_tail adds a special packet command request to the
- * tail of the request queue, and waits for it to be serviced.
+ * Add a special packet command request to the tail of the request queue,
+ * and wait for it to be serviced.
*/
-static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc)
+static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc)
{
struct ide_floppy_obj *floppy = drive->driver_data;
struct request rq;
- ide_init_drive_cmd (&rq);
+ ide_init_drive_cmd(&rq);
rq.buffer = (char *) pc;
rq.cmd_type = REQ_TYPE_SPECIAL;
rq.rq_disk = floppy->disk;
@@ -1351,88 +971,90 @@ static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc)
}
/*
- * Look at the flexible disk page parameters. We will ignore the CHS
- * capacity parameters and use the LBA parameters instead.
+ * Look at the flexible disk page parameters. We ignore the CHS capacity
+ * parameters and use the LBA parameters instead.
*/
-static int idefloppy_get_flexible_disk_page (ide_drive_t *drive)
+static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t pc;
- idefloppy_mode_parameter_header_t *header;
- idefloppy_flexible_disk_page_t *page;
+ u8 *page;
int capacity, lba_capacity;
+ u16 transfer_rate, sector_size, cyls, rpm;
+ u8 heads, sectors;
+
+ idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE,
+ MODE_SENSE_CURRENT);
- idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT);
- if (idefloppy_queue_pc_tail(drive,&pc)) {
- printk(KERN_ERR "ide-floppy: Can't get flexible disk "
- "page parameters\n");
+ if (idefloppy_queue_pc_tail(drive, &pc)) {
+ printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
+ " parameters\n");
return 1;
}
- header = (idefloppy_mode_parameter_header_t *) pc.buffer;
- floppy->wp = header->wp;
+ floppy->wp = !!(pc.buffer[3] & 0x80);
set_disk_ro(floppy->disk, floppy->wp);
- page = (idefloppy_flexible_disk_page_t *) (header + 1);
-
- page->transfer_rate = ntohs(page->transfer_rate);
- page->sector_size = ntohs(page->sector_size);
- page->cyls = ntohs(page->cyls);
- page->rpm = ntohs(page->rpm);
- capacity = page->cyls * page->heads * page->sectors * page->sector_size;
- if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t)))
+ page = &pc.buffer[8];
+
+ transfer_rate = be16_to_cpu(*(u16 *)&pc.buffer[8 + 2]);
+ sector_size = be16_to_cpu(*(u16 *)&pc.buffer[8 + 6]);
+ cyls = be16_to_cpu(*(u16 *)&pc.buffer[8 + 8]);
+ rpm = be16_to_cpu(*(u16 *)&pc.buffer[8 + 28]);
+ heads = pc.buffer[8 + 4];
+ sectors = pc.buffer[8 + 5];
+
+ capacity = cyls * heads * sectors * sector_size;
+
+ if (memcmp(page, &floppy->flexible_disk_page, 32))
printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, "
"%d sector size, %d rpm\n",
- drive->name, capacity / 1024, page->cyls,
- page->heads, page->sectors,
- page->transfer_rate / 8, page->sector_size, page->rpm);
-
- floppy->flexible_disk_page = *page;
- drive->bios_cyl = page->cyls;
- drive->bios_head = page->heads;
- drive->bios_sect = page->sectors;
+ drive->name, capacity / 1024, cyls, heads,
+ sectors, transfer_rate / 8, sector_size, rpm);
+
+ memcpy(&floppy->flexible_disk_page, page, 32);
+ drive->bios_cyl = cyls;
+ drive->bios_head = heads;
+ drive->bios_sect = sectors;
lba_capacity = floppy->blocks * floppy->block_size;
+
if (capacity < lba_capacity) {
printk(KERN_NOTICE "%s: The disk reports a capacity of %d "
"bytes, but the drive only handles %d\n",
drive->name, lba_capacity, capacity);
- floppy->blocks = floppy->block_size ? capacity / floppy->block_size : 0;
+ floppy->blocks = floppy->block_size ?
+ capacity / floppy->block_size : 0;
}
return 0;
}
-static int idefloppy_get_capability_page(ide_drive_t *drive)
+static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t pc;
- idefloppy_mode_parameter_header_t *header;
- idefloppy_capabilities_page_t *page;
floppy->srfp = 0;
idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE,
MODE_SENSE_CURRENT);
- set_bit(PC_SUPPRESS_ERROR, &pc.flags);
- if (idefloppy_queue_pc_tail(drive,&pc)) {
+ pc.flags |= PC_FLAG_SUPPRESS_ERROR;
+ if (idefloppy_queue_pc_tail(drive, &pc))
return 1;
- }
- header = (idefloppy_mode_parameter_header_t *) pc.buffer;
- page= (idefloppy_capabilities_page_t *)(header+1);
- floppy->srfp = page->srfp;
+ floppy->srfp = pc.buffer[8 + 2] & 0x40;
return (0);
}
/*
- * Determine if a media is present in the floppy drive, and if so,
- * its LBA capacity.
+ * Determine if a media is present in the floppy drive, and if so, its LBA
+ * capacity.
*/
-static int idefloppy_get_capacity (ide_drive_t *drive)
+static int ide_floppy_get_capacity(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t pc;
- idefloppy_capacity_header_t *header;
- idefloppy_capacity_descriptor_t *descriptor;
- int i, descriptors, rc = 1, blocks, length;
-
+ u8 *cap_desc;
+ u8 header_len, desc_cnt;
+ int i, rc = 1, blocks, length;
+
drive->bios_cyl = 0;
drive->bios_head = drive->bios_sect = 0;
floppy->blocks = 0;
@@ -1444,44 +1066,55 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
return 1;
}
- header = (idefloppy_capacity_header_t *) pc.buffer;
- descriptors = header->length / sizeof(idefloppy_capacity_descriptor_t);
- descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
+ header_len = pc.buffer[3];
+ cap_desc = &pc.buffer[4];
+ desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
+
+ for (i = 0; i < desc_cnt; i++) {
+ unsigned int desc_start = 4 + i*8;
+
+ blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
+ length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
- for (i = 0; i < descriptors; i++, descriptor++) {
- blocks = descriptor->blocks = ntohl(descriptor->blocks);
- length = descriptor->length = ntohs(descriptor->length);
+ debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
+ i, blocks * length / 1024, blocks, length);
+
+ if (i)
+ continue;
+ /*
+ * the code below is valid only for the 1st descriptor, ie i=0
+ */
- if (!i)
- {
- switch (descriptor->dc) {
+ switch (pc.buffer[desc_start + 4] & 0x03) {
/* Clik! drive returns this instead of CAPACITY_CURRENT */
case CAPACITY_UNFORMATTED:
- if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
- /*
+ if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+ /*
* If it is not a clik drive, break out
* (maintains previous driver behaviour)
*/
break;
case CAPACITY_CURRENT:
/* Normal Zip/LS-120 disks */
- if (memcmp(descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t)))
+ if (memcmp(cap_desc, &floppy->cap_desc, 8))
printk(KERN_INFO "%s: %dkB, %d blocks, %d "
"sector size\n", drive->name,
blocks * length / 1024, blocks, length);
- floppy->capacity = *descriptor;
+ memcpy(&floppy->cap_desc, cap_desc, 8);
+
if (!length || length % 512) {
printk(KERN_NOTICE "%s: %d bytes block size "
"not supported\n", drive->name, length);
} else {
- floppy->blocks = blocks;
- floppy->block_size = length;
- if ((floppy->bs_factor = length / 512) != 1)
- printk(KERN_NOTICE "%s: warning: non "
+ floppy->blocks = blocks;
+ floppy->block_size = length;
+ floppy->bs_factor = length / 512;
+ if (floppy->bs_factor != 1)
+ printk(KERN_NOTICE "%s: warning: non "
"512 bytes block size not "
"fully supported\n",
drive->name);
- rc = 0;
+ rc = 0;
}
break;
case CAPACITY_NO_CARTRIDGE:
@@ -1496,54 +1129,42 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
"in drive\n", drive->name);
break;
}
- }
- if (!i) {
- debug_log( "Descriptor 0 Code: %d\n",
- descriptor->dc);
- }
- debug_log( "Descriptor %d: %dkB, %d blocks, %d "
- "sector size\n", i, blocks * length / 1024, blocks,
- length);
+ debug_log("Descriptor 0 Code: %d\n",
+ pc.buffer[desc_start + 4] & 0x03);
}
/* Clik! disk does not support get_flexible_disk_page */
- if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
- (void) idefloppy_get_flexible_disk_page(drive);
- }
+ if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+ (void) ide_floppy_get_flexible_disk_page(drive);
set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor);
return rc;
}
/*
-** Obtain the list of formattable capacities.
-** Very similar to idefloppy_get_capacity, except that we push the capacity
-** descriptors to userland, instead of our own structures.
-**
-** Userland gives us the following structure:
-**
-** struct idefloppy_format_capacities {
-** int nformats;
-** struct {
-** int nblocks;
-** int blocksize;
-** } formats[];
-** } ;
-**
-** userland initializes nformats to the number of allocated formats[]
-** records. On exit we set nformats to the number of records we've
-** actually initialized.
-**
-*/
-
-static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ * Obtain the list of formattable capacities.
+ * Very similar to ide_floppy_get_capacity, except that we push the capacity
+ * descriptors to userland, instead of our own structures.
+ *
+ * Userland gives us the following structure:
+ *
+ * struct idefloppy_format_capacities {
+ * int nformats;
+ * struct {
+ * int nblocks;
+ * int blocksize;
+ * } formats[];
+ * };
+ *
+ * userland initializes nformats to the number of allocated formats[] records.
+ * On exit we set nformats to the number of records we've actually initialized.
+ */
+
+static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
{
- idefloppy_pc_t pc;
- idefloppy_capacity_header_t *header;
- idefloppy_capacity_descriptor_t *descriptor;
- int i, descriptors, blocks, length;
- int u_array_size;
- int u_index;
+ idefloppy_pc_t pc;
+ u8 header_len, desc_cnt;
+ int i, blocks, length, u_array_size, u_index;
int __user *argp;
if (get_user(u_array_size, arg))
@@ -1555,30 +1176,27 @@ static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
idefloppy_create_read_capacity_cmd(&pc);
if (idefloppy_queue_pc_tail(drive, &pc)) {
printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
- return (-EIO);
- }
- header = (idefloppy_capacity_header_t *) pc.buffer;
- descriptors = header->length /
- sizeof(idefloppy_capacity_descriptor_t);
- descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
+ return (-EIO);
+ }
+ header_len = pc.buffer[3];
+ desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
u_index = 0;
argp = arg + 1;
/*
- ** We always skip the first capacity descriptor. That's the
- ** current capacity. We are interested in the remaining descriptors,
- ** the formattable capacities.
- */
+ * We always skip the first capacity descriptor. That's the current
+ * capacity. We are interested in the remaining descriptors, the
+ * formattable capacities.
+ */
+ for (i = 1; i < desc_cnt; i++) {
+ unsigned int desc_start = 4 + i*8;
- for (i=0; i<descriptors; i++, descriptor++) {
if (u_index >= u_array_size)
break; /* User-supplied buffer too small */
- if (i == 0)
- continue; /* Skip the first descriptor */
- blocks = ntohl(descriptor->blocks);
- length = ntohs(descriptor->length);
+ blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
+ length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
if (put_user(blocks, argp))
return(-EFAULT);
@@ -1597,53 +1215,14 @@ static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
}
/*
-** Send ATAPI_FORMAT_UNIT to the drive.
-**
-** Userland gives us the following structure:
-**
-** struct idefloppy_format_command {
-** int nblocks;
-** int blocksize;
-** int flags;
-** } ;
-**
-** flags is a bitmask, currently, the only defined flag is:
-**
-** 0x01 - verify media after format.
-*/
-
-static int idefloppy_begin_format(ide_drive_t *drive, int __user *arg)
-{
- int blocks;
- int length;
- int flags;
- idefloppy_pc_t pc;
-
- if (get_user(blocks, arg) ||
- get_user(length, arg+1) ||
- get_user(flags, arg+2)) {
- return (-EFAULT);
- }
-
- /* Get the SFRP bit */
- (void) idefloppy_get_capability_page(drive);
- idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- return (-EIO);
- }
-
- return (0);
-}
-
-/*
-** Get ATAPI_FORMAT_UNIT progress indication.
-**
-** Userland gives a pointer to an int. The int is set to a progress
-** indicator 0-65536, with 65536=100%.
-**
-** If the drive does not support format progress indication, we just check
-** the dsc bit, and return either 0 or 65536.
-*/
+ * Get ATAPI_FORMAT_UNIT progress indication.
+ *
+ * Userland gives a pointer to an int. The int is set to a progress
+ * indicator 0-65536, with 65536=100%.
+ *
+ * If the drive does not support format progress indication, we just check
+ * the dsc bit, and return either 0 or 65536.
+ */
static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
{
@@ -1653,26 +1232,24 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
if (floppy->srfp) {
idefloppy_create_request_sense_cmd(&pc);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
+ if (idefloppy_queue_pc_tail(drive, &pc))
return (-EIO);
- }
if (floppy->sense_key == 2 &&
floppy->asc == 4 &&
- floppy->ascq == 4) {
+ floppy->ascq == 4)
progress_indication = floppy->progress_indication;
- }
- /* Else assume format_unit has finished, and we're
- ** at 0x10000 */
+
+ /* Else assume format_unit has finished, and we're at 0x10000 */
} else {
- atapi_status_t status;
unsigned long flags;
+ u8 stat;
local_irq_save(flags);
- status.all = HWIF(drive)->INB(IDE_STATUS_REG);
+ stat = drive->hwif->INB(IDE_STATUS_REG);
local_irq_restore(flags);
- progress_indication = !status.b.dsc ? 0 : 0x10000;
+ progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
}
if (put_user(progress_indication, arg))
return (-EFAULT);
@@ -1680,10 +1257,7 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
return (0);
}
-/*
- * Return the current floppy capacity.
- */
-static sector_t idefloppy_capacity (ide_drive_t *drive)
+static sector_t idefloppy_capacity(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
unsigned long capacity = floppy->blocks * floppy->bs_factor;
@@ -1692,16 +1266,12 @@ static sector_t idefloppy_capacity (ide_drive_t *drive)
}
/*
- * idefloppy_identify_device checks if we can support a drive,
- * based on the ATAPI IDENTIFY command results.
+ * Check whether we can support a drive, based on the ATAPI IDENTIFY command
+ * results.
*/
-static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id)
+static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id)
{
struct idefloppy_id_gcw gcw;
-#if IDEFLOPPY_DEBUG_INFO
- u16 mask,i;
- char buffer[80];
-#endif /* IDEFLOPPY_DEBUG_INFO */
*((u16 *) &gcw) = id->config;
@@ -1710,103 +1280,23 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id)
if ((gcw.device_type == 5) &&
!strstr(id->model, "CD-ROM") &&
strstr(id->model, "ZIP"))
- gcw.device_type = 0;
+ gcw.device_type = 0;
#endif
-#if IDEFLOPPY_DEBUG_INFO
- printk(KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n");
- switch (gcw.protocol) {
- case 0: case 1: sprintf(buffer, "ATA");break;
- case 2: sprintf(buffer, "ATAPI");break;
- case 3: sprintf(buffer, "Reserved (Unknown to ide-floppy)");break;
- }
- printk(KERN_INFO "Protocol Type: %s\n", buffer);
- switch (gcw.device_type) {
- case 0: sprintf(buffer, "Direct-access Device");break;
- case 1: sprintf(buffer, "Streaming Tape Device");break;
- case 2: case 3: case 4: sprintf (buffer, "Reserved");break;
- case 5: sprintf(buffer, "CD-ROM Device");break;
- case 6: sprintf(buffer, "Reserved");
- case 7: sprintf(buffer, "Optical memory Device");break;
- case 0x1f: sprintf(buffer, "Unknown or no Device type");break;
- default: sprintf(buffer, "Reserved");
- }
- printk(KERN_INFO "Device Type: %x - %s\n", gcw.device_type, buffer);
- printk(KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No");
- switch (gcw.drq_type) {
- case 0: sprintf(buffer, "Microprocessor DRQ");break;
- case 1: sprintf(buffer, "Interrupt DRQ");break;
- case 2: sprintf(buffer, "Accelerated DRQ");break;
- case 3: sprintf(buffer, "Reserved");break;
- }
- printk(KERN_INFO "Command Packet DRQ Type: %s\n", buffer);
- switch (gcw.packet_size) {
- case 0: sprintf(buffer, "12 bytes");break;
- case 1: sprintf(buffer, "16 bytes");break;
- default: sprintf(buffer, "Reserved");break;
- }
- printk(KERN_INFO "Command Packet Size: %s\n", buffer);
- printk(KERN_INFO "Model: %.40s\n",id->model);
- printk(KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev);
- printk(KERN_INFO "Serial Number: %.20s\n",id->serial_no);
- printk(KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512);
- printk(KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
- printk(KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
- printk(KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
- printk(KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
- printk(KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
- printk(KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO);
- printk(KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA);
- printk(KERN_INFO "Single Word DMA supported modes:\n");
- for (i=0,mask=1;i<8;i++,mask=mask << 1) {
- if (id->dma_1word & mask)
- printk(KERN_INFO " Mode %d%s\n", i,
- (id->dma_1word & (mask << 8)) ? " (active)" : "");
- }
- printk(KERN_INFO "Multi Word DMA supported modes:\n");
- for (i=0,mask=1;i<8;i++,mask=mask << 1) {
- if (id->dma_mword & mask)
- printk(KERN_INFO " Mode %d%s\n", i,
- (id->dma_mword & (mask << 8)) ? " (active)" : "");
- }
- if (id->field_valid & 0x0002) {
- printk(KERN_INFO "Enhanced PIO Modes: %s\n",
- id->eide_pio_modes & 1 ? "Mode 3":"None");
- if (id->eide_dma_min == 0)
- sprintf(buffer, "Not supported");
- else
- sprintf(buffer, "%d ns",id->eide_dma_min);
- printk(KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer);
- if (id->eide_dma_time == 0)
- sprintf(buffer, "Not supported");
- else
- sprintf(buffer, "%d ns",id->eide_dma_time);
- printk(KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer);
- if (id->eide_pio == 0)
- sprintf(buffer, "Not supported");
- else
- sprintf(buffer, "%d ns",id->eide_pio);
- printk(KERN_INFO "Minimum PIO cycle without IORDY: %s\n",
- buffer);
- if (id->eide_pio_iordy == 0)
- sprintf(buffer, "Not supported");
- else
- sprintf(buffer, "%d ns",id->eide_pio_iordy);
- printk(KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer);
- } else
- printk(KERN_INFO "According to the device, fields 64-70 are not valid.\n");
-#endif /* IDEFLOPPY_DEBUG_INFO */
-
if (gcw.protocol != 2)
- printk(KERN_ERR "ide-floppy: Protocol is not ATAPI\n");
+ printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n",
+ gcw.protocol);
else if (gcw.device_type != 0)
- printk(KERN_ERR "ide-floppy: Device type is not set to floppy\n");
+ printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set "
+ "to floppy\n", gcw.device_type);
else if (!gcw.removable)
printk(KERN_ERR "ide-floppy: The removable flag is not set\n");
else if (gcw.drq_type == 3) {
- printk(KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type);
+ printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not "
+ "supported\n", gcw.drq_type);
} else if (gcw.packet_size != 0) {
- printk(KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n");
+ printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 "
+ "bytes long\n", gcw.packet_size);
} else
return 1;
return 0;
@@ -1817,59 +1307,53 @@ static void idefloppy_add_settings(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
-/*
- * drive setting name read/write data type min max mul_factor div_factor data pointer set function
- */
- ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL);
- ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
- ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
- ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL);
+ ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1,
+ &drive->bios_cyl, NULL);
+ ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
+ &drive->bios_head, NULL);
+ ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
+ &drive->bios_sect, NULL);
+ ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
+ &floppy->ticks, NULL);
}
#else
static inline void idefloppy_add_settings(ide_drive_t *drive) { ; }
#endif
-/*
- * Driver initialization.
- */
-static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
+static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
{
struct idefloppy_id_gcw gcw;
*((u16 *) &gcw) = drive->id->config;
floppy->pc = floppy->pc_stack;
if (gcw.drq_type == 1)
- set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags);
+ floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT;
/*
- * We used to check revisions here. At this point however
- * I'm giving up. Just assume they are all broken, its easier.
+ * 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.
+ * 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 (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) {
- set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags);
+ floppy->flags |= IDEFLOPPY_FLAG_ZIP_DRIVE;
/* This value will be visible in the /proc/ide/hdx/settings */
floppy->ticks = IDEFLOPPY_TICKS_DELAY;
blk_queue_max_sectors(drive->queue, 64);
}
/*
- * Guess what? The IOMEGA Clik! drive also needs the
- * above fix. It makes nasty clicking noises without
- * it, so please don't remove this.
- */
+ * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes
+ * nasty clicking noises without it, so please don't remove this.
+ */
if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {
blk_queue_max_sectors(drive->queue, 64);
- set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
+ floppy->flags |= IDEFLOPPY_FLAG_CLIK_DRIVE;
}
-
- (void) idefloppy_get_capacity(drive);
+ (void) ide_floppy_get_capacity(drive);
idefloppy_add_settings(drive);
}
@@ -1885,7 +1369,7 @@ static void ide_floppy_remove(ide_drive_t *drive)
ide_floppy_put(floppy);
}
-static void ide_floppy_release(struct kref *kref)
+static void idefloppy_cleanup_obj(struct kref *kref)
{
struct ide_floppy_obj *floppy = to_ide_floppy(kref);
ide_drive_t *drive = floppy->drive;
@@ -1898,19 +1382,19 @@ static void ide_floppy_release(struct kref *kref)
}
#ifdef CONFIG_IDE_PROC_FS
-static int proc_idefloppy_read_capacity
- (char *page, char **start, off_t off, int count, int *eof, void *data)
+static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
ide_drive_t*drive = (ide_drive_t *)data;
int len;
- len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive));
- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+ len = sprintf(page, "%llu\n", (long long)idefloppy_capacity(drive));
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
}
static ide_proc_entry_t idefloppy_proc[] = {
- { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL },
- { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
+ { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL },
+ { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
{ NULL, 0, NULL, NULL }
};
#endif /* CONFIG_IDE_PROC_FS */
@@ -1945,9 +1429,10 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
idefloppy_pc_t pc;
int ret = 0;
- debug_log(KERN_INFO "Reached idefloppy_open\n");
+ debug_log("Reached %s\n", __func__);
- if (!(floppy = ide_floppy_get(disk)))
+ floppy = ide_floppy_get(disk);
+ if (!floppy)
return -ENXIO;
drive = floppy->drive;
@@ -1955,7 +1440,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
floppy->openers++;
if (floppy->openers == 1) {
- clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+ floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
/* Just in case */
idefloppy_create_test_unit_ready_cmd(&pc);
@@ -1964,13 +1449,13 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
(void) idefloppy_queue_pc_tail(drive, &pc);
}
- if (idefloppy_get_capacity (drive)
+ if (ide_floppy_get_capacity(drive)
&& (filp->f_flags & O_NDELAY) == 0
/*
- ** Allow O_NDELAY to open a drive without a disk, or with
- ** an unreadable disk, so that we can get the format
- ** capacity of the drive or begin the format - Sam
- */
+ * Allow O_NDELAY to open a drive without a disk, or with an
+ * unreadable disk, so that we can get the format capacity
+ * of the drive or begin the format - Sam
+ */
) {
ret = -EIO;
goto out_put_floppy;
@@ -1980,14 +1465,14 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
ret = -EROFS;
goto out_put_floppy;
}
- set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
+ floppy->flags |= IDEFLOPPY_FLAG_MEDIA_CHANGED;
/* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+ if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
idefloppy_create_prevent_cmd(&pc, 1);
(void) idefloppy_queue_pc_tail(drive, &pc);
}
check_disk_change(inode->i_bdev);
- } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
+ } else if (floppy->flags & IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS) {
ret = -EBUSY;
goto out_put_floppy;
}
@@ -2005,17 +1490,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
struct ide_floppy_obj *floppy = ide_floppy_g(disk);
ide_drive_t *drive = floppy->drive;
idefloppy_pc_t pc;
-
- debug_log(KERN_INFO "Reached idefloppy_release\n");
+
+ debug_log("Reached %s\n", __func__);
if (floppy->openers == 1) {
/* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+ if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
idefloppy_create_prevent_cmd(&pc, 0);
(void) idefloppy_queue_pc_tail(drive, &pc);
}
- clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+ floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
}
floppy->openers--;
@@ -2036,64 +1521,105 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
+static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc,
+ unsigned long arg, unsigned int cmd)
+{
+ if (floppy->openers > 1)
+ return -EBUSY;
+
+ /* The IOMEGA Clik! Drive doesn't support this command -
+ * no room for an eject mechanism */
+ if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ int prevent = arg ? 1 : 0;
+
+ if (cmd == CDROMEJECT)
+ prevent = 0;
+
+ idefloppy_create_prevent_cmd(pc, prevent);
+ (void) idefloppy_queue_pc_tail(floppy->drive, pc);
+ }
+
+ if (cmd == CDROMEJECT) {
+ idefloppy_create_start_stop_cmd(pc, 2);
+ (void) idefloppy_queue_pc_tail(floppy->drive, pc);
+ }
+
+ return 0;
+}
+
+static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
+ int __user *arg)
+{
+ int blocks, length, flags, err = 0;
+ idefloppy_pc_t pc;
+
+ if (floppy->openers > 1) {
+ /* Don't format if someone is using the disk */
+ floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ return -EBUSY;
+ }
+
+ floppy->flags |= IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+
+ /*
+ * Send ATAPI_FORMAT_UNIT to the drive.
+ *
+ * Userland gives us the following structure:
+ *
+ * struct idefloppy_format_command {
+ * int nblocks;
+ * int blocksize;
+ * int flags;
+ * } ;
+ *
+ * flags is a bitmask, currently, the only defined flag is:
+ *
+ * 0x01 - verify media after format.
+ */
+ if (get_user(blocks, arg) ||
+ get_user(length, arg+1) ||
+ get_user(flags, arg+2)) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ (void) idefloppy_get_sfrp_bit(floppy->drive);
+ idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
+
+ if (idefloppy_queue_pc_tail(floppy->drive, &pc))
+ err = -EIO;
+
+out:
+ if (err)
+ floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ return err;
+}
+
+
static int idefloppy_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
ide_drive_t *drive = floppy->drive;
+ idefloppy_pc_t pc;
void __user *argp = (void __user *)arg;
int err;
- int prevent = (arg) ? 1 : 0;
- idefloppy_pc_t pc;
switch (cmd) {
case CDROMEJECT:
- prevent = 0;
/* fall through */
case CDROM_LOCKDOOR:
- if (floppy->openers > 1)
- return -EBUSY;
-
- /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
- if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
- idefloppy_create_prevent_cmd(&pc, prevent);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
- if (cmd == CDROMEJECT) {
- idefloppy_create_start_stop_cmd(&pc, 2);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
- return 0;
+ return ide_floppy_lockdoor(floppy, &pc, arg, cmd);
case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
return 0;
case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
- return idefloppy_get_format_capacities(drive, argp);
+ return ide_floppy_get_format_capacities(drive, argp);
case IDEFLOPPY_IOCTL_FORMAT_START:
-
if (!(file->f_mode & 2))
return -EPERM;
- if (floppy->openers > 1) {
- /* Don't format if someone is using the disk */
-
- clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
- &floppy->flags);
- return -EBUSY;
- }
-
- set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
-
- err = idefloppy_begin_format(drive, argp);
- if (err)
- clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
- return err;
- /*
- ** Note, the bit will be cleared when the device is
- ** closed. This is the cleanest way to handle the
- ** situation where the drive does not support
- ** format progress reporting.
- */
+ return ide_floppy_format_unit(floppy, (int __user *)arg);
case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
return idefloppy_get_format_progress(drive, argp);
}
@@ -2118,13 +1644,16 @@ static int idefloppy_media_changed(struct gendisk *disk)
{
struct ide_floppy_obj *floppy = ide_floppy_g(disk);
ide_drive_t *drive = floppy->drive;
+ int ret;
/* do not scan partitions twice if this is a removable device */
if (drive->attach) {
drive->attach = 0;
return 0;
}
- return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
+ ret = !!(floppy->flags & IDEFLOPPY_FLAG_MEDIA_CHANGED);
+ floppy->flags &= ~IDEFLOPPY_FLAG_MEDIA_CHANGED;
+ return ret;
}
static int idefloppy_revalidate_disk(struct gendisk *disk)
@@ -2155,16 +1684,20 @@ static int ide_floppy_probe(ide_drive_t *drive)
goto failed;
if (drive->media != ide_floppy)
goto failed;
- if (!idefloppy_identify_device (drive, drive->id)) {
- printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name);
+ if (!idefloppy_identify_device(drive, drive->id)) {
+ printk(KERN_ERR "ide-floppy: %s: not supported by this version"
+ " of ide-floppy\n", drive->name);
goto failed;
}
if (drive->scsi) {
- printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
+ printk(KERN_INFO "ide-floppy: passing drive %s to ide-scsi"
+ " emulation.\n", drive->name);
goto failed;
}
- if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
- printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
+ floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL);
+ if (!floppy) {
+ printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy"
+ " structure\n", drive->name);
goto failed;
}
@@ -2186,7 +1719,7 @@ static int ide_floppy_probe(ide_drive_t *drive)
drive->driver_data = floppy;
- idefloppy_setup (drive, floppy);
+ idefloppy_setup(drive, floppy);
g->minors = 1 << PARTN_BITS;
g->driverfs_dev = &drive->gendev;
@@ -2202,9 +1735,7 @@ failed:
return -ENODEV;
}
-MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
-
-static void __exit idefloppy_exit (void)
+static void __exit idefloppy_exit(void)
{
driver_unregister(&idefloppy_driver.gen_driver);
}
@@ -2219,3 +1750,5 @@ MODULE_ALIAS("ide:*m-floppy*");
module_init(idefloppy_init);
module_exit(idefloppy_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
+
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
index 0f72b98d727..be469dbbe8f 100644
--- a/drivers/ide/ide-generic.c
+++ b/drivers/ide/ide-generic.c
@@ -14,10 +14,16 @@
static int __init ide_generic_init(void)
{
+ u8 idx[MAX_HWIFS];
+ int i;
+
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
ide_get_lock(NULL, NULL); /* for atari only */
- (void)ideprobe_init();
+ for (i = 0; i < MAX_HWIFS; i++)
+ idx[i] = ide_hwifs[i].present ? 0xff : i;
+
+ ide_device_add_all(idx, NULL);
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
ide_release_lock(); /* for atari only */
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index c89f0d3058e..4bddef0c0b9 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -58,15 +58,19 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
int uptodate, unsigned int nr_bytes, int dequeue)
{
int ret = 1;
+ int error = 0;
+
+ if (uptodate <= 0)
+ error = uptodate ? uptodate : -EIO;
/*
* if failfast is set on a request, override number of sectors and
* complete the whole request right now
*/
- if (blk_noretry_request(rq) && end_io_error(uptodate))
+ if (blk_noretry_request(rq) && error)
nr_bytes = rq->hard_nr_sectors << 9;
- if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
+ if (!blk_fs_request(rq) && error && !rq->errors)
rq->errors = -EIO;
/*
@@ -75,17 +79,12 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
*/
if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
drive->state = 0;
- HWGROUP(drive)->hwif->ide_dma_on(drive);
+ ide_dma_on(drive);
}
- if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
- add_disk_randomness(rq->rq_disk);
- if (dequeue) {
- if (!list_empty(&rq->queuelist))
- blkdev_dequeue_request(rq);
+ if (!__blk_end_request(rq, error, nr_bytes)) {
+ if (dequeue)
HWGROUP(drive)->rq = NULL;
- }
- end_that_request_last(rq, uptodate);
ret = 0;
}
@@ -189,18 +188,14 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
return ide_stopped;
}
if (ide_id_has_flush_cache_ext(drive->id))
- args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
+ args->tf.command = WIN_FLUSH_CACHE_EXT;
else
- args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
- args->command_type = IDE_DRIVE_TASK_NO_DATA;
- args->handler = &task_no_data_intr;
- return do_rw_taskfile(drive, args);
+ args->tf.command = WIN_FLUSH_CACHE;
+ goto out_do_tf;
case idedisk_pm_standby: /* Suspend step 2 (standby) */
- args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
- args->command_type = IDE_DRIVE_TASK_NO_DATA;
- args->handler = &task_no_data_intr;
- return do_rw_taskfile(drive, args);
+ args->tf.command = WIN_STANDBYNOW1;
+ goto out_do_tf;
case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */
ide_set_max_pio(drive);
@@ -214,10 +209,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
return ide_stopped;
case idedisk_pm_idle: /* Resume step 2 (idle) */
- args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
- args->command_type = IDE_DRIVE_TASK_NO_DATA;
- args->handler = task_no_data_intr;
- return do_rw_taskfile(drive, args);
+ args->tf.command = WIN_IDLEIMMEDIATE;
+ goto out_do_tf;
case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */
/*
@@ -225,9 +218,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
* we could be smarter and check for current xfer_speed
* in struct drive etc...
*/
- if (drive->hwif->ide_dma_on == NULL)
+ if (drive->hwif->dma_host_set == NULL)
break;
- drive->hwif->dma_off_quietly(drive);
/*
* TODO: respect ->using_dma setting
*/
@@ -236,6 +228,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
}
pm->pm_step = ide_pm_state_completed;
return ide_stopped;
+
+out_do_tf:
+ args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ args->data_phase = TASKFILE_NO_DATA;
+ return do_rw_taskfile(drive, args);
}
/**
@@ -292,12 +289,54 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
drive->blocked = 0;
blk_start_queue(drive->queue);
}
- blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq, 1);
+ if (__blk_end_request(rq, 0, 0))
+ BUG();
spin_unlock_irqrestore(&ide_lock, flags);
}
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct ide_taskfile *tf = &task->tf;
+
+ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+ u16 data = hwif->INW(IDE_DATA_REG);
+
+ tf->data = data & 0xff;
+ tf->hob_data = (data >> 8) & 0xff;
+ }
+
+ /* be sure we're looking at the low order bits */
+ hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
+
+ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+ tf->nsect = hwif->INB(IDE_NSECTOR_REG);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+ tf->lbal = hwif->INB(IDE_SECTOR_REG);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+ tf->lbam = hwif->INB(IDE_LCYL_REG);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+ tf->lbah = hwif->INB(IDE_HCYL_REG);
+ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+ tf->device = hwif->INB(IDE_SELECT_REG);
+
+ if (task->tf_flags & IDE_TFLAG_LBA48) {
+ hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
+
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+ tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+ tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+ tf->hob_lbal = hwif->INB(IDE_SECTOR_REG);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+ tf->hob_lbam = hwif->INB(IDE_LCYL_REG);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+ tf->hob_lbah = hwif->INB(IDE_HCYL_REG);
+ }
+}
+
/**
* ide_end_drive_cmd - end an explicit drive command
* @drive: command
@@ -314,7 +353,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
{
- ide_hwif_t *hwif = HWIF(drive);
unsigned long flags;
struct request *rq;
@@ -322,59 +360,18 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
rq = HWGROUP(drive)->rq;
spin_unlock_irqrestore(&ide_lock, flags);
- if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
- u8 *args = (u8 *) rq->buffer;
- if (rq->errors == 0)
- rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-
- if (args) {
- args[0] = stat;
- args[1] = err;
- args[2] = hwif->INB(IDE_NSECTOR_REG);
- }
- } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
- u8 *args = (u8 *) rq->buffer;
- if (rq->errors == 0)
- rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-
- if (args) {
- args[0] = stat;
- args[1] = err;
- args[2] = hwif->INB(IDE_NSECTOR_REG);
- args[3] = hwif->INB(IDE_SECTOR_REG);
- args[4] = hwif->INB(IDE_LCYL_REG);
- args[5] = hwif->INB(IDE_HCYL_REG);
- args[6] = hwif->INB(IDE_SELECT_REG);
- }
- } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+ if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
ide_task_t *args = (ide_task_t *) rq->special;
if (rq->errors == 0)
rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
if (args) {
- if (args->tf_in_flags.b.data) {
- u16 data = hwif->INW(IDE_DATA_REG);
- args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF;
- args->hobRegister[IDE_DATA_OFFSET] = (data >> 8) & 0xFF;
- }
- args->tfRegister[IDE_ERROR_OFFSET] = err;
- /* be sure we're looking at the low order bits */
- hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
- args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
- args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG);
- args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG);
- args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG);
- args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG);
- args->tfRegister[IDE_STATUS_OFFSET] = stat;
-
- if (drive->addressing == 1) {
- hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
- args->hobRegister[IDE_FEATURE_OFFSET] = hwif->INB(IDE_FEATURE_REG);
- args->hobRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
- args->hobRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG);
- args->hobRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG);
- args->hobRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG);
- }
+ struct ide_taskfile *tf = &args->tf;
+
+ tf->error = err;
+ tf->status = stat;
+
+ ide_tf_read(drive, args);
}
} else if (blk_pm_request(rq)) {
struct request_pm_state *pm = rq->data;
@@ -389,10 +386,10 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
}
spin_lock_irqsave(&ide_lock, flags);
- blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
rq->errors = err;
- end_that_request_last(rq, !rq->errors);
+ if (__blk_end_request(rq, (rq->errors ? -EIO : 0), 0))
+ BUG();
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -613,89 +610,26 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
return __ide_abort(drive, rq);
}
-/**
- * ide_cmd - issue a simple drive command
- * @drive: drive the command is for
- * @cmd: command byte
- * @nsect: sector byte
- * @handler: handler for the command completion
- *
- * Issue a simple drive command with interrupts.
- * The drive must be selected beforehand.
- */
-
-static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
- ide_handler_t *handler)
+static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
- ide_hwif_t *hwif = HWIF(drive);
- if (IDE_CONTROL_REG)
- hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
- SELECT_MASK(drive,0);
- hwif->OUTB(nsect,IDE_NSECTOR_REG);
- ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
+ tf->nsect = drive->sect;
+ tf->lbal = drive->sect;
+ tf->lbam = drive->cyl;
+ tf->lbah = drive->cyl >> 8;
+ tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
+ tf->command = WIN_SPECIFY;
}
-/**
- * drive_cmd_intr - drive command completion interrupt
- * @drive: drive the completion interrupt occurred on
- *
- * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- * We do any necessary data reading and then wait for the drive to
- * go non busy. At that point we may read the error data and complete
- * the request
- */
-
-static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
+static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
- struct request *rq = HWGROUP(drive)->rq;
- ide_hwif_t *hwif = HWIF(drive);
- u8 *args = (u8 *) rq->buffer;
- u8 stat = hwif->INB(IDE_STATUS_REG);
- int retries = 10;
-
- local_irq_enable_in_hardirq();
- if ((stat & DRQ_STAT) && args && args[3]) {
- u8 io_32bit = drive->io_32bit;
- drive->io_32bit = 0;
- hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
- drive->io_32bit = io_32bit;
- while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
- udelay(100);
- }
-
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
- return ide_error(drive, "drive_cmd", stat);
- /* calls ide_end_drive_cmd */
- ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
- return ide_stopped;
+ tf->nsect = drive->sect;
+ tf->command = WIN_RESTORE;
}
-static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task)
+static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
- task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
- task->tfRegister[IDE_SECTOR_OFFSET] = drive->sect;
- task->tfRegister[IDE_LCYL_OFFSET] = drive->cyl;
- task->tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8;
- task->tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF;
- task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
-
- task->handler = &set_geometry_intr;
-}
-
-static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task)
-{
- task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
- task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
-
- task->handler = &recal_intr;
-}
-
-static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task)
-{
- task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
- task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
-
- task->handler = &set_multmode_intr;
+ tf->nsect = drive->mult_req;
+ tf->command = WIN_SETMULT;
}
static ide_startstop_t ide_disk_special(ide_drive_t *drive)
@@ -704,19 +638,19 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.data_phase = TASKFILE_NO_DATA;
if (s->b.set_geometry) {
s->b.set_geometry = 0;
- ide_init_specify_cmd(drive, &args);
+ ide_tf_set_specify_cmd(drive, &args.tf);
} else if (s->b.recalibrate) {
s->b.recalibrate = 0;
- ide_init_restore_cmd(drive, &args);
+ ide_tf_set_restore_cmd(drive, &args.tf);
} else if (s->b.set_multmode) {
s->b.set_multmode = 0;
if (drive->mult_req > drive->id->max_multsect)
drive->mult_req = drive->id->max_multsect;
- ide_init_setmult_cmd(drive, &args);
+ ide_tf_set_setmult_cmd(drive, &args.tf);
} else if (s->all) {
int special = s->all;
s->all = 0;
@@ -724,6 +658,9 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
return ide_stopped;
}
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE |
+ IDE_TFLAG_CUSTOM_HANDLER;
+
do_rw_taskfile(drive, &args);
return ide_started;
@@ -798,7 +735,7 @@ static ide_startstop_t do_special (ide_drive_t *drive)
if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
if (keep_dma)
- hwif->ide_dma_on(drive);
+ ide_dma_on(drive);
}
}
@@ -858,13 +795,10 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
struct request *rq)
{
ide_hwif_t *hwif = HWIF(drive);
- if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
- ide_task_t *args = rq->special;
-
- if (!args)
- goto done;
+ ide_task_t *task = rq->special;
- hwif->data_phase = args->data_phase;
+ if (task) {
+ hwif->data_phase = task->data_phase;
switch (hwif->data_phase) {
case TASKFILE_MULTI_OUT:
@@ -877,61 +811,9 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
break;
}
- if (args->tf_out_flags.all != 0)
- return flagged_taskfile(drive, args);
- return do_rw_taskfile(drive, args);
- } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
- u8 *args = rq->buffer;
- u8 sel;
-
- if (!args)
- goto done;
-#ifdef DEBUG
- printk("%s: DRIVE_TASK_CMD ", drive->name);
- printk("cmd=0x%02x ", args[0]);
- printk("fr=0x%02x ", args[1]);
- printk("ns=0x%02x ", args[2]);
- printk("sc=0x%02x ", args[3]);
- printk("lcyl=0x%02x ", args[4]);
- printk("hcyl=0x%02x ", args[5]);
- printk("sel=0x%02x\n", args[6]);
-#endif
- hwif->OUTB(args[1], IDE_FEATURE_REG);
- hwif->OUTB(args[3], IDE_SECTOR_REG);
- hwif->OUTB(args[4], IDE_LCYL_REG);
- hwif->OUTB(args[5], IDE_HCYL_REG);
- sel = (args[6] & ~0x10);
- if (drive->select.b.unit)
- sel |= 0x10;
- hwif->OUTB(sel, IDE_SELECT_REG);
- ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
- return ide_started;
- } else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
- u8 *args = rq->buffer;
-
- if (!args)
- goto done;
-#ifdef DEBUG
- printk("%s: DRIVE_CMD ", drive->name);
- printk("cmd=0x%02x ", args[0]);
- printk("sc=0x%02x ", args[1]);
- printk("fr=0x%02x ", args[2]);
- printk("xx=0x%02x\n", args[3]);
-#endif
- if (args[0] == WIN_SMART) {
- hwif->OUTB(0x4f, IDE_LCYL_REG);
- hwif->OUTB(0xc2, IDE_HCYL_REG);
- hwif->OUTB(args[2],IDE_FEATURE_REG);
- hwif->OUTB(args[1],IDE_SECTOR_REG);
- ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
- return ide_started;
- }
- hwif->OUTB(args[2],IDE_FEATURE_REG);
- ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
- return ide_started;
- }
-
-done:
+ return do_rw_taskfile(drive, task);
+ }
+
/*
* NULL is actually a valid way of waiting for
* all current requests to be flushed from the queue.
@@ -971,7 +853,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
if (rc)
printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
SELECT_DRIVE(drive);
- HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
+ ide_set_irq(drive, 1);
rc = ide_wait_not_busy(HWIF(drive), 100000);
if (rc)
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
@@ -1003,6 +885,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
+ rq->cmd_flags |= REQ_FAILED;
goto kill_rq;
}
@@ -1034,9 +917,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
if (drive->current_speed == 0xff)
ide_config_drive_speed(drive, drive->desired_speed);
- if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
- rq->cmd_type == REQ_TYPE_ATA_TASK ||
- rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
+ if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
return execute_drive_cmd(drive, rq);
else if (blk_pm_request(rq)) {
struct request_pm_state *pm = rq->data;
@@ -1244,11 +1125,13 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
}
again:
hwif = HWIF(drive);
- if (hwgroup->hwif->sharing_irq &&
- hwif != hwgroup->hwif &&
- hwif->io_ports[IDE_CONTROL_OFFSET]) {
- /* set nIEN for previous hwif */
- SELECT_INTERRUPT(drive);
+ if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) {
+ /*
+ * set nIEN for previous hwif, drives in the
+ * quirk_list may not like intr setups/cleanups
+ */
+ if (drive->quirk_list != 1)
+ ide_set_irq(drive, 0);
}
hwgroup->hwif = hwif;
hwgroup->drive = drive;
@@ -1361,7 +1244,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
*/
drive->retry_pio++;
drive->state = DMA_PIO_RETRY;
- hwif->dma_off_quietly(drive);
+ ide_dma_off_quietly(drive);
/*
* un-busy drive etc (hwgroup->busy is cleared on return) and
@@ -1454,12 +1337,8 @@ void ide_timer_expiry (unsigned long data)
*/
spin_unlock(&ide_lock);
hwif = HWIF(drive);
-#if DISABLE_IRQ_NOSYNC
- disable_irq_nosync(hwif->irq);
-#else
/* disable_irq_nosync ?? */
disable_irq(hwif->irq);
-#endif /* DISABLE_IRQ_NOSYNC */
/* local CPU only,
* as if we were handling an interrupt */
local_irq_disable();
@@ -1608,7 +1487,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
* remove all the ifdef PCI crap
*/
#ifdef CONFIG_BLK_DEV_IDEPCI
- if (hwif->pci_dev && !hwif->pci_dev->vendor)
+ if (hwif->chipset != ide_pci)
#endif /* CONFIG_BLK_DEV_IDEPCI */
{
/*
@@ -1710,7 +1589,6 @@ irqreturn_t ide_intr (int irq, void *dev_id)
void ide_init_drive_cmd (struct request *rq)
{
memset(rq, 0, sizeof(*rq));
- rq->cmd_type = REQ_TYPE_ATA_CMD;
rq->ref_count = 1;
}
@@ -1785,3 +1663,19 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
}
EXPORT_SYMBOL(ide_do_drive_cmd);
+
+void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
+ IDE_TFLAG_OUT_FEATURE | tf_flags;
+ task.tf.feature = dma; /* Use PIO/DMA */
+ task.tf.lbam = bcount & 0xff;
+ task.tf.lbah = (bcount >> 8) & 0xff;
+
+ ide_tf_load(drive, &task);
+}
+
+EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index dcda0f109df..a95178f5e1b 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/ide-iops.c Version 0.37 Mar 05, 2003
- *
* Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat <alan@redhat.com>
*
@@ -158,14 +156,6 @@ void default_hwif_mmiops (ide_hwif_t *hwif)
EXPORT_SYMBOL(default_hwif_mmiops);
-u32 ide_read_24 (ide_drive_t *drive)
-{
- u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG);
- u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG);
- u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG);
- return (hcyl<<16)|(lcyl<<8)|sect;
-}
-
void SELECT_DRIVE (ide_drive_t *drive)
{
if (HWIF(drive)->selectproc)
@@ -173,28 +163,12 @@ void SELECT_DRIVE (ide_drive_t *drive)
HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
}
-EXPORT_SYMBOL(SELECT_DRIVE);
-
-void SELECT_INTERRUPT (ide_drive_t *drive)
-{
- if (HWIF(drive)->intrproc)
- HWIF(drive)->intrproc(drive);
- else
- HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG);
-}
-
void SELECT_MASK (ide_drive_t *drive, int mask)
{
if (HWIF(drive)->maskproc)
HWIF(drive)->maskproc(drive, mask);
}
-void QUIRK_LIST (ide_drive_t *drive)
-{
- if (HWIF(drive)->quirkproc)
- drive->quirk_list = HWIF(drive)->quirkproc(drive);
-}
-
/*
* Some localbus EIDE interfaces require a special access sequence
* when using 32-bit I/O instructions to transfer data. We call this
@@ -303,9 +277,6 @@ void default_hwif_transport(ide_hwif_t *hwif)
hwif->atapi_output_bytes = atapi_output_bytes;
}
-/*
- * Beginning of Taskfile OPCODE Library and feature sets.
- */
void ide_fix_driveid (struct hd_driveid *id)
{
#ifndef __LITTLE_ENDIAN
@@ -403,8 +374,12 @@ void ide_fix_driveid (struct hd_driveid *id)
#endif
}
-/* FIXME: exported for use by the USB storage (isd200.c) code only */
-EXPORT_SYMBOL(ide_fix_driveid);
+/*
+ * 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 (u8 *s, const int bytecount, const int byteswap)
{
@@ -448,7 +423,6 @@ int drive_is_ready (ide_drive_t *drive)
udelay(1);
#endif
-#ifdef CONFIG_IDEPCI_SHARE_IRQ
/*
* We do a passive status test under shared PCI interrupts on
* cards that truly share the ATA side interrupt, but may also share
@@ -458,7 +432,6 @@ int drive_is_ready (ide_drive_t *drive)
if (IDE_CONTROL_REG)
stat = hwif->INB(IDE_ALTSTATUS_REG);
else
-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
/* Note: this may clear a pending IRQ!! */
stat = hwif->INB(IDE_STATUS_REG);
@@ -588,6 +561,9 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list);
static const struct drive_list_entry ivb_list[] = {
{ "QUANTUM FIREBALLlct10 05" , "A03.0900" },
{ "TSSTcorp CDDVDW SH-S202J" , "SB00" },
+ { "TSSTcorp CDDVDW SH-S202J" , "SB01" },
+ { "TSSTcorp CDDVDW SH-S202N" , "SB00" },
+ { "TSSTcorp CDDVDW SH-S202N" , "SB01" },
{ NULL , NULL }
};
@@ -608,12 +584,12 @@ u8 eighty_ninty_three (ide_drive_t *drive)
printk(KERN_DEBUG "%s: skipping word 93 validity check\n",
drive->name);
+ if (ide_dev_is_sata(id) && !ivb)
+ return 1;
+
if (hwif->cbl != ATA_CBL_PATA80 && !ivb)
goto no_80w;
- if (ide_dev_is_sata(id))
- return 1;
-
/*
* FIXME:
* - force bit13 (80c cable present) check also for !ivb devices
@@ -636,66 +612,6 @@ no_80w:
return 0;
}
-int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
-{
- if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
- (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&
- (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {
- if (eighty_ninty_three(drive) == 0) {
- printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
- "be set\n", drive->name);
- return 1;
- }
- }
-
- return 0;
-}
-
-/*
- * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
- * 1 : Safe to update drive->id DMA registers.
- * 0 : OOPs not allowed.
- */
-int set_transfer (ide_drive_t *drive, ide_task_t *args)
-{
- if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
- (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&
- (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&
- (drive->id->dma_ultra ||
- drive->id->dma_mword ||
- drive->id->dma_1word))
- return 1;
-
- return 0;
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static u8 ide_auto_reduce_xfer (ide_drive_t *drive)
-{
- if (!drive->crc_count)
- return drive->current_speed;
- drive->crc_count = 0;
-
- switch(drive->current_speed) {
- case XFER_UDMA_7: return XFER_UDMA_6;
- case XFER_UDMA_6: return XFER_UDMA_5;
- case XFER_UDMA_5: return XFER_UDMA_4;
- case XFER_UDMA_4: return XFER_UDMA_3;
- case XFER_UDMA_3: return XFER_UDMA_2;
- case XFER_UDMA_2: return XFER_UDMA_1;
- case XFER_UDMA_1: return XFER_UDMA_0;
- /*
- * OOPS we do not goto non Ultra DMA modes
- * without iCRC's available we force
- * the system to PIO and make the user
- * invoke the ATA-1 ATA-2 DMA modes.
- */
- case XFER_UDMA_0:
- default: return XFER_PIO_4;
- }
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
int ide_driveid_update(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
@@ -708,8 +624,7 @@ int ide_driveid_update(ide_drive_t *drive)
*/
SELECT_MASK(drive, 1);
- if (IDE_CONTROL_REG)
- hwif->OUTB(drive->ctl,IDE_CONTROL_REG);
+ ide_set_irq(drive, 1);
msleep(50);
hwif->OUTB(WIN_IDENTIFY, IDE_COMMAND_REG);
timeout = jiffies + WAIT_WORSTCASE;
@@ -744,6 +659,9 @@ int ide_driveid_update(ide_drive_t *drive)
drive->id->dma_1word = id->dma_1word;
/* anything more ? */
kfree(id);
+
+ if (drive->using_dma && ide_id_dma_bug(drive))
+ ide_dma_off(drive);
}
return 1;
@@ -752,17 +670,21 @@ int ide_driveid_update(ide_drive_t *drive)
int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
{
ide_hwif_t *hwif = drive->hwif;
- int error;
+ int error = 0;
u8 stat;
// while (HWGROUP(drive)->busy)
// msleep(50);
#ifdef CONFIG_BLK_DEV_IDEDMA
- if (hwif->ide_dma_on) /* check if host supports DMA */
- hwif->dma_host_off(drive);
+ if (hwif->dma_host_set) /* check if host supports DMA */
+ hwif->dma_host_set(drive, 0);
#endif
+ /* Skip setting PIO flow-control modes on pre-EIDE drives */
+ if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08))
+ goto skip;
+
/*
* Don't use ide_wait_cmd here - it will
* attempt to set_geometry and recalibrate,
@@ -785,13 +707,12 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
SELECT_DRIVE(drive);
SELECT_MASK(drive, 0);
udelay(1);
- if (IDE_CONTROL_REG)
- hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
+ ide_set_irq(drive, 0);
hwif->OUTB(speed, IDE_NSECTOR_REG);
hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG);
hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);
- if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+ if (drive->quirk_list == 2)
+ ide_set_irq(drive, 1);
error = __ide_wait_stat(drive, drive->ready_stat,
BUSY_STAT|DRQ_STAT|ERR_STAT,
@@ -810,11 +731,13 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
+ skip:
#ifdef CONFIG_BLK_DEV_IDEDMA
- if (speed >= XFER_SW_DMA_0)
- hwif->dma_host_on(drive);
- else if (hwif->ide_dma_on) /* check if host supports DMA */
- hwif->dma_off_quietly(drive);
+ if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
+ drive->using_dma)
+ hwif->dma_host_set(drive, 1);
+ else if (hwif->dma_host_set) /* check if host supports DMA */
+ ide_dma_off_quietly(drive);
#endif
switch(speed) {
@@ -890,28 +813,24 @@ EXPORT_SYMBOL(ide_set_handler);
* handler and IRQ setup do not race. All IDE command kick off
* should go via this function or do equivalent locking.
*/
-
-void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry)
+
+void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
+ unsigned timeout, ide_expiry_t *expiry)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
ide_hwif_t *hwif = HWIF(drive);
-
+
spin_lock_irqsave(&ide_lock, flags);
-
BUG_ON(hwgroup->handler);
- hwgroup->handler = handler;
- hwgroup->expiry = expiry;
- hwgroup->timer.expires = jiffies + timeout;
- hwgroup->req_gen_timer = hwgroup->req_gen;
- add_timer(&hwgroup->timer);
+ __ide_set_handler(drive, handler, timeout, expiry);
hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);
- /* Drive takes 400nS to respond, we must avoid the IRQ being
- serviced before that.
-
- FIXME: we could skip this delay with care on non shared
- devices
- */
+ /*
+ * Drive takes 400nS to respond, we must avoid the IRQ being
+ * serviced before that.
+ *
+ * FIXME: we could skip this delay with care on non shared devices
+ */
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -1019,19 +938,6 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
return ide_stopped;
}
-static void check_dma_crc(ide_drive_t *drive)
-{
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (drive->crc_count) {
- drive->hwif->dma_off_quietly(drive);
- ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));
- if (drive->current_speed >= XFER_SW_DMA_0)
- (void) HWIF(drive)->ide_dma_on(drive);
- } else
- ide_dma_off(drive);
-#endif
-}
-
static void ide_disk_pre_reset(ide_drive_t *drive)
{
int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
@@ -1039,8 +945,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
drive->special.all = 0;
drive->special.b.set_geometry = legacy;
drive->special.b.recalibrate = legacy;
- if (OK_TO_RESET_CONTROLLER)
- drive->mult_count = 0;
+ drive->mult_count = 0;
if (!drive->keep_settings && !drive->using_dma)
drive->mult_req = 0;
if (drive->mult_req != drive->mult_count)
@@ -1054,17 +959,20 @@ static void pre_reset(ide_drive_t *drive)
else
drive->post_reset = 1;
+ if (drive->using_dma) {
+ if (drive->crc_count)
+ ide_check_dma_crc(drive);
+ else
+ ide_dma_off(drive);
+ }
+
if (!drive->keep_settings) {
- if (drive->using_dma) {
- check_dma_crc(drive);
- } else {
+ if (!drive->using_dma) {
drive->unmask = 0;
drive->io_32bit = 0;
}
return;
}
- if (drive->using_dma)
- check_dma_crc(drive);
if (HWIF(drive)->pre_reset != NULL)
HWIF(drive)->pre_reset(drive);
@@ -1125,7 +1033,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
for (unit = 0; unit < MAX_DRIVES; ++unit)
pre_reset(&hwif->drives[unit]);
-#if OK_TO_RESET_CONTROLLER
if (!IDE_CONTROL_REG) {
spin_unlock_irqrestore(&ide_lock, flags);
return ide_stopped;
@@ -1162,11 +1069,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
* state when the disks are reset this way. At least, the Winbond
* 553 documentation says that
*/
- if (hwif->resetproc != NULL) {
+ if (hwif->resetproc)
hwif->resetproc(drive);
- }
-
-#endif /* OK_TO_RESET_CONTROLLER */
spin_unlock_irqrestore(&ide_lock, flags);
return ide_started;
@@ -1185,7 +1089,7 @@ EXPORT_SYMBOL(ide_do_reset);
/*
* ide_wait_not_busy() waits for the currently selected device on the hwif
- * to report a non-busy status, see comments in probe_hwif().
+ * to report a non-busy status, see comments in ide_probe_port().
*/
int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
{
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index af86433baed..b42940d8bf7 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -29,41 +29,44 @@
* Add common non I/O op stuff here. Make sure it has proper
* kernel-doc function headers or your patch will be rejected
*/
-
+
+static const char *udma_str[] =
+ { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
+ "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
+static const char *mwdma_str[] =
+ { "MWDMA0", "MWDMA1", "MWDMA2" };
+static const char *swdma_str[] =
+ { "SWDMA0", "SWDMA1", "SWDMA2" };
+static const char *pio_str[] =
+ { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
/**
* ide_xfer_verbose - return IDE mode names
- * @xfer_rate: rate to name
+ * @mode: transfer mode
*
* Returns a constant string giving the name of the mode
* requested.
*/
-char *ide_xfer_verbose (u8 xfer_rate)
+const char *ide_xfer_verbose(u8 mode)
{
- switch(xfer_rate) {
- case XFER_UDMA_7: return("UDMA 7");
- case XFER_UDMA_6: return("UDMA 6");
- case XFER_UDMA_5: return("UDMA 5");
- case XFER_UDMA_4: return("UDMA 4");
- case XFER_UDMA_3: return("UDMA 3");
- case XFER_UDMA_2: return("UDMA 2");
- case XFER_UDMA_1: return("UDMA 1");
- case XFER_UDMA_0: return("UDMA 0");
- case XFER_MW_DMA_2: return("MW DMA 2");
- case XFER_MW_DMA_1: return("MW DMA 1");
- case XFER_MW_DMA_0: return("MW DMA 0");
- case XFER_SW_DMA_2: return("SW DMA 2");
- case XFER_SW_DMA_1: return("SW DMA 1");
- case XFER_SW_DMA_0: return("SW DMA 0");
- case XFER_PIO_4: return("PIO 4");
- case XFER_PIO_3: return("PIO 3");
- case XFER_PIO_2: return("PIO 2");
- case XFER_PIO_1: return("PIO 1");
- case XFER_PIO_0: return("PIO 0");
- case XFER_PIO_SLOW: return("PIO SLOW");
- default: return("XFER ERROR");
- }
+ const char *s;
+ u8 i = mode & 0xf;
+
+ if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
+ s = udma_str[i];
+ else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
+ s = mwdma_str[i];
+ else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
+ s = swdma_str[i];
+ else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
+ s = pio_str[i & 0x7];
+ else if (mode == XFER_PIO_SLOW)
+ s = "PIO SLOW";
+ else
+ s = "XFER ERROR";
+
+ return s;
}
EXPORT_SYMBOL(ide_xfer_verbose);
@@ -355,8 +358,10 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
if (!PCI_DMA_BUS_IS_PHYS) {
addr = BLK_BOUNCE_ANY;
} else if (on && drive->media == ide_disk) {
- if (HWIF(drive)->pci_dev)
- addr = HWIF(drive)->pci_dev->dma_mask;
+ struct device *dev = drive->hwif->dev;
+
+ if (dev && dev->dma_mask)
+ addr = *dev->dma_mask;
}
if (drive->queue)
@@ -438,6 +443,12 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
* case could happen iff the transfer mode has already been set on
* the device by ide-proc.c::set_xfer_rate()).
*/
+ if (rate < XFER_PIO_0) {
+ if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
+ return ide_set_dma_mode(drive, rate);
+ else
+ return ide_config_drive_speed(drive, rate);
+ }
return ide_set_dma_mode(drive, rate);
}
@@ -445,8 +456,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
static void ide_dump_opcode(ide_drive_t *drive)
{
struct request *rq;
- u8 opcode = 0;
- int found = 0;
+ ide_task_t *task = NULL;
spin_lock(&ide_lock);
rq = NULL;
@@ -455,163 +465,129 @@ static void ide_dump_opcode(ide_drive_t *drive)
spin_unlock(&ide_lock);
if (!rq)
return;
- if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
- rq->cmd_type == REQ_TYPE_ATA_TASK) {
- char *args = rq->buffer;
- if (args) {
- opcode = args[0];
- found = 1;
- }
- } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
- ide_task_t *args = rq->special;
- if (args) {
- task_struct_t *tf = (task_struct_t *) args->tfRegister;
- opcode = tf->command;
- found = 1;
- }
- }
+
+ if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
+ task = rq->special;
printk("ide: failed opcode was: ");
- if (!found)
- printk("unknown\n");
+ if (task == NULL)
+ printk(KERN_CONT "unknown\n");
else
- printk("0x%02x\n", opcode);
+ printk(KERN_CONT "0x%02x\n", task->tf.command);
}
-static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
+u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
{
- ide_hwif_t *hwif = HWIF(drive);
- unsigned long flags;
- u8 err = 0;
+ u32 high, low;
- local_irq_save(flags);
- printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
- if (stat & BUSY_STAT)
- printk("Busy ");
- else {
- if (stat & READY_STAT) printk("DriveReady ");
- if (stat & WRERR_STAT) printk("DeviceFault ");
- if (stat & SEEK_STAT) printk("SeekComplete ");
- if (stat & DRQ_STAT) printk("DataRequest ");
- if (stat & ECC_STAT) printk("CorrectedError ");
- if (stat & INDEX_STAT) printk("Index ");
- if (stat & ERR_STAT) printk("Error ");
+ if (lba48)
+ high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) |
+ tf->hob_lbal;
+ else
+ high = tf->device & 0xf;
+ low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
+
+ return ((u64)high << 24) | low;
+}
+EXPORT_SYMBOL_GPL(ide_get_lba_addr);
+
+static void ide_dump_sector(ide_drive_t *drive)
+{
+ ide_task_t task;
+ struct ide_taskfile *tf = &task.tf;
+ int lba48 = (drive->addressing == 1) ? 1 : 0;
+
+ memset(&task, 0, sizeof(task));
+ if (lba48)
+ task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
+ IDE_TFLAG_LBA48;
+ else
+ task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
+
+ ide_tf_read(drive, &task);
+
+ if (lba48 || (tf->device & ATA_LBA))
+ printk(", LBAsect=%llu",
+ (unsigned long long)ide_get_lba_addr(tf, lba48));
+ else
+ printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
+ tf->device & 0xf, tf->lbal);
+}
+
+static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
+{
+ printk("{ ");
+ if (err & ABRT_ERR) printk("DriveStatusError ");
+ if (err & ICRC_ERR)
+ printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
+ if (err & ECC_ERR) printk("UncorrectableError ");
+ if (err & ID_ERR) printk("SectorIdNotFound ");
+ if (err & TRK0_ERR) printk("TrackZeroNotFound ");
+ if (err & MARK_ERR) printk("AddrMarkNotFound ");
+ printk("}");
+ if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
+ (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
+ ide_dump_sector(drive);
+ if (HWGROUP(drive) && HWGROUP(drive)->rq)
+ printk(", sector=%llu",
+ (unsigned long long)HWGROUP(drive)->rq->sector);
}
+ printk("\n");
+}
+
+static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
+{
+ printk("{ ");
+ if (err & ILI_ERR) printk("IllegalLengthIndication ");
+ if (err & EOM_ERR) printk("EndOfMedia ");
+ if (err & ABRT_ERR) printk("AbortedCommand ");
+ if (err & MCR_ERR) printk("MediaChangeRequested ");
+ if (err & LFS_ERR) printk("LastFailedSense=0x%02x ",
+ (err & LFS_ERR) >> 4);
printk("}\n");
- if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
- err = hwif->INB(IDE_ERROR_REG);
- printk("%s: %s: error=0x%02x { ", drive->name, msg, err);
- if (err & ABRT_ERR) printk("DriveStatusError ");
- if (err & ICRC_ERR)
- printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
- if (err & ECC_ERR) printk("UncorrectableError ");
- if (err & ID_ERR) printk("SectorIdNotFound ");
- if (err & TRK0_ERR) printk("TrackZeroNotFound ");
- if (err & MARK_ERR) printk("AddrMarkNotFound ");
- printk("}");
- if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
- (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
- if (drive->addressing == 1) {
- __u64 sectors = 0;
- u32 low = 0, high = 0;
- low = ide_read_24(drive);
- hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
- high = ide_read_24(drive);
- sectors = ((__u64)high << 24) | low;
- printk(", LBAsect=%llu, high=%d, low=%d",
- (unsigned long long) sectors,
- high, low);
- } else {
- u8 cur = hwif->INB(IDE_SELECT_REG);
- if (cur & 0x40) { /* using LBA? */
- printk(", LBAsect=%ld", (unsigned long)
- ((cur&0xf)<<24)
- |(hwif->INB(IDE_HCYL_REG)<<16)
- |(hwif->INB(IDE_LCYL_REG)<<8)
- | hwif->INB(IDE_SECTOR_REG));
- } else {
- printk(", CHS=%d/%d/%d",
- (hwif->INB(IDE_HCYL_REG)<<8) +
- hwif->INB(IDE_LCYL_REG),
- cur & 0xf,
- hwif->INB(IDE_SECTOR_REG));
- }
- }
- if (HWGROUP(drive) && HWGROUP(drive)->rq)
- printk(", sector=%llu",
- (unsigned long long)HWGROUP(drive)->rq->sector);
- }
- printk("\n");
- }
- ide_dump_opcode(drive);
- local_irq_restore(flags);
- return err;
}
/**
- * ide_dump_atapi_status - print human readable atapi status
+ * ide_dump_status - translate ATA/ATAPI error
* @drive: drive that status applies to
* @msg: text message to print
* @stat: status byte to decode
*
* Error reporting, in human readable form (luxurious, but a memory hog).
+ * Combines the drive name, message and status byte to provide a
+ * user understandable explanation of the device error.
*/
-static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
+u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
{
unsigned long flags;
+ u8 err = 0;
- atapi_status_t status;
- atapi_error_t error;
-
- status.all = stat;
- error.all = 0;
local_irq_save(flags);
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
- if (status.b.bsy)
+ if (stat & BUSY_STAT)
printk("Busy ");
else {
- if (status.b.drdy) printk("DriveReady ");
- if (status.b.df) printk("DeviceFault ");
- if (status.b.dsc) printk("SeekComplete ");
- if (status.b.drq) printk("DataRequest ");
- if (status.b.corr) printk("CorrectedError ");
- if (status.b.idx) printk("Index ");
- if (status.b.check) printk("Error ");
+ if (stat & READY_STAT) printk("DriveReady ");
+ if (stat & WRERR_STAT) printk("DeviceFault ");
+ if (stat & SEEK_STAT) printk("SeekComplete ");
+ if (stat & DRQ_STAT) printk("DataRequest ");
+ if (stat & ECC_STAT) printk("CorrectedError ");
+ if (stat & INDEX_STAT) printk("Index ");
+ if (stat & ERR_STAT) printk("Error ");
}
printk("}\n");
- if (status.b.check && !status.b.bsy) {
- error.all = HWIF(drive)->INB(IDE_ERROR_REG);
- printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all);
- if (error.b.ili) printk("IllegalLengthIndication ");
- if (error.b.eom) printk("EndOfMedia ");
- if (error.b.abrt) printk("AbortedCommand ");
- if (error.b.mcr) printk("MediaChangeRequested ");
- if (error.b.sense_key) printk("LastFailedSense=0x%02x ",
- error.b.sense_key);
- printk("}\n");
+ if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
+ err = drive->hwif->INB(IDE_ERROR_REG);
+ printk("%s: %s: error=0x%02x ", drive->name, msg, err);
+ if (drive->media == ide_disk)
+ ide_dump_ata_error(drive, err);
+ else
+ ide_dump_atapi_error(drive, err);
}
ide_dump_opcode(drive);
local_irq_restore(flags);
- return error.all;
-}
-
-/**
- * ide_dump_status - translate ATA/ATAPI error
- * @drive: drive the error occured on
- * @msg: information string
- * @stat: status byte
- *
- * Error reporting, in human readable form (luxurious, but a memory hog).
- * Combines the drive name, message and status byte to provide a
- * user understandable explanation of the device error.
- */
-
-u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
-{
- if (drive->media == ide_disk)
- return ide_dump_ata_status(drive, msg, stat);
- return ide_dump_atapi_status(drive, msg, stat);
+ return err;
}
EXPORT_SYMBOL(ide_dump_status);
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index e245521af7b..b163b2e5221 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/ide-pnp.c
- *
* This file provides autodetection for ISA PnP IDE interfaces.
* It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
*
@@ -31,7 +29,6 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
{
hw_regs_t hw;
ide_hwif_t *hwif;
- int index;
if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
return -1;
@@ -41,11 +38,19 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
pnp_port_start(dev, 1));
hw.irq = pnp_irq(dev, 0);
- index = ide_register_hw(&hw, NULL, 1, &hwif);
+ hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif) {
+ u8 index = hwif->index;
+ u8 idx[4] = { index, 0xff, 0xff, 0xff };
+
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
- if (index != -1) {
- printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
+ printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
pnp_set_drvdata(dev,hwif);
+
+ ide_device_add(idx, NULL);
+
return 0;
}
@@ -55,9 +60,10 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
static void idepnp_remove(struct pnp_dev * dev)
{
ide_hwif_t *hwif = pnp_get_drvdata(dev);
- if (hwif) {
- ide_unregister(hwif->index);
- } else
+
+ if (hwif)
+ ide_unregister(hwif->index, 0, 0);
+ else
printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
}
@@ -68,12 +74,15 @@ static struct pnp_driver idepnp_driver = {
.remove = idepnp_remove,
};
-void __init pnpide_init(void)
+static int __init pnpide_init(void)
{
- pnp_register_driver(&idepnp_driver);
+ return pnp_register_driver(&idepnp_driver);
}
-void __exit pnpide_exit(void)
+static void __exit pnpide_exit(void)
{
pnp_unregister_driver(&idepnp_driver);
}
+
+module_init(pnpide_init);
+module_exit(pnpide_exit);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 6a6f2e066b4..9c07bdb68d1 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1,7 +1,6 @@
/*
- * linux/drivers/ide/ide-probe.c Version 1.11 Mar 05, 2003
- *
- * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
+ * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
+ * Copyright (C) 2005, 2007 Bartlomiej Zolnierkiewicz
*/
/*
@@ -13,22 +12,8 @@
*
* This is the IDE probe module, as evolved from hd.c and ide.c.
*
- * Version 1.00 move drive probing code from ide.c to ide-probe.c
- * Version 1.01 fix compilation problem for m68k
- * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
- * by Andrea Arcangeli
- * Version 1.03 fix for (hwif->chipset == ide_4drives)
- * Version 1.04 fixed buggy treatments of known flash memory cards
- *
- * Version 1.05 fix for (hwif->chipset == ide_pdc4030)
- * added ide6/7/8/9
- * allowed for secondary flash card to be detectable
- * with new flag : drive->ata_flash : 1;
- * Version 1.06 stream line request queue and prep for cascade project.
- * Version 1.07 max_sect <= 255; slower disks would get behind and
- * then fall over when they get to 256. Paul G.
- * Version 1.10 Update set for new IDE. drive->id is now always
- * valid after probe time even with noprobe
+ * -- increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
+ * by Andrea Arcangeli
*/
#include <linux/module.h>
@@ -109,10 +94,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
#ifdef CONFIG_IDEDISK_MULTI_MODE
id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
id->multsect_valid = id->multsect ? 1 : 0;
- drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
+ drive->mult_req = id->multsect_valid ? id->max_multsect : 0;
drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
#else /* original, pre IDE-NFG, per request of AC */
- drive->mult_req = INITIAL_MULT_COUNT;
+ drive->mult_req = 0;
if (drive->mult_req > id->max_multsect)
drive->mult_req = id->max_multsect;
if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
@@ -143,6 +128,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
drive->id_read = 1;
local_irq_enable();
+#ifdef DEBUG
+ printk(KERN_INFO "%s: dumping identify data\n", drive->name);
+ ide_dump_identify((u8 *)id);
+#endif
ide_fix_driveid(id);
#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
@@ -172,11 +161,12 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap);
ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap);
+ /* we depend on this a lot! */
+ id->model[sizeof(id->model)-1] = '\0';
+
if (strstr(id->model, "E X A B Y T E N E S T"))
goto err_misc;
- /* we depend on this a lot! */
- id->model[sizeof(id->model)-1] = '\0';
printk("%s: %s, ", drive->name, id->model);
drive->present = 1;
drive->dead = 0;
@@ -247,7 +237,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
drive->media = ide_disk;
printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
- QUIRK_LIST(drive);
+
return;
err_misc:
@@ -363,22 +353,19 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
* the irq handler isn't expecting.
*/
if (IDE_CONTROL_REG) {
- u8 ctl = drive->ctl | 2;
if (!hwif->irq) {
autoprobe = 1;
cookie = probe_irq_on();
- /* enable device irq */
- ctl &= ~2;
}
- hwif->OUTB(ctl, IDE_CONTROL_REG);
+ ide_set_irq(drive, autoprobe);
}
retval = actual_try_to_identify(drive, cmd);
if (autoprobe) {
int irq;
- /* mask device irq */
- hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);
+
+ ide_set_irq(drive, 0);
/* clear drive IRQ */
(void) hwif->INB(IDE_STATUS_REG);
udelay(5);
@@ -398,6 +385,20 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
return retval;
}
+static int ide_busy_sleep(ide_hwif_t *hwif)
+{
+ unsigned long timeout = jiffies + WAIT_WORSTCASE;
+ u8 stat;
+
+ do {
+ msleep(50);
+ stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ if ((stat & BUSY_STAT) == 0)
+ return 0;
+ } while (time_before(jiffies, timeout));
+
+ return 1;
+}
/**
* do_probe - probe an IDE device
@@ -422,8 +423,9 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
static int do_probe (ide_drive_t *drive, u8 cmd)
{
- int rc;
ide_hwif_t *hwif = HWIF(drive);
+ int rc;
+ u8 stat;
if (drive->present) {
/* avoid waiting for inappropriate probes */
@@ -460,31 +462,31 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
/* failed: try again */
rc = try_to_identify(drive,cmd);
}
- if (hwif->INB(IDE_STATUS_REG) == (BUSY_STAT|READY_STAT))
+
+ stat = hwif->INB(IDE_STATUS_REG);
+
+ if (stat == (BUSY_STAT | READY_STAT))
return 4;
if ((rc == 1 && cmd == WIN_PIDENTIFY) &&
((drive->autotune == IDE_TUNE_DEFAULT) ||
(drive->autotune == IDE_TUNE_AUTO))) {
- unsigned long timeout;
- printk("%s: no response (status = 0x%02x), "
- "resetting drive\n", drive->name,
- hwif->INB(IDE_STATUS_REG));
+ printk(KERN_ERR "%s: no response (status = 0x%02x), "
+ "resetting drive\n", drive->name, stat);
msleep(50);
hwif->OUTB(drive->select.all, IDE_SELECT_REG);
msleep(50);
hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
- timeout = jiffies;
- while (((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) &&
- time_before(jiffies, timeout + WAIT_WORSTCASE))
- msleep(50);
+ (void)ide_busy_sleep(hwif);
rc = try_to_identify(drive, cmd);
}
+
+ /* ensure drive IRQ is clear */
+ stat = hwif->INB(IDE_STATUS_REG);
+
if (rc == 1)
- printk("%s: no response (status = 0x%02x)\n",
- drive->name, hwif->INB(IDE_STATUS_REG));
- /* ensure drive irq is clear */
- (void) hwif->INB(IDE_STATUS_REG);
+ printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
+ drive->name, stat);
} else {
/* not present or maybe ATAPI */
rc = 3;
@@ -505,28 +507,26 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
static void enable_nest (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned long timeout;
+ u8 stat;
printk("%s: enabling %s -- ", hwif->name, drive->id->model);
SELECT_DRIVE(drive);
msleep(50);
hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
- timeout = jiffies + WAIT_WORSTCASE;
- do {
- if (time_after(jiffies, timeout)) {
- printk("failed (timeout)\n");
- return;
- }
- msleep(50);
- } while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT);
+
+ if (ide_busy_sleep(hwif)) {
+ printk(KERN_CONT "failed (timeout)\n");
+ return;
+ }
msleep(50);
- if (!OK_STAT((hwif->INB(IDE_STATUS_REG)), 0, BAD_STAT)) {
- printk("failed (status = 0x%02x)\n", hwif->INB(IDE_STATUS_REG));
- } else {
- printk("success\n");
- }
+ stat = hwif->INB(IDE_STATUS_REG);
+
+ if (!OK_STAT(stat, 0, BAD_STAT))
+ printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
+ else
+ printk(KERN_CONT "success\n");
/* if !(success||timed-out) */
if (do_probe(drive, WIN_IDENTIFY) >= 2) {
@@ -620,7 +620,7 @@ static void hwif_release_dev (struct device *dev)
complete(&hwif->gendev_rel_comp);
}
-static void hwif_register (ide_hwif_t *hwif)
+static void ide_register_port(ide_hwif_t *hwif)
{
int ret;
@@ -628,8 +628,8 @@ static void hwif_register (ide_hwif_t *hwif)
strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE);
hwif->gendev.driver_data = hwif;
if (hwif->gendev.parent == NULL) {
- if (hwif->pci_dev)
- hwif->gendev.parent = &hwif->pci_dev->dev;
+ if (hwif->dev)
+ hwif->gendev.parent = hwif->dev;
else
/* Would like to do = &device_legacy */
hwif->gendev.parent = NULL;
@@ -641,9 +641,35 @@ static void hwif_register (ide_hwif_t *hwif)
__FUNCTION__, ret);
}
-static int wait_hwif_ready(ide_hwif_t *hwif)
+/**
+ * ide_port_wait_ready - wait for port to become ready
+ * @hwif: IDE port
+ *
+ * This is needed on some PPCs and a bunch of BIOS-less embedded
+ * platforms. Typical cases are:
+ *
+ * - The firmware hard reset the disk before booting the kernel,
+ * the drive is still doing it's poweron-reset sequence, that
+ * can take up to 30 seconds.
+ *
+ * - The firmware does nothing (or no firmware), the device is
+ * still in POST state (same as above actually).
+ *
+ * - Some CD/DVD/Writer combo drives tend to drive the bus during
+ * their reset sequence even when they are non-selected slave
+ * devices, thus preventing discovery of the main HD.
+ *
+ * Doing this wait-for-non-busy should not harm any existing
+ * configuration and fix some issues like the above.
+ *
+ * BenH.
+ *
+ * Returns 0 on success, error code (< 0) otherwise.
+ */
+
+static int ide_port_wait_ready(ide_hwif_t *hwif)
{
- int rc;
+ int unit, rc;
printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name);
@@ -660,38 +686,43 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
return rc;
/* Now make sure both master & slave are ready */
- SELECT_DRIVE(&hwif->drives[0]);
- hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
- mdelay(2);
- rc = ide_wait_not_busy(hwif, 35000);
- if (rc)
- return rc;
- SELECT_DRIVE(&hwif->drives[1]);
- hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
- mdelay(2);
- rc = ide_wait_not_busy(hwif, 35000);
+ for (unit = 0; unit < MAX_DRIVES; unit++) {
+ ide_drive_t *drive = &hwif->drives[unit];
+ /* Ignore disks that we will not probe for later. */
+ if (!drive->noprobe || drive->present) {
+ SELECT_DRIVE(drive);
+ ide_set_irq(drive, 1);
+ mdelay(2);
+ rc = ide_wait_not_busy(hwif, 35000);
+ if (rc)
+ goto out;
+ } else
+ printk(KERN_DEBUG "%s: ide_wait_not_busy() skipped\n",
+ drive->name);
+ }
+out:
/* Exit function with master reselected (let's be sane) */
- SELECT_DRIVE(&hwif->drives[0]);
-
+ if (unit)
+ SELECT_DRIVE(&hwif->drives[0]);
+
return rc;
}
/**
* ide_undecoded_slave - look for bad CF adapters
- * @hwif: interface
+ * @drive1: drive
*
* Analyse the drives on the interface and attempt to decide if we
* have the same drive viewed twice. This occurs with crap CF adapters
* and PCMCIA sometimes.
*/
-void ide_undecoded_slave(ide_hwif_t *hwif)
+void ide_undecoded_slave(ide_drive_t *drive1)
{
- ide_drive_t *drive0 = &hwif->drives[0];
- ide_drive_t *drive1 = &hwif->drives[1];
+ ide_drive_t *drive0 = &drive1->hwif->drives[0];
- if (drive0->present == 0 || drive1->present == 0)
+ if ((drive1->dn & 1) == 0 || drive0->present == 0)
return;
/* If the models don't match they are not the same product */
@@ -714,36 +745,16 @@ void ide_undecoded_slave(ide_hwif_t *hwif)
EXPORT_SYMBOL_GPL(ide_undecoded_slave);
-/*
- * 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.
- */
-static void probe_hwif(ide_hwif_t *hwif)
+static int ide_probe_port(ide_hwif_t *hwif)
{
unsigned long flags;
unsigned int irqd;
- int unit;
+ int unit, rc = -ENODEV;
- if (hwif->noprobe)
- return;
+ BUG_ON(hwif->present);
- if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) &&
- (ide_hwif_request_regions(hwif))) {
- u16 msgout = 0;
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present) {
- drive->present = 0;
- printk(KERN_ERR "%s: ERROR, PORTS ALREADY IN USE\n",
- drive->name);
- msgout = 1;
- }
- }
- if (!msgout)
- printk(KERN_ERR "%s: ports already in use, skipping probe\n",
- hwif->name);
- return;
- }
+ if (hwif->noprobe)
+ return -EACCES;
/*
* We must always disable IRQ, as probe_for_drive will assert IRQ, but
@@ -755,26 +766,7 @@ static void probe_hwif(ide_hwif_t *hwif)
local_irq_set(flags);
- /* This is needed on some PPCs and a bunch of BIOS-less embedded
- * platforms. Typical cases are:
- *
- * - The firmware hard reset the disk before booting the kernel,
- * the drive is still doing it's poweron-reset sequence, that
- * can take up to 30 seconds
- * - The firmware does nothing (or no firmware), the device is
- * still in POST state (same as above actually).
- * - Some CD/DVD/Writer combo drives tend to drive the bus during
- * their reset sequence even when they are non-selected slave
- * devices, thus preventing discovery of the main HD
- *
- * Doing this wait-for-busy should not harm any existing configuration
- * (at least things won't be worse than what current code does, that
- * is blindly go & talk to the drive) and fix some issues like the
- * above.
- *
- * BenH.
- */
- if (wait_hwif_ready(hwif) == -EBUSY)
+ if (ide_port_wait_ready(hwif) == -EBUSY)
printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
/*
@@ -784,28 +776,15 @@ static void probe_hwif(ide_hwif_t *hwif)
ide_drive_t *drive = &hwif->drives[unit];
drive->dn = (hwif->channel ? 2 : 0) + unit;
(void) probe_for_drive(drive);
- if (drive->present && !hwif->present) {
- hwif->present = 1;
- if (hwif->chipset != ide_4drives ||
- !hwif->mate ||
- !hwif->mate->present) {
- hwif_register(hwif);
- }
- }
+ if (drive->present)
+ rc = 0;
}
if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
- unsigned long timeout = jiffies + WAIT_WORSTCASE;
- u8 stat;
-
printk(KERN_WARNING "%s: reset\n", hwif->name);
hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
udelay(10);
hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
- do {
- msleep(50);
- stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
- } while ((stat & BUSY_STAT) && time_after(timeout, jiffies));
-
+ (void)ide_busy_sleep(hwif);
}
local_irq_restore(flags);
/*
@@ -815,13 +794,19 @@ static void probe_hwif(ide_hwif_t *hwif)
if (irqd)
enable_irq(irqd);
- if (!hwif->present) {
- ide_hwif_release_regions(hwif);
- return;
- }
+ return rc;
+}
+
+static void ide_port_tune_devices(ide_hwif_t *hwif)
+{
+ int unit;
+
+ for (unit = 0; unit < MAX_DRIVES; unit++) {
+ ide_drive_t *drive = &hwif->drives[unit];
- if (hwif->fixup)
- hwif->fixup(hwif);
+ if (drive->present && hwif->quirkproc)
+ hwif->quirkproc(drive);
+ }
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
@@ -836,48 +821,21 @@ static void probe_hwif(ide_hwif_t *hwif)
drive->nice1 = 1;
- if (hwif->ide_dma_on) {
- /*
- * Force DMAing for the beginning of the check.
- * Some chipsets appear to do interesting
- * things, if not checked and cleared.
- * PARANOIA!!!
- */
- hwif->dma_off_quietly(drive);
+ if (hwif->dma_host_set)
ide_set_dma(drive);
- }
}
}
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- if (hwif->no_io_32bit)
+ if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
drive->no_io_32bit = 1;
else
drive->no_io_32bit = drive->id->dword_io ? 1 : 0;
}
}
-static int hwif_init(ide_hwif_t *hwif);
-static void hwif_register_devices(ide_hwif_t *hwif);
-
-static int probe_hwif_init(ide_hwif_t *hwif)
-{
- probe_hwif(hwif);
-
- if (!hwif_init(hwif)) {
- printk(KERN_INFO "%s: failed to initialize IDE interface\n",
- hwif->name);
- return -1;
- }
-
- if (hwif->present)
- hwif_register_devices(hwif);
-
- return 0;
-}
-
#if MAX_HWIFS > 1
/*
* save_match() is used to simplify logic in init_irq() below.
@@ -930,13 +888,6 @@ static int ide_init_queue(ide_drive_t *drive)
q->queuedata = drive;
blk_queue_segment_boundary(q, 0xffff);
- if (!hwif->rqsize) {
- if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
- (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
- hwif->rqsize = 256;
- else
- hwif->rqsize = 65536;
- }
if (hwif->rqsize < max_sectors)
max_sectors = hwif->rqsize;
blk_queue_max_sectors(q, max_sectors);
@@ -967,6 +918,48 @@ static int ide_init_queue(ide_drive_t *drive)
return 0;
}
+static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
+{
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+
+ spin_lock_irq(&ide_lock);
+ if (!hwgroup->drive) {
+ /* first drive for hwgroup. */
+ drive->next = drive;
+ hwgroup->drive = drive;
+ hwgroup->hwif = HWIF(hwgroup->drive);
+ } else {
+ drive->next = hwgroup->drive->next;
+ hwgroup->drive->next = drive;
+ }
+ spin_unlock_irq(&ide_lock);
+}
+
+/*
+ * For any present drive:
+ * - allocate the block device queue
+ * - link drive into the hwgroup
+ */
+static void ide_port_setup_devices(ide_hwif_t *hwif)
+{
+ int i;
+
+ for (i = 0; i < MAX_DRIVES; i++) {
+ ide_drive_t *drive = &hwif->drives[i];
+
+ if (!drive->present)
+ continue;
+
+ if (ide_init_queue(drive)) {
+ printk(KERN_ERR "ide: failed to init %s\n",
+ drive->name);
+ continue;
+ }
+
+ ide_add_drive_to_hwgroup(drive);
+ }
+}
+
/*
* This routine sets up the irq for an ide interface, and creates a new
* hwgroup for the irq/hwif if none was previously assigned.
@@ -974,11 +967,6 @@ static int ide_init_queue(ide_drive_t *drive)
* Much of the code is for correctly detecting/handling irq sharing
* and irq serialization situations. This is somewhat complex because
* it handles static as well as dynamic (PCMCIA) IDE interfaces.
- *
- * The IRQF_DISABLED in sa_flags means ide_intr() is always entered with
- * interrupts completely disabled. This can be bad for interrupt latency,
- * but anything else has led to problems on some machines. We re-enable
- * interrupts as much as we can safely do in most places.
*/
static int init_irq (ide_hwif_t *hwif)
{
@@ -1037,21 +1025,17 @@ static int init_irq (ide_hwif_t *hwif)
spin_lock_irq(&ide_lock);
hwif->next = hwgroup->hwif->next;
hwgroup->hwif->next = hwif;
+ BUG_ON(hwif->next == hwif);
spin_unlock_irq(&ide_lock);
} else {
- hwgroup = kmalloc_node(sizeof(ide_hwgroup_t),
- GFP_KERNEL | __GFP_ZERO,
- hwif_to_node(hwif->drives[0].hwif));
- if (!hwgroup)
- goto out_up;
+ hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO,
+ hwif_to_node(hwif));
+ if (hwgroup == NULL)
+ goto out_up;
hwif->hwgroup = hwgroup;
+ hwgroup->hwif = hwif->next = hwif;
- hwgroup->hwif = hwif->next = hwif;
- hwgroup->rq = NULL;
- hwgroup->handler = NULL;
- hwgroup->drive = NULL;
- hwgroup->busy = 0;
init_timer(&hwgroup->timer);
hwgroup->timer.function = &ide_timer_expiry;
hwgroup->timer.data = (unsigned long) hwgroup;
@@ -1061,17 +1045,13 @@ static int init_irq (ide_hwif_t *hwif)
* Allocate the irq, if not already obtained for another hwif
*/
if (!match || match->irq != hwif->irq) {
- int sa = IRQF_DISABLED;
+ int sa = 0;
#if defined(__mc68000__) || defined(CONFIG_APUS)
sa = IRQF_SHARED;
#endif /* __mc68000__ || CONFIG_APUS */
- if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {
+ if (IDE_CHIPSET_IS_PCI(hwif->chipset))
sa = IRQF_SHARED;
-#ifndef CONFIG_IDEPCI_SHARE_IRQ
- sa |= IRQF_DISABLED;
-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
- }
if (hwif->io_ports[IDE_CONTROL_OFFSET])
/* clear nIEN */
@@ -1081,30 +1061,12 @@ static int init_irq (ide_hwif_t *hwif)
goto out_unlink;
}
- /*
- * For any present drive:
- * - allocate the block device queue
- * - link drive into the hwgroup
- */
- for (index = 0; index < MAX_DRIVES; ++index) {
- ide_drive_t *drive = &hwif->drives[index];
- if (!drive->present)
- continue;
- if (ide_init_queue(drive)) {
- printk(KERN_ERR "ide: failed to init %s\n",drive->name);
- continue;
- }
- spin_lock_irq(&ide_lock);
- if (!hwgroup->drive) {
- /* first drive for hwgroup. */
- drive->next = drive;
- hwgroup->drive = drive;
- hwgroup->hwif = HWIF(hwgroup->drive);
- } else {
- drive->next = hwgroup->drive->next;
- hwgroup->drive->next = drive;
- }
- spin_unlock_irq(&ide_lock);
+ if (!hwif->rqsize) {
+ if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+ (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
+ hwif->rqsize = 256;
+ else
+ hwif->rqsize = 65536;
}
#if !defined(__mc68000__) && !defined(CONFIG_APUS)
@@ -1120,28 +1082,13 @@ static int init_irq (ide_hwif_t *hwif)
printk(" (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name);
printk("\n");
+
+ ide_port_setup_devices(hwif);
+
mutex_unlock(&ide_cfg_mtx);
return 0;
out_unlink:
- spin_lock_irq(&ide_lock);
- if (hwif->next == hwif) {
- BUG_ON(match);
- BUG_ON(hwgroup->hwif != hwif);
- kfree(hwgroup);
- } else {
- ide_hwif_t *g;
- g = hwgroup->hwif;
- while (g->next != hwif)
- g = g->next;
- g->next = hwif->next;
- if (hwgroup->hwif == hwif) {
- /* Impossible. */
- printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n");
- hwgroup->hwif = g;
- }
- BUG_ON(hwgroup->hwif == hwif);
- }
- spin_unlock_irq(&ide_lock);
+ ide_remove_port_from_hwgroup(hwif);
out_up:
mutex_unlock(&ide_cfg_mtx);
return 1;
@@ -1179,7 +1126,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data)
{
struct gendisk *p = data;
*part &= (1 << PARTN_BITS) - 1;
- return &p->kobj;
+ return &p->dev.kobj;
}
static int exact_lock(dev_t dev, void *data)
@@ -1262,56 +1209,25 @@ static void drive_release_dev (struct device *dev)
complete(&drive->gendev_rel_comp);
}
-/*
- * init_gendisk() (as opposed to ide_geninit) is called for each major device,
- * after probing for drives, to allocate partition tables and other data
- * structures needed for the routines in genhd.c. ide_geninit() gets called
- * somewhat later, during the partition check.
- */
-static void init_gendisk (ide_hwif_t *hwif)
-{
- unsigned int unit;
-
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t * drive = &hwif->drives[unit];
- ide_add_generic_settings(drive);
- snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u",
- hwif->index,unit);
- drive->gendev.parent = &hwif->gendev;
- drive->gendev.bus = &ide_bus_type;
- drive->gendev.driver_data = drive;
- drive->gendev.release = drive_release_dev;
- }
- blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
- THIS_MODULE, ata_probe, ata_lock, hwif);
-}
-
static int hwif_init(ide_hwif_t *hwif)
{
int old_irq;
- /* Return success if no device is connected */
- if (!hwif->present)
- return 1;
-
if (!hwif->irq) {
if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
{
printk("%s: DISABLED, NO IRQ\n", hwif->name);
- return (hwif->present = 0);
+ return 0;
}
}
#ifdef CONFIG_BLK_DEV_HD
if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
printk("%s: CANNOT SHARE IRQ WITH OLD "
"HARDDISK DRIVER (hd.c)\n", hwif->name);
- return (hwif->present = 0);
+ return 0;
}
#endif /* CONFIG_BLK_DEV_HD */
- /* we set it back to 1 if all is ok below */
- hwif->present = 0;
-
if (register_blkdev(hwif->major, hwif->name))
return 0;
@@ -1349,11 +1265,8 @@ static int hwif_init(ide_hwif_t *hwif)
hwif->name, hwif->irq);
done:
- init_gendisk(hwif);
-
- ide_acpi_init(hwif);
-
- hwif->present = 1; /* success */
+ blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
+ THIS_MODULE, ata_probe, ata_lock, hwif);
return 1;
out:
@@ -1367,66 +1280,204 @@ static void hwif_register_devices(ide_hwif_t *hwif)
for (i = 0; i < MAX_DRIVES; i++) {
ide_drive_t *drive = &hwif->drives[i];
+ struct device *dev = &drive->gendev;
+ int ret;
- if (drive->present) {
- int ret = device_register(&drive->gendev);
+ if (!drive->present)
+ continue;
- if (ret < 0)
- printk(KERN_WARNING "IDE: %s: "
- "device_register error: %d\n",
- __FUNCTION__, ret);
- }
+ ide_add_generic_settings(drive);
+
+ snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
+ dev->parent = &hwif->gendev;
+ dev->bus = &ide_bus_type;
+ dev->driver_data = drive;
+ dev->release = drive_release_dev;
+
+ ret = device_register(dev);
+ if (ret < 0)
+ printk(KERN_WARNING "IDE: %s: device_register error: "
+ "%d\n", __func__, ret);
}
}
-int ideprobe_init (void)
+static void ide_port_init_devices(ide_hwif_t *hwif)
{
- unsigned int index;
- int probe[MAX_HWIFS];
-
- memset(probe, 0, MAX_HWIFS * sizeof(int));
- for (index = 0; index < MAX_HWIFS; ++index)
- probe[index] = !ide_hwifs[index].present;
-
- for (index = 0; index < MAX_HWIFS; ++index)
- if (probe[index])
- probe_hwif(&ide_hwifs[index]);
- for (index = 0; index < MAX_HWIFS; ++index)
- if (probe[index])
- hwif_init(&ide_hwifs[index]);
- for (index = 0; index < MAX_HWIFS; ++index) {
- if (probe[index]) {
- ide_hwif_t *hwif = &ide_hwifs[index];
- if (!hwif->present)
- continue;
- if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced)
- hwif->chipset = ide_generic;
- hwif_register_devices(hwif);
- }
+ int i;
+
+ for (i = 0; i < MAX_DRIVES; i++) {
+ ide_drive_t *drive = &hwif->drives[i];
+
+ if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
+ drive->io_32bit = 1;
+ if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS)
+ drive->unmask = 1;
+ if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
+ drive->no_unmask = 1;
+ if ((hwif->host_flags & IDE_HFLAG_NO_AUTOTUNE) == 0)
+ drive->autotune = 1;
}
- for (index = 0; index < MAX_HWIFS; ++index)
- if (probe[index])
- ide_proc_register_port(&ide_hwifs[index]);
- return 0;
+
+ if (hwif->port_init_devs)
+ hwif->port_init_devs(hwif);
}
-EXPORT_SYMBOL_GPL(ideprobe_init);
+static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
+ const struct ide_port_info *d)
+{
+ if (d->chipset != ide_etrax100)
+ hwif->channel = port;
+
+ if (d->chipset)
+ hwif->chipset = d->chipset;
+
+ if (d->init_iops)
+ d->init_iops(hwif);
+
+ if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
+ ide_hwif_setup_dma(hwif, d);
+
+ if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
+ (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
+ hwif->irq = port ? 15 : 14;
+
+ hwif->host_flags = d->host_flags;
+ hwif->pio_mask = d->pio_mask;
+
+ if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
+ hwif->mate->serialized = hwif->serialized = 1;
+
+ hwif->swdma_mask = d->swdma_mask;
+ hwif->mwdma_mask = d->mwdma_mask;
+ hwif->ultra_mask = d->udma_mask;
+
+ /* reset DMA masks only for SFF-style DMA controllers */
+ if ((d->host_flags && IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0)
+ hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0;
+
+ if (d->host_flags & IDE_HFLAG_RQSIZE_256)
+ hwif->rqsize = 256;
+
+ /* call chipset specific routine for each enabled port */
+ if (d->init_hwif)
+ d->init_hwif(hwif);
+
+ if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = hwif->cable_detect(hwif);
+ }
+}
-int ide_device_add(u8 idx[4])
+int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
{
+ ide_hwif_t *hwif, *mate = NULL;
int i, rc = 0;
- for (i = 0; i < 4; i++) {
- if (idx[i] != 0xff)
- rc |= probe_hwif_init(&ide_hwifs[idx[i]]);
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (d == NULL || idx[i] == 0xff) {
+ mate = NULL;
+ continue;
+ }
+
+ hwif = &ide_hwifs[idx[i]];
+
+ if (d->chipset != ide_etrax100 && (i & 1) && mate) {
+ hwif->mate = mate;
+ mate->mate = hwif;
+ }
+
+ mate = (i & 1) ? NULL : hwif;
+
+ ide_init_port(hwif, i & 1, d);
+ ide_port_init_devices(hwif);
+ }
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (idx[i] == 0xff)
+ continue;
+
+ hwif = &ide_hwifs[idx[i]];
+
+ if ((hwif->chipset != ide_4drives || !hwif->mate ||
+ !hwif->mate->present) && ide_hwif_request_regions(hwif)) {
+ printk(KERN_ERR "%s: ports already in use, "
+ "skipping probe\n", hwif->name);
+ continue;
+ }
+
+ if (ide_probe_port(hwif) < 0) {
+ ide_hwif_release_regions(hwif);
+ continue;
+ }
+
+ hwif->present = 1;
+
+ if (hwif->chipset != ide_4drives || !hwif->mate ||
+ !hwif->mate->present)
+ ide_register_port(hwif);
+
+ ide_port_tune_devices(hwif);
+ }
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (idx[i] == 0xff)
+ continue;
+
+ hwif = &ide_hwifs[idx[i]];
+
+ if (!hwif->present)
+ continue;
+
+ if (hwif_init(hwif) == 0) {
+ printk(KERN_INFO "%s: failed to initialize IDE "
+ "interface\n", hwif->name);
+ hwif->present = 0;
+ rc = -1;
+ continue;
+ }
+
+ ide_acpi_init(hwif);
+ ide_acpi_port_init_devices(hwif);
}
- for (i = 0; i < 4; i++) {
- if (idx[i] != 0xff)
- ide_proc_register_port(&ide_hwifs[idx[i]]);
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (idx[i] == 0xff)
+ continue;
+
+ hwif = &ide_hwifs[idx[i]];
+
+ if (hwif->present) {
+ if (hwif->chipset == ide_unknown ||
+ hwif->chipset == ide_forced)
+ hwif->chipset = ide_generic;
+ hwif_register_devices(hwif);
+ }
+ }
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (idx[i] == 0xff)
+ continue;
+
+ hwif = &ide_hwifs[idx[i]];
+
+ if (hwif->present) {
+ ide_proc_register_port(hwif);
+ ide_proc_port_register_devices(hwif);
+ }
}
return rc;
}
+EXPORT_SYMBOL_GPL(ide_device_add_all);
+int ide_device_add(u8 idx[4], const struct ide_port_info *d)
+{
+ u8 idx_all[MAX_HWIFS];
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++)
+ idx_all[i] = (i < 4) ? idx[i] : 0xff;
+
+ return ide_device_add_all(idx_all, d);
+}
EXPORT_SYMBOL_GPL(ide_device_add);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index a4007d30da5..975c0ff0f43 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/ide-proc.c Version 1.05 Mar 05, 2003
- *
* Copyright (C) 1997-1998 Mark Lord
* Copyright (C) 2003 Red Hat <alan@redhat.com>
*
@@ -346,14 +344,20 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va
static int set_xfer_rate (ide_drive_t *drive, int arg)
{
+ ide_task_t task;
int err;
if (arg < 0 || arg > 70)
return -EINVAL;
- err = ide_wait_cmd(drive,
- WIN_SETFEATURES, (u8) arg,
- SETFEATURES_XFER, 0, NULL);
+ memset(&task, 0, sizeof(task));
+ task.tf.command = WIN_SETFEATURES;
+ task.tf.feature = SETFEATURES_XFER;
+ task.tf.nsect = (u8)arg;
+ task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
+ IDE_TFLAG_IN_NSECT;
+
+ err = ide_no_data_taskfile(drive, &task);
if (!err && arg) {
ide_set_xfer_rate(drive, (u8) arg);
@@ -735,7 +739,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
EXPORT_SYMBOL(ide_proc_unregister_driver);
-static void create_proc_ide_drives(ide_hwif_t *hwif)
+void ide_proc_port_register_devices(ide_hwif_t *hwif)
{
int d;
struct proc_dir_entry *ent;
@@ -789,9 +793,6 @@ static ide_proc_entry_t hwif_entries[] = {
void ide_proc_register_port(ide_hwif_t *hwif)
{
- if (!hwif->present)
- return;
-
if (!hwif->proc) {
hwif->proc = proc_mkdir(hwif->name, proc_ide_root);
@@ -800,8 +801,6 @@ void ide_proc_register_port(ide_hwif_t *hwif)
ide_add_proc_entries(hwif->proc, hwif_entries, hwif);
}
-
- create_proc_ide_drives(hwif);
}
#ifdef CONFIG_BLK_DEV_IDEPCI
diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c
new file mode 100644
index 00000000000..93d2e41be85
--- /dev/null
+++ b/drivers/ide/ide-scan-pci.c
@@ -0,0 +1,116 @@
+/*
+ * support for probing IDE PCI devices in the PCI bus order
+ *
+ * Copyright (c) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (c) 1995-1998 Mark Lord
+ *
+ * May be copied or modified under the terms of the GNU General Public License
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ide.h>
+
+/*
+ * Module interfaces
+ */
+
+static int pre_init = 1; /* Before first ordered IDE scan */
+static LIST_HEAD(ide_pci_drivers);
+
+/*
+ * __ide_pci_register_driver - attach IDE driver
+ * @driver: pci driver
+ * @module: owner module of the driver
+ *
+ * Registers a driver with the IDE layer. The IDE layer arranges that
+ * boot time setup is done in the expected device order and then
+ * hands the controllers off to the core PCI code to do the rest of
+ * the work.
+ *
+ * Returns are the same as for pci_register_driver
+ */
+
+int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
+ const char *mod_name)
+{
+ if (!pre_init)
+ return __pci_register_driver(driver, module, mod_name);
+ driver->driver.owner = module;
+ list_add_tail(&driver->node, &ide_pci_drivers);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
+
+/**
+ * ide_scan_pcidev - find an IDE driver for a device
+ * @dev: PCI device to check
+ *
+ * Look for an IDE driver to handle the device we are considering.
+ * This is only used during boot up to get the ordering correct. After
+ * boot up the pci layer takes over the job.
+ */
+
+static int __init ide_scan_pcidev(struct pci_dev *dev)
+{
+ struct list_head *l;
+ struct pci_driver *d;
+
+ list_for_each(l, &ide_pci_drivers) {
+ d = list_entry(l, struct pci_driver, node);
+ if (d->id_table) {
+ const struct pci_device_id *id =
+ pci_match_id(d->id_table, dev);
+
+ if (id != NULL && d->probe(dev, id) >= 0) {
+ dev->driver = d;
+ pci_dev_get(dev);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * ide_scan_pcibus - perform the initial IDE driver scan
+ *
+ * Perform the initial bus rather than driver ordered scan of the
+ * PCI drivers. After this all IDE pci handling becomes standard
+ * module ordering not traditionally ordered.
+ */
+
+static int __init ide_scan_pcibus(void)
+{
+ struct pci_dev *dev = NULL;
+ struct pci_driver *d;
+ struct list_head *l, *n;
+
+ pre_init = 0;
+ if (!ide_scan_direction)
+ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
+ ide_scan_pcidev(dev);
+ else
+ while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID,
+ dev)))
+ ide_scan_pcidev(dev);
+
+ /*
+ * Hand the drivers over to the PCI layer now we
+ * are post init.
+ */
+
+ list_for_each_safe(l, n, &ide_pci_drivers) {
+ list_del(l);
+ d = list_entry(l, struct pci_driver, node);
+ if (__pci_register_driver(d, d->driver.owner,
+ d->driver.mod_name))
+ printk(KERN_ERR "%s: failed to register %s driver\n",
+ __FUNCTION__, d->driver.mod_name);
+ }
+
+ return 0;
+}
+
+module_init(ide_scan_pcibus);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 7b9181b5469..bf40d8c824a 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1,9 +1,8 @@
/*
- * linux/drivers/ide/ide-tape.c Version 1.19 Nov, 2003
- *
- * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il>
+ * IDE ATAPI streaming tape driver.
*
- * $Header$
+ * Copyright (C) 1995-1999 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 2003-2005 Bartlomiej Zolnierkiewicz
*
* This driver was constructed as a student project in the software laboratory
* of the faculty of electrical engineering in the Technion - Israel's
@@ -11,415 +10,9 @@
*
* It is hereby placed under the terms of the GNU general public license.
* (See linux/COPYING).
- */
-
-/*
- * IDE ATAPI streaming tape driver.
- *
- * This driver is a part of the Linux ide driver and works in co-operation
- * with linux/drivers/block/ide.c.
- *
- * The driver, in co-operation with ide.c, basically traverses the
- * request-list for the block device interface. The character device
- * interface, on the other hand, creates new requests, adds them
- * to the request-list of the block device, and waits for their completion.
- *
- * Pipelined operation mode is now supported on both reads and writes.
- *
- * The block device major and minor numbers are determined from the
- * tape's relative position in the ide interfaces, as explained in ide.c.
- *
- * The character device interface consists of the following devices:
- *
- * ht0 major 37, minor 0 first IDE tape, rewind on close.
- * ht1 major 37, minor 1 second IDE tape, rewind on close.
- * ...
- * nht0 major 37, minor 128 first IDE tape, no rewind on close.
- * nht1 major 37, minor 129 second IDE tape, no rewind on close.
- * ...
- *
- * Run linux/scripts/MAKEDEV.ide to create the above entries.
- *
- * The general magnetic tape commands compatible interface, as defined by
- * include/linux/mtio.h, is accessible through the character device.
- *
- * General ide driver configuration options, such as the interrupt-unmask
- * flag, can be configured by issuing an ioctl to the block device interface,
- * as any other ide device.
- *
- * Our own ide-tape ioctl's can be issued to either the block device or
- * the character device interface.
- *
- * Maximal throughput with minimal bus load will usually be achieved in the
- * following scenario:
- *
- * 1. ide-tape is operating in the pipelined operation mode.
- * 2. No buffering is performed by the user backup program.
- *
- * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
- *
- * Ver 0.1 Nov 1 95 Pre-working code :-)
- * Ver 0.2 Nov 23 95 A short backup (few megabytes) and restore procedure
- * was successful ! (Using tar cvf ... on the block
- * device interface).
- * A longer backup resulted in major swapping, bad
- * overall Linux performance and eventually failed as
- * we received non serial read-ahead requests from the
- * buffer cache.
- * Ver 0.3 Nov 28 95 Long backups are now possible, thanks to the
- * character device interface. Linux's responsiveness
- * and performance doesn't seem to be much affected
- * from the background backup procedure.
- * Some general mtio.h magnetic tape operations are
- * now supported by our character device. As a result,
- * popular tape utilities are starting to work with
- * ide tapes :-)
- * The following configurations were tested:
- * 1. An IDE ATAPI TAPE shares the same interface
- * and irq with an IDE ATAPI CDROM.
- * 2. An IDE ATAPI TAPE shares the same interface
- * and irq with a normal IDE disk.
- * Both configurations seemed to work just fine !
- * However, to be on the safe side, it is meanwhile
- * recommended to give the IDE TAPE its own interface
- * and irq.
- * The one thing which needs to be done here is to
- * add a "request postpone" feature to ide.c,
- * so that we won't have to wait for the tape to finish
- * performing a long media access (DSC) request (such
- * as a rewind) before we can access the other device
- * on the same interface. This effect doesn't disturb
- * normal operation most of the time because read/write
- * requests are relatively fast, and once we are
- * performing one tape r/w request, a lot of requests
- * from the other device can be queued and ide.c will
- * service all of them after this single tape request.
- * Ver 1.0 Dec 11 95 Integrated into Linux 1.3.46 development tree.
- * On each read / write request, we now ask the drive
- * if we can transfer a constant number of bytes
- * (a parameter of the drive) only to its buffers,
- * without causing actual media access. If we can't,
- * we just wait until we can by polling the DSC bit.
- * This ensures that while we are not transferring
- * more bytes than the constant referred to above, the
- * interrupt latency will not become too high and
- * we won't cause an interrupt timeout, as happened
- * occasionally in the previous version.
- * While polling for DSC, the current request is
- * postponed and ide.c is free to handle requests from
- * the other device. This is handled transparently to
- * ide.c. The hwgroup locking method which was used
- * in the previous version was removed.
- * Use of new general features which are provided by
- * ide.c for use with atapi devices.
- * (Programming done by Mark Lord)
- * Few potential bug fixes (Again, suggested by Mark)
- * Single character device data transfers are now
- * not limited in size, as they were before.
- * We are asking the tape about its recommended
- * transfer unit and send a larger data transfer
- * as several transfers of the above size.
- * For best results, use an integral number of this
- * basic unit (which is shown during driver
- * initialization). I will soon add an ioctl to get
- * this important parameter.
- * Our data transfer buffer is allocated on startup,
- * rather than before each data transfer. This should
- * ensure that we will indeed have a data buffer.
- * Ver 1.1 Dec 14 95 Fixed random problems which occurred when the tape
- * shared an interface with another device.
- * (poll_for_dsc was a complete mess).
- * Removed some old (non-active) code which had
- * to do with supporting buffer cache originated
- * requests.
- * The block device interface can now be opened, so
- * that general ide driver features like the unmask
- * interrupts flag can be selected with an ioctl.
- * This is the only use of the block device interface.
- * New fast pipelined operation mode (currently only on
- * writes). When using the pipelined mode, the
- * throughput can potentially reach the maximum
- * tape supported throughput, regardless of the
- * user backup program. On my tape drive, it sometimes
- * boosted performance by a factor of 2. Pipelined
- * mode is enabled by default, but since it has a few
- * downfalls as well, you may want to disable it.
- * A short explanation of the pipelined operation mode
- * is available below.
- * Ver 1.2 Jan 1 96 Eliminated pipelined mode race condition.
- * Added pipeline read mode. As a result, restores
- * are now as fast as backups.
- * Optimized shared interface behavior. The new behavior
- * typically results in better IDE bus efficiency and
- * higher tape throughput.
- * Pre-calculation of the expected read/write request
- * service time, based on the tape's parameters. In
- * the pipelined operation mode, this allows us to
- * adjust our polling frequency to a much lower value,
- * and thus to dramatically reduce our load on Linux,
- * without any decrease in performance.
- * Implemented additional mtio.h operations.
- * The recommended user block size is returned by
- * the MTIOCGET ioctl.
- * Additional minor changes.
- * Ver 1.3 Feb 9 96 Fixed pipelined read mode bug which prevented the
- * use of some block sizes during a restore procedure.
- * The character device interface will now present a
- * continuous view of the media - any mix of block sizes
- * during a backup/restore procedure is supported. The
- * driver will buffer the requests internally and
- * convert them to the tape's recommended transfer
- * unit, making performance almost independent of the
- * chosen user block size.
- * Some improvements in error recovery.
- * By cooperating with ide-dma.c, bus mastering DMA can
- * now sometimes be used with IDE tape drives as well.
- * Bus mastering DMA has the potential to dramatically
- * reduce the CPU's overhead when accessing the device,
- * and can be enabled by using hdparm -d1 on the tape's
- * block device interface. For more info, read the
- * comments in ide-dma.c.
- * Ver 1.4 Mar 13 96 Fixed serialize support.
- * Ver 1.5 Apr 12 96 Fixed shared interface operation, broken in 1.3.85.
- * Fixed pipelined read mode inefficiency.
- * Fixed nasty null dereferencing bug.
- * Ver 1.6 Aug 16 96 Fixed FPU usage in the driver.
- * Fixed end of media bug.
- * Ver 1.7 Sep 10 96 Minor changes for the CONNER CTT8000-A model.
- * Ver 1.8 Sep 26 96 Attempt to find a better balance between good
- * interactive response and high system throughput.
- * Ver 1.9 Nov 5 96 Automatically cross encountered filemarks rather
- * than requiring an explicit FSF command.
- * Abort pending requests at end of media.
- * MTTELL was sometimes returning incorrect results.
- * Return the real block size in the MTIOCGET ioctl.
- * Some error recovery bug fixes.
- * Ver 1.10 Nov 5 96 Major reorganization.
- * Reduced CPU overhead a bit by eliminating internal
- * bounce buffers.
- * Added module support.
- * Added multiple tape drives support.
- * Added partition support.
- * Rewrote DSC handling.
- * Some portability fixes.
- * Removed ide-tape.h.
- * Additional minor changes.
- * Ver 1.11 Dec 2 96 Bug fix in previous DSC timeout handling.
- * Use ide_stall_queue() for DSC overlap.
- * Use the maximum speed rather than the current speed
- * to compute the request service time.
- * Ver 1.12 Dec 7 97 Fix random memory overwriting and/or last block data
- * corruption, which could occur if the total number
- * of bytes written to the tape was not an integral
- * number of tape blocks.
- * Add support for INTERRUPT DRQ devices.
- * Ver 1.13 Jan 2 98 Add "speed == 0" work-around for HP COLORADO 5GB
- * Ver 1.14 Dec 30 98 Partial fixes for the Sony/AIWA tape drives.
- * Replace cli()/sti() with hwgroup spinlocks.
- * Ver 1.15 Mar 25 99 Fix SMP race condition by replacing hwgroup
- * spinlock with private per-tape spinlock.
- * Ver 1.16 Sep 1 99 Add OnStream tape support.
- * Abort read pipeline on EOD.
- * Wait for the tape to become ready in case it returns
- * "in the process of becoming ready" on open().
- * Fix zero padding of the last written block in
- * case the tape block size is larger than PAGE_SIZE.
- * Decrease the default disconnection time to tn.
- * Ver 1.16e Oct 3 99 Minor fixes.
- * Ver 1.16e1 Oct 13 99 Patches by Arnold Niessen,
- * niessen@iae.nl / arnold.niessen@philips.com
- * GO-1) Undefined code in idetape_read_position
- * according to Gadi's email
- * AJN-1) Minor fix asc == 11 should be asc == 0x11
- * in idetape_issue_packet_command (did effect
- * debugging output only)
- * AJN-2) Added more debugging output, and
- * added ide-tape: where missing. I would also
- * like to add tape->name where possible
- * AJN-3) Added different debug_level's
- * via /proc/ide/hdc/settings
- * "debug_level" determines amount of debugging output;
- * can be changed using /proc/ide/hdx/settings
- * 0 : almost no debugging output
- * 1 : 0+output errors only
- * 2 : 1+output all sensekey/asc
- * 3 : 2+follow all chrdev related procedures
- * 4 : 3+follow all procedures
- * 5 : 4+include pc_stack rq_stack info
- * 6 : 5+USE_COUNT updates
- * AJN-4) Fixed timeout for retension in idetape_queue_pc_tail
- * from 5 to 10 minutes
- * AJN-5) Changed maximum number of blocks to skip when
- * reading tapes with multiple consecutive write
- * errors from 100 to 1000 in idetape_get_logical_blk
- * Proposed changes to code:
- * 1) output "logical_blk_num" via /proc
- * 2) output "current_operation" via /proc
- * 3) Either solve or document the fact that `mt rewind' is
- * required after reading from /dev/nhtx to be
- * able to rmmod the idetape module;
- * Also, sometimes an application finishes but the
- * device remains `busy' for some time. Same cause ?
- * Proposed changes to release-notes:
- * 4) write a simple `quickstart' section in the
- * release notes; I volunteer if you don't want to
- * 5) include a pointer to video4linux in the doc
- * to stimulate video applications
- * 6) release notes lines 331 and 362: explain what happens
- * if the application data rate is higher than 1100 KB/s;
- * similar approach to lower-than-500 kB/s ?
- * 7) 6.6 Comparison; wouldn't it be better to allow different
- * strategies for read and write ?
- * Wouldn't it be better to control the tape buffer
- * contents instead of the bandwidth ?
- * 8) line 536: replace will by would (if I understand
- * this section correctly, a hypothetical and unwanted situation
- * is being described)
- * Ver 1.16f Dec 15 99 Change place of the secondary OnStream header frames.
- * Ver 1.17 Nov 2000 / Jan 2001 Marcel Mol, marcel@mesa.nl
- * - Add idetape_onstream_mode_sense_tape_parameter_page
- * function to get tape capacity in frames: tape->capacity.
- * - Add support for DI-50 drives( or any DI- drive).
- * - 'workaround' for read error/blank block around block 3000.
- * - Implement Early warning for end of media for Onstream.
- * - Cosmetic code changes for readability.
- * - Idetape_position_tape should not use SKIP bit during
- * Onstream read recovery.
- * - Add capacity, logical_blk_num and first/last_frame_position
- * to /proc/ide/hd?/settings.
- * - Module use count was gone in the Linux 2.4 driver.
- * Ver 1.17a Apr 2001 Willem Riede osst@riede.org
- * - Get drive's actual block size from mode sense block descriptor
- * - Limit size of pipeline
- * Ver 1.17b Oct 2002 Alan Stern <stern@rowland.harvard.edu>
- * Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used
- * it in the code!
- * Actually removed aborted stages in idetape_abort_pipeline
- * instead of just changing the command code.
- * Made the transfer byte count for Request Sense equal to the
- * actual length of the data transfer.
- * Changed handling of partial data transfers: they do not
- * cause DMA errors.
- * Moved initiation of DMA transfers to the correct place.
- * Removed reference to unallocated memory.
- * Made __idetape_discard_read_pipeline return the number of
- * sectors skipped, not the number of stages.
- * Replaced errant kfree() calls with __idetape_kfree_stage().
- * Fixed off-by-one error in testing the pipeline length.
- * Fixed handling of filemarks in the read pipeline.
- * Small code optimization for MTBSF and MTBSFM ioctls.
- * Don't try to unlock the door during device close if is
- * already unlocked!
- * Cosmetic fixes to miscellaneous debugging output messages.
- * Set the minimum /proc/ide/hd?/settings values for "pipeline",
- * "pipeline_min", and "pipeline_max" to 1.
- *
- * Here are some words from the first releases of hd.c, which are quoted
- * in ide.c and apply here as well:
- *
- * | Special care is recommended. Have Fun!
- *
- */
-
-/*
- * An overview of the pipelined operation mode.
- *
- * In the pipelined write mode, we will usually just add requests to our
- * pipeline and return immediately, before we even start to service them. The
- * user program will then have enough time to prepare the next request while
- * we are still busy servicing previous requests. In the pipelined read mode,
- * the situation is similar - we add read-ahead requests into the pipeline,
- * before the user even requested them.
- *
- * The pipeline can be viewed as a "safety net" which will be activated when
- * the system load is high and prevents the user backup program from keeping up
- * with the current tape speed. At this point, the pipeline will get
- * shorter and shorter but the tape will still be streaming at the same speed.
- * Assuming we have enough pipeline stages, the system load will hopefully
- * decrease before the pipeline is completely empty, and the backup program
- * will be able to "catch up" and refill the pipeline again.
- *
- * When using the pipelined mode, it would be best to disable any type of
- * buffering done by the user program, as ide-tape already provides all the
- * benefits in the kernel, where it can be done in a more efficient way.
- * As we will usually not block the user program on a request, the most
- * efficient user code will then be a simple read-write-read-... cycle.
- * Any additional logic will usually just slow down the backup process.
- *
- * Using the pipelined mode, I get a constant over 400 KBps throughput,
- * which seems to be the maximum throughput supported by my tape.
*
- * However, there are some downfalls:
- *
- * 1. We use memory (for data buffers) in proportional to the number
- * of pipeline stages (each stage is about 26 KB with my tape).
- * 2. In the pipelined write mode, we cheat and postpone error codes
- * to the user task. In read mode, the actual tape position
- * will be a bit further than the last requested block.
- *
- * Concerning (1):
- *
- * 1. We allocate stages dynamically only when we need them. When
- * we don't need them, we don't consume additional memory. In
- * case we can't allocate stages, we just manage without them
- * (at the expense of decreased throughput) so when Linux is
- * tight in memory, we will not pose additional difficulties.
- *
- * 2. The maximum number of stages (which is, in fact, the maximum
- * amount of memory) which we allocate is limited by the compile
- * time parameter IDETAPE_MAX_PIPELINE_STAGES.
- *
- * 3. The maximum number of stages is a controlled parameter - We
- * don't start from the user defined maximum number of stages
- * but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
- * will not even allocate this amount of stages if the user
- * program can't handle the speed). We then implement a feedback
- * loop which checks if the pipeline is empty, and if it is, we
- * increase the maximum number of stages as necessary until we
- * reach the optimum value which just manages to keep the tape
- * busy with minimum allocated memory or until we reach
- * IDETAPE_MAX_PIPELINE_STAGES.
- *
- * Concerning (2):
- *
- * In pipelined write mode, ide-tape can not return accurate error codes
- * to the user program since we usually just add the request to the
- * pipeline without waiting for it to be serviced. In case an error
- * occurs, I will report it on the next user request.
- *
- * In the pipelined read mode, subsequent read requests or forward
- * filemark spacing will perform correctly, as we preserve all blocks
- * and filemarks which we encountered during our excess read-ahead.
- *
- * For accurate tape positioning and error reporting, disabling
- * pipelined mode might be the best option.
- *
- * You can enable/disable/tune the pipelined operation mode by adjusting
- * the compile time parameters below.
- */
-
-/*
- * Possible improvements.
- *
- * 1. Support for the ATAPI overlap protocol.
- *
- * In order to maximize bus throughput, we currently use the DSC
- * overlap method which enables ide.c to service requests from the
- * other device while the tape is busy executing a command. The
- * DSC overlap method involves polling the tape's status register
- * for the DSC bit, and servicing the other device while the tape
- * isn't ready.
- *
- * In the current QIC development standard (December 1995),
- * it is recommended that new tape drives will *in addition*
- * implement the ATAPI overlap protocol, which is used for the
- * same purpose - efficient use of the IDE bus, but is interrupt
- * driven and thus has much less CPU overhead.
- *
- * ATAPI overlap is likely to be supported in most new ATAPI
- * devices, including new ATAPI cdroms, and thus provides us
- * a method by which we can achieve higher throughput when
- * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
+ * For a historical changelog see
+ * Documentation/ide/ChangeLog.ide-tape.1995-2002
*/
#define IDETAPE_VERSION "1.19"
@@ -443,49 +36,13 @@
#include <linux/completion.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
+#include <scsi/scsi.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/unaligned.h>
-
-/*
- * partition
- */
-typedef struct os_partition_s {
- __u8 partition_num;
- __u8 par_desc_ver;
- __u16 wrt_pass_cntr;
- __u32 first_frame_addr;
- __u32 last_frame_addr;
- __u32 eod_frame_addr;
-} os_partition_t;
-
-/*
- * DAT entry
- */
-typedef struct os_dat_entry_s {
- __u32 blk_sz;
- __u16 blk_cnt;
- __u8 flags;
- __u8 reserved;
-} os_dat_entry_t;
-
-/*
- * DAT
- */
-#define OS_DAT_FLAGS_DATA (0xc)
-#define OS_DAT_FLAGS_MARK (0x1)
-
-typedef struct os_dat_s {
- __u8 dat_sz;
- __u8 reserved1;
- __u8 entry_cnt;
- __u8 reserved3;
- os_dat_entry_t dat_list[16];
-} os_dat_t;
-
#include <linux/mtio.h>
/**************************** Tunable parameters *****************************/
@@ -513,10 +70,7 @@ typedef struct os_dat_s {
/*
* The following are used to debug the driver:
*
- * Setting IDETAPE_DEBUG_INFO to 1 will report device capabilities.
* Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control.
- * Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in
- * some places.
*
* Setting them to 0 will restore normal operation mode:
*
@@ -528,9 +82,7 @@ typedef struct os_dat_s {
* is verified to be stable enough. This will make it much more
* esthetic.
*/
-#define IDETAPE_DEBUG_INFO 0
#define IDETAPE_DEBUG_LOG 0
-#define IDETAPE_DEBUG_BUGS 1
/*
* After each failed packet command we issue a request sense command
@@ -615,16 +167,6 @@ typedef struct os_dat_s {
/*************************** End of tunable parameters ***********************/
/*
- * Debugging/Performance analysis
- *
- * I/O trace support
- */
-#define USE_IOTRACE 0
-#if USE_IOTRACE
-#define IO_IDETAPE_FIFO 500
-#endif
-
-/*
* Read/Write error simulation
*/
#define SIMULATE_ERRORS 0
@@ -682,65 +224,6 @@ typedef struct idetape_packet_command_s {
#define PC_WRITING 5
/*
- * Capabilities and Mechanical Status Page
- */
-typedef struct {
- unsigned page_code :6; /* Page code - Should be 0x2a */
- __u8 reserved0_6 :1;
- __u8 ps :1; /* parameters saveable */
- __u8 page_length; /* Page Length - Should be 0x12 */
- __u8 reserved2, reserved3;
- unsigned ro :1; /* Read Only Mode */
- unsigned reserved4_1234 :4;
- unsigned sprev :1; /* Supports SPACE in the reverse direction */
- unsigned reserved4_67 :2;
- unsigned reserved5_012 :3;
- unsigned efmt :1; /* Supports ERASE command initiated formatting */
- unsigned reserved5_4 :1;
- unsigned qfa :1; /* Supports the QFA two partition formats */
- unsigned reserved5_67 :2;
- unsigned lock :1; /* Supports locking the volume */
- unsigned locked :1; /* The volume is locked */
- unsigned prevent :1; /* The device defaults in the prevent state after power up */
- unsigned eject :1; /* The device can eject the volume */
- __u8 disconnect :1; /* The device can break request > ctl */
- __u8 reserved6_5 :1;
- unsigned ecc :1; /* Supports error correction */
- unsigned cmprs :1; /* Supports data compression */
- unsigned reserved7_0 :1;
- unsigned blk512 :1; /* Supports 512 bytes block size */
- unsigned blk1024 :1; /* Supports 1024 bytes block size */
- unsigned reserved7_3_6 :4;
- unsigned blk32768 :1; /* slowb - the device restricts the byte count for PIO */
- /* transfers for slow buffer memory ??? */
- /* Also 32768 block size in some cases */
- __u16 max_speed; /* Maximum speed supported in KBps */
- __u8 reserved10, reserved11;
- __u16 ctl; /* Continuous Transfer Limit in blocks */
- __u16 speed; /* Current Speed, in KBps */
- __u16 buffer_size; /* Buffer Size, in 512 bytes */
- __u8 reserved18, reserved19;
-} idetape_capabilities_page_t;
-
-/*
- * Block Size Page
- */
-typedef struct {
- unsigned page_code :6; /* Page code - Should be 0x30 */
- unsigned reserved1_6 :1;
- unsigned ps :1;
- __u8 page_length; /* Page Length - Should be 2 */
- __u8 reserved2;
- unsigned play32 :1;
- unsigned play32_5 :1;
- unsigned reserved2_23 :2;
- unsigned record32 :1;
- unsigned record32_5 :1;
- unsigned reserved2_6 :1;
- unsigned one :1;
-} idetape_block_size_page_t;
-
-/*
* A pipeline stage.
*/
typedef struct idetape_stage_s {
@@ -750,32 +233,6 @@ typedef struct idetape_stage_s {
} idetape_stage_t;
/*
- * REQUEST SENSE packet command result - Data Format.
- */
-typedef struct {
- unsigned error_code :7; /* Current of deferred errors */
- unsigned valid :1; /* The information field conforms to QIC-157C */
- __u8 reserved1 :8; /* Segment Number - Reserved */
- unsigned sense_key :4; /* Sense Key */
- unsigned reserved2_4 :1; /* Reserved */
- unsigned ili :1; /* Incorrect Length Indicator */
- unsigned eom :1; /* End Of Medium */
- unsigned filemark :1; /* Filemark */
- __u32 information __attribute__ ((packed));
- __u8 asl; /* Additional sense length (n-7) */
- __u32 command_specific; /* Additional command specific information */
- __u8 asc; /* Additional Sense Code */
- __u8 ascq; /* Additional Sense Code Qualifier */
- __u8 replaceable_unit_code; /* Field Replaceable Unit Code */
- unsigned sk_specific1 :7; /* Sense Key Specific */
- unsigned sksv :1; /* Sense Key Specific information is valid */
- __u8 sk_specific2; /* Sense Key Specific */
- __u8 sk_specific3; /* Sense Key Specific */
- __u8 pad[2]; /* Padding to 20 bytes */
-} idetape_request_sense_result_t;
-
-
-/*
* Most of our global data which we need to save even as we leave the
* driver due to an interrupt or a timer event is stored in a variable
* of type idetape_tape_t, defined below.
@@ -865,8 +322,9 @@ typedef struct ide_tape_obj {
/* Usually 512 or 1024 bytes */
unsigned short tape_block_size;
int user_bs_factor;
+
/* Copy of the tape's Capabilities and Mechanical Page */
- idetape_capabilities_page_t capabilities;
+ u8 caps[20];
/*
* Active data transfer request parameters.
@@ -929,9 +387,6 @@ typedef struct ide_tape_obj {
int avg_size;
int avg_speed;
- /* last sense information */
- idetape_request_sense_result_t sense;
-
char vendor_id[10];
char product_id[18];
char firmware_revision[6];
@@ -1063,27 +518,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
#define IDETAPE_MEDIUM_PRESENT 9
/*
- * Supported ATAPI tape drives packet commands
- */
-#define IDETAPE_TEST_UNIT_READY_CMD 0x00
-#define IDETAPE_REWIND_CMD 0x01
-#define IDETAPE_REQUEST_SENSE_CMD 0x03
-#define IDETAPE_READ_CMD 0x08
-#define IDETAPE_WRITE_CMD 0x0a
-#define IDETAPE_WRITE_FILEMARK_CMD 0x10
-#define IDETAPE_SPACE_CMD 0x11
-#define IDETAPE_INQUIRY_CMD 0x12
-#define IDETAPE_ERASE_CMD 0x19
-#define IDETAPE_MODE_SENSE_CMD 0x1a
-#define IDETAPE_MODE_SELECT_CMD 0x15
-#define IDETAPE_LOAD_UNLOAD_CMD 0x1b
-#define IDETAPE_PREVENT_CMD 0x1e
-#define IDETAPE_LOCATE_CMD 0x2b
-#define IDETAPE_READ_POSITION_CMD 0x34
-#define IDETAPE_READ_BUFFER_CMD 0x3c
-#define IDETAPE_SET_SPEED_CMD 0xbb
-
-/*
* Some defines for the READ BUFFER command
*/
#define IDETAPE_RETRIEVE_FAULTY_BLOCK 6
@@ -1140,31 +574,6 @@ struct idetape_id_gcw {
};
/*
- * INQUIRY packet command - Data Format (From Table 6-8 of QIC-157C)
- */
-typedef struct {
- unsigned device_type :5; /* Peripheral Device Type */
- unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */
- unsigned reserved1_6t0 :7; /* Reserved */
- unsigned rmb :1; /* Removable Medium Bit */
- unsigned ansi_version :3; /* ANSI Version */
- unsigned ecma_version :3; /* ECMA Version */
- unsigned iso_version :2; /* ISO Version */
- unsigned response_format :4; /* Response Data Format */
- unsigned reserved3_45 :2; /* Reserved */
- unsigned reserved3_6 :1; /* TrmIOP - Reserved */
- unsigned reserved3_7 :1; /* AENC - Reserved */
- __u8 additional_length; /* Additional Length (total_length-4) */
- __u8 rsv5, rsv6, rsv7; /* Reserved */
- __u8 vendor_id[8]; /* Vendor Identification */
- __u8 product_id[16]; /* Product Identification */
- __u8 revision_level[4]; /* Revision Level */
- __u8 vendor_specific[20]; /* Vendor Specific - Optional */
- __u8 reserved56t95[40]; /* Reserved - Optional */
- /* Additional information may be returned */
-} idetape_inquiry_result_t;
-
-/*
* READ POSITION packet command - Data Format (From Table 6-57)
*/
typedef struct {
@@ -1182,100 +591,9 @@ typedef struct {
u32 bytes_in_buffer; /* Bytes In Buffer (Optional) */
} idetape_read_position_result_t;
-/*
- * Follows structures which are related to the SELECT SENSE / MODE SENSE
- * packet commands. Those packet commands are still not supported
- * by ide-tape.
- */
+/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
#define IDETAPE_BLOCK_DESCRIPTOR 0
#define IDETAPE_CAPABILITIES_PAGE 0x2a
-#define IDETAPE_PARAMTR_PAGE 0x2b /* Onstream DI-x0 only */
-#define IDETAPE_BLOCK_SIZE_PAGE 0x30
-#define IDETAPE_BUFFER_FILLING_PAGE 0x33
-
-/*
- * Mode Parameter Header for the MODE SENSE packet command
- */
-typedef struct {
- __u8 mode_data_length; /* Length of the following data transfer */
- __u8 medium_type; /* Medium Type */
- __u8 dsp; /* Device Specific Parameter */
- __u8 bdl; /* Block Descriptor Length */
-#if 0
- /* data transfer page */
- __u8 page_code :6;
- __u8 reserved0_6 :1;
- __u8 ps :1; /* parameters saveable */
- __u8 page_length; /* page Length == 0x02 */
- __u8 reserved2;
- __u8 read32k :1; /* 32k blk size (data only) */
- __u8 read32k5 :1; /* 32.5k blk size (data&AUX) */
- __u8 reserved3_23 :2;
- __u8 write32k :1; /* 32k blk size (data only) */
- __u8 write32k5 :1; /* 32.5k blk size (data&AUX) */
- __u8 reserved3_6 :1;
- __u8 streaming :1; /* streaming mode enable */
-#endif
-} idetape_mode_parameter_header_t;
-
-/*
- * Mode Parameter Block Descriptor the MODE SENSE packet command
- *
- * Support for block descriptors is optional.
- */
-typedef struct {
- __u8 density_code; /* Medium density code */
- __u8 blocks[3]; /* Number of blocks */
- __u8 reserved4; /* Reserved */
- __u8 length[3]; /* Block Length */
-} idetape_parameter_block_descriptor_t;
-
-/*
- * The Data Compression Page, as returned by the MODE SENSE packet command.
- */
-typedef struct {
- unsigned page_code :6; /* Page Code - Should be 0xf */
- unsigned reserved0 :1; /* Reserved */
- unsigned ps :1;
- __u8 page_length; /* Page Length - Should be 14 */
- unsigned reserved2 :6; /* Reserved */
- unsigned dcc :1; /* Data Compression Capable */
- unsigned dce :1; /* Data Compression Enable */
- unsigned reserved3 :5; /* Reserved */
- unsigned red :2; /* Report Exception on Decompression */
- unsigned dde :1; /* Data Decompression Enable */
- __u32 ca; /* Compression Algorithm */
- __u32 da; /* Decompression Algorithm */
- __u8 reserved[4]; /* Reserved */
-} idetape_data_compression_page_t;
-
-/*
- * The Medium Partition Page, as returned by the MODE SENSE packet command.
- */
-typedef struct {
- unsigned page_code :6; /* Page Code - Should be 0x11 */
- unsigned reserved1_6 :1; /* Reserved */
- unsigned ps :1;
- __u8 page_length; /* Page Length - Should be 6 */
- __u8 map; /* Maximum Additional Partitions - Should be 0 */
- __u8 apd; /* Additional Partitions Defined - Should be 0 */
- unsigned reserved4_012 :3; /* Reserved */
- unsigned psum :2; /* Should be 0 */
- unsigned idp :1; /* Should be 0 */
- unsigned sdp :1; /* Should be 0 */
- unsigned fdp :1; /* Fixed Data Partitions */
- __u8 mfr; /* Medium Format Recognition */
- __u8 reserved[2]; /* Reserved */
-} idetape_medium_partition_page_t;
-
-/*
- * Run time configurable parameters.
- */
-typedef struct {
- int dsc_rw_frequency;
- int dsc_media_access_frequency;
- int nr_stages;
-} idetape_config_t;
/*
* The variables below are used for the character device interface.
@@ -1320,14 +638,12 @@ static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigne
int count;
while (bcount) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_input_buffers\n");
idetape_discard_data(drive, bcount);
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), bcount);
HWIF(drive)->atapi_input_bytes(drive, bh->b_data + atomic_read(&bh->b_count), count);
bcount -= count;
@@ -1347,13 +663,11 @@ static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsign
int count;
while (bcount) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_output_buffers\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)pc->b_count, (unsigned int)bcount);
HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count);
bcount -= count;
@@ -1378,13 +692,11 @@ static void idetape_update_buffers (idetape_pc_t *pc)
if (test_bit(PC_WRITING, &pc->flags))
return;
while (bcount) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_update_buffers\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)bh->b_size, (unsigned int)bcount);
atomic_set(&bh->b_count, count);
if (atomic_read(&bh->b_count) == bh->b_size)
@@ -1457,36 +769,34 @@ static void idetape_init_pc (idetape_pc_t *pc)
}
/*
- * idetape_analyze_error is called on each failed packet command retry
- * to analyze the request sense. We currently do not utilize this
- * information.
+ * called on each failed packet command retry to analyze the request sense. We
+ * currently do not utilize this information.
*/
-static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_result_t *result)
+static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->failed_pc;
- tape->sense = *result;
- tape->sense_key = result->sense_key;
- tape->asc = result->asc;
- tape->ascq = result->ascq;
+ tape->sense_key = sense[2] & 0xF;
+ tape->asc = sense[12];
+ tape->ascq = sense[13];
#if IDETAPE_DEBUG_LOG
/*
- * Without debugging, we only log an error if we decided to
- * give up retrying.
+ * Without debugging, we only log an error if we decided to give up
+ * retrying.
*/
if (tape->debug_level >= 1)
printk(KERN_INFO "ide-tape: pc = %x, sense key = %x, "
"asc = %x, ascq = %x\n",
- pc->c[0], result->sense_key,
- result->asc, result->ascq);
+ pc->c[0], tape->sense_key,
+ tape->asc, tape->ascq);
#endif /* IDETAPE_DEBUG_LOG */
- /*
- * Correct pc->actually_transferred by asking the tape.
- */
+ /* Correct pc->actually_transferred by asking the tape. */
if (test_bit(PC_DMA_ERROR, &pc->flags)) {
- pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned(&result->information));
+ pc->actually_transferred = pc->request_transfer -
+ tape->tape_block_size *
+ be32_to_cpu(get_unaligned((u32 *)&sense[3]));
idetape_update_buffers(pc);
}
@@ -1495,29 +805,29 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res
* with sense key=5, asc=0x22, ascq=0, let it slide. Some drives
* (i.e. Seagate STT3401A Travan) don't support 0-length read/writes.
*/
- if ((pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD)
- && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) { /* length==0 */
- if (result->sense_key == 5) {
+ if ((pc->c[0] == READ_6 || pc->c[0] == WRITE_6)
+ /* length == 0 */
+ && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) {
+ if (tape->sense_key == 5) {
/* don't report an error, everything's ok */
pc->error = 0;
/* don't retry read/write */
set_bit(PC_ABORT, &pc->flags);
}
}
- if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) {
+ if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
pc->error = IDETAPE_ERROR_FILEMARK;
set_bit(PC_ABORT, &pc->flags);
}
- if (pc->c[0] == IDETAPE_WRITE_CMD) {
- if (result->eom ||
- (result->sense_key == 0xd && result->asc == 0x0 &&
- result->ascq == 0x2)) {
+ if (pc->c[0] == WRITE_6) {
+ if ((sense[2] & 0x40) || (tape->sense_key == 0xd
+ && tape->asc == 0x0 && tape->ascq == 0x2)) {
pc->error = IDETAPE_ERROR_EOD;
set_bit(PC_ABORT, &pc->flags);
}
}
- if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) {
- if (result->sense_key == 8) {
+ if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
+ if (tape->sense_key == 8) {
pc->error = IDETAPE_ERROR_EOD;
set_bit(PC_ABORT, &pc->flags);
}
@@ -1527,10 +837,7 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res
}
}
-/*
- * idetape_active_next_stage will declare the next stage as "active".
- */
-static void idetape_active_next_stage (ide_drive_t *drive)
+static void idetape_activate_next_stage(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_stage_t *stage = tape->next_stage;
@@ -1540,12 +847,10 @@ static void idetape_active_next_stage (ide_drive_t *drive)
if (tape->debug_level >= 4)
printk(KERN_INFO "ide-tape: Reached idetape_active_next_stage\n");
#endif /* IDETAPE_DEBUG_LOG */
-#if IDETAPE_DEBUG_BUGS
if (stage == NULL) {
printk(KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
rq->rq_disk = tape->disk;
rq->buffer = NULL;
@@ -1620,28 +925,24 @@ static void idetape_remove_stage_head (ide_drive_t *drive)
if (tape->debug_level >= 4)
printk(KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n");
#endif /* IDETAPE_DEBUG_LOG */
-#if IDETAPE_DEBUG_BUGS
if (tape->first_stage == NULL) {
printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n");
- return;
+ return;
}
if (tape->active_stage == tape->first_stage) {
printk(KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
stage = tape->first_stage;
tape->first_stage = stage->next;
idetape_kfree_stage(tape, stage);
tape->nr_stages--;
if (tape->first_stage == NULL) {
tape->last_stage = NULL;
-#if IDETAPE_DEBUG_BUGS
if (tape->next_stage != NULL)
printk(KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n");
if (tape->nr_stages)
printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 now\n");
-#endif /* IDETAPE_DEBUG_BUGS */
}
}
@@ -1700,6 +1001,11 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
if (error)
tape->failed_pc = NULL;
+ if (!blk_special_request(rq)) {
+ ide_end_request(drive, uptodate, nr_sects);
+ return 0;
+ }
+
spin_lock_irqsave(&tape->spinlock, flags);
/* The request was a pipelined data transfer request */
@@ -1722,7 +1028,7 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
}
}
if (tape->next_stage != NULL) {
- idetape_active_next_stage(drive);
+ idetape_activate_next_stage(drive);
/*
* Insert the next request into the request queue.
@@ -1754,7 +1060,7 @@ static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive)
printk(KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n");
#endif /* IDETAPE_DEBUG_LOG */
if (!tape->pc->error) {
- idetape_analyze_error(drive, (idetape_request_sense_result_t *) tape->pc->buffer);
+ idetape_analyze_error(drive, tape->pc->buffer);
idetape_end_request(drive, 1, 0);
} else {
printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n");
@@ -1766,7 +1072,7 @@ static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive)
static void idetape_create_request_sense_cmd (idetape_pc_t *pc)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_REQUEST_SENSE_CMD;
+ pc->c[0] = REQUEST_SENSE;
pc->c[4] = 20;
pc->request_transfer = 20;
pc->callback = &idetape_request_sense_callback;
@@ -1818,9 +1124,8 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc;
struct request *rq;
- atapi_error_t error;
- error.all = HWIF(drive)->INB(IDE_ERROR_REG);
+ (void)drive->hwif->INB(IDE_ERROR_REG);
pc = idetape_next_pc_storage(drive);
rq = idetape_next_rq_storage(drive);
idetape_create_request_sense_cmd(pc);
@@ -1858,15 +1163,13 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
- atapi_status_t status;
- atapi_bcount_t bcount;
- atapi_ireason_t ireason;
idetape_pc_t *pc = tape->pc;
-
unsigned int temp;
#if SIMULATE_ERRORS
static int error_sim_count = 0;
#endif
+ u16 bcount;
+ u8 stat, ireason;
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 4)
@@ -1875,10 +1178,10 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
#endif /* IDETAPE_DEBUG_LOG */
/* Clear the interrupt */
- status.all = HWIF(drive)->INB(IDE_STATUS_REG);
+ stat = hwif->INB(IDE_STATUS_REG);
if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
- if (HWIF(drive)->ide_dma_end(drive) || status.b.check) {
+ if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
/*
* A DMA error is sometimes expected. For example,
* if the tape is crossing a filemark during a
@@ -1912,7 +1215,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
}
/* No more interrupts */
- if (!status.b.drq) {
+ if ((stat & DRQ_STAT) == 0) {
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
@@ -1922,23 +1225,23 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
local_irq_enable();
#if SIMULATE_ERRORS
- if ((pc->c[0] == IDETAPE_WRITE_CMD ||
- pc->c[0] == IDETAPE_READ_CMD) &&
+ if ((pc->c[0] == WRITE_6 || pc->c[0] == READ_6) &&
(++error_sim_count % 100) == 0) {
printk(KERN_INFO "ide-tape: %s: simulating error\n",
tape->name);
- status.b.check = 1;
+ stat |= ERR_STAT;
}
#endif
- if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
- status.b.check = 0;
- if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */
+ if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
+ stat &= ~ERR_STAT;
+ if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
+ /* Error detected */
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 1)
printk(KERN_INFO "ide-tape: %s: I/O error\n",
tape->name);
#endif /* IDETAPE_DEBUG_LOG */
- if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
+ if (pc->c[0] == REQUEST_SENSE) {
printk(KERN_ERR "ide-tape: I/O error in request sense command\n");
return ide_do_reset(drive);
}
@@ -1951,7 +1254,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
}
pc->error = 0;
if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
- !status.b.dsc) {
+ (stat & SEEK_STAT) == 0) {
/* Media access command */
tape->dsc_polling_start = jiffies;
tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST;
@@ -1973,30 +1276,30 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
return ide_do_reset(drive);
}
/* Get the number of bytes to transfer on this interrupt. */
- bcount.b.high = hwif->INB(IDE_BCOUNTH_REG);
- bcount.b.low = hwif->INB(IDE_BCOUNTL_REG);
+ bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
+ hwif->INB(IDE_BCOUNTL_REG);
- ireason.all = hwif->INB(IDE_IREASON_REG);
+ ireason = hwif->INB(IDE_IREASON_REG);
- if (ireason.b.cod) {
+ if (ireason & CD) {
printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
return ide_do_reset(drive);
}
- if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
+ if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
/* Hopefully, we will never get here */
printk(KERN_ERR "ide-tape: We wanted to %s, ",
- ireason.b.io ? "Write":"Read");
+ (ireason & IO) ? "Write" : "Read");
printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n",
- ireason.b.io ? "Read":"Write");
+ (ireason & IO) ? "Read" : "Write");
return ide_do_reset(drive);
}
if (!test_bit(PC_WRITING, &pc->flags)) {
/* Reading - Check that we have enough space */
- temp = pc->actually_transferred + bcount.all;
+ temp = pc->actually_transferred + bcount;
if (temp > pc->request_transfer) {
if (temp > pc->buffer_size) {
printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
- idetape_discard_data(drive, bcount.all);
+ idetape_discard_data(drive, bcount);
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
return ide_started;
}
@@ -2008,23 +1311,26 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
}
if (test_bit(PC_WRITING, &pc->flags)) {
if (pc->bh != NULL)
- idetape_output_buffers(drive, pc, bcount.all);
+ idetape_output_buffers(drive, pc, bcount);
else
/* Write the current buffer */
- HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all);
+ hwif->atapi_output_bytes(drive, pc->current_position,
+ bcount);
} else {
if (pc->bh != NULL)
- idetape_input_buffers(drive, pc, bcount.all);
+ idetape_input_buffers(drive, pc, bcount);
else
/* Read the current buffer */
- HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all);
+ hwif->atapi_input_bytes(drive, pc->current_position,
+ bcount);
}
/* Update the current position */
- pc->actually_transferred += bcount.all;
- pc->current_position += bcount.all;
+ pc->actually_transferred += bcount;
+ pc->current_position += bcount;
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 2)
- printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
+ printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes "
+ "on that interrupt\n", pc->c[0], bcount);
#endif
/* And set the interrupt handler again */
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
@@ -2078,28 +1384,28 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
- atapi_ireason_t ireason;
int retries = 100;
ide_startstop_t startstop;
+ u8 ireason;
if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop;
}
- ireason.all = hwif->INB(IDE_IREASON_REG);
- while (retries-- && (!ireason.b.cod || ireason.b.io)) {
+ ireason = hwif->INB(IDE_IREASON_REG);
+ while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
"a packet command, retrying\n");
udelay(100);
- ireason.all = hwif->INB(IDE_IREASON_REG);
+ ireason = hwif->INB(IDE_IREASON_REG);
if (retries == 0) {
printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
"issuing a packet command, ignoring\n");
- ireason.b.cod = 1;
- ireason.b.io = 0;
+ ireason |= CD;
+ ireason &= ~IO;
}
}
- if (!ireason.b.cod || ireason.b.io) {
+ if ((ireason & CD) == 0 || (ireason & IO)) {
printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing "
"a packet command\n");
return ide_do_reset(drive);
@@ -2120,18 +1426,16 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
{
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
- atapi_bcount_t bcount;
int dma_ok = 0;
+ u16 bcount;
-#if IDETAPE_DEBUG_BUGS
- if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD &&
- pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
+ if (tape->pc->c[0] == REQUEST_SENSE &&
+ pc->c[0] == REQUEST_SENSE) {
printk(KERN_ERR "ide-tape: possible ide-tape.c bug - "
"Two request sense in serial were issued\n");
}
-#endif /* IDETAPE_DEBUG_BUGS */
- if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD)
+ if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
tape->failed_pc = pc;
/* Set the current packet command */
tape->pc = pc;
@@ -2144,7 +1448,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
* filemark, or end of the media, for example).
*/
if (!test_bit(PC_ABORT, &pc->flags)) {
- if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD &&
+ if (!(pc->c[0] == TEST_UNIT_READY &&
tape->sense_key == 2 && tape->asc == 4 &&
(tape->ascq == 1 || tape->ascq == 8))) {
printk(KERN_ERR "ide-tape: %s: I/O error, "
@@ -2170,7 +1474,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
pc->actually_transferred = 0;
pc->current_position = pc->buffer;
/* Request to transfer the entire buffer at once */
- bcount.all = pc->request_transfer;
+ bcount = pc->request_transfer;
if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
printk(KERN_WARNING "ide-tape: DMA disabled, "
@@ -2180,17 +1484,14 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
dma_ok = !hwif->dma_setup(drive);
- if (IDE_CONTROL_REG)
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
- hwif->OUTB(dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */
- hwif->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
- hwif->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
- hwif->OUTB(drive->select.all, IDE_SELECT_REG);
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
+ IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
+
if (dma_ok) /* Will begin DMA later */
set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
- ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
- hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
+ ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
+ IDETAPE_WAIT_CMD, NULL);
return ide_started;
} else {
hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
@@ -2220,7 +1521,7 @@ static ide_startstop_t idetape_pc_callback (ide_drive_t *drive)
static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, u8 page_code)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_MODE_SENSE_CMD;
+ pc->c[0] = MODE_SENSE;
if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors */
pc->c[2] = page_code;
@@ -2295,13 +1596,13 @@ static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
- atapi_status_t status;
+ u8 stat;
- status.all = HWIF(drive)->INB(IDE_STATUS_REG);
- if (status.b.dsc) {
- if (status.b.check) {
+ stat = drive->hwif->INB(IDE_STATUS_REG);
+ if (stat & SEEK_STAT) {
+ if (stat & ERR_STAT) {
/* Error detected */
- if (pc->c[0] != IDETAPE_TEST_UNIT_READY_CMD)
+ if (pc->c[0] != TEST_UNIT_READY)
printk(KERN_ERR "ide-tape: %s: I/O error, ",
tape->name);
/* Retry operation */
@@ -2358,8 +1659,8 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_READ_CMD;
- put_unaligned(htonl(length), (unsigned int *) &pc->c[1]);
+ pc->c[0] = READ_6;
+ put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
pc->callback = &idetape_rw_callback;
pc->bh = bh;
@@ -2376,7 +1677,7 @@ static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *p
struct idetape_bh *p = bh;
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_READ_BUFFER_CMD;
+ pc->c[0] = READ_BUFFER;
pc->c[1] = IDETAPE_RETRIEVE_FAULTY_BLOCK;
pc->c[7] = size >> 8;
pc->c[8] = size & 0xff;
@@ -2394,8 +1695,8 @@ static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *p
static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_WRITE_CMD;
- put_unaligned(htonl(length), (unsigned int *) &pc->c[1]);
+ pc->c[0] = WRITE_6;
+ put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
pc->callback = &idetape_rw_callback;
set_bit(PC_WRITING, &pc->flags);
@@ -2417,15 +1718,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = NULL;
struct request *postponed_rq = tape->postponed_rq;
- atapi_status_t status;
+ u8 stat;
#if IDETAPE_DEBUG_LOG
-#if 0
- if (tape->debug_level >= 5)
- printk(KERN_INFO "ide-tape: %d, "
- "dev: %s, cmd: %ld, errors: %d\n",
- rq->rq_disk->disk_name, rq->cmd[0], rq->errors);
-#endif
if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: sector: %ld, "
"nr_sectors: %ld, current_nr_sectors: %d\n",
@@ -2446,10 +1741,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
* Retry a failed packet command
*/
if (tape->failed_pc != NULL &&
- tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
+ tape->pc->c[0] == REQUEST_SENSE) {
return idetape_issue_packet_command(drive, tape->failed_pc);
}
-#if IDETAPE_DEBUG_BUGS
if (postponed_rq != NULL)
if (rq != postponed_rq) {
printk(KERN_ERR "ide-tape: ide-tape.c bug - "
@@ -2457,7 +1751,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
idetape_end_request(drive, 0, 0);
return ide_stopped;
}
-#endif /* IDETAPE_DEBUG_BUGS */
tape->postponed_rq = NULL;
@@ -2465,7 +1758,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
* If the tape is still busy, postpone our request and service
* the other device meanwhile.
*/
- status.all = HWIF(drive)->INB(IDE_STATUS_REG);
+ stat = drive->hwif->INB(IDE_STATUS_REG);
if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
@@ -2481,7 +1774,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
calculate_speeds(drive);
if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
- !status.b.dsc) {
+ (stat & SEEK_STAT) == 0) {
if (postponed_rq == NULL) {
tape->dsc_polling_start = jiffies;
tape->dsc_polling_frequency = tape->best_dsc_rw_frequency;
@@ -2502,9 +1795,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
}
if (rq->cmd[0] & REQ_IDETAPE_READ) {
tape->buffer_head++;
-#if USE_IOTRACE
- IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
-#endif
tape->postpone_cnt = 0;
pc = idetape_next_pc_storage(drive);
idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
@@ -2512,9 +1802,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
}
if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
tape->buffer_head++;
-#if USE_IOTRACE
- IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
-#endif
tape->postpone_cnt = 0;
pc = idetape_next_pc_storage(drive);
idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
@@ -2650,13 +1937,11 @@ static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *
int ret = 0;
while (n) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_copy_stage_from_user\n");
return 1;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
ret = 1;
@@ -2680,13 +1965,11 @@ static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, i
int ret = 0;
while (n) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_copy_stage_to_user\n");
return 1;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min(tape->b_count, n);
if (copy_to_user(buf, tape->b_data, count))
ret = 1;
@@ -2766,12 +2049,10 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
DECLARE_COMPLETION_ONSTACK(wait);
idetape_tape_t *tape = drive->driver_data;
-#if IDETAPE_DEBUG_BUGS
if (rq == NULL || !blk_special_request(rq)) {
printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
rq->end_io_data = &wait;
rq->end_io = blk_end_sync_rq;
spin_unlock_irq(&tape->spinlock);
@@ -2831,7 +2112,7 @@ static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive)
static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD;
+ pc->c[0] = WRITE_FILEMARKS;
pc->c[4] = write_filemark;
set_bit(PC_WAIT_FOR_DSC, &pc->flags);
pc->callback = &idetape_pc_callback;
@@ -2840,7 +2121,7 @@ static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t
static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_TEST_UNIT_READY_CMD;
+ pc->c[0] = TEST_UNIT_READY;
pc->callback = &idetape_pc_callback;
}
@@ -2878,7 +2159,7 @@ static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc)
static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD;
+ pc->c[0] = START_STOP;
pc->c[4] = cmd;
set_bit(PC_WAIT_FOR_DSC, &pc->flags);
pc->callback = &idetape_pc_callback;
@@ -2935,7 +2216,7 @@ static int idetape_flush_tape_buffers (ide_drive_t *drive)
static void idetape_create_read_position_cmd (idetape_pc_t *pc)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_READ_POSITION_CMD;
+ pc->c[0] = READ_POSITION;
pc->request_transfer = 20;
pc->callback = &idetape_read_position_callback;
}
@@ -2961,9 +2242,9 @@ static int idetape_read_position (ide_drive_t *drive)
static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_LOCATE_CMD;
+ pc->c[0] = POSITION_TO_ELEMENT;
pc->c[1] = 2;
- put_unaligned(htonl(block), (unsigned int *) &pc->c[3]);
+ put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
pc->c[8] = partition;
set_bit(PC_WAIT_FOR_DSC, &pc->flags);
pc->callback = &idetape_pc_callback;
@@ -2973,11 +2254,12 @@ static int idetape_create_prevent_cmd (ide_drive_t *drive, idetape_pc_t *pc, int
{
idetape_tape_t *tape = drive->driver_data;
- if (!tape->capabilities.lock)
+ /* device supports locking according to capabilities page */
+ if (!(tape->caps[6] & 0x01))
return 0;
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_PREVENT_CMD;
+ pc->c[0] = ALLOW_MEDIUM_REMOVAL;
pc->c[4] = prevent;
pc->callback = &idetape_pc_callback;
return 1;
@@ -3086,12 +2368,10 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, struct
if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd);
#endif /* IDETAPE_DEBUG_LOG */
-#if IDETAPE_DEBUG_BUGS
if (idetape_pipeline_active(tape)) {
printk(KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n");
return (0);
}
-#endif /* IDETAPE_DEBUG_BUGS */
idetape_init_rq(&rq, cmd);
rq.rq_disk = tape->disk;
@@ -3122,7 +2402,7 @@ static void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
return;
if (!idetape_pipeline_active(tape)) {
set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
- idetape_active_next_stage(drive);
+ idetape_activate_next_stage(drive);
(void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end);
}
}
@@ -3130,7 +2410,7 @@ static void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
static void idetape_create_inquiry_cmd (idetape_pc_t *pc)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_INQUIRY_CMD;
+ pc->c[0] = INQUIRY;
pc->c[4] = pc->request_transfer = 254;
pc->callback = &idetape_pc_callback;
}
@@ -3138,28 +2418,15 @@ static void idetape_create_inquiry_cmd (idetape_pc_t *pc)
static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_REWIND_CMD;
+ pc->c[0] = REZERO_UNIT;
set_bit(PC_WAIT_FOR_DSC, &pc->flags);
pc->callback = &idetape_pc_callback;
}
-#if 0
-static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length)
-{
- idetape_init_pc(pc);
- set_bit(PC_WRITING, &pc->flags);
- pc->c[0] = IDETAPE_MODE_SELECT_CMD;
- pc->c[1] = 0x10;
- put_unaligned(htons(length), (unsigned short *) &pc->c[3]);
- pc->request_transfer = 255;
- pc->callback = &idetape_pc_callback;
-}
-#endif
-
static void idetape_create_erase_cmd (idetape_pc_t *pc)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_ERASE_CMD;
+ pc->c[0] = ERASE;
pc->c[1] = 1;
set_bit(PC_WAIT_FOR_DSC, &pc->flags);
pc->callback = &idetape_pc_callback;
@@ -3168,8 +2435,8 @@ static void idetape_create_erase_cmd (idetape_pc_t *pc)
static void idetape_create_space_cmd (idetape_pc_t *pc,int count, u8 cmd)
{
idetape_init_pc(pc);
- pc->c[0] = IDETAPE_SPACE_CMD;
- put_unaligned(htonl(count), (unsigned int *) &pc->c[1]);
+ pc->c[0] = SPACE;
+ put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
pc->c[1] = cmd;
set_bit(PC_WAIT_FOR_DSC, &pc->flags);
pc->callback = &idetape_pc_callback;
@@ -3241,9 +2508,6 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
idetape_switch_buffers(tape, new_stage);
idetape_add_stage_tail(drive, new_stage);
tape->pipeline_head++;
-#if USE_IOTRACE
- IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
-#endif
calculate_speeds(drive);
/*
@@ -3292,8 +2556,7 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
idetape_tape_t *tape = drive->driver_data;
int blocks, min;
struct idetape_bh *bh;
-
-#if IDETAPE_DEBUG_BUGS
+
if (tape->chrdev_direction != idetape_direction_write) {
printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n");
return;
@@ -3302,7 +2565,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
tape->merge_stage_size = tape->stage_size;
}
-#endif /* IDETAPE_DEBUG_BUGS */
if (tape->merge_stage_size) {
blocks = tape->merge_stage_size / tape->tape_block_size;
if (tape->merge_stage_size % tape->tape_block_size) {
@@ -3347,7 +2609,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
* can be totally different on the next backup).
*/
tape->max_stages = tape->min_pipeline;
-#if IDETAPE_DEBUG_BUGS
if (tape->first_stage != NULL ||
tape->next_stage != NULL ||
tape->last_stage != NULL ||
@@ -3358,7 +2619,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
tape->first_stage, tape->next_stage,
tape->last_stage, tape->nr_stages);
}
-#endif /* IDETAPE_DEBUG_BUGS */
}
static void idetape_restart_speed_control (ide_drive_t *drive)
@@ -3381,7 +2641,7 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
idetape_stage_t *new_stage;
struct request rq;
int bytes_read;
- int blocks = tape->capabilities.ctl;
+ u16 blocks = *(u16 *)&tape->caps[12];
/* Initialize read operation */
if (tape->chrdev_direction != idetape_direction_read) {
@@ -3389,12 +2649,10 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
idetape_empty_write_pipeline(drive);
idetape_flush_tape_buffers(drive);
}
-#if IDETAPE_DEBUG_BUGS
if (tape->merge_stage || tape->merge_stage_size) {
printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n");
tape->merge_stage_size = 0;
}
-#endif /* IDETAPE_DEBUG_BUGS */
if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
return -ENOMEM;
tape->chrdev_direction = idetape_direction_read;
@@ -3493,17 +2751,12 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
idetape_remove_stage_head(drive);
spin_unlock_irqrestore(&tape->spinlock, flags);
tape->pipeline_head++;
-#if USE_IOTRACE
- IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
-#endif
calculate_speeds(drive);
}
-#if IDETAPE_DEBUG_BUGS
if (bytes_read > blocks * tape->tape_block_size) {
printk(KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n");
bytes_read = blocks * tape->tape_block_size;
}
-#endif /* IDETAPE_DEBUG_BUGS */
return (bytes_read);
}
@@ -3587,16 +2840,21 @@ static int idetape_rewind_tape (ide_drive_t *drive)
static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
idetape_tape_t *tape = drive->driver_data;
- idetape_config_t config;
void __user *argp = (void __user *)arg;
+ struct idetape_config {
+ int dsc_rw_frequency;
+ int dsc_media_access_frequency;
+ int nr_stages;
+ } config;
+
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 4)
printk(KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n");
#endif /* IDETAPE_DEBUG_LOG */
switch (cmd) {
case 0x0340:
- if (copy_from_user(&config, argp, sizeof (idetape_config_t)))
+ if (copy_from_user(&config, argp, sizeof(config)))
return -EFAULT;
tape->best_dsc_rw_frequency = config.dsc_rw_frequency;
tape->max_stages = config.nr_stages;
@@ -3604,7 +2862,7 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned l
case 0x0350:
config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency;
config.nr_stages = tape->max_stages;
- if (copy_to_user(argp, &config, sizeof (idetape_config_t)))
+ if (copy_to_user(argp, &config, sizeof(config)))
return -EFAULT;
break;
default:
@@ -3628,11 +2886,12 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
idetape_pc_t pc;
unsigned long flags;
int retval,count=0;
+ int sprev = !!(tape->caps[4] & 0x20);
if (mt_count == 0)
return 0;
if (MTBSF == mt_op || MTBSFM == mt_op) {
- if (!tape->capabilities.sprev)
+ if (!sprev)
return -EIO;
mt_count = - mt_count;
}
@@ -3686,7 +2945,7 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
return (idetape_queue_pc_tail(drive, &pc));
case MTFSFM:
case MTBSFM:
- if (!tape->capabilities.sprev)
+ if (!sprev)
return (-EIO);
retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count);
if (retval) return (retval);
@@ -3723,6 +2982,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
ide_drive_t *drive = tape->drive;
ssize_t bytes_read,temp, actually_read = 0, rc;
ssize_t ret = 0;
+ u16 ctl = *(u16 *)&tape->caps[12];
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 3)
@@ -3748,7 +3008,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
count -= actually_read;
}
while (count >= tape->stage_size) {
- bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
+ bytes_read = idetape_add_chrdev_read_request(drive, ctl);
if (bytes_read <= 0)
goto finish;
if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
@@ -3758,7 +3018,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
actually_read += bytes_read;
}
if (count) {
- bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
+ bytes_read = idetape_add_chrdev_read_request(drive, ctl);
if (bytes_read <= 0)
goto finish;
temp = min((unsigned long)count, (unsigned long)bytes_read);
@@ -3787,6 +3047,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
ide_drive_t *drive = tape->drive;
ssize_t actually_written = 0;
ssize_t ret = 0;
+ u16 ctl = *(u16 *)&tape->caps[12];
/* The drive is write protected. */
if (tape->write_prot)
@@ -3802,13 +3063,11 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
if (tape->chrdev_direction != idetape_direction_write) {
if (tape->chrdev_direction == idetape_direction_read)
idetape_discard_read_pipeline(drive, 1);
-#if IDETAPE_DEBUG_BUGS
if (tape->merge_stage || tape->merge_stage_size) {
printk(KERN_ERR "ide-tape: merge_stage_size "
"should be 0 now\n");
tape->merge_stage_size = 0;
}
-#endif /* IDETAPE_DEBUG_BUGS */
if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
return -ENOMEM;
tape->chrdev_direction = idetape_direction_write;
@@ -3836,12 +3095,10 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
if (tape->restart_speed_control_req)
idetape_restart_speed_control(drive);
if (tape->merge_stage_size) {
-#if IDETAPE_DEBUG_BUGS
if (tape->merge_stage_size >= tape->stage_size) {
printk(KERN_ERR "ide-tape: bug: merge buffer too big\n");
tape->merge_stage_size = 0;
}
-#endif /* IDETAPE_DEBUG_BUGS */
actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
ret = -EFAULT;
@@ -3852,7 +3109,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
if (tape->merge_stage_size == tape->stage_size) {
ssize_t retval;
tape->merge_stage_size = 0;
- retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
+ retval = idetape_add_chrdev_write_request(drive, ctl);
if (retval <= 0)
return (retval);
}
@@ -3863,7 +3120,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
ret = -EFAULT;
buf += tape->stage_size;
count -= tape->stage_size;
- retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
+ retval = idetape_add_chrdev_write_request(drive, ctl);
actually_written += tape->stage_size;
if (retval <= 0)
return (retval);
@@ -3891,69 +3148,20 @@ static int idetape_write_filemark (ide_drive_t *drive)
}
/*
- * idetape_mtioctop is called from idetape_chrdev_ioctl when
- * the general mtio MTIOCTOP ioctl is requested.
- *
- * We currently support the following mtio.h operations:
- *
- * MTFSF - Space over mt_count filemarks in the positive direction.
- * The tape is positioned after the last spaced filemark.
- *
- * MTFSFM - Same as MTFSF, but the tape is positioned before the
- * last filemark.
- *
- * MTBSF - Steps background over mt_count filemarks, tape is
- * positioned before the last filemark.
+ * Called from idetape_chrdev_ioctl when the general mtio MTIOCTOP ioctl is
+ * requested.
*
- * MTBSFM - Like MTBSF, only tape is positioned after the last filemark.
+ * Note: MTBSF and MTBSFM are not supported when the tape doesn't support
+ * spacing over filemarks in the reverse direction. In this case, MTFSFM is also
+ * usually not supported (it is supported in the rare case in which we crossed
+ * the filemark during our read-ahead pipelined operation mode).
*
- * Note:
+ * The following commands are currently not supported:
*
- * MTBSF and MTBSFM are not supported when the tape doesn't
- * support spacing over filemarks in the reverse direction.
- * In this case, MTFSFM is also usually not supported (it is
- * supported in the rare case in which we crossed the filemark
- * during our read-ahead pipelined operation mode).
- *
- * MTWEOF - Writes mt_count filemarks. Tape is positioned after
- * the last written filemark.
- *
- * MTREW - Rewinds tape.
- *
- * MTLOAD - Loads the tape.
- *
- * MTOFFL - Puts the tape drive "Offline": Rewinds the tape and
- * MTUNLOAD prevents further access until the media is replaced.
- *
- * MTNOP - Flushes tape buffers.
- *
- * MTRETEN - Retension media. This typically consists of one end
- * to end pass on the media.
- *
- * MTEOM - Moves to the end of recorded data.
- *
- * MTERASE - Erases tape.
- *
- * MTSETBLK - Sets the user block size to mt_count bytes. If
- * mt_count is 0, we will attempt to autodetect
- * the block size.
- *
- * MTSEEK - Positions the tape in a specific block number, where
- * each block is assumed to contain which user_block_size
- * bytes.
- *
- * MTSETPART - Switches to another tape partition.
- *
- * MTLOCK - Locks the tape door.
- *
- * MTUNLOCK - Unlocks the tape door.
- *
- * The following commands are currently not supported:
- *
- * MTFSS, MTBSS, MTWSM, MTSETDENSITY,
- * MTSETDRVBUFFER, MT_ST_BOOLEANS, MT_ST_WRITE_THRESHOLD.
+ * MTFSS, MTBSS, MTWSM, MTSETDENSITY, MTSETDRVBUFFER, MT_ST_BOOLEANS,
+ * MT_ST_WRITE_THRESHOLD.
*/
-static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count)
+static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
@@ -4068,29 +3276,12 @@ static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count)
}
/*
- * Our character device ioctls.
- *
- * General mtio.h magnetic io commands are supported here, and not in
- * the corresponding block interface.
- *
- * The following ioctls are supported:
- *
- * MTIOCTOP - Refer to idetape_mtioctop for detailed description.
- *
- * MTIOCGET - The mt_dsreg field in the returned mtget structure
- * will be set to (user block size in bytes <<
- * MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK.
- *
- * The mt_blkno is set to the current user block number.
- * The other mtget fields are not supported.
- *
- * MTIOCPOS - The current tape "block position" is returned. We
- * assume that each block contains user_block_size
- * bytes.
- *
- * Our own ide-tape ioctls are supported on both interfaces.
+ * Our character device ioctls. General mtio.h magnetic io commands are
+ * supported here, and not in the corresponding block interface. Our own
+ * ide-tape ioctls are supported on both interfaces.
*/
-static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct ide_tape_obj *tape = ide_tape_f(file);
ide_drive_t *drive = tape->drive;
@@ -4144,7 +3335,30 @@ static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigne
}
}
-static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive);
+/*
+ * Do a mode sense page 0 with block descriptor and if it succeeds set the tape
+ * block size with the reported value.
+ */
+static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
+{
+ idetape_tape_t *tape = drive->driver_data;
+ idetape_pc_t pc;
+
+ idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
+ if (idetape_queue_pc_tail(drive, &pc)) {
+ printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
+ if (tape->tape_block_size == 0) {
+ printk(KERN_WARNING "ide-tape: Cannot deal with zero "
+ "block size, assuming 32k\n");
+ tape->tape_block_size = 32768;
+ }
+ return;
+ }
+ tape->tape_block_size = (pc.buffer[4 + 5] << 16) +
+ (pc.buffer[4 + 6] << 8) +
+ pc.buffer[4 + 7];
+ tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7;
+}
/*
* Our character device open function.
@@ -4198,7 +3412,7 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
/* Read block size and write protect status from drive. */
- idetape_get_blocksize_from_block_descriptor(drive);
+ ide_tape_get_bsize_from_bdesc(drive);
/* Set write protect flag if device is opened as read-only. */
if ((filp->f_flags & O_ACCMODE) == O_RDONLY)
@@ -4310,255 +3524,106 @@ static int idetape_identify_device (ide_drive_t *drive)
{
struct idetape_id_gcw gcw;
struct hd_driveid *id = drive->id;
-#if IDETAPE_DEBUG_INFO
- unsigned short mask,i;
-#endif /* IDETAPE_DEBUG_INFO */
if (drive->id_read == 0)
return 1;
*((unsigned short *) &gcw) = id->config;
-#if IDETAPE_DEBUG_INFO
- printk(KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n");
- printk(KERN_INFO "ide-tape: Protocol Type: ");
- switch (gcw.protocol) {
- case 0: case 1: printk("ATA\n");break;
- case 2: printk("ATAPI\n");break;
- case 3: printk("Reserved (Unknown to ide-tape)\n");break;
- }
- printk(KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type);
- switch (gcw.device_type) {
- case 0: printk("Direct-access Device\n");break;
- case 1: printk("Streaming Tape Device\n");break;
- case 2: case 3: case 4: printk("Reserved\n");break;
- case 5: printk("CD-ROM Device\n");break;
- case 6: printk("Reserved\n");
- case 7: printk("Optical memory Device\n");break;
- case 0x1f: printk("Unknown or no Device type\n");break;
- default: printk("Reserved\n");
- }
- printk(KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n");
- printk(KERN_INFO "ide-tape: Command Packet DRQ Type: ");
- switch (gcw.drq_type) {
- case 0: printk("Microprocessor DRQ\n");break;
- case 1: printk("Interrupt DRQ\n");break;
- case 2: printk("Accelerated DRQ\n");break;
- case 3: printk("Reserved\n");break;
- }
- printk(KERN_INFO "ide-tape: Command Packet Size: ");
- switch (gcw.packet_size) {
- case 0: printk("12 bytes\n");break;
- case 1: printk("16 bytes\n");break;
- default: printk("Reserved\n");break;
- }
- printk(KERN_INFO "ide-tape: Model: %.40s\n",id->model);
- printk(KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev);
- printk(KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no);
- printk(KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512);
- printk(KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
- printk(KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
- printk(KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
- printk(KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
- printk(KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
- printk(KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO);
- printk(KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA);
- printk(KERN_INFO "ide-tape: Single Word DMA supported modes: ");
- for (i=0,mask=1;i<8;i++,mask=mask << 1) {
- if (id->dma_1word & mask)
- printk("%d ",i);
- if (id->dma_1word & (mask << 8))
- printk("(active) ");
- }
- printk("\n");
- printk(KERN_INFO "ide-tape: Multi Word DMA supported modes: ");
- for (i=0,mask=1;i<8;i++,mask=mask << 1) {
- if (id->dma_mword & mask)
- printk("%d ",i);
- if (id->dma_mword & (mask << 8))
- printk("(active) ");
- }
- printk("\n");
- if (id->field_valid & 0x0002) {
- printk(KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",
- id->eide_pio_modes & 1 ? "Mode 3":"None");
- printk(KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: ");
- if (id->eide_dma_min == 0)
- printk("Not supported\n");
- else
- printk("%d ns\n",id->eide_dma_min);
-
- printk(KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: ");
- if (id->eide_dma_time == 0)
- printk("Not supported\n");
- else
- printk("%d ns\n",id->eide_dma_time);
-
- printk(KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: ");
- if (id->eide_pio == 0)
- printk("Not supported\n");
- else
- printk("%d ns\n",id->eide_pio);
-
- printk(KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: ");
- if (id->eide_pio_iordy == 0)
- printk("Not supported\n");
- else
- printk("%d ns\n",id->eide_pio_iordy);
-
- } else
- printk(KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n");
-#endif /* IDETAPE_DEBUG_INFO */
-
/* Check that we can support this device */
- if (gcw.protocol !=2 )
- printk(KERN_ERR "ide-tape: Protocol is not ATAPI\n");
+ if (gcw.protocol != 2)
+ printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n",
+ gcw.protocol);
else if (gcw.device_type != 1)
- printk(KERN_ERR "ide-tape: Device type is not set to tape\n");
+ printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set "
+ "to tape\n", gcw.device_type);
else if (!gcw.removable)
printk(KERN_ERR "ide-tape: The removable flag is not set\n");
else if (gcw.packet_size != 0) {
- printk(KERN_ERR "ide-tape: Packet size is not 12 bytes long\n");
- if (gcw.packet_size == 1)
- printk(KERN_ERR "ide-tape: Sorry, padding to 16 bytes is still not supported\n");
+ printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12 "
+ "bytes long\n", gcw.packet_size);
} else
return 1;
return 0;
}
-/*
- * Use INQUIRY to get the firmware revision
- */
-static void idetape_get_inquiry_results (ide_drive_t *drive)
+static void idetape_get_inquiry_results(ide_drive_t *drive)
{
char *r;
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
- idetape_inquiry_result_t *inquiry;
-
+
idetape_create_inquiry_cmd(&pc);
if (idetape_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name);
+ printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
+ tape->name);
return;
}
- inquiry = (idetape_inquiry_result_t *) pc.buffer;
- memcpy(tape->vendor_id, inquiry->vendor_id, 8);
- memcpy(tape->product_id, inquiry->product_id, 16);
- memcpy(tape->firmware_revision, inquiry->revision_level, 4);
+ memcpy(tape->vendor_id, &pc.buffer[8], 8);
+ memcpy(tape->product_id, &pc.buffer[16], 16);
+ memcpy(tape->firmware_revision, &pc.buffer[32], 4);
+
ide_fixstring(tape->vendor_id, 10, 0);
ide_fixstring(tape->product_id, 18, 0);
ide_fixstring(tape->firmware_revision, 6, 0);
r = tape->firmware_revision;
if (*(r + 1) == '.')
- tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0';
- printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision);
+ tape->firmware_revision_num = (*r - '0') * 100 +
+ (*(r + 2) - '0') * 10 + *(r + 3) - '0';
+ printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n",
+ drive->name, tape->name, tape->vendor_id,
+ tape->product_id, tape->firmware_revision);
}
/*
- * idetape_get_mode_sense_results asks the tape about its various
- * parameters. In particular, we will adjust our data transfer buffer
- * size to the recommended value as returned by the tape.
+ * Ask the tape about its various parameters. In particular, we will adjust our
+ * data transfer buffer size to the recommended value as returned by the tape.
*/
static void idetape_get_mode_sense_results (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
- idetape_mode_parameter_header_t *header;
- idetape_capabilities_page_t *capabilities;
-
+ u8 *caps;
+ u8 speed, max_speed;
+
idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
if (idetape_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n");
+ printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
+ " some default values\n");
tape->tape_block_size = 512;
- tape->capabilities.ctl = 52;
- tape->capabilities.speed = 450;
- tape->capabilities.buffer_size = 6 * 52;
+ put_unaligned(52, (u16 *)&tape->caps[12]);
+ put_unaligned(540, (u16 *)&tape->caps[14]);
+ put_unaligned(6*52, (u16 *)&tape->caps[16]);
return;
}
- header = (idetape_mode_parameter_header_t *) pc.buffer;
- capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
+ caps = pc.buffer + 4 + pc.buffer[3];
- capabilities->max_speed = ntohs(capabilities->max_speed);
- capabilities->ctl = ntohs(capabilities->ctl);
- capabilities->speed = ntohs(capabilities->speed);
- capabilities->buffer_size = ntohs(capabilities->buffer_size);
+ /* convert to host order and save for later use */
+ speed = be16_to_cpu(*(u16 *)&caps[14]);
+ max_speed = be16_to_cpu(*(u16 *)&caps[8]);
- if (!capabilities->speed) {
- printk(KERN_INFO "ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name);
- capabilities->speed = 650;
+ put_unaligned(max_speed, (u16 *)&caps[8]);
+ put_unaligned(be16_to_cpu(*(u16 *)&caps[12]), (u16 *)&caps[12]);
+ put_unaligned(speed, (u16 *)&caps[14]);
+ put_unaligned(be16_to_cpu(*(u16 *)&caps[16]), (u16 *)&caps[16]);
+
+ if (!speed) {
+ printk(KERN_INFO "ide-tape: %s: invalid tape speed "
+ "(assuming 650KB/sec)\n", drive->name);
+ put_unaligned(650, (u16 *)&caps[14]);
}
- if (!capabilities->max_speed) {
- printk(KERN_INFO "ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name);
- capabilities->max_speed = 650;
+ if (!max_speed) {
+ printk(KERN_INFO "ide-tape: %s: invalid max_speed "
+ "(assuming 650KB/sec)\n", drive->name);
+ put_unaligned(650, (u16 *)&caps[8]);
}
- tape->capabilities = *capabilities; /* Save us a copy */
- if (capabilities->blk512)
+ memcpy(&tape->caps, caps, 20);
+ if (caps[7] & 0x02)
tape->tape_block_size = 512;
- else if (capabilities->blk1024)
+ else if (caps[7] & 0x04)
tape->tape_block_size = 1024;
-
-#if IDETAPE_DEBUG_INFO
- printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n");
- printk(KERN_INFO "ide-tape: Mode Parameter Header:\n");
- printk(KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length);
- printk(KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type);
- printk(KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp);
- printk(KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl);
-
- printk(KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n");
- printk(KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code);
- printk(KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length);
- printk(KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No");
- printk(KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No");
- printk(KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed);
- printk(KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl);
- printk(KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed);
- printk(KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512);
-#endif /* IDETAPE_DEBUG_INFO */
-}
-
-/*
- * ide_get_blocksize_from_block_descriptor does a mode sense page 0 with block descriptor
- * and if it succeeds sets the tape block size with the reported value
- */
-static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive)
-{
-
- idetape_tape_t *tape = drive->driver_data;
- idetape_pc_t pc;
- idetape_mode_parameter_header_t *header;
- idetape_parameter_block_descriptor_t *block_descrp;
-
- idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
- if (idetape_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
- if (tape->tape_block_size == 0) {
- printk(KERN_WARNING "ide-tape: Cannot deal with zero block size, assume 32k\n");
- tape->tape_block_size = 32768;
- }
- return;
- }
- header = (idetape_mode_parameter_header_t *) pc.buffer;
- block_descrp = (idetape_parameter_block_descriptor_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t));
- tape->tape_block_size =( block_descrp->length[0]<<16) + (block_descrp->length[1]<<8) + block_descrp->length[2];
- tape->drv_write_prot = (header->dsp & 0x80) >> 7;
-
-#if IDETAPE_DEBUG_INFO
- printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size);
-#endif /* IDETAPE_DEBUG_INFO */
}
#ifdef CONFIG_IDE_PROC_FS
@@ -4569,13 +3634,15 @@ static void idetape_add_settings (ide_drive_t *drive)
/*
* drive setting name read/write data type min max mul_factor div_factor data pointer set function
*/
- ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL);
+ ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
+ 1, 2, (u16 *)&tape->caps[16], NULL);
ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL);
ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL);
ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL);
- ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL);
+ ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
+ 1, 1, (u16 *)&tape->caps[14], NULL);
ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL);
ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL);
ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
@@ -4607,22 +3674,15 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
struct idetape_id_gcw gcw;
int stage_size;
struct sysinfo si;
+ u16 *ctl = (u16 *)&tape->caps[12];
spin_lock_init(&tape->spinlock);
drive->dsc_overlap = 1;
-#ifdef CONFIG_BLK_DEV_IDEPCI
- if (HWIF(drive)->pci_dev != NULL) {
- /*
- * These two ide-pci host adapters appear to need DSC overlap disabled.
- * This probably needs further analysis.
- */
- if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
- (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
- printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name);
- drive->dsc_overlap = 0;
- }
+ if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
+ printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
+ tape->name);
+ drive->dsc_overlap = 0;
}
-#endif /* CONFIG_BLK_DEV_IDEPCI */
/* Seagate Travan drives do not support DSC overlap. */
if (strstr(drive->id->model, "Seagate STT3401"))
drive->dsc_overlap = 0;
@@ -4642,13 +3702,13 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
idetape_get_inquiry_results(drive);
idetape_get_mode_sense_results(drive);
- idetape_get_blocksize_from_block_descriptor(drive);
+ ide_tape_get_bsize_from_bdesc(drive);
tape->user_bs_factor = 1;
- tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
+ tape->stage_size = *ctl * tape->tape_block_size;
while (tape->stage_size > 0xffff) {
printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
- tape->capabilities.ctl /= 2;
- tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
+ *ctl /= 2;
+ tape->stage_size = *ctl * tape->tape_block_size;
}
stage_size = tape->stage_size;
tape->pages_per_stage = stage_size / PAGE_SIZE;
@@ -4657,11 +3717,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE;
}
- /*
- * Select the "best" DSC read/write polling frequency
- * and pipeline size.
- */
- speed = max(tape->capabilities.speed, tape->capabilities.max_speed);
+ /* Select the "best" DSC read/write polling freq and pipeline size. */
+ speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
tape->max_stages = speed * 1000 * 10 / tape->stage_size;
@@ -4678,7 +3735,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1;
t1 = (tape->stage_size * HZ) / (speed * 1000);
- tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125);
+ tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125);
tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
if (tape->max_stages)
@@ -4693,8 +3750,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
tape->best_dsc_rw_frequency = max_t(unsigned long, min_t(unsigned long, t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
"%dkB pipeline, %lums tDSC%s\n",
- drive->name, tape->name, tape->capabilities.speed,
- (tape->capabilities.buffer_size * 512) / tape->stage_size,
+ drive->name, tape->name, *(u16 *)&tape->caps[14],
+ (*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
tape->stage_size / 1024,
tape->max_stages * tape->stage_size / 1024,
tape->best_dsc_rw_frequency * 1000 / HZ,
@@ -4724,10 +3781,8 @@ static void ide_tape_release(struct kref *kref)
drive->dsc_overlap = 0;
drive->driver_data = NULL;
- class_device_destroy(idetape_sysfs_class,
- MKDEV(IDETAPE_MAJOR, tape->minor));
- class_device_destroy(idetape_sysfs_class,
- MKDEV(IDETAPE_MAJOR, tape->minor + 128));
+ device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
+ device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor + 128));
idetape_devs[tape->minor] = NULL;
g->private_data = NULL;
put_disk(g);
@@ -4884,10 +3939,10 @@ static int ide_tape_probe(ide_drive_t *drive)
idetape_setup(drive, tape, minor);
- class_device_create(idetape_sysfs_class, NULL,
- MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name);
- class_device_create(idetape_sysfs_class, NULL,
- MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name);
+ device_create(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name);
+ device_create(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name);
g->fops = &idetape_block_ops;
ide_register_region(g);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index d066546f283..4e1da1c78cb 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -1,11 +1,9 @@
/*
- * linux/drivers/ide/ide-taskfile.c Version 0.38 March 05, 2003
- *
- * Copyright (C) 2000-2002 Michael Cornwell <cornwell@acm.org>
- * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2001-2002 Klaus Smolin
+ * Copyright (C) 2000-2002 Michael Cornwell <cornwell@acm.org>
+ * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2001-2002 Klaus Smolin
* IBM Storage Technology Division
- * Copyright (C) 2003-2004 Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2003-2004, 2007 Bartlomiej Zolnierkiewicz
*
* The big the bad and the ugly.
*/
@@ -35,93 +33,81 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-static void ata_bswap_data (void *buffer, int wcount)
-{
- u16 *p = buffer;
-
- while (wcount--) {
- *p = *p << 8 | *p >> 8; p++;
- *p = *p << 8 | *p >> 8; p++;
- }
-}
-
-static void taskfile_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
{
- HWIF(drive)->ata_input_data(drive, buffer, wcount);
- if (drive->bswap)
- ata_bswap_data(buffer, wcount);
-}
+ ide_hwif_t *hwif = drive->hwif;
+ struct ide_taskfile *tf = &task->tf;
+ u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+
+ if (task->tf_flags & IDE_TFLAG_FLAGGED)
+ HIHI = 0xFF;
+
+#ifdef DEBUG
+ printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
+ "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
+ drive->name, tf->feature, tf->nsect, tf->lbal,
+ tf->lbam, tf->lbah, tf->device, tf->command);
+ printk("%s: hob: nsect 0x%02x lbal 0x%02x "
+ "lbam 0x%02x lbah 0x%02x\n",
+ drive->name, tf->hob_nsect, tf->hob_lbal,
+ tf->hob_lbam, tf->hob_lbah);
+#endif
-static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
-{
- if (drive->bswap) {
- ata_bswap_data(buffer, wcount);
- HWIF(drive)->ata_output_data(drive, buffer, wcount);
- ata_bswap_data(buffer, wcount);
- } else {
- HWIF(drive)->ata_output_data(drive, buffer, wcount);
- }
+ ide_set_irq(drive, 1);
+
+ if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
+ SELECT_MASK(drive, 0);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DATA)
+ hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+ hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+ hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+ hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+ hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+ hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+ hwif->OUTB(tf->feature, IDE_FEATURE_REG);
+ if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+ hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+ hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+ hwif->OUTB(tf->lbam, IDE_LCYL_REG);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+ hwif->OUTB(tf->lbah, IDE_HCYL_REG);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+ hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
}
int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
{
ide_task_t args;
+
memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
+ args.tf.nsect = 0x01;
if (drive->media == ide_disk)
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY;
+ args.tf.command = WIN_IDENTIFY;
else
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY;
- args.command_type = IDE_DRIVE_TASK_IN;
- args.data_phase = TASKFILE_IN;
- args.handler = &task_in_intr;
- return ide_raw_taskfile(drive, &args, buf);
+ args.tf.command = WIN_PIDENTIFY;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ args.data_phase = TASKFILE_IN;
+ return ide_raw_taskfile(drive, &args, buf, 1);
}
-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+static int inline task_dma_ok(ide_task_t *task)
{
- ide_hwif_t *hwif = HWIF(drive);
- task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
- hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
- u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF;
-
- /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
- if (IDE_CONTROL_REG) {
- /* clear nIEN */
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
- }
- SELECT_MASK(drive, 0);
-
- if (drive->addressing == 1) {
- hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
- hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
- hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
- hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
- hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
- }
-
- hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
- hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
- hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
- hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
- hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
-
- hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
-
- if (task->handler != NULL) {
- if (task->prehandler != NULL) {
- hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
- ndelay(400); /* FIXME */
- return task->prehandler(drive, task->rq);
- }
- ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
- return ide_started;
- }
-
- if (!drive->using_dma)
- return ide_stopped;
+ if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED))
+ return 1;
- switch (taskfile->command) {
+ switch (task->tf.command) {
case WIN_WRITEDMA_ONCE:
case WIN_WRITEDMA:
case WIN_WRITEDMA_EXT:
@@ -129,24 +115,79 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
case WIN_READDMA:
case WIN_READDMA_EXT:
case WIN_IDENTIFY_DMA:
- if (!hwif->dma_setup(drive)) {
- hwif->dma_exec_cmd(drive, taskfile->command);
- hwif->dma_start(drive);
- return ide_started;
- }
- break;
- default:
- if (task->handler == NULL)
- return ide_stopped;
+ return 1;
}
- return ide_stopped;
+ return 0;
}
+static ide_startstop_t task_no_data_intr(ide_drive_t *);
+static ide_startstop_t set_geometry_intr(ide_drive_t *);
+static ide_startstop_t recal_intr(ide_drive_t *);
+static ide_startstop_t set_multmode_intr(ide_drive_t *);
+static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
+static ide_startstop_t task_in_intr(ide_drive_t *);
+
+ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ struct ide_taskfile *tf = &task->tf;
+ ide_handler_t *handler = NULL;
+
+ if (task->data_phase == TASKFILE_MULTI_IN ||
+ task->data_phase == TASKFILE_MULTI_OUT) {
+ if (!drive->mult_count) {
+ printk(KERN_ERR "%s: multimode not set!\n",
+ drive->name);
+ return ide_stopped;
+ }
+ }
+
+ if (task->tf_flags & IDE_TFLAG_FLAGGED)
+ task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
+
+ if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0)
+ ide_tf_load(drive, task);
+
+ switch (task->data_phase) {
+ case TASKFILE_MULTI_OUT:
+ case TASKFILE_OUT:
+ hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG);
+ ndelay(400); /* FIXME */
+ return pre_task_out_intr(drive, task->rq);
+ case TASKFILE_MULTI_IN:
+ case TASKFILE_IN:
+ handler = task_in_intr;
+ /* fall-through */
+ case TASKFILE_NO_DATA:
+ if (handler == NULL)
+ handler = task_no_data_intr;
+ /* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */
+ if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
+ switch (tf->command) {
+ case WIN_SPECIFY: handler = set_geometry_intr; break;
+ case WIN_RESTORE: handler = recal_intr; break;
+ case WIN_SETMULT: handler = set_multmode_intr; break;
+ }
+ }
+ ide_execute_command(drive, tf->command, handler,
+ WAIT_WORSTCASE, NULL);
+ return ide_started;
+ default:
+ if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
+ hwif->dma_setup(drive))
+ return ide_stopped;
+ hwif->dma_exec_cmd(drive, tf->command);
+ hwif->dma_start(drive);
+ return ide_started;
+ }
+}
+EXPORT_SYMBOL_GPL(do_rw_taskfile);
+
/*
* set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
*/
-ide_startstop_t set_multmode_intr (ide_drive_t *drive)
+static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 stat;
@@ -164,7 +205,7 @@ ide_startstop_t set_multmode_intr (ide_drive_t *drive)
/*
* set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
*/
-ide_startstop_t set_geometry_intr (ide_drive_t *drive)
+static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
int retries = 5;
@@ -187,7 +228,7 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive)
/*
* recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
*/
-ide_startstop_t recal_intr (ide_drive_t *drive)
+static ide_startstop_t recal_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 stat;
@@ -200,7 +241,7 @@ ide_startstop_t recal_intr (ide_drive_t *drive)
/*
* Handler for commands without a data phase
*/
-ide_startstop_t task_no_data_intr (ide_drive_t *drive)
+static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{
ide_task_t *args = HWGROUP(drive)->rq->special;
ide_hwif_t *hwif = HWIF(drive);
@@ -217,8 +258,6 @@ ide_startstop_t task_no_data_intr (ide_drive_t *drive)
return ide_stopped;
}
-EXPORT_SYMBOL(task_no_data_intr);
-
static u8 wait_drive_not_busy(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -227,8 +266,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
/*
* Last sector was transfered, wait until drive is ready.
- * This can take up to 10 usec, but we will wait max 1 ms
- * (drive_cmd_intr() waits that long).
+ * This can take up to 10 usec, but we will wait max 1 ms.
*/
for (retries = 0; retries < 100; retries++) {
if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT)
@@ -283,9 +321,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
/* do the actual data transfer */
if (write)
- taskfile_output_data(drive, buf, SECTOR_WORDS);
+ hwif->ata_output_data(drive, buf, SECTOR_WORDS);
else
- taskfile_input_data(drive, buf, SECTOR_WORDS);
+ hwif->ata_input_data(drive, buf, SECTOR_WORDS);
kunmap_atomic(buf, KM_BIO_SRC_IRQ);
#ifdef CONFIG_HIGHMEM
@@ -305,9 +343,18 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
unsigned int write)
{
+ u8 saved_io_32bit = drive->io_32bit;
+
if (rq->bio) /* fs request */
rq->errors = 0;
+ if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+ ide_task_t *task = rq->special;
+
+ if (task->tf_flags & IDE_TFLAG_IO_16BIT)
+ drive->io_32bit = 0;
+ }
+
touch_softlockup_watchdog();
switch (drive->hwif->data_phase) {
@@ -319,6 +366,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
ide_pio_sector(drive, write);
break;
}
+
+ drive->io_32bit = saved_io_32bit;
}
static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
@@ -356,40 +405,35 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
return ide_error(drive, s, stat);
}
-static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
+void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
{
- HWIF(drive)->cursg = NULL;
-
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
- ide_task_t *task = rq->special;
+ u8 err = drive->hwif->INB(IDE_ERROR_REG);
- if (task->tf_out_flags.all) {
- u8 err = drive->hwif->INB(IDE_ERROR_REG);
- ide_end_drive_cmd(drive, stat, err);
- return;
- }
+ ide_end_drive_cmd(drive, stat, err);
+ return;
}
if (rq->rq_disk) {
ide_driver_t *drv;
drv = *(ide_driver_t **)rq->rq_disk->private_data;;
- drv->end_request(drive, 1, rq->hard_nr_sectors);
+ drv->end_request(drive, 1, rq->nr_sectors);
} else
- ide_end_request(drive, 1, rq->hard_nr_sectors);
+ ide_end_request(drive, 1, rq->nr_sectors);
}
/*
* Handler for command with PIO data-in phase (Read/Read Multiple).
*/
-ide_startstop_t task_in_intr (ide_drive_t *drive)
+static ide_startstop_t task_in_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
u8 stat = hwif->INB(IDE_STATUS_REG);
/* new way for dealing with premature shared PCI interrupts */
- if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
+ if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
if (stat & (ERR_STAT | DRQ_STAT))
return task_error(drive, rq, __FUNCTION__, stat);
/* No data yet, so wait for another IRQ. */
@@ -402,7 +446,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
/* If it was the last datablock check status and finish transfer. */
if (!hwif->nleft) {
stat = wait_drive_not_busy(drive);
- if (!OK_STAT(stat, 0, BAD_R_STAT))
+ if (!OK_STAT(stat, 0, BAD_STAT))
return task_error(drive, rq, __FUNCTION__, stat);
task_end_request(drive, rq, stat);
return ide_stopped;
@@ -413,7 +457,6 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
return ide_started;
}
-EXPORT_SYMBOL(task_in_intr);
/*
* Handler for command with PIO data-out phase (Write/Write Multiple).
@@ -443,11 +486,11 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
return ide_started;
}
-ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
- if (ide_wait_stat(&startstop, drive, DATA_READY,
+ if (ide_wait_stat(&startstop, drive, DRQ_STAT,
drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
drive->name,
@@ -464,13 +507,13 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
return ide_started;
}
-EXPORT_SYMBOL(pre_task_out_intr);
-static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
+int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
{
struct request rq;
memset(&rq, 0, sizeof(rq));
+ rq.ref_count = 1;
rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
rq.buffer = buf;
@@ -480,50 +523,41 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
* if we would find a solution to transfer any size.
* To support special commands like READ LONG.
*/
- if (args->command_type != IDE_DRIVE_TASK_NO_DATA) {
- if (data_size == 0)
- rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
- else
- rq.nr_sectors = data_size / SECTOR_SIZE;
-
- if (!rq.nr_sectors) {
- printk(KERN_ERR "%s: in/out command without data\n",
- drive->name);
- return -EFAULT;
- }
+ rq.hard_nr_sectors = rq.nr_sectors = nsect;
+ rq.hard_cur_sectors = rq.current_nr_sectors = nsect;
- rq.hard_nr_sectors = rq.nr_sectors;
- rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
+ if (task->tf_flags & IDE_TFLAG_WRITE)
+ rq.cmd_flags |= REQ_RW;
- if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
- rq.cmd_flags |= REQ_RW;
- }
+ rq.special = task;
+ task->rq = &rq;
- rq.special = args;
- args->rq = &rq;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
-int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
+EXPORT_SYMBOL(ide_raw_taskfile);
+
+int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task)
{
- return ide_diag_taskfile(drive, args, 0, buf);
-}
+ task->data_phase = TASKFILE_NO_DATA;
-EXPORT_SYMBOL(ide_raw_taskfile);
+ return ide_raw_taskfile(drive, task, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
+#ifdef CONFIG_IDE_TASK_IOCTL
int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
ide_task_request_t *req_task;
ide_task_t args;
u8 *outbuf = NULL;
u8 *inbuf = NULL;
- task_ioreg_t *argsptr = args.tfRegister;
- task_ioreg_t *hobsptr = args.hobRegister;
+ u8 *data_buf = NULL;
int err = 0;
int tasksize = sizeof(struct ide_task_request_s);
unsigned int taskin = 0;
unsigned int taskout = 0;
- u8 io_32bit = drive->io_32bit;
+ u16 nsect = 0;
char __user *buf = (char __user *)arg;
// printk("IDE Taskfile ...\n");
@@ -570,24 +604,52 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
}
memset(&args, 0, sizeof(ide_task_t));
- memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
- memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
- args.tf_in_flags = req_task->in_flags;
- args.tf_out_flags = req_task->out_flags;
- args.data_phase = req_task->data_phase;
- args.command_type = req_task->req_cmd;
+ memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
+ memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
+
+ args.data_phase = req_task->data_phase;
+
+ args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
+ IDE_TFLAG_IN_TF;
+ if (drive->addressing == 1)
+ args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
+
+ if (req_task->out_flags.all) {
+ args.tf_flags |= IDE_TFLAG_FLAGGED;
+
+ if (req_task->out_flags.b.data)
+ args.tf_flags |= IDE_TFLAG_OUT_DATA;
+
+ if (req_task->out_flags.b.nsector_hob)
+ args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT;
+ if (req_task->out_flags.b.sector_hob)
+ args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL;
+ if (req_task->out_flags.b.lcyl_hob)
+ args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM;
+ if (req_task->out_flags.b.hcyl_hob)
+ args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH;
+
+ if (req_task->out_flags.b.error_feature)
+ args.tf_flags |= IDE_TFLAG_OUT_FEATURE;
+ if (req_task->out_flags.b.nsector)
+ args.tf_flags |= IDE_TFLAG_OUT_NSECT;
+ if (req_task->out_flags.b.sector)
+ args.tf_flags |= IDE_TFLAG_OUT_LBAL;
+ if (req_task->out_flags.b.lcyl)
+ args.tf_flags |= IDE_TFLAG_OUT_LBAM;
+ if (req_task->out_flags.b.hcyl)
+ args.tf_flags |= IDE_TFLAG_OUT_LBAH;
+ } else {
+ args.tf_flags |= IDE_TFLAG_OUT_TF;
+ if (args.tf_flags & IDE_TFLAG_LBA48)
+ args.tf_flags |= IDE_TFLAG_OUT_HOB;
+ }
+
+ if (req_task->in_flags.b.data)
+ args.tf_flags |= IDE_TFLAG_IN_DATA;
- drive->io_32bit = 0;
switch(req_task->data_phase) {
- case TASKFILE_OUT_DMAQ:
- case TASKFILE_OUT_DMA:
- err = ide_diag_taskfile(drive, &args, taskout, outbuf);
- break;
- case TASKFILE_IN_DMAQ:
- case TASKFILE_IN_DMA:
- err = ide_diag_taskfile(drive, &args, taskin, inbuf);
- break;
case TASKFILE_MULTI_OUT:
if (!drive->mult_count) {
/* (hs): give up if multcount is not set */
@@ -599,9 +661,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
}
/* fall through */
case TASKFILE_OUT:
- args.prehandler = &pre_task_out_intr;
- args.handler = &task_out_intr;
- err = ide_diag_taskfile(drive, &args, taskout, outbuf);
+ /* fall through */
+ case TASKFILE_OUT_DMAQ:
+ case TASKFILE_OUT_DMA:
+ nsect = taskout / SECTOR_SIZE;
+ data_buf = outbuf;
break;
case TASKFILE_MULTI_IN:
if (!drive->mult_count) {
@@ -614,22 +678,46 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
}
/* fall through */
case TASKFILE_IN:
- args.handler = &task_in_intr;
- err = ide_diag_taskfile(drive, &args, taskin, inbuf);
+ /* fall through */
+ case TASKFILE_IN_DMAQ:
+ case TASKFILE_IN_DMA:
+ nsect = taskin / SECTOR_SIZE;
+ data_buf = inbuf;
break;
case TASKFILE_NO_DATA:
- args.handler = &task_no_data_intr;
- err = ide_diag_taskfile(drive, &args, 0, NULL);
break;
default:
err = -EFAULT;
goto abort;
}
- memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
- memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
- req_task->in_flags = args.tf_in_flags;
- req_task->out_flags = args.tf_out_flags;
+ if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
+ nsect = 0;
+ else if (!nsect) {
+ nsect = (args.tf.hob_nsect << 8) | args.tf.nsect;
+
+ if (!nsect) {
+ printk(KERN_ERR "%s: in/out command without data\n",
+ drive->name);
+ err = -EFAULT;
+ goto abort;
+ }
+ }
+
+ if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE)
+ args.tf_flags |= IDE_TFLAG_WRITE;
+
+ err = ide_raw_taskfile(drive, &args, data_buf, nsect);
+
+ memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2);
+ memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE);
+
+ if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
+ req_task->in_flags.all == 0) {
+ req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
+ if (drive->addressing == 1)
+ req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
+ }
if (copy_to_user(buf, req_task, tasksize)) {
err = -EFAULT;
@@ -656,39 +744,25 @@ abort:
// printk("IDE Taskfile ioctl ended. rc = %i\n", err);
- drive->io_32bit = io_32bit;
-
return err;
}
-
-int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf)
-{
- struct request rq;
- u8 buffer[4];
-
- if (!buf)
- buf = buffer;
- memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
- ide_init_drive_cmd(&rq);
- rq.buffer = buf;
- *buf++ = cmd;
- *buf++ = nsect;
- *buf++ = feature;
- *buf++ = sectors;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
+#endif
int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
- int err = 0;
- u8 args[4], *argbuf = args;
- u8 xfer_rate = 0;
- int argsize = 4;
+ u8 *buf = NULL;
+ int bufsize = 0, err = 0;
+ u8 args[4], xfer_rate = 0;
ide_task_t tfargs;
+ struct ide_taskfile *tf = &tfargs.tf;
+ struct hd_driveid *id = drive->id;
if (NULL == (void *) arg) {
struct request rq;
+
ide_init_drive_cmd(&rq);
+ rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
@@ -696,27 +770,46 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
return -EFAULT;
memset(&tfargs, 0, sizeof(ide_task_t));
- tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
- tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
- tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1];
- tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00;
- tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00;
- tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00;
- tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
+ tf->feature = args[2];
+ if (args[0] == WIN_SMART) {
+ tf->nsect = args[3];
+ tf->lbal = args[1];
+ tf->lbam = 0x4f;
+ tf->lbah = 0xc2;
+ tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
+ } else {
+ tf->nsect = args[1];
+ tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
+ IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
+ }
+ tf->command = args[0];
+ tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
if (args[3]) {
- argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
- argbuf = kzalloc(argsize, GFP_KERNEL);
- if (argbuf == NULL)
+ tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
+ bufsize = SECTOR_WORDS * 4 * args[3];
+ buf = kzalloc(bufsize, GFP_KERNEL);
+ if (buf == NULL)
return -ENOMEM;
}
- if (set_transfer(drive, &tfargs)) {
+
+ if (tf->command == WIN_SETFEATURES &&
+ tf->feature == SETFEATURES_XFER &&
+ tf->nsect >= XFER_SW_DMA_0 &&
+ (id->dma_ultra || id->dma_mword || id->dma_1word)) {
xfer_rate = args[1];
- if (ide_ata66_check(drive, &tfargs))
+ if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
+ printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
+ "be set\n", drive->name);
goto abort;
+ }
}
- err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
+ err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
+
+ args[0] = tf->status;
+ args[1] = tf->error;
+ args[2] = tf->nsect;
if (!err && xfer_rate) {
/* active-retuning-calls future */
@@ -724,142 +817,38 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
ide_driveid_update(drive);
}
abort:
- if (copy_to_user((void __user *)arg, argbuf, argsize))
+ if (copy_to_user((void __user *)arg, &args, 4))
err = -EFAULT;
- if (argsize > 4)
- kfree(argbuf);
+ if (buf) {
+ if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
+ err = -EFAULT;
+ kfree(buf);
+ }
return err;
}
-static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
-{
- struct request rq;
-
- ide_init_drive_cmd(&rq);
- rq.cmd_type = REQ_TYPE_ATA_TASK;
- rq.buffer = buf;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
void __user *p = (void __user *)arg;
int err = 0;
- u8 args[7], *argbuf = args;
- int argsize = 7;
+ u8 args[7];
+ ide_task_t task;
if (copy_from_user(args, p, 7))
return -EFAULT;
- err = ide_wait_cmd_task(drive, argbuf);
- if (copy_to_user(p, argbuf, argsize))
- err = -EFAULT;
- return err;
-}
-/*
- * NOTICE: This is additions from IBM to provide a discrete interface,
- * for selective taskregister access operations. Nice JOB Klaus!!!
- * Glad to be able to work and co-develop this with you and IBM.
- */
-ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
-{
- ide_hwif_t *hwif = HWIF(drive);
- task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
- hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
+ memset(&task, 0, sizeof(task));
+ memcpy(&task.tf_array[7], &args[1], 6);
+ task.tf.command = args[0];
+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- if (task->data_phase == TASKFILE_MULTI_IN ||
- task->data_phase == TASKFILE_MULTI_OUT) {
- if (!drive->mult_count) {
- printk(KERN_ERR "%s: multimode not set!\n", drive->name);
- return ide_stopped;
- }
- }
-
- /*
- * (ks) Check taskfile in flags.
- * If set, then execute as it is defined.
- * If not set, then define default settings.
- * The default values are:
- * read all taskfile registers (except data)
- * read the hob registers (sector, nsector, lcyl, hcyl)
- */
- if (task->tf_in_flags.all == 0) {
- task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
- if (drive->addressing == 1)
- task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
- }
-
- /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
- if (IDE_CONTROL_REG)
- /* clear nIEN */
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
- SELECT_MASK(drive, 0);
-
- if (task->tf_out_flags.b.data) {
- u16 data = taskfile->data + (hobfile->data << 8);
- hwif->OUTW(data, IDE_DATA_REG);
- }
-
- /* (ks) send hob registers first */
- if (task->tf_out_flags.b.nsector_hob)
- hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
- if (task->tf_out_flags.b.sector_hob)
- hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl_hob)
- hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl_hob)
- hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
-
- /* (ks) Send now the standard registers */
- if (task->tf_out_flags.b.error_feature)
- hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
- /* refers to number of sectors to transfer */
- if (task->tf_out_flags.b.nsector)
- hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
- /* refers to sector offset or start sector */
- if (task->tf_out_flags.b.sector)
- hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl)
- hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl)
- hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
-
- /*
- * (ks) In the flagged taskfile approch, we will use all specified
- * registers and the register value will not be changed, except the
- * select bit (master/slave) in the drive_head register. We must make
- * sure that the desired drive is selected.
- */
- hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
- switch(task->data_phase) {
+ err = ide_no_data_taskfile(drive, &task);
- case TASKFILE_OUT_DMAQ:
- case TASKFILE_OUT_DMA:
- case TASKFILE_IN_DMAQ:
- case TASKFILE_IN_DMA:
- if (!drive->using_dma)
- break;
+ args[0] = task.tf.command;
+ memcpy(&args[1], &task.tf_array[7], 6);
- if (!hwif->dma_setup(drive)) {
- hwif->dma_exec_cmd(drive, taskfile->command);
- hwif->dma_start(drive);
- return ide_started;
- }
- break;
-
- default:
- if (task->handler == NULL)
- return ide_stopped;
-
- /* Issue the command */
- if (task->prehandler) {
- hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
- ndelay(400); /* FIXME */
- return task->prehandler(drive, task->rq);
- }
- ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
- return ide_started;
- }
+ if (copy_to_user(p, args, 7))
+ err = -EFAULT;
- return ide_stopped;
+ return err;
}
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index daffbb9797e..adeda762652 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -2,8 +2,6 @@
#define _IDE_TIMING_H
/*
- * $Id: ide-timing.h,v 1.6 2001/12/23 22:47:56 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 674a65c1a13..ac613600161 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1,7 +1,6 @@
/*
- * linux/drivers/ide/ide.c Version 7.00beta2 Mar 05 2003
- *
- * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
+ * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
+ * Copyrifht (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
*/
/*
@@ -46,7 +45,6 @@
*/
#define REVISION "Revision: 7.00alpha2"
-#define VERSION "Id: ide.c 7.00a2 20020906"
#define _IDE_C /* Tell ide.h it's really us */
@@ -95,7 +93,7 @@ DEFINE_MUTEX(ide_cfg_mtx);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
-static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
+int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
#endif
int noautodma = 0;
@@ -116,7 +114,7 @@ EXPORT_SYMBOL(ide_hwifs);
/*
* Do not even *think* about calling this!
*/
-static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
+void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
{
unsigned int unit;
@@ -159,6 +157,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
init_completion(&drive->gendev_rel_comp);
}
}
+EXPORT_SYMBOL_GPL(ide_init_port_data);
static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
{
@@ -177,8 +176,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
#endif
}
-extern void ide_arm_init(void);
-
/*
* init_ide_data() sets reasonable default values into all fields
* of all instances of the hwifs and drives, but only on the first call.
@@ -210,16 +207,13 @@ static void __init init_ide_data (void)
/* Initialise all interface structures */
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
- init_hwif_data(hwif, index);
+ ide_init_port_data(hwif, index);
init_hwif_default(hwif, index);
#if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)
hwif->irq =
ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
#endif
}
-#ifdef CONFIG_IDE_ARM
- ide_arm_init();
-#endif
}
/**
@@ -246,22 +240,12 @@ static int ide_system_bus_speed(void)
#define pci_default 0
#endif /* CONFIG_PCI */
- if (!system_bus_speed) {
- if (idebus_parameter) {
- /* user supplied value */
- system_bus_speed = idebus_parameter;
- } else if (pci_dev_present(pci_default)) {
- /* safe default value for PCI */
- system_bus_speed = 33;
- } else {
- /* safe default value for VESA and PCI */
- system_bus_speed = 50;
- }
- printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
- "for PIO modes%s\n", system_bus_speed,
- idebus_parameter ? "" : "; override with idebus=xx");
- }
- return system_bus_speed;
+ /* user supplied value */
+ if (idebus_parameter)
+ return idebus_parameter;
+
+ /* safe default value for PCI or VESA and PCI*/
+ return pci_dev_present(pci_default) ? 33 : 50;
}
ide_hwif_t * ide_find_port(unsigned long base)
@@ -409,13 +393,12 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->chipset = tmp_hwif->chipset;
hwif->hold = tmp_hwif->hold;
+ hwif->dev = tmp_hwif->dev;
+
#ifdef CONFIG_BLK_DEV_IDEPCI
- hwif->pci_dev = tmp_hwif->pci_dev;
hwif->cds = tmp_hwif->cds;
#endif
- hwif->fixup = tmp_hwif->fixup;
-
hwif->set_pio_mode = tmp_hwif->set_pio_mode;
hwif->set_dma_mode = tmp_hwif->set_dma_mode;
hwif->mdma_filter = tmp_hwif->mdma_filter;
@@ -424,7 +407,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->reset_poll = tmp_hwif->reset_poll;
hwif->pre_reset = tmp_hwif->pre_reset;
hwif->resetproc = tmp_hwif->resetproc;
- hwif->intrproc = tmp_hwif->intrproc;
hwif->maskproc = tmp_hwif->maskproc;
hwif->quirkproc = tmp_hwif->quirkproc;
hwif->busproc = tmp_hwif->busproc;
@@ -434,16 +416,13 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->atapi_input_bytes = tmp_hwif->atapi_input_bytes;
hwif->atapi_output_bytes = tmp_hwif->atapi_output_bytes;
+ hwif->dma_host_set = tmp_hwif->dma_host_set;
hwif->dma_setup = tmp_hwif->dma_setup;
hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd;
hwif->dma_start = tmp_hwif->dma_start;
hwif->ide_dma_end = tmp_hwif->ide_dma_end;
- hwif->ide_dma_on = tmp_hwif->ide_dma_on;
- hwif->dma_off_quietly = tmp_hwif->dma_off_quietly;
hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq;
hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq;
- hwif->dma_host_on = tmp_hwif->dma_host_on;
- hwif->dma_host_off = tmp_hwif->dma_host_off;
hwif->dma_lost_irq = tmp_hwif->dma_lost_irq;
hwif->dma_timeout = tmp_hwif->dma_timeout;
@@ -468,7 +447,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
#endif
hwif->dma_base = tmp_hwif->dma_base;
- hwif->dma_master = tmp_hwif->dma_master;
hwif->dma_command = tmp_hwif->dma_command;
hwif->dma_vendor1 = tmp_hwif->dma_vendor1;
hwif->dma_status = tmp_hwif->dma_status;
@@ -483,9 +461,46 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->hwif_data = tmp_hwif->hwif_data;
}
+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+{
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+
+ spin_lock_irq(&ide_lock);
+ /*
+ * Remove us from the hwgroup, and free
+ * the hwgroup if we were the only member
+ */
+ if (hwif->next == hwif) {
+ BUG_ON(hwgroup->hwif != hwif);
+ kfree(hwgroup);
+ } else {
+ /* There is another interface in hwgroup.
+ * Unlink us, and set hwgroup->drive and ->hwif to
+ * something sane.
+ */
+ ide_hwif_t *g = hwgroup->hwif;
+
+ while (g->next != hwif)
+ g = g->next;
+ g->next = hwif->next;
+ if (hwgroup->hwif == hwif) {
+ /* Chose a random hwif for hwgroup->hwif.
+ * It's guaranteed that there are no drives
+ * left in the hwgroup.
+ */
+ BUG_ON(hwgroup->drive != NULL);
+ hwgroup->hwif = g;
+ }
+ BUG_ON(hwgroup->hwif == hwif);
+ }
+ spin_unlock_irq(&ide_lock);
+}
+
/**
* ide_unregister - free an IDE interface
* @index: index of interface (will change soon to a pointer)
+ * @init_default: init default hwif flag
+ * @restore: restore hwif flag
*
* Perform the final unregister of an IDE interface. At the moment
* we don't refcount interfaces so this will also get split up.
@@ -505,7 +520,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
* This is raving bonkers.
*/
-void ide_unregister(unsigned int index)
+void ide_unregister(unsigned int index, int init_default, int restore)
{
ide_drive_t *drive;
ide_hwif_t *hwif, *g;
@@ -550,43 +565,8 @@ void ide_unregister(unsigned int index)
if (irq_count == 1)
free_irq(hwif->irq, hwgroup);
- spin_lock_irq(&ide_lock);
- /*
- * Note that we only release the standard ports,
- * and do not even try to handle any extra ports
- * allocated for weird IDE interface chipsets.
- */
- ide_hwif_release_regions(hwif);
+ ide_remove_port_from_hwgroup(hwif);
- /*
- * Remove us from the hwgroup, and free
- * the hwgroup if we were the only member
- */
- if (hwif->next == hwif) {
- BUG_ON(hwgroup->hwif != hwif);
- kfree(hwgroup);
- } else {
- /* There is another interface in hwgroup.
- * Unlink us, and set hwgroup->drive and ->hwif to
- * something sane.
- */
- g = hwgroup->hwif;
- while (g->next != hwif)
- g = g->next;
- g->next = hwif->next;
- if (hwgroup->hwif == hwif) {
- /* Chose a random hwif for hwgroup->hwif.
- * It's guaranteed that there are no drives
- * left in the hwgroup.
- */
- BUG_ON(hwgroup->drive != NULL);
- hwgroup->hwif = g;
- }
- BUG_ON(hwgroup->hwif == hwif);
- }
-
- /* More messed up locking ... */
- spin_unlock_irq(&ide_lock);
device_unregister(&hwif->gendev);
wait_for_completion(&hwif->gendev_rel_comp);
@@ -602,7 +582,6 @@ void ide_unregister(unsigned int index)
(void) ide_release_dma(hwif);
hwif->dma_base = 0;
- hwif->dma_master = 0;
hwif->dma_command = 0;
hwif->dma_vendor1 = 0;
hwif->dma_status = 0;
@@ -613,14 +592,24 @@ void ide_unregister(unsigned int index)
hwif->extra_ports = 0;
}
+ /*
+ * Note that we only release the standard ports,
+ * and do not even try to handle any extra ports
+ * allocated for weird IDE interface chipsets.
+ */
+ ide_hwif_release_regions(hwif);
+
/* copy original settings */
tmp_hwif = *hwif;
/* restore hwif data to pristine status */
- init_hwif_data(hwif, index);
- init_hwif_default(hwif, index);
+ ide_init_port_data(hwif, index);
- ide_hwif_restore(hwif, &tmp_hwif);
+ if (init_default)
+ init_hwif_default(hwif, index);
+
+ if (restore)
+ ide_hwif_restore(hwif, &tmp_hwif);
abort:
spin_unlock_irq(&ide_lock);
@@ -683,70 +672,86 @@ void ide_setup_ports ( hw_regs_t *hw,
*/
}
+void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
+{
+ memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
+ hwif->irq = hw->irq;
+ hwif->noprobe = 0;
+ hwif->chipset = hw->chipset;
+ hwif->gendev.parent = hw->dev;
+ hwif->ack_intr = hw->ack_intr;
+}
+EXPORT_SYMBOL_GPL(ide_init_port_hw);
+
+ide_hwif_t *ide_deprecated_find_port(unsigned long base)
+{
+ ide_hwif_t *hwif;
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ hwif = &ide_hwifs[i];
+ if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+ goto found;
+ }
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ hwif = &ide_hwifs[i];
+ if (hwif->hold)
+ continue;
+ if (!hwif->present && hwif->mate == NULL)
+ goto found;
+ }
+
+ hwif = NULL;
+found:
+ return hwif;
+}
+EXPORT_SYMBOL_GPL(ide_deprecated_find_port);
+
/**
* ide_register_hw - register IDE interface
* @hw: hardware registers
- * @fixup: fixup function
- * @initializing: set while initializing built-in drivers
+ * @quirkproc: quirkproc function
* @hwifp: pointer to returned hwif
*
* Register an IDE interface, specifying exactly the registers etc.
- * Set init=1 iff calling before probes have taken place.
*
* Returns -1 on error.
*/
-int ide_register_hw(hw_regs_t *hw, void (*fixup)(ide_hwif_t *),
- int initializing, ide_hwif_t **hwifp)
+int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *),
+ ide_hwif_t **hwifp)
{
int index, retry = 1;
ide_hwif_t *hwif;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
do {
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = &ide_hwifs[index];
- if (hwif->io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
- goto found;
- }
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = &ide_hwifs[index];
- if (hwif->hold)
- continue;
- if ((!hwif->present && !hwif->mate && !initializing) ||
- (!hwif->io_ports[IDE_DATA_OFFSET] && initializing))
- goto found;
- }
+ hwif = ide_deprecated_find_port(hw->io_ports[IDE_DATA_OFFSET]);
+ index = hwif->index;
+ if (hwif)
+ goto found;
for (index = 0; index < MAX_HWIFS; index++)
- ide_unregister(index);
+ ide_unregister(index, 1, 1);
} while (retry--);
return -1;
found:
if (hwif->present)
- ide_unregister(index);
- else if (!hwif->hold) {
- init_hwif_data(hwif, index);
- init_hwif_default(hwif, index);
- }
- if (hwif->present)
- return -1;
- memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
- hwif->irq = hw->irq;
- hwif->noprobe = 0;
- hwif->fixup = fixup;
- hwif->chipset = hw->chipset;
- hwif->gendev.parent = hw->dev;
- hwif->ack_intr = hw->ack_intr;
+ ide_unregister(index, 0, 1);
+ else if (!hwif->hold)
+ ide_init_port_data(hwif, index);
- if (initializing == 0) {
- u8 idx[4] = { index, 0xff, 0xff, 0xff };
+ ide_init_port_hw(hwif, hw);
+ hwif->quirkproc = quirkproc;
- ide_device_add(idx);
- }
+ idx[0] = index;
+
+ ide_device_add(idx, NULL);
if (hwifp)
*hwifp = hwif;
- return (initializing || hwif->present) ? index : -1;
+ return hwif->present ? index : -1;
}
EXPORT_SYMBOL(ide_register_hw);
@@ -800,11 +805,13 @@ int set_io_32bit(ide_drive_t *drive, int arg)
if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
return -EINVAL;
+ if (ide_spin_wait_hwgroup(drive))
+ return -EBUSY;
+
drive->io_32bit = arg;
-#ifdef CONFIG_BLK_DEV_DTC2278
- if (HWIF(drive)->chipset == ide_dtc2278)
- HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
-#endif /* CONFIG_BLK_DEV_DTC2278 */
+
+ spin_unlock_irq(&ide_lock);
+
return 0;
}
@@ -833,7 +840,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
if (!drive->id || !(drive->id->capability & 1))
goto out;
- if (hwif->ide_dma_on == NULL)
+ if (hwif->dma_host_set == NULL)
goto out;
err = -EBUSY;
@@ -848,8 +855,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
err = 0;
if (arg) {
- hwif->dma_off_quietly(drive);
- if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
+ if (ide_set_dma(drive))
err = -EIO;
} else
ide_dma_off(drive);
@@ -882,7 +888,10 @@ int set_pio_mode(ide_drive_t *drive, int arg)
if (drive->special.b.set_tune)
return -EBUSY;
+
ide_init_drive_cmd(&rq);
+ rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+
drive->tune_req = (u8) arg;
drive->special.b.set_tune = 1;
(void) ide_do_drive_cmd(drive, &rq, ide_wait);
@@ -914,7 +923,7 @@ static int set_unmaskirq(ide_drive_t *drive, int arg)
int system_bus_clock (void)
{
- return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
+ return system_bus_speed;
}
EXPORT_SYMBOL(system_bus_clock);
@@ -1026,11 +1035,8 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
case HDIO_GET_NICE:
return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP |
drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP |
- drive->nice0 << IDE_NICE_0 |
- drive->nice1 << IDE_NICE_1 |
- drive->nice2 << IDE_NICE_2,
+ drive->nice1 << IDE_NICE_1,
(long __user *) arg);
-
#ifdef CONFIG_IDE_TASK_IOCTL
case HDIO_DRIVE_TASKFILE:
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
@@ -1064,14 +1070,14 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
ide_init_hwif_ports(&hw, (unsigned long) args[0],
(unsigned long) args[1], NULL);
hw.irq = args[2];
- if (ide_register_hw(&hw, NULL, 0, NULL) == -1)
+ if (ide_register_hw(&hw, NULL, NULL) == -1)
return -EIO;
return 0;
}
case HDIO_UNREGISTER_HWIF:
if (!capable(CAP_SYS_RAWIO)) return -EACCES;
/* (arg > MAX_HWIFS) checked in function */
- ide_unregister(arg);
+ ide_unregister(arg, 1, 1);
return 0;
case HDIO_SET_NICE:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
@@ -1225,26 +1231,12 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
return 0; /* zero = nothing matched */
}
-#ifdef CONFIG_BLK_DEV_ALI14XX
extern int probe_ali14xx;
-extern int ali14xx_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_UMC8672
extern int probe_umc8672;
-extern int umc8672_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_DTC2278
extern int probe_dtc2278;
-extern int dtc2278_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_HT6560B
extern int probe_ht6560b;
-extern int ht6560b_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_QD65XX
extern int probe_qd65xx;
-extern int qd65xx_init(void);
-#endif
+extern int cmd640_vlb;
static int __initdata is_chipset_set[MAX_HWIFS];
@@ -1321,7 +1313,7 @@ static int __init ide_setup(char *s)
if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
const char *hd_words[] = {
"none", "noprobe", "nowerr", "cdrom", "nodma",
- "autotune", "noautotune", "minus8", "swapdata", "bswap",
+ "autotune", "noautotune", "-8", "-9", "-10",
"noflush", "remap", "remap63", "scsi", NULL };
unit = s[2] - 'a';
hw = unit / MAX_DRIVES;
@@ -1357,10 +1349,6 @@ static int __init ide_setup(char *s)
case -7: /* "noautotune" */
drive->autotune = IDE_TUNE_NOAUTO;
goto obsolete_option;
- case -9: /* "swapdata" */
- case -10: /* "bswap" */
- drive->bswap = 1;
- goto done;
case -11: /* noflush */
drive->noflush = 1;
goto done;
@@ -1460,11 +1448,8 @@ static int __init ide_setup(char *s)
#endif
#ifdef CONFIG_BLK_DEV_CMD640
case -14: /* "cmd640_vlb" */
- {
- extern int cmd640_vlb; /* flag for cmd640.c */
cmd640_vlb = 1;
goto done;
- }
#endif
#ifdef CONFIG_BLK_DEV_HT6560B
case -13: /* "ht6560b" */
@@ -1554,79 +1539,6 @@ done:
return 1;
}
-extern void __init pnpide_init(void);
-extern void __exit pnpide_exit(void);
-extern void __init h8300_ide_init(void);
-
-/*
- * probe_for_hwifs() finds/initializes "known" IDE interfaces
- */
-static void __init probe_for_hwifs (void)
-{
-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
- ide_scan_pcibus(ide_scan_direction);
-#endif
-
-#ifdef CONFIG_ETRAX_IDE
- {
- extern void init_e100_ide(void);
- init_e100_ide();
- }
-#endif /* CONFIG_ETRAX_IDE */
-#ifdef CONFIG_BLK_DEV_CMD640
- {
- extern void ide_probe_for_cmd640x(void);
- ide_probe_for_cmd640x();
- }
-#endif /* CONFIG_BLK_DEV_CMD640 */
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
- {
- extern int pmac_ide_probe(void);
- (void)pmac_ide_probe();
- }
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#ifdef CONFIG_BLK_DEV_GAYLE
- {
- extern void gayle_init(void);
- gayle_init();
- }
-#endif /* CONFIG_BLK_DEV_GAYLE */
-#ifdef CONFIG_BLK_DEV_FALCON_IDE
- {
- extern void falconide_init(void);
- falconide_init();
- }
-#endif /* CONFIG_BLK_DEV_FALCON_IDE */
-#ifdef CONFIG_BLK_DEV_MAC_IDE
- {
- extern void macide_init(void);
- macide_init();
- }
-#endif /* CONFIG_BLK_DEV_MAC_IDE */
-#ifdef CONFIG_BLK_DEV_Q40IDE
- {
- extern void q40ide_init(void);
- q40ide_init();
- }
-#endif /* CONFIG_BLK_DEV_Q40IDE */
-#ifdef CONFIG_BLK_DEV_BUDDHA
- {
- extern void buddha_init(void);
- buddha_init();
- }
-#endif /* CONFIG_BLK_DEV_BUDDHA */
-#ifdef CONFIG_BLK_DEV_IDEPNP
- pnpide_init();
-#endif
-#ifdef CONFIG_H8300
- h8300_ide_init();
-#endif
-}
-
-/*
- * Probe module
- */
-
EXPORT_SYMBOL(ide_lock);
static int ide_bus_match(struct device *dev, struct device_driver *drv)
@@ -1670,10 +1582,34 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "ide:m-%s\n", media_string(drive));
}
+static ssize_t model_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->model);
+}
+
+static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->fw_rev);
+}
+
+static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->id->serial_no);
+}
+
static struct device_attribute ide_dev_attrs[] = {
__ATTR_RO(media),
__ATTR_RO(drivename),
__ATTR_RO(modalias),
+ __ATTR_RO(model),
+ __ATTR_RO(firmware),
+ __ATTR(serial, 0400, serial_show, NULL),
__ATTR_NULL
};
@@ -1739,6 +1675,10 @@ static int __init ide_init(void)
printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
system_bus_speed = ide_system_bus_speed();
+ printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
+ "for PIO modes%s\n", system_bus_speed,
+ idebus_parameter ? "" : "; override with idebus=xx");
+
ret = bus_register(&ide_bus_type);
if (ret < 0) {
printk(KERN_WARNING "IDE: bus_register error: %d\n", ret);
@@ -1749,30 +1689,6 @@ static int __init ide_init(void)
proc_ide_create();
-#ifdef CONFIG_BLK_DEV_ALI14XX
- if (probe_ali14xx)
- (void)ali14xx_init();
-#endif
-#ifdef CONFIG_BLK_DEV_UMC8672
- if (probe_umc8672)
- (void)umc8672_init();
-#endif
-#ifdef CONFIG_BLK_DEV_DTC2278
- if (probe_dtc2278)
- (void)dtc2278_init();
-#endif
-#ifdef CONFIG_BLK_DEV_HT6560B
- if (probe_ht6560b)
- (void)ht6560b_init();
-#endif
-#ifdef CONFIG_BLK_DEV_QD65XX
- if (probe_qd65xx)
- (void)qd65xx_init();
-#endif
-
- /* Probe for special PCI and other "known" interface chipsets. */
- probe_for_hwifs();
-
return 0;
}
@@ -1806,11 +1722,7 @@ void __exit cleanup_module (void)
int index;
for (index = 0; index < MAX_HWIFS; ++index)
- ide_unregister(index);
-
-#ifdef CONFIG_BLK_DEV_IDEPNP
- pnpide_exit();
-#endif
+ ide_unregister(index, 0, 0);
proc_ide_destroy();
diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
index 409822349f1..7043ec7d1e0 100644
--- a/drivers/ide/legacy/Makefile
+++ b/drivers/ide/legacy/Makefile
@@ -1,15 +1,24 @@
+# link order is important here
+
obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o
+obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o
obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o
obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
-obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
-obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o
+obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o
+obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o
+obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o
+obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o
+obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o
-obj-$(CONFIG_BLK_DEV_PLATFORM) += ide_platform.o
+ifeq ($(CONFIG_BLK_DEV_IDECS), m)
+ obj-m += ide-cs.o
+endif
-# Last of all
-obj-$(CONFIG_BLK_DEV_HD) += hd.o
+ifeq ($(CONFIG_BLK_DEV_PLATFORM), m)
+ obj-m += ide_platform.o
+endif
EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
index 10311ecc674..d4d1a6bea59 100644
--- a/drivers/ide/legacy/ali14xx.c
+++ b/drivers/ide/legacy/ali14xx.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/legacy/ali14xx.c Version 0.03 Feb 09, 1996
- *
* Copyright (C) 1996 Linus Torvalds & author (see below)
*/
@@ -53,12 +51,13 @@
/* port addresses for auto-detection */
#define ALI_NUM_PORTS 4
-static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4};
+static const int ports[ALI_NUM_PORTS] __initdata =
+ { 0x074, 0x0f4, 0x034, 0x0e4 };
/* register initialization data */
typedef struct { u8 reg, data; } RegInitializer;
-static RegInitializer initData[] __initdata = {
+static const RegInitializer initData[] __initdata = {
{0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
{0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
{0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
@@ -177,7 +176,7 @@ static int __init findPort (void)
* Initialize controller registers with default values.
*/
static int __init initRegisters (void) {
- RegInitializer *p;
+ const RegInitializer *p;
u8 t;
unsigned long flags;
@@ -192,9 +191,14 @@ static int __init initRegisters (void) {
return t;
}
+static const struct ide_port_info ali14xx_port_info = {
+ .chipset = ide_ali14xx,
+ .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
+ .pio_mask = ATA_PIO4,
+};
+
static int __init ali14xx_probe(void)
{
- ide_hwif_t *hwif, *mate;
static u8 idx[4] = { 0, 1, 0xff, 0xff };
printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
@@ -206,21 +210,10 @@ static int __init ali14xx_probe(void)
return 1;
}
- hwif = &ide_hwifs[0];
- mate = &ide_hwifs[1];
-
- hwif->chipset = ide_ali14xx;
- hwif->pio_mask = ATA_PIO4;
- hwif->set_pio_mode = &ali14xx_set_pio_mode;
- hwif->mate = mate;
-
- mate->chipset = ide_ali14xx;
- mate->pio_mask = ATA_PIO4;
- mate->set_pio_mode = &ali14xx_set_pio_mode;
- mate->mate = hwif;
- mate->channel = 1;
+ ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode;
+ ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode;
- ide_device_add(idx);
+ ide_device_add(idx, &ali14xx_port_info);
return 0;
}
@@ -230,8 +223,7 @@ int probe_ali14xx = 0;
module_param_named(probe, probe_ali14xx, bool, 0);
MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
-/* Can be called directly from ide.c. */
-int __init ali14xx_init(void)
+static int __init ali14xx_init(void)
{
if (probe_ali14xx == 0)
goto out;
@@ -247,9 +239,7 @@ out:
return -ENODEV;
}
-#ifdef MODULE
module_init(ali14xx_init);
-#endif
MODULE_AUTHOR("see local file");
MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 4a0be251a05..8bdb79da17e 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver
+ * Amiga Buddha, Catweasel and X-Surf IDE Driver
*
* Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
*
@@ -112,6 +112,7 @@ typedef enum BuddhaType_Enum {
BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF
} BuddhaType;
+static const char *buddha_board_name[] = { "Buddha", "Catweasel", "X-Surf" };
/*
* Check and acknowledge the interrupt status
@@ -143,11 +144,11 @@ static int xsurf_ack_intr(ide_hwif_t *hwif)
* Probe for a Buddha or Catweasel IDE interface
*/
-void __init buddha_init(void)
+static int __init buddha_init(void)
{
hw_regs_t hw;
ide_hwif_t *hwif;
- int i, index;
+ int i;
struct zorro_dev *z = NULL;
u_long buddha_board = 0;
@@ -156,6 +157,8 @@ void __init buddha_init(void)
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
unsigned long board;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+
if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
buddha_num_hwifs = BUDDHA_NUM_HWIFS;
type=BOARD_BUDDHA;
@@ -195,7 +198,10 @@ fail_base2:
/* X-Surf doesn't have this. IRQs are always on */
if (type != BOARD_XSURF)
z_writeb(0, buddha_board+BUDDHA_IRQ_MR);
-
+
+ printk(KERN_INFO "ide: %s IDE controller\n",
+ buddha_board_name[type]);
+
for(i=0;i<buddha_num_hwifs;i++) {
if(type != BOARD_XSURF) {
ide_setup_ports(&hw, (buddha_board+buddha_bases[i]),
@@ -213,23 +219,23 @@ fail_base2:
IRQ_AMIGA_PORTS);
}
- index = ide_register_hw(&hw, NULL, 1, &hwif);
- if (index != -1) {
+ hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif) {
+ u8 index = hwif->index;
+
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
+
hwif->mmio = 1;
- printk("ide%d: ", index);
- switch(type) {
- case BOARD_BUDDHA:
- printk("Buddha");
- break;
- case BOARD_CATWEASEL:
- printk("Catweasel");
- break;
- case BOARD_XSURF:
- printk("X-Surf");
- break;
- }
- printk(" IDE interface\n");
- }
+
+ idx[i] = index;
+ }
}
+
+ ide_device_add(idx, NULL);
}
+
+ return 0;
}
+
+module_init(buddha_init);
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
index 24a845d45bd..73396f70f2b 100644
--- a/drivers/ide/legacy/dtc2278.c
+++ b/drivers/ide/legacy/dtc2278.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/legacy/dtc2278.c Version 0.02 Feb 10, 1996
- *
* Copyright (C) 1996 Linus Torvalds & author (see below)
*/
@@ -86,14 +84,20 @@ static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
/* Actually we do - there is a data sheet available for the
Winbond but does anyone actually care */
}
-
- /*
- * 32bit I/O has to be enabled for *both* drives at the same time.
- */
- drive->io_32bit = 1;
- HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
}
+static const struct ide_port_info dtc2278_port_info __initdata = {
+ .chipset = ide_dtc2278,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_NO_UNMASK_IRQS |
+ IDE_HFLAG_IO_32BIT |
+ /* disallow ->io_32bit changes */
+ IDE_HFLAG_NO_IO_32BIT |
+ IDE_HFLAG_NO_DMA |
+ IDE_HFLAG_NO_AUTOTUNE,
+ .pio_mask = ATA_PIO4,
+};
+
static int __init dtc2278_probe(void)
{
unsigned long flags;
@@ -124,23 +128,9 @@ static int __init dtc2278_probe(void)
#endif
local_irq_restore(flags);
- hwif->serialized = 1;
- hwif->chipset = ide_dtc2278;
- hwif->pio_mask = ATA_PIO4;
hwif->set_pio_mode = &dtc2278_set_pio_mode;
- hwif->drives[0].no_unmask = 1;
- hwif->drives[1].no_unmask = 1;
- hwif->mate = mate;
-
- mate->serialized = 1;
- mate->chipset = ide_dtc2278;
- mate->pio_mask = ATA_PIO4;
- mate->drives[0].no_unmask = 1;
- mate->drives[1].no_unmask = 1;
- mate->mate = hwif;
- mate->channel = 1;
- ide_device_add(idx);
+ ide_device_add(idx, &dtc2278_port_info);
return 0;
}
@@ -150,8 +140,7 @@ int probe_dtc2278 = 0;
module_param_named(probe, probe_dtc2278, bool, 0);
MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
-/* Can be called directly from ide.c. */
-int __init dtc2278_init(void)
+static int __init dtc2278_init(void)
{
if (probe_dtc2278 == 0)
return -ENODEV;
@@ -163,9 +152,7 @@ int __init dtc2278_init(void)
return 0;
}
-#ifdef MODULE
module_init(dtc2278_init);
-#endif
MODULE_AUTHOR("See Local File");
MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index 7d7936f1b90..85b69a82825 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/legacy/falconide.c -- Atari Falcon IDE Driver
+ * Atari Falcon IDE Driver
*
* Created 12 Jul 1997 by Geert Uytterhoeven
*
@@ -62,19 +62,32 @@ EXPORT_SYMBOL(falconide_intr_lock);
* Probe for a Falcon IDE interface
*/
-void __init falconide_init(void)
+static int __init falconide_init(void)
{
if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
hw_regs_t hw;
- int index;
+ ide_hwif_t *hwif;
+
+ printk(KERN_INFO "ide: Falcon IDE controller\n");
ide_setup_ports(&hw, ATA_HD_BASE, falconide_offsets,
0, 0, NULL,
// falconide_iops,
IRQ_MFP_IDE);
- index = ide_register_hw(&hw, NULL, 1, NULL);
- if (index != -1)
- printk("ide%d: Falcon IDE interface\n", index);
+ hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif) {
+ u8 index = hwif->index;
+ u8 idx[4] = { index, 0xff, 0xff, 0xff };
+
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
+
+ ide_device_add(idx, NULL);
+ }
}
+
+ return 0;
}
+
+module_init(falconide_init);
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 53331ee1e95..fc29ce75aff 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver
+ * Amiga Gayle IDE Driver
*
* Created 9 Jul 1997 by Geert Uytterhoeven
*
@@ -110,12 +110,13 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
* Probe for a Gayle IDE interface (and optionally for an IDE doubler)
*/
-void __init gayle_init(void)
+static int __init gayle_init(void)
{
int a4000, i;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (!MACH_IS_AMIGA)
- return;
+ return -ENODEV;
if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
goto found;
@@ -125,15 +126,21 @@ void __init gayle_init(void)
NULL))
goto found;
#endif
- return;
+ return -ENODEV;
found:
+ printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n",
+ a4000 ? 4000 : 1200,
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+ ide_doubler ? ", IDE doubler" :
+#endif
+ "");
+
for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
unsigned long base, ctrlport, irqport;
ide_ack_intr_t *ack_intr;
hw_regs_t hw;
ide_hwif_t *hwif;
- int index;
unsigned long phys_base, res_start, res_n;
if (a4000) {
@@ -165,21 +172,23 @@ found:
// &gayle_iops,
IRQ_AMIGA_PORTS);
- index = ide_register_hw(&hw, NULL, 1, &hwif);
- if (index != -1) {
+ hwif = ide_find_port(base);
+ if (hwif) {
+ u8 index = hwif->index;
+
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
+
hwif->mmio = 1;
- switch (i) {
- case 0:
- printk("ide%d: Gayle IDE interface (A%d style)\n", index,
- a4000 ? 4000 : 1200);
- break;
-#ifdef CONFIG_BLK_DEV_IDEDOUBLER
- case 1:
- printk("ide%d: IDE doubler\n", index);
- break;
-#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
- }
+
+ idx[i] = index;
} else
release_mem_region(res_start, res_n);
}
+
+ ide_device_add(idx, NULL);
+
+ return 0;
}
+
+module_init(gayle_init);
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index a4245d13f11..02d12c74764 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/legacy/ht6560b.c Version 0.07 Feb 1, 2000
- *
* Copyright (C) 1995-2000 Linus Torvalds & author (see below)
*/
@@ -302,17 +300,36 @@ static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
#endif
}
+static void __init ht6560b_port_init_devs(ide_hwif_t *hwif)
+{
+ /* Setting default configurations for drives. */
+ int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
+
+ if (hwif->channel)
+ t |= (HT_SECONDARY_IF << 8);
+
+ hwif->drives[0].drive_data = t;
+ hwif->drives[1].drive_data = t;
+}
+
int probe_ht6560b = 0;
module_param_named(probe, probe_ht6560b, bool, 0);
MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
-/* Can be called directly from ide.c. */
-int __init ht6560b_init(void)
+static const struct ide_port_info ht6560b_port_info __initdata = {
+ .chipset = ide_ht6560b,
+ .host_flags = IDE_HFLAG_SERIALIZE | /* is this needed? */
+ IDE_HFLAG_NO_DMA |
+ IDE_HFLAG_NO_AUTOTUNE |
+ IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO5,
+};
+
+static int __init ht6560b_init(void)
{
ide_hwif_t *hwif, *mate;
static u8 idx[4] = { 0, 1, 0xff, 0xff };
- int t;
if (probe_ht6560b == 0)
return -ENODEV;
@@ -331,36 +348,16 @@ int __init ht6560b_init(void)
goto release_region;
}
- hwif->chipset = ide_ht6560b;
hwif->selectproc = &ht6560b_selectproc;
- hwif->host_flags = IDE_HFLAG_ABUSE_PREFETCH;
- hwif->pio_mask = ATA_PIO5;
hwif->set_pio_mode = &ht6560b_set_pio_mode;
- hwif->serialized = 1; /* is this needed? */
- hwif->mate = mate;
- mate->chipset = ide_ht6560b;
mate->selectproc = &ht6560b_selectproc;
- mate->host_flags = IDE_HFLAG_ABUSE_PREFETCH;
- mate->pio_mask = ATA_PIO5;
mate->set_pio_mode = &ht6560b_set_pio_mode;
- mate->serialized = 1; /* is this needed? */
- mate->mate = hwif;
- mate->channel = 1;
- /*
- * Setting default configurations for drives
- */
- t = (HT_CONFIG_DEFAULT << 8);
- t |= HT_TIMING_DEFAULT;
- hwif->drives[0].drive_data = t;
- hwif->drives[1].drive_data = t;
-
- t |= (HT_SECONDARY_IF << 8);
- mate->drives[0].drive_data = t;
- mate->drives[1].drive_data = t;
+ hwif->port_init_devs = ht6560b_port_init_devs;
+ mate->port_init_devs = ht6560b_port_init_devs;
- ide_device_add(idx);
+ ide_device_add(idx, &ht6560b_port_info);
return 0;
@@ -369,9 +366,7 @@ release_region:
return -ENODEV;
}
-#ifdef MODULE
module_init(ht6560b_init);
-#endif
MODULE_AUTHOR("See Local File");
MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 03715c05866..15ccf6944ae 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -2,8 +2,6 @@
A driver for PCMCIA IDE/ATA disk cards
- ide-cs.c 1.3 2002/10/26 05:45:31
-
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
@@ -147,13 +145,36 @@ static void ide_detach(struct pcmcia_device *link)
static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
{
+ ide_hwif_t *hwif;
hw_regs_t hw;
+ int i;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+
memset(&hw, 0, sizeof(hw));
- ide_init_hwif_ports(&hw, io, ctl, NULL);
+ ide_std_init_ports(&hw, io, ctl);
hw.irq = irq;
hw.chipset = ide_pci;
hw.dev = &handle->dev;
- return ide_register_hw(&hw, &ide_undecoded_slave, 0, NULL);
+
+ hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif == NULL)
+ return -1;
+
+ i = hwif->index;
+
+ if (hwif->present)
+ ide_unregister(i, 0, 0);
+ else if (!hwif->hold)
+ ide_init_port_data(hwif, i);
+
+ ide_init_port_hw(hwif, &hw);
+ hwif->quirkproc = &ide_undecoded_slave;
+
+ idx[0] = i;
+
+ ide_device_add(idx, NULL);
+
+ return hwif->present ? i : -1;
}
/*======================================================================
@@ -339,7 +360,7 @@ void ide_release(struct pcmcia_device *link)
if (info->ndev) {
/* FIXME: if this fails we need to queue the cleanup somehow
-- need to investigate the required PCMCIA magic */
- ide_unregister(info->hd);
+ ide_unregister(info->hd, 0, 0);
}
info->ndev = 0;
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index 7bb79f53dac..26c82ce602d 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -21,56 +21,39 @@
#include <linux/platform_device.h>
#include <linux/io.h>
-static struct {
- void __iomem *plat_ide_mapbase;
- void __iomem *plat_ide_alt_mapbase;
- ide_hwif_t *hwif;
- int index;
-} hwif_prop;
-
-static ide_hwif_t *__devinit plat_ide_locate_hwif(void __iomem *base,
- void __iomem *ctrl, struct pata_platform_info *pdata, int irq,
- int mmio)
+static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
+ void __iomem *base,
+ void __iomem *ctrl,
+ struct pata_platform_info *pdata,
+ int irq)
{
unsigned long port = (unsigned long)base;
- ide_hwif_t *hwif = ide_find_port(port);
int i;
- if (hwif == NULL)
- goto out;
-
- hwif->io_ports[IDE_DATA_OFFSET] = port;
+ hw->io_ports[IDE_DATA_OFFSET] = port;
port += (1 << pdata->ioport_shift);
for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET;
i++, port += (1 << pdata->ioport_shift))
- hwif->io_ports[i] = port;
-
- hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
+ hw->io_ports[i] = port;
- hwif->irq = irq;
+ hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
- hwif->chipset = ide_generic;
+ hw->irq = irq;
- if (mmio) {
- hwif->mmio = 1;
- default_hwif_mmiops(hwif);
- }
-
- hwif_prop.hwif = hwif;
- hwif_prop.index = hwif->index;
-out:
- return hwif;
+ hw->chipset = ide_generic;
}
static int __devinit plat_ide_probe(struct platform_device *pdev)
{
struct resource *res_base, *res_alt, *res_irq;
+ void __iomem *base, *alt_base;
ide_hwif_t *hwif;
struct pata_platform_info *pdata;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
int ret = 0;
int mmio = 0;
+ hw_regs_t hw;
pdata = pdev->dev.platform_data;
@@ -95,30 +78,37 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
}
if (mmio) {
- hwif_prop.plat_ide_mapbase = devm_ioremap(&pdev->dev,
+ base = devm_ioremap(&pdev->dev,
res_base->start, res_base->end - res_base->start + 1);
- hwif_prop.plat_ide_alt_mapbase = devm_ioremap(&pdev->dev,
+ alt_base = devm_ioremap(&pdev->dev,
res_alt->start, res_alt->end - res_alt->start + 1);
} else {
- hwif_prop.plat_ide_mapbase = devm_ioport_map(&pdev->dev,
+ base = devm_ioport_map(&pdev->dev,
res_base->start, res_base->end - res_base->start + 1);
- hwif_prop.plat_ide_alt_mapbase = devm_ioport_map(&pdev->dev,
+ alt_base = devm_ioport_map(&pdev->dev,
res_alt->start, res_alt->end - res_alt->start + 1);
}
- hwif = plat_ide_locate_hwif(hwif_prop.plat_ide_mapbase,
- hwif_prop.plat_ide_alt_mapbase, pdata, res_irq->start, mmio);
-
+ hwif = ide_find_port((unsigned long)base);
if (!hwif) {
ret = -ENODEV;
goto out;
}
- hwif->gendev.parent = &pdev->dev;
- hwif->noprobe = 0;
+
+ memset(&hw, 0, sizeof(hw));
+ plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
+ hw.dev = &pdev->dev;
+
+ ide_init_port_hw(hwif, &hw);
+
+ if (mmio) {
+ hwif->mmio = 1;
+ default_hwif_mmiops(hwif);
+ }
idx[0] = hwif->index;
- ide_device_add(idx);
+ ide_device_add(idx, NULL);
platform_set_drvdata(pdev, hwif);
@@ -132,14 +122,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
{
ide_hwif_t *hwif = pdev->dev.driver_data;
- if (hwif != hwif_prop.hwif) {
- dev_printk(KERN_DEBUG, &pdev->dev, "%s: hwif value error",
- pdev->name);
- } else {
- ide_unregister(hwif_prop.index);
- hwif_prop.index = 0;
- hwif_prop.hwif = NULL;
- }
+ ide_unregister(hwif->index, 0, 0);
return 0;
}
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index e87cd2f1643..06df8df857a 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/legacy/macide.c -- Macintosh IDE Driver
+ * Macintosh IDE Driver
*
* Copyright (C) 1998 by Michael Schmitz
*
@@ -77,15 +77,17 @@ int macide_ack_intr(ide_hwif_t* hwif)
return 0;
}
+static const char *mac_ide_name[] =
+ { "Quadra", "Powerbook", "Powerbook Baboon" };
+
/*
* Probe for a Macintosh IDE interface
*/
-void macide_init(void)
+static int __init macide_init(void)
{
hw_regs_t hw;
ide_hwif_t *hwif;
- int index = -1;
switch (macintosh_config->ide_type) {
case MAC_IDE_QUADRA:
@@ -93,48 +95,40 @@ void macide_init(void)
0, 0, macide_ack_intr,
// quadra_ide_iops,
IRQ_NUBUS_F);
- index = ide_register_hw(&hw, NULL, 1, &hwif);
break;
case MAC_IDE_PB:
ide_setup_ports(&hw, IDE_BASE, macide_offsets,
0, 0, macide_ack_intr,
// macide_pb_iops,
IRQ_NUBUS_C);
- index = ide_register_hw(&hw, NULL, 1, &hwif);
break;
case MAC_IDE_BABOON:
ide_setup_ports(&hw, BABOON_BASE, macide_offsets,
0, 0, NULL,
// macide_baboon_iops,
IRQ_BABOON_1);
- index = ide_register_hw(&hw, NULL, 1, &hwif);
- if (index == -1) break;
- if (macintosh_config->ident == MAC_MODEL_PB190) {
-
- /* Fix breakage in ide-disk.c: drive capacity */
- /* is not initialized for drives without a */
- /* hardware ID, and we can't get that without */
- /* probing the drive which freezes a 190. */
-
- ide_drive_t *drive = &ide_hwifs[index].drives[0];
- drive->capacity64 = drive->cyl*drive->head*drive->sect;
-
- }
break;
-
default:
- return;
+ return -ENODEV;
}
- if (index != -1) {
+ printk(KERN_INFO "ide: Macintosh %s IDE controller\n",
+ mac_ide_name[macintosh_config->ide_type - 1]);
+
+ hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif) {
+ u8 index = hwif->index;
+ u8 idx[4] = { index, 0xff, 0xff, 0xff };
+
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
+
hwif->mmio = 1;
- if (macintosh_config->ide_type == MAC_IDE_QUADRA)
- printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index);
- else if (macintosh_config->ide_type == MAC_IDE_PB)
- printk(KERN_INFO "ide%d: Macintosh Powerbook IDE interface\n", index);
- else if (macintosh_config->ide_type == MAC_IDE_BABOON)
- printk(KERN_INFO "ide%d: Macintosh Powerbook Baboon IDE interface\n", index);
- else
- printk(KERN_INFO "ide%d: Unknown Macintosh IDE interface\n", index);
+
+ ide_device_add(idx, NULL);
}
+
+ return 0;
}
+
+module_init(macide_init);
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index a73db1bd482..2f0b34d892a 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/legacy/q40ide.c -- Q40 I/O port IDE Driver
+ * Q40 I/O port IDE Driver
*
* (c) Richard Zidlicky
*
@@ -111,15 +111,17 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
* Probe for Q40 IDE interfaces
*/
-void q40ide_init(void)
+static int __init q40ide_init(void)
{
int i;
ide_hwif_t *hwif;
- int index;
const char *name;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (!MACH_IS_Q40)
- return ;
+ return -ENODEV;
+
+ printk(KERN_INFO "ide: Q40 IDE controller\n");
for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
hw_regs_t hw;
@@ -141,10 +143,20 @@ void q40ide_init(void)
0, NULL,
// m68kide_iops,
q40ide_default_irq(pcide_bases[i]));
- index = ide_register_hw(&hw, NULL, 1, &hwif);
- // **FIXME**
- if (index != -1)
+
+ hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif) {
+ ide_init_port_data(hwif, hwif->index);
+ ide_init_port_hw(hwif, &hw);
hwif->mmio = 1;
+
+ idx[i] = hwif->index;
+ }
}
+
+ ide_device_add(idx, NULL);
+
+ return 0;
}
+module_init(q40ide_init);
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
index 912e73853fa..bba29df5f21 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/legacy/qd65xx.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/legacy/qd65xx.c Version 0.07 Sep 30, 2001
- *
* Copyright (C) 1996-2001 Linus Torvalds & author (see below)
*/
@@ -307,18 +305,33 @@ static int __init qd_testreg(int port)
* called to setup an ata channel : adjusts attributes & links for tuning
*/
-static void __init qd_setup(ide_hwif_t *hwif, int base, int config,
- unsigned int data0, unsigned int data1)
+static void __init qd_setup(ide_hwif_t *hwif, int base, int config)
{
- hwif->chipset = ide_qd65xx;
- hwif->channel = hwif->index;
hwif->select_data = base;
hwif->config_data = config;
- hwif->drives[0].drive_data = data0;
- hwif->drives[1].drive_data = data1;
- hwif->drives[0].io_32bit =
- hwif->drives[1].io_32bit = 1;
- hwif->pio_mask = ATA_PIO4;
+}
+
+static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
+{
+ u8 base = hwif->select_data, config = QD_CONFIG(hwif);
+
+ hwif->drives[0].drive_data = QD6500_DEF_DATA;
+ hwif->drives[1].drive_data = QD6500_DEF_DATA;
+}
+
+static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
+{
+ u16 t1, t2;
+ u8 base = hwif->select_data, config = QD_CONFIG(hwif);
+
+ if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
+ t1 = QD6580_DEF_DATA;
+ t2 = QD6580_DEF_DATA2;
+ } else
+ t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
+
+ hwif->drives[0].drive_data = t1;
+ hwif->drives[1].drive_data = t2;
}
/*
@@ -358,6 +371,14 @@ static void __exit qd_unsetup(ide_hwif_t *hwif)
}
*/
+static const struct ide_port_info qd65xx_port_info __initdata = {
+ .chipset = ide_qd65xx,
+ .host_flags = IDE_HFLAG_IO_32BIT |
+ IDE_HFLAG_NO_DMA |
+ IDE_HFLAG_NO_AUTOTUNE,
+ .pio_mask = ATA_PIO4,
+};
+
/*
* qd_probe:
*
@@ -395,13 +416,14 @@ static int __init qd_probe(int base)
return 1;
}
- qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA);
+ qd_setup(hwif, base, config);
+ hwif->port_init_devs = qd6500_port_init_devs;
hwif->set_pio_mode = &qd6500_set_pio_mode;
- idx[0] = unit;
+ idx[unit] = unit;
- ide_device_add(idx);
+ ide_device_add(idx, &qd65xx_port_info);
return 1;
}
@@ -428,14 +450,15 @@ static int __init qd_probe(int base)
hwif = &ide_hwifs[unit];
printk(KERN_INFO "%s: qd6580: single IDE board\n",
hwif->name);
- qd_setup(hwif, base, config | (control << 8),
- QD6580_DEF_DATA, QD6580_DEF_DATA2);
+ qd_setup(hwif, base, config | (control << 8));
+
+ hwif->port_init_devs = qd6580_port_init_devs;
hwif->set_pio_mode = &qd6580_set_pio_mode;
- idx[0] = unit;
+ idx[unit] = unit;
- ide_device_add(idx);
+ ide_device_add(idx, &qd65xx_port_info);
outb(QD_DEF_CONTR, QD_CONTROL_PORT);
@@ -449,20 +472,20 @@ static int __init qd_probe(int base)
printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
hwif->name, mate->name);
- qd_setup(hwif, base, config | (control << 8),
- QD6580_DEF_DATA, QD6580_DEF_DATA);
+ qd_setup(hwif, base, config | (control << 8));
+ hwif->port_init_devs = qd6580_port_init_devs;
hwif->set_pio_mode = &qd6580_set_pio_mode;
- qd_setup(mate, base, config | (control << 8),
- QD6580_DEF_DATA2, QD6580_DEF_DATA2);
+ qd_setup(mate, base, config | (control << 8));
+ mate->port_init_devs = qd6580_port_init_devs;
mate->set_pio_mode = &qd6580_set_pio_mode;
idx[0] = 0;
idx[1] = 1;
- ide_device_add(idx);
+ ide_device_add(idx, &qd65xx_port_info);
outb(QD_DEF_CONTR, QD_CONTROL_PORT);
@@ -478,8 +501,7 @@ int probe_qd65xx = 0;
module_param_named(probe, probe_qd65xx, bool, 0);
MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
-/* Can be called directly from ide.c. */
-int __init qd65xx_init(void)
+static int __init qd65xx_init(void)
{
if (probe_qd65xx == 0)
return -ENODEV;
@@ -492,9 +514,7 @@ int __init qd65xx_init(void)
return 0;
}
-#ifdef MODULE
module_init(qd65xx_init);
-#endif
MODULE_AUTHOR("Samuel Thibault");
MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
index 633a42456ef..28dd50a15d5 100644
--- a/drivers/ide/legacy/qd65xx.h
+++ b/drivers/ide/legacy/qd65xx.h
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/legacy/qd65xx.h
- *
* Copyright (c) 2000 Linus Torvalds & authors
*/
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
index 79577b91687..5696ba02600 100644
--- a/drivers/ide/legacy/umc8672.c
+++ b/drivers/ide/legacy/umc8672.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/legacy/umc8672.c Version 0.05 Jul 31, 1996
- *
* Copyright (C) 1995-1996 Linus Torvalds & author (see below)
*/
@@ -122,9 +120,14 @@ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
spin_unlock_irqrestore(&ide_lock, flags);
}
+static const struct ide_port_info umc8672_port_info __initdata = {
+ .chipset = ide_umc8672,
+ .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
+ .pio_mask = ATA_PIO4,
+};
+
static int __init umc8672_probe(void)
{
- ide_hwif_t *hwif, *mate;
unsigned long flags;
static u8 idx[4] = { 0, 1, 0xff, 0xff };
@@ -145,21 +148,10 @@ static int __init umc8672_probe(void)
umc_set_speeds (current_speeds);
local_irq_restore(flags);
- hwif = &ide_hwifs[0];
- mate = &ide_hwifs[1];
-
- hwif->chipset = ide_umc8672;
- hwif->pio_mask = ATA_PIO4;
- hwif->set_pio_mode = &umc_set_pio_mode;
- hwif->mate = mate;
-
- mate->chipset = ide_umc8672;
- mate->pio_mask = ATA_PIO4;
- mate->set_pio_mode = &umc_set_pio_mode;
- mate->mate = hwif;
- mate->channel = 1;
+ ide_hwifs[0].set_pio_mode = &umc_set_pio_mode;
+ ide_hwifs[1].set_pio_mode = &umc_set_pio_mode;
- ide_device_add(idx);
+ ide_device_add(idx, &umc8672_port_info);
return 0;
}
@@ -169,8 +161,7 @@ int probe_umc8672 = 0;
module_param_named(probe, probe_umc8672, bool, 0);
MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
-/* Can be called directly from ide.c. */
-int __init umc8672_init(void)
+static int __init umc8672_init(void)
{
if (probe_umc8672 == 0)
goto out;
@@ -181,9 +172,7 @@ out:
return -ENODEV;;
}
-#ifdef MODULE
module_init(umc8672_init);
-#endif
MODULE_AUTHOR("Wolfram Podien");
MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index a4ce3ba15d6..0f4bf5d7283 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/mips/au1xxx-ide.c version 01.30.00 Aug. 02 2005
- *
* BRIEF MODULE DESCRIPTION
* AMD Alchemy Au1xxx IDE interface routines over the Static Bus
*
@@ -50,7 +48,6 @@
#include <asm/mach-au1x00/au1xxx_ide.h>
#define DRV_NAME "au1200-ide"
-#define DRV_VERSION "1.0"
#define DRV_AUTHOR "Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>"
/* enable the burstmode in the dbdma */
@@ -198,8 +195,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
break;
#endif
- default:
- return;
}
au_writel(mem_sttime,MEM_STTIME2);
@@ -211,24 +206,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
*/
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-
-static int auide_build_sglist(ide_drive_t *drive, struct request *rq)
-{
- ide_hwif_t *hwif = drive->hwif;
- _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
- struct scatterlist *sg = hwif->sg_table;
-
- ide_map_sg(drive, rq);
-
- if (rq_data_dir(rq) == READ)
- hwif->sg_dma_direction = DMA_FROM_DEVICE;
- else
- hwif->sg_dma_direction = DMA_TO_DEVICE;
-
- return dma_map_sg(ahwif->dev, sg, hwif->sg_nents,
- hwif->sg_dma_direction);
-}
-
static int auide_build_dmatable(ide_drive_t *drive)
{
int i, iswrite, count = 0;
@@ -243,8 +220,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
/* Save for interrupt context */
ahwif->drive = drive;
- /* Build sglist */
- hwif->sg_nents = i = auide_build_sglist(drive, rq);
+ hwif->sg_nents = i = ide_build_sglist(drive, rq);
if (!i)
return 0;
@@ -302,10 +278,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
return 1;
use_pio_instead:
- dma_unmap_sg(ahwif->dev,
- hwif->sg_table,
- hwif->sg_nents,
- hwif->sg_dma_direction);
+ ide_destroy_dmatable(drive);
return 0; /* revert to PIO for this request */
}
@@ -313,11 +286,9 @@ static int auide_build_dmatable(ide_drive_t *drive)
static int auide_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
if (hwif->sg_nents) {
- dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents,
- hwif->sg_dma_direction);
+ ide_destroy_dmatable(drive);
hwif->sg_nents = 0;
}
@@ -397,26 +368,10 @@ static int auide_dma_test_irq(ide_drive_t *drive)
return 0;
}
-static void auide_dma_host_on(ide_drive_t *drive)
+static void auide_dma_host_set(ide_drive_t *drive, int on)
{
}
-static int auide_dma_on(ide_drive_t *drive)
-{
- drive->using_dma = 1;
-
- return 0;
-}
-
-static void auide_dma_host_off(ide_drive_t *drive)
-{
-}
-
-static void auide_dma_off_quietly(ide_drive_t *drive)
-{
- drive->using_dma = 0;
-}
-
static void auide_dma_lost_irq(ide_drive_t *drive)
{
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
@@ -522,7 +477,7 @@ static int auide_ddma_init(_auide_hwif *auide) {
auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
NUM_DESCRIPTORS);
- hwif->dmatable_cpu = dma_alloc_coherent(auide->dev,
+ hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev,
PRD_ENTRIES * PRD_BYTES, /* 1 Page */
&hwif->dmatable_dma, GFP_KERNEL);
@@ -593,6 +548,17 @@ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
*ata_regs = ahwif->regbase + (14 << AU1XXX_ATA_REG_OFFSET);
}
+static const struct ide_port_info au1xxx_port_info = {
+ .host_flags = IDE_HFLAG_POST_SET_MODE |
+ IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+ IDE_HFLAG_NO_IO_32BIT |
+ IDE_HFLAG_UNMASK_IRQS,
+ .pio_mask = ATA_PIO4,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ .mwdma_mask = ATA_MWDMA2,
+#endif
+};
+
static int au_ide_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -610,9 +576,6 @@ static int au_ide_probe(struct device *dev)
#endif
memset(&auide_hwif, 0, sizeof(_auide_hwif));
- auide_hwif.dev = 0;
-
- ahwif->dev = dev;
ahwif->irq = platform_get_irq(pdev, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -643,28 +606,16 @@ static int au_ide_probe(struct device *dev)
/* FIXME: This might possibly break PCMCIA IDE devices */
hwif = &ide_hwifs[pdev->id];
- hwif->irq = ahwif->irq;
- hwif->chipset = ide_au1xxx;
memset(&hw, 0, sizeof(hw));
auide_setup_ports(&hw, ahwif);
- memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
+ hw.irq = ahwif->irq;
+ hw.dev = dev;
+ hw.chipset = ide_au1xxx;
- hwif->ultra_mask = 0x0; /* Disable Ultra DMA */
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
- hwif->mwdma_mask = 0x07; /* Multimode-2 DMA */
- hwif->swdma_mask = 0x00;
-#else
- hwif->mwdma_mask = 0x0;
- hwif->swdma_mask = 0x0;
-#endif
-
- hwif->pio_mask = ATA_PIO4;
- hwif->host_flags = IDE_HFLAG_POST_SET_MODE;
+ ide_init_port_hw(hwif, &hw);
- hwif->noprobe = 0;
- hwif->drives[0].unmask = 1;
- hwif->drives[1].unmask = 1;
+ hwif->dev = dev;
/* hold should be on in all cases */
hwif->hold = 1;
@@ -684,32 +635,21 @@ static int au_ide_probe(struct device *dev)
hwif->set_dma_mode = &auide_set_dma_mode;
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
- hwif->dma_off_quietly = &auide_dma_off_quietly;
hwif->dma_timeout = &auide_dma_timeout;
hwif->mdma_filter = &auide_mdma_filter;
+ hwif->dma_host_set = &auide_dma_host_set;
hwif->dma_exec_cmd = &auide_dma_exec_cmd;
hwif->dma_start = &auide_dma_start;
hwif->ide_dma_end = &auide_dma_end;
hwif->dma_setup = &auide_dma_setup;
hwif->ide_dma_test_irq = &auide_dma_test_irq;
- hwif->dma_host_off = &auide_dma_host_off;
- hwif->dma_host_on = &auide_dma_host_on;
hwif->dma_lost_irq = &auide_dma_lost_irq;
- hwif->ide_dma_on = &auide_dma_on;
-#else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
- hwif->channel = 0;
- hwif->hold = 1;
+#endif
hwif->select_data = 0; /* no chipset-specific code */
hwif->config_data = 0; /* no chipset-specific code */
- hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */
- hwif->drives[1].autotune = 1;
-#endif
- hwif->drives[0].no_io_32bit = 1;
- hwif->drives[1].no_io_32bit = 1;
-
auide_hwif.hwif = hwif;
hwif->hwif_data = &auide_hwif;
@@ -720,7 +660,7 @@ static int au_ide_probe(struct device *dev)
idx[0] = hwif->index;
- ide_device_add(idx);
+ ide_device_add(idx, &au1xxx_port_info);
dev_set_drvdata(dev, hwif);
@@ -737,7 +677,7 @@ static int au_ide_remove(struct device *dev)
ide_hwif_t *hwif = dev_get_drvdata(dev);
_auide_hwif *ahwif = &auide_hwif;
- ide_unregister(hwif - ide_hwifs);
+ ide_unregister(hwif->index, 0, 0);
iounmap((void *)ahwif->regbase);
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
index 521edd41b57..956259fc09b 100644
--- a/drivers/ide/mips/swarm.c
+++ b/drivers/ide/mips/swarm.c
@@ -117,6 +117,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
default_hwif_mmiops(hwif);
/* Prevent resource map manipulation. */
hwif->mmio = 1;
+ hwif->chipset = ide_generic;
hwif->noprobe = 0;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
@@ -128,7 +129,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
idx[0] = hwif->index;
- ide_device_add(idx);
+ ide_device_add(idx, NULL);
dev_set_drvdata(dev, hwif);
diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
index 95d1ea8f1f1..94803253e8a 100644
--- a/drivers/ide/pci/Makefile
+++ b/drivers/ide/pci/Makefile
@@ -36,4 +36,8 @@ obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o
# Must appear at the end of the block
obj-$(CONFIG_BLK_DEV_GENERIC) += generic.o
+ifeq ($(CONFIG_BLK_DEV_CMD640), m)
+ obj-m += cmd640.o
+endif
+
EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index 19ec421f7b9..cfb3265bc1a 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/aec62xx.c Version 0.27 Sep 16, 2007
- *
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
*
@@ -9,7 +7,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -90,7 +87,7 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr
static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 d_conf = 0;
u8 ultra = 0, ultra_conf = 0;
u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
@@ -116,7 +113,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 unit = (drive->select.b.unit & 0x01);
u8 tmp1 = 0, tmp2 = 0;
u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
@@ -168,29 +165,28 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch
return dev->irq;
}
+static u8 __devinit atp86x_cable_detect(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
+
+ pci_read_config_byte(dev, 0x49, &ata66);
+
+ return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
hwif->set_pio_mode = &aec_set_pio_mode;
if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
hwif->set_dma_mode = &aec6210_set_mode;
- else
+ else {
hwif->set_dma_mode = &aec6260_set_mode;
- if (hwif->dma_base == 0)
- return;
-
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
- return;
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
- u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
-
- pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
-
- hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+ hwif->cable_detect = atp86x_cable_detect;
}
}
@@ -202,6 +198,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.host_flags = IDE_HFLAG_SERIALIZE |
IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_NO_DSC |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -211,6 +209,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -220,7 +219,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
@@ -228,7 +228,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.name = "AEC6280",
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -237,7 +239,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -260,6 +264,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi
{
struct ide_port_info d;
u8 idx = id->driver_data;
+ int err;
+
+ err = pci_enable_device(dev);
+ if (err)
+ return err;
d = aec62xx_chipsets[idx];
@@ -272,7 +281,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi
}
}
- return ide_setup_pci_device(dev, &d);
+ err = ide_setup_pci_device(dev, &d);
+ if (err)
+ pci_disable_device(dev);
+
+ return err;
}
static const struct pci_device_id aec62xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index a607dd31a64..b3b6f514ce2 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/alim15x3.c Version 0.29 Sep 16 2007
- *
* Copyright (C) 1998-2000 Michel Aubry, Maintainer
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
* Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
@@ -33,7 +31,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -293,7 +290,7 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count)
static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
int s_time, a_time, c_time;
u8 s_clc, a_clc, r_clc;
unsigned long flags;
@@ -396,15 +393,12 @@ static u8 ali_udma_filter(ide_drive_t *drive)
static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 speed1 = speed;
u8 unit = (drive->select.b.unit & 0x01);
u8 tmpbyte = 0x00;
int m5229_udma = (hwif->channel) ? 0x57 : 0x56;
- if (speed < XFER_PIO_0)
- return;
-
if (speed == XFER_UDMA_6)
speed1 = 0x47;
@@ -603,6 +597,11 @@ static int ali_cable_override(struct pci_dev *pdev)
pdev->subsystem_device == 0x10AF)
return 1;
+ /* Mitac 8317 (Winbook-A) and relatives */
+ if (pdev->subsystem_vendor == 0x1071 &&
+ pdev->subsystem_device == 0x8317)
+ return 1;
+
/* Systems by DMI */
if (dmi_check_system(cable_dmi_table))
return 1;
@@ -623,7 +622,7 @@ static int ali_cable_override(struct pci_dev *pdev)
static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long flags;
u8 cbl = ATA_CBL_PATA40, tmpbyte;
@@ -666,13 +665,12 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
hwif->set_dma_mode = &ali_set_dma_mode;
hwif->udma_filter = &ali_udma_filter;
+ hwif->cable_detect = ata66_ali15x3;
+
if (hwif->dma_base == 0)
return;
hwif->dma_setup = &ali15x3_dma_setup;
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = ata66_ali15x3(hwif);
}
/**
@@ -686,12 +684,13 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 ideic, inmir;
s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6,
1, 11, 0, 12, 0, 14, 0, 15 };
int irq = -1;
- if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229)
+ if (dev->device == PCI_DEVICE_ID_AL_M5229)
hwif->irq = hwif->channel ? 15 : 14;
if (isa_dev) {
@@ -743,7 +742,7 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
return;
if (!hwif->channel)
outb(inb(dmabase + 2) & 0x60, dmabase + 2);
- ide_setup_dma(hwif, dmabase, 8);
+ ide_setup_dma(hwif, dmabase);
}
static const struct ide_port_info ali15x3_chipset __devinitdata = {
@@ -773,7 +772,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
};
struct ide_port_info d = ali15x3_chipset;
- u8 rev = dev->revision;
+ u8 rev = dev->revision, idx = id->driver_data;
if (pci_dev_present(ati_rs100))
printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n");
@@ -796,6 +795,9 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
d.udma_mask = ATA_UDMA6;
}
+ if (idx == 0)
+ d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+
#if defined(CONFIG_SPARC64)
d.init_hwif = init_hwif_common_ali15x3;
#endif /* CONFIG_SPARC64 */
@@ -805,7 +807,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
static const struct pci_device_id alim15x3_pci_tbl[] = {
{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 },
- { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 0 },
+ { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 8d4125ec252..2ef890ce809 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,6 +1,4 @@
/*
- * Version 2.24
- *
* AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
* IDE driver for Linux.
*
@@ -19,90 +17,52 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
-#include <asm/io.h>
#include "ide-timing.h"
-#define AMD_IDE_CONFIG (0x01 + amd_config->base)
-#define AMD_CABLE_DETECT (0x02 + amd_config->base)
-#define AMD_DRIVE_TIMING (0x08 + amd_config->base)
-#define AMD_8BIT_TIMING (0x0e + amd_config->base)
-#define AMD_ADDRESS_SETUP (0x0c + amd_config->base)
-#define AMD_UDMA_TIMING (0x10 + amd_config->base)
-
-#define AMD_CHECK_SWDMA 0x08
-#define AMD_BAD_SWDMA 0x10
-#define AMD_BAD_FIFO 0x20
-#define AMD_CHECK_SERENADE 0x40
-
-/*
- * AMD SouthBridge chips.
- */
-
-static struct amd_ide_chip {
- unsigned short id;
- u8 base;
- u8 udma_mask;
- u8 flags;
-} amd_ide_chips[] = {
- { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, ATA_UDMA2, AMD_BAD_SWDMA },
- { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, ATA_UDMA4, AMD_CHECK_SWDMA },
- { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, ATA_UDMA5, AMD_BAD_FIFO },
- { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, ATA_UDMA5, },
- { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, ATA_UDMA6, AMD_CHECK_SERENADE },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, ATA_UDMA5, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, },
- { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, ATA_UDMA5, },
- { 0 }
+enum {
+ AMD_IDE_CONFIG = 0x41,
+ AMD_CABLE_DETECT = 0x42,
+ AMD_DRIVE_TIMING = 0x48,
+ AMD_8BIT_TIMING = 0x4e,
+ AMD_ADDRESS_SETUP = 0x4c,
+ AMD_UDMA_TIMING = 0x50,
};
-static struct amd_ide_chip *amd_config;
-static const struct ide_port_info *amd_chipset;
static unsigned int amd_80w;
static unsigned int amd_clock;
static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
+static inline u8 amd_offset(struct pci_dev *dev)
+{
+ return (dev->vendor == PCI_VENDOR_ID_NVIDIA) ? 0x10 : 0;
+}
+
/*
* amd_set_speed() writes timing values to the chipset registers
*/
-static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing)
+static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
+ struct ide_timing *timing)
{
- unsigned char t;
+ u8 t = 0, offset = amd_offset(dev);
- pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t);
+ pci_read_config_byte(dev, AMD_ADDRESS_SETUP + offset, &t);
t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
- pci_write_config_byte(dev, AMD_ADDRESS_SETUP, t);
+ pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t);
- pci_write_config_byte(dev, AMD_8BIT_TIMING + (1 - (dn >> 1)),
+ pci_write_config_byte(dev, AMD_8BIT_TIMING + offset + (1 - (dn >> 1)),
((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
- pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
+ pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn),
((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
- switch (amd_config->udma_mask) {
+ switch (udma_mask) {
case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
@@ -110,7 +70,7 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
default: return;
}
- pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
+ pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t);
}
/*
@@ -120,12 +80,15 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
static void amd_set_drive(ide_drive_t *drive, const u8 speed)
{
- ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
struct ide_timing t, p;
int T, UT;
+ u8 udma_mask = hwif->ultra_mask;
T = 1000000000 / amd_clock;
- UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
+ UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
ide_timing_compute(drive, speed, &t, T, UT);
@@ -137,7 +100,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
- amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
+ amd_set_speed(dev, drive->dn, udma_mask, &t);
}
/*
@@ -149,67 +112,68 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
amd_set_drive(drive, XFER_PIO_0 + pio);
}
-/*
- * The initialization callback. Here we determine the IDE chip type
- * and initialize its drive independent registers.
- */
+static void __devinit amd7409_cable_detect(struct pci_dev *dev,
+ const char *name)
+{
+ /* no host side cable detection */
+ amd_80w = 0x03;
+}
-static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const char *name)
+static void __devinit amd7411_cable_detect(struct pci_dev *dev,
+ const char *name)
{
- unsigned char t;
- unsigned int u;
int i;
+ u32 u = 0;
+ u8 t = 0, offset = amd_offset(dev);
+
+ pci_read_config_byte(dev, AMD_CABLE_DETECT + offset, &t);
+ pci_read_config_dword(dev, AMD_UDMA_TIMING + offset, &u);
+ amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
+ for (i = 24; i >= 0; i -= 8)
+ if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
+ printk(KERN_WARNING "%s: BIOS didn't set cable bits "
+ "correctly. Enabling workaround.\n",
+ name);
+ amd_80w |= (1 << (1 - (i >> 4)));
+ }
+}
/*
- * Check for bad SWDMA.
+ * The initialization callback. Initialize drive independent registers.
*/
- if (amd_config->flags & AMD_CHECK_SWDMA) {
- if (dev->revision <= 7)
- amd_config->flags |= AMD_BAD_SWDMA;
- }
+static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
+ const char *name)
+{
+ u8 t = 0, offset = amd_offset(dev);
/*
* Check 80-wire cable presence.
*/
- switch (amd_config->udma_mask) {
-
- case ATA_UDMA6:
- case ATA_UDMA5:
- pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
- pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
- amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
- for (i = 24; i >= 0; i -= 8)
- if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
- printk(KERN_WARNING "%s: BIOS didn't set cable bits correctly. Enabling workaround.\n",
- amd_chipset->name);
- amd_80w |= (1 << (1 - (i >> 4)));
- }
- break;
-
- case ATA_UDMA4:
- /* no host side cable detection */
- amd_80w = 0x03;
- break;
- }
+ if (dev->vendor == PCI_VENDOR_ID_AMD &&
+ dev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
+ ; /* no UDMA > 2 */
+ else if (dev->vendor == PCI_VENDOR_ID_AMD &&
+ dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
+ amd7409_cable_detect(dev, name);
+ else
+ amd7411_cable_detect(dev, name);
/*
* Take care of prefetch & postwrite.
*/
- pci_read_config_byte(dev, AMD_IDE_CONFIG, &t);
- pci_write_config_byte(dev, AMD_IDE_CONFIG,
- (amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0));
-
-/*
- * Take care of incorrectly wired Serenade mainboards.
- */
-
- if ((amd_config->flags & AMD_CHECK_SERENADE) &&
- dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
- dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
- amd_config->udma_mask = ATA_UDMA5;
+ pci_read_config_byte(dev, AMD_IDE_CONFIG + offset, &t);
+ /*
+ * Check for broken FIFO support.
+ */
+ if (dev->vendor == PCI_VENDOR_ID_AMD &&
+ dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411)
+ t &= 0x0f;
+ else
+ t |= 0xf0;
+ pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
/*
* Determine the system bus clock.
@@ -225,53 +189,44 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
if (amd_clock < 20000 || amd_clock > 50000) {
printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
- amd_chipset->name, amd_clock);
+ name, amd_clock);
amd_clock = 33333;
}
-/*
- * Print the boot message.
- */
-
- printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
- amd_chipset->name, pci_name(dev), dev->revision,
- amd_dma[fls(amd_config->udma_mask) - 1]);
-
return dev->irq;
}
+static u8 __devinit amd_cable_detect(ide_hwif_t *hwif)
+{
+ if ((amd_80w >> hwif->channel) & 1)
+ return ATA_CBL_PATA80;
+ else
+ return ATA_CBL_PATA40;
+}
+
static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
if (hwif->irq == 0) /* 0 is bogus but will do for now */
- hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel);
+ hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
hwif->set_pio_mode = &amd_set_pio_mode;
hwif->set_dma_mode = &amd_set_drive;
- if (!hwif->dma_base)
- return;
-
- hwif->ultra_mask = amd_config->udma_mask;
- if (amd_config->flags & AMD_BAD_SWDMA)
- hwif->swdma_mask = 0x00;
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
- if ((amd_80w >> hwif->channel) & 1)
- hwif->cbl = ATA_CBL_PATA80;
- else
- hwif->cbl = ATA_CBL_PATA40;
- }
+ hwif->cable_detect = amd_cable_detect;
}
#define IDE_HFLAGS_AMD \
(IDE_HFLAG_PIO_NO_BLACKLIST | \
IDE_HFLAG_PIO_NO_DOWNGRADE | \
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_POST_SET_MODE | \
IDE_HFLAG_IO_32BIT | \
IDE_HFLAG_UNMASK_IRQS | \
IDE_HFLAG_BOOTABLE)
-#define DECLARE_AMD_DEV(name_str) \
+#define DECLARE_AMD_DEV(name_str, swdma, udma) \
{ \
.name = name_str, \
.init_chipset = init_chipset_amd74xx, \
@@ -279,11 +234,12 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
.enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
.host_flags = IDE_HFLAGS_AMD, \
.pio_mask = ATA_PIO5, \
- .swdma_mask = ATA_SWDMA2, \
+ .swdma_mask = swdma, \
.mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = udma, \
}
-#define DECLARE_NV_DEV(name_str) \
+#define DECLARE_NV_DEV(name_str, udma) \
{ \
.name = name_str, \
.init_chipset = init_chipset_amd74xx, \
@@ -293,45 +249,62 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
.pio_mask = ATA_PIO5, \
.swdma_mask = ATA_SWDMA2, \
.mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = udma, \
}
static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_AMD_DEV("AMD7401"),
- /* 1 */ DECLARE_AMD_DEV("AMD7409"),
- /* 2 */ DECLARE_AMD_DEV("AMD7411"),
- /* 3 */ DECLARE_AMD_DEV("AMD7441"),
- /* 4 */ DECLARE_AMD_DEV("AMD8111"),
-
- /* 5 */ DECLARE_NV_DEV("NFORCE"),
- /* 6 */ DECLARE_NV_DEV("NFORCE2"),
- /* 7 */ DECLARE_NV_DEV("NFORCE2-U400R"),
- /* 8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA"),
- /* 9 */ DECLARE_NV_DEV("NFORCE3-150"),
- /* 10 */ DECLARE_NV_DEV("NFORCE3-250"),
- /* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA"),
- /* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
- /* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
- /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
- /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
- /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"),
- /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
- /* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
- /* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"),
- /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"),
- /* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"),
- /* 22 */ DECLARE_AMD_DEV("AMD5536"),
+ /* 0 */ DECLARE_AMD_DEV("AMD7401", 0x00, ATA_UDMA2),
+ /* 1 */ DECLARE_AMD_DEV("AMD7409", ATA_SWDMA2, ATA_UDMA4),
+ /* 2 */ DECLARE_AMD_DEV("AMD7411", ATA_SWDMA2, ATA_UDMA5),
+ /* 3 */ DECLARE_AMD_DEV("AMD7441", ATA_SWDMA2, ATA_UDMA5),
+ /* 4 */ DECLARE_AMD_DEV("AMD8111", ATA_SWDMA2, ATA_UDMA6),
+
+ /* 5 */ DECLARE_NV_DEV("NFORCE", ATA_UDMA5),
+ /* 6 */ DECLARE_NV_DEV("NFORCE2", ATA_UDMA6),
+ /* 7 */ DECLARE_NV_DEV("NFORCE2-U400R", ATA_UDMA6),
+ /* 8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA", ATA_UDMA6),
+ /* 9 */ DECLARE_NV_DEV("NFORCE3-150", ATA_UDMA6),
+ /* 10 */ DECLARE_NV_DEV("NFORCE3-250", ATA_UDMA6),
+ /* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA", ATA_UDMA6),
+ /* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2", ATA_UDMA6),
+ /* 13 */ DECLARE_NV_DEV("NFORCE-CK804", ATA_UDMA6),
+ /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04", ATA_UDMA6),
+ /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51", ATA_UDMA6),
+ /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55", ATA_UDMA6),
+ /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61", ATA_UDMA6),
+ /* 18 */ DECLARE_NV_DEV("NFORCE-MCP65", ATA_UDMA6),
+ /* 19 */ DECLARE_NV_DEV("NFORCE-MCP67", ATA_UDMA6),
+ /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73", ATA_UDMA6),
+ /* 21 */ DECLARE_NV_DEV("NFORCE-MCP77", ATA_UDMA6),
+
+ /* 22 */ DECLARE_AMD_DEV("AMD5536", ATA_SWDMA2, ATA_UDMA5),
};
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
- amd_chipset = amd74xx_chipsets + id->driver_data;
- amd_config = amd_ide_chips + id->driver_data;
- if (dev->device != amd_config->id) {
- printk(KERN_ERR "%s: assertion 0x%02x == 0x%02x failed !\n",
- pci_name(dev), dev->device, amd_config->id);
- return -ENODEV;
+ struct ide_port_info d;
+ u8 idx = id->driver_data;
+
+ d = amd74xx_chipsets[idx];
+
+ /*
+ * Check for bad SWDMA and incorrectly wired Serenade mainboards.
+ */
+ if (idx == 1) {
+ if (dev->revision <= 7)
+ d.swdma_mask = 0;
+ d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+ } else if (idx == 4) {
+ if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
+ dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
+ d.udma_mask = ATA_UDMA5;
}
- return ide_setup_pci_device(dev, amd_chipset);
+
+ printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
+ d.name, pci_name(dev), dev->revision,
+ amd_dma[fls(d.udma_mask) - 1]);
+
+ return ide_setup_pci_device(dev, &d);
}
static const struct pci_device_id amd74xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index ef8e0164ef7..7e037c880cb 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/atiixp.c Version 0.03 Aug 3 2007
- *
* Copyright (C) 2003 ATI Inc. <hyu@ati.com>
* Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz
*/
@@ -8,15 +6,11 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/delay.h>
#include <linux/init.h>
-#include <asm/io.h>
-
#define ATIIXP_IDE_PIO_TIMING 0x40
#define ATIIXP_IDE_MDMA_TIMING 0x44
#define ATIIXP_IDE_PIO_CONTROL 0x48
@@ -43,47 +37,8 @@ static atiixp_ide_timing mdma_timing[] = {
{ 0x02, 0x00 },
};
-static int save_mdma_mode[4];
-
static DEFINE_SPINLOCK(atiixp_lock);
-static void atiixp_dma_host_on(ide_drive_t *drive)
-{
- struct pci_dev *dev = drive->hwif->pci_dev;
- unsigned long flags;
- u16 tmp16;
-
- spin_lock_irqsave(&atiixp_lock, flags);
-
- pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
- if (save_mdma_mode[drive->dn])
- tmp16 &= ~(1 << drive->dn);
- else
- tmp16 |= (1 << drive->dn);
- pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
-
- spin_unlock_irqrestore(&atiixp_lock, flags);
-
- ide_dma_host_on(drive);
-}
-
-static void atiixp_dma_host_off(ide_drive_t *drive)
-{
- struct pci_dev *dev = drive->hwif->pci_dev;
- unsigned long flags;
- u16 tmp16;
-
- spin_lock_irqsave(&atiixp_lock, flags);
-
- pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
- tmp16 &= ~(1 << drive->dn);
- pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
-
- spin_unlock_irqrestore(&atiixp_lock, flags);
-
- ide_dma_host_off(drive);
-}
-
/**
* atiixp_set_pio_mode - set host controller for PIO mode
* @drive: drive
@@ -94,7 +49,7 @@ static void atiixp_dma_host_off(ide_drive_t *drive)
static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- struct pci_dev *dev = drive->hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
unsigned long flags;
int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
u32 pio_timing_data;
@@ -127,37 +82,54 @@ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- struct pci_dev *dev = drive->hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
unsigned long flags;
int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
u32 tmp32;
u16 tmp16;
-
- if (speed < XFER_MW_DMA_0)
- return;
+ u16 udma_ctl = 0;
spin_lock_irqsave(&atiixp_lock, flags);
- save_mdma_mode[drive->dn] = 0;
+ pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_ctl);
+
if (speed >= XFER_UDMA_0) {
pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
tmp16 &= ~(0x07 << (drive->dn * 4));
tmp16 |= ((speed & 0x07) << (drive->dn * 4));
pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
- } else {
- if ((speed >= XFER_MW_DMA_0) && (speed <= XFER_MW_DMA_2)) {
- save_mdma_mode[drive->dn] = speed;
- pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
- tmp32 &= ~(0xff << timing_shift);
- tmp32 |= (mdma_timing[speed & 0x03].recover_width << timing_shift) |
- (mdma_timing[speed & 0x03].command_width << (timing_shift + 4));
- pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
- }
+
+ udma_ctl |= (1 << drive->dn);
+ } else if (speed >= XFER_MW_DMA_0) {
+ u8 i = speed & 0x03;
+
+ pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
+ tmp32 &= ~(0xff << timing_shift);
+ tmp32 |= (mdma_timing[i].recover_width << timing_shift) |
+ (mdma_timing[i].command_width << (timing_shift + 4));
+ pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
+
+ udma_ctl &= ~(1 << drive->dn);
}
+ pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, udma_ctl);
+
spin_unlock_irqrestore(&atiixp_lock, flags);
}
+static u8 __devinit atiixp_cable_detect(ide_hwif_t *hwif)
+{
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ u8 udma_mode = 0, ch = hwif->channel;
+
+ pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+
+ if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
+ return ATA_CBL_PATA80;
+ else
+ return ATA_CBL_PATA40;
+}
+
/**
* init_hwif_atiixp - fill in the hwif for the ATIIXP
* @hwif: IDE interface
@@ -168,25 +140,10 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
{
- u8 udma_mode = 0;
- u8 ch = hwif->channel;
- struct pci_dev *pdev = hwif->pci_dev;
-
hwif->set_pio_mode = &atiixp_set_pio_mode;
hwif->set_dma_mode = &atiixp_set_dma_mode;
- if (!hwif->dma_base)
- return;
-
- pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
-
- if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
- hwif->cbl = ATA_CBL_PATA80;
- else
- hwif->cbl = ATA_CBL_PATA40;
-
- hwif->dma_host_on = &atiixp_dma_host_on;
- hwif->dma_host_off = &atiixp_dma_host_off;
+ hwif->cable_detect = atiixp_cable_detect;
}
static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index 4aa48104e0c..bd24dad3cfc 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/cmd640.c Version 1.02 Sep 01, 1996
- *
* Copyright (C) 1995-1996 Linus Torvalds & authors (see below)
*/
@@ -105,10 +103,6 @@
#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/ide.h>
#include <linux/init.h>
@@ -705,10 +699,22 @@ static int pci_conf2(void)
return 0;
}
+static const struct ide_port_info cmd640_port_info __initdata = {
+ .chipset = ide_cmd640,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_NO_DMA |
+ IDE_HFLAG_NO_AUTOTUNE |
+ IDE_HFLAG_ABUSE_PREFETCH |
+ IDE_HFLAG_ABUSE_FAST_DEVSEL,
+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ .pio_mask = ATA_PIO5,
+#endif
+};
+
/*
- * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c
+ * Probe for a cmd640 chipset, and initialize it if found.
*/
-int __init ide_probe_for_cmd640x (void)
+static int __init cmd640x_init(void)
{
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
int second_port_toggled = 0;
@@ -717,6 +723,7 @@ int __init ide_probe_for_cmd640x (void)
const char *bus_type, *port2;
unsigned int index;
u8 b, cfr;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (cmd640_vlb && probe_for_cmd640_vlb()) {
bus_type = "VLB";
@@ -761,14 +768,12 @@ int __init ide_probe_for_cmd640x (void)
setup_device_ptrs ();
printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n",
cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr);
- cmd_hwif0->chipset = ide_cmd640;
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
- cmd_hwif0->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
- IDE_HFLAG_ABUSE_FAST_DEVSEL;
- cmd_hwif0->pio_mask = ATA_PIO5;
cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+ idx[0] = cmd_hwif0->index;
+
/*
* Ensure compatibility by always using the slowest timings
* for access to the drive's command register block,
@@ -814,21 +819,14 @@ int __init ide_probe_for_cmd640x (void)
* Initialize data for secondary cmd640 port, if enabled
*/
if (second_port_cmd640) {
- cmd_hwif0->serialized = 1;
- cmd_hwif1->serialized = 1;
- cmd_hwif1->chipset = ide_cmd640;
- cmd_hwif0->mate = cmd_hwif1;
- cmd_hwif1->mate = cmd_hwif0;
- cmd_hwif1->channel = 1;
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
- cmd_hwif1->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
- IDE_HFLAG_ABUSE_FAST_DEVSEL;
- cmd_hwif1->pio_mask = ATA_PIO5;
cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+
+ idx[1] = cmd_hwif1->index;
}
printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
- cmd_hwif0->serialized ? "" : "not ", port2);
+ second_port_cmd640 ? "" : "not ", port2);
/*
* Establish initial timings/prefetch for all drives.
@@ -872,6 +870,13 @@ int __init ide_probe_for_cmd640x (void)
#ifdef CMD640_DUMP_REGS
cmd640_dump_regs();
#endif
+
+ ide_device_add(idx, &cmd640_port_info);
+
return 1;
}
+module_param_named(probe_vlb, cmd640_vlb, bool, 0);
+MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset");
+
+module_init(cmd640x_init);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index ea0143ef5fe..edabe6299ef 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007
- *
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported
* on the 646U2 and not on the 646U.
@@ -15,15 +13,12 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
-#define DISPLAY_CMD64X_TIMINGS
-
#define CMD_DEBUG 0
#if CMD_DEBUG
@@ -37,11 +32,6 @@
*/
#define CFR 0x50
#define CFR_INTR_CH0 0x04
-#define CNTRL 0x51
-#define CNTRL_ENA_1ST 0x04
-#define CNTRL_ENA_2ND 0x08
-#define CNTRL_DIS_RA0 0x40
-#define CNTRL_DIS_RA1 0x80
#define CMDTIM 0x52
#define ARTTIM0 0x53
@@ -60,108 +50,13 @@
#define MRDMODE 0x71
#define MRDMODE_INTR_CH0 0x04
#define MRDMODE_INTR_CH1 0x08
-#define MRDMODE_BLK_CH0 0x10
-#define MRDMODE_BLK_CH1 0x20
-#define BMIDESR0 0x72
#define UDIDETCR0 0x73
#define DTPR0 0x74
#define BMIDECR1 0x78
#define BMIDECSR 0x79
-#define BMIDESR1 0x7A
#define UDIDETCR1 0x7B
#define DTPR1 0x7C
-#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 cmd64x_proc = 0;
-
-#define CMD_MAX_DEVS 5
-
-static struct pci_dev *cmd_devs[CMD_MAX_DEVS];
-static int n_cmd_devs;
-
-static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
-{
- char *p = buf;
- u8 reg72 = 0, reg73 = 0; /* primary */
- u8 reg7a = 0, reg7b = 0; /* secondary */
- u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0; /* extra */
-
- p += sprintf(p, "\nController: %d\n", index);
- p += sprintf(p, "PCI-%x Chipset.\n", dev->device);
-
- (void) pci_read_config_byte(dev, CFR, &reg50);
- (void) pci_read_config_byte(dev, CNTRL, &reg51);
- (void) pci_read_config_byte(dev, ARTTIM23, &reg57);
- (void) pci_read_config_byte(dev, MRDMODE, &reg71);
- (void) pci_read_config_byte(dev, BMIDESR0, &reg72);
- (void) pci_read_config_byte(dev, UDIDETCR0, &reg73);
- (void) pci_read_config_byte(dev, BMIDESR1, &reg7a);
- (void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
-
- /* PCI0643/6 originally didn't have the primary channel enable bit */
- if ((dev->device == PCI_DEVICE_ID_CMD_643) ||
- (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 3))
- reg51 |= CNTRL_ENA_1ST;
-
- p += sprintf(p, "---------------- Primary Channel "
- "---------------- Secondary Channel ------------\n");
- p += sprintf(p, " %s %s\n",
- (reg51 & CNTRL_ENA_1ST) ? "enabled " : "disabled",
- (reg51 & CNTRL_ENA_2ND) ? "enabled " : "disabled");
- p += sprintf(p, "---------------- drive0 --------- drive1 "
- "-------- drive0 --------- drive1 ------\n");
- p += sprintf(p, "DMA enabled: %s %s"
- " %s %s\n",
- (reg72 & 0x20) ? "yes" : "no ", (reg72 & 0x40) ? "yes" : "no ",
- (reg7a & 0x20) ? "yes" : "no ", (reg7a & 0x40) ? "yes" : "no ");
- p += sprintf(p, "UltraDMA mode: %s (%c) %s (%c)",
- ( reg73 & 0x01) ? " on" : "off",
- ((reg73 & 0x30) == 0x30) ? ((reg73 & 0x04) ? '3' : '0') :
- ((reg73 & 0x30) == 0x20) ? ((reg73 & 0x04) ? '3' : '1') :
- ((reg73 & 0x30) == 0x10) ? ((reg73 & 0x04) ? '4' : '2') :
- ((reg73 & 0x30) == 0x00) ? ((reg73 & 0x04) ? '5' : '2') : '?',
- ( reg73 & 0x02) ? " on" : "off",
- ((reg73 & 0xC0) == 0xC0) ? ((reg73 & 0x08) ? '3' : '0') :
- ((reg73 & 0xC0) == 0x80) ? ((reg73 & 0x08) ? '3' : '1') :
- ((reg73 & 0xC0) == 0x40) ? ((reg73 & 0x08) ? '4' : '2') :
- ((reg73 & 0xC0) == 0x00) ? ((reg73 & 0x08) ? '5' : '2') : '?');
- p += sprintf(p, " %s (%c) %s (%c)\n",
- ( reg7b & 0x01) ? " on" : "off",
- ((reg7b & 0x30) == 0x30) ? ((reg7b & 0x04) ? '3' : '0') :
- ((reg7b & 0x30) == 0x20) ? ((reg7b & 0x04) ? '3' : '1') :
- ((reg7b & 0x30) == 0x10) ? ((reg7b & 0x04) ? '4' : '2') :
- ((reg7b & 0x30) == 0x00) ? ((reg7b & 0x04) ? '5' : '2') : '?',
- ( reg7b & 0x02) ? " on" : "off",
- ((reg7b & 0xC0) == 0xC0) ? ((reg7b & 0x08) ? '3' : '0') :
- ((reg7b & 0xC0) == 0x80) ? ((reg7b & 0x08) ? '3' : '1') :
- ((reg7b & 0xC0) == 0x40) ? ((reg7b & 0x08) ? '4' : '2') :
- ((reg7b & 0xC0) == 0x00) ? ((reg7b & 0x08) ? '5' : '2') : '?');
- p += sprintf(p, "Interrupt: %s, %s %s, %s\n",
- (reg71 & MRDMODE_BLK_CH0 ) ? "blocked" : "enabled",
- (reg50 & CFR_INTR_CH0 ) ? "pending" : "clear ",
- (reg71 & MRDMODE_BLK_CH1 ) ? "blocked" : "enabled",
- (reg57 & ARTTIM23_INTR_CH1) ? "pending" : "clear ");
-
- return (char *)p;
-}
-
-static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
-{
- char *p = buffer;
- int i;
-
- for (i = 0; i < n_cmd_devs; i++) {
- struct pci_dev *dev = cmd_devs[i];
- p = print_cmd64x_get_info(p, dev, i);
- }
- return p-buffer; /* => must be less than 4k! */
-}
-
-#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
-
static u8 quantize_timing(int timing, int quant)
{
return (timing + quant - 1) / quant;
@@ -173,7 +68,7 @@ static u8 quantize_timing(int timing, int quant)
*/
static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
int clock_time = 1000 / system_bus_clock();
u8 cycle_count, active_count, recovery_count, drwtim;
static const u8 recovery_values[] =
@@ -220,7 +115,7 @@ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_
static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned int cycle_time;
u8 setup_count, arttim = 0;
@@ -285,7 +180,7 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 unit = drive->dn & 0x01;
u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0;
@@ -322,8 +217,6 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
case XFER_MW_DMA_0:
program_cycle_times(drive, 480, 215);
break;
- default:
- return;
}
if (speed >= XFER_SW_DMA_0)
@@ -333,13 +226,15 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
static int cmd648_ide_dma_end (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ unsigned long base = hwif->dma_base - (hwif->channel * 8);
int err = __ide_dma_end(drive);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
- u8 mrdmode = inb(hwif->dma_master + 0x01);
+ u8 mrdmode = inb(base + 1);
/* clear the interrupt bit */
- outb(mrdmode | irq_mask, hwif->dma_master + 0x01);
+ outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
+ base + 1);
return err;
}
@@ -347,7 +242,7 @@ static int cmd648_ide_dma_end (ide_drive_t *drive)
static int cmd64x_ide_dma_end (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
@@ -364,10 +259,11 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ unsigned long base = hwif->dma_base - (hwif->channel * 8);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
u8 dma_stat = inb(hwif->dma_status);
- u8 mrdmode = inb(hwif->dma_master + 0x01);
+ u8 mrdmode = inb(base + 1);
#ifdef DEBUG
printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
@@ -386,7 +282,7 @@ static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
@@ -471,22 +367,12 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
mrdmode &= ~0x30;
(void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
-#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
-
- cmd_devs[n_cmd_devs++] = dev;
-
- if (!cmd64x_proc) {
- cmd64x_proc = 1;
- ide_pci_create_host_proc("cmd64x", cmd64x_get_info);
- }
-#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_IDE_PROC_FS */
-
return 0;
}
static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01;
switch (dev->device) {
@@ -501,11 +387,13 @@ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
hwif->set_pio_mode = &cmd64x_set_pio_mode;
hwif->set_dma_mode = &cmd64x_set_dma_mode;
+ hwif->cable_detect = ata66_cmd64x;
+
if (!hwif->dma_base)
return;
@@ -524,9 +412,6 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
if (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5)
hwif->ultra_mask = 0x00;
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = ata66_cmd64x(hwif);
-
switch (dev->device) {
case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_649:
@@ -554,7 +439,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.init_chipset = init_chipset_cmd64x,
.init_hwif = init_hwif_cmd64x,
.enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
- .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
+ .host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
+ IDE_HFLAG_ABUSE_PREFETCH |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* no udma */
@@ -563,6 +450,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.init_chipset = init_chipset_cmd64x,
.init_hwif = init_hwif_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+ .chipset = ide_cmd646,
.host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
@@ -572,7 +460,6 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.init_chipset = init_chipset_cmd64x,
.init_hwif = init_hwif_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
- .chipset = ide_cmd646,
.host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 0466462fd21..0be1a824102 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -35,22 +35,12 @@
#include <linux/module.h>
#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/init.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/dma-mapping.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
struct pio_clocks
{
int address;
@@ -69,9 +59,8 @@ static struct pio_clocks cs5520_pio_clocks[]={
static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *pdev = hwif->pci_dev;
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
int controller = drive->dn > 1 ? 1 : 0;
- u8 reg;
/* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
@@ -91,11 +80,6 @@ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1),
(cs5520_pio_clocks[pio].recovery << 4) |
(cs5520_pio_clocks[pio].assert));
-
- /* Set the DMA enable/disable flag */
- reg = inb(hwif->dma_base + 0x02 + 8*controller);
- reg |= 1<<((drive->dn&1)+5);
- outb(reg, hwif->dma_base + 0x02 + 8*controller);
}
static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
@@ -109,13 +93,14 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
* We wrap the DMA activate to set the vdma flag. This is needed
* so that the IDE DMA layer issues PIO not DMA commands over the
* DMA channel
+ *
+ * ATAPI is harder so disable it for now using IDE_HFLAG_NO_ATAPI_DMA
*/
-
-static int cs5520_dma_on(ide_drive_t *drive)
+
+static void cs5520_dma_host_set(ide_drive_t *drive, int on)
{
- /* ATAPI is harder so leave it for now */
- drive->vdma = 1;
- return 0;
+ drive->vdma = on;
+ ide_dma_host_set(drive, on);
}
static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
@@ -126,7 +111,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
if (hwif->dma_base == 0)
return;
- hwif->ide_dma_on = &cs5520_dma_on;
+ hwif->dma_host_set = &cs5520_dma_host_set;
}
#define DECLARE_CS_DEV(name_str) \
@@ -137,6 +122,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
IDE_HFLAG_CS5520 | \
IDE_HFLAG_VDMA | \
IDE_HFLAG_NO_ATAPI_DMA | \
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |\
IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
}
@@ -160,8 +146,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
ide_setup_pci_noise(dev, d);
/* We must not grab the entire device, it has 'ISA' space in its
- BARS too and we will freak out other bits of the kernel */
- if (pci_enable_device_bars(dev, 1<<2)) {
+ * BARS too and we will freak out other bits of the kernel
+ *
+ * pci_enable_device_bars() is going away. I replaced it with
+ * IO only enable for now but I'll need confirmation this is
+ * allright for that device. If not, it will need some kind of
+ * quirk. --BenH.
+ */
+ if (pci_enable_device_io(dev)) {
printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
return -ENODEV;
}
@@ -178,7 +170,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
ide_pci_setup_ports(dev, d, 14, &idx[0]);
- ide_device_add(idx);
+ ide_device_add(idx, d);
return 0;
}
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index 599408952bd..941a1344820 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/cs5530.c Version 0.77 Sep 24 2007
- *
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2000 Mark Lord <mlord@pobox.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
@@ -17,18 +15,12 @@
#include <linux/module.h>
#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>
/*
* Here are the standard PIO mode 0-4 timings for each "format".
@@ -116,9 +108,6 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
case XFER_MW_DMA_0: timings = 0x00077771; break;
case XFER_MW_DMA_1: timings = 0x00012121; break;
case XFER_MW_DMA_2: timings = 0x00002020; break;
- default:
- BUG();
- break;
}
basereg = CS5530_BASEREG(drive->hwif);
reg = inl(basereg + 4); /* get drive0 config register */
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 9094916e378..d7b5ea992e9 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/cs5535.c
- *
* Copyright (C) 2004-2005 Advanced Micro Devices, Inc.
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
@@ -49,7 +47,7 @@
#define ATAC_BM0_PRD 0x04
#define CS5535_CABLE_DETECT 0x48
-/* Format I PIO settings. We seperate out cmd and data for safer timings */
+/* Format I PIO settings. We separate out cmd and data for safer timings */
static unsigned int cs5535_pio_cmd_timings[5] =
{ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 };
@@ -157,8 +155,9 @@ static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
cs5535_set_speed(drive, XFER_PIO_0 + pio);
}
-static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
+static u8 __devinit cs5535_cable_detect(ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 bit;
/* if a 80 wire cable was detected */
@@ -180,17 +179,14 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
hwif->set_pio_mode = &cs5535_set_pio_mode;
hwif->set_dma_mode = &cs5535_set_dma_mode;
- if (hwif->dma_base == 0)
- return;
-
- hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
+ hwif->cable_detect = cs5535_cable_detect;
}
static const struct ide_port_info cs5535_chipset __devinitdata = {
.name = "CS5535",
.init_hwif = init_hwif_cs5535,
.host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
- IDE_HFLAG_BOOTABLE,
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index 1cd4e9cb052..724cbacf4e5 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/cy82c693.c Version 0.42 Oct 23, 2007
- *
* Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
*
@@ -47,7 +45,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -176,17 +173,12 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
* set DMA mode a specific channel for CY82C693
*/
-static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
+static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
{
- u8 index = 0, data = 0;
+ ide_hwif_t *hwif = drive->hwif;
+ u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
- if (mode>2) /* make sure we set a valid mode */
- mode = 2;
-
- if (mode > drive->id->tDMA) /* to be absolutly sure we have a valid mode */
- mode = drive->id->tDMA;
-
- index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1;
+ index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
#if CY82C693_DEBUG_LOGS
/* for debug let's show the previous values */
@@ -199,7 +191,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
(data&0x3), ((data>>2)&1));
#endif /* CY82C693_DEBUG_LOGS */
- data = (u8)mode|(u8)(single<<2);
+ data = (mode & 3) | (single << 2);
outb(index, CY82_INDEX_PORT);
outb(data, CY82_DATA_PORT);
@@ -207,7 +199,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
#if CY82C693_DEBUG_INFO
printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
drive->name, HWIF(drive)->channel, drive->select.b.unit,
- mode, single);
+ mode & 3, single);
#endif /* CY82C693_DEBUG_INFO */
/*
@@ -230,43 +222,10 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
#endif /* CY82C693_DEBUG_INFO */
}
-/*
- * used to set DMA mode for CY82C693 (single and multi modes)
- */
-static int cy82c693_ide_dma_on (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
-
-#if CY82C693_DEBUG_INFO
- printk (KERN_INFO "dma_on: %s\n", drive->name);
-#endif /* CY82C693_DEBUG_INFO */
-
- if (id != NULL) {
- /* Enable DMA on any drive that has DMA
- * (multi or single) enabled
- */
- if (id->field_valid & 2) { /* regular DMA */
- int mmode, smode;
-
- mmode = id->dma_mword & (id->dma_mword >> 8);
- smode = id->dma_1word & (id->dma_1word >> 8);
-
- if (mmode != 0) {
- /* enable multi */
- cy82c693_dma_enable(drive, (mmode >> 1), 0);
- } else if (smode != 0) {
- /* enable single */
- cy82c693_dma_enable(drive, (smode >> 1), 1);
- }
- }
- }
- return __ide_dma_on(drive);
-}
-
static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
pio_clocks_t pclk;
unsigned int addrCtrl;
@@ -429,18 +388,15 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif)
{
hwif->set_pio_mode = &cy82c693_set_pio_mode;
-
- if (hwif->dma_base == 0)
- return;
-
- hwif->ide_dma_on = &cy82c693_ide_dma_on;
+ hwif->set_dma_mode = &cy82c693_set_dma_mode;
}
static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
{
static ide_hwif_t *primary;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
- if (PCI_FUNC(hwif->pci_dev->devfn) == 1)
+ if (PCI_FUNC(dev->devfn) == 1)
primary = hwif;
else {
hwif->mate = primary;
@@ -454,11 +410,11 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = {
.init_iops = init_iops_cy82c693,
.init_hwif = init_hwif_cy82c693,
.chipset = ide_cy82c693,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 |
IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
- .swdma_mask = ATA_SWDMA2_ONLY,
- .mwdma_mask = ATA_MWDMA2_ONLY,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
};
static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
index 83829081640..3f9cd64c26a 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/pci/delkin_cb.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/delkin_cb.c
- *
* Created 20 Oct 2004 by Mark Lord
*
* Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
@@ -18,15 +16,14 @@
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
-#include <linux/autoconf.h>
+
#include <linux/types.h>
#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/pci.h>
+
#include <asm/io.h>
/*
@@ -54,6 +51,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
ide_hwif_t *hwif = NULL;
ide_drive_t *drive;
int i, rc;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
rc = pci_enable_device(dev);
if (rc) {
@@ -80,20 +78,40 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
hw.irq = dev->irq;
hw.chipset = ide_pci; /* this enables IRQ sharing */
- rc = ide_register_hw(&hw, &ide_undecoded_slave, 0, &hwif);
- if (rc < 0) {
- printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc);
- pci_disable_device(dev);
- return -ENODEV;
- }
+ hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ if (hwif == NULL)
+ goto out_disable;
+
+ i = hwif->index;
+
+ if (hwif->present)
+ ide_unregister(i, 0, 0);
+ else if (!hwif->hold)
+ ide_init_port_data(hwif, i);
+
+ ide_init_port_hw(hwif, &hw);
+ hwif->quirkproc = &ide_undecoded_slave;
+
+ idx[0] = i;
+
+ ide_device_add(idx, NULL);
+
+ if (!hwif->present)
+ goto out_disable;
+
pci_set_drvdata(dev, hwif);
- hwif->pci_dev = dev;
+ hwif->dev = &dev->dev;
drive = &hwif->drives[0];
if (drive->present) {
drive->io_32bit = 1;
drive->unmask = 1;
}
return 0;
+
+out_disable:
+ printk(KERN_ERR "delkin_cb: no IDE devices found\n");
+ pci_disable_device(dev);
+ return -ENODEV;
}
static void
@@ -102,7 +120,8 @@ delkin_cb_remove (struct pci_dev *dev)
ide_hwif_t *hwif = pci_get_drvdata(dev);
if (hwif)
- ide_unregister(hwif->index);
+ ide_unregister(hwif->index, 0, 0);
+
pci_disable_device(dev);
}
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 06885697ed7..9262a9174b4 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/generic.c Version 0.11 December 30, 2002
- *
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
* Portions (C) Copyright 2002 Red Hat Inc <alan@redhat.com>
*
@@ -24,18 +22,11 @@
#include <linux/types.h>
#include <linux/module.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/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
-#include <asm/io.h>
-
static int ide_generic_all; /* Set to claim all devices */
/*
@@ -104,7 +95,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
{ /* 14 */
.name = "Revolution",
- .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ .host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
+ IDE_HFLAG_TRUST_BIOS_FOR_DMA |
IDE_HFLAG_OFF_BOARD,
.swdma_mask = ATA_SWDMA2,
.mwdma_mask = ATA_MWDMA2,
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index ae6307fae4f..9f01da46b01 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -1,7 +1,6 @@
/*
- * linux/drivers/ide/pci/hpt34x.c Version 0.40 Sept 10, 2002
- *
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ *
* May be copied or modified under the terms of the GNU General Public License
*
*
@@ -27,25 +26,18 @@
#include <linux/module.h>
#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>
-
#define HPT343_DEBUG_DRIVE_INFO 0
static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
u8 hi_speed, lo_speed;
@@ -129,14 +121,19 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
hwif->set_dma_mode = &hpt34x_set_mode;
}
+#define IDE_HFLAGS_HPT34X \
+ (IDE_HFLAG_NO_ATAPI_DMA | \
+ IDE_HFLAG_NO_DSC | \
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ IDE_HFLAG_NO_AUTODMA)
+
static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
{ /* 0 */
.name = "HPT343",
.init_chipset = init_chipset_hpt34x,
.init_hwif = init_hwif_hpt34x,
.extra = 16,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_NO_AUTODMA,
+ .host_flags = IDE_HFLAGS_HPT34X,
.pio_mask = ATA_PIO5,
},
{ /* 1 */
@@ -144,9 +141,7 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
.init_chipset = init_chipset_hpt34x,
.init_hwif = init_hwif_hpt34x,
.extra = 16,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_NO_AUTODMA |
- IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO5,
#ifdef CONFIG_HPT34X_AUTODMA
.swdma_mask = ATA_SWDMA2,
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 5682895d36d..d0f7bb8b8ad 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.21 Oct 23, 2007
- *
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
@@ -88,7 +86,7 @@
* - rename all the register related variables consistently
* - move all the interrupt twiddling code from the speedproc handlers into
* init_hwif_hpt366(), also grouping all the DMA related code together there
- * - merge two HPT37x speedproc handlers, fix the PIO timing register mask and
+ * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
* separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
* when setting an UltraDMA mode
* - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
@@ -123,12 +121,8 @@
#include <linux/module.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>
@@ -136,7 +130,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/irq.h>
/* various tuning parameters */
#define HPT_RESET_STATE_ENGINE
@@ -310,6 +303,8 @@ static u32 twenty_five_base_hpt36x[] = {
/* XFER_PIO_0 */ 0xc0d08585
};
+#if 0
+/* These are the timing tables from the HighPoint open source drivers... */
static u32 thirty_three_base_hpt37x[] = {
/* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */
/* XFER_UDMA_5 */ 0x12446231,
@@ -369,6 +364,73 @@ static u32 sixty_six_base_hpt37x[] = {
/* XFER_PIO_1 */ 0x0d029d26,
/* XFER_PIO_0 */ 0x0d029d5e
};
+#else
+/*
+ * The following are the new timing tables with PIO mode data/taskfile transfer
+ * overclocking fixed...
+ */
+
+/* This table is taken from the HPT370 data manual rev. 1.02 */
+static u32 thirty_three_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x16455031, /* 0x16655031 ?? */
+ /* XFER_UDMA_5 */ 0x16455031,
+ /* XFER_UDMA_4 */ 0x16455031,
+ /* XFER_UDMA_3 */ 0x166d5031,
+ /* XFER_UDMA_2 */ 0x16495031,
+ /* XFER_UDMA_1 */ 0x164d5033,
+ /* XFER_UDMA_0 */ 0x16515097,
+
+ /* XFER_MW_DMA_2 */ 0x26515031,
+ /* XFER_MW_DMA_1 */ 0x26515033,
+ /* XFER_MW_DMA_0 */ 0x26515097,
+
+ /* XFER_PIO_4 */ 0x06515021,
+ /* XFER_PIO_3 */ 0x06515022,
+ /* XFER_PIO_2 */ 0x06515033,
+ /* XFER_PIO_1 */ 0x06915065,
+ /* XFER_PIO_0 */ 0x06d1508a
+};
+
+static u32 fifty_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x1a861842,
+ /* XFER_UDMA_5 */ 0x1a861842,
+ /* XFER_UDMA_4 */ 0x1aae1842,
+ /* XFER_UDMA_3 */ 0x1a8e1842,
+ /* XFER_UDMA_2 */ 0x1a0e1842,
+ /* XFER_UDMA_1 */ 0x1a161854,
+ /* XFER_UDMA_0 */ 0x1a1a18ea,
+
+ /* XFER_MW_DMA_2 */ 0x2a821842,
+ /* XFER_MW_DMA_1 */ 0x2a821854,
+ /* XFER_MW_DMA_0 */ 0x2a8218ea,
+
+ /* XFER_PIO_4 */ 0x0a821842,
+ /* XFER_PIO_3 */ 0x0a821843,
+ /* XFER_PIO_2 */ 0x0a821855,
+ /* XFER_PIO_1 */ 0x0ac218a8,
+ /* XFER_PIO_0 */ 0x0b02190c
+};
+
+static u32 sixty_six_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x1c86fe62,
+ /* XFER_UDMA_5 */ 0x1caefe62, /* 0x1c8afe62 */
+ /* XFER_UDMA_4 */ 0x1c8afe62,
+ /* XFER_UDMA_3 */ 0x1c8efe62,
+ /* XFER_UDMA_2 */ 0x1c92fe62,
+ /* XFER_UDMA_1 */ 0x1c9afe62,
+ /* XFER_UDMA_0 */ 0x1c82fe62,
+
+ /* XFER_MW_DMA_2 */ 0x2c82fe62,
+ /* XFER_MW_DMA_1 */ 0x2c82fe66,
+ /* XFER_MW_DMA_0 */ 0x2c82ff2e,
+
+ /* XFER_PIO_4 */ 0x0c82fe62,
+ /* XFER_PIO_3 */ 0x0c82fe84,
+ /* XFER_PIO_2 */ 0x0c82fea6,
+ /* XFER_PIO_1 */ 0x0d02ff26,
+ /* XFER_PIO_0 */ 0x0d42ff7f
+};
+#endif
#define HPT366_DEBUG_DRIVE_INFO 0
#define HPT371_ALLOW_ATA133_6 1
@@ -389,6 +451,13 @@ enum ata_clock {
NUM_ATA_CLOCKS
};
+struct hpt_timings {
+ u32 pio_mask;
+ u32 dma_mask;
+ u32 ultra_mask;
+ u32 *clock_table[NUM_ATA_CLOCKS];
+};
+
/*
* Hold all the HighPoint chip information in one place.
*/
@@ -399,7 +468,8 @@ struct hpt_info {
u8 udma_mask; /* Allowed UltraDMA modes mask. */
u8 dpll_clk; /* DPLL clock in MHz */
u8 pci_clk; /* PCI clock in MHz */
- u32 **settings; /* Chipset settings table */
+ struct hpt_timings *timings; /* Chipset timing data */
+ u8 clock; /* ATA clock selected */
};
/* Supported HighPoint chips */
@@ -417,20 +487,30 @@ enum {
HPT371N
};
-static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = {
- twenty_five_base_hpt36x,
- thirty_three_base_hpt36x,
- forty_base_hpt36x,
- NULL,
- NULL
+static struct hpt_timings hpt36x_timings = {
+ .pio_mask = 0xc1f8ffff,
+ .dma_mask = 0x303800ff,
+ .ultra_mask = 0x30070000,
+ .clock_table = {
+ [ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
+ [ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
+ [ATA_CLOCK_40MHZ] = forty_base_hpt36x,
+ [ATA_CLOCK_50MHZ] = NULL,
+ [ATA_CLOCK_66MHZ] = NULL
+ }
};
-static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
- NULL,
- thirty_three_base_hpt37x,
- NULL,
- fifty_base_hpt37x,
- sixty_six_base_hpt37x
+static struct hpt_timings hpt37x_timings = {
+ .pio_mask = 0xcfc3ffff,
+ .dma_mask = 0x31c001ff,
+ .ultra_mask = 0x303c0000,
+ .clock_table = {
+ [ATA_CLOCK_25MHZ] = NULL,
+ [ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
+ [ATA_CLOCK_40MHZ] = NULL,
+ [ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
+ [ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
+ }
};
static const struct hpt_info hpt36x __devinitdata = {
@@ -438,7 +518,7 @@ static const struct hpt_info hpt36x __devinitdata = {
.chip_type = HPT36x,
.udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
.dpll_clk = 0, /* no DPLL */
- .settings = hpt36x_settings
+ .timings = &hpt36x_timings
};
static const struct hpt_info hpt370 __devinitdata = {
@@ -446,7 +526,7 @@ static const struct hpt_info hpt370 __devinitdata = {
.chip_type = HPT370,
.udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
.dpll_clk = 48,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt370a __devinitdata = {
@@ -454,7 +534,7 @@ static const struct hpt_info hpt370a __devinitdata = {
.chip_type = HPT370A,
.udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
.dpll_clk = 48,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt374 __devinitdata = {
@@ -462,7 +542,7 @@ static const struct hpt_info hpt374 __devinitdata = {
.chip_type = HPT374,
.udma_mask = ATA_UDMA5,
.dpll_clk = 48,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt372 __devinitdata = {
@@ -470,7 +550,7 @@ static const struct hpt_info hpt372 __devinitdata = {
.chip_type = HPT372,
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 55,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt372a __devinitdata = {
@@ -478,7 +558,7 @@ static const struct hpt_info hpt372a __devinitdata = {
.chip_type = HPT372A,
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt302 __devinitdata = {
@@ -486,7 +566,7 @@ static const struct hpt_info hpt302 __devinitdata = {
.chip_type = HPT302,
.udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt371 __devinitdata = {
@@ -494,7 +574,7 @@ static const struct hpt_info hpt371 __devinitdata = {
.chip_type = HPT371,
.udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt372n __devinitdata = {
@@ -502,7 +582,7 @@ static const struct hpt_info hpt372n __devinitdata = {
.chip_type = HPT372N,
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt302n __devinitdata = {
@@ -510,7 +590,7 @@ static const struct hpt_info hpt302n __devinitdata = {
.chip_type = HPT302N,
.udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static const struct hpt_info hpt371n __devinitdata = {
@@ -518,7 +598,7 @@ static const struct hpt_info hpt371n __devinitdata = {
.chip_type = HPT371N,
.udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
- .settings = hpt37x_settings
+ .timings = &hpt37x_timings
};
static int check_in_drive_list(ide_drive_t *drive, const char **list)
@@ -539,7 +619,8 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list)
static u8 hpt3xx_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct hpt_info *info = pci_get_drvdata(hwif->pci_dev);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct hpt_info *info = pci_get_drvdata(dev);
u8 mask = hwif->ultra_mask;
switch (info->chip_type) {
@@ -578,7 +659,8 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct hpt_info *info = pci_get_drvdata(hwif->pci_dev);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct hpt_info *info = pci_get_drvdata(dev);
switch (info->chip_type) {
case HPT372 :
@@ -606,100 +688,56 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
if (xfer_speeds[i] == speed)
break;
- /*
- * NOTE: info->settings only points to the pointer
- * to the list of the actual register values
- */
- return (*info->settings)[i];
+
+ return info->timings->clock_table[info->clock][i];
}
-static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed)
+static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
struct hpt_info *info = pci_get_drvdata(dev);
- u8 itr_addr = drive->dn ? 0x44 : 0x40;
+ struct hpt_timings *t = info->timings;
+ u8 itr_addr = 0x40 + (drive->dn * 4);
u32 old_itr = 0;
- u32 itr_mask, new_itr;
-
- itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :
- (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff);
-
- new_itr = get_speed_setting(speed, info);
+ u32 new_itr = get_speed_setting(speed, info);
+ u32 itr_mask = speed < XFER_MW_DMA_0 ? t->pio_mask :
+ (speed < XFER_UDMA_0 ? t->dma_mask :
+ t->ultra_mask);
+ pci_read_config_dword(dev, itr_addr, &old_itr);
+ new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
/*
* Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
* to avoid problems handling I/O errors later
*/
- pci_read_config_dword(dev, itr_addr, &old_itr);
- new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
new_itr &= ~0xc0000000;
pci_write_config_dword(dev, itr_addr, new_itr);
}
-static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- struct hpt_info *info = pci_get_drvdata(dev);
- u8 itr_addr = 0x40 + (drive->dn * 4);
- u32 old_itr = 0;
- u32 itr_mask, new_itr;
-
- itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :
- (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff);
-
- new_itr = get_speed_setting(speed, info);
-
- pci_read_config_dword(dev, itr_addr, &old_itr);
- new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
-
- if (speed < XFER_MW_DMA_0)
- new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
- pci_write_config_dword(dev, itr_addr, new_itr);
-}
-
-static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct hpt_info *info = pci_get_drvdata(hwif->pci_dev);
-
- if (info->chip_type >= HPT370)
- hpt37x_set_mode(drive, speed);
- else /* hpt368: hpt_minimum_revision(dev, 2) */
- hpt36x_set_mode(drive, speed);
-}
-
static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
}
-static int hpt3xx_quirkproc(ide_drive_t *drive)
+static void hpt3xx_quirkproc(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
const char **list = quirk_drives;
while (*list)
- if (strstr(id->model, *list++))
- return 1;
- return 0;
-}
-
-static void hpt3xx_intrproc(ide_drive_t *drive)
-{
- if (drive->quirk_list)
- return;
+ if (strstr(id->model, *list++)) {
+ drive->quirk_list = 1;
+ return;
+ }
- /* drives in the quirk_list may not like intr setups/cleanups */
- outb(drive->ctl | 2, IDE_CONTROL_REG);
+ drive->quirk_list = 0;
}
static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct hpt_info *info = pci_get_drvdata(dev);
if (drive->quirk_list) {
@@ -731,7 +769,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
*/
static void hpt366_dma_lost_irq(ide_drive_t *drive)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
pci_read_config_byte(dev, 0x50, &mcr1);
@@ -747,18 +785,20 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive)
static void hpt370_clear_engine(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
- pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37);
+ pci_write_config_byte(dev, hwif->select_data, 0x37);
udelay(10);
}
static void hpt370_irq_timeout(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 bfifo = 0;
u8 dma_cmd;
- pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
+ pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
/* get DMA command mode */
@@ -801,10 +841,11 @@ static void hpt370_dma_timeout(ide_drive_t *drive)
static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 bfifo = 0;
u8 dma_stat;
- pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
+ pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
if (bfifo & 0x1FF) {
// printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
return 0;
@@ -824,7 +865,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
static int hpt374_ide_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 mcr = 0, mcr_addr = hwif->select_data;
u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01;
@@ -845,32 +886,33 @@ static int hpt374_ide_dma_end(ide_drive_t *drive)
static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
{
- u8 scr2 = inb(hwif->dma_master + 0x7b);
+ unsigned long base = hwif->extra_base;
+ u8 scr2 = inb(base + 0x6b);
if ((scr2 & 0x7f) == mode)
return;
/* Tristate the bus */
- outb(0x80, hwif->dma_master + 0x73);
- outb(0x80, hwif->dma_master + 0x77);
+ outb(0x80, base + 0x63);
+ outb(0x80, base + 0x67);
/* Switch clock and reset channels */
- outb(mode, hwif->dma_master + 0x7b);
- outb(0xc0, hwif->dma_master + 0x79);
+ outb(mode, base + 0x6b);
+ outb(0xc0, base + 0x69);
/*
* Reset the state machines.
* NOTE: avoid accidentally enabling the disabled channels.
*/
- outb(inb(hwif->dma_master + 0x70) | 0x32, hwif->dma_master + 0x70);
- outb(inb(hwif->dma_master + 0x74) | 0x32, hwif->dma_master + 0x74);
+ outb(inb(base + 0x60) | 0x32, base + 0x60);
+ outb(inb(base + 0x64) | 0x32, base + 0x64);
/* Complete reset */
- outb(0x00, hwif->dma_master + 0x79);
+ outb(0x00, base + 0x69);
/* Reconnect channels to bus */
- outb(0x00, hwif->dma_master + 0x73);
- outb(0x00, hwif->dma_master + 0x77);
+ outb(0x00, base + 0x63);
+ outb(0x00, base + 0x67);
}
/**
@@ -898,7 +940,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
static int hpt3xx_busproc(ide_drive_t *drive, int state)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 mcr_addr = hwif->select_data + 2;
u8 resetmask = hwif->channel ? 0x80 : 0x40;
u8 bsr2 = 0;
@@ -1141,7 +1183,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
* We also don't like using the DPLL because this causes glitches
* on PRST-/SRST- when the state engine gets reset...
*/
- if (chip_type >= HPT374 || info->settings[clock] == NULL) {
+ if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
u16 f_low, delta = pci_clk < 50 ? 2 : 4;
int adjust;
@@ -1157,7 +1199,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
clock = ATA_CLOCK_50MHZ;
}
- if (info->settings[clock] == NULL) {
+ if (info->timings->clock_table[clock] == NULL) {
printk(KERN_ERR "%s: unknown bus timing!\n", name);
kfree(info);
return -EIO;
@@ -1198,15 +1240,10 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
printk("%s: using %d MHz PCI clock\n", name, pci_clk);
}
- /*
- * Advance the table pointer to a slot which points to the list
- * of the register values settings matching the clock being used.
- */
- info->settings += clock;
-
/* Store the clock frequencies. */
info->dpll_clk = dpll_clk;
info->pci_clk = pci_clk;
+ info->clock = clock;
/* Point to this chip's own instance of the hpt_info structure. */
pci_set_drvdata(dev, info);
@@ -1237,12 +1274,55 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
return dev->irq;
}
+static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct hpt_info *info = pci_get_drvdata(dev);
+ u8 chip_type = info->chip_type;
+ u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02;
+
+ /*
+ * The HPT37x uses the CBLID pins as outputs for MA15/MA16
+ * address lines to access an external EEPROM. To read valid
+ * cable detect state the pins must be enabled as inputs.
+ */
+ if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
+ /*
+ * HPT374 PCI function 1
+ * - set bit 15 of reg 0x52 to enable TCBLID as input
+ * - set bit 15 of reg 0x56 to enable FCBLID as input
+ */
+ u8 mcr_addr = hwif->select_data + 2;
+ u16 mcr;
+
+ pci_read_config_word(dev, mcr_addr, &mcr);
+ pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
+ /* now read cable id register */
+ pci_read_config_byte(dev, 0x5a, &scr1);
+ pci_write_config_word(dev, mcr_addr, mcr);
+ } else if (chip_type >= HPT370) {
+ /*
+ * HPT370/372 and 374 pcifn 0
+ * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
+ */
+ u8 scr2 = 0;
+
+ pci_read_config_byte(dev, 0x5b, &scr2);
+ pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
+ /* now read cable id register */
+ pci_read_config_byte(dev, 0x5a, &scr1);
+ pci_write_config_byte(dev, 0x5b, scr2);
+ } else
+ pci_read_config_byte(dev, 0x5a, &scr1);
+
+ return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct hpt_info *info = pci_get_drvdata(dev);
int serialize = HPT_SERIALIZE_IO;
- u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02;
u8 chip_type = info->chip_type;
u8 new_mcr, old_mcr = 0;
@@ -1251,14 +1331,16 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->set_pio_mode = &hpt3xx_set_pio_mode;
hwif->set_dma_mode = &hpt3xx_set_mode;
+
hwif->quirkproc = &hpt3xx_quirkproc;
- hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
hwif->busproc = &hpt3xx_busproc;
hwif->udma_filter = &hpt3xx_udma_filter;
hwif->mdma_filter = &hpt3xx_mdma_filter;
+ hwif->cable_detect = hpt3xx_cable_detect;
+
/*
* HPT3xxN chips have some complications:
*
@@ -1304,43 +1386,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
if (hwif->dma_base == 0)
return;
- /*
- * The HPT37x uses the CBLID pins as outputs for MA15/MA16
- * address lines to access an external EEPROM. To read valid
- * cable detect state the pins must be enabled as inputs.
- */
- if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
- /*
- * HPT374 PCI function 1
- * - set bit 15 of reg 0x52 to enable TCBLID as input
- * - set bit 15 of reg 0x56 to enable FCBLID as input
- */
- u8 mcr_addr = hwif->select_data + 2;
- u16 mcr;
-
- pci_read_config_word (dev, mcr_addr, &mcr);
- pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
- /* now read cable id register */
- pci_read_config_byte (dev, 0x5a, &scr1);
- pci_write_config_word(dev, mcr_addr, mcr);
- } else if (chip_type >= HPT370) {
- /*
- * HPT370/372 and 374 pcifn 0
- * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
- */
- u8 scr2 = 0;
-
- pci_read_config_byte (dev, 0x5b, &scr2);
- pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
- /* now read cable id register */
- pci_read_config_byte (dev, 0x5a, &scr1);
- pci_write_config_byte(dev, 0x5b, scr2);
- } else
- pci_read_config_byte (dev, 0x5a, &scr1);
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-
if (chip_type >= HPT374) {
hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
hwif->ide_dma_end = &hpt374_ide_dma_end;
@@ -1354,7 +1399,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 masterdma = 0, slavedma = 0;
u8 dma_new = 0, dma_old = 0;
unsigned long flags;
@@ -1374,7 +1419,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
local_irq_restore(flags);
- ide_setup_dma(hwif, dmabase, 8);
+ ide_setup_dma(hwif, dmabase);
}
static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
@@ -1425,6 +1470,11 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
return 0;
}
+#define IDE_HFLAGS_HPT3XX \
+ (IDE_HFLAG_NO_ATAPI_DMA | \
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ IDE_HFLAG_OFF_BOARD)
+
static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
{ /* 0 */
.name = "HPT36x",
@@ -1439,9 +1489,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
*/
.enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAG_SINGLE |
- IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 1 */
@@ -1451,7 +1499,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.init_dma = init_dma_hpt366,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAGS_HPT3XX,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 2 */
@@ -1461,7 +1509,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.init_dma = init_dma_hpt366,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAGS_HPT3XX,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 3 */
@@ -1471,7 +1519,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.init_dma = init_dma_hpt366,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAGS_HPT3XX,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 4 */
@@ -1482,7 +1530,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.udma_mask = ATA_UDMA5,
.extra = 240,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAGS_HPT3XX,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 5 */
@@ -1492,7 +1540,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.init_dma = init_dma_hpt366,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAGS_HPT3XX,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
}
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index 90b52ed37bf..e3427eaab43 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -10,13 +10,10 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
-#include <asm/io.h>
-
/**
* it8213_set_pio_mode - set host controller for PIO mode
* @drive: drive
@@ -28,7 +25,7 @@
static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
int is_slave = drive->dn & 1;
int master_port = 0x40;
int slave_port = 0x44;
@@ -85,7 +82,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 maslave = 0x40;
int a_speed = 3 << (drive->dn * 4);
int u_flag = 1 << drive->dn;
@@ -101,24 +98,11 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_read_config_byte(dev, 0x54, &reg54);
pci_read_config_byte(dev, 0x55, &reg55);
- switch(speed) {
- case XFER_UDMA_6:
- case XFER_UDMA_4:
- case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
- case XFER_UDMA_5:
- case XFER_UDMA_3:
- case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
- case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
- break;
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_SW_DMA_2:
- break;
- default:
- return;
- }
-
if (speed >= XFER_UDMA_0) {
+ u8 udma = speed - XFER_UDMA_0;
+
+ u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
+
if (!(reg48 & u_flag))
pci_write_config_byte(dev, 0x48, reg48 | u_flag);
if (speed >= XFER_UDMA_5) {
@@ -156,6 +140,16 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
}
+static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u8 reg42h = 0;
+
+ pci_read_config_byte(dev, 0x42, &reg42h);
+
+ return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
/**
* init_hwif_it8213 - set up hwif structs
* @hwif: interface to set up
@@ -165,18 +159,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
{
- u8 reg42h = 0;
-
hwif->set_dma_mode = &it8213_set_dma_mode;
hwif->set_pio_mode = &it8213_set_pio_mode;
- if (!hwif->dma_base)
- return;
-
- pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+ hwif->cable_detect = it8213_cable_detect;
}
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 5c997543531..1597f0cc1bf 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -1,7 +1,4 @@
-
/*
- * linux/drivers/ide/pci/it821x.c Version 0.16 Jul 3 2007
- *
* Copyright (C) 2004 Red Hat <alan@redhat.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
@@ -66,13 +63,10 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
-#include <asm/io.h>
-
struct it821x_dev
{
unsigned int smart:1, /* Are we in smart raid mode */
@@ -113,7 +107,8 @@ static int it8212_noraid;
static void it821x_program(ide_drive_t *drive, u16 timing)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int channel = hwif->channel;
u8 conf;
@@ -123,7 +118,8 @@ static void it821x_program(ide_drive_t *drive, u16 timing)
conf = timing >> 8;
else
conf = timing & 0xFF;
- pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
+
+ pci_write_config_byte(dev, 0x54 + 4 * channel, conf);
}
/**
@@ -137,7 +133,8 @@ static void it821x_program(ide_drive_t *drive, u16 timing)
static void it821x_program_udma(ide_drive_t *drive, u16 timing)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int channel = hwif->channel;
int unit = drive->select.b.unit;
@@ -148,11 +145,12 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
conf = timing >> 8;
else
conf = timing & 0xFF;
- if(itdev->timing10 == 0)
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf);
+
+ if (itdev->timing10 == 0)
+ pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf);
else {
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf);
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf);
+ pci_write_config_byte(dev, 0x56 + 4 * channel, conf);
+ pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf);
}
}
@@ -167,6 +165,7 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
static void it821x_clock_strategy(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
u8 unit = drive->select.b.unit;
@@ -205,10 +204,11 @@ static void it821x_clock_strategy(ide_drive_t *drive)
itdev->clock_mode = ATA_50;
sel = 1;
}
- pci_read_config_byte(hwif->pci_dev, 0x50, &v);
+
+ pci_read_config_byte(dev, 0x50, &v);
v &= ~(1 << (1 + hwif->channel));
v |= sel << (1 + hwif->channel);
- pci_write_config_byte(hwif->pci_dev, 0x50, v);
+ pci_write_config_byte(dev, 0x50, v);
/*
* Reprogram the UDMA/PIO of the pair drive for the switch
@@ -282,7 +282,8 @@ static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
int unit = drive->select.b.unit;
int channel = hwif->channel;
@@ -297,12 +298,12 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
itdev->udma[unit] = UDMA_OFF;
/* UDMA bits off - Revision 0x10 do them in pairs */
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(itdev->timing10)
+ pci_read_config_byte(dev, 0x50, &conf);
+ if (itdev->timing10)
conf |= channel ? 0x60: 0x18;
else
conf |= 1 << (3 + 2 * channel + unit);
- pci_write_config_byte(hwif->pci_dev, 0x50, conf);
+ pci_write_config_byte(dev, 0x50, conf);
it821x_clock_strategy(drive);
/* FIXME: do we need to program this ? */
@@ -320,7 +321,8 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int unit = drive->select.b.unit;
int channel = hwif->channel;
@@ -337,12 +339,12 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */
/* UDMA on. Again revision 0x10 must do the pair */
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(itdev->timing10)
+ pci_read_config_byte(dev, 0x50, &conf);
+ if (itdev->timing10)
conf &= channel ? 0x9F: 0xE7;
else
conf &= ~ (1 << (3 + 2 * channel + unit));
- pci_write_config_byte(hwif->pci_dev, 0x50, conf);
+ pci_write_config_byte(dev, 0x50, conf);
it821x_clock_strategy(drive);
it821x_program_udma(drive, itdev->udma[unit]);
@@ -431,33 +433,29 @@ static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
}
/**
- * it821x_fixup - post init callback
- * @hwif: interface
+ * it821x_quirkproc - post init callback
+ * @drive: drive
*
- * This callback is run after the drives have been probed but
+ * This callback is run after the drive has been probed but
* before anything gets attached. It allows drivers to do any
* final tuning that is needed, or fixups to work around bugs.
*/
-static void __devinit it821x_fixups(ide_hwif_t *hwif)
+static void __devinit it821x_quirkproc(ide_drive_t *drive)
{
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int i;
+ struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif);
+ struct hd_driveid *id = drive->id;
+ u16 *idbits = (u16 *)drive->id;
- if(!itdev->smart) {
+ if (!itdev->smart) {
/*
* If we are in pass through mode then not much
* needs to be done, but we do bother to clear the
* IRQ mask as we may well be in PIO (eg rev 0x10)
* for now and we know unmasking is safe on this chipset.
*/
- for (i = 0; i < 2; i++) {
- ide_drive_t *drive = &hwif->drives[i];
- if(drive->present)
- drive->unmask = 1;
- }
- return;
- }
+ drive->unmask = 1;
+ } else {
/*
* Perform fixups on smart mode. We need to "lose" some
* capabilities the firmware lacks but does not filter, and
@@ -465,16 +463,6 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
* in RAID mode.
*/
- for(i = 0; i < 2; i++) {
- ide_drive_t *drive = &hwif->drives[i];
- struct hd_driveid *id;
- u16 *idbits;
-
- if(!drive->present)
- continue;
- id = drive->id;
- idbits = (u16 *)drive->id;
-
/* Check for RAID v native */
if(strstr(id->model, "Integrated Technology Express")) {
/* In raid mode the ident block is slightly buggy
@@ -534,9 +522,12 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
u8 conf;
+ hwif->quirkproc = &it821x_quirkproc;
+
if (idev == NULL) {
printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
return;
@@ -544,7 +535,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
ide_set_hwifdata(hwif, idev);
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
+ pci_read_config_byte(dev, 0x50, &conf);
if (conf & 1) {
idev->smart = 1;
hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
@@ -567,7 +558,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
* this is necessary.
*/
- pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
+ pci_read_config_byte(dev, 0x08, &conf);
if (conf == 0x10) {
idev->timing10 = 1;
hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
@@ -585,14 +576,13 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
} else
hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
+ hwif->cable_detect = ata66_it821x;
+
if (hwif->dma_base == 0)
return;
hwif->ultra_mask = ATA_UDMA6;
hwif->mwdma_mask = ATA_MWDMA2;
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = ata66_it821x(hwif);
}
static void __devinit it8212_disable_raid(struct pci_dev *dev)
@@ -633,7 +623,6 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
.name = name_str, \
.init_chipset = init_chipset_it821x, \
.init_hwif = init_hwif_it821x, \
- .fixup = it821x_fixups, \
.host_flags = IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
}
@@ -653,8 +642,7 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
- return 0;
+ return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
}
static const struct pci_device_id it821x_pci_tbl[] = {
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index bdf64d99770..a56bcb4f22f 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -8,13 +8,10 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
-#include <asm/io.h>
-
typedef enum {
PORT_PATA0 = 0,
PORT_PATA1 = 1,
@@ -30,7 +27,7 @@ typedef enum {
static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
{
- struct pci_dev *pdev = hwif->pci_dev;
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
u32 control;
u32 control5;
@@ -111,11 +108,7 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
hwif->set_pio_mode = &jmicron_set_pio_mode;
hwif->set_dma_mode = &jmicron_set_dma_mode;
- if (hwif->dma_base == 0)
- return;
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = ata66_jmicron(hwif);
+ hwif->cable_detect = ata66_jmicron;
}
static const struct ide_port_info jmicron_chipset __devinitdata = {
@@ -139,8 +132,7 @@ static const struct ide_port_info jmicron_chipset __devinitdata = {
static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &jmicron_chipset);
- return 0;
+ return ide_setup_pci_device(dev, &jmicron_chipset);
}
/* All JMB PATA controllers have and will continue to have the same
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index d4df4642dbb..bf0d3b2931f 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/ns87415.c Version 2.00 Sep. 10, 2002
- *
* Copyright (C) 1997-1998 Mark Lord <mlord@pobox.com>
* Copyright (C) 1998 Eddie C. Dost <ecd@skynet.be>
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
@@ -12,11 +10,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
#include <linux/interrupt.h>
-#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/delay.h>
@@ -71,10 +65,9 @@ static u8 superio_ide_inb (unsigned long port)
static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
{
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
u32 base, dmabase;
- u8 tmp;
- struct pci_dev *pdev = hwif->pci_dev;
- u8 port = hwif->channel;
+ u8 port = hwif->channel, tmp;
base = pci_resource_start(pdev, port * 2) & ~3;
dmabase = pci_resource_start(pdev, 4) & ~3;
@@ -93,10 +86,11 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
{
- if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) {
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+ if (PCI_SLOT(dev->devfn) == 0xE)
/* Built-in - assume it's under superio. */
superio_ide_init_iops(hwif);
- }
}
#endif
@@ -110,8 +104,8 @@ static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
- struct pci_dev *dev = hwif->pci_dev;
unsigned long flags;
local_irq_save(flags);
@@ -189,7 +183,7 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive)
static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned int ctrl, using_inta;
u8 progif;
#ifdef __sparc_v9__
@@ -231,8 +225,8 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
#ifdef __sparc_v9__
/*
- * XXX: Reset the device, if we don't it will not respond
- * to SELECT_DRIVE() properly during first probe_hwif().
+ * XXX: Reset the device, if we don't it will not respond to
+ * SELECT_DRIVE() properly during first ide_probe_port().
*/
timeout = 10000;
outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 8953d9c3926..46e8748f507 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/opti621.c Version 0.9 Sep 24, 2007
- *
* Copyright (C) 1996-1998 Linus Torvalds & authors (see below)
*/
@@ -89,11 +87,6 @@
#include <linux/types.h>
#include <linux/module.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/pci.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
@@ -322,14 +315,18 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
spin_unlock_irqrestore(&opti621_lock, flags);
}
+static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
+{
+ hwif->drives[0].drive_data = PIO_DONT_KNOW;
+ hwif->drives[1].drive_data = PIO_DONT_KNOW;
+}
+
/*
* init_hwif_opti621() is called once for each hwif found at boot.
*/
static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
{
- hwif->drives[0].drive_data = PIO_DONT_KNOW;
- hwif->drives[1].drive_data = PIO_DONT_KNOW;
-
+ hwif->port_init_devs = opti621_port_init_devs;
hwif->set_pio_mode = &opti621_set_pio_mode;
}
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 4234efeba60..1c8cb7797a4 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -19,18 +19,12 @@
#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>
#ifdef CONFIG_PPC_PMAC
#include <asm/prom.h>
@@ -146,9 +140,10 @@ static struct udma_timing {
{ 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */
};
-static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
+static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
/*
@@ -159,48 +154,21 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
* As we set up the PLL to output 133 MHz for UltraDMA/133 capable
* chips, we must override the default register settings...
*/
- if (max_dma_rate(hwif->pci_dev) == 4) {
+ if (max_dma_rate(dev) == 4) {
u8 mode = speed & 0x07;
- switch (speed) {
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- set_indexed_reg(hwif, 0x10 + adj,
- udma_timings[mode].reg10);
- set_indexed_reg(hwif, 0x11 + adj,
- udma_timings[mode].reg11);
- set_indexed_reg(hwif, 0x12 + adj,
- udma_timings[mode].reg12);
- break;
-
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_MW_DMA_0:
- set_indexed_reg(hwif, 0x0e + adj,
- mwdma_timings[mode].reg0e);
- set_indexed_reg(hwif, 0x0f + adj,
- mwdma_timings[mode].reg0f);
- break;
- case XFER_PIO_4:
- case XFER_PIO_3:
- case XFER_PIO_2:
- case XFER_PIO_1:
- case XFER_PIO_0:
- set_indexed_reg(hwif, 0x0c + adj,
- pio_timings[mode].reg0c);
- set_indexed_reg(hwif, 0x0d + adj,
- pio_timings[mode].reg0d);
- set_indexed_reg(hwif, 0x13 + adj,
- pio_timings[mode].reg13);
- break;
- default:
- printk(KERN_ERR "pdc202xx_new: "
- "Unknown speed %d ignored\n", speed);
+ if (speed >= XFER_UDMA_0) {
+ set_indexed_reg(hwif, 0x10 + adj,
+ udma_timings[mode].reg10);
+ set_indexed_reg(hwif, 0x11 + adj,
+ udma_timings[mode].reg11);
+ set_indexed_reg(hwif, 0x12 + adj,
+ udma_timings[mode].reg12);
+ } else {
+ set_indexed_reg(hwif, 0x0e + adj,
+ mwdma_timings[mode].reg0e);
+ set_indexed_reg(hwif, 0x0f + adj,
+ mwdma_timings[mode].reg0f);
}
} else if (speed == XFER_UDMA_2) {
/* Set tHOLD bit to 0 if using UDMA mode 2 */
@@ -212,10 +180,18 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- pdcnew_set_mode(drive, XFER_PIO_0 + pio);
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
+
+ if (max_dma_rate(dev) == 4) {
+ set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
+ set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d);
+ set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13);
+ }
}
-static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
+static u8 __devinit pdcnew_cable_detect(ide_hwif_t *hwif)
{
if (get_indexed_reg(hwif, 0x0b) & 0x04)
return ATA_CBL_PATA40;
@@ -223,14 +199,17 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
return ATA_CBL_PATA80;
}
-static int pdcnew_quirkproc(ide_drive_t *drive)
+static void pdcnew_quirkproc(ide_drive_t *drive)
{
const char **list, *model = drive->id->model;
for (list = pdc_quirk_drives; *list != NULL; list++)
- if (strstr(model, *list) != NULL)
- return 2;
- return 0;
+ if (strstr(model, *list) != NULL) {
+ drive->quirk_list = 2;
+ return;
+ }
+
+ drive->quirk_list = 0;
}
static void pdcnew_reset(ide_drive_t *drive)
@@ -466,24 +445,21 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
{
hwif->set_pio_mode = &pdcnew_set_pio_mode;
- hwif->set_dma_mode = &pdcnew_set_mode;
+ hwif->set_dma_mode = &pdcnew_set_dma_mode;
hwif->quirkproc = &pdcnew_quirkproc;
hwif->resetproc = &pdcnew_reset;
- if (hwif->dma_base == 0)
- return;
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = pdcnew_cable_detect(hwif);
+ hwif->cable_detect = pdcnew_cable_detect;
}
static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
{
struct pci_dev *dev2;
- dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 2,
+ dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1,
PCI_FUNC(dev->devfn)));
+
if (dev2 &&
dev2->vendor == dev->vendor &&
dev2->device == dev->device) {
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index e09742e2ba5..da432979038 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/pdc202xx_old.c Version 0.52 Aug 27, 2007
- *
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2006-2007 MontaVista Software, Inc.
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
@@ -34,18 +32,13 @@
#include <linux/module.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>
#define PDC202XX_DEBUG_DRIVE_INFO 0
@@ -66,7 +59,7 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 drive_pci = 0x60 + (drive->dn << 2);
u8 AP = 0, BP = 0, CP = 0;
@@ -142,11 +135,12 @@ static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
}
-static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
+static u8 __devinit pdc2026x_old_cable_detect(ide_hwif_t *hwif)
{
- u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10);
- pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
+ pci_read_config_word(dev, 0x50, &CIS);
return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
@@ -162,7 +156,7 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
*/
static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
{
- unsigned long clock_reg = hwif->dma_master + 0x11;
+ unsigned long clock_reg = hwif->extra_base + 0x01;
u8 clock = inb(clock_reg);
outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
@@ -170,20 +164,23 @@ static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
{
- unsigned long clock_reg = hwif->dma_master + 0x11;
+ unsigned long clock_reg = hwif->extra_base + 0x01;
u8 clock = inb(clock_reg);
outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
}
-static int pdc202xx_quirkproc (ide_drive_t *drive)
+static void pdc202xx_quirkproc(ide_drive_t *drive)
{
const char **list, *model = drive->id->model;
for (list = pdc_quirk_drives; *list != NULL; list++)
- if (strstr(model, *list) != NULL)
- return 2;
- return 0;
+ if (strstr(model, *list) != NULL) {
+ drive->quirk_list = 2;
+ return;
+ }
+
+ drive->quirk_list = 0;
}
static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
@@ -193,7 +190,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
if (drive->media != ide_disk || drive->addressing == 1) {
struct request *rq = HWGROUP(drive)->rq;
ide_hwif_t *hwif = HWIF(drive);
- unsigned long high_16 = hwif->dma_master;
+ unsigned long high_16 = hwif->extra_base - 16;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u32 word_count = 0;
u8 clock = inb(high_16 + 0x11);
@@ -212,7 +209,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
{
if (drive->media != ide_disk || drive->addressing == 1) {
ide_hwif_t *hwif = HWIF(drive);
- unsigned long high_16 = hwif->dma_master;
+ unsigned long high_16 = hwif->extra_base - 16;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u8 clock = 0;
@@ -228,7 +225,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned long high_16 = hwif->dma_master;
+ unsigned long high_16 = hwif->extra_base - 16;
u8 dma_stat = inb(hwif->dma_status);
u8 sc1d = inb(high_16 + 0x001d);
@@ -271,7 +268,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
static void pdc202xx_reset_host (ide_hwif_t *hwif)
{
- unsigned long high_16 = hwif->dma_master;
+ unsigned long high_16 = hwif->extra_base - 16;
u8 udma_speed_flag = inb(high_16 | 0x001f);
outb(udma_speed_flag | 0x10, high_16 | 0x001f);
@@ -302,24 +299,26 @@ static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
hwif->set_pio_mode = &pdc202xx_set_pio_mode;
hwif->set_dma_mode = &pdc202xx_set_mode;
hwif->quirkproc = &pdc202xx_quirkproc;
- if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
+ if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
hwif->resetproc = &pdc202xx_reset;
+ hwif->cable_detect = pdc2026x_old_cable_detect;
+ }
+
if (hwif->dma_base == 0)
return;
hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
hwif->dma_timeout = &pdc202xx_dma_timeout;
- if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = pdc202xx_old_cable_detect(hwif);
-
+ if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
hwif->dma_start = &pdc202xx_old_ide_dma_start;
hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
}
@@ -331,7 +330,7 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
if (hwif->channel) {
- ide_setup_dma(hwif, dmabase, 8);
+ ide_setup_dma(hwif, dmabase);
return;
}
@@ -355,7 +354,7 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
}
#endif /* CONFIG_PDC202XX_BURST */
- ide_setup_dma(hwif, dmabase, 8);
+ ide_setup_dma(hwif, dmabase);
}
static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
@@ -375,6 +374,11 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
}
}
+#define IDE_HFLAGS_PDC202XX \
+ (IDE_HFLAG_ERROR_STOPS_FIFO | \
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ IDE_HFLAG_OFF_BOARD)
+
#define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
{ \
.name = name_str, \
@@ -382,9 +386,7 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
.init_hwif = init_hwif_pdc202xx, \
.init_dma = init_dma_pdc202xx, \
.extra = 48, \
- .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO | \
- extra_flags | \
- IDE_HFLAG_OFF_BOARD, \
+ .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \
.pio_mask = ATA_PIO4, \
.mwdma_mask = ATA_MWDMA2, \
.udma_mask = udma, \
@@ -397,8 +399,7 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
.init_hwif = init_hwif_pdc202xx,
.init_dma = init_dma_pdc202xx,
.extra = 16,
- .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO |
- IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAGS_PDC202XX,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 9329d4a810e..decef0f4767 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/piix.c Version 0.54 Sep 5, 2007
- *
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
@@ -8,53 +6,8 @@
*
* May be copied or modified under the terms of the GNU General Public License
*
- * PIO mode setting function for Intel chipsets.
- * For use instead of BIOS settings.
- *
- * 40-41
- * 42-43
- *
- * 41
- * 43
- *
- * | PIO 0 | c0 | 80 | 0 |
- * | PIO 2 | SW2 | d0 | 90 | 4 |
- * | PIO 3 | MW1 | e1 | a1 | 9 |
- * | PIO 4 | MW2 | e3 | a3 | b |
- *
- * sitre = word40 & 0x4000; primary
- * sitre = word42 & 0x4000; secondary
- *
- * 44 8421|8421 hdd|hdb
- *
- * 48 8421 hdd|hdc|hdb|hda udma enabled
- *
- * 0001 hda
- * 0010 hdb
- * 0100 hdc
- * 1000 hdd
- *
- * 4a 84|21 hdb|hda
- * 4b 84|21 hdd|hdc
- *
- * ata-33/82371AB
- * ata-33/82371EB
- * ata-33/82801AB ata-66/82801AA
- * 00|00 udma 0 00|00 reserved
- * 01|01 udma 1 01|01 udma 3
- * 10|10 udma 2 10|10 udma 4
- * 11|11 reserved 11|11 reserved
+ * Documentation:
*
- * 54 8421|8421 ata66 drive|ata66 enable
- *
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
- * pci_read_config_byte(HWIF(drive)->pci_dev, 0x48, &reg48);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
- * pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &reg54);
- *
- * Documentation
* Publically available from Intel web site. Errata documentation
* is also publically available. As an aide to anyone hacking on this
* driver the list of errata that are relevant is below.going back to
@@ -94,11 +47,9 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/delay.h>
#include <linux/init.h>
#include <asm/io.h>
@@ -116,7 +67,7 @@ static int no_piix_dma;
static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
int is_slave = drive->dn & 1;
int master_port = hwif->channel ? 0x42 : 0x40;
int slave_port = 0x44;
@@ -185,7 +136,7 @@ static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 maslave = hwif->channel ? 0x42 : 0x40;
int a_speed = 3 << (drive->dn * 4);
int u_flag = 1 << drive->dn;
@@ -203,20 +154,11 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_read_config_byte(dev, 0x54, &reg54);
pci_read_config_byte(dev, 0x55, &reg55);
- switch(speed) {
- case XFER_UDMA_4:
- case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
- case XFER_UDMA_5:
- case XFER_UDMA_3:
- case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
- case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_SW_DMA_2: break;
- default: return;
- }
-
if (speed >= XFER_UDMA_0) {
+ u8 udma = speed - XFER_UDMA_0;
+
+ u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
+
if (!(reg48 & u_flag))
pci_write_config_byte(dev, 0x48, reg48 | u_flag);
if (speed == XFER_UDMA_5) {
@@ -302,9 +244,11 @@ struct ich_laptop {
static const struct ich_laptop ich_laptop[] = {
/* devid, subvendor, subdev */
+ { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */
{ 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
+ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
/* end marker */
{ 0, }
@@ -312,7 +256,7 @@ static const struct ich_laptop ich_laptop[] = {
static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
{
- struct pci_dev *pdev = hwif->pci_dev;
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
const struct ich_laptop *lap = &ich_laptop[0];
u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
@@ -344,14 +288,11 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
hwif->set_pio_mode = &piix_set_pio_mode;
hwif->set_dma_mode = &piix_set_dma_mode;
+ hwif->cable_detect = piix_cable_detect;
+
if (!hwif->dma_base)
return;
- if (hwif->ultra_mask & 0x78) {
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = piix_cable_detect(hwif);
- }
-
if (no_piix_dma)
hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
}
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 6b10ae260fa..51676612f78 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/rz1000.c Version 0.06 January 12, 2003
- *
* Copyright (C) 1995-1998 Linus Torvalds & author (see below)
*/
@@ -18,22 +16,15 @@
#include <linux/types.h>
#include <linux/module.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/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
-#include <asm/io.h>
-
static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 reg;
- struct pci_dev *dev = hwif->pci_dev;
if (!pci_read_config_word (dev, 0x40, &reg) &&
!pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
@@ -42,8 +33,7 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
} else {
if (hwif->mate)
hwif->mate->serialized = hwif->serialized = 1;
- hwif->drives[0].no_unmask = 1;
- hwif->drives[1].no_unmask = 1;
+ hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
printk(KERN_INFO "%s: serialized, disabled unmasking "
"(buggy RZ1000/RZ1001)\n", hwif->name);
}
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 0a7b3202066..561aa47c772 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/sc1200.c Version 0.97 Aug 3 2007
- *
* Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
@@ -16,19 +14,13 @@
#include <linux/module.h>
#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 <linux/pm.h>
+
#include <asm/io.h>
-#include <asm/irq.h>
#define SC1200_REV_A 0x00
#define SC1200_REV_B1 0x01
@@ -87,7 +79,7 @@ static const unsigned int sc1200_pio_timings[4][5] =
static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
{
ide_hwif_t *hwif = drive->hwif;
- struct pci_dev *pdev = hwif->pci_dev;
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
pci_read_config_dword(pdev, basereg + 4, &format);
@@ -130,73 +122,42 @@ out:
static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
int unit = drive->select.b.unit;
unsigned int reg, timings;
unsigned short pci_clock;
unsigned int basereg = hwif->channel ? 0x50 : 0x40;
+ static const u32 udma_timing[3][3] = {
+ { 0x00921250, 0x00911140, 0x00911030 },
+ { 0x00932470, 0x00922260, 0x00922140 },
+ { 0x009436a1, 0x00933481, 0x00923261 },
+ };
+
+ static const u32 mwdma_timing[3][3] = {
+ { 0x00077771, 0x00012121, 0x00002020 },
+ { 0x000bbbb2, 0x00024241, 0x00013131 },
+ { 0x000ffff3, 0x00035352, 0x00015151 },
+ };
+
pci_clock = sc1200_get_pci_clock();
/*
* Note that each DMA mode has several timings associated with it.
* The correct timing depends on the fast PCI clock freq.
*/
- timings = 0;
- switch (mode) {
- case XFER_UDMA_0:
- switch (pci_clock) {
- case PCI_CLK_33: timings = 0x00921250; break;
- case PCI_CLK_48: timings = 0x00932470; break;
- case PCI_CLK_66: timings = 0x009436a1; break;
- }
- break;
- case XFER_UDMA_1:
- switch (pci_clock) {
- case PCI_CLK_33: timings = 0x00911140; break;
- case PCI_CLK_48: timings = 0x00922260; break;
- case PCI_CLK_66: timings = 0x00933481; break;
- }
- break;
- case XFER_UDMA_2:
- switch (pci_clock) {
- case PCI_CLK_33: timings = 0x00911030; break;
- case PCI_CLK_48: timings = 0x00922140; break;
- case PCI_CLK_66: timings = 0x00923261; break;
- }
- break;
- case XFER_MW_DMA_0:
- switch (pci_clock) {
- case PCI_CLK_33: timings = 0x00077771; break;
- case PCI_CLK_48: timings = 0x000bbbb2; break;
- case PCI_CLK_66: timings = 0x000ffff3; break;
- }
- break;
- case XFER_MW_DMA_1:
- switch (pci_clock) {
- case PCI_CLK_33: timings = 0x00012121; break;
- case PCI_CLK_48: timings = 0x00024241; break;
- case PCI_CLK_66: timings = 0x00035352; break;
- }
- break;
- case XFER_MW_DMA_2:
- switch (pci_clock) {
- case PCI_CLK_33: timings = 0x00002020; break;
- case PCI_CLK_48: timings = 0x00013131; break;
- case PCI_CLK_66: timings = 0x00015151; break;
- }
- break;
- default:
- BUG();
- break;
- }
+
+ if (mode >= XFER_UDMA_0)
+ timings = udma_timing[pci_clock][mode - XFER_UDMA_0];
+ else
+ timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
if (unit == 0) { /* are we configuring drive0? */
- pci_read_config_dword(hwif->pci_dev, basereg+4, &reg);
+ pci_read_config_dword(dev, basereg + 4, &reg);
timings |= reg & 0x80000000; /* preserve PIO format bit */
- pci_write_config_dword(hwif->pci_dev, basereg+4, timings);
- } else {
- pci_write_config_dword(hwif->pci_dev, basereg+12, timings);
- }
+ pci_write_config_dword(dev, basereg + 4, timings);
+ } else
+ pci_write_config_dword(dev, basereg + 12, timings);
}
/* Replacement for the standard ide_dma_end action in
@@ -251,9 +212,9 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
if (mode != -1) {
printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
- hwif->dma_off_quietly(drive);
- if (ide_set_dma_mode(drive, mode) == 0)
- hwif->dma_host_on(drive);
+ ide_dma_off_quietly(drive);
+ if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
+ hwif->dma_host_set(drive, 1);
return;
}
@@ -261,66 +222,39 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
#ifdef CONFIG_PM
-static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev)
-{
- int h;
-
- for (h = 0; h < MAX_HWIFS; h++) {
- ide_hwif_t *hwif = &ide_hwifs[h];
- if (prev) {
- if (hwif == prev)
- prev = NULL; // found previous, now look for next match
- } else {
- if (hwif && hwif->pci_dev == dev)
- return hwif; // found next match
- }
- }
- return NULL; // not found
-}
-
-typedef struct sc1200_saved_state_s {
- __u32 regs[4];
-} sc1200_saved_state_t;
-
+struct sc1200_saved_state {
+ u32 regs[8];
+};
static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
{
- ide_hwif_t *hwif = NULL;
-
printk("SC1200: suspend(%u)\n", state.event);
+ /*
+ * we only save state when going from full power to less
+ */
if (state.event == PM_EVENT_ON) {
- // we only save state when going from full power to less
-
- //
- // Loop over all interfaces that are part of this PCI device:
- //
- while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
- sc1200_saved_state_t *ss;
- unsigned int basereg, r;
- //
- // allocate a permanent save area, if not already allocated
- //
- ss = (sc1200_saved_state_t *)hwif->config_data;
- if (ss == NULL) {
- ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
- if (ss == NULL)
- return -ENOMEM;
- hwif->config_data = (unsigned long)ss;
- }
- ss = (sc1200_saved_state_t *)hwif->config_data;
- //
- // Save timing registers: this may be unnecessary if
- // BIOS also does it
- //
- basereg = hwif->channel ? 0x50 : 0x40;
- for (r = 0; r < 4; ++r) {
- pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]);
- }
+ struct sc1200_saved_state *ss;
+ unsigned int r;
+
+ /*
+ * allocate a permanent save area, if not already allocated
+ */
+ ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
+ if (ss == NULL) {
+ ss = kmalloc(sizeof(*ss), GFP_KERNEL);
+ if (ss == NULL)
+ return -ENOMEM;
+ pci_set_drvdata(dev, ss);
}
- }
- /* You don't need to iterate over disks -- sysfs should have done that for you already */
+ /*
+ * save timing registers
+ * (this may be unnecessary if BIOS also does it)
+ */
+ for (r = 0; r < 8; r++)
+ pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]);
+ }
pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
@@ -329,30 +263,25 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
static int sc1200_resume (struct pci_dev *dev)
{
- ide_hwif_t *hwif = NULL;
- int i;
+ struct sc1200_saved_state *ss;
+ unsigned int r;
+ int i;
i = pci_enable_device(dev);
if (i)
return i;
- //
- // loop over all interfaces that are part of this pci device:
- //
- while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
- unsigned int basereg, r;
- sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data;
-
- //
- // Restore timing registers: this may be unnecessary if BIOS also does it
- //
- basereg = hwif->channel ? 0x50 : 0x40;
- if (ss != NULL) {
- for (r = 0; r < 4; ++r) {
- pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]);
- }
- }
+ ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
+
+ /*
+ * restore timing registers
+ * (this may be unnecessary if BIOS also does it)
+ */
+ if (ss) {
+ for (r = 0; r < 8; r++)
+ pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
}
+
return 0;
}
#endif
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index ebb7132b9b8..238e3e181e8 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -254,19 +254,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
offset = 0; /* 100MHz */
}
- switch (speed) {
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- idx = speed - XFER_UDMA_0;
- break;
- default:
- return;
- }
+ idx = speed - XFER_UDMA_0;
jcactsel = JCACTSELtbl[offset][idx];
if (is_slave) {
@@ -606,7 +594,7 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct scc_ports *ports = pci_get_drvdata(dev);
unsigned long dma_base = ports->dma;
@@ -632,7 +620,7 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
- hwif->irq = hwif->pci_dev->irq;
+ hwif->irq = dev->irq;
hwif->dma_base = dma_base;
hwif->config_data = ports->ctl;
hwif->mmio = 1;
@@ -648,13 +636,19 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
static void __devinit init_iops_scc(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
hwif->hwif_data = NULL;
if (pci_get_drvdata(dev) == NULL)
return;
init_mmio_iops_scc(hwif);
}
+static u8 __devinit scc_cable_detect(ide_hwif_t *hwif)
+{
+ return ATA_CBL_PATA80;
+}
+
/**
* init_hwif_scc - set up hwif
* @hwif: interface to set up
@@ -689,8 +683,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
else
hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
- /* we support 80c cable only. */
- hwif->cbl = ATA_CBL_PATA80;
+ hwif->cable_detect = scc_cable_detect;
}
#define DECLARE_SCC_DEV(name_str) \
@@ -738,14 +731,12 @@ static void __devexit scc_remove(struct pci_dev *dev)
unsigned long dma_size = pci_resource_len(dev, 1);
if (hwif->dmatable_cpu) {
- pci_free_consistent(hwif->pci_dev,
- PRD_ENTRIES * PRD_BYTES,
- hwif->dmatable_cpu,
- hwif->dmatable_dma);
+ pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
+ hwif->dmatable_cpu, hwif->dmatable_dma);
hwif->dmatable_cpu = NULL;
}
- ide_unregister(hwif->index);
+ ide_unregister(hwif->index, 0, 0);
hwif->chipset = ide_unknown;
iounmap((void*)ports->dma);
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index a7280311357..c11880b0709 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/serverworks.c Version 0.22 Jun 27 2007
- *
* Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -33,12 +31,10 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
-#include <linux/delay.h>
#include <asm/io.h>
@@ -67,7 +63,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
static u8 svwks_udma_filter(ide_drive_t *drive)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u8 mask = 0;
if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
@@ -130,7 +126,7 @@ static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio)
static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
- struct pci_dev *dev = drive->hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
@@ -153,7 +149,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
static const u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 };
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 unit = (drive->select.b.unit & 0x01);
u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0;
@@ -164,25 +160,12 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
ultra_timing &= ~(0x0F << (4*unit));
ultra_enable &= ~(0x01 << drive->dn);
- switch(speed) {
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_MW_DMA_0:
- dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
- break;
-
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- dma_timing |= dma_modes[2];
- ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
- ultra_enable |= (0x01 << drive->dn);
- default:
- break;
- }
+ if (speed >= XFER_UDMA_0) {
+ dma_timing |= dma_modes[2];
+ ultra_timing |= (udma_modes[speed - XFER_UDMA_0] << (4 * unit));
+ ultra_enable |= (0x01 << drive->dn);
+ } else if (speed >= XFER_MW_DMA_0)
+ dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing);
pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing);
@@ -300,7 +283,8 @@ static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
*/
static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
@@ -318,7 +302,8 @@ static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
*/
static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
@@ -329,7 +314,7 @@ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
/* Server Works */
if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS)
@@ -353,25 +338,27 @@ static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
hwif->set_pio_mode = &svwks_set_pio_mode;
hwif->set_dma_mode = &svwks_set_dma_mode;
hwif->udma_filter = &svwks_udma_filter;
- if (!hwif->dma_base)
- return;
-
- if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = ata66_svwks(hwif);
- }
+ if (dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
+ hwif->cable_detect = ata66_svwks;
}
+#define IDE_HFLAGS_SVWKS \
+ (IDE_HFLAG_LEGACY_IRQS | \
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ IDE_HFLAG_BOOTABLE)
+
static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
{ /* 0 */
.name = "SvrWks OSB4",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
+ .host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* UDMA is problematic on OSB4 */
@@ -379,7 +366,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = "SvrWks CSB5",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
+ .host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -387,7 +374,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = "SvrWks CSB6",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
+ .host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -395,8 +382,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = "SvrWks CSB6",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
- IDE_HFLAG_BOOTABLE,
+ .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -404,8 +390,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = "SvrWks HT1000",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
- IDE_HFLAG_BOOTABLE,
+ .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -428,7 +413,9 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
d = serverworks_chipsets[idx];
- if (idx == 2 || idx == 3) {
+ if (idx == 1)
+ d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+ else if (idx == 2 || idx == 3) {
if ((PCI_FUNC(dev->devfn) & 1) == 0) {
if (pci_resource_start(dev, 0) != 0x01f1)
d.host_flags &= ~IDE_HFLAG_BOOTABLE;
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index de820aa58cd..054626497be 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -25,8 +25,6 @@
#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/scatterlist.h>
@@ -159,6 +157,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
}
if (intr_reg & 0x02) {
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
/* Error when transferring DMA data on PCI bus */
u32 pci_err_addr_low, pci_err_addr_high,
pci_stat_cmd_reg;
@@ -167,7 +166,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
pci_err_addr_high =
readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
- pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
+ pci_read_config_dword(dev, PCI_COMMAND,
&pci_stat_cmd_reg);
printk(KERN_ERR
"%s(%s) : PCI Bus Error when doing DMA:"
@@ -178,8 +177,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
__FUNCTION__, drive->name,
pci_err_addr_high, pci_err_addr_low);
/* Clear the PCI Error indicator */
- pci_write_config_dword(hwif->pci_dev, PCI_COMMAND,
- 0x00000146);
+ pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
}
/* Clear the Interrupt, Error bits on the IOC4 */
@@ -277,21 +275,6 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
return dma_stat;
}
-static int
-sgiioc4_ide_dma_on(ide_drive_t * drive)
-{
- drive->using_dma = 1;
-
- return 0;
-}
-
-static void sgiioc4_dma_off_quietly(ide_drive_t *drive)
-{
- drive->using_dma = 0;
-
- drive->hwif->dma_host_off(drive);
-}
-
static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
}
@@ -303,13 +286,10 @@ sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
return sgiioc4_checkirq(HWIF(drive));
}
-static void sgiioc4_dma_host_on(ide_drive_t * drive)
+static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
{
-}
-
-static void sgiioc4_dma_host_off(ide_drive_t * drive)
-{
- sgiioc4_clearirq(drive);
+ if (!on)
+ sgiioc4_clearirq(drive);
}
static void
@@ -352,6 +332,7 @@ sgiioc4_INB(unsigned long port)
static int __devinit
ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
void __iomem *virt_dma_base;
int num_ports = sizeof (ioc4_dma_regs_t);
void *pad;
@@ -377,7 +358,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
}
hwif->dma_base = (unsigned long) virt_dma_base;
- hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
+ hwif->dmatable_cpu = pci_alloc_consistent(dev,
IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
&hwif->dmatable_dma);
@@ -386,7 +367,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
hwif->sg_max_nents = IOC4_PRD_ENTRIES;
- pad = pci_alloc_consistent(hwif->pci_dev, IOC4_IDE_CACHELINE_SIZE,
+ pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
(dma_addr_t *) &(hwif->dma_status));
if (pad) {
@@ -394,8 +375,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
return 0;
}
- pci_free_consistent(hwif->pci_dev,
- IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
+ pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
hwif->dmatable_cpu, hwif->dmatable_dma);
printk(KERN_INFO
"%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
@@ -535,8 +515,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
}
use_pio_instead:
- pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents,
- hwif->sg_dma_direction);
+ ide_destroy_dmatable(drive);
return 0; /* revert to PIO for this request */
}
@@ -574,7 +553,6 @@ static void __devinit
ide_init_sgiioc4(ide_hwif_t * hwif)
{
hwif->mmio = 1;
- hwif->pio_mask = 0x00;
hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */
hwif->set_dma_mode = &sgiioc4_set_dma_mode;
hwif->selectproc = NULL;/* Use the default routine to select drive */
@@ -582,7 +560,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->pre_reset = NULL; /* No HBA specific pre_set needed */
hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
clear interrupts */
- hwif->intrproc = NULL; /* Enable or Disable interrupt from drive */
hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */
hwif->quirkproc = NULL;
hwif->busproc = NULL;
@@ -592,20 +569,22 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
if (hwif->dma_base == 0)
return;
- hwif->mwdma_mask = ATA_MWDMA2_ONLY;
-
+ hwif->dma_host_set = &sgiioc4_dma_host_set;
hwif->dma_setup = &sgiioc4_ide_dma_setup;
hwif->dma_start = &sgiioc4_ide_dma_start;
hwif->ide_dma_end = &sgiioc4_ide_dma_end;
- hwif->ide_dma_on = &sgiioc4_ide_dma_on;
- hwif->dma_off_quietly = &sgiioc4_dma_off_quietly;
hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
- hwif->dma_host_on = &sgiioc4_dma_host_on;
- hwif->dma_host_off = &sgiioc4_dma_host_off;
hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
hwif->dma_timeout = &ide_dma_timeout;
}
+static const struct ide_port_info sgiioc4_port_info __devinitdata = {
+ .chipset = ide_pci,
+ .host_flags = IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+ IDE_HFLAG_NO_AUTOTUNE,
+ .mwdma_mask = ATA_MWDMA2_ONLY,
+};
+
static int __devinit
sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
{
@@ -615,6 +594,8 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
ide_hwif_t *hwif;
int h;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw;
+ struct ide_port_info d = sgiioc4_port_info;
/*
* Find an empty HWIF; if none available, return -ENOMEM.
@@ -654,21 +635,15 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
return -ENOMEM;
}
- if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
- hw_regs_t hw;
+ /* Initialize the IO registers */
+ memset(&hw, 0, sizeof(hw));
+ sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
+ hw.irq = dev->irq;
+ hw.chipset = ide_pci;
+ hw.dev = &dev->dev;
+ ide_init_port_hw(hwif, &hw);
- /* Initialize the IO registers */
- memset(&hw, 0, sizeof(hw));
- sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
- memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
- }
-
- hwif->irq = dev->irq;
- hwif->chipset = ide_pci;
- hwif->pci_dev = dev;
- hwif->channel = 0; /* Single Channel chip */
- hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
+ hwif->dev = &dev->dev;
/* The IOC4 uses MMIO rather than Port IO. */
default_hwif_mmiops(hwif);
@@ -676,15 +651,17 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
/* Initializing chipset IRQ Registers */
writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
- if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base))
+ if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) {
printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
hwif->name, DRV_NAME);
+ d.mwdma_mask = 0;
+ }
ide_init_sgiioc4(hwif);
idx[0] = hwif->index;
- if (ide_device_add(idx))
+ if (ide_device_add(idx, &d))
return -EIO;
return 0;
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 6d99441c605..ef5b39fa042 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/siimage.c Version 1.18 Oct 18 2007
- *
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat <alan@redhat.com>
* Copyright (C) 2007 MontaVista Software, Inc.
@@ -41,7 +39,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -79,7 +76,7 @@ static int pdev_is_sata(struct pci_dev *pdev)
static inline int is_sata(ide_hwif_t *hwif)
{
- return pdev_is_sata(hwif->pci_dev);
+ return pdev_is_sata(to_pci_dev(hwif->dev));
}
/**
@@ -140,13 +137,14 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
static u8 sil_pata_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long base = (unsigned long) hwif->hwif_data;
u8 mask = 0, scsc = 0;
if (hwif->mmio)
scsc = hwif->INB(base + 0x4A);
else
- pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
+ pci_read_config_byte(dev, 0x8A, &scsc);
if ((scsc & 0x30) == 0x10) /* 133 */
mask = ATA_UDMA6;
@@ -219,19 +217,21 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
mode |= (unit ? 0x10 : 0x01);
hwif->OUTB(mode, base + addr_mask);
} else {
- pci_write_config_word(hwif->pci_dev, addr, speedp);
- pci_write_config_word(hwif->pci_dev, tfaddr, speedt);
- pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+ pci_write_config_word(dev, addr, speedp);
+ pci_write_config_word(dev, tfaddr, speedt);
+ pci_read_config_word(dev, tfaddr - 2, &speedp);
speedp &= ~0x200;
/* Set IORDY for mode 3 or 4 */
if (pio > 2)
speedp |= 0x200;
- pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp);
+ pci_write_config_word(dev, tfaddr - 2, speedp);
- pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
+ pci_read_config_byte(dev, addr_mask, &mode);
mode &= ~(unit ? 0x30 : 0x03);
mode |= (unit ? 0x10 : 0x01);
- pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
+ pci_write_config_byte(dev, addr_mask, mode);
}
}
@@ -250,6 +250,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
u16 dma[] = { 0x2208, 0x10C2, 0x10C1 };
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 ultra = 0, multi = 0;
u8 mode = 0, unit = drive->select.b.unit;
unsigned long base = (unsigned long)hwif->hwif_data;
@@ -266,10 +267,10 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
multi = hwif->INW(ma);
ultra = hwif->INW(ua);
} else {
- pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
- pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
- pci_read_config_word(hwif->pci_dev, ma, &multi);
- pci_read_config_word(hwif->pci_dev, ua, &ultra);
+ pci_read_config_byte(dev, 0x8A, &scsc);
+ pci_read_config_byte(dev, addr_mask, &mode);
+ pci_read_config_word(dev, ma, &multi);
+ pci_read_config_word(dev, ua, &ultra);
}
mode &= ~((unit) ? 0x30 : 0x03);
@@ -278,27 +279,14 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
scsc = is_sata(hwif) ? 1 : scsc;
- switch(speed) {
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_MW_DMA_0:
- multi = dma[speed - XFER_MW_DMA_0];
- mode |= ((unit) ? 0x20 : 0x02);
- break;
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- multi = dma[2];
- ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) :
- (ultra5[speed - XFER_UDMA_0]));
- mode |= ((unit) ? 0x30 : 0x03);
- break;
- default:
- return;
+ if (speed >= XFER_UDMA_0) {
+ multi = dma[2];
+ ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] :
+ ultra5[speed - XFER_UDMA_0]);
+ mode |= (unit ? 0x30 : 0x03);
+ } else {
+ multi = dma[speed - XFER_MW_DMA_0];
+ mode |= (unit ? 0x20 : 0x02);
}
if (hwif->mmio) {
@@ -306,9 +294,9 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
hwif->OUTW(multi, ma);
hwif->OUTW(ultra, ua);
} else {
- pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
- pci_write_config_word(hwif->pci_dev, ma, multi);
- pci_write_config_word(hwif->pci_dev, ua, ultra);
+ pci_write_config_byte(dev, addr_mask, mode);
+ pci_write_config_word(dev, ma, multi);
+ pci_write_config_word(dev, ua, ultra);
}
}
@@ -316,6 +304,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 dma_altstat = 0;
unsigned long addr = siimage_selreg(hwif, 1);
@@ -324,7 +313,7 @@ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
return 1;
/* return 1 if Device INTR asserted */
- pci_read_config_byte(hwif->pci_dev, addr, &dma_altstat);
+ pci_read_config_byte(dev, addr, &dma_altstat);
if (dma_altstat & 8)
return 0; //return 1;
return 0;
@@ -342,15 +331,18 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long addr = siimage_selreg(hwif, 0x1);
+ void __iomem *sata_error_addr
+ = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
- if (SATA_ERROR_REG) {
+ if (sata_error_addr) {
unsigned long base = (unsigned long)hwif->hwif_data;
-
u32 ext_stat = readl((void __iomem *)(base + 0x10));
u8 watchdog = 0;
+
if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
- u32 sata_error = readl((void __iomem *)SATA_ERROR_REG);
- writel(sata_error, (void __iomem *)SATA_ERROR_REG);
+ u32 sata_error = readl(sata_error_addr);
+
+ writel(sata_error, sata_error_addr);
watchdog = (sata_error & 0x00680000) ? 1 : 0;
printk(KERN_WARNING "%s: sata_error = 0x%08x, "
"watchdog = %d, %s\n",
@@ -390,13 +382,14 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
static int sil_sata_busproc(ide_drive_t * drive, int state)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u32 stat_config = 0;
unsigned long addr = siimage_selreg(hwif, 0);
if (hwif->mmio)
stat_config = readl((void __iomem *)addr);
else
- pci_read_config_dword(hwif->pci_dev, addr, &stat_config);
+ pci_read_config_dword(dev, addr, &stat_config);
switch (state) {
case BUSSTATE_ON:
@@ -428,13 +421,17 @@ static int sil_sata_busproc(ide_drive_t * drive, int state)
static int sil_sata_reset_poll(ide_drive_t *drive)
{
- if (SATA_STATUS_REG) {
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ void __iomem *sata_status_addr
+ = (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET];
+
+ if (sata_status_addr) {
+ /* SATA Status is available only when in MMIO mode */
+ u32 sata_stat = readl(sata_status_addr);
- /* SATA_STATUS_REG is valid only when in MMIO mode */
- if ((readl((void __iomem *)SATA_STATUS_REG) & 0x03) != 0x03) {
+ if ((sata_stat & 0x03) != 0x03) {
printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
- hwif->name, readl((void __iomem *)SATA_STATUS_REG));
+ hwif->name, sata_stat);
HWGROUP(drive)->polling = 0;
return ide_started;
}
@@ -460,48 +457,6 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
}
/**
- * siimage_reset - reset a device on an siimage controller
- * @drive: drive to reset
- *
- * Perform a controller level reset fo the device. For
- * SATA we must also check the PHY.
- */
-
-static void siimage_reset (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 reset = 0;
- unsigned long addr = siimage_selreg(hwif, 0);
-
- if (hwif->mmio) {
- reset = hwif->INB(addr);
- hwif->OUTB((reset|0x03), addr);
- /* FIXME:posting */
- udelay(25);
- hwif->OUTB(reset, addr);
- (void) hwif->INB(addr);
- } else {
- pci_read_config_byte(hwif->pci_dev, addr, &reset);
- pci_write_config_byte(hwif->pci_dev, addr, reset|0x03);
- udelay(25);
- pci_write_config_byte(hwif->pci_dev, addr, reset);
- pci_read_config_byte(hwif->pci_dev, addr, &reset);
- }
-
- if (SATA_STATUS_REG) {
- /* SATA_STATUS_REG is valid only when in MMIO mode */
- u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG);
- printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n",
- hwif->name, sata_stat, __FUNCTION__);
- if (!(sata_stat)) {
- printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
- hwif->name, sata_stat);
- drive->failures++;
- }
- }
-}
-
-/**
* proc_reports_siimage - add siimage controller to proc
* @dev: PCI device
* @clocking: SCSC value
@@ -698,7 +653,7 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const ch
static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
void *addr = pci_get_drvdata(dev);
u8 ch = hwif->channel;
hw_regs_t hw;
@@ -768,9 +723,6 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
const char *s = &drive->id->model[0];
unsigned len;
- if (!drive->present)
- return 0;
-
len = strnlen(s, sizeof(drive->id->model));
if ((len > 4) && (!memcmp(s, "ST", 2))) {
@@ -785,18 +737,20 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
}
/**
- * siimage_fixup - post probe fixups
- * @hwif: interface to fix up
+ * sil_quirkproc - post probe fixups
+ * @drive: drive
*
* Called after drive probe we use this to decide whether the
* Seagate fixup must be applied. This used to be in init_iops but
* that can occur before we know what drives are present.
*/
-static void __devinit siimage_fixup(ide_hwif_t *hwif)
+static void __devinit sil_quirkproc(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
+
/* Try and raise the rqsize */
- if (!is_sata(hwif) || !is_dev_seagate_sata(&hwif->drives[0]))
+ if (!is_sata(hwif) || !is_dev_seagate_sata(drive))
hwif->rqsize = 128;
}
@@ -812,12 +766,14 @@ static void __devinit siimage_fixup(ide_hwif_t *hwif)
static void __devinit init_iops_siimage(ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
hwif->hwif_data = NULL;
/* Pessimal until we finish probing */
hwif->rqsize = 15;
- if (pci_get_drvdata(hwif->pci_dev) == NULL)
+ if (pci_get_drvdata(dev) == NULL)
return;
init_mmio_iops_siimage(hwif);
@@ -833,11 +789,12 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long addr = siimage_selreg(hwif, 0);
u8 ata66 = 0;
- if (pci_get_drvdata(hwif->pci_dev) == NULL)
- pci_read_config_byte(hwif->pci_dev, addr, &ata66);
+ if (pci_get_drvdata(dev) == NULL)
+ pci_read_config_byte(dev, addr, &ata66);
else
ata66 = hwif->INB(addr);
@@ -857,9 +814,9 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
{
u8 sata = is_sata(hwif);
- hwif->resetproc = &siimage_reset;
hwif->set_pio_mode = &sil_set_pio_mode;
hwif->set_dma_mode = &sil_set_dma_mode;
+ hwif->quirkproc = &sil_quirkproc;
if (sata) {
static int first = 1;
@@ -876,15 +833,14 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
} else
hwif->udma_filter = &sil_pata_udma_filter;
+ hwif->cable_detect = ata66_siimage;
+
if (hwif->dma_base == 0)
return;
if (sata)
hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = ata66_siimage(hwif);
-
if (hwif->mmio) {
hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
} else {
@@ -898,7 +854,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
.init_chipset = init_chipset_siimage, \
.init_iops = init_iops_siimage, \
.init_hwif = init_hwif_siimage, \
- .fixup = siimage_fixup, \
.host_flags = IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
.mwdma_mask = ATA_MWDMA2, \
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 6b7bb53acef..512bb4c1fd5 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/sis5513.c Version 0.31 Aug 9, 2007
- *
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
* Copyright (C) 2003 Vojtech Pavlik <vojtech@suse.cz>
@@ -49,20 +47,11 @@
#include <linux/types.h>
#include <linux/module.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/irq.h>
-
#include "ide-timing.h"
/* registers layout and init values are chipset family dependant */
@@ -197,7 +186,7 @@ static char* chipset_capability[] = {
static u8 sis_ata133_get_base(ide_drive_t *drive)
{
- struct pci_dev *dev = drive->hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u32 reg54 = 0;
pci_read_config_dword(dev, 0x54, &reg54);
@@ -207,7 +196,7 @@ static u8 sis_ata133_get_base(ide_drive_t *drive)
static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
{
- struct pci_dev *dev = drive->hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u16 t1 = 0;
u8 drive_pci = 0x40 + drive->dn * 2;
@@ -230,7 +219,7 @@ static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
{
- struct pci_dev *dev = drive->hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u8 t1, drive_pci = 0x40 + drive->dn * 2;
/* timing bits: 7:4 active 3:0 recovery */
@@ -253,7 +242,7 @@ static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
{
- struct pci_dev *dev = drive->hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u32 t1 = 0;
u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
@@ -286,7 +275,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode)
static void config_drive_art_rwp (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 reg4bh = 0;
u8 rw_prefetch = 0;
@@ -305,65 +294,61 @@ static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
sis_program_timings(drive, XFER_PIO_0 + pio);
}
+static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
+{
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ u32 regdw = 0;
+ u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
+
+ pci_read_config_dword(dev, drive_pci, &regdw);
+
+ regdw |= 0x04;
+ regdw &= 0xfffff00f;
+ /* check if ATA133 enable */
+ clk = (regdw & 0x08) ? ATA_133 : ATA_100;
+ idx = mode - XFER_UDMA_0;
+ regdw |= cycle_time_value[clk][idx] << 4;
+ regdw |= cvs_time_value[clk][idx] << 8;
+
+ pci_write_config_dword(dev, drive_pci, regdw);
+}
+
+static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
+{
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
+
+ pci_read_config_byte(dev, drive_pci + 1, &reg);
+
+ /* force the UDMA bit on if we want to use UDMA */
+ reg |= 0x80;
+ /* clean reg cycle time bits */
+ reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
+ /* set reg cycle time bits */
+ reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
+
+ pci_write_config_byte(dev, drive_pci + 1, reg);
+}
+
+static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
+{
+ if (chipset_family >= ATA_133) /* ATA_133 */
+ sis_ata133_program_udma_timings(drive, mode);
+ else /* ATA_33/66/100a/100/133a */
+ sis_ata33_program_udma_timings(drive, mode);
+}
+
static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
-
- /* Config chip for mode */
- switch(speed) {
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- if (chipset_family >= ATA_133) {
- u32 regdw = 0;
- u8 drive_pci = sis_ata133_get_base(drive);
-
- pci_read_config_dword(dev, drive_pci, &regdw);
- regdw |= 0x04;
- regdw &= 0xfffff00f;
- /* check if ATA133 enable */
- if (regdw & 0x08) {
- regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4;
- regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8;
- } else {
- regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4;
- regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8;
- }
- pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
- } else {
- u8 drive_pci = 0x40 + drive->dn * 2, reg = 0;
-
- pci_read_config_byte(dev, drive_pci+1, &reg);
- /* Force the UDMA bit on if we want to use UDMA */
- reg |= 0x80;
- /* clean reg cycle time bits */
- reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
- << cycle_time_offset[chipset_family]);
- /* set reg cycle time bits */
- reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0]
- << cycle_time_offset[chipset_family];
- pci_write_config_byte(dev, drive_pci+1, reg);
- }
- break;
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_MW_DMA_0:
- sis_program_timings(drive, speed);
- break;
- default:
- BUG();
- break;
- }
+ if (speed >= XFER_UDMA_0)
+ sis_program_udma_timings(drive, speed);
+ else
+ sis_program_timings(drive, speed);
}
static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
{
- struct pci_dev *dev = drive->hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u32 regdw = 0;
u8 drive_pci = sis_ata133_get_base(drive);
@@ -527,13 +512,14 @@ static const struct sis_laptop sis_laptop[] = {
/* devid, subvendor, subdev */
{ 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */
{ 0x5513, 0x1734, 0x105f }, /* FSC Amilo A1630 */
+ { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */
/* end marker */
{ 0, }
};
static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
{
- struct pci_dev *pdev = hwif->pci_dev;
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
const struct sis_laptop *lap = &sis_laptop[0];
u8 ata66 = 0;
@@ -548,12 +534,12 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
if (chipset_family >= ATA_133) {
u16 regw = 0;
u16 reg_addr = hwif->channel ? 0x52: 0x50;
- pci_read_config_word(hwif->pci_dev, reg_addr, &regw);
+ pci_read_config_word(pdev, reg_addr, &regw);
ata66 = (regw & 0x8000) ? 0 : 1;
} else if (chipset_family >= ATA_66) {
u8 reg48h = 0;
u8 mask = hwif->channel ? 0x20 : 0x10;
- pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
+ pci_read_config_byte(pdev, 0x48, &reg48h);
ata66 = (reg48h & mask) ? 0 : 1;
}
@@ -570,13 +556,12 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
if (chipset_family >= ATA_133)
hwif->udma_filter = sis5513_ata133_udma_filter;
+ hwif->cable_detect = ata66_sis5513;
+
if (hwif->dma_base == 0)
return;
hwif->ultra_mask = udma_rates[chipset_family];
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = ata66_sis5513(hwif);
}
static const struct ide_port_info sis5513_chipset __devinitdata = {
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 147d783f752..ee261ae15b6 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/sl82c105.c
- *
* SL82C105/Winbond 553 IDE driver
*
* Maintainer unknown.
@@ -13,22 +11,17 @@
* -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org
*
* Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include <asm/dma.h>
#undef DEBUG
@@ -77,7 +70,7 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
*/
static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
int reg = 0x44 + drive->dn * 4;
u16 drv_ctrl;
@@ -90,14 +83,8 @@ static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->drive_data &= 0xffff0000;
drive->drive_data |= drv_ctrl;
- if (!drive->using_dma) {
- /*
- * If we are actually using MW DMA, then we can not
- * reprogram the interface drive control register.
- */
- pci_write_config_word(dev, reg, drv_ctrl);
- pci_read_config_word (dev, reg, &drv_ctrl);
- }
+ pci_write_config_word(dev, reg, drv_ctrl);
+ pci_read_config_word (dev, reg, &drv_ctrl);
printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name,
ide_xfer_verbose(pio + XFER_PIO_0),
@@ -115,33 +102,14 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
drive->name, ide_xfer_verbose(speed)));
- switch (speed) {
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_MW_DMA_0:
- drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
+ drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
- /*
- * Store the DMA timings so that we can actually program
- * them when DMA will be turned on...
- */
- drive->drive_data &= 0x0000ffff;
- drive->drive_data |= (unsigned long)drv_ctrl << 16;
-
- /*
- * If we are already using DMA, we just reprogram
- * the drive control register.
- */
- if (drive->using_dma) {
- struct pci_dev *dev = HWIF(drive)->pci_dev;
- int reg = 0x44 + drive->dn * 4;
-
- pci_write_config_word(dev, reg, drv_ctrl);
- }
- break;
- default:
- return;
- }
+ /*
+ * Store the DMA timings so that we can actually program
+ * them when DMA will be turned on...
+ */
+ drive->drive_data &= 0x0000ffff;
+ drive->drive_data |= (unsigned long)drv_ctrl << 16;
}
/*
@@ -171,7 +139,7 @@ static inline void sl82c105_reset_host(struct pci_dev *dev)
static void sl82c105_dma_lost_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
u8 dma_cmd;
@@ -208,7 +176,12 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive)
static void sl82c105_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ int reg = 0x44 + drive->dn * 4;
+
+ DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
+
+ pci_write_config_word(dev, reg, drive->drive_data >> 16);
sl82c105_reset_host(dev);
ide_dma_start(drive);
@@ -216,80 +189,43 @@ static void sl82c105_dma_start(ide_drive_t *drive)
static void sl82c105_dma_timeout(ide_drive_t *drive)
{
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+
DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
- sl82c105_reset_host(HWIF(drive)->pci_dev);
+ sl82c105_reset_host(dev);
ide_dma_timeout(drive);
}
-static int sl82c105_ide_dma_on(ide_drive_t *drive)
+static int sl82c105_dma_end(ide_drive_t *drive)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
- int rc, reg = 0x44 + drive->dn * 4;
-
- DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name));
-
- rc = __ide_dma_on(drive);
- if (rc == 0) {
- pci_write_config_word(dev, reg, drive->drive_data >> 16);
-
- printk(KERN_INFO "%s: DMA enabled\n", drive->name);
- }
- return rc;
-}
-
-static void sl82c105_dma_off_quietly(ide_drive_t *drive)
-{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
int reg = 0x44 + drive->dn * 4;
+ int ret;
- DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name));
+ DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
- pci_write_config_word(dev, reg, drive->drive_data);
+ ret = __ide_dma_end(drive);
- ide_dma_off_quietly(drive);
-}
+ pci_write_config_word(dev, reg, drive->drive_data);
-/*
- * Ok, that is nasty, but we must make sure the DMA timings
- * won't be used for a PIO access. The solution here is
- * to make sure the 16 bits mode is diabled on the channel
- * when DMA is enabled, thus causing the chip to use PIO0
- * timings for those operations.
- */
-static void sl82c105_selectproc(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- u32 val, old, mask;
-
- //DBG(("sl82c105_selectproc(drive:%s)\n", drive->name));
-
- mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16;
- old = val = (u32)pci_get_drvdata(dev);
- if (drive->using_dma)
- val &= ~mask;
- else
- val |= mask;
- if (old != val) {
- pci_write_config_dword(dev, 0x40, val);
- pci_set_drvdata(dev, (void *)val);
- }
+ return ret;
}
/*
* ATA reset will clear the 16 bits mode in the control
- * register, we need to update our cache
+ * register, we need to reprogram it
*/
static void sl82c105_resetproc(ide_drive_t *drive)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
+ struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
u32 val;
DBG(("sl82c105_resetproc(drive:%s)\n", drive->name));
pci_read_config_dword(dev, 0x40, &val);
- pci_set_drvdata(dev, (void *)val);
+ val |= (CTRL_P1F16 | CTRL_P0F16);
+ pci_write_config_dword(dev, 0x40, val);
}
/*
@@ -342,7 +278,6 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
pci_read_config_dword(dev, 0x40, &val);
val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
pci_write_config_dword(dev, 0x40, val);
- pci_set_drvdata(dev, (void *)val);
return dev->irq;
}
@@ -352,19 +287,19 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
*/
static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned int rev;
DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
hwif->set_pio_mode = &sl82c105_set_pio_mode;
hwif->set_dma_mode = &sl82c105_set_dma_mode;
- hwif->selectproc = &sl82c105_selectproc;
hwif->resetproc = &sl82c105_resetproc;
if (!hwif->dma_base)
return;
- rev = sl82c105_bridge_revision(hwif->pci_dev);
+ rev = sl82c105_bridge_revision(dev);
if (rev <= 5) {
/*
* Never ever EVER under any circumstances enable
@@ -377,10 +312,9 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
hwif->mwdma_mask = ATA_MWDMA2;
- hwif->ide_dma_on = &sl82c105_ide_dma_on;
- hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
hwif->dma_lost_irq = &sl82c105_dma_lost_irq;
hwif->dma_start = &sl82c105_dma_start;
+ hwif->ide_dma_end = &sl82c105_dma_end;
hwif->dma_timeout = &sl82c105_dma_timeout;
if (hwif->mate)
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index eb4445b229e..65f4c2ffaa5 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/pci/slc90e66.c Version 0.19 Sep 24, 2007
- *
* Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
*
@@ -12,21 +10,17 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/delay.h>
#include <linux/init.h>
-#include <asm/io.h>
-
static DEFINE_SPINLOCK(slc90e66_lock);
static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
int is_slave = drive->dn & 1;
int master_port = hwif->channel ? 0x42 : 0x40;
int slave_port = 0x44;
@@ -79,7 +73,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 maslave = hwif->channel ? 0x42 : 0x40;
int sitre = 0, a_speed = 7 << (drive->dn * 4);
int u_speed = 0, u_flag = 1 << drive->dn;
@@ -91,19 +85,9 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_read_config_word(dev, 0x48, &reg48);
pci_read_config_word(dev, 0x4a, &reg4a);
- switch(speed) {
- case XFER_UDMA_4: u_speed = 4 << (drive->dn * 4); break;
- case XFER_UDMA_3: u_speed = 3 << (drive->dn * 4); break;
- case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
- case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
- case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_SW_DMA_2: break;
- default: return;
- }
-
if (speed >= XFER_UDMA_0) {
+ u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4);
+
if (!(reg48 & u_flag))
pci_write_config_word(dev, 0x48, reg48|u_flag);
/* FIXME: (reg4a & a_speed) ? */
@@ -130,22 +114,23 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
}
-static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
+static u8 __devinit slc90e66_cable_detect(ide_hwif_t *hwif)
{
- u8 reg47 = 0;
- u8 mask = hwif->channel ? 0x01 : 0x02; /* bit0:Primary */
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02;
- hwif->set_pio_mode = &slc90e66_set_pio_mode;
- hwif->set_dma_mode = &slc90e66_set_dma_mode;
+ pci_read_config_byte(dev, 0x47, &reg47);
- pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
+ /* bit[0(1)]: 0:80, 1:40 */
+ return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
- if (hwif->dma_base == 0)
- return;
+static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
+{
+ hwif->set_pio_mode = &slc90e66_set_pio_mode;
+ hwif->set_dma_mode = &slc90e66_set_dma_mode;
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- /* bit[0(1)]: 0:80, 1:40 */
- hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+ hwif->cable_detect = slc90e66_cable_detect;
}
static const struct ide_port_info slc90e66_chipset __devinitdata = {
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index a66ebd14664..2ef2ed2f2b3 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -1,6 +1,4 @@
/*
- * drivers/ide/pci/tc86c001.c Version 1.01 Sep 5, 2007
- *
* Copyright (C) 2002 Toshiba Corporation
* Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
*
@@ -162,9 +160,23 @@ static int tc86c001_busproc(ide_drive_t *drive, int state)
return 0;
}
+static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ unsigned long sc_base = pci_resource_start(dev, 5);
+ u16 scr1 = inw(sc_base + 0x00);
+
+ /*
+ * System Control 1 Register bit 13 (PDIAGN):
+ * 0=80-pin cable, 1=40-pin cable
+ */
+ return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
{
- unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ unsigned long sc_base = pci_resource_start(dev, 5);
u16 scr1 = inw(sc_base + 0x00);
/* System Control 1 Register bit 15 (Soft Reset) set */
@@ -184,6 +196,8 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
hwif->busproc = &tc86c001_busproc;
+ hwif->cable_detect = tc86c001_cable_detect;
+
if (!hwif->dma_base)
return;
@@ -197,15 +211,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
hwif->rqsize = 0xffff;
hwif->dma_start = &tc86c001_dma_start;
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
- /*
- * System Control 1 Register bit 13 (PDIAGN):
- * 0=80-pin cable, 1=40-pin cable
- */
- scr1 = inw(sc_base + 0x00);
- hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
- }
}
static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
@@ -222,7 +227,8 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
.name = "TC86C001",
.init_chipset = init_chipset_tc86c001,
.init_hwif = init_hwif_tc86c001,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index a227c41d23a..a67d02a3f96 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -1,6 +1,4 @@
/*
- * triflex.c
- *
* IDE Chipset driver for the Compaq TriFlex IDE controller.
*
* Known to work with the Compaq Workstation 5x00 series.
@@ -30,11 +28,6 @@
#include <linux/types.h>
#include <linux/module.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/pci.h>
#include <linux/ide.h>
@@ -43,7 +36,7 @@
static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 channel_offset = hwif->channel ? 0x74 : 0x70;
u16 timing = 0;
u32 triflex_timings = 0;
@@ -81,8 +74,6 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
case XFER_PIO_0:
timing = 0x0808;
break;
- default:
- return;
}
triflex_timings &= ~(0xFFFF << (16 * unit));
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index 5011ba22e36..de750f7a43e 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -1,7 +1,7 @@
/*
- * linux/drivers/ide/pci/trm290.c Version 1.02 Mar. 18, 2000
- *
* Copyright (c) 1997-1998 Mark Lord
+ * Copyright (c) 2007 MontaVista Software, Inc. <source@mvista.com>
+ *
* May be copied or modified under the terms of the GNU General Public License
*
* June 22, 2004 - get rid of check_region
@@ -131,14 +131,12 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/ide.h>
#include <asm/io.h>
@@ -177,15 +175,12 @@ static void trm290_selectproc (ide_drive_t *drive)
trm290_prepare_drive(drive, drive->using_dma);
}
-static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
{
- BUG_ON(HWGROUP(drive)->handler != NULL); /* paranoia check */
- ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
- /* issue cmd to drive */
- outb(command, IDE_COMMAND_REG);
+ ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL);
}
-static int trm290_ide_dma_setup(ide_drive_t *drive)
+static int trm290_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->hwgroup->rq;
@@ -208,58 +203,73 @@ static int trm290_ide_dma_setup(ide_drive_t *drive)
}
/* select DMA xfer */
trm290_prepare_drive(drive, 1);
- outl(hwif->dmatable_dma | rw, hwif->dma_command);
+ outl(hwif->dmatable_dma | rw, hwif->dma_base);
drive->waiting_for_dma = 1;
/* start DMA */
- outw((count * 2) - 1, hwif->dma_status);
+ outw(count * 2 - 1, hwif->dma_base + 2);
return 0;
}
-static void trm290_ide_dma_start(ide_drive_t *drive)
+static void trm290_dma_start(ide_drive_t *drive)
{
}
static int trm290_ide_dma_end (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- u16 status = 0;
+ u16 status;
drive->waiting_for_dma = 0;
/* purge DMA mappings */
ide_destroy_dmatable(drive);
- status = inw(hwif->dma_status);
- return (status != 0x00ff);
+ status = inw(HWIF(drive)->dma_base + 2);
+ return status != 0x00ff;
}
static int trm290_ide_dma_test_irq (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- u16 status = 0;
+ u16 status;
- status = inw(hwif->dma_status);
- return (status == 0x00ff);
+ status = inw(HWIF(drive)->dma_base + 2);
+ return status == 0x00ff;
+}
+
+static void trm290_dma_host_set(ide_drive_t *drive, int on)
+{
}
-/*
- * Invoked from ide-dma.c at boot time.
- */
static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
{
- unsigned int cfgbase = 0;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ unsigned int cfg_base = pci_resource_start(dev, 4);
unsigned long flags;
u8 reg = 0;
- struct pci_dev *dev = hwif->pci_dev;
-
- cfgbase = pci_resource_start(dev, 4);
- if ((dev->class & 5) && cfgbase) {
- hwif->config_data = cfgbase;
- printk(KERN_INFO "TRM290: chip config base at 0x%04lx\n",
- hwif->config_data);
- } else {
- hwif->config_data = 0x3df0;
- printk(KERN_INFO "TRM290: using default config base at 0x%04lx\n",
- hwif->config_data);
+
+ if ((dev->class & 5) && cfg_base)
+ printk(KERN_INFO "TRM290: chip");
+ else {
+ cfg_base = 0x3df0;
+ printk(KERN_INFO "TRM290: using default");
+ }
+ printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
+ hwif->config_data = cfg_base;
+ hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0);
+
+ printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx",
+ hwif->name, hwif->dma_base, hwif->dma_base + 3);
+
+ if (!request_region(hwif->dma_base, 4, hwif->name)) {
+ printk(KERN_CONT " -- Error, ports in use.\n");
+ return;
+ }
+
+ hwif->dmatable_cpu = pci_alloc_consistent(dev, PRD_ENTRIES * PRD_BYTES,
+ &hwif->dmatable_dma);
+ if (!hwif->dmatable_cpu) {
+ printk(KERN_CONT " -- Error, unable to allocate DMA table.\n");
+ release_region(hwif->dma_base, 4);
+ return;
}
+ printk(KERN_CONT "\n");
local_irq_save(flags);
/* put config reg into first byte of hwif->select_data */
@@ -274,20 +284,19 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
outb(reg, hwif->config_data + 3);
local_irq_restore(flags);
- if ((reg & 0x10))
+ if (reg & 0x10)
/* legacy mode */
hwif->irq = hwif->channel ? 15 : 14;
else if (!hwif->irq && hwif->mate && hwif->mate->irq)
/* sharing IRQ with mate */
hwif->irq = hwif->mate->irq;
- ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
-
- hwif->dma_setup = &trm290_ide_dma_setup;
- hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd;
- hwif->dma_start = &trm290_ide_dma_start;
- hwif->ide_dma_end = &trm290_ide_dma_end;
- hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
+ hwif->dma_host_set = &trm290_dma_host_set;
+ hwif->dma_setup = &trm290_dma_setup;
+ hwif->dma_exec_cmd = &trm290_dma_exec_cmd;
+ hwif->dma_start = &trm290_dma_start;
+ hwif->ide_dma_end = &trm290_ide_dma_end;
+ hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
hwif->selectproc = &trm290_selectproc;
#if 1
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index a0d3c16b68e..f3f79f80581 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -1,7 +1,4 @@
/*
- *
- * Version 3.50
- *
* VIA IDE driver for Linux. Supported southbridges:
*
* vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
@@ -29,15 +26,11 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <linux/dmi.h>
-#include <asm/io.h>
-
#ifdef CONFIG_PPC_CHRP
#include <asm/processor.h>
#endif
@@ -121,8 +114,8 @@ struct via82cxxx_dev
static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
{
- struct pci_dev *dev = hwif->pci_dev;
- struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
u8 t;
if (~vdev->via_config->flags & VIA_BAD_AST) {
@@ -159,8 +152,10 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
static void via_set_drive(ide_drive_t *drive, const u8 speed)
{
- ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
- struct via82cxxx_dev *vdev = pci_get_drvdata(drive->hwif->pci_dev);
+ ide_hwif_t *hwif = drive->hwif;
+ ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
struct ide_timing t, p;
unsigned int T, UT;
@@ -408,7 +403,7 @@ static int via_cable_override(struct pci_dev *pdev)
static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
{
- struct pci_dev *pdev = hwif->pci_dev;
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
struct via82cxxx_dev *vdev = pci_get_drvdata(pdev);
if (via_cable_override(pdev))
@@ -425,11 +420,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
hwif->set_pio_mode = &via_set_pio_mode;
hwif->set_dma_mode = &via_set_drive;
- if (!hwif->dma_base)
- return;
-
- if (hwif->cbl != ATA_CBL_PATA40_SHORT)
- hwif->cbl = via82cxxx_cable_detect(hwif);
+ hwif->cable_detect = via82cxxx_cable_detect;
}
static const struct ide_port_info via82cxxx_chipset __devinitdata = {
@@ -439,6 +430,7 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
.enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
.host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
IDE_HFLAG_PIO_NO_DOWNGRADE |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_IO_32BIT |
IDE_HFLAG_BOOTABLE,
diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile
new file mode 100644
index 00000000000..65af5848b28
--- /dev/null
+++ b/drivers/ide/ppc/Makefile
@@ -0,0 +1,3 @@
+
+obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o
+obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += mpc8xx.o
diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
index 5f0da35ab5a..06190b1c4ec 100644
--- a/drivers/ide/ppc/mpc8xx.c
+++ b/drivers/ide/ppc/mpc8xx.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/ppc/ide-m8xx.c
- *
* Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de
* Modified for direct IDE interface
* by Thomas Lange, thomas@corelatus.com
@@ -838,3 +836,21 @@ void m8xx_ide_init(void)
ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
}
+
+static int __init mpc8xx_ide_probe(void)
+{
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+
+#ifdef IDE0_BASE_OFFSET
+ idx[0] = 0;
+#ifdef IDE1_BASE_OFFSET
+ idx[1] = 1;
+#endif
+#endif
+
+ ide_device_add(idx, NULL);
+
+ return 0;
+}
+
+module_init(mpc8xx_ide_probe);
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 816b5311dad..12ac3bfb4f9 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1,7 +1,6 @@
/*
- * linux/drivers/ide/ppc/pmac.c
- *
* Support for IDE interfaces on PowerMacs.
+ *
* These IDE interfaces are memory-mapped and have a DBDMA channel
* for doing DMA.
*
@@ -413,7 +412,7 @@ kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
*/
#define IDE_WAKEUP_DELAY (1*HZ)
-static void pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif);
+static int pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif);
static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
static void pmac_ide_selectproc(ide_drive_t *drive);
static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
@@ -438,13 +437,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
if (data_port == pmac_ide[ix].regbase)
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;
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- return;
- }
+ if (ix >= MAX_HWIFS)
+ return; /* not an IDE PMAC interface */
for (i = 0; i < 8; ++i)
hw->io_ports[i] = data_port + i * 0x10;
@@ -833,38 +827,20 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
tl[0] = *timings;
tl[1] = *timings2;
- switch(speed) {
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- if (pmif->kind == controller_kl_ata4)
- ret = set_timings_udma_ata4(&tl[0], speed);
- else if (pmif->kind == controller_un_ata6
- || pmif->kind == controller_k2_ata6)
- ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
- else if (pmif->kind == controller_sh_ata6)
- ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
- else
- ret = 1;
- break;
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_MW_DMA_0:
- set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
- break;
- case XFER_SW_DMA_2:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- return;
+ if (speed >= XFER_UDMA_0) {
+ if (pmif->kind == controller_kl_ata4)
+ ret = set_timings_udma_ata4(&tl[0], speed);
+ else if (pmif->kind == controller_un_ata6
+ || pmif->kind == controller_k2_ata6)
+ ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
+ else if (pmif->kind == controller_sh_ata6)
+ ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
+ else
+ ret = -1;
+ } else
+ set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
- default:
- ret = 1;
- }
if (ret)
return;
@@ -1027,6 +1003,17 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
return 0;
}
+static const struct ide_port_info pmac_port_info = {
+ .chipset = ide_pmac,
+ .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+ IDE_HFLAG_PIO_NO_DOWNGRADE |
+ IDE_HFLAG_POST_SET_MODE |
+ IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+ IDE_HFLAG_UNMASK_IRQS,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+};
+
/*
* Setup, register & probe an IDE channel driven by this driver, this is
* called by one of the 2 probe functions (macio or PCI). Note that a channel
@@ -1034,30 +1021,34 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
* (it is kept in 2.4). This introduce an interface numbering change on some
* rare machines unfortunately, but it's better this way.
*/
-static int
-pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
+static int __devinit
+pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
{
struct device_node *np = pmif->node;
const int *bidp;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ struct ide_port_info d = pmac_port_info;
pmif->cable_80 = 0;
pmif->broken_dma = pmif->broken_dma_warn = 0;
- if (of_device_is_compatible(np, "shasta-ata"))
+ if (of_device_is_compatible(np, "shasta-ata")) {
pmif->kind = controller_sh_ata6;
- else if (of_device_is_compatible(np, "kauai-ata"))
+ d.udma_mask = ATA_UDMA6;
+ } else if (of_device_is_compatible(np, "kauai-ata")) {
pmif->kind = controller_un_ata6;
- else if (of_device_is_compatible(np, "K2-UATA"))
+ d.udma_mask = ATA_UDMA5;
+ } else if (of_device_is_compatible(np, "K2-UATA")) {
pmif->kind = controller_k2_ata6;
- else if (of_device_is_compatible(np, "keylargo-ata")) {
- if (strcmp(np->name, "ata-4") == 0)
+ d.udma_mask = ATA_UDMA5;
+ } else if (of_device_is_compatible(np, "keylargo-ata")) {
+ if (strcmp(np->name, "ata-4") == 0) {
pmif->kind = controller_kl_ata4;
- else
+ d.udma_mask = ATA_UDMA4;
+ } else
pmif->kind = controller_kl_ata3;
- } else if (of_device_is_compatible(np, "heathrow-ata"))
+ } else if (of_device_is_compatible(np, "heathrow-ata")) {
pmif->kind = controller_heathrow;
- else {
+ } else {
pmif->kind = controller_ohare;
pmif->broken_dma = 1;
}
@@ -1126,20 +1117,10 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
/* Tell common code _not_ to mess with resources */
hwif->mmio = 1;
hwif->hwif_data = pmif;
- memset(&hw, 0, sizeof(hw));
- pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, &hwif->irq);
- memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
- hwif->chipset = ide_pmac;
- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
+ ide_init_port_hw(hwif, hw);
+ hwif->noprobe = pmif->mediabay;
hwif->hold = pmif->mediabay;
hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
- hwif->drives[0].unmask = 1;
- hwif->drives[1].unmask = 1;
- hwif->drives[0].autotune = IDE_TUNE_AUTO;
- hwif->drives[1].autotune = IDE_TUNE_AUTO;
- hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
- IDE_HFLAG_POST_SET_MODE;
- hwif->pio_mask = ATA_PIO4;
hwif->set_pio_mode = pmac_ide_set_pio_mode;
if (pmif->kind == controller_un_ata6
|| pmif->kind == controller_k2_ata6
@@ -1158,17 +1139,17 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->noprobe = 0;
#endif /* CONFIG_PMAC_MEDIABAY */
- hwif->sg_max_nents = MAX_DCMDS;
-
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+ if (pmif->cable_80 == 0)
+ d.udma_mask &= ATA_UDMA2;
/* has a DBDMA controller channel */
- if (pmif->dma_regs)
- pmac_ide_setup_dma(pmif, hwif);
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+ if (pmif->dma_regs == 0 || pmac_ide_setup_dma(pmif, hwif) < 0)
+#endif
+ d.udma_mask = d.mwdma_mask = 0;
idx[0] = hwif->index;
- ide_device_add(idx);
+ ide_device_add(idx, &d);
return 0;
}
@@ -1185,6 +1166,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
ide_hwif_t *hwif;
pmac_ide_hwif_t *pmif;
int i, rc;
+ hw_regs_t hw;
i = 0;
while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
@@ -1226,8 +1208,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
base = ioremap(macio_resource_start(mdev, 0), 0x400);
regbase = (unsigned long) base;
- hwif->pci_dev = mdev->bus->pdev;
- hwif->gendev.parent = &mdev->ofdev.dev;
+ hwif->dev = &mdev->bus->pdev->dev;
pmif->mdev = mdev;
pmif->node = mdev->ofdev.node;
@@ -1245,17 +1226,22 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
dev_set_drvdata(&mdev->ofdev.dev, hwif);
- rc = pmac_ide_setup_device(pmif, hwif);
+ memset(&hw, 0, sizeof(hw));
+ pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
+ hw.irq = irq;
+ hw.dev = &mdev->ofdev.dev;
+
+ rc = pmac_ide_setup_device(pmif, hwif, &hw);
if (rc != 0) {
/* The inteface is released to the common IDE layer */
dev_set_drvdata(&mdev->ofdev.dev, NULL);
iounmap(base);
- if (pmif->dma_regs)
+ if (pmif->dma_regs) {
iounmap(pmif->dma_regs);
+ macio_release_resource(mdev, 1);
+ }
memset(pmif, 0, sizeof(*pmif));
macio_release_resource(mdev, 0);
- if (pmif->dma_regs)
- macio_release_resource(mdev, 1);
}
return rc;
@@ -1304,6 +1290,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
void __iomem *base;
unsigned long rbase, rlen;
int i, rc;
+ hw_regs_t hw;
np = pci_device_to_OF_node(pdev);
if (np == NULL) {
@@ -1336,8 +1323,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENXIO;
}
- hwif->pci_dev = pdev;
- hwif->gendev.parent = &pdev->dev;
+ hwif->dev = &pdev->dev;
pmif->mdev = NULL;
pmif->node = np;
@@ -1354,7 +1340,12 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, hwif);
- rc = pmac_ide_setup_device(pmif, hwif);
+ memset(&hw, 0, sizeof(hw));
+ pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
+ hw.irq = pdev->irq;
+ hw.dev = &pdev->dev;
+
+ rc = pmac_ide_setup_device(pmif, hwif, &hw);
if (rc != 0) {
/* The inteface is released to the common IDE layer */
pci_set_drvdata(pdev, NULL);
@@ -1512,7 +1503,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) {
if (pmif->broken_dma_warn == 0) {
- printk(KERN_WARNING "%s: DMA on non aligned address,"
+ printk(KERN_WARNING "%s: DMA on non aligned address, "
"switching to PIO on Ohare chipset\n", drive->name);
pmif->broken_dma_warn = 1;
}
@@ -1552,11 +1543,10 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
}
printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
- use_pio_instead:
- pci_unmap_sg(hwif->pci_dev,
- hwif->sg_table,
- hwif->sg_nents,
- hwif->sg_dma_direction);
+
+use_pio_instead:
+ ide_destroy_dmatable(drive);
+
return 0; /* revert to PIO for this request */
}
@@ -1565,12 +1555,9 @@ static void
pmac_ide_destroy_dmatable (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct pci_dev *dev = HWIF(drive)->pci_dev;
- struct scatterlist *sg = hwif->sg_table;
- int nents = hwif->sg_nents;
- if (nents) {
- pci_unmap_sg(dev, sg, nents, hwif->sg_dma_direction);
+ if (hwif->sg_nents) {
+ ide_destroy_dmatable(drive);
hwif->sg_nents = 0;
}
}
@@ -1720,11 +1707,7 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
return 1;
}
-static void pmac_ide_dma_host_off(ide_drive_t *drive)
-{
-}
-
-static void pmac_ide_dma_host_on(ide_drive_t *drive)
+static void pmac_ide_dma_host_set(ide_drive_t *drive, int on)
{
}
@@ -1747,64 +1730,44 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive)
* Allocate the data structures needed for using DMA with an interface
* and fill the proper list of functions pointers
*/
-static void __init
-pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
+static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+
/* We won't need pci_dev if we switch to generic consistent
* DMA routines ...
*/
- if (hwif->pci_dev == NULL)
- return;
+ if (dev == NULL)
+ return -ENODEV;
/*
* Allocate space for the DBDMA commands.
* The +2 is +1 for the stop command and +1 to allow for
* aligning the start address to a multiple of 16 bytes.
*/
pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
- hwif->pci_dev,
+ dev,
(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
&hwif->dmatable_dma);
if (pmif->dma_table_cpu == NULL) {
printk(KERN_ERR "%s: unable to allocate DMA command list\n",
hwif->name);
- return;
+ return -ENOMEM;
}
- hwif->dma_off_quietly = &ide_dma_off_quietly;
- hwif->ide_dma_on = &__ide_dma_on;
+ hwif->sg_max_nents = MAX_DCMDS;
+
+ hwif->dma_host_set = &pmac_ide_dma_host_set;
hwif->dma_setup = &pmac_ide_dma_setup;
hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd;
hwif->dma_start = &pmac_ide_dma_start;
hwif->ide_dma_end = &pmac_ide_dma_end;
hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
- hwif->dma_host_off = &pmac_ide_dma_host_off;
- hwif->dma_host_on = &pmac_ide_dma_host_on;
hwif->dma_timeout = &ide_dma_timeout;
hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
- switch(pmif->kind) {
- case controller_sh_ata6:
- hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x00;
- break;
- case controller_un_ata6:
- case controller_k2_ata6:
- hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x00;
- break;
- case controller_kl_ata4:
- hwif->ultra_mask = pmif->cable_80 ? 0x1f : 0x07;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x00;
- break;
- default:
- hwif->ultra_mask = 0x00;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x00;
- break;
- }
+ return 0;
}
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+
+module_init(pmac_ide_probe);
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 02d14bf85ab..634e3f6a960 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -1,17 +1,11 @@
/*
- * linux/drivers/ide/setup-pci.c Version 1.10 2002/08/19
+ * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 1995-1998 Mark Lord
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
- * Copyright (c) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *
- * Copyright (c) 1995-1998 Mark Lord
* May be copied or modified under the terms of the GNU General Public License
*/
-/*
- * This module provides support for automatic detection and
- * configuration of all PCI IDE interfaces present in a system.
- */
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -145,6 +139,16 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
+{
+ u8 dma_stat = inb(dma_base + 2);
+
+ outb(dma_stat & 0x60, dma_base + 2);
+ dma_stat = inb(dma_base + 2);
+ if (dma_stat & 0x80)
+ printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
+}
+
/**
* ide_get_or_set_dma_base - setup BMIBA
* @d: IDE port info
@@ -157,8 +161,9 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif)
{
- unsigned long dma_base = 0;
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ unsigned long dma_base = 0;
+ u8 dma_stat = 0;
if (hwif->mmio)
return hwif->dma_base;
@@ -170,57 +175,39 @@ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_
dma_base = pci_resource_start(dev, baridx);
- if (dma_base == 0)
+ if (dma_base == 0) {
printk(KERN_ERR "%s: DMA base is invalid\n", d->name);
+ return 0;
+ }
}
- if ((d->host_flags & IDE_HFLAG_CS5520) == 0 && dma_base) {
- u8 simplex_stat = 0;
- dma_base += hwif->channel ? 8 : 0;
-
- switch(dev->device) {
- case PCI_DEVICE_ID_AL_M5219:
- case PCI_DEVICE_ID_AL_M5229:
- case PCI_DEVICE_ID_AMD_VIPER_7409:
- case PCI_DEVICE_ID_CMD_643:
- case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
- case PCI_DEVICE_ID_REVOLUTION:
- simplex_stat = inb(dma_base + 2);
- outb(simplex_stat & 0x60, dma_base + 2);
- simplex_stat = inb(dma_base + 2);
- if (simplex_stat & 0x80) {
- printk(KERN_INFO "%s: simplex device: "
- "DMA forced\n",
- d->name);
- }
- break;
- default:
- /*
- * 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.
- */
- simplex_stat = hwif->INB(dma_base + 2);
- if (simplex_stat & 0x80) {
- /* simplex device? */
-/*
- * At this point we haven't probed the drives so we can't make the
- * appropriate decision. Really we should defer this problem
- * until we tune the drive then try to grab DMA ownership if we want
- * to be the DMA end. This has to be become dynamic to handle hot
- * plug.
- */
- if (hwif->mate && hwif->mate->dma_base) {
- printk(KERN_INFO "%s: simplex device: "
- "DMA disabled\n",
- d->name);
- dma_base = 0;
- }
- }
- }
+ if (hwif->channel)
+ dma_base += 8;
+
+ if (d->host_flags & IDE_HFLAG_CS5520)
+ goto out;
+
+ if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
+ ide_pci_clear_simplex(dma_base, d->name);
+ goto out;
}
+
+ /*
+ * If the device claims "simplex" DMA, this means that 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).
+ *
+ * FIXME: At this point we haven't probed the drives so we can't make
+ * the appropriate decision. Really we should defer this problem until
+ * we tune the drive then try to grab DMA ownership if we want to be
+ * the DMA end. This has to be become dynamic to handle hot-plug.
+ */
+ dma_stat = hwif->INB(dma_base + 2);
+ if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
+ printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
+ dma_base = 0;
+ }
+out:
return dma_base;
}
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
@@ -241,7 +228,9 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
* @d: IDE port info
*
* Enable the IDE PCI device. We attempt to enable the device in full
- * but if that fails then we only need BAR4 so we will enable that.
+ * but if that fails then we only need IO space. The PCI code should
+ * have setup the proper resources for us already for controllers in
+ * legacy mode.
*
* Returns zero on success or an error code
*/
@@ -251,7 +240,7 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
int ret;
if (pci_enable_device(dev)) {
- ret = pci_enable_device_bars(dev, 1 << 4);
+ ret = pci_enable_device_io(dev);
if (ret < 0) {
printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
"Could not enable device.\n", d->name);
@@ -350,7 +339,8 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
* ide_hwif_configure - configure an IDE interface
* @dev: PCI device holding interface
* @d: IDE port info
- * @mate: Paired interface if any
+ * @port: port number
+ * @irq: PCI IRQ
*
* Perform the initial set up for the hardware interface structure. This
* is done per interface port rather than per PCI device. There may be
@@ -359,11 +349,15 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
* Returns the new hardware interface structure, or NULL on a failure
*/
-static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *mate, int port, int irq)
+static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
+ const struct ide_port_info *d,
+ unsigned int port, int irq)
{
unsigned long ctl = 0, base = 0;
ide_hwif_t *hwif;
u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0;
+ u8 oldnoprobe = 0;
+ struct hw_regs_s hw;
if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
/* Possibly we should fail if these checks report true */
@@ -386,47 +380,41 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port
}
if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL)
return NULL; /* no room in ide_hwifs[] */
- if (hwif->io_ports[IDE_DATA_OFFSET] != base ||
- hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) {
- hw_regs_t hw;
-
- memset(&hw, 0, sizeof(hw));
-#ifndef CONFIG_IDE_ARCH_OBSOLETE_INIT
- ide_std_init_ports(&hw, base, ctl | 2);
-#else
- ide_init_hwif_ports(&hw, base, ctl | 2, NULL);
-#endif
- memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
- }
- hwif->chipset = d->chipset ? d->chipset : ide_pci;
- hwif->pci_dev = dev;
+
+ memset(&hw, 0, sizeof(hw));
+ hw.irq = hwif->irq ? hwif->irq : irq;
+ hw.dev = &dev->dev;
+ hw.chipset = d->chipset ? d->chipset : ide_pci;
+ ide_std_init_ports(&hw, base, ctl | 2);
+
+ if (hwif->io_ports[IDE_DATA_OFFSET] == base &&
+ hwif->io_ports[IDE_CONTROL_OFFSET] == (ctl | 2))
+ oldnoprobe = hwif->noprobe;
+
+ ide_init_port_hw(hwif, &hw);
+
+ hwif->noprobe = oldnoprobe;
+
+ hwif->dev = &dev->dev;
hwif->cds = d;
- hwif->channel = port;
- if (!hwif->irq)
- hwif->irq = irq;
- if (mate) {
- hwif->mate = mate;
- mate->mate = hwif;
- }
return hwif;
}
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
/**
* ide_hwif_setup_dma - configure DMA interface
- * @dev: PCI device
- * @d: IDE port info
* @hwif: IDE interface
+ * @d: IDE port info
*
* Set up the DMA base for the interface. Enable the master bits as
* necessary and attempt to bring the device DMA into a ready to use
* state
*/
-static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *hwif)
+void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
{
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 pcicmd;
pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
@@ -451,15 +439,15 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *
if (d->init_dma) {
d->init_dma(hwif, dma_base);
} else {
- ide_setup_dma(hwif, dma_base, 8);
+ ide_setup_dma(hwif, dma_base);
}
} else {
printk(KERN_INFO "%s: %s Bus-Master DMA disabled "
"(BIOS)\n", hwif->name, d->name);
}
}
-#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
}
+#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
/**
* ide_setup_pci_controller - set up IDE PCI
@@ -521,7 +509,7 @@ out:
void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx)
{
int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
- ide_hwif_t *hwif, *mate = NULL;
+ ide_hwif_t *hwif;
u8 tmp;
/*
@@ -537,62 +525,11 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
continue; /* port not enabled */
}
- if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL)
+ hwif = ide_hwif_configure(dev, d, port, pciirq);
+ if (hwif == NULL)
continue;
- /* setup proper ancestral information */
- hwif->gendev.parent = &dev->dev;
-
*(idx + port) = hwif->index;
-
-
- if (d->init_iops)
- d->init_iops(hwif);
-
- if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
- ide_hwif_setup_dma(dev, d, hwif);
-
- if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
- (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
- hwif->irq = port ? 15 : 14;
-
- hwif->fixup = d->fixup;
-
- hwif->host_flags = d->host_flags;
- hwif->pio_mask = d->pio_mask;
-
- if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
- hwif->mate->serialized = hwif->serialized = 1;
-
- if (d->host_flags & IDE_HFLAG_IO_32BIT) {
- hwif->drives[0].io_32bit = 1;
- hwif->drives[1].io_32bit = 1;
- }
-
- if (d->host_flags & IDE_HFLAG_UNMASK_IRQS) {
- hwif->drives[0].unmask = 1;
- hwif->drives[1].unmask = 1;
- }
-
- if (hwif->dma_base) {
- hwif->swdma_mask = d->swdma_mask;
- hwif->mwdma_mask = d->mwdma_mask;
- hwif->ultra_mask = d->udma_mask;
- }
-
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- if (d->host_flags & IDE_HFLAG_RQSIZE_256)
- hwif->rqsize = 256;
-
- if (d->init_hwif)
- /* Call chipset-specific routine
- * for each enabled hwif
- */
- d->init_hwif(hwif);
-
- mate = hwif;
}
}
@@ -674,7 +611,7 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
ret = do_ide_setup_pci_device(dev, d, &idx[0], 1);
if (ret >= 0)
- ide_device_add(idx);
+ ide_device_add(idx, d);
return ret;
}
@@ -698,110 +635,9 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
goto out;
}
- ide_device_add(idx);
+ ide_device_add(idx, d);
out:
return ret;
}
EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
-
-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
-/*
- * Module interfaces
- */
-
-static int pre_init = 1; /* Before first ordered IDE scan */
-static LIST_HEAD(ide_pci_drivers);
-
-/*
- * __ide_pci_register_driver - attach IDE driver
- * @driver: pci driver
- * @module: owner module of the driver
- *
- * Registers a driver with the IDE layer. The IDE layer arranges that
- * boot time setup is done in the expected device order and then
- * hands the controllers off to the core PCI code to do the rest of
- * the work.
- *
- * Returns are the same as for pci_register_driver
- */
-
-int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
- const char *mod_name)
-{
- if(!pre_init)
- return __pci_register_driver(driver, module, mod_name);
- driver->driver.owner = module;
- list_add_tail(&driver->node, &ide_pci_drivers);
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
-
-/**
- * ide_scan_pcidev - find an IDE driver for a device
- * @dev: PCI device to check
- *
- * Look for an IDE driver to handle the device we are considering.
- * This is only used during boot up to get the ordering correct. After
- * boot up the pci layer takes over the job.
- */
-
-static int __init ide_scan_pcidev(struct pci_dev *dev)
-{
- struct list_head *l;
- struct pci_driver *d;
-
- list_for_each(l, &ide_pci_drivers) {
- d = list_entry(l, struct pci_driver, node);
- if (d->id_table) {
- const struct pci_device_id *id = pci_match_id(d->id_table,
- dev);
- if (id != NULL && d->probe(dev, id) >= 0) {
- dev->driver = d;
- pci_dev_get(dev);
- return 1;
- }
- }
- }
- return 0;
-}
-
-/**
- * ide_scan_pcibus - perform the initial IDE driver scan
- * @scan_direction: set for reverse order scanning
- *
- * Perform the initial bus rather than driver ordered scan of the
- * PCI drivers. After this all IDE pci handling becomes standard
- * module ordering not traditionally ordered.
- */
-
-void __init ide_scan_pcibus (int scan_direction)
-{
- struct pci_dev *dev = NULL;
- struct pci_driver *d;
- struct list_head *l, *n;
-
- pre_init = 0;
- if (!scan_direction)
- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
- ide_scan_pcidev(dev);
- else
- while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev))
- != NULL)
- ide_scan_pcidev(dev);
-
- /*
- * Hand the drivers over to the PCI layer now we
- * are post init.
- */
-
- list_for_each_safe(l, n, &ide_pci_drivers) {
- list_del(l);
- d = list_entry(l, struct pci_driver, node);
- if (__pci_register_driver(d, d->driver.owner, d->driver.mod_name))
- printk(KERN_ERR "%s: failed to register driver for %s\n",
- __FUNCTION__, d->driver.mod_name);
- }
-}
-#endif