summaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-15 13:46:29 +0200
committerIngo Molnar <mingo@elte.hu>2008-10-15 13:46:29 +0200
commitb2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (patch)
tree53ccb1c2c14751fe69cf93102e76e97021f6df07 /drivers/ide
parent4f962d4d65923d7b722192e729840cfb79af0a5a (diff)
parent278429cff8809958d25415ba0ed32b59866ab1a8 (diff)
Merge branch 'linus' into stackprotector
Conflicts: arch/x86/kernel/Makefile include/asm-x86/pda.h
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/Kconfig196
-rw-r--r--drivers/ide/Makefile40
-rw-r--r--drivers/ide/arm/icside.c162
-rw-r--r--drivers/ide/arm/ide_arm.c17
-rw-r--r--drivers/ide/arm/palm_bk3710.c99
-rw-r--r--drivers/ide/arm/rapide.c45
-rw-r--r--drivers/ide/h8300/ide-h8300.c67
-rw-r--r--drivers/ide/ide-acpi.c24
-rw-r--r--drivers/ide/ide-atapi.c597
-rw-r--r--drivers/ide/ide-cd.c789
-rw-r--r--drivers/ide/ide-cd.h43
-rw-r--r--drivers/ide/ide-cd_ioctl.c140
-rw-r--r--drivers/ide/ide-disk.c615
-rw-r--r--drivers/ide/ide-disk.h32
-rw-r--r--drivers/ide/ide-disk_ioctl.c29
-rw-r--r--drivers/ide/ide-disk_proc.c129
-rw-r--r--drivers/ide/ide-dma-sff.c356
-rw-r--r--drivers/ide/ide-dma.c510
-rw-r--r--drivers/ide/ide-floppy.c1276
-rw-r--r--drivers/ide/ide-floppy.h62
-rw-r--r--drivers/ide/ide-floppy_ioctl.c293
-rw-r--r--drivers/ide/ide-floppy_proc.c33
-rw-r--r--drivers/ide/ide-generic.c129
-rw-r--r--drivers/ide/ide-io.c554
-rw-r--r--drivers/ide/ide-ioctls.c299
-rw-r--r--drivers/ide/ide-iops.c574
-rw-r--r--drivers/ide/ide-lib.c243
-rw-r--r--drivers/ide/ide-park.c121
-rw-r--r--drivers/ide/ide-pio-blacklist.c94
-rw-r--r--drivers/ide/ide-pnp.c33
-rw-r--r--drivers/ide/ide-probe.c823
-rw-r--r--drivers/ide/ide-proc.c320
-rw-r--r--drivers/ide/ide-tape.c1196
-rw-r--r--drivers/ide/ide-taskfile.c315
-rw-r--r--drivers/ide/ide-timings.c (renamed from drivers/ide/ide-timing.h)211
-rw-r--r--drivers/ide/ide.c829
-rw-r--r--drivers/ide/legacy/ali14xx.c8
-rw-r--r--drivers/ide/legacy/buddha.c26
-rw-r--r--drivers/ide/legacy/dtc2278.c1
-rw-r--r--drivers/ide/legacy/falconide.c58
-rw-r--r--drivers/ide/legacy/gayle.c49
-rw-r--r--drivers/ide/legacy/hd.c815
-rw-r--r--drivers/ide/legacy/ht6560b.c51
-rw-r--r--drivers/ide/legacy/ide-4drives.c43
-rw-r--r--drivers/ide/legacy/ide-cs.c228
-rw-r--r--drivers/ide/legacy/ide_platform.c39
-rw-r--r--drivers/ide/legacy/macide.c17
-rw-r--r--drivers/ide/legacy/q40ide.c50
-rw-r--r--drivers/ide/legacy/qd65xx.c46
-rw-r--r--drivers/ide/legacy/umc8672.c1
-rw-r--r--drivers/ide/mips/Makefile1
-rw-r--r--drivers/ide/mips/au1xxx-ide.c103
-rw-r--r--drivers/ide/mips/swarm.c200
-rw-r--r--drivers/ide/pci/aec62xx.c92
-rw-r--r--drivers/ide/pci/alim15x3.c60
-rw-r--r--drivers/ide/pci/amd74xx.c180
-rw-r--r--drivers/ide/pci/atiixp.c29
-rw-r--r--drivers/ide/pci/cmd640.c203
-rw-r--r--drivers/ide/pci/cmd64x.c85
-rw-r--r--drivers/ide/pci/cs5520.c71
-rw-r--r--drivers/ide/pci/cs5530.c41
-rw-r--r--drivers/ide/pci/cs5535.c40
-rw-r--r--drivers/ide/pci/cy82c693.c158
-rw-r--r--drivers/ide/pci/delkin_cb.c33
-rw-r--r--drivers/ide/pci/generic.c85
-rw-r--r--drivers/ide/pci/hpt34x.c29
-rw-r--r--drivers/ide/pci/hpt366.c302
-rw-r--r--drivers/ide/pci/it8213.c45
-rw-r--r--drivers/ide/pci/it821x.c184
-rw-r--r--drivers/ide/pci/jmicron.c22
-rw-r--r--drivers/ide/pci/ns87415.c164
-rw-r--r--drivers/ide/pci/opti621.c26
-rw-r--r--drivers/ide/pci/pdc202xx_new.c97
-rw-r--r--drivers/ide/pci/pdc202xx_old.c75
-rw-r--r--drivers/ide/pci/piix.c171
-rw-r--r--drivers/ide/pci/rz1000.c18
-rw-r--r--drivers/ide/pci/sc1200.c75
-rw-r--r--drivers/ide/pci/scc_pata.c189
-rw-r--r--drivers/ide/pci/serverworks.c65
-rw-r--r--drivers/ide/pci/sgiioc4.c139
-rw-r--r--drivers/ide/pci/siimage.c229
-rw-r--r--drivers/ide/pci/sis5513.c49
-rw-r--r--drivers/ide/pci/sl82c105.c35
-rw-r--r--drivers/ide/pci/slc90e66.c22
-rw-r--r--drivers/ide/pci/tc86c001.c81
-rw-r--r--drivers/ide/pci/triflex.c29
-rw-r--r--drivers/ide/pci/trm290.c26
-rw-r--r--drivers/ide/pci/via82cxxx.c168
-rw-r--r--drivers/ide/ppc/Makefile1
-rw-r--r--drivers/ide/ppc/mpc8xx.c851
-rw-r--r--drivers/ide/ppc/pmac.c321
-rw-r--r--drivers/ide/setup-pci.c381
92 files changed, 7677 insertions, 10225 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 8e07de23d22..6c6dd2faced 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -54,49 +54,13 @@ menuconfig IDE
if IDE
-config IDE_MAX_HWIFS
- int "Max IDE interfaces"
- depends on ALPHA || SUPERH || IA64 || EMBEDDED
- range 1 10
- default 4
- help
- This is the maximum number of IDE hardware interfaces that will
- be supported by the driver. Make sure it is at least as high as
- the number of IDE interfaces in your system.
+comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
-config BLK_DEV_IDE
- tristate "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support"
- ---help---
- If you say Y here, you will use the full-featured IDE driver to
- control up to ten ATA/IDE interfaces, each being able to serve a
- "master" and a "slave" device, for a total of up to twenty ATA/IDE
- disk/cdrom/tape/floppy drives.
-
- Useful information about large (>540 MB) IDE disks, multiple
- interfaces, what to do if ATA/IDE devices are not automatically
- detected, sound card ATA/IDE ports, module support, and other
- topics, is contained in <file:Documentation/ide/ide.txt>. For detailed
- information about hard drives, consult the Disk-HOWTO and the
- Multi-Disk-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To fine-tune ATA/IDE drive/interface parameters for improved
- performance, look for the hdparm package at
- <ftp://ibiblio.org/pub/Linux/system/hardware/>.
-
- To compile this driver as a module, choose M here and read
- <file:Documentation/ide/ide.txt>. The module will be called ide-mod.
- Do not compile this driver as a module if your root file system (the
- one containing the directory /) is located on an IDE device.
-
- If you have one or more IDE drives, say Y or M here. If your system
- has no IDE drives, or if memory requirements are really tight, you
- could say N here, and select the "Old hard disk driver" below
- instead to save about 13 KB of memory in the kernel.
-
-if BLK_DEV_IDE
+config IDE_TIMINGS
+ bool
-comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
+config IDE_ATAPI
+ bool
config BLK_DEV_IDE_SATA
bool "Support for SATA (deprecated; conflicts with libata SATA driver)"
@@ -135,29 +99,6 @@ config BLK_DEV_IDEDISK
If unsure, say Y.
-config IDEDISK_MULTI_MODE
- 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 }
-
- If in doubt, say N.
-
config BLK_DEV_IDECS
tristate "PCMCIA IDE support"
depends on PCMCIA
@@ -201,6 +142,7 @@ config BLK_DEV_IDECD_VERBOSE_ERRORS
config BLK_DEV_IDETAPE
tristate "Include IDE/ATAPI TAPE support"
+ select IDE_ATAPI
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,
@@ -223,6 +165,7 @@ config BLK_DEV_IDETAPE
config BLK_DEV_IDEFLOPPY
tristate "Include IDE/ATAPI FLOPPY support"
+ select IDE_ATAPI
---help---
If you have an IDE floppy drive which uses the ATAPI protocol,
answer Y. ATAPI is a newer protocol used by IDE CD-ROM/tape/floppy
@@ -244,8 +187,9 @@ config BLK_DEV_IDEFLOPPY
module will be called ide-floppy.
config BLK_DEV_IDESCSI
- tristate "SCSI emulation support"
+ tristate "SCSI emulation support (DEPRECATED)"
depends on SCSI
+ select IDE_ATAPI
---help---
WARNING: ide-scsi is no longer needed for cd writing applications!
The 2.6 kernel supports direct writing to ide-cd, which eliminates
@@ -256,20 +200,6 @@ config BLK_DEV_IDESCSI
and will allow you to use a SCSI device driver instead of a native
ATAPI driver.
- This is useful if you have an ATAPI device for which no native
- driver has been written (for example, an ATAPI PD-CD drive);
- you can then use this emulation together with an appropriate SCSI
- device driver. In order to do this, say Y here and to "SCSI support"
- and "SCSI generic support", below. You must then provide the kernel
- command line "hdx=ide-scsi" (try "man bootparam" or see the
- documentation of your boot loader (lilo or loadlin) about how to
- pass options to the kernel at boot time) for devices if you want the
- native EIDE sub-drivers to skip over the native support, so that
- this SCSI emulation can be used instead.
-
- Note that this option does NOT allow you to attach SCSI devices to a
- box that doesn't have a SCSI host adapter installed.
-
If both this SCSI emulation and native ATAPI support are compiled
into the kernel, the native support will be used.
@@ -305,8 +235,22 @@ comment "IDE chipset support/bugfixes"
config IDE_GENERIC
tristate "generic/default IDE chipset support"
- depends on ALPHA || X86 || IA64 || M32R || MIPS || PPC32
- help
+ depends on ALPHA || X86 || IA64 || M32R || MIPS
+ help
+ This is the generic IDE driver. This driver attaches to the
+ fixed legacy ports (e.g. on PCs 0x1f0/0x170, 0x1e8/0x168 and
+ so on). Please note that if this driver is built into the
+ kernel or loaded before other ATA (IDE or libata) drivers
+ and the controller is located at legacy ports, this driver
+ may grab those ports and thus can prevent the controller
+ specific driver from attaching.
+
+ Also, currently, IDE generic doesn't allow IRQ sharing
+ meaning that the IRQs it grabs won't be available to other
+ controllers sharing those IRQs which usually makes drivers
+ for those controllers fail. Generally, it's not a good idea
+ to load IDE generic driver on modern systems.
+
If unsure, say N.
config BLK_DEV_PLATFORM
@@ -320,6 +264,7 @@ config BLK_DEV_PLATFORM
config BLK_DEV_CMD640
tristate "CMD640 chipset bugfix/support"
depends on X86
+ select IDE_TIMINGS
---help---
The CMD-Technologies CMD640 IDE chip is used on many common 486 and
Pentium motherboards, usually in combination with a "Neptune" or
@@ -371,7 +316,7 @@ config 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
+ depends on IDE=y && BLK_DEV_IDEPCI
default y
help
Probe IDE PCI devices in the order in which they appear on the
@@ -449,6 +394,7 @@ config BLK_DEV_AEC62XX
config BLK_DEV_ALI15X3
tristate "ALI M15x3 chipset support"
+ select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C
@@ -463,6 +409,7 @@ config BLK_DEV_ALI15X3
config BLK_DEV_AMD74XX
tristate "AMD and nVidia IDE support"
depends on !ARM
+ select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
This driver adds explicit support for AMD-7xx and AMD-8111 chips
@@ -483,6 +430,7 @@ config BLK_DEV_ATIIXP
config BLK_DEV_CMD64X
tristate "CMD64{3|6|8|9} chipset support"
+ select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
Say Y here if you have an IDE controller which uses any of these
@@ -497,6 +445,8 @@ config BLK_DEV_TRIFLEX
config BLK_DEV_CY82C693
tristate "CY82C693 chipset support"
+ depends on ALPHA
+ select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
This driver adds detection and support for the CY82C693 chipset
@@ -534,6 +484,7 @@ config BLK_DEV_CS5535
config BLK_DEV_HPT34X
tristate "HPT34X chipset support"
+ depends on BROKEN
select BLK_DEV_IDEDMA_PCI
help
This driver adds up to 4 more EIDE devices sharing a single
@@ -689,6 +640,7 @@ config BLK_DEV_SIS5513
config BLK_DEV_SL82C105
tristate "Winbond SL82c105 support"
depends on (PPC || ARM)
+ select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
If you have a Winbond SL82c105 IDE controller, say Y here to enable
@@ -719,6 +671,7 @@ config BLK_DEV_TRM290
config BLK_DEV_VIA82CXXX
tristate "VIA82CXXX chipset support"
+ select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
This driver adds explicit support for VIA BusMastering IDE chips.
@@ -744,7 +697,8 @@ endif
config BLK_DEV_IDE_PMAC
tristate "PowerMac on-board IDE support"
- depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
+ depends on PPC_PMAC && IDE=y
+ select IDE_TIMINGS
help
This driver provides support for the on-board IDE controller on
most of the recent Apple Power Macintoshes and PowerBooks.
@@ -771,10 +725,6 @@ config BLK_DEV_IDEDMA_PMAC
to transfer data to and from memory. Saying Y is safe and improves
performance.
-config BLK_DEV_IDE_SWARM
- tristate "IDE for Sibyte evaluation boards"
- depends on SIBYTE_SB1xxx_SOC
-
config BLK_DEV_IDE_AU1XXX
bool "IDE for AMD Alchemy Au1200"
depends on SOC_AU1200
@@ -906,51 +856,12 @@ config BLK_DEV_Q40IDE
config BLK_DEV_PALMCHIP_BK3710
tristate "Palmchip bk3710 IDE controller support"
depends on ARCH_DAVINCI
+ select IDE_TIMINGS
select BLK_DEV_IDEDMA_SFF
help
Say Y here if you want to support the onchip IDE controller on the
TI DaVinci SoC
-
-config BLK_DEV_MPC8xx_IDE
- 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.
-
- If unsure, say N.
-
-choice
- prompt "Type of MPC8xx IDE interface"
- depends on BLK_DEV_MPC8xx_IDE
- default IDE_8xx_PCCARD
-
-config IDE_8xx_PCCARD
- bool "8xx_PCCARD"
- ---help---
- Select how the IDE devices are connected to the MPC8xx system:
-
- 8xx_PCCARD uses the 8xx internal PCMCIA interface in combination
- with a PC Card (e.g. ARGOSY portable Hard Disk Adapter),
- ATA PC Card HDDs or ATA PC Flash Cards (example: TQM8xxL
- systems)
-
- 8xx_DIRECT is used for directly connected IDE devices using the 8xx
- internal PCMCIA interface (example: IVMS8 systems)
-
- EXT_DIRECT is used for IDE devices directly connected to the 8xx
- bus using some glue logic, but _not_ the 8xx internal
- PCMCIA interface (example: IDIF860 systems)
-
-config IDE_8xx_DIRECT
- bool "8xx_DIRECT"
-
-config IDE_EXT_DIRECT
- bool "EXT_DIRECT"
-
-endchoice
-
# no isa -> no vlb
if ISA && (ALPHA || X86 || MIPS)
@@ -968,6 +879,7 @@ config BLK_DEV_4DRIVES
config BLK_DEV_ALI14XX
tristate "ALI M14xx support"
+ select IDE_TIMINGS
help
This driver is enabled at runtime using the "ali14xx.probe" kernel
boot parameter. It enables support for the secondary IDE interface
@@ -987,6 +899,7 @@ config BLK_DEV_DTC2278
config BLK_DEV_HT6560B
tristate "Holtek HT6560B support"
+ select IDE_TIMINGS
help
This driver is enabled at runtime using the "ht6560b.probe" kernel
boot parameter. It enables support for the secondary IDE interface
@@ -996,6 +909,7 @@ config BLK_DEV_HT6560B
config BLK_DEV_QD65XX
tristate "QDI QD65xx support"
+ select IDE_TIMINGS
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
@@ -1017,32 +931,4 @@ config BLK_DEV_IDEDMA
def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \
BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-endif
-
-config BLK_DEV_HD_ONLY
- bool "Old hard disk (MFM/RLL/IDE) driver"
- depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN
- help
- There are two drivers for MFM/RLL/IDE hard disks. Most people use
- the newer enhanced driver, but this old one is still around for two
- reasons. Some older systems have strange timing problems and seem to
- work only with the old driver (which itself does not work with some
- newer systems). The other reason is that the old driver is smaller,
- since it lacks the enhanced functionality of the new one. This makes
- it a good choice for systems with very tight memory restrictions, or
- for systems with only older MFM/RLL/ESDI drives. Choosing the old
- driver can save 13 KB or so of kernel memory.
-
- If you want to use this driver together with the new one you have
- to use "hda=noprobe hdb=noprobe" kernel parameters to prevent the new
- driver from probing the primary interface.
-
- If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
- instead of this one. For more detailed information, read the
- Disk-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
-config BLK_DEV_HD
- def_bool BLK_DEV_HD_ONLY
-
endif # IDE
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index f94b679b611..ceaf779054e 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -1,32 +1,29 @@
#
-# Makefile for the kernel ata, atapi, and ide block device drivers.
-#
-# 12 September 2000, Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
-# Rewritten to use lists instead of if-statements.
-#
-# Note : at this point, these files are compiled on all systems.
-# In the future, some of these should be built conditionally.
-#
# link order is important here
+#
EXTRA_CFLAGS += -Idrivers/ide
-ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o
+ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
+ ide-taskfile.o ide-park.o ide-pio-blacklist.o
# core IDE code
+ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
+ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o
ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
+ide-core-$(CONFIG_BLK_DEV_IDEDMA_SFF) += ide-dma-sff.o
ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o
ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
-obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o
+obj-$(CONFIG_IDE) += ide-core.o
ifeq ($(CONFIG_IDE_ARM), y)
ide-arm-core-y += arm/ide_arm.o
obj-y += ide-arm-core.o
endif
-obj-$(CONFIG_BLK_DEV_IDE) += legacy/ pci/
+obj-$(CONFIG_IDE) += legacy/ pci/
obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o
@@ -35,17 +32,24 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y)
obj-y += cmd640-core.o
endif
-obj-$(CONFIG_BLK_DEV_IDE) += ppc/
+obj-$(CONFIG_IDE) += ppc/
obj-$(CONFIG_IDE_H8300) += h8300/
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
+ide-disk_mod-y += ide-disk.o ide-disk_ioctl.o
ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
+ide-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o
-obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o
+ifeq ($(CONFIG_IDE_PROC_FS), y)
+ ide-disk_mod-y += ide-disk_proc.o
+ ide-floppy_mod-y += ide-floppy_proc.o
+endif
+
+obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk_mod.o
obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o
+obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy_mod.o
obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
-obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
ifeq ($(CONFIG_BLK_DEV_IDECS), y)
ide-cs-core-y += legacy/ide-cs.o
@@ -57,10 +61,4 @@ ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
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
+obj-$(CONFIG_IDE) += arm/ mips/
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 061456914ca..76bdc9a27f6 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -10,7 +10,6 @@
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/errno.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
@@ -21,6 +20,8 @@
#include <asm/dma.h>
#include <asm/ecard.h>
+#define DRV_NAME "icside"
+
#define ICS_IDENT_OFFSET 0x2280
#define ICS_ARCIN_V5_INTRSTAT 0x0000
@@ -68,8 +69,9 @@ struct icside_state {
unsigned int enabled;
void __iomem *irq_port;
void __iomem *ioc_base;
+ unsigned int sel;
unsigned int type;
- ide_hwif_t *hwif[2];
+ struct ide_host *host;
};
#define ICS_TYPE_A3IN 0
@@ -165,7 +167,8 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = {
static void icside_maskproc(ide_drive_t *drive, int mask)
{
ide_hwif_t *hwif = HWIF(drive);
- struct icside_state *state = hwif->hwif_data;
+ struct expansion_card *ec = ECARD_DEV(hwif->dev);
+ struct icside_state *state = ecard_get_drvdata(ec);
unsigned long flags;
local_irq_save(flags);
@@ -261,8 +264,8 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
* If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
* take care to note the values in the ID...
*/
- if (use_dma_info && drive->id->eide_dma_time > cycle_time)
- cycle_time = drive->id->eide_dma_time;
+ if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
+ cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
drive->drive_data = cycle_time;
@@ -308,6 +311,7 @@ static int icside_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct expansion_card *ec = ECARD_DEV(hwif->dev);
+ struct icside_state *state = ecard_get_drvdata(ec);
struct request *rq = hwif->hwgroup->rq;
unsigned int dma_mode;
@@ -331,7 +335,7 @@ static int icside_dma_setup(ide_drive_t *drive)
/*
* Route the DMA signals to the correct interface.
*/
- writeb(hwif->select_data, hwif->config_data);
+ writeb(state->sel | hwif->channel, state->ioc_base);
/*
* Select the correct timing for this drive.
@@ -359,7 +363,8 @@ static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
static int icside_dma_test_irq(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 icside_state *state = ecard_get_drvdata(ec);
return readb(state->irq_port +
(hwif->channel ?
@@ -367,23 +372,6 @@ static int icside_dma_test_irq(ide_drive_t *drive)
ICS_ARCIN_V6_INTRSTAT_1)) & 1;
}
-static void icside_dma_timeout(ide_drive_t *drive)
-{
- printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-
- if (icside_dma_test_irq(drive))
- return;
-
- ide_dump_status(drive, "DMA timeout", ide_read_status(drive));
-
- icside_dma_end(drive);
-}
-
-static void icside_dma_lost_irq(ide_drive_t *drive)
-{
- printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-}
-
static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
{
hwif->dmatable_cpu = NULL;
@@ -399,8 +387,8 @@ static const struct ide_dma_ops icside_v6_dma_ops = {
.dma_start = icside_dma_start,
.dma_end = icside_dma_end,
.dma_test_irq = icside_dma_test_irq,
- .dma_timeout = icside_dma_timeout,
- .dma_lost_irq = icside_dma_lost_irq,
+ .dma_timeout = ide_dma_timeout,
+ .dma_lost_irq = ide_dma_lost_irq,
};
#else
#define icside_v6_dma_ops NULL
@@ -411,44 +399,33 @@ static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
return -EOPNOTSUPP;
}
-static ide_hwif_t *
-icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec)
+static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
+ struct cardinfo *info, struct expansion_card *ec)
{
unsigned long port = (unsigned long)base + info->dataoffset;
- ide_hwif_t *hwif;
- hwif = ide_find_port();
- if (hwif) {
- /*
- * Ensure we're using MMIO
- */
- default_hwif_mmiops(hwif);
-
- hwif->io_ports.data_addr = port;
- hwif->io_ports.error_addr = port + (1 << info->stepping);
- hwif->io_ports.nsect_addr = port + (2 << info->stepping);
- hwif->io_ports.lbal_addr = port + (3 << info->stepping);
- hwif->io_ports.lbam_addr = port + (4 << info->stepping);
- hwif->io_ports.lbah_addr = port + (5 << info->stepping);
- hwif->io_ports.device_addr = port + (6 << info->stepping);
- hwif->io_ports.status_addr = port + (7 << info->stepping);
- hwif->io_ports.ctl_addr =
- (unsigned long)base + info->ctrloffset;
- hwif->irq = ec->irq;
- hwif->chipset = ide_acorn;
- hwif->gendev.parent = &ec->dev;
- hwif->dev = &ec->dev;
- }
-
- return hwif;
+ hw->io_ports.data_addr = port;
+ hw->io_ports.error_addr = port + (1 << info->stepping);
+ hw->io_ports.nsect_addr = port + (2 << info->stepping);
+ hw->io_ports.lbal_addr = port + (3 << info->stepping);
+ hw->io_ports.lbam_addr = port + (4 << info->stepping);
+ hw->io_ports.lbah_addr = port + (5 << info->stepping);
+ hw->io_ports.device_addr = port + (6 << info->stepping);
+ hw->io_ports.status_addr = port + (7 << info->stepping);
+ hw->io_ports.ctl_addr = (unsigned long)base + info->ctrloffset;
+
+ hw->irq = ec->irq;
+ hw->dev = &ec->dev;
+ hw->chipset = ide_acorn;
}
static int __init
icside_register_v5(struct icside_state *state, struct expansion_card *ec)
{
- ide_hwif_t *hwif;
void __iomem *base;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int ret;
base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base)
@@ -466,17 +443,25 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
*/
icside_irqdisable_arcin_v5(ec, 0);
- hwif = icside_setup(base, &icside_cardinfo_v5, ec);
- if (!hwif)
+ icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
+
+ host = ide_host_alloc(NULL, hws);
+ if (host == NULL)
return -ENODEV;
- state->hwif[0] = hwif;
+ state->host = host;
- idx[0] = hwif->index;
+ ecard_set_drvdata(ec, state);
- ide_device_add(idx, NULL);
+ ret = ide_host_register(host, NULL, hws);
+ if (ret)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
+ ecard_set_drvdata(ec, NULL);
+ return ret;
}
static const struct ide_port_info icside_v6_port_info __initdata = {
@@ -491,11 +476,11 @@ static const struct ide_port_info icside_v6_port_info __initdata = {
static int __init
icside_register_v6(struct icside_state *state, struct expansion_card *ec)
{
- ide_hwif_t *hwif, *mate;
void __iomem *ioc_base, *easi_base;
+ struct ide_host *host;
unsigned int sel = 0;
int ret;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL };
struct ide_port_info d = icside_v6_port_info;
ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
@@ -525,48 +510,41 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
state->irq_port = easi_base;
state->ioc_base = ioc_base;
+ state->sel = sel;
/*
* Be on the safe side - disable interrupts
*/
icside_irqdisable_arcin_v6(ec, 0);
- /*
- * Find and register the interfaces.
- */
- hwif = icside_setup(easi_base, &icside_cardinfo_v6_1, ec);
- mate = icside_setup(easi_base, &icside_cardinfo_v6_2, ec);
-
- if (!hwif || !mate) {
- ret = -ENODEV;
- goto out;
- }
+ icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
+ icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
- state->hwif[0] = hwif;
- state->hwif[1] = mate;
+ host = ide_host_alloc(&d, hws);
+ if (host == NULL)
+ return -ENODEV;
- hwif->hwif_data = state;
- hwif->config_data = (unsigned long)ioc_base;
- hwif->select_data = sel;
+ state->host = host;
- mate->hwif_data = state;
- mate->config_data = (unsigned long)ioc_base;
- mate->select_data = sel | 1;
+ ecard_set_drvdata(ec, state);
- if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
+ if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
d.init_dma = icside_dma_init;
d.port_ops = &icside_v6_port_ops;
d.dma_ops = NULL;
}
- idx[0] = hwif->index;
- idx[1] = mate->index;
-
- ide_device_add(idx, &d);
+ ret = ide_host_register(host, NULL, hws);
+ if (ret)
+ goto err_free;
return 0;
-
- out:
+err_free:
+ ide_host_free(host);
+ if (d.dma_ops)
+ free_dma(ec->dma);
+ ecard_set_drvdata(ec, NULL);
+out:
return ret;
}
@@ -627,10 +605,8 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
break;
}
- if (ret == 0) {
- ecard_set_drvdata(ec, state);
+ if (ret == 0)
goto out;
- }
kfree(state);
release:
@@ -714,8 +690,14 @@ static int __init icside_init(void)
return ecard_register_driver(&icside_driver);
}
+static void __exit icside_exit(void);
+{
+ ecard_unregister_driver(&icside_driver);
+}
+
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ICS IDE driver");
module_init(icside_init);
+module_exit(icside_exit);
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
index 2f311da4c96..f728f2927b5 100644
--- a/drivers/ide/arm/ide_arm.c
+++ b/drivers/ide/arm/ide_arm.c
@@ -11,13 +11,12 @@
#include <linux/init.h>
#include <linux/ide.h>
-#include <asm/mach-types.h>
#include <asm/irq.h>
#define DRV_NAME "ide_arm"
#ifdef CONFIG_ARCH_CLPS7500
-# include <asm/arch/hardware.h>
+# include <mach/hardware.h>
#
# define IDE_ARM_IO (ISASLOT_IO + 0x1f0)
# define IDE_ARM_IRQ IRQ_ISA_14
@@ -28,10 +27,8 @@
static int __init ide_arm_init(void)
{
- ide_hwif_t *hwif;
- hw_regs_t hw;
unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!request_region(base, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -51,15 +48,7 @@ static int __init ide_arm_init(void)
hw.irq = IDE_ARM_IRQ;
hw.chipset = ide_generic;
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
- }
-
- return 0;
+ return ide_host_add(NULL, hws, NULL);
}
module_init(ide_arm_init);
diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
index cc24803fadf..122ed3c072f 100644
--- a/drivers/ide/arm/palm_bk3710.c
+++ b/drivers/ide/arm/palm_bk3710.c
@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -74,20 +73,17 @@ struct palm_bk3710_udmatiming {
#define BK3710_IORDYTMP 0x78
#define BK3710_IORDYTMS 0x7C
-#include "../ide-timing.h"
-
-static long ide_palm_clk;
+static unsigned ideclk_period; /* in nanoseconds */
static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
{160, 240}, /* UDMA Mode 0 */
{125, 160}, /* UDMA Mode 1 */
{100, 120}, /* UDMA Mode 2 */
{100, 90}, /* UDMA Mode 3 */
- {85, 60}, /* UDMA Mode 4 */
+ {100, 60}, /* UDMA Mode 4 */
+ {85, 40}, /* UDMA Mode 5 */
};
-static struct clk *ideclkp;
-
static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
unsigned int mode)
{
@@ -97,10 +93,10 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
/* DMA Data Setup */
t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
- ide_palm_clk) - 1;
- tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1;
+ ideclk_period) - 1;
+ tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
- ide_palm_clk) - 1;
+ ideclk_period) - 1;
/* udmatim Register */
val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
@@ -141,8 +137,8 @@ static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
cycletime = max_t(int, t->cycle, min_cycle);
/* DMA Data Setup */
- t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
- td = DIV_ROUND_UP(t->active, ide_palm_clk);
+ t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+ td = DIV_ROUND_UP(t->active, ideclk_period);
tkw = t0 - td - 1;
td -= 1;
@@ -168,9 +164,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
struct ide_timing *t;
/* PIO Data Setup */
- t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
+ t0 = DIV_ROUND_UP(cycletime, ideclk_period);
t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
- ide_palm_clk);
+ ideclk_period);
t2i = t0 - t2 - 1;
t2 -= 1;
@@ -183,7 +179,7 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
val32 |= (t2i << (dev ? 8 : 0));
writel(val32, base + BK3710_DATRCVR);
- if (mate && mate->present) {
+ if (mate) {
u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
if (mode2 < mode)
@@ -192,8 +188,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
/* TASKFILE Setup */
t = ide_timing_find_mode(XFER_PIO_0 + mode);
- t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk);
- t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk);
+ t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
+ t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
t2i = t0 - t2 - 1;
t2 -= 1;
@@ -216,7 +212,8 @@ static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
palm_bk3710_setudmamode(base, is_slave,
xferspeed - XFER_UDMA_0);
} else {
- palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
+ palm_bk3710_setdmamode(base, is_slave,
+ drive->id[ATA_ID_EIDE_DMA_MIN],
xferspeed);
}
}
@@ -232,7 +229,7 @@ static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
* Obtain the drive PIO data for tuning the Palm Chip registers
*/
cycle_time = ide_pio_cycle_time(drive, pio);
- mate = ide_get_paired_drive(drive);
+ mate = ide_get_pair_dev(drive);
palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
}
@@ -312,7 +309,7 @@ static void __devinit palm_bk3710_chipinit(void __iomem *base)
palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
}
-static u8 __devinit palm_bk3710_cable_detect(ide_hwif_t *hwif)
+static u8 palm_bk3710_cable_detect(ide_hwif_t *hwif)
{
return ATA_CBL_PATA80;
}
@@ -320,15 +317,14 @@ static u8 __devinit palm_bk3710_cable_detect(ide_hwif_t *hwif)
static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
const struct ide_port_info *d)
{
- unsigned long base =
- hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
-
printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
+
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
@@ -339,33 +335,30 @@ static const struct ide_port_ops palm_bk3710_ports_ops = {
.cable_detect = palm_bk3710_cable_detect,
};
-static const struct ide_port_info __devinitdata palm_bk3710_port_info = {
+static struct ide_port_info __devinitdata palm_bk3710_port_info = {
.init_dma = palm_bk3710_init_dma,
.port_ops = &palm_bk3710_ports_ops,
.host_flags = IDE_HFLAG_MMIO,
.pio_mask = ATA_PIO4,
- .udma_mask = ATA_UDMA4, /* (input clk 99MHz) */
.mwdma_mask = ATA_MWDMA2,
};
-static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+static int __init palm_bk3710_probe(struct platform_device *pdev)
{
- struct clk *clkp;
+ struct clk *clk;
struct resource *mem, *irq;
- ide_hwif_t *hwif;
- unsigned long base;
- int i;
- hw_regs_t hw;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-
- clkp = clk_get(NULL, "IDECLK");
- if (IS_ERR(clkp))
+ unsigned long base, rate;
+ int i, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+ clk = clk_get(&pdev->dev, "IDECLK");
+ if (IS_ERR(clk))
return -ENODEV;
- ideclkp = clkp;
- clk_enable(ideclkp);
- ide_palm_clk = clk_get_rate(ideclkp)/100000;
- ide_palm_clk = (10000/ide_palm_clk) + 1;
+ clk_enable(clk);
+ rate = clk_get_rate(clk);
+ ideclk_period = 1000000000UL / rate;
+
/* Register the IDE interface with Linux ATA Interface */
memset(&hw, 0, sizeof(hw));
@@ -396,28 +389,20 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
hw.io_ports_array[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i;
hw.io_ports.ctl_addr = base + IDE_PALM_ATA_PRI_CTL_OFFSET;
hw.irq = irq->start;
+ hw.dev = &pdev->dev;
hw.chipset = ide_palm3710;
- hwif = ide_find_port();
- if (hwif == NULL)
- goto out;
-
- i = hwif->index;
-
- ide_init_port_data(hwif, i);
- ide_init_port_hw(hwif, &hw);
+ palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
+ ATA_UDMA5;
- hwif->mmio = 1;
- default_hwif_mmiops(hwif);
-
- idx[0] = i;
-
- ide_device_add(idx, &palm_bk3710_port_info);
+ rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
+ if (rc)
+ goto out;
return 0;
out:
printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
- return -ENODEV;
+ return rc;
}
/* work with hotplug and coldplug */
@@ -428,13 +413,11 @@ static struct platform_driver platform_bk_driver = {
.name = "palm_bk3710",
.owner = THIS_MODULE,
},
- .probe = palm_bk3710_probe,
- .remove = NULL,
};
static int __init palm_bk3710_init(void)
{
- return platform_driver_register(&platform_bk_driver);
+ return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe);
}
module_init(palm_bk3710_init);
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 1747b235877..78d27d9ae43 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -11,6 +11,10 @@
#include <asm/ecard.h>
+static struct const ide_port_info rapide_port_info = {
+ .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+};
+
static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
void __iomem *ctrl, unsigned int sz, int irq)
{
@@ -28,11 +32,10 @@ static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
static int __devinit
rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
{
- ide_hwif_t *hwif;
void __iomem *base;
+ struct ide_host *host;
int ret;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
ret = ecard_request_resources(ec);
if (ret)
@@ -44,25 +47,17 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
goto release;
}
- hwif = ide_find_port();
- if (hwif) {
- 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);
+ memset(&hw, 0, sizeof(hw));
+ rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
+ hw.chipset = ide_generic;
+ hw.dev = &ec->dev;
- hwif->host_flags = IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
+ ret = ide_host_add(&rapide_port_info, hws, &host);
+ if (ret)
+ goto release;
- ecard_set_drvdata(ec, hwif);
- goto out;
- }
+ ecard_set_drvdata(ec, host);
+ goto out;
release:
ecard_release_resources(ec);
@@ -72,11 +67,11 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit rapide_remove(struct expansion_card *ec)
{
- ide_hwif_t *hwif = ecard_get_drvdata(ec);
+ struct ide_host *host = ecard_get_drvdata(ec);
ecard_set_drvdata(ec, NULL);
- ide_unregister(hwif);
+ ide_host_remove(host);
ecard_release_resources(ec);
}
@@ -100,7 +95,13 @@ static int __init rapide_init(void)
return ecard_register_driver(&rapide_driver);
}
+static void __exit rapide_exit(void)
+{
+ ecard_unregister_driver(&rapide_driver);
+}
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Yellowstone RAPIDE driver");
module_init(rapide_init);
+module_exit(rapide_exit);
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index ecf53bb0d2a..e2cdd2e9cde 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -8,6 +8,8 @@
#include <asm/io.h>
#include <asm/irq.h>
+#define DRV_NAME "ide-h8300"
+
#define bswap(d) \
({ \
u16 r; \
@@ -52,8 +54,6 @@ static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
- ide_set_irq(drive, 1);
-
if (task->tf_flags & IDE_TFLAG_OUT_DATA)
mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr);
@@ -80,7 +80,7 @@ static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
- outb((tf->device & HIHI) | drive->select.all,
+ outb((tf->device & HIHI) | drive->select,
io_ports->device_addr);
}
@@ -98,8 +98,10 @@ static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
}
/* be sure we're looking at the low order bits */
- outb(drive->ctl & ~0x80, io_ports->ctl_addr);
+ outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -112,7 +114,7 @@ static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
tf->device = inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
- outb(drive->ctl | 0x80, io_ports->ctl_addr);
+ outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = inb(io_ports->feature_addr);
@@ -153,6 +155,21 @@ static void h8300_output_data(ide_drive_t *drive, struct request *rq,
mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
+static const struct ide_tp_ops h8300_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = h8300_tf_load,
+ .tf_read = h8300_tf_read,
+
+ .input_data = h8300_input_data,
+ .output_data = h8300_output_data,
+};
+
#define H8300_IDE_GAP (2)
static inline void hw_setup(hw_regs_t *hw)
@@ -167,23 +184,16 @@ static inline void hw_setup(hw_regs_t *hw)
hw->chipset = ide_generic;
}
-static inline void hwif_setup(ide_hwif_t *hwif)
-{
- default_hwif_iops(hwif);
-
- hwif->tf_load = h8300_tf_load;
- hwif->tf_read = h8300_tf_read;
-
- hwif->input_data = h8300_input_data;
- hwif->output_data = h8300_output_data;
-}
+static const struct ide_port_info h8300_port_info = {
+ .tp_ops = &h8300_tp_ops,
+ .host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
+};
static int __init h8300_ide_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
- int index;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+ printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
goto out_busy;
@@ -194,24 +204,7 @@ static int __init h8300_ide_init(void)
hw_setup(&hw);
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
- return -ENOENT;
- }
-
- index = hwif->index;
- ide_init_port_data(hwif, index);
- ide_init_port_hw(hwif, &hw);
- hwif_setup(hwif);
- hwif->host_flags = IDE_HFLAG_NO_IO_32BIT;
- printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index);
-
- idx[0] = index;
-
- ide_device_add(idx, NULL);
-
- return 0;
+ return ide_host_add(&h8300_port_info, hws, NULL);
out_busy:
printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 9d3601fa568..244a8a052ce 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -60,15 +60,15 @@ struct ide_acpi_hwif_link {
#define DEBPRINT(fmt, args...) do {} while (0)
#endif /* DEBUGGING */
-int ide_noacpi;
+static int ide_noacpi;
module_param_named(noacpi, ide_noacpi, bool, 0);
MODULE_PARM_DESC(noacpi, "disable IDE ACPI support");
-int ide_acpigtf;
+static int ide_acpigtf;
module_param_named(acpigtf, ide_acpigtf, bool, 0);
MODULE_PARM_DESC(acpigtf, "enable IDE ACPI _GTF support");
-int ide_acpionboot;
+static int ide_acpionboot;
module_param_named(acpionboot, ide_acpionboot, bool, 0);
MODULE_PARM_DESC(acpionboot, "call IDE ACPI methods on boot");
@@ -290,7 +290,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
hwif->name, dev->bus_id, port, hwif->channel);
- if (!drive->present) {
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) {
DEBPRINT("%s drive %d:%d not present\n",
hwif->name, hwif->channel, port);
goto out;
@@ -420,8 +420,9 @@ static int do_drive_set_taskfiles(ide_drive_t *drive,
DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn);
- if (!drive->present)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
goto out;
+
if (!gtf_count) /* shouldn't be here */
goto out;
@@ -584,7 +585,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
* This function executes the _STM ACPI method for the target channel.
*
* _STM requires Identify Drive data, which has to passed as an argument.
- * Unfortunately hd_driveid is a mangled version which we can't readily
+ * Unfortunately drive->id is a mangled version which we can't readily
* use; hence we'll get the information afresh.
*/
void ide_acpi_push_timing(ide_hwif_t *hwif)
@@ -614,10 +615,10 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
in_params[0].buffer.length = sizeof(struct GTM_buffer);
in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm;
in_params[1].type = ACPI_TYPE_BUFFER;
- in_params[1].buffer.length = sizeof(struct hd_driveid);
+ in_params[1].buffer.length = sizeof(ATA_ID_WORDS * 2);
in_params[1].buffer.pointer = (u8 *)&master->idbuff;
in_params[2].type = ACPI_TYPE_BUFFER;
- in_params[2].buffer.length = sizeof(struct hd_driveid);
+ in_params[2].buffer.length = sizeof(ATA_ID_WORDS * 2);
in_params[2].buffer.pointer = (u8 *)&slave->idbuff;
/* Output buffer: _STM has no output */
@@ -660,7 +661,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
if (!drive->acpidata->obj_handle)
drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
- if (drive->acpidata->obj_handle && drive->present) {
+ if (drive->acpidata->obj_handle &&
+ (drive->dev_flags & IDE_DFLAG_PRESENT)) {
acpi_bus_set_power(drive->acpidata->obj_handle,
on? ACPI_STATE_D0: ACPI_STATE_D3);
}
@@ -720,7 +722,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
memset(drive->acpidata, 0, sizeof(*drive->acpidata));
- if (!drive->present)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
@@ -745,7 +747,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
for (i = 0; i < MAX_DRIVES; i++) {
drive = &hwif->drives[i];
- if (drive->present)
+ if (drive->dev_flags & IDE_DFLAG_PRESENT)
/* Execute ACPI startup code */
ide_acpi_exec_tfs(drive);
}
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
new file mode 100644
index 00000000000..2e305714c20
--- /dev/null
+++ b/drivers/ide/ide-atapi.c
@@ -0,0 +1,597 @@
+/*
+ * ATAPI support.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <scsi/scsi.h>
+
+#ifdef DEBUG
+#define debug_log(fmt, args...) \
+ printk(KERN_INFO "ide: " fmt, ## args)
+#else
+#define debug_log(fmt, args...) do {} while (0)
+#endif
+
+/*
+ * Check whether we can support a device,
+ * based on the ATAPI IDENTIFY command results.
+ */
+int ide_check_atapi_device(ide_drive_t *drive, const char *s)
+{
+ u16 *id = drive->id;
+ u8 gcw[2], protocol, device_type, removable, drq_type, packet_size;
+
+ *((u16 *)&gcw) = id[ATA_ID_CONFIG];
+
+ protocol = (gcw[1] & 0xC0) >> 6;
+ device_type = gcw[1] & 0x1F;
+ removable = (gcw[0] & 0x80) >> 7;
+ drq_type = (gcw[0] & 0x60) >> 5;
+ packet_size = gcw[0] & 0x03;
+
+#ifdef CONFIG_PPC
+ /* kludge for Apple PowerBook internal zip */
+ if (drive->media == ide_floppy && device_type == 5 &&
+ !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") &&
+ strstr((char *)&id[ATA_ID_PROD], "ZIP"))
+ device_type = 0;
+#endif
+
+ if (protocol != 2)
+ printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n",
+ s, drive->name, protocol);
+ else if ((drive->media == ide_floppy && device_type != 0) ||
+ (drive->media == ide_tape && device_type != 1))
+ printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n",
+ s, drive->name, device_type);
+ else if (removable == 0)
+ printk(KERN_ERR "%s: %s: the removable flag is not set\n",
+ s, drive->name);
+ else if (drive->media == ide_floppy && drq_type == 3)
+ printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not "
+ "supported\n", s, drive->name, drq_type);
+ else if (packet_size != 0)
+ printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 "
+ "bytes\n", s, drive->name, packet_size);
+ else
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_check_atapi_device);
+
+/* PIO data transfer routine using the scatter gather table. */
+int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned int bcount, int write)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
+ struct scatterlist *sg = pc->sg;
+ char *buf;
+ int count, done = 0;
+
+ while (bcount) {
+ count = min(sg->length - pc->b_count, bcount);
+
+ if (PageHighMem(sg_page(sg))) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+ xf(drive, NULL, buf + pc->b_count, count);
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
+ } else {
+ buf = sg_virt(sg);
+ xf(drive, NULL, buf + pc->b_count, count);
+ }
+
+ bcount -= count;
+ pc->b_count += count;
+ done += count;
+
+ if (pc->b_count == sg->length) {
+ if (!--pc->sg_cnt)
+ break;
+ pc->sg = sg = sg_next(sg);
+ pc->b_count = 0;
+ }
+ }
+
+ if (bcount) {
+ printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name,
+ bcount, write ? "padding with zeros"
+ : "discarding data");
+ ide_pad_transfer(drive, write, bcount);
+ }
+
+ return done;
+}
+EXPORT_SYMBOL_GPL(ide_io_buffers);
+
+void ide_init_pc(struct ide_atapi_pc *pc)
+{
+ memset(pc, 0, sizeof(*pc));
+ pc->buf = pc->pc_buf;
+ pc->buf_size = IDE_PC_BUFFER_SIZE;
+}
+EXPORT_SYMBOL_GPL(ide_init_pc);
+
+/*
+ * 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 ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
+ struct ide_atapi_pc *pc, struct request *rq)
+{
+ blk_rq_init(NULL, rq);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd_flags |= REQ_PREEMPT;
+ rq->buffer = (char *)pc;
+ rq->rq_disk = disk;
+ memcpy(rq->cmd, pc->c, 12);
+ if (drive->media == ide_tape)
+ rq->cmd[13] = REQ_IDETAPE_PC1;
+ ide_do_drive_cmd(drive, rq);
+}
+
+/*
+ * Add a special packet command request to the tail of the request queue,
+ * and wait for it to be serviced.
+ */
+int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
+ struct ide_atapi_pc *pc)
+{
+ struct request *rq;
+ int error;
+
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->buffer = (char *)pc;
+ memcpy(rq->cmd, pc->c, 12);
+ if (drive->media == ide_tape)
+ rq->cmd[13] = REQ_IDETAPE_PC1;
+ error = blk_execute_rq(drive->queue, disk, rq, 0);
+ blk_put_request(rq);
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
+
+int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk)
+{
+ struct ide_atapi_pc pc;
+
+ ide_init_pc(&pc);
+ pc.c[0] = TEST_UNIT_READY;
+
+ return ide_queue_pc_tail(drive, disk, &pc);
+}
+EXPORT_SYMBOL_GPL(ide_do_test_unit_ready);
+
+int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start)
+{
+ struct ide_atapi_pc pc;
+
+ ide_init_pc(&pc);
+ pc.c[0] = START_STOP;
+ pc.c[4] = start;
+
+ if (drive->media == ide_tape)
+ pc.flags |= PC_FLAG_WAIT_FOR_DSC;
+
+ return ide_queue_pc_tail(drive, disk, &pc);
+}
+EXPORT_SYMBOL_GPL(ide_do_start_stop);
+
+int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
+{
+ struct ide_atapi_pc pc;
+
+ if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK)
+ return 0;
+
+ ide_init_pc(&pc);
+ pc.c[0] = ALLOW_MEDIUM_REMOVAL;
+ pc.c[4] = on;
+
+ return ide_queue_pc_tail(drive, disk, &pc);
+}
+EXPORT_SYMBOL_GPL(ide_set_media_lock);
+
+void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc)
+{
+ ide_init_pc(pc);
+ pc->c[0] = REQUEST_SENSE;
+ if (drive->media == ide_floppy) {
+ pc->c[4] = 255;
+ pc->req_xfer = 18;
+ } else {
+ pc->c[4] = 20;
+ pc->req_xfer = 20;
+ }
+}
+EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
+
+/*
+ * 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.
+ */
+void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
+{
+ struct request *rq = &drive->request_sense_rq;
+ struct ide_atapi_pc *pc = &drive->request_sense_pc;
+
+ (void)ide_read_error(drive);
+ ide_create_request_sense_cmd(drive, pc);
+ if (drive->media == ide_tape)
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
+ ide_queue_pc_head(drive, disk, pc, rq);
+}
+EXPORT_SYMBOL_GPL(ide_retry_pc);
+
+int ide_scsi_expiry(ide_drive_t *drive)
+{
+ struct ide_atapi_pc *pc = drive->pc;
+
+ debug_log("%s called for %lu at %lu\n", __func__,
+ pc->scsi_cmd->serial_number, jiffies);
+
+ pc->flags |= PC_FLAG_TIMEDOUT;
+
+ return 0; /* we do not want the IDE subsystem to retry */
+}
+EXPORT_SYMBOL_GPL(ide_scsi_expiry);
+
+/*
+ * This is the usual interrupt handler which will be called during a packet
+ * command. We will transfer some of the data (as requested by the drive)
+ * and will re-point interrupt handler to us.
+ */
+static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
+{
+ struct ide_atapi_pc *pc = drive->pc;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ xfer_func_t *xferfunc;
+ ide_expiry_t *expiry;
+ unsigned int timeout, temp;
+ u16 bcount;
+ u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0;
+
+ debug_log("Enter %s - interrupt handler\n", __func__);
+
+ if (scsi) {
+ timeout = ide_scsi_get_timeout(pc);
+ expiry = ide_scsi_expiry;
+ } else {
+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+ : WAIT_TAPE_CMD;
+ expiry = NULL;
+ }
+
+ if (pc->flags & PC_FLAG_TIMEDOUT) {
+ drive->pc_callback(drive, 0);
+ return ide_stopped;
+ }
+
+ /* Clear the interrupt */
+ stat = tp_ops->read_status(hwif);
+
+ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
+ if (hwif->dma_ops->dma_end(drive) ||
+ (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) {
+ if (drive->media == ide_floppy && !scsi)
+ printk(KERN_ERR "%s: DMA %s error\n",
+ drive->name, rq_data_dir(pc->rq)
+ ? "write" : "read");
+ pc->flags |= PC_FLAG_DMA_ERROR;
+ } else {
+ pc->xferred = pc->req_xfer;
+ if (drive->pc_update_buffers)
+ drive->pc_update_buffers(drive, pc);
+ }
+ debug_log("%s: DMA finished\n", drive->name);
+ }
+
+ /* No more interrupts */
+ if ((stat & ATA_DRQ) == 0) {
+ debug_log("Packet command completed, %d bytes transferred\n",
+ pc->xferred);
+
+ pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+
+ local_irq_enable_in_hardirq();
+
+ if (drive->media == ide_tape && !scsi &&
+ (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE)
+ stat &= ~ATA_ERR;
+
+ if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) {
+ /* Error detected */
+ debug_log("%s: I/O error\n", drive->name);
+
+ if (drive->media != ide_tape || scsi) {
+ pc->rq->errors++;
+ if (scsi)
+ goto cmd_finished;
+ }
+
+ if (rq->cmd[0] == REQUEST_SENSE) {
+ printk(KERN_ERR "%s: I/O error in request sense"
+ " command\n", drive->name);
+ return ide_do_reset(drive);
+ }
+
+ debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
+
+ /* Retry operation */
+ ide_retry_pc(drive, rq->rq_disk);
+
+ /* queued, but not started */
+ return ide_stopped;
+ }
+cmd_finished:
+ pc->error = 0;
+
+ if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
+ dsc = 1;
+
+ /* Command finished - Call the callback function */
+ drive->pc_callback(drive, dsc);
+
+ return ide_stopped;
+ }
+
+ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
+ pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ printk(KERN_ERR "%s: The device wants to issue more interrupts "
+ "in DMA mode\n", drive->name);
+ ide_dma_off(drive);
+ return ide_do_reset(drive);
+ }
+
+ /* Get the number of bytes to transfer on this interrupt. */
+ ide_read_bcount_and_ireason(drive, &bcount, &ireason);
+
+ if (ireason & ATAPI_COD) {
+ printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
+ return ide_do_reset(drive);
+ }
+
+ if (((ireason & ATAPI_IO) == ATAPI_IO) ==
+ !!(pc->flags & PC_FLAG_WRITING)) {
+ /* Hopefully, we will never get here */
+ printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
+ "to %s!\n", drive->name,
+ (ireason & ATAPI_IO) ? "Write" : "Read",
+ (ireason & ATAPI_IO) ? "Read" : "Write");
+ return ide_do_reset(drive);
+ }
+
+ if (!(pc->flags & PC_FLAG_WRITING)) {
+ /* Reading - Check that we have enough space */
+ temp = pc->xferred + bcount;
+ if (temp > pc->req_xfer) {
+ if (temp > pc->buf_size) {
+ printk(KERN_ERR "%s: The device wants to send "
+ "us more data than expected - "
+ "discarding data\n",
+ drive->name);
+ if (scsi)
+ temp = pc->buf_size - pc->xferred;
+ else
+ temp = 0;
+ if (temp) {
+ if (pc->sg)
+ drive->pc_io_buffers(drive, pc,
+ temp, 0);
+ else
+ tp_ops->input_data(drive, NULL,
+ pc->cur_pos, temp);
+ printk(KERN_ERR "%s: transferred %d of "
+ "%d bytes\n",
+ drive->name,
+ temp, bcount);
+ }
+ pc->xferred += temp;
+ pc->cur_pos += temp;
+ ide_pad_transfer(drive, 0, bcount - temp);
+ goto next_irq;
+ }
+ debug_log("The device wants to send us more data than "
+ "expected - allowing transfer\n");
+ }
+ xferfunc = tp_ops->input_data;
+ } else
+ xferfunc = tp_ops->output_data;
+
+ if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
+ (drive->media == ide_tape && !scsi && pc->bh) ||
+ (scsi && pc->sg)) {
+ int done = drive->pc_io_buffers(drive, pc, bcount,
+ !!(pc->flags & PC_FLAG_WRITING));
+
+ /* FIXME: don't do partial completions */
+ if (drive->media == ide_floppy && !scsi)
+ ide_end_request(drive, 1, done >> 9);
+ } else
+ xferfunc(drive, NULL, pc->cur_pos, bcount);
+
+ /* Update the current position */
+ pc->xferred += bcount;
+ pc->cur_pos += bcount;
+
+ debug_log("[cmd %x] transferred %d bytes on that intr.\n",
+ rq->cmd[0], bcount);
+next_irq:
+ /* And set the interrupt handler again */
+ ide_set_handler(drive, ide_pc_intr, timeout, expiry);
+ return ide_started;
+}
+
+static u8 ide_read_ireason(ide_drive_t *drive)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_NSECT;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.nsect & 3;
+}
+
+static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
+{
+ int retries = 100;
+
+ while (retries-- && ((ireason & ATAPI_COD) == 0 ||
+ (ireason & ATAPI_IO))) {
+ printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
+ "a packet command, retrying\n", drive->name);
+ udelay(100);
+ ireason = ide_read_ireason(drive);
+ if (retries == 0) {
+ printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
+ "a packet command, ignoring\n",
+ drive->name);
+ ireason |= ATAPI_COD;
+ ireason &= ~ATAPI_IO;
+ }
+ }
+
+ return ireason;
+}
+
+static int ide_delayed_transfer_pc(ide_drive_t *drive)
+{
+ /* Send the actual packet */
+ drive->hwif->tp_ops->output_data(drive, NULL, drive->pc->c, 12);
+
+ /* Timeout for the packet command */
+ return WAIT_FLOPPY_CMD;
+}
+
+static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
+{
+ struct ide_atapi_pc *pc = drive->pc;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
+ ide_expiry_t *expiry;
+ unsigned int timeout;
+ ide_startstop_t startstop;
+ u8 ireason;
+
+ if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
+ printk(KERN_ERR "%s: Strange, packet command initiated yet "
+ "DRQ isn't asserted\n", drive->name);
+ return startstop;
+ }
+
+ ireason = ide_read_ireason(drive);
+ if (drive->media == ide_tape &&
+ (drive->dev_flags & IDE_DFLAG_SCSI) == 0)
+ ireason = ide_wait_ireason(drive, ireason);
+
+ if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
+ printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
+ "a packet command\n", drive->name);
+ return ide_do_reset(drive);
+ }
+
+ /*
+ * If necessary schedule the packet transfer to occur 'timeout'
+ * miliseconds later in ide_delayed_transfer_pc() after the device
+ * says it's ready for a packet.
+ */
+ if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
+ timeout = drive->pc_delay;
+ expiry = &ide_delayed_transfer_pc;
+ } else {
+ if (drive->dev_flags & IDE_DFLAG_SCSI) {
+ timeout = ide_scsi_get_timeout(pc);
+ expiry = ide_scsi_expiry;
+ } else {
+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+ : WAIT_TAPE_CMD;
+ expiry = NULL;
+ }
+ }
+
+ /* Set the interrupt routine */
+ ide_set_handler(drive, ide_pc_intr, timeout, expiry);
+
+ /* Begin DMA, if necessary */
+ if (pc->flags & PC_FLAG_DMA_OK) {
+ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
+ hwif->dma_ops->dma_start(drive);
+ }
+
+ /* Send the actual packet */
+ if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12);
+
+ return ide_started;
+}
+
+ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout,
+ ide_expiry_t *expiry)
+{
+ struct ide_atapi_pc *pc = drive->pc;
+ ide_hwif_t *hwif = drive->hwif;
+ u32 tf_flags;
+ u16 bcount;
+ u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI);
+
+ /* We haven't transferred any data yet */
+ pc->xferred = 0;
+ pc->cur_pos = pc->buf;
+
+ /* Request to transfer the entire buffer at once */
+ if (drive->media == ide_tape && scsi == 0)
+ bcount = pc->req_xfer;
+ else
+ bcount = min(pc->req_xfer, 63 * 1024);
+
+ if (pc->flags & PC_FLAG_DMA_ERROR) {
+ pc->flags &= ~PC_FLAG_DMA_ERROR;
+ ide_dma_off(drive);
+ }
+
+ if ((pc->flags & PC_FLAG_DMA_OK) &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA)) {
+ if (scsi)
+ hwif->sg_mapped = 1;
+ drive->dma = !hwif->dma_ops->dma_setup(drive);
+ if (scsi)
+ hwif->sg_mapped = 0;
+ }
+
+ if (!drive->dma)
+ pc->flags &= ~PC_FLAG_DMA_OK;
+
+ if (scsi)
+ tf_flags = 0;
+ else if (drive->media == ide_cdrom || drive->media == ide_optical)
+ tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
+ else
+ tf_flags = IDE_TFLAG_OUT_DEVICE;
+
+ ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
+
+ /* Issue the packet command */
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
+ ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,
+ timeout, NULL);
+ return ide_started;
+ } else {
+ ide_execute_pkt_cmd(drive);
+ return ide_transfer_pc(drive);
+ }
+}
+EXPORT_SYMBOL_GPL(ide_issue_pc);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 68e7f19dc03..3308b1cd3a3 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -23,6 +23,9 @@
* Documentation/ide/ChangeLog.ide-cd.1994-2004
*/
+#define DRV_NAME "ide-cd"
+#define PFX DRV_NAME ": "
+
#define IDECD_VERSION "5.00"
#include <linux/module.h>
@@ -50,31 +53,42 @@
#include "ide-cd.h"
-static DEFINE_MUTEX(idecd_ref_mutex);
+#define IDECD_DEBUG_LOG 1
-#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
+#if IDECD_DEBUG_LOG
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
+#else
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
+#endif
-#define ide_cd_g(disk) \
- container_of((disk)->private_data, struct cdrom_info, driver)
+static DEFINE_MUTEX(idecd_ref_mutex);
+
+static void ide_cd_release(struct kref *);
static struct cdrom_info *ide_cd_get(struct gendisk *disk)
{
struct cdrom_info *cd = NULL;
mutex_lock(&idecd_ref_mutex);
- cd = ide_cd_g(disk);
- if (cd)
- kref_get(&cd->kref);
+ cd = ide_drv_g(disk, cdrom_info);
+ if (cd) {
+ if (ide_device_get(cd->drive))
+ cd = NULL;
+ else
+ kref_get(&cd->kref);
+
+ }
mutex_unlock(&idecd_ref_mutex);
return cd;
}
-static void ide_cd_release(struct kref *);
-
static void ide_cd_put(struct cdrom_info *cd)
{
+ ide_drive_t *drive = cd->drive;
+
mutex_lock(&idecd_ref_mutex);
kref_put(&cd->kref, ide_cd_release);
+ ide_device_put(drive);
mutex_unlock(&idecd_ref_mutex);
}
@@ -85,10 +99,8 @@ static void ide_cd_put(struct cdrom_info *cd)
/* Mark that we've seen a media change and invalidate our internal buffers. */
static void cdrom_saw_media_change(ide_drive_t *drive)
{
- struct cdrom_info *cd = drive->driver_data;
-
- cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
- cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
+ drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
}
static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -96,6 +108,9 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
{
int log = 0;
+ ide_debug_log(IDE_DBG_SENSE, "Call %s, sense_key: 0x%x\n", __func__,
+ sense->sense_key);
+
if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
return 0;
@@ -144,6 +159,14 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
unsigned long bio_sectors;
struct cdrom_info *info = drive->driver_data;
+ ide_debug_log(IDE_DBG_SENSE, "Call %s, error_code: 0x%x, "
+ "sense_key: 0x%x\n", __func__, sense->error_code,
+ sense->sense_key);
+
+ if (failed_command)
+ ide_debug_log(IDE_DBG_SENSE, "%s: failed cmd: 0x%x\n",
+ __func__, failed_command->cmd[0]);
+
if (!cdrom_log_sense(drive, failed_command, sense))
return;
@@ -188,27 +211,21 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
ide_cd_log_error(drive->name, failed_command, sense);
}
-/* Initialize a ide-cd packet command request */
-void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
-{
- struct cdrom_info *cd = drive->driver_data;
-
- ide_init_drive_cmd(rq);
- rq->cmd_type = REQ_TYPE_ATA_PC;
- rq->rq_disk = cd->disk;
-}
-
static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
struct request *failed_command)
{
struct cdrom_info *info = drive->driver_data;
struct request *rq = &info->request_sense_request;
+ ide_debug_log(IDE_DBG_SENSE, "Call %s\n", __func__);
+
if (sense == NULL)
sense = &info->sense_data;
/* stuff the sense request in front of our current request */
- ide_cd_init_rq(drive, rq);
+ blk_rq_init(NULL, rq);
+ rq->cmd_type = REQ_TYPE_ATA_PC;
+ rq->rq_disk = info->disk;
rq->data = sense;
rq->cmd[0] = GPCMD_REQUEST_SENSE;
@@ -216,11 +233,16 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
rq->data_len = 18;
rq->cmd_type = REQ_TYPE_SENSE;
+ rq->cmd_flags |= REQ_PREEMPT;
/* NOTE! Save the failed command in "rq->buffer" */
rq->buffer = (void *) failed_command;
- (void) ide_do_drive_cmd(drive, rq, ide_preempt);
+ if (failed_command)
+ ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n",
+ failed_command->cmd[0]);
+
+ ide_do_drive_cmd(drive, rq);
}
static void cdrom_end_request(ide_drive_t *drive, int uptodate)
@@ -228,6 +250,10 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
struct request *rq = HWGROUP(drive)->rq;
int nsectors = rq->hard_cur_sectors;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s, cmd: 0x%x, uptodate: 0x%x, "
+ "nsectors: %d\n", __func__, rq->cmd[0], uptodate,
+ nsectors);
+
if (blk_sense_request(rq) && uptodate) {
/*
* For REQ_TYPE_SENSE, "rq->buffer" points to the original
@@ -270,6 +296,9 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
if (!nsectors)
nsectors = 1;
+ ide_debug_log(IDE_DBG_FUNC, "Exit %s, uptodate: 0x%x, nsectors: %d\n",
+ __func__, uptodate, nsectors);
+
ide_end_request(drive, uptodate, nsectors);
}
@@ -287,11 +316,12 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
*/
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
int stat, err, sense_key;
/* check for errors */
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat_ret)
*stat_ret = stat;
@@ -304,11 +334,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
sense_key = err >> 4;
if (rq == NULL) {
- printk(KERN_ERR "%s: missing rq in %s\n",
+ printk(KERN_ERR PFX "%s: missing rq in %s\n",
drive->name, __func__);
return 1;
}
+ ide_debug_log(IDE_DBG_RQ, "%s: stat: 0x%x, good_stat: 0x%x, "
+ "rq->cmd_type: 0x%x, err: 0x%x\n", __func__, stat,
+ good_stat, rq->cmd_type, err);
+
if (blk_sense_request(rq)) {
/*
* We got an error trying to get sense info from the drive
@@ -374,7 +408,8 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
cdrom_saw_media_change(drive);
/* fail the request */
- printk(KERN_ERR "%s: tray open\n", drive->name);
+ printk(KERN_ERR PFX "%s: tray open\n",
+ drive->name);
do_end_request = 1;
} else {
struct cdrom_info *info = drive->driver_data;
@@ -436,7 +471,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
ide_dump_status_no_sense(drive, "media error (blank)",
stat);
do_end_request = 1;
- } else if ((err & ~ABRT_ERR) != 0) {
+ } else if ((err & ~ATA_ABORTED) != 0) {
/* go to the default handler for other errors */
ide_error(drive, "cdrom_decode_status", stat);
return 1;
@@ -457,10 +492,10 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
* If we got a CHECK_CONDITION status, queue
* a request sense command.
*/
- if (stat & ERR_STAT)
+ if (stat & ATA_ERR)
cdrom_queue_request_sense(drive, NULL, NULL);
} else {
- blk_dump_rq_flags(rq, "ide-cd: bad rq");
+ blk_dump_rq_flags(rq, PFX "bad rq");
cdrom_end_request(drive, 0);
}
@@ -468,7 +503,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
return 1;
end_request:
- if (stat & ERR_STAT) {
+ if (stat & ATA_ERR) {
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
@@ -488,6 +523,9 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
struct request *rq = HWGROUP(drive)->rq;
unsigned long wait = 0;
+ ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__,
+ rq->cmd[0]);
+
/*
* Some commands are *slow* and normally take a long time to complete.
* Usually we can use the ATAPI "disconnect" to bypass this, but not all
@@ -504,7 +542,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
break;
default:
if (!(rq->cmd_flags & REQ_QUIET))
- printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n",
+ printk(KERN_INFO PFX "cmd 0x%x timed out\n",
rq->cmd[0]);
wait = 0;
break;
@@ -524,29 +562,25 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
int xferlen,
ide_handler_t *handler)
{
- ide_startstop_t startstop;
- struct cdrom_info *info = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
- /* wait for the controller to be idle */
- if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
- return startstop;
+ ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen);
/* FIXME: for Virtual DMA we must check harder */
- if (info->dma)
- info->dma = !hwif->dma_ops->dma_setup(drive);
+ if (drive->dma)
+ drive->dma = !hwif->dma_ops->dma_setup(drive);
/* set up the controller registers */
- ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
- IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
+ xferlen, drive->dma);
- if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/* waiting for CDB interrupt, not DMA yet. */
- if (info->dma)
+ if (drive->dma)
drive->waiting_for_dma = 0;
/* packet command */
- ide_execute_command(drive, WIN_PACKETCMD, handler,
+ ide_execute_command(drive, ATA_CMD_PACKET, handler,
ATAPI_WAIT_PC, cdrom_timer_expiry);
return ide_started;
} else {
@@ -569,26 +603,27 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
{
ide_hwif_t *hwif = drive->hwif;
int cmd_len;
- struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop;
- if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ ide_debug_log(IDE_DBG_PC, "Call %s\n", __func__);
+
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/*
* Here we should have been called after receiving an interrupt
* from the device. DRQ should how be set.
*/
/* check for errors */
- if (cdrom_decode_status(drive, DRQ_STAT, NULL))
+ if (cdrom_decode_status(drive, ATA_DRQ, NULL))
return ide_stopped;
/* ok, next interrupt will be DMA interrupt */
- if (info->dma)
+ if (drive->dma)
drive->waiting_for_dma = 1;
} else {
/* otherwise, we must wait for DRQ to get set */
- if (ide_wait_stat(&startstop, drive, DRQ_STAT,
- BUSY_STAT, WAIT_READY))
+ if (ide_wait_stat(&startstop, drive, ATA_DRQ,
+ ATA_BUSY, WAIT_READY))
return startstop;
}
@@ -601,38 +636,16 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
cmd_len = ATAPI_MIN_CDB_BYTES;
/* send the command to the device */
- hwif->output_data(drive, NULL, rq->cmd, cmd_len);
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
/* start the DMA if need be */
- if (info->dma)
+ if (drive->dma)
hwif->dma_ops->dma_start(drive);
return ide_started;
}
/*
- * 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, NULL, &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->input_data(drive, NULL, dum, sizeof(dum));
- nsects--;
- }
-}
-
-/*
* Check the contents of the interrupt reason register from the cdrom
* and attempt to recover if there are problems. Returns 0 if everything's
* ok; nonzero if the request has been terminated.
@@ -640,6 +653,11 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
int len, int ireason, int rw)
{
+ ide_hwif_t *hwif = drive->hwif;
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s, ireason: 0x%x, rw: 0x%x\n",
+ __func__, ireason, rw);
+
/*
* ireason == 0: the drive wants to receive data from us
* ireason == 2: the drive is expecting to transfer data to us
@@ -647,25 +665,22 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
if (ireason == (!rw << 1))
return 0;
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",
+ printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
drive->name, __func__);
- xf = rw ? hwif->output_data : hwif->input_data;
- ide_cd_pad_transfer(drive, xf, len);
+ ide_pad_transfer(drive, rw, len);
} else if (rw == 0 && ireason == 1) {
/*
* Some drives (ASUS) seem to tell us that status info is
* available. Just get it and ignore.
*/
- (void)ide_read_status(drive);
+ (void)hwif->tp_ops->read_status(hwif);
return 0;
} else {
/* drive wants a command packet, or invalid ireason... */
- printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
+ printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
drive->name, __func__, ireason);
}
@@ -682,20 +697,20 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
*/
static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
{
- struct cdrom_info *cd = drive->driver_data;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s, len: %d\n", __func__, len);
if ((len % SECTOR_SIZE) == 0)
return 0;
- printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
- drive->name, __func__, len);
+ printk(KERN_ERR PFX "%s: %s: Bad transfer size %d\n", drive->name,
+ __func__, len);
- if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
- printk(KERN_ERR " This drive is not supported by "
- "this version of the driver\n");
+ if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
+ printk(KERN_ERR PFX "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;
+ printk(KERN_ERR PFX "Trying to limit transfer sizes\n");
+ drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
}
return 1;
@@ -703,15 +718,11 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
-/*
- * 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_rw_cont(ide_drive_t *drive)
+static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
+ struct request *rq)
{
- struct request *rq = HWGROUP(drive)->rq;
+ ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd_flags: 0x%x\n", __func__,
+ rq->cmd_flags);
if (rq_data_dir(rq) == READ) {
unsigned short sectors_per_frame =
@@ -732,7 +743,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
/* sanity check... */
if (rq->current_nr_sectors !=
bio_cur_sectors(rq->bio)) {
- printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
+ printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n",
drive->name, __func__,
rq->current_nr_sectors);
cdrom_end_request(drive, 0);
@@ -741,14 +752,23 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
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;
+ return ide_started;
+}
+
+/*
+ * 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_rw_cont(ide_drive_t *drive)
+{
+ struct request *rq = drive->hwif->hwgroup->rq;
+
/* send the command to the drive and return */
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
@@ -763,23 +783,26 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
int stat;
static int retry = 10;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
if (cdrom_decode_status(drive, 0, &stat))
return ide_stopped;
- info->cd_flags |= IDE_CD_FLAG_SEEKING;
+ drive->atapi_flags |= IDE_AFLAG_SEEKING;
if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
if (--retry == 0)
- drive->dsc_overlap = 0;
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
}
return ide_stopped;
}
-static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
+static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
{
- struct request *rq = HWGROUP(drive)->rq;
sector_t frame = rq->sector;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
memset(rq->cmd, 0, BLK_MAX_CDB);
@@ -787,25 +810,24 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
rq->timeout = ATAPI_WAIT_PC;
- return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
}
-static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block)
+static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
{
- struct cdrom_info *info = drive->driver_data;
+ struct request *rq = drive->hwif->hwgroup->rq;
- info->dma = 0;
- info->start_seek = jiffies;
- return cdrom_start_packet_command(drive, 0,
- cdrom_start_seek_continuation);
+ return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
}
/*
* Fix up a possibly partially-processed request so that we can start it over
* entirely, or even put it back on the request queue.
*/
-static void restore_request(struct request *rq)
+static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
{
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
if (rq->buffer != bio_data(rq->bio)) {
sector_t n =
(rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
@@ -824,8 +846,11 @@ static void restore_request(struct request *rq)
/*
* All other packet commands.
*/
-static void ide_cd_request_sense_fixup(struct request *rq)
+static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
{
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
/*
* Some of the trailing request sense fields are optional,
* and some drives don't send them. Sigh.
@@ -838,34 +863,58 @@ static void ide_cd_request_sense_fixup(struct request *rq)
}
}
-int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
+int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
+ int write, void *buffer, unsigned *bufflen,
+ struct request_sense *sense, int timeout,
+ unsigned int cmd_flags)
{
- struct request_sense sense;
+ struct cdrom_info *info = drive->driver_data;
+ struct request_sense local_sense;
int retries = 10;
- unsigned int flags = rq->cmd_flags;
+ unsigned int flags = 0;
- if (rq->sense == NULL)
- rq->sense = &sense;
+ if (!sense)
+ sense = &local_sense;
+
+ ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x, "
+ "timeout: %d, cmd_flags: 0x%x\n", __func__, cmd[0], write,
+ timeout, cmd_flags);
/* start of retry loop */
do {
+ struct request *rq;
int error;
- unsigned long time = jiffies;
- rq->cmd_flags = flags;
- error = ide_do_drive_cmd(drive, rq, ide_wait);
- time = jiffies - time;
+ rq = blk_get_request(drive->queue, write, __GFP_WAIT);
+
+ memcpy(rq->cmd, cmd, BLK_MAX_CDB);
+ rq->cmd_type = REQ_TYPE_ATA_PC;
+ rq->sense = sense;
+ rq->cmd_flags |= cmd_flags;
+ rq->timeout = timeout;
+ if (buffer) {
+ rq->data = buffer;
+ rq->data_len = *bufflen;
+ }
+
+ error = blk_execute_rq(drive->queue, info->disk, rq, 0);
+
+ if (buffer)
+ *bufflen = rq->data_len;
+
+ flags = rq->cmd_flags;
+ blk_put_request(rq);
/*
* FIXME: we should probably abort/retry or something in case of
* failure.
*/
- if (rq->cmd_flags & REQ_FAILED) {
+ if (flags & REQ_FAILED) {
/*
* The request failed. Retry if it was due to a unit
* attention status (usually means media was changed).
*/
- struct request_sense *reqbuf = rq->sense;
+ struct request_sense *reqbuf = sense;
if (reqbuf->sense_key == UNIT_ATTENTION)
cdrom_saw_media_change(drive);
@@ -885,10 +934,10 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
}
/* end of retry loop */
- } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
+ } while ((flags & REQ_FAILED) && retries >= 0);
/* return an error if the command failed */
- return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
+ return (flags & REQ_FAILED) ? -EIO : 0;
}
/*
@@ -904,22 +953,25 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct cdrom_info *info = drive->driver_data;
struct request *rq = HWGROUP(drive)->rq;
xfer_func_t *xferfunc;
ide_expiry_t *expiry = NULL;
- int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
+ int dma_error = 0, dma, stat, thislen, uptodate = 0;
int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
unsigned int timeout;
- u8 lowcyl, highcyl;
+ u16 len;
+ u8 ireason;
+
+ ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x\n",
+ __func__, rq->cmd[0], write);
/* check for errors */
- dma = info->dma;
+ dma = drive->dma;
if (dma) {
- info->dma = 0;
+ drive->dma = 0;
dma_error = hwif->dma_ops->dma_end(drive);
if (dma_error) {
- printk(KERN_ERR "%s: DMA %s error\n", drive->name,
+ printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
write ? "write" : "read");
ide_dma_off(drive);
}
@@ -939,19 +991,17 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
goto end_request;
}
- /* ok we fall to pio :/ */
- ireason = hwif->INB(hwif->io_ports.nsect_addr) & 0x3;
- lowcyl = hwif->INB(hwif->io_ports.lbam_addr);
- highcyl = hwif->INB(hwif->io_ports.lbah_addr);
-
- len = lowcyl + (256 * highcyl);
+ ide_read_bcount_and_ireason(drive, &len, &ireason);
thislen = blk_fs_request(rq) ? len : rq->data_len;
if (thislen > len)
thislen = len;
+ ide_debug_log(IDE_DBG_PC, "%s: DRQ: stat: 0x%x, thislen: %d\n",
+ __func__, stat, thislen);
+
/* If DRQ is clear, the command has completed. */
- if ((stat & DRQ_STAT) == 0) {
+ if ((stat & ATA_DRQ) == 0) {
if (blk_fs_request(rq)) {
/*
* If we're not done reading/writing, complain.
@@ -959,7 +1009,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
*/
uptodate = 1;
if (rq->current_nr_sectors > 0) {
- printk(KERN_ERR "%s: %s: data underrun "
+ printk(KERN_ERR PFX "%s: %s: data underrun "
"(%d blocks)\n",
drive->name, __func__,
rq->current_nr_sectors);
@@ -970,7 +1020,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
cdrom_end_request(drive, uptodate);
return ide_stopped;
} else if (!blk_pc_request(rq)) {
- ide_cd_request_sense_fixup(rq);
+ ide_cd_request_sense_fixup(drive, rq);
/* complain if we still have data left to transfer */
uptodate = rq->data_len ? 0 : 1;
}
@@ -998,7 +1048,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
- bio_cur_sectors(rq->bio),
thislen >> 9);
if (nskip > 0) {
- ide_cd_drain_data(drive, nskip);
+ ide_pad_transfer(drive, write, nskip << 9);
rq->current_nr_sectors -= nskip;
thislen -= (nskip << 9);
}
@@ -1007,12 +1057,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (ireason == 0) {
write = 1;
- xferfunc = hwif->output_data;
+ xferfunc = hwif->tp_ops->output_data;
} else {
write = 0;
- xferfunc = hwif->input_data;
+ xferfunc = hwif->tp_ops->input_data;
}
+ ide_debug_log(IDE_DBG_PC, "%s: data transfer, rq->cmd_type: 0x%x, "
+ "ireason: 0x%x\n", __func__, rq->cmd_type, ireason);
+
/* transfer data */
while (thislen > 0) {
u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
@@ -1035,9 +1088,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
* If the buffers are full, pipe the rest into
* oblivion.
*/
- ide_cd_drain_data(drive, thislen >> 9);
+ ide_pad_transfer(drive, 0, thislen);
else {
- printk(KERN_ERR "%s: confused, missing data\n",
+ printk(KERN_ERR PFX "%s: confused, missing data\n",
drive->name);
blk_dump_rq_flags(rq, rq_data_dir(rq)
? "cdrom_newpc_intr, write"
@@ -1083,7 +1136,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
/* pad, if necessary */
if (!blk_fs_request(rq) && len > 0)
- ide_cd_pad_transfer(drive, xferfunc, len);
+ ide_pad_transfer(drive, write, len);
if (blk_pc_request(rq)) {
timeout = rq->timeout;
@@ -1124,9 +1177,12 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
unsigned short sectors_per_frame =
queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+ ide_debug_log(IDE_DBG_RQ, "Call %s, write: 0x%x, secs_per_frame: %u\n",
+ __func__, write, sectors_per_frame);
+
if (write) {
/* disk has become write protected */
- if (cd->disk->policy) {
+ if (get_disk_ro(cd->disk)) {
cdrom_end_request(drive, 0);
return ide_stopped;
}
@@ -1135,7 +1191,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
* We may be retrying this request after an error. Fix up any
* weirdness which might be present in the request packet.
*/
- restore_request(rq);
+ ide_cd_restore_request(drive, rq);
}
/* use DMA, if possible / writes *must* be hardware frame aligned */
@@ -1145,45 +1201,48 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
cdrom_end_request(drive, 0);
return ide_stopped;
}
- cd->dma = 0;
+ drive->dma = 0;
} else
- cd->dma = drive->using_dma;
+ drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
if (write)
cd->devinfo.media_written = 1;
- /* start sending the read/write request to the drive */
- return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
+ return ide_started;
}
static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
- if (!rq->timeout)
- rq->timeout = ATAPI_WAIT_PC;
-
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
-static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
- struct cdrom_info *info = drive->driver_data;
+
+ ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd_type: 0x%x\n", __func__,
+ rq->cmd_type);
if (blk_pc_request(rq))
rq->cmd_flags |= REQ_QUIET;
else
rq->cmd_flags &= ~REQ_FAILED;
- info->dma = 0;
+ drive->dma = 0;
/* sg request */
- if (rq->bio) {
- int mask = drive->queue->dma_alignment;
- unsigned long addr =
- (unsigned long)page_address(bio_page(rq->bio));
+ if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
+ struct request_queue *q = drive->queue;
+ unsigned int alignment;
+ char *buf;
+
+ if (rq->bio)
+ buf = bio_data(rq->bio);
+ else
+ buf = rq->data;
- info->dma = drive->using_dma;
+ drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
/*
* check if dma is safe
@@ -1191,65 +1250,87 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
* NOTE! The "len" and "addr" checks should possibly have
* separate masks.
*/
- if ((rq->data_len & 15) || (addr & mask))
- info->dma = 0;
+ alignment = queue_dma_alignment(q) | q->dma_pad_mask;
+ if ((unsigned long)buf & alignment || rq->data_len & alignment
+ || object_is_on_stack(buf))
+ drive->dma = 0;
}
-
- /* start sending the command to the drive */
- return cdrom_start_packet_command(drive, rq->data_len,
- cdrom_do_newpc_cont);
}
/*
* cdrom driver request routine.
*/
-static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq,
+static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
sector_t block)
{
- ide_startstop_t action;
struct cdrom_info *info = drive->driver_data;
+ ide_handler_t *fn;
+ int xferlen;
+
+ ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd_type: 0x%x, block: %llu\n",
+ __func__, rq->cmd_type, (unsigned long long)block);
if (blk_fs_request(rq)) {
- if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
+ if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
+ ide_hwif_t *hwif = drive->hwif;
unsigned long elapsed = jiffies - info->start_seek;
- int stat = ide_read_status(drive);
+ int stat = hwif->tp_ops->read_status(hwif);
- if ((stat & SEEK_STAT) != SEEK_STAT) {
+ if ((stat & ATA_DSC) != ATA_DSC) {
if (elapsed < IDECD_SEEK_TIMEOUT) {
ide_stall_queue(drive,
IDECD_SEEK_TIMER);
return ide_stopped;
}
- printk(KERN_ERR "%s: DSC timeout\n",
+ printk(KERN_ERR PFX "%s: DSC timeout\n",
drive->name);
}
- info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
+ drive->atapi_flags &= ~IDE_AFLAG_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
- action = cdrom_start_rw(drive, rq);
+ IDECD_SEEK_THRESHOLD) &&
+ (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)) {
+ xferlen = 0;
+ fn = cdrom_start_seek_continuation;
+
+ drive->dma = 0;
+ info->start_seek = jiffies;
+
+ ide_cd_prepare_seek_request(drive, rq);
+ } else {
+ xferlen = 32768;
+ fn = cdrom_start_rw_cont;
+
+ if (cdrom_start_rw(drive, rq) == ide_stopped)
+ return ide_stopped;
+
+ if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
+ return ide_stopped;
+ }
info->last_block = block;
- return action;
} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
rq->cmd_type == REQ_TYPE_ATA_PC) {
- return cdrom_do_block_pc(drive, rq);
+ xferlen = rq->data_len;
+ fn = cdrom_do_newpc_cont;
+
+ if (!rq->timeout)
+ rq->timeout = ATAPI_WAIT_PC;
+
+ cdrom_do_block_pc(drive, rq);
} else if (blk_special_request(rq)) {
/* right now this can only be a reset... */
cdrom_end_request(drive, 1);
return ide_stopped;
+ } else {
+ blk_dump_rq_flags(rq, DRV_NAME " bad flags");
+ cdrom_end_request(drive, 0);
+ return ide_stopped;
}
- blk_dump_rq_flags(rq, "ide-cd bad flags");
- cdrom_end_request(drive, 0);
- return ide_stopped;
+ return cdrom_start_packet_command(drive, xferlen, fn);
}
-
-
/*
* Ioctl handling.
*
@@ -1261,30 +1342,29 @@ static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq,
*/
static void msf_from_bcd(struct atapi_msf *msf)
{
- msf->minute = BCD2BIN(msf->minute);
- msf->second = BCD2BIN(msf->second);
- msf->frame = BCD2BIN(msf->frame);
+ msf->minute = bcd2bin(msf->minute);
+ msf->second = bcd2bin(msf->second);
+ msf->frame = bcd2bin(msf->frame);
}
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;
+ unsigned char cmd[BLK_MAX_CDB];
- ide_cd_init_rq(drive, &req);
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
- req.sense = sense;
- req.cmd[0] = GPCMD_TEST_UNIT_READY;
- req.cmd_flags |= REQ_QUIET;
+ memset(cmd, 0, BLK_MAX_CDB);
+ cmd[0] = GPCMD_TEST_UNIT_READY;
/*
* 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;
+ cmd[7] = cdi->sanyo_slot % 3;
- return ide_cd_queue_pc(drive, &req);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
}
static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -1292,53 +1372,69 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
struct request_sense *sense)
{
struct {
- __u32 lba;
- __u32 blocklen;
+ __be32 lba;
+ __be32 blocklen;
} capbuf;
int stat;
- struct request req;
+ unsigned char cmd[BLK_MAX_CDB];
+ unsigned len = sizeof(capbuf);
+ u32 blocklen;
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
- ide_cd_init_rq(drive, &req);
+ memset(cmd, 0, BLK_MAX_CDB);
+ cmd[0] = GPCMD_READ_CDVD_CAPACITY;
- req.sense = sense;
- req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
- req.data = (char *)&capbuf;
- req.data_len = sizeof(capbuf);
- req.cmd_flags |= REQ_QUIET;
+ stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
+ REQ_QUIET);
+ if (stat)
+ return stat;
- stat = ide_cd_queue_pc(drive, &req);
- if (stat == 0) {
- *capacity = 1 + be32_to_cpu(capbuf.lba);
- *sectors_per_frame =
- be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+ /*
+ * Sanity check the given block size
+ */
+ blocklen = be32_to_cpu(capbuf.blocklen);
+ switch (blocklen) {
+ case 512:
+ case 1024:
+ case 2048:
+ case 4096:
+ break;
+ default:
+ printk(KERN_ERR PFX "%s: weird block size %u\n",
+ drive->name, blocklen);
+ printk(KERN_ERR PFX "%s: default to 2kb block size\n",
+ drive->name);
+ blocklen = 2048;
+ break;
}
- return stat;
+ *capacity = 1 + be32_to_cpu(capbuf.lba);
+ *sectors_per_frame = blocklen >> SECTOR_BITS;
+ return 0;
}
static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
int format, char *buf, int buflen,
struct request_sense *sense)
{
- struct request req;
+ unsigned char cmd[BLK_MAX_CDB];
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
- ide_cd_init_rq(drive, &req);
+ memset(cmd, 0, BLK_MAX_CDB);
- req.sense = sense;
- req.data = buf;
- req.data_len = buflen;
- req.cmd_flags |= REQ_QUIET;
- req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- req.cmd[6] = trackno;
- req.cmd[7] = (buflen >> 8);
- req.cmd[8] = (buflen & 0xff);
- req.cmd[9] = (format << 6);
+ cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+ cmd[6] = trackno;
+ cmd[7] = (buflen >> 8);
+ cmd[8] = (buflen & 0xff);
+ cmd[9] = (format << 6);
if (msf_flag)
- req.cmd[1] = 2;
+ cmd[1] = 2;
- return ide_cd_queue_pc(drive, &req);
+ return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, REQ_QUIET);
}
/* Try to read the entire TOC for the disk into our internal buffer. */
@@ -1355,11 +1451,13 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
long last_written;
unsigned long sectors_per_frame = SECTORS_PER_FRAME;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
if (toc == NULL) {
/* try to allocate space */
toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
if (toc == NULL) {
- printk(KERN_ERR "%s: No cdrom TOC buffer!\n",
+ printk(KERN_ERR PFX "%s: No cdrom TOC buffer!\n",
drive->name);
return -ENOMEM;
}
@@ -1372,7 +1470,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
*/
(void) cdrom_check_status(drive, sense);
- if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
+ if (drive->atapi_flags & IDE_AFLAG_TOC_VALID)
return 0;
/* try to get the total cdrom capacity and sector size */
@@ -1394,9 +1492,9 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
- 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);
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
+ toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
+ toc->hdr.last_track = bcd2bin(toc->hdr.last_track);
}
ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
@@ -1435,9 +1533,9 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
- 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);
+ if (drive->atapi_flags & IDE_AFLAG_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;
@@ -1449,15 +1547,15 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length);
- 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);
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
+ toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
+ toc->hdr.last_track = bcd2bin(toc->hdr.last_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);
+ if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD)
+ toc->ent[i].track = bcd2bin(toc->ent[i].track);
msf_from_bcd(&toc->ent[i].addr.msf);
}
toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute,
@@ -1479,7 +1577,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
}
- if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_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);
@@ -1503,7 +1601,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
}
/* Remember that we've read this stuff. */
- info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags |= IDE_AFLAG_TOC_VALID;
return 0;
}
@@ -1515,7 +1613,9 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
struct packet_command cgc;
int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
- if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
+ if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
@@ -1533,15 +1633,14 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
struct cdrom_info *cd = drive->driver_data;
u16 curspeed, maxspeed;
- curspeed = *(u16 *)&buf[8 + 14];
- maxspeed = *(u16 *)&buf[8 + 8];
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
- if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
- curspeed = le16_to_cpu(curspeed);
- maxspeed = le16_to_cpu(maxspeed);
+ if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
+ curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
+ maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
} else {
- curspeed = be16_to_cpu(curspeed);
- maxspeed = be16_to_cpu(maxspeed);
+ curspeed = be16_to_cpup((__be16 *)&buf[8 + 14]);
+ maxspeed = be16_to_cpup((__be16 *)&buf[8 + 8]);
}
cd->current_speed = (curspeed + (176/2)) / 176;
@@ -1576,13 +1675,15 @@ static int ide_cdrom_register(ide_drive_t *drive, int nslots)
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *devinfo = &info->devinfo;
+ ide_debug_log(IDE_DBG_PROBE, "Call %s, nslots: %d\n", __func__, nslots);
+
devinfo->ops = &ide_cdrom_dops;
devinfo->speed = info->current_speed;
devinfo->capacity = nslots;
devinfo->handle = drive;
strcpy(devinfo->name, drive->name);
- if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
+ if (drive->atapi_flags & IDE_AFLAG_NO_SPEED_SELECT)
devinfo->mask |= CDC_SELECT_SPEED;
devinfo->disk = info->disk;
@@ -1597,19 +1698,23 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
mechtype_t mechtype;
int nslots = 1;
+ ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->media: 0x%x, "
+ "drive->atapi_flags: 0x%lx\n", __func__, drive->media,
+ drive->atapi_flags);
+
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) {
cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
- printk(KERN_ERR "%s: ATAPI magneto-optical drive\n",
+ printk(KERN_ERR PFX "%s: ATAPI magneto-optical drive\n",
drive->name);
return nslots;
}
- if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
- cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ if (drive->atapi_flags & IDE_AFLAG_PRE_ATAPI12) {
+ drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
cdi->mask &= ~CDC_PLAY_AUDIO;
return nslots;
}
@@ -1627,9 +1732,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return 0;
if ((buf[8 + 6] & 0x01) == 0)
- cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
if (buf[8 + 6] & 0x08)
- cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
if (buf[8 + 3] & 0x01)
cdi->mask &= ~CDC_CD_R;
if (buf[8 + 3] & 0x02)
@@ -1640,11 +1745,13 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
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))
+ if ((buf[8 + 4] & 0x01) || (drive->atapi_flags & IDE_AFLAG_PLAY_AUDIO_OK))
cdi->mask &= ~CDC_PLAY_AUDIO;
mechtype = buf[8 + 6] >> 5;
- if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
+ if (mechtype == mechtype_caddy ||
+ mechtype == mechtype_popup ||
+ (drive->atapi_flags & IDE_AFLAG_NO_AUTOCLOSE))
cdi->mask |= CDC_CLOSE_TRAY;
if (cdi->sanyo_slot > 0) {
@@ -1659,7 +1766,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
ide_cdrom_update_speed(drive, buf);
- printk(KERN_INFO "%s: ATAPI", drive->name);
+ printk(KERN_INFO PFX "%s: ATAPI", drive->name);
/* don't print speed if the drive reported 0 */
if (cd->max_speed)
@@ -1682,7 +1789,8 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
else
printk(KERN_CONT " drive");
- printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
+ printk(KERN_CONT ", %dkB Cache\n",
+ be16_to_cpup((__be16 *)&buf[8 + 12]));
return nslots;
}
@@ -1794,65 +1902,66 @@ static ide_proc_entry_t idecd_proc[] = {
{ NULL, 0, NULL, NULL }
};
-static void ide_cdrom_add_settings(ide_drive_t *drive)
-{
- ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
- &drive->dsc_overlap, NULL);
-}
-#else
-static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
+ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
+
+static const struct ide_proc_devset idecd_settings[] = {
+ IDE_PROC_DEVSET(dsc_overlap, 0, 1),
+ { 0 },
+};
#endif
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 },
+ { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_AFLAG_LIMIT_NFRAMES },
+ { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_AFLAG_LIMIT_NFRAMES },
/* SCR-3231 doesn't support the SET_CD_SPEED command. */
- { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT },
+ { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_AFLAG_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, },
+ { "NEC CD-ROM DRIVE:260", "1.01", IDE_AFLAG_TOCADDR_AS_BCD |
+ IDE_AFLAG_PRE_ATAPI12, },
/* Vertos 300, some versions of this drive like to talk BCD. */
- { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, },
+ { "V003S0DS", NULL, IDE_AFLAG_VERTOS_300_SSD, },
/* Vertos 600 ESD. */
- { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, },
+ { "V006E0DS", NULL, IDE_AFLAG_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 },
+ { "CD-ROM CDR-C3 G", NULL, IDE_AFLAG_SANYO_3CD },
+ { "CD-ROM CDR-C3G", NULL, IDE_AFLAG_SANYO_3CD },
+ { "CD-ROM CDR_C36", NULL, IDE_AFLAG_SANYO_3CD },
/* Stingray 8X CD-ROM. */
- { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
+ { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_AFLAG_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 },
+ { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_AFLAG_FULL_CAPS_PAGE },
+ { "WPI CDS-32X", NULL, IDE_AFLAG_FULL_CAPS_PAGE },
/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
- { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS },
+ { "", "241N", IDE_AFLAG_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 },
- { "Optiarc DVD RW AD-5200A", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8187", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8186", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8176", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8174", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-7200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-7543A", NULL, IDE_AFLAG_NO_AUTOCLOSE },
{ NULL, NULL, 0 }
};
-static unsigned int ide_cd_flags(struct hd_driveid *id)
+static unsigned int ide_cd_flags(u16 *id)
{
const struct cd_list_entry *cle = ide_cd_quirks_list;
while (cle->id_model) {
- if (strcmp(cle->id_model, id->model) == 0 &&
+ if (strcmp(cle->id_model, (char *)&id[ATA_ID_PROD]) == 0 &&
(cle->id_firmware == NULL ||
- strstr(id->fw_rev, cle->id_firmware)))
+ strstr((char *)&id[ATA_ID_FW_REV], cle->id_firmware)))
return cle->cd_flags;
cle++;
}
@@ -1864,31 +1973,30 @@ static int ide_cdrom_setup(ide_drive_t *drive)
{
struct cdrom_info *cd = drive->driver_data;
struct cdrom_device_info *cdi = &cd->devinfo;
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
+ char *fw_rev = (char *)&id[ATA_ID_FW_REV];
int nslots;
+ ide_debug_log(IDE_DBG_PROBE, "Call %s\n", __func__);
+
blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
blk_queue_dma_alignment(drive->queue, 31);
+ blk_queue_update_dma_pad(drive->queue, 15);
drive->queue->unplug_delay = (1 * HZ) / 1000;
if (!drive->queue->unplug_delay)
drive->queue->unplug_delay = 1;
- drive->special.all = 0;
-
- cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
+ drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
ide_cd_flags(id);
- if ((id->config & 0x0060) == 0x20)
- cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
-
- 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)
+ if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
+ fw_rev[4] == '1' && fw_rev[6] <= '2')
+ drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
+ IDE_AFLAG_TOCADDR_AS_BCD);
+ else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) &&
+ fw_rev[4] == '1' && fw_rev[6] <= '2')
+ drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD;
+ else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD)
/* 3 => use CD in slot 0 */
cdi->sanyo_slot = 3;
@@ -1897,15 +2005,19 @@ static int ide_cdrom_setup(ide_drive_t *drive)
/* set correct block size */
blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
- drive->dsc_overlap = (drive->next != drive);
+ if (drive->next != drive)
+ drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
if (ide_cdrom_register(drive, nslots)) {
- printk(KERN_ERR "%s: %s failed to register device with the"
+ printk(KERN_ERR PFX "%s: %s failed to register device with the"
" cdrom driver.\n", drive->name, __func__);
cd->devinfo.handle = NULL;
return 1;
}
- ide_cdrom_add_settings(drive);
+
+ ide_proc_register_driver(drive, cd->driver);
return 0;
}
@@ -1913,6 +2025,8 @@ static void ide_cd_remove(ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
ide_proc_unregister_driver(drive, info->driver);
del_gendisk(info->disk);
@@ -1922,15 +2036,17 @@ static void ide_cd_remove(ide_drive_t *drive)
static void ide_cd_release(struct kref *kref)
{
- struct cdrom_info *info = to_ide_cd(kref);
+ struct cdrom_info *info = to_ide_drv(kref, cdrom_info);
struct cdrom_device_info *devinfo = &info->devinfo;
ide_drive_t *drive = info->drive;
struct gendisk *g = info->disk;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
kfree(info->toc);
if (devinfo->handle == drive)
unregister_cdrom(devinfo);
- drive->dsc_overlap = 0;
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
drive->driver_data = NULL;
blk_queue_prep_rq(drive->queue, NULL);
g->private_data = NULL;
@@ -1949,14 +2065,12 @@ static ide_driver_t ide_cdrom_driver = {
.probe = ide_cd_probe,
.remove = ide_cd_remove,
.version = IDECD_VERSION,
- .media = ide_cdrom,
- .supports_dsc_overlap = 1,
- .do_request = ide_do_rw_cdrom,
+ .do_request = ide_cd_do_request,
.end_request = ide_end_request,
.error = __ide_error,
- .abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
.proc = idecd_proc,
+ .settings = idecd_settings,
#endif
};
@@ -1981,7 +2095,7 @@ static int idecd_open(struct inode *inode, struct file *file)
static int idecd_release(struct inode *inode, struct file *file)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct cdrom_info *info = ide_cd_g(disk);
+ struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
cdrom_release(&info->devinfo, file);
@@ -2033,7 +2147,7 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
+ struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info);
int err;
switch (cmd) {
@@ -2054,13 +2168,13 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
static int idecd_media_changed(struct gendisk *disk)
{
- struct cdrom_info *info = ide_cd_g(disk);
+ struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
return cdrom_media_changed(&info->devinfo);
}
static int idecd_revalidate_disk(struct gendisk *disk)
{
- struct cdrom_info *info = ide_cd_g(disk);
+ struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
struct request_sense sense;
ide_cd_read_toc(info->drive, &sense);
@@ -2079,8 +2193,11 @@ static struct block_device_operations idecd_ops = {
/* module options */
static char *ignore;
-
module_param(ignore, charp, 0400);
+
+static unsigned long debug_mask;
+module_param(debug_mask, ulong, 0644);
+
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
static int ide_cd_probe(ide_drive_t *drive)
@@ -2089,28 +2206,30 @@ static int ide_cd_probe(ide_drive_t *drive)
struct gendisk *g;
struct request_sense sense;
+ ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->driver_req: %s, "
+ "drive->media: 0x%x\n", __func__, drive->driver_req,
+ drive->media);
+
if (!strstr("ide-cdrom", drive->driver_req))
goto failed;
- if (!drive->present)
- goto failed;
+
if (drive->media != ide_cdrom && drive->media != ide_optical)
goto failed;
+
/* skip drives that we were told to ignore */
if (ignore != NULL) {
if (strstr(ignore, drive->name)) {
- printk(KERN_INFO "ide-cd: ignoring drive %s\n",
+ printk(KERN_INFO PFX "ignoring drive %s\n",
drive->name);
goto failed;
}
}
- if (drive->scsi) {
- printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi "
- "emulation.\n", drive->name);
- goto failed;
- }
+
+ drive->debug_mask = debug_mask;
+
info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
- printk(KERN_ERR "%s: Can't allocate a cdrom structure\n",
+ printk(KERN_ERR PFX "%s: Can't allocate a cdrom structure\n",
drive->name);
goto failed;
}
@@ -2121,8 +2240,6 @@ static int ide_cd_probe(ide_drive_t *drive)
ide_init_disk(g, drive);
- ide_proc_register_driver(drive, &ide_cdrom_driver);
-
kref_init(&info->kref);
info->drive = drive;
@@ -2137,7 +2254,6 @@ 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)) {
- ide_proc_unregister_driver(drive, &ide_cdrom_driver);
ide_cd_release(&info->kref);
goto failed;
}
@@ -2161,6 +2277,7 @@ static void __exit ide_cdrom_exit(void)
static int __init ide_cdrom_init(void)
{
+ printk(KERN_INFO DRV_NAME " driver " IDECD_VERSION "\n");
return driver_register(&ide_cdrom_driver.gen_driver);
}
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index a58801c4484..5882b9a9ea8 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -27,42 +27,6 @@
#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),
-};
-
/* Structure of a MSF cdrom address. */
struct atapi_msf {
byte reserved;
@@ -124,12 +88,9 @@ struct cdrom_info {
struct request_sense sense_data;
struct request request_sense_request;
- int dma;
unsigned long last_block;
unsigned long start_seek;
- unsigned int cd_flags;
-
u8 max_speed; /* Max speed of the drive. */
u8 current_speed; /* Current speed of the drive. */
@@ -143,8 +104,8 @@ struct cdrom_info {
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_queue_pc(ide_drive_t *, const unsigned char *, int, void *,
+ unsigned *, struct request_sense *, int, unsigned int);
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 *);
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 6d147ce6782..74231b41f61 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -27,10 +27,9 @@ int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose)
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;
+ drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
}
/*
@@ -83,13 +82,12 @@ 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;
+ retval = (drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED) ? 1 : 0;
+ drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
return retval;
} else {
return -EINVAL;
@@ -104,27 +102,26 @@ int cdrom_eject(ide_drive_t *drive, int ejectflag,
{
struct cdrom_info *cd = drive->driver_data;
struct cdrom_device_info *cdi = &cd->devinfo;
- struct request req;
char loej = 0x02;
+ unsigned char cmd[BLK_MAX_CDB];
- if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
+ if ((drive->atapi_flags & IDE_AFLAG_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)
+ if ((drive->atapi_flags & IDE_AFLAG_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);
+ memset(cmd, 0, BLK_MAX_CDB);
+
+ cmd[0] = GPCMD_START_STOP_UNIT;
+ cmd[4] = loej | (ejectflag != 0);
- return ide_cd_queue_pc(drive, &req);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, 0);
}
/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
@@ -132,23 +129,25 @@ 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) {
+ if (drive->atapi_flags & IDE_AFLAG_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);
+ unsigned char cmd[BLK_MAX_CDB];
+
+ memset(cmd, 0, BLK_MAX_CDB);
+
+ cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
+ cmd[4] = lockflag ? 1 : 0;
+
+ stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL,
+ sense, 0, 0);
}
/* If we got an illegal field error, the drive
@@ -158,7 +157,7 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
(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;
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
stat = 0;
}
@@ -168,9 +167,9 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
if (stat == 0) {
if (lockflag)
- cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
+ drive->atapi_flags |= IDE_AFLAG_DOOR_LOCKED;
else
- cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
+ drive->atapi_flags &= ~IDE_AFLAG_DOOR_LOCKED;
}
return stat;
@@ -206,32 +205,30 @@ 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;
+ unsigned char cmd[BLK_MAX_CDB];
if (speed == 0)
speed = 0xffff; /* set to max */
else
speed *= 177; /* Nx to kbytes/s */
- rq.cmd[0] = GPCMD_SET_SPEED;
+ memset(cmd, 0, BLK_MAX_CDB);
+
+ cmd[0] = GPCMD_SET_SPEED;
/* Read Drive speed in kbytes/second MSB/LSB */
- rq.cmd[2] = (speed >> 8) & 0xff;
- rq.cmd[3] = speed & 0xff;
+ cmd[2] = (speed >> 8) & 0xff;
+ 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;
+ cmd[4] = (speed >> 8) & 0xff;
+ cmd[5] = speed & 0xff;
}
- stat = ide_cd_queue_pc(drive, &rq);
+ stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
if (!ide_cdrom_get_capabilities(drive, buf)) {
ide_cdrom_update_speed(drive, buf);
@@ -250,7 +247,7 @@ int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
struct request_sense sense;
int ret;
- if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
+ if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0 || !info->toc) {
ret = ide_cd_read_toc(drive, &sense);
if (ret)
return ret;
@@ -268,21 +265,19 @@ int ide_cdrom_get_mcn(struct cdrom_device_info *cdi,
{
ide_drive_t *drive = cdi->handle;
int stat, mcnlen;
- struct request rq;
char buf[24];
+ unsigned char cmd[BLK_MAX_CDB];
+ unsigned len = sizeof(buf);
- ide_cd_init_rq(drive, &rq);
-
- rq.data = buf;
- rq.data_len = sizeof(buf);
+ memset(cmd, 0, BLK_MAX_CDB);
- 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);
+ cmd[0] = GPCMD_READ_SUBCHANNEL;
+ cmd[1] = 2; /* MSF addressing */
+ cmd[2] = 0x40; /* request subQ data */
+ cmd[3] = 2; /* format */
+ cmd[8] = len;
- stat = ide_cd_queue_pc(drive, &rq);
+ stat = ide_cd_queue_pc(drive, cmd, 0, buf, &len, NULL, 0, 0);
if (stat)
return stat;
@@ -298,19 +293,19 @@ 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;
+ struct request *rq;
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);
-
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd_flags = REQ_QUIET;
+ ret = blk_execute_rq(drive->queue, cd->disk, rq, 0);
+ blk_put_request(rq);
/*
* A reset will unlock the door. If it was previously locked,
* lock it again.
*/
- if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
+ if (drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED)
(void)ide_cd_lockdoor(drive, 1, &sense);
return ret;
@@ -326,7 +321,7 @@ static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
/*
* don't serve cached data, if the toc isn't valid
*/
- if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
+ if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0)
return -EINVAL;
/* Check validity of requested track number. */
@@ -351,8 +346,8 @@ static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
struct atapi_toc_entry *first_toc, *last_toc;
unsigned long lba_start, lba_end;
int stat;
- struct request rq;
struct request_sense sense;
+ unsigned char cmd[BLK_MAX_CDB];
stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
if (stat)
@@ -370,14 +365,13 @@ static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
if (lba_end <= lba_start)
return -EINVAL;
- ide_cd_init_rq(drive, &rq);
+ memset(cmd, 0, BLK_MAX_CDB);
- 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]);
+ cmd[0] = GPCMD_PLAY_AUDIO_MSF;
+ lba_to_msf(lba_start, &cmd[3], &cmd[4], &cmd[5]);
+ lba_to_msf(lba_end - 1, &cmd[6], &cmd[7], &cmd[8]);
- return ide_cd_queue_pc(drive, &rq);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
}
static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
@@ -447,8 +441,9 @@ int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi,
int ide_cdrom_packet(struct cdrom_device_info *cdi,
struct packet_command *cgc)
{
- struct request req;
ide_drive_t *drive = cdi->handle;
+ unsigned int flags = 0;
+ unsigned len = cgc->buflen;
if (cgc->timeout <= 0)
cgc->timeout = ATAPI_WAIT_PC;
@@ -456,24 +451,21 @@ int ide_cdrom_packet(struct cdrom_device_info *cdi,
/* 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);
if (cgc->data_direction == CGC_DATA_WRITE)
- req.cmd_flags |= REQ_RW;
+ flags |= REQ_RW;
- 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;
+ flags |= REQ_QUIET;
- req.sense = cgc->sense;
- cgc->stat = ide_cd_queue_pc(drive, &req);
+ cgc->stat = ide_cd_queue_pc(drive, cgc->cmd,
+ cgc->data_direction == CGC_DATA_WRITE,
+ cgc->buffer, &len,
+ cgc->sense, cgc->timeout, flags);
if (!cgc->stat)
- cgc->buflen -= req.data_len;
+ cgc->buflen -= len;
return cgc->stat;
}
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 8e08d083fce..3853bde8eed 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -30,10 +30,8 @@
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/leds.h>
-
-#define _IDE_DISK
-
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -41,20 +39,19 @@
#include <asm/io.h>
#include <asm/div64.h>
-struct ide_disk_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
- unsigned int openers; /* protected by BKL for now */
-};
+#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
+#define IDE_DISK_MINORS (1 << PARTN_BITS)
+#else
+#define IDE_DISK_MINORS 0
+#endif
+
+#include "ide-disk.h"
static DEFINE_MUTEX(idedisk_ref_mutex);
#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
-#define ide_disk_g(disk) \
- container_of((disk)->private_data, struct ide_disk_obj, driver)
+static void ide_disk_release(struct kref *);
static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
{
@@ -62,83 +59,39 @@ static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
mutex_lock(&idedisk_ref_mutex);
idkp = ide_disk_g(disk);
- if (idkp)
- kref_get(&idkp->kref);
+ if (idkp) {
+ if (ide_device_get(idkp->drive))
+ idkp = NULL;
+ else
+ kref_get(&idkp->kref);
+ }
mutex_unlock(&idedisk_ref_mutex);
return idkp;
}
-static void ide_disk_release(struct kref *);
-
static void ide_disk_put(struct ide_disk_obj *idkp)
{
+ ide_drive_t *drive = idkp->drive;
+
mutex_lock(&idedisk_ref_mutex);
kref_put(&idkp->kref, ide_disk_release);
+ ide_device_put(drive);
mutex_unlock(&idedisk_ref_mutex);
}
-/*
- * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
- * value for this drive (from its reported identification information).
- *
- * Returns: 1 if lba_capacity looks sensible
- * 0 otherwise
- *
- * It is called only once for each drive.
- */
-static int lba_capacity_is_ok(struct hd_driveid *id)
-{
- unsigned long lba_sects, chs_sects, head, tail;
-
- /* No non-LBA info .. so valid! */
- if (id->cyls == 0)
- return 1;
-
- /*
- * The ATA spec tells large drives to return
- * C/H/S = 16383/16/63 independent of their size.
- * Some drives can be jumpered to use 15 heads instead of 16.
- * Some drives can be jumpered to use 4092 cyls instead of 16383.
- */
- if ((id->cyls == 16383
- || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
- id->sectors == 63 &&
- (id->heads == 15 || id->heads == 16) &&
- (id->lba_capacity >= 16383*63*id->heads))
- return 1;
-
- lba_sects = id->lba_capacity;
- chs_sects = id->cyls * id->heads * id->sectors;
-
- /* perform a rough sanity check on lba_sects: within 10% is OK */
- if ((lba_sects - chs_sects) < chs_sects/10)
- return 1;
-
- /* some drives have the word order reversed */
- head = ((lba_sects >> 16) & 0xffff);
- tail = (lba_sects & 0xffff);
- lba_sects = (head | (tail << 16));
- if ((lba_sects - chs_sects) < chs_sects/10) {
- id->lba_capacity = lba_sects;
- return 1; /* lba_capacity is (now) good */
- }
-
- 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,
+ ATA_CMD_READ_MULTI,
+ ATA_CMD_WRITE_MULTI,
+ ATA_CMD_READ_MULTI_EXT,
+ ATA_CMD_WRITE_MULTI_EXT,
+ ATA_CMD_PIO_READ,
+ ATA_CMD_PIO_WRITE,
+ ATA_CMD_PIO_READ_EXT,
+ ATA_CMD_PIO_WRITE_EXT,
+ ATA_CMD_READ,
+ ATA_CMD_WRITE,
+ ATA_CMD_READ_EXT,
+ ATA_CMD_WRITE_EXT,
};
static const u8 ide_data_phases[] = {
@@ -158,7 +111,7 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
if (dma)
- index = drive->vdma ? 4 : 8;
+ index = 8;
else
index = drive->mult_count ? 0 : 4;
@@ -178,9 +131,9 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
sector_t block)
{
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;
+ u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
+ u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
ide_task_t task;
struct ide_taskfile *tf = &task.tf;
ide_startstop_t rc;
@@ -198,10 +151,9 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
}
memset(&task, 0, sizeof(task));
- task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */
- task.tf_flags |= (IDE_TFLAG_TF | IDE_TFLAG_DEVICE);
+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- if (drive->select.b.lba) {
+ if (drive->dev_flags & IDE_DFLAG_LBA) {
if (lba48) {
pr_debug("%s: LBA=0x%012llx\n", drive->name,
(unsigned long long)block);
@@ -226,6 +178,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
tf->lbah = block >>= 8;
tf->device = (block >> 8) & 0xf;
}
+
+ tf->device |= ATA_LBA;
} else {
unsigned int sect, head, cyl, track;
@@ -276,7 +230,7 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
{
ide_hwif_t *hwif = HWIF(drive);
- BUG_ON(drive->blocked);
+ BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
if (!blk_fs_request(rq)) {
blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
@@ -310,9 +264,9 @@ static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
/* Create IDE/ATA command request structure */
memset(&args, 0, sizeof(ide_task_t));
if (lba48)
- tf->command = WIN_READ_NATIVE_MAX_EXT;
+ tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
else
- tf->command = WIN_READ_NATIVE_MAX;
+ tf->command = ATA_CMD_READ_NATIVE_MAX;
tf->device = ATA_LBA;
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
if (lba48)
@@ -347,10 +301,10 @@ static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int 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;
+ tf->command = ATA_CMD_SET_MAX_EXT;
} else {
tf->device = (addr_req >>= 8) & 0x0f;
- tf->command = WIN_SET_MAX;
+ tf->command = ATA_CMD_SET_MAX;
}
tf->device |= ATA_LBA;
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
@@ -373,25 +327,6 @@ static unsigned long long sectors_to_MB(unsigned long long n)
}
/*
- * Bits 10 of command_set_1 and cfs_enable_1 must be equal,
- * so on non-buggy drives we need test only one.
- * However, we should also check whether these fields are valid.
- */
-static inline int idedisk_supports_hpa(const struct hd_driveid *id)
-{
- return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400);
-}
-
-/*
- * The same here.
- */
-static inline int idedisk_supports_lba48(const struct hd_driveid *id)
-{
- return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)
- && id->lba_capacity_2;
-}
-
-/*
* Some disks report total number of sectors instead of
* maximum sector address. We list them here.
*/
@@ -405,7 +340,7 @@ static const struct drive_list_entry hpa_list[] = {
static void idedisk_check_hpa(ide_drive_t *drive)
{
unsigned long long capacity, set_max;
- int lba48 = idedisk_supports_lba48(drive->id);
+ int lba48 = ata_id_lba48_enabled(drive->id);
capacity = drive->capacity64;
@@ -439,155 +374,42 @@ static void idedisk_check_hpa(ide_drive_t *drive)
}
}
-/*
- * Compute drive->capacity, the full capacity of the drive
- * Called with drive->id != NULL.
- *
- * To compute capacity, this uses either of
- *
- * 1. CHS value set by user (whatever user sets will be trusted)
- * 2. LBA value from target drive (require new ATA feature)
- * 3. LBA value from system BIOS (new one is OK, old one may break)
- * 4. CHS value from system BIOS (traditional style)
- *
- * in above order (i.e., if value of higher priority is available,
- * reset will be ignored).
- */
static void init_idedisk_capacity(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
- /*
- * If this drive supports the Host Protected Area feature set,
- * then we may need to change our opinion about the drive's capacity.
- */
- int hpa = idedisk_supports_hpa(id);
+ u16 *id = drive->id;
+ int lba;
- if (idedisk_supports_lba48(id)) {
+ if (ata_id_lba48_enabled(id)) {
/* drive speaks 48-bit LBA */
- drive->select.b.lba = 1;
- drive->capacity64 = id->lba_capacity_2;
- if (hpa)
- idedisk_check_hpa(drive);
- } else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
+ lba = 1;
+ drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
+ } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {
/* drive speaks 28-bit LBA */
- drive->select.b.lba = 1;
- drive->capacity64 = id->lba_capacity;
- if (hpa)
- idedisk_check_hpa(drive);
+ lba = 1;
+ drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
} else {
/* drive speaks boring old 28-bit CHS */
+ lba = 0;
drive->capacity64 = drive->cyl * drive->head * drive->sect;
}
-}
-
-static sector_t idedisk_capacity(ide_drive_t *drive)
-{
- return drive->capacity64 - drive->sect0;
-}
-
-#ifdef CONFIG_IDE_PROC_FS
-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));
- 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));
- 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, 1);
-}
-
-static int proc_idedisk_read_cache
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- ide_drive_t *drive = (ide_drive_t *) data;
- char *out = page;
- int len;
-
- if (drive->id_read)
- len = sprintf(out, "%i\n", drive->id->buf_size / 2);
- else
- len = sprintf(out, "(none)\n");
-
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-
-static int proc_idedisk_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)idedisk_capacity(drive));
+ if (lba) {
+ drive->dev_flags |= IDE_DFLAG_LBA;
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-
-static int proc_idedisk_read_smart(char *page, char **start, off_t off,
- int count, int *eof, void *data, u8 sub_cmd)
-{
- ide_drive_t *drive = (ide_drive_t *)data;
- int len = 0, i = 0;
-
- if (get_smart_data(drive, page, sub_cmd) == 0) {
- unsigned short *val = (unsigned short *) page;
- char *out = ((char *)val) + (SECTOR_WORDS * 4);
- page = out;
- do {
- out += sprintf(out, "%04x%c", le16_to_cpu(*val),
- (++i & 7) ? ' ' : '\n');
- val += 1;
- } while (i < (SECTOR_WORDS * 2));
- len = out - page;
+ /*
+ * If this device supports the Host Protected Area feature set,
+ * then we may need to change our opinion about its capacity.
+ */
+ if (ata_id_hpa_enabled(id))
+ idedisk_check_hpa(drive);
}
-
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-
-static int proc_idedisk_read_sv
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- return proc_idedisk_read_smart(page, start, off, count, eof, data,
- SMART_READ_VALUES);
}
-static int proc_idedisk_read_st
- (char *page, char **start, off_t off, int count, int *eof, void *data)
+sector_t ide_disk_capacity(ide_drive_t *drive)
{
- return proc_idedisk_read_smart(page, start, off, count, eof, data,
- SMART_READ_THRESHOLDS);
+ return drive->capacity64;
}
-static ide_proc_entry_t idedisk_proc[] = {
- { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
- { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
- { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
- { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
- { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
- { NULL, 0, NULL, NULL }
-};
-#endif /* CONFIG_IDE_PROC_FS */
-
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
@@ -597,11 +419,11 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
BUG_ON(task == NULL);
memset(task, 0, sizeof(*task));
- if (ide_id_has_flush_cache_ext(drive->id) &&
+ if (ata_id_flush_ext_enabled(drive->id) &&
(drive->capacity64 >= (1UL << 28)))
- task->tf.command = WIN_FLUSH_CACHE_EXT;
+ task->tf.command = ATA_CMD_FLUSH_EXT;
else
- task->tf.command = WIN_FLUSH_CACHE;
+ task->tf.command = ATA_CMD_FLUSH;
task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
IDE_TFLAG_DYN;
task->data_phase = TASKFILE_NO_DATA;
@@ -611,50 +433,71 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
rq->special = task;
}
+ide_devset_get(multcount, mult_count);
+
/*
* This is tightly woven into the driver->do_special can not touch.
* DON'T do it again until a total personality rewrite is committed.
*/
static int set_multcount(ide_drive_t *drive, int arg)
{
- struct request rq;
+ struct request *rq;
+ int error;
- if (arg < 0 || arg > drive->id->max_multsect)
+ if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
return -EINVAL;
if (drive->special.b.set_multmode)
return -EBUSY;
- ide_init_drive_cmd(&rq);
- rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ 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);
+ error = blk_execute_rq(drive->queue, NULL, rq, 0);
+ blk_put_request(rq);
return (drive->mult_count == arg) ? 0 : -EIO;
}
+ide_devset_get_flag(nowerr, IDE_DFLAG_NOWERR);
+
static int set_nowerr(ide_drive_t *drive, int arg)
{
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- drive->nowerr = arg;
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_NOWERR;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_NOWERR;
+
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
- spin_unlock_irq(&ide_lock);
+
return 0;
}
+static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf.feature = feature;
+ task.tf.nsect = nsect;
+ task.tf.command = ATA_CMD_SET_FEATURES;
+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+ return ide_no_data_taskfile(drive, &task);
+}
+
static void update_ordered(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
unsigned ordered = QUEUE_ORDERED_NONE;
prepare_flush_fn *prep_fn = NULL;
- if (drive->wcache) {
+ if (drive->dev_flags & IDE_DFLAG_WCACHE) {
unsigned long long capacity;
int barrier;
/*
@@ -665,10 +508,12 @@ static void update_ordered(ide_drive_t *drive)
* time we have trimmed the drive capacity if LBA48 is
* not available so we don't need to recheck that.
*/
- capacity = idedisk_capacity(drive);
- barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
- (drive->addressing == 0 || capacity <= (1ULL << 28) ||
- ide_id_has_flush_cache_ext(id));
+ capacity = ide_disk_capacity(drive);
+ barrier = ata_id_flush_enabled(id) &&
+ (drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 &&
+ ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 ||
+ capacity <= (1ULL << 28) ||
+ ata_id_flush_ext_enabled(id));
printk(KERN_INFO "%s: cache flushes %ssupported\n",
drive->name, barrier ? "" : "not ");
@@ -683,23 +528,24 @@ static void update_ordered(ide_drive_t *drive)
blk_queue_ordered(drive->queue, ordered, prep_fn);
}
-static int write_cache(ide_drive_t *drive, int arg)
+ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
+
+static int set_wcache(ide_drive_t *drive, int arg)
{
- ide_task_t args;
int err = 1;
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_id_has_flush_cache(drive->id)) {
- memset(&args, 0, sizeof(ide_task_t));
- args.tf.feature = arg ?
- SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
- 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;
+ if (ata_id_flush_enabled(drive->id)) {
+ err = ide_do_setfeature(drive,
+ arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);
+ if (err == 0) {
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_WCACHE;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_WCACHE;
+ }
}
update_ordered(drive);
@@ -712,108 +558,88 @@ static int do_idedisk_flushcache(ide_drive_t *drive)
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
- if (ide_id_has_flush_cache_ext(drive->id))
- args.tf.command = WIN_FLUSH_CACHE_EXT;
+ if (ata_id_flush_ext_enabled(drive->id))
+ args.tf.command = ATA_CMD_FLUSH_EXT;
else
- args.tf.command = WIN_FLUSH_CACHE;
+ args.tf.command = ATA_CMD_FLUSH;
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
return ide_no_data_taskfile(drive, &args);
}
+ide_devset_get(acoustic, acoustic);
+
static int set_acoustic(ide_drive_t *drive, int arg)
{
- ide_task_t args;
-
if (arg < 0 || arg > 254)
return -EINVAL;
- memset(&args, 0, sizeof(ide_task_t));
- 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);
+ ide_do_setfeature(drive,
+ arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg);
+
drive->acoustic = arg;
+
return 0;
}
+ide_devset_get_flag(addressing, IDE_DFLAG_LBA48);
+
/*
* drive->addressing:
* 0: 28-bit
* 1: 48-bit
* 2: 48-bit capable doing 28-bit
*/
-static int set_lba_addressing(ide_drive_t *drive, int arg)
+static int set_addressing(ide_drive_t *drive, int arg)
{
if (arg < 0 || arg > 2)
return -EINVAL;
- drive->addressing = 0;
+ if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+ ata_id_lba48_enabled(drive->id) == 0))
+ return -EIO;
+
+ if (arg == 2)
+ arg = 0;
- if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
- return 0;
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_LBA48;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_LBA48;
- if (!idedisk_supports_lba48(drive->id))
- return -EIO;
- drive->addressing = arg;
return 0;
}
-#ifdef CONFIG_IDE_PROC_FS
-static void idedisk_add_settings(ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
-
- ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 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, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
- &drive->addressing, set_lba_addressing);
- 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);
- ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
- &drive->wcache, write_cache);
- ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
- &drive->acoustic, set_acoustic);
- ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
- &drive->failures, NULL);
- ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
- 1, 1, &drive->max_failures, NULL);
-}
-#else
-static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
-#endif
+ide_ext_devset_rw(acoustic, acoustic);
+ide_ext_devset_rw(address, addressing);
+ide_ext_devset_rw(multcount, multcount);
+ide_ext_devset_rw(wcache, wcache);
+
+ide_ext_devset_rw_sync(nowerr, nowerr);
static void idedisk_setup(ide_drive_t *drive)
{
+ struct ide_disk_obj *idkp = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
unsigned long long capacity;
- idedisk_add_settings(drive);
+ ide_proc_register_driver(drive, idkp->driver);
- if (drive->id_read == 0)
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0)
return;
- if (drive->removable) {
+ if (drive->dev_flags & IDE_DFLAG_REMOVABLE) {
/*
* Removable disks (eg. SYQUEST); ignore 'WD' drives
*/
- if (id->model[0] != 'W' || id->model[1] != 'D')
- drive->doorlocking = 1;
+ if (m[0] != 'W' || m[1] != 'D')
+ drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
}
- (void)set_lba_addressing(drive, 1);
+ (void)set_addressing(drive, 1);
- if (drive->addressing == 1) {
+ if (drive->dev_flags & IDE_DFLAG_LBA48) {
int max_s = 2048;
if (max_s > hwif->rqsize)
@@ -829,7 +655,8 @@ static void idedisk_setup(ide_drive_t *drive)
init_idedisk_capacity(drive);
/* limit drive capacity to 137GB if LBA48 cannot be used */
- if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
+ if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 &&
+ drive->capacity64 > 1ULL << 28) {
printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
"%llu sectors (%llu MB)\n",
drive->name, (unsigned long long)drive->capacity64,
@@ -837,24 +664,24 @@ static void idedisk_setup(ide_drive_t *drive)
drive->capacity64 = 1ULL << 28;
}
- if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
+ if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
+ (drive->dev_flags & IDE_DFLAG_LBA48)) {
if (drive->capacity64 > 1ULL << 28) {
printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
" will be used for accessing sectors "
"> %u\n", drive->name, 1 << 28);
} else
- drive->addressing = 0;
+ drive->dev_flags &= ~IDE_DFLAG_LBA48;
}
/*
* if possible, give fdisk access to more of the drive,
* by correcting bios_cyls:
*/
- capacity = idedisk_capacity(drive);
-
- if (!drive->forced_geom) {
+ capacity = ide_disk_capacity(drive);
- if (idedisk_supports_lba48(drive->id)) {
+ if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) {
+ if (ata_id_lba48_enabled(drive->id)) {
/* compatibility */
drive->bios_sect = 63;
drive->bios_head = 255;
@@ -880,22 +707,23 @@ static void idedisk_setup(ide_drive_t *drive)
drive->name, capacity, sectors_to_MB(capacity));
/* Only print cache size when it was specified */
- if (id->buf_size)
- printk(KERN_CONT " w/%dKiB Cache", id->buf_size / 2);
+ if (id[ATA_ID_BUF_SIZE])
+ printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
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)))
- drive->wcache = 1;
+ if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
+ drive->dev_flags |= IDE_DFLAG_WCACHE;
- write_cache(drive, 1);
+ set_wcache(drive, 1);
}
static void ide_cacheflush_p(ide_drive_t *drive)
{
- if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
+ if (ata_id_flush_enabled(drive->id) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
return;
if (do_idedisk_flushcache(drive))
@@ -937,7 +765,7 @@ static int ide_disk_probe(ide_drive_t *drive);
*/
static void ide_disk_resume(ide_drive_t *drive)
{
- if (idedisk_supports_hpa(drive->id))
+ if (ata_id_hpa_enabled(drive->id))
init_idedisk_capacity(drive);
}
@@ -979,14 +807,12 @@ static ide_driver_t idedisk_driver = {
.resume = ide_disk_resume,
.shutdown = ide_device_shutdown,
.version = IDEDISK_VERSION,
- .media = ide_disk,
- .supports_dsc_overlap = 0,
.do_request = ide_do_rw_disk,
.end_request = ide_end_request,
.error = __ide_error,
- .abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
- .proc = idedisk_proc,
+ .proc = ide_disk_proc,
+ .settings = ide_disk_settings,
#endif
};
@@ -995,7 +821,7 @@ 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.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
return ide_no_data_taskfile(drive, &task);
@@ -1015,15 +841,16 @@ static int idedisk_open(struct inode *inode, struct file *filp)
idkp->openers++;
- if (drive->removable && idkp->openers == 1) {
+ if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
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 && idedisk_set_doorlock(drive, 1))
- drive->doorlocking = 0;
+ if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
+ idedisk_set_doorlock(drive, 1))
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
}
return 0;
}
@@ -1037,9 +864,10 @@ static int idedisk_release(struct inode *inode, struct file *filp)
if (idkp->openers == 1)
ide_cacheflush_p(drive);
- if (drive->removable && idkp->openers == 1) {
- if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
- drive->doorlocking = 0;
+ if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
+ if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
+ idedisk_set_doorlock(drive, 0))
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
}
idkp->openers--;
@@ -1060,72 +888,25 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int idedisk_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- unsigned long flags;
- struct block_device *bdev = inode->i_bdev;
- struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
- ide_drive_t *drive = idkp->drive;
- int err, (*setfunc)(ide_drive_t *, int);
- u8 *val;
-
- switch (cmd) {
- case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
- case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
- case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
- case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
- case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
- case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
- case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
- case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
- case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
- case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
- }
-
- return generic_ide_ioctl(drive, file, bdev, cmd, arg);
-
-read_val:
- mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
- err = *val;
- spin_unlock_irqrestore(&ide_lock, flags);
- mutex_unlock(&ide_setting_mtx);
- return err >= 0 ? put_user(err, (long __user *)arg) : err;
-
-set_val:
- if (bdev != bdev->bd_contains)
- err = -EINVAL;
- else {
- if (!capable(CAP_SYS_ADMIN))
- err = -EACCES;
- else {
- mutex_lock(&ide_setting_mtx);
- err = setfunc(drive, arg);
- mutex_unlock(&ide_setting_mtx);
- }
- }
- return err;
-}
-
static int idedisk_media_changed(struct gendisk *disk)
{
struct ide_disk_obj *idkp = ide_disk_g(disk);
ide_drive_t *drive = idkp->drive;
/* do not scan partitions twice if this is a removable device */
- if (drive->attach) {
- drive->attach = 0;
+ if (drive->dev_flags & IDE_DFLAG_ATTACH) {
+ drive->dev_flags &= ~IDE_DFLAG_ATTACH;
return 0;
}
+
/* if removable, always assume it was changed */
- return drive->removable;
+ return !!(drive->dev_flags & IDE_DFLAG_REMOVABLE);
}
static int idedisk_revalidate_disk(struct gendisk *disk)
{
struct ide_disk_obj *idkp = ide_disk_g(disk);
- set_capacity(disk, idedisk_capacity(idkp->drive));
+ set_capacity(disk, ide_disk_capacity(idkp->drive));
return 0;
}
@@ -1133,7 +914,7 @@ static struct block_device_operations idedisk_ops = {
.owner = THIS_MODULE,
.open = idedisk_open,
.release = idedisk_release,
- .ioctl = idedisk_ioctl,
+ .ioctl = ide_disk_ioctl,
.getgeo = idedisk_getgeo,
.media_changed = idedisk_media_changed,
.revalidate_disk = idedisk_revalidate_disk
@@ -1149,8 +930,7 @@ static int ide_disk_probe(ide_drive_t *drive)
/* strstr("foo", "") is non-NULL */
if (!strstr("ide-disk", drive->driver_req))
goto failed;
- if (!drive->present)
- goto failed;
+
if (drive->media != ide_disk)
goto failed;
@@ -1158,15 +938,12 @@ static int ide_disk_probe(ide_drive_t *drive)
if (!idkp)
goto failed;
- g = alloc_disk_node(1 << PARTN_BITS,
- hwif_to_node(drive->hwif));
+ g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
if (!g)
goto out_free_idkp;
ide_init_disk(g, drive);
- ide_proc_register_driver(drive, &idedisk_driver);
-
kref_init(&idkp->kref);
idkp->drive = drive;
@@ -1178,17 +955,20 @@ static int ide_disk_probe(ide_drive_t *drive)
drive->driver_data = idkp;
idedisk_setup(drive);
- if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
+ if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&
+ (drive->head == 0 || drive->head > 16)) {
printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
drive->name, drive->head);
- drive->attach = 0;
+ drive->dev_flags &= ~IDE_DFLAG_ATTACH;
} else
- drive->attach = 1;
+ drive->dev_flags |= IDE_DFLAG_ATTACH;
- g->minors = 1 << PARTN_BITS;
+ g->minors = IDE_DISK_MINORS;
g->driverfs_dev = &drive->gendev;
- g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
- set_capacity(g, idedisk_capacity(drive));
+ g->flags |= GENHD_FL_EXT_DEVT;
+ if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
+ g->flags = GENHD_FL_REMOVABLE;
+ set_capacity(g, ide_disk_capacity(drive));
g->fops = &idedisk_ops;
add_disk(g);
return 0;
@@ -1210,6 +990,7 @@ static int __init idedisk_init(void)
}
MODULE_ALIAS("ide:*m-disk*");
+MODULE_ALIAS("ide-disk");
module_init(idedisk_init);
module_exit(idedisk_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-disk.h b/drivers/ide/ide-disk.h
new file mode 100644
index 00000000000..a82fa435566
--- /dev/null
+++ b/drivers/ide/ide-disk.h
@@ -0,0 +1,32 @@
+#ifndef __IDE_DISK_H
+#define __IDE_DISK_H
+
+struct ide_disk_obj {
+ ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
+ struct kref kref;
+ unsigned int openers; /* protected by BKL for now */
+};
+
+#define ide_disk_g(disk) \
+ container_of((disk)->private_data, struct ide_disk_obj, driver)
+
+/* ide-disk.c */
+sector_t ide_disk_capacity(ide_drive_t *);
+ide_decl_devset(address);
+ide_decl_devset(multcount);
+ide_decl_devset(nowerr);
+ide_decl_devset(wcache);
+ide_decl_devset(acoustic);
+
+/* ide-disk_ioctl.c */
+int ide_disk_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+
+#ifdef CONFIG_IDE_PROC_FS
+/* ide-disk_proc.c */
+extern ide_proc_entry_t ide_disk_proc[];
+extern const struct ide_proc_devset ide_disk_settings[];
+#endif
+
+#endif /* __IDE_DISK_H */
diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c
new file mode 100644
index 00000000000..a6cf1a03a80
--- /dev/null
+++ b/drivers/ide/ide-disk_ioctl.c
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/hdreg.h>
+
+#include "ide-disk.h"
+
+static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
+{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
+{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
+{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
+{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
+{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
+{ 0 }
+};
+
+int ide_disk_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
+ ide_drive_t *drive = idkp->drive;
+ int err;
+
+ err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
+ if (err != -EOPNOTSUPP)
+ return err;
+
+ return generic_ide_ioctl(drive, file, bdev, cmd, arg);
+}
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c
new file mode 100644
index 00000000000..4724976afe7
--- /dev/null
+++ b/drivers/ide/ide-disk_proc.c
@@ -0,0 +1,129 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/hdreg.h>
+
+#include "ide-disk.h"
+
+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));
+ tf->feature = ATA_SMART_ENABLE;
+ tf->lbam = ATA_SMART_LBAM_PASS;
+ tf->lbah = ATA_SMART_LBAH_PASS;
+ tf->command = ATA_CMD_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));
+ tf->feature = sub_cmd;
+ tf->nsect = 0x01;
+ tf->lbam = ATA_SMART_LBAM_PASS;
+ tf->lbah = ATA_SMART_LBAH_PASS;
+ tf->command = ATA_CMD_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, 1);
+}
+
+static int proc_idedisk_read_cache
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ ide_drive_t *drive = (ide_drive_t *) data;
+ char *out = page;
+ int len;
+
+ if (drive->dev_flags & IDE_DFLAG_ID_READ)
+ len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
+ else
+ len = sprintf(out, "(none)\n");
+
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_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)ide_disk_capacity(drive));
+
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_read_smart(char *page, char **start, off_t off,
+ int count, int *eof, void *data, u8 sub_cmd)
+{
+ ide_drive_t *drive = (ide_drive_t *)data;
+ int len = 0, i = 0;
+
+ if (get_smart_data(drive, page, sub_cmd) == 0) {
+ unsigned short *val = (unsigned short *) page;
+ char *out = (char *)val + SECTOR_SIZE;
+
+ page = out;
+ do {
+ out += sprintf(out, "%04x%c", le16_to_cpu(*val),
+ (++i & 7) ? ' ' : '\n');
+ val += 1;
+ } while (i < SECTOR_SIZE / 2);
+ len = out - page;
+ }
+
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_read_sv
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ return proc_idedisk_read_smart(page, start, off, count, eof, data,
+ ATA_SMART_READ_VALUES);
+}
+
+static int proc_idedisk_read_st
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ return proc_idedisk_read_smart(page, start, off, count, eof, data,
+ ATA_SMART_READ_THRESHOLDS);
+}
+
+ide_proc_entry_t ide_disk_proc[] = {
+ { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
+ { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
+ { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
+ { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
+ { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
+ { NULL, 0, NULL, NULL }
+};
+
+ide_devset_rw_field(bios_cyl, bios_cyl);
+ide_devset_rw_field(bios_head, bios_head);
+ide_devset_rw_field(bios_sect, bios_sect);
+ide_devset_rw_field(failures, failures);
+ide_devset_rw_field(lun, lun);
+ide_devset_rw_field(max_failures, max_failures);
+
+const struct ide_proc_devset ide_disk_settings[] = {
+ IDE_PROC_DEVSET(acoustic, 0, 254),
+ IDE_PROC_DEVSET(address, 0, 2),
+ IDE_PROC_DEVSET(bios_cyl, 0, 65535),
+ IDE_PROC_DEVSET(bios_head, 0, 255),
+ IDE_PROC_DEVSET(bios_sect, 0, 63),
+ IDE_PROC_DEVSET(failures, 0, 65535),
+ IDE_PROC_DEVSET(lun, 0, 7),
+ IDE_PROC_DEVSET(max_failures, 0, 65535),
+ IDE_PROC_DEVSET(multcount, 0, 16),
+ IDE_PROC_DEVSET(nowerr, 0, 1),
+ IDE_PROC_DEVSET(wcache, 0, 1),
+ { 0 },
+};
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c
new file mode 100644
index 00000000000..0903782689e
--- /dev/null
+++ b/drivers/ide/ide-dma-sff.c
@@ -0,0 +1,356 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+/**
+ * config_drive_for_dma - attempt to activate IDE DMA
+ * @drive: the drive to place in DMA mode
+ *
+ * If the drive supports at least mode 2 DMA or UDMA of any kind
+ * then attempt to place it into DMA mode. Drives that are known to
+ * support DMA but predate the DMA properties or that are known
+ * to have DMA handling bugs are also set up appropriately based
+ * on the good/bad drive lists.
+ */
+
+int config_drive_for_dma(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u16 *id = drive->id;
+
+ if (drive->media != ide_disk) {
+ if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
+ return 0;
+ }
+
+ /*
+ * Enable DMA on any drive that has
+ * UltraDMA (mode 0/1/2/3/4/5/6) enabled
+ */
+ if ((id[ATA_ID_FIELD_VALID] & 4) &&
+ ((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
+ return 1;
+
+ /*
+ * Enable DMA on any drive that has mode2 DMA
+ * (multi or single) enabled
+ */
+ if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */
+ if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
+ (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
+ return 1;
+
+ /* Consult the list of known "good" drives */
+ if (ide_dma_good_drive(drive))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * ide_dma_host_set - Enable/disable DMA on a host
+ * @drive: drive to control
+ *
+ * Enable/disable DMA on an IDE controller following generic
+ * bus-mastering IDE controller behaviour.
+ */
+
+void ide_dma_host_set(ide_drive_t *drive, int on)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 unit = drive->dn & 1;
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ if (on)
+ dma_stat |= (1 << (5 + unit));
+ else
+ dma_stat &= ~(1 << (5 + unit));
+
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(dma_stat,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ide_dma_host_set);
+
+/**
+ * ide_build_dmatable - build IDE DMA table
+ *
+ * ide_build_dmatable() prepares a dma request. We map the command
+ * to get the pci bus addresses of the buffers and then build up
+ * the PRD table that the IDE layer wants to be fed.
+ *
+ * Most chipsets correctly interpret a length of 0x0000 as 64KB,
+ * but at least one (e.g. CS5530) misinterprets it as zero (!).
+ * So we break the 64KB entry into two 32KB entries instead.
+ *
+ * Returns the number of built PRD entries if all went okay,
+ * returns 0 otherwise.
+ *
+ * May also be invoked from trm290.c
+ */
+
+int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ __le32 *table = (__le32 *)hwif->dmatable_cpu;
+ unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
+ unsigned int count = 0;
+ int i;
+ struct scatterlist *sg;
+
+ hwif->sg_nents = ide_build_sglist(drive, rq);
+ if (hwif->sg_nents == 0)
+ return 0;
+
+ for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
+ u32 cur_addr, cur_len, xcount, bcount;
+
+ cur_addr = sg_dma_address(sg);
+ cur_len = sg_dma_len(sg);
+
+ /*
+ * Fill in the dma table, without crossing any 64kB boundaries.
+ * Most hardware requires 16-bit alignment of all blocks,
+ * but the trm290 requires 32-bit alignment.
+ */
+
+ while (cur_len) {
+ if (count++ >= PRD_ENTRIES)
+ goto use_pio_instead;
+
+ bcount = 0x10000 - (cur_addr & 0xffff);
+ if (bcount > cur_len)
+ bcount = cur_len;
+ *table++ = cpu_to_le32(cur_addr);
+ xcount = bcount & 0xffff;
+ if (is_trm290)
+ xcount = ((xcount >> 2) - 1) << 16;
+ if (xcount == 0x0000) {
+ if (count++ >= PRD_ENTRIES)
+ goto use_pio_instead;
+ *table++ = cpu_to_le32(0x8000);
+ *table++ = cpu_to_le32(cur_addr + 0x8000);
+ xcount = 0x8000;
+ }
+ *table++ = cpu_to_le32(xcount);
+ cur_addr += bcount;
+ cur_len -= bcount;
+ }
+ }
+
+ if (count) {
+ if (!is_trm290)
+ *--table |= cpu_to_le32(0x80000000);
+ return count;
+ }
+
+use_pio_instead:
+ printk(KERN_ERR "%s: %s\n", drive->name,
+ count ? "DMA table too small" : "empty DMA table?");
+
+ ide_destroy_dmatable(drive);
+
+ return 0; /* revert to PIO for this request */
+}
+EXPORT_SYMBOL_GPL(ide_build_dmatable);
+
+/**
+ * ide_dma_setup - begin a DMA phase
+ * @drive: target device
+ *
+ * Build an IDE DMA PRD (IDE speak for scatter gather table)
+ * and then set up the DMA transfer registers for a device
+ * that follows generic IDE PCI DMA behaviour. Controllers can
+ * override this function if they need to
+ *
+ * Returns 0 on success. If a PIO fallback is required then 1
+ * is returned.
+ */
+
+int ide_dma_setup(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
+ unsigned int reading;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+ u8 dma_stat;
+
+ if (rq_data_dir(rq))
+ reading = 0;
+ else
+ reading = 1 << 3;
+
+ /* fall back to pio! */
+ if (!ide_build_dmatable(drive, rq)) {
+ ide_map_sg(drive, rq);
+ return 1;
+ }
+
+ /* PRD table */
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writel(hwif->dmatable_dma,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
+ else
+ outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
+
+ /* specify r/w */
+ if (mmio)
+ writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ else
+ outb(reading, hwif->dma_base + ATA_DMA_CMD);
+
+ /* read DMA status for INTR & ERROR flags */
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ /* clear INTR & ERROR flags */
+ if (mmio)
+ writeb(dma_stat | 6,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
+ drive->waiting_for_dma = 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_setup);
+
+/**
+ * dma_timer_expiry - handle a DMA timeout
+ * @drive: Drive that timed out
+ *
+ * An IDE DMA transfer timed out. In the event of an error we ask
+ * the driver to resolve the problem, if a DMA transfer is still
+ * in progress we continue to wait (arguably we need to add a
+ * secondary 'I don't care what the drive thinks' timeout here)
+ * Finally if we have an interrupt we let it complete the I/O.
+ * But only one time - we clear expiry and if it's still not
+ * completed after WAIT_CMD, we error and retry in PIO.
+ * This can occur if an interrupt is lost or due to hang or bugs.
+ */
+
+static int dma_timer_expiry(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n",
+ drive->name, __func__, dma_stat);
+
+ if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */
+ return WAIT_CMD;
+
+ hwif->hwgroup->expiry = NULL; /* one free ride for now */
+
+ /* 1 dmaing, 2 error, 4 intr */
+ if (dma_stat & 2) /* ERROR */
+ return -1;
+
+ if (dma_stat & 1) /* DMAing */
+ return WAIT_CMD;
+
+ if (dma_stat & 4) /* Got an Interrupt */
+ return WAIT_CMD;
+
+ return 0; /* Status is unknown -- reset the bus */
+}
+
+void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+{
+ /* issue cmd to drive */
+ ide_execute_command(drive, command, &ide_dma_intr, 2 * WAIT_CMD,
+ dma_timer_expiry);
+}
+EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
+
+void ide_dma_start(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_cmd;
+
+ /* Note that this is done *after* the cmd has
+ * been issued to the drive, as per the BM-IDE spec.
+ * The Promise Ultra33 doesn't work correctly when
+ * we do this part before issuing the drive cmd.
+ */
+ if (hwif->host_flags & IDE_HFLAG_MMIO) {
+ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ /* start DMA */
+ writeb(dma_cmd | 1,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ } else {
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
+ }
+
+ wmb();
+}
+EXPORT_SYMBOL_GPL(ide_dma_start);
+
+/* returns 1 on error, 0 otherwise */
+int ide_dma_end(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+ u8 dma_stat = 0, dma_cmd = 0;
+
+ drive->waiting_for_dma = 0;
+
+ if (mmio) {
+ /* get DMA command mode */
+ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ /* stop DMA */
+ writeb(dma_cmd & ~1,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ } else {
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+ }
+
+ /* get DMA status */
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ if (mmio)
+ /* clear the INTR & ERROR bits */
+ writeb(dma_stat | 6,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
+ /* purge DMA mappings */
+ ide_destroy_dmatable(drive);
+ /* verify good DMA status */
+ wmb();
+ return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_end);
+
+/* returns 1 if dma irq issued, 0 otherwise */
+int ide_dma_test_irq(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ /* return 1 if INTR asserted */
+ if ((dma_stat & 4) == 4)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_test_irq);
+
+const struct ide_dma_ops sff_dma_ops = {
+ .dma_host_set = ide_dma_host_set,
+ .dma_setup = ide_dma_setup,
+ .dma_exec_cmd = ide_dma_exec_cmd,
+ .dma_start = ide_dma_start,
+ .dma_end = ide_dma_end,
+ .dma_test_irq = ide_dma_test_irq,
+ .dma_timeout = ide_dma_timeout,
+ .dma_lost_irq = ide_dma_lost_irq,
+};
+EXPORT_SYMBOL_GPL(sff_dma_ops);
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 653b1ade13d..fffd11717b2 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -28,24 +28,13 @@
* for supplying a Promise UDMA board & WD UDMA drive for this work!
*/
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
#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>
-
-static const struct drive_list_entry drive_whitelist [] = {
-
+static const struct drive_list_entry drive_whitelist[] = {
{ "Micropolis 2112A" , NULL },
{ "CONNER CTMA 4000" , NULL },
{ "CONNER CTT8000-A" , NULL },
@@ -53,8 +42,7 @@ static const struct drive_list_entry drive_whitelist [] = {
{ NULL , NULL }
};
-static const struct drive_list_entry drive_blacklist [] = {
-
+static const struct drive_list_entry drive_blacklist[] = {
{ "WDC AC11000H" , NULL },
{ "WDC AC22100H" , NULL },
{ "WDC AC32500H" , NULL },
@@ -94,33 +82,33 @@ static const struct drive_list_entry drive_blacklist [] = {
* ide_dma_intr - IDE DMA interrupt handler
* @drive: the drive the interrupt is for
*
- * Handle an interrupt completing a read/write DMA transfer on an
+ * Handle an interrupt completing a read/write DMA transfer on an
* IDE device
*/
-
-ide_startstop_t ide_dma_intr (ide_drive_t *drive)
+
+ide_startstop_t ide_dma_intr(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
u8 stat = 0, dma_stat = 0;
- dma_stat = drive->hwif->dma_ops->dma_end(drive);
- stat = ide_read_status(drive);
+ dma_stat = hwif->dma_ops->dma_end(drive);
+ stat = hwif->tp_ops->read_status(hwif);
- if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
+ if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
if (!dma_stat) {
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = hwif->hwgroup->rq;
task_end_request(drive, rq, stat);
return ide_stopped;
}
- printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
- drive->name, dma_stat);
+ printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n",
+ drive->name, __func__, dma_stat);
}
return ide_error(drive, "dma_intr", stat);
}
-
EXPORT_SYMBOL_GPL(ide_dma_intr);
-static int ide_dma_good_drive(ide_drive_t *drive)
+int ide_dma_good_drive(ide_drive_t *drive)
{
return ide_in_drive_list(drive->id, drive_whitelist);
}
@@ -138,7 +126,7 @@ static int ide_dma_good_drive(ide_drive_t *drive)
int ide_build_sglist(ide_drive_t *drive, struct request *rq)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct scatterlist *sg = hwif->sg_table;
ide_map_sg(drive, rq);
@@ -151,106 +139,8 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
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_SFF
-/**
- * ide_build_dmatable - build IDE DMA table
- *
- * ide_build_dmatable() prepares a dma request. We map the command
- * to get the pci bus addresses of the buffers and then build up
- * the PRD table that the IDE layer wants to be fed. The code
- * knows about the 64K wrap bug in the CS5530.
- *
- * Returns the number of built PRD entries if all went okay,
- * returns 0 otherwise.
- *
- * May also be invoked from trm290.c
- */
-
-int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
-{
- ide_hwif_t *hwif = HWIF(drive);
- unsigned int *table = hwif->dmatable_cpu;
- unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
- unsigned int count = 0;
- int i;
- struct scatterlist *sg;
-
- hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
- if (!i)
- return 0;
-
- sg = hwif->sg_table;
- while (i) {
- u32 cur_addr;
- u32 cur_len;
-
- cur_addr = sg_dma_address(sg);
- cur_len = sg_dma_len(sg);
-
- /*
- * Fill in the dma table, without crossing any 64kB boundaries.
- * Most hardware requires 16-bit alignment of all blocks,
- * but the trm290 requires 32-bit alignment.
- */
-
- while (cur_len) {
- if (count++ >= PRD_ENTRIES) {
- printk(KERN_ERR "%s: DMA table too small\n", drive->name);
- goto use_pio_instead;
- } else {
- u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
-
- if (bcount > cur_len)
- bcount = cur_len;
- *table++ = cpu_to_le32(cur_addr);
- xcount = bcount & 0xffff;
- if (is_trm290)
- xcount = ((xcount >> 2) - 1) << 16;
- if (xcount == 0x0000) {
- /*
- * Most chipsets correctly interpret a length of 0x0000 as 64KB,
- * but at least one (e.g. CS5530) misinterprets it as zero (!).
- * So here we break the 64KB entry into two 32KB entries instead.
- */
- if (count++ >= PRD_ENTRIES) {
- printk(KERN_ERR "%s: DMA table too small\n", drive->name);
- goto use_pio_instead;
- }
- *table++ = cpu_to_le32(0x8000);
- *table++ = cpu_to_le32(cur_addr + 0x8000);
- xcount = 0x8000;
- }
- *table++ = cpu_to_le32(xcount);
- cur_addr += bcount;
- cur_len -= bcount;
- }
- }
-
- sg = sg_next(sg);
- i--;
- }
-
- if (count) {
- if (!is_trm290)
- *--table |= cpu_to_le32(0x80000000);
- return count;
- }
-
- printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
-
-use_pio_instead:
- 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
* @drive: The drive to unmap
@@ -261,142 +151,30 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
* an oops as only one mapping can be live for each target at a given
* time.
*/
-
-void ide_destroy_dmatable (ide_drive_t *drive)
+
+void ide_destroy_dmatable(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
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_SFF
-/**
- * config_drive_for_dma - attempt to activate IDE DMA
- * @drive: the drive to place in DMA mode
- *
- * If the drive supports at least mode 2 DMA or UDMA of any kind
- * then attempt to place it into DMA mode. Drives that are known to
- * support DMA but predate the DMA properties or that are known
- * to have DMA handling bugs are also set up appropriately based
- * on the good/bad drive lists.
- */
-
-static int config_drive_for_dma (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid *id = drive->id;
-
- if (drive->media != ide_disk) {
- if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
- return 0;
- }
-
- /*
- * Enable DMA on any drive that has
- * UltraDMA (mode 0/1/2/3/4/5/6) enabled
- */
- if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f))
- return 1;
-
- /*
- * Enable DMA on any drive that has mode2 DMA
- * (multi or single) enabled
- */
- if (id->field_valid & 2) /* regular DMA */
- if ((id->dma_mword & 0x404) == 0x404 ||
- (id->dma_1word & 0x404) == 0x404)
- return 1;
-
- /* Consult the list of known "good" drives */
- if (ide_dma_good_drive(drive))
- return 1;
-
- return 0;
-}
-
-/**
- * dma_timer_expiry - handle a DMA timeout
- * @drive: Drive that timed out
- *
- * An IDE DMA transfer timed out. In the event of an error we ask
- * the driver to resolve the problem, if a DMA transfer is still
- * in progress we continue to wait (arguably we need to add a
- * secondary 'I don't care what the drive thinks' timeout here)
- * Finally if we have an interrupt we let it complete the I/O.
- * But only one time - we clear expiry and if it's still not
- * completed after WAIT_CMD, we error and retry in PIO.
- * This can occur if an interrupt is lost or due to hang or bugs.
- */
-
-static int dma_timer_expiry (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->INB(hwif->dma_status);
-
- printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
- drive->name, dma_stat);
-
- if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */
- return WAIT_CMD;
-
- HWGROUP(drive)->expiry = NULL; /* one free ride for now */
-
- /* 1 dmaing, 2 error, 4 intr */
- if (dma_stat & 2) /* ERROR */
- return -1;
-
- if (dma_stat & 1) /* DMAing */
- return WAIT_CMD;
-
- if (dma_stat & 4) /* Got an Interrupt */
- return WAIT_CMD;
-
- return 0; /* Status is unknown -- reset the bus */
-}
-
-/**
- * ide_dma_host_set - Enable/disable DMA on a host
- * @drive: drive to control
- *
- * Enable/disable DMA on an IDE controller following generic
- * bus-mastering IDE controller behaviour.
- */
-
-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);
-
- if (on)
- dma_stat |= (1 << (5 + unit));
- else
- dma_stat &= ~(1 << (5 + unit));
-
- hwif->OUTB(dma_stat, hwif->dma_status);
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_host_set);
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
-
/**
* ide_dma_off_quietly - Generic DMA kill
* @drive: drive to control
*
- * Turn off the current DMA on this IDE controller.
+ * Turn off the current DMA on this IDE controller.
*/
void ide_dma_off_quietly(ide_drive_t *drive)
{
- drive->using_dma = 0;
+ drive->dev_flags &= ~IDE_DFLAG_USING_DMA;
ide_toggle_bounce(drive, 0);
drive->hwif->dma_ops->dma_host_set(drive, 0);
}
-
EXPORT_SYMBOL(ide_dma_off_quietly);
/**
@@ -412,7 +190,6 @@ void ide_dma_off(ide_drive_t *drive)
printk(KERN_INFO "%s: DMA disabled\n", drive->name);
ide_dma_off_quietly(drive);
}
-
EXPORT_SYMBOL(ide_dma_off);
/**
@@ -424,147 +201,24 @@ EXPORT_SYMBOL(ide_dma_off);
void ide_dma_on(ide_drive_t *drive)
{
- drive->using_dma = 1;
+ drive->dev_flags |= IDE_DFLAG_USING_DMA;
ide_toggle_bounce(drive, 1);
drive->hwif->dma_ops->dma_host_set(drive, 1);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- * ide_dma_setup - begin a DMA phase
- * @drive: target device
- *
- * Build an IDE DMA PRD (IDE speak for scatter gather table)
- * and then set up the DMA transfer registers for a device
- * that follows generic IDE PCI DMA behaviour. Controllers can
- * override this function if they need to
- *
- * Returns 0 on success. If a PIO fallback is required then 1
- * is returned.
- */
-
-int ide_dma_setup(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct request *rq = HWGROUP(drive)->rq;
- unsigned int reading;
- u8 dma_stat;
-
- if (rq_data_dir(rq))
- reading = 0;
- else
- reading = 1 << 3;
-
- /* fall back to pio! */
- if (!ide_build_dmatable(drive, rq)) {
- ide_map_sg(drive, rq);
- return 1;
- }
-
- /* PRD table */
- if (hwif->mmio)
- writel(hwif->dmatable_dma,
- (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
- else
- outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
-
- /* specify r/w */
- hwif->OUTB(reading, hwif->dma_command);
-
- /* read dma_status for INTR & ERROR flags */
- dma_stat = hwif->INB(hwif->dma_status);
-
- /* clear INTR & ERROR flags */
- hwif->OUTB(dma_stat|6, hwif->dma_status);
- drive->waiting_for_dma = 1;
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_setup);
-
-void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+int __ide_dma_bad_drive(ide_drive_t *drive)
{
- /* issue cmd to drive */
- ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
-}
-EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
-
-void ide_dma_start(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 dma_cmd = hwif->INB(hwif->dma_command);
-
- /* Note that this is done *after* the cmd has
- * been issued to the drive, as per the BM-IDE spec.
- * The Promise Ultra33 doesn't work correctly when
- * we do this part before issuing the drive cmd.
- */
- /* start DMA */
- hwif->OUTB(dma_cmd|1, hwif->dma_command);
- hwif->dma = 1;
- wmb();
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_start);
-
-/* returns 1 on error, 0 otherwise */
-int __ide_dma_end (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = 0, dma_cmd = 0;
-
- drive->waiting_for_dma = 0;
- /* get dma_command mode */
- dma_cmd = hwif->INB(hwif->dma_command);
- /* stop DMA */
- hwif->OUTB(dma_cmd&~1, hwif->dma_command);
- /* get DMA status */
- dma_stat = hwif->INB(hwif->dma_status);
- /* clear the INTR & ERROR bits */
- hwif->OUTB(dma_stat|6, hwif->dma_status);
- /* purge DMA mappings */
- ide_destroy_dmatable(drive);
- /* verify good DMA status */
- hwif->dma = 0;
- wmb();
- return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
-}
-
-EXPORT_SYMBOL(__ide_dma_end);
-
-/* returns 1 if dma irq issued, 0 otherwise */
-int ide_dma_test_irq(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->INB(hwif->dma_status);
-
- /* return 1 if INTR asserted */
- if ((dma_stat & 4) == 4)
- return 1;
- if (!drive->waiting_for_dma)
- printk(KERN_WARNING "%s: (%s) called while not waiting\n",
- drive->name, __func__);
- return 0;
-}
-EXPORT_SYMBOL_GPL(ide_dma_test_irq);
-#else
-static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
-
-int __ide_dma_bad_drive (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
int blacklist = ide_in_drive_list(id, drive_blacklist);
if (blacklist) {
printk(KERN_WARNING "%s: Disabling (U)DMA for %s (blacklisted)\n",
- drive->name, id->model);
+ drive->name, (char *)&id[ATA_ID_PROD]);
return blacklist;
}
return 0;
}
-
EXPORT_SYMBOL(__ide_dma_bad_drive);
static const u8 xfer_mode_bases[] = {
@@ -575,21 +229,21 @@ static const u8 xfer_mode_bases[] = {
static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
unsigned int mask = 0;
- switch(base) {
+ switch (base) {
case XFER_UDMA_0:
- if ((id->field_valid & 4) == 0)
+ if ((id[ATA_ID_FIELD_VALID] & 4) == 0)
break;
if (port_ops && port_ops->udma_filter)
mask = port_ops->udma_filter(drive);
else
mask = hwif->ultra_mask;
- mask &= id->dma_ultra;
+ mask &= id[ATA_ID_UDMA_MODES];
/*
* avoid false cable warning from eighty_ninty_three()
@@ -600,23 +254,19 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
}
break;
case XFER_MW_DMA_0:
- if ((id->field_valid & 2) == 0)
+ if ((id[ATA_ID_FIELD_VALID] & 2) == 0)
break;
if (port_ops && port_ops->mdma_filter)
mask = port_ops->mdma_filter(drive);
else
mask = hwif->mwdma_mask;
- mask &= id->dma_mword;
+ mask &= id[ATA_ID_MWDMA_MODES];
break;
case XFER_SW_DMA_0:
- if (id->field_valid & 2) {
- mask = id->dma_1word & hwif->swdma_mask;
- } else if (id->tDMA) {
- /*
- * ide_fix_driveid() doesn't convert ->tDMA to the
- * CPU endianness so we need to do it here
- */
- u8 mode = le16_to_cpu(id->tDMA);
+ if (id[ATA_ID_FIELD_VALID] & 2) {
+ mask = id[ATA_ID_SWDMA_MODES] & hwif->swdma_mask;
+ } else if (id[ATA_ID_OLD_DMA_MODES] >> 8) {
+ u8 mode = id[ATA_ID_OLD_DMA_MODES] >> 8;
/*
* if the mode is valid convert it to the mask
@@ -673,7 +323,8 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
/*
* is this correct?
*/
- if (ide_dma_good_drive(drive) && drive->id->eide_dma_time < 150)
+ if (ide_dma_good_drive(drive) &&
+ drive->id[ATA_ID_EIDE_DMA_TIME] < 150)
mode = XFER_MW_DMA_1;
}
@@ -684,7 +335,6 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
return mode;
}
-
EXPORT_SYMBOL_GPL(ide_find_dma_mode);
static int ide_tune_dma(ide_drive_t *drive)
@@ -692,7 +342,8 @@ 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)
+ if (ata_id_has_dma(drive->id) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_NODMA))
return 0;
/* consult the list of known "bad" drives */
@@ -719,9 +370,8 @@ static int ide_tune_dma(ide_drive_t *drive)
static int ide_dma_check(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- int vdma = (hwif->host_flags & IDE_HFLAG_VDMA)? 1 : 0;
- if (!vdma && ide_tune_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
/* TODO: always do PIO fallback */
@@ -730,18 +380,20 @@ static int ide_dma_check(ide_drive_t *drive)
ide_set_max_pio(drive);
- return vdma ? 0 : -1;
+ return -1;
}
int ide_id_dma_bug(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
- if (id->field_valid & 4) {
- if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))
+ if (id[ATA_ID_FIELD_VALID] & 4) {
+ if ((id[ATA_ID_UDMA_MODES] >> 8) &&
+ (id[ATA_ID_MWDMA_MODES] >> 8))
goto err_out;
- } else if (id->field_valid & 2) {
- if ((id->dma_mword >> 8) && (id->dma_1word >> 8))
+ } else if (id[ATA_ID_FIELD_VALID] & 2) {
+ if ((id[ATA_ID_MWDMA_MODES] >> 8) &&
+ (id[ATA_ID_SWDMA_MODES] >> 8))
goto err_out;
}
return 0;
@@ -791,79 +443,59 @@ void ide_check_dma_crc(ide_drive_t *drive)
ide_dma_on(drive);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-void ide_dma_lost_irq (ide_drive_t *drive)
+void ide_dma_lost_irq(ide_drive_t *drive)
{
- printk("%s: DMA interrupt recovery\n", drive->name);
+ printk(KERN_ERR "%s: DMA interrupt recovery\n", drive->name);
}
+EXPORT_SYMBOL_GPL(ide_dma_lost_irq);
-EXPORT_SYMBOL(ide_dma_lost_irq);
-
-void ide_dma_timeout (ide_drive_t *drive)
+void ide_dma_timeout(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
if (hwif->dma_ops->dma_test_irq(drive))
return;
+ ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
+
hwif->dma_ops->dma_end(drive);
}
-
-EXPORT_SYMBOL(ide_dma_timeout);
+EXPORT_SYMBOL_GPL(ide_dma_timeout);
void ide_release_dma_engine(ide_hwif_t *hwif)
{
if (hwif->dmatable_cpu) {
- struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ int prd_size = hwif->prd_max_nents * hwif->prd_ent_size;
- pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
- hwif->dmatable_cpu, hwif->dmatable_dma);
+ dma_free_coherent(hwif->dev, prd_size,
+ hwif->dmatable_cpu, hwif->dmatable_dma);
hwif->dmatable_cpu = NULL;
}
}
+EXPORT_SYMBOL_GPL(ide_release_dma_engine);
int ide_allocate_dma_engine(ide_hwif_t *hwif)
{
- struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ int prd_size;
- hwif->dmatable_cpu = pci_alloc_consistent(pdev,
- PRD_ENTRIES * PRD_BYTES,
- &hwif->dmatable_dma);
+ if (hwif->prd_max_nents == 0)
+ hwif->prd_max_nents = PRD_ENTRIES;
+ if (hwif->prd_ent_size == 0)
+ hwif->prd_ent_size = PRD_BYTES;
- if (hwif->dmatable_cpu)
- return 0;
+ prd_size = hwif->prd_max_nents * hwif->prd_ent_size;
- printk(KERN_ERR "%s: -- Error, unable to allocate DMA table.\n",
+ hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev, prd_size,
+ &hwif->dmatable_dma,
+ GFP_ATOMIC);
+ if (hwif->dmatable_cpu == NULL) {
+ printk(KERN_ERR "%s: unable to allocate PRD table\n",
hwif->name);
+ return -ENOMEM;
+ }
- return 1;
+ return 0;
}
EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
-
-static const struct ide_dma_ops sff_dma_ops = {
- .dma_host_set = ide_dma_host_set,
- .dma_setup = ide_dma_setup,
- .dma_exec_cmd = ide_dma_exec_cmd,
- .dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
- .dma_test_irq = ide_dma_test_irq,
- .dma_timeout = ide_dma_timeout,
- .dma_lost_irq = ide_dma_lost_irq,
-};
-
-void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
-{
- hwif->dma_base = base;
-
- if (!hwif->dma_command)
- hwif->dma_command = hwif->dma_base + 0;
- if (!hwif->dma_status)
- hwif->dma_status = hwif->dma_base + 2;
-
- hwif->dma_ops = &sff_dma_ops;
-}
-
-EXPORT_SYMBOL_GPL(ide_setup_dma);
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index f05fbc2bd7a..cf0aa25470e 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -15,6 +15,9 @@
* Documentation/ide/ChangeLog.ide-floppy.1996-2002
*/
+#define DRV_NAME "ide-floppy"
+#define PFX DRV_NAME ": "
+
#define IDEFLOPPY_VERSION "1.00"
#include <linux/module.h>
@@ -31,8 +34,10 @@
#include <linux/slab.h>
#include <linux/cdrom.h>
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
+#include <linux/scatterlist.h>
#include <scsi/scsi_ioctl.h>
@@ -42,42 +47,27 @@
#include <linux/io.h>
#include <asm/unaligned.h>
-/* define to see debug info */
-#define IDEFLOPPY_DEBUG_LOG 0
+#include "ide-floppy.h"
+
+/* module parameters */
+static unsigned long debug_mask;
+module_param(debug_mask, ulong, 0644);
-/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
-#define IDEFLOPPY_DEBUG(fmt, args...)
+/* define to see debug info */
+#define IDEFLOPPY_DEBUG_LOG 0
#if IDEFLOPPY_DEBUG_LOG
-#define debug_log(fmt, args...) \
- printk(KERN_INFO "ide-floppy: " fmt, ## args)
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
#else
-#define debug_log(fmt, args...) do {} while (0)
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
#endif
-
-/* 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.
*/
#define IDEFLOPPY_MAX_PC_RETRIES 3
-/*
- * 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.
- */
-#define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES)
-
/* format capacities descriptor codes */
#define CAPACITY_INVALID 0x00
#define CAPACITY_UNFORMATTED 0x01
@@ -85,113 +75,41 @@
#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.
+ * The following delay solves a problem with ATAPI Zip 100 drive where BSY bit
+ * was apparently being deasserted before the unit was ready to receive data.
*/
-typedef struct ide_floppy_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
- unsigned int openers; /* protected by BKL for now */
-
- /* Current packet command */
- struct ide_atapi_pc *pc;
- /* Last failed packet command */
- struct ide_atapi_pc *failed_pc;
- /* Packet command stack */
- struct ide_atapi_pc pc_stack[IDEFLOPPY_PC_STACK];
- /* Next free packet command storage space */
- int pc_stack_index;
- struct request rq_stack[IDEFLOPPY_PC_STACK];
- /* We implement a circular array */
- int rq_stack_index;
-
- /* Last error information */
- u8 sense_key, asc, ascq;
- /* delay this long before sending packet command */
- u8 ticks;
- int progress_indication;
-
- /* Device information */
- /* Current format */
- int blocks, block_size, bs_factor;
- /* Last format capacity descriptor */
- u8 cap_desc[8];
- /* Copy of the flexible disk page */
- u8 flexible_disk_page[32];
- /* Write protect */
- int wp;
- /* Supports format progress report */
- int srfp;
- /* Status/Action flags */
- unsigned long flags;
-} idefloppy_floppy_t;
-
-#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
-
-/* 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 */
-#define MODE_SENSE_CURRENT 0x00
-#define MODE_SENSE_CHANGEABLE 0x01
-#define MODE_SENSE_DEFAULT 0x02
-#define MODE_SENSE_SAVED 0x03
-
-/* 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
+#define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */
/* Error code returned in rq->errors to the higher part of the driver. */
#define IDEFLOPPY_ERROR_GENERAL 101
-/*
- * Pages of the SELECT SENSE / MODE SENSE packet commands.
- * See SFF-8070i spec.
- */
-#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b
-#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05
-
static DEFINE_MUTEX(idefloppy_ref_mutex);
-#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
-
-#define ide_floppy_g(disk) \
- container_of((disk)->private_data, struct ide_floppy_obj, driver)
+static void idefloppy_cleanup_obj(struct kref *);
static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
{
struct ide_floppy_obj *floppy = NULL;
mutex_lock(&idefloppy_ref_mutex);
- floppy = ide_floppy_g(disk);
- if (floppy)
- kref_get(&floppy->kref);
+ floppy = ide_drv_g(disk, ide_floppy_obj);
+ if (floppy) {
+ if (ide_device_get(floppy->drive))
+ floppy = NULL;
+ else
+ kref_get(&floppy->kref);
+ }
mutex_unlock(&idefloppy_ref_mutex);
return floppy;
}
-static void idefloppy_cleanup_obj(struct kref *);
-
static void ide_floppy_put(struct ide_floppy_obj *floppy)
{
+ ide_drive_t *drive = floppy->drive;
+
mutex_lock(&idefloppy_ref_mutex);
kref_put(&floppy->kref, idefloppy_cleanup_obj);
+ ide_device_put(drive);
mutex_unlock(&idefloppy_ref_mutex);
}
@@ -205,13 +123,21 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
struct request *rq = HWGROUP(drive)->rq;
int error;
- debug_log("Reached %s\n", __func__);
+ ide_debug_log(IDE_DBG_FUNC, "Call %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;
/* Why does this happen? */
@@ -228,44 +154,6 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
return 0;
}
-static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount, int direction)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct request *rq = pc->rq;
- struct req_iterator iter;
- struct bio_vec *bvec;
- unsigned long flags;
- int count, done = 0;
- char *data;
-
- rq_for_each_segment(bvec, rq, iter) {
- if (!bcount)
- break;
-
- count = min(bvec->bv_len, bcount);
-
- data = bvec_kmap_irq(bvec, &flags);
- if (direction)
- hwif->output_data(drive, NULL, data, count);
- else
- hwif->input_data(drive, NULL, data, count);
- bvec_kunmap_irq(data, &flags);
-
- bcount -= count;
- pc->b_count += count;
- done += count;
- }
-
- idefloppy_end_request(drive, 1, done >> 9);
-
- if (bcount) {
- printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
- drive->name, __func__, bcount);
- ide_pad_transfer(drive, direction, bcount);
- }
-}
-
static void idefloppy_update_buffers(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
@@ -276,335 +164,43 @@ static void idefloppy_update_buffers(ide_drive_t *drive,
idefloppy_end_request(drive, 1, 0);
}
-/*
- * 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, struct ide_atapi_pc *pc,
- struct request *rq)
-{
- struct ide_floppy_obj *floppy = drive->driver_data;
-
- ide_init_drive_cmd(rq);
- rq->buffer = (char *) pc;
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->rq_disk = floppy->disk;
- (void) ide_do_drive_cmd(drive, rq, ide_preempt);
-}
-
-static struct ide_atapi_pc *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;
- return (&floppy->pc_stack[floppy->pc_stack_index++]);
-}
-
-static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
+static void ide_floppy_callback(ide_drive_t *drive, int dsc)
{
idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_atapi_pc *pc = drive->pc;
+ int uptodate = pc->error ? 0 : 1;
- if (floppy->rq_stack_index == IDEFLOPPY_PC_STACK)
- floppy->rq_stack_index = 0;
- return (&floppy->rq_stack[floppy->rq_stack_index++]);
-}
-
-static void idefloppy_request_sense_callback(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- u8 *buf = floppy->pc->buf;
-
- debug_log("Reached %s\n", __func__);
-
- if (!floppy->pc->error) {
- 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_end_request(drive, 1, 0);
- } else {
- printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting"
- " request!\n");
- idefloppy_end_request(drive, 0, 0);
- }
-}
-
-/* General packet command callback function. */
-static void idefloppy_pc_callback(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- debug_log("Reached %s\n", __func__);
-
- idefloppy_end_request(drive, floppy->pc->error ? 0 : 1, 0);
-}
-
-static void idefloppy_init_pc(struct ide_atapi_pc *pc)
-{
- memset(pc->c, 0, 12);
- pc->retries = 0;
- pc->flags = 0;
- pc->req_xfer = 0;
- pc->buf = pc->pc_buf;
- pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
- pc->idefloppy_callback = &idefloppy_pc_callback;
-}
-
-static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
-{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_REQUEST_SENSE;
- pc->c[4] = 255;
- pc->req_xfer = 18;
- pc->idefloppy_callback = &idefloppy_request_sense_callback;
-}
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
-/*
- * 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)
-{
- struct ide_atapi_pc *pc;
- struct request *rq;
-
- (void)ide_read_error(drive);
- 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);
-}
-
-/* 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;
- ide_hwif_t *hwif = drive->hwif;
- struct ide_atapi_pc *pc = floppy->pc;
- struct request *rq = pc->rq;
- xfer_func_t *xferfunc;
- unsigned int temp;
- 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->dma_ops->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->xferred = pc->req_xfer;
- idefloppy_update_buffers(drive, pc);
- }
- debug_log("DMA finished\n");
- }
-
- /* Clear the interrupt */
- stat = ide_read_status(drive);
-
- /* No more interrupts */
- if ((stat & DRQ_STAT) == 0) {
- debug_log("Packet command completed, %d bytes transferred\n",
- pc->xferred);
- pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
-
- local_irq_enable_in_hardirq();
-
- if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
- /* Error detected */
- debug_log("%s: I/O error\n", drive->name);
- rq->errors++;
- 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);
- }
- /* Retry operation */
- idefloppy_retry_pc(drive);
- /* queued, but not started */
- return ide_stopped;
- }
- pc->error = 0;
- if (floppy->failed_pc == pc)
- floppy->failed_pc = NULL;
- /* Command finished - Call the callback function */
- pc->idefloppy_callback(drive);
- return ide_stopped;
- }
-
- 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);
- return ide_do_reset(drive);
- }
-
- /* Get the number of bytes to transfer */
- bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
- hwif->INB(hwif->io_ports.lbam_addr);
- /* on this interrupt */
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
-
- if (ireason & CD) {
- printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
- return ide_do_reset(drive);
- }
- 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 & IO) ? "Write" : "Read");
- printk(KERN_ERR "but the floppy wants us to %s !\n",
- (ireason & IO) ? "Read" : "Write");
- return ide_do_reset(drive);
- }
- if (!(pc->flags & PC_FLAG_WRITING)) {
- /* Reading - Check that we have enough space */
- temp = pc->xferred + bcount;
- if (temp > pc->req_xfer) {
- if (temp > pc->buf_size) {
- printk(KERN_ERR "ide-floppy: The floppy wants "
- "to send us more data than expected "
- "- discarding data\n");
- ide_pad_transfer(drive, 0, bcount);
-
- ide_set_handler(drive,
- &idefloppy_pc_intr,
- IDEFLOPPY_WAIT_CMD,
- NULL);
- return ide_started;
- }
- debug_log("The floppy wants to send us more data than"
- " expected - allowing transfer\n");
- }
- }
- if (pc->flags & PC_FLAG_WRITING)
- xferfunc = hwif->output_data;
- else
- xferfunc = hwif->input_data;
-
- if (pc->buf)
- xferfunc(drive, NULL, pc->cur_pos, bcount);
- else
- ide_floppy_io_buffers(drive, pc, bcount,
- !!(pc->flags & PC_FLAG_WRITING));
-
- /* Update the current position */
- pc->xferred += bcount;
- pc->cur_pos += bcount;
-
- /* And set the interrupt handler again */
- ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
- return ide_started;
-}
-
-/*
- * This is the original routine that did the packet transfer.
- * 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)
-{
- ide_hwif_t *hwif = drive->hwif;
- ide_startstop_t startstop;
- idefloppy_floppy_t *floppy = drive->driver_data;
- 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 = hwif->INB(hwif->io_ports.nsect_addr);
- 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);
- }
-
- /* Set the interrupt routine */
- ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
-
- /* Send the actual packet */
- hwif->output_data(drive, NULL, floppy->pc->c, 12);
-
- return ide_started;
-}
-
-
-/*
- * 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.
- */
-static int idefloppy_transfer_pc2(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ if (floppy->failed_pc == pc)
+ floppy->failed_pc = NULL;
- /* Send the actual packet */
- drive->hwif->output_data(drive, NULL, floppy->pc->c, 12);
+ if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
+ (pc->rq && blk_pc_request(pc->rq)))
+ uptodate = 1; /* FIXME */
+ else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
+ u8 *buf = pc->buf;
- /* Timeout for the packet command */
- return IDEFLOPPY_WAIT_CMD;
-}
+ if (!pc->error) {
+ 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;
-static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- idefloppy_floppy_t *floppy = drive->driver_data;
- ide_startstop_t startstop;
- u8 ireason;
+ if (floppy->failed_pc)
+ ide_debug_log(IDE_DBG_PC, "pc = %x, ",
+ floppy->failed_pc->c[0]);
- 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;
+ ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
+ "ascq = %x\n", floppy->sense_key,
+ floppy->asc, floppy->ascq);
+ } else
+ printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
+ "Aborting request!\n");
}
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
- 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
- * 1200 MHz Athlon system. 10/26/01 25msec is too short,
- * 40 and 50msec work well. idefloppy_pc_intr will not be actually
- * used until after the packet is moved in about 50 msec.
- */
- ide_set_handler(drive, &idefloppy_pc_intr, floppy->ticks,
- &idefloppy_transfer_pc2);
- return ide_started;
+ idefloppy_end_request(drive, uptodate, 0);
}
static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
@@ -616,7 +212,7 @@ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
floppy->ascq == 0x00)
return;
- printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, "
+ printk(KERN_ERR PFX "%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);
@@ -627,16 +223,13 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
idefloppy_floppy_t *floppy = drive->driver_data;
- ide_hwif_t *hwif = drive->hwif;
- ide_handler_t *pkt_xfer_routine;
- u16 bcount;
- u8 dma;
if (floppy->failed_pc == NULL &&
pc->c[0] != GPCMD_REQUEST_SENSE)
floppy->failed_pc = pc;
+
/* Set the current packet command */
- floppy->pc = pc;
+ drive->pc = pc;
if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
@@ -645,116 +238,35 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
pc->error = IDEFLOPPY_ERROR_GENERAL;
floppy->failed_pc = NULL;
- pc->idefloppy_callback(drive);
+ drive->pc_callback(drive, 0);
return ide_stopped;
}
- debug_log("Retry number - %d\n", pc->retries);
+ ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d\n", __func__, pc->retries);
pc->retries++;
- /* We haven't transferred any data yet */
- pc->xferred = 0;
- pc->cur_pos = pc->buf;
- bcount = min(pc->req_xfer, 63 * 1024);
-
- if (pc->flags & PC_FLAG_DMA_ERROR) {
- pc->flags &= ~PC_FLAG_DMA_ERROR;
- ide_dma_off(drive);
- }
- dma = 0;
-
- if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
- dma = !hwif->dma_ops->dma_setup(drive);
-
- ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
- IDE_TFLAG_OUT_DEVICE, bcount, dma);
- if (dma) {
- /* Begin DMA, if necessary */
- pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
- hwif->dma_ops->dma_start(drive);
- }
-
- /* Can we transfer the packet when we get the interrupt or wait? */
- if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE) {
- /* wait */
- pkt_xfer_routine = &idefloppy_transfer_pc1;
- } else {
- /* immediate */
- pkt_xfer_routine = &idefloppy_transfer_pc;
- }
-
- if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) {
- /* Issue the packet command */
- ide_execute_command(drive, WIN_PACKETCMD,
- pkt_xfer_routine,
- IDEFLOPPY_WAIT_CMD,
- NULL);
- return ide_started;
- } else {
- /* Issue the packet command */
- ide_execute_pkt_cmd(drive);
- return (*pkt_xfer_routine) (drive);
- }
+ return ide_issue_pc(drive, WAIT_FLOPPY_CMD, NULL);
}
-static void idefloppy_rw_callback(ide_drive_t *drive)
+void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
{
- debug_log("Reached %s\n", __func__);
-
- idefloppy_end_request(drive, 1, 0);
- return;
-}
-
-static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent)
-{
- debug_log("creating prevent removal command, prevent = %d\n", prevent);
-
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
- pc->c[4] = prevent;
-}
-
-static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
-{
- idefloppy_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
pc->c[7] = 255;
pc->c[8] = 255;
pc->req_xfer = 255;
}
-static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
- int l, int flags)
-{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_FORMAT_UNIT;
- pc->c[1] = 0x17;
-
- memset(pc->buf, 0, 12);
- pc->buf[1] = 0xA2;
- /* Default format list header, u8 1: FOV/DCRT/IMM bits set */
-
- if (flags & 1) /* Verify bit on... */
- pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */
- pc->buf[3] = 8;
-
- put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
- put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
- pc->buf_size = 12;
- pc->flags |= PC_FLAG_WRITING;
-}
-
/* A mode sense command is used to "sense" floppy parameters. */
-static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc,
- u8 page_code, u8 type)
+void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
{
u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
- idefloppy_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = GPCMD_MODE_SENSE_10;
pc->c[1] = 0;
- pc->c[2] = page_code + (type << 6);
+ pc->c[2] = page_code;
switch (page_code) {
case IDEFLOPPY_CAPABILITIES_PAGE:
@@ -764,65 +276,52 @@ static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc,
length += 32;
break;
default:
- printk(KERN_ERR "ide-floppy: unsupported page code "
- "in create_mode_sense_cmd\n");
+ printk(KERN_ERR PFX "unsupported page code in %s\n", __func__);
}
put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
pc->req_xfer = length;
}
-static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start)
-{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_START_STOP_UNIT;
- pc->c[4] = start;
-}
-
-static void idefloppy_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
-{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_TEST_UNIT_READY;
-}
-
-static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
+static void idefloppy_create_rw_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc, struct request *rq,
unsigned long sector)
{
+ idefloppy_floppy_t *floppy = drive->driver_data;
int block = sector / floppy->bs_factor;
int blocks = rq->nr_sectors / floppy->bs_factor;
int cmd = rq_data_dir(rq);
- debug_log("create_rw10_cmd: block == %d, blocks == %d\n",
- block, blocks);
+ ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d\n", __func__,
+ block, blocks);
- idefloppy_init_pc(pc);
+ ide_init_pc(pc);
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->idefloppy_callback = &idefloppy_rw_callback;
+ memcpy(rq->cmd, pc->c, 12);
+
pc->rq = rq;
- pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
+ pc->b_count = 0;
if (rq->cmd_flags & REQ_RW)
pc->flags |= PC_FLAG_WRITING;
pc->buf = NULL;
pc->req_xfer = pc->buf_size = blocks * floppy->block_size;
- pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ pc->flags |= PC_FLAG_DMA_OK;
}
static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
struct ide_atapi_pc *pc, struct request *rq)
{
- idefloppy_init_pc(pc);
- pc->idefloppy_callback = &idefloppy_rw_callback;
+ ide_init_pc(pc);
memcpy(pc->c, rq->cmd, sizeof(pc->c));
pc->rq = rq;
- pc->b_count = rq->data_len;
+ pc->b_count = 0;
if (rq->data_len && rq_data_dir(rq) == WRITE)
pc->flags |= PC_FLAG_WRITING;
pc->buf = rq->data;
if (rq->bio)
- pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ pc->flags |= PC_FLAG_DMA_OK;
/*
* possibly problematic, doesn't look like ide-floppy correctly
* handled scattered requests if dma fails...
@@ -834,66 +333,59 @@ 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;
+ ide_hwif_t *hwif = drive->hwif;
struct ide_atapi_pc *pc;
unsigned long block = (unsigned long)block_s;
- debug_log("dev: %s, cmd_type: %x, errors: %d\n",
- rq->rq_disk ? rq->rq_disk->disk_name : "?",
- 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);
+ ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
+ "errors: %d\n",
+ __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
+ rq->cmd[0], rq->cmd_type, rq->errors);
+
+ ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, "
+ "current_nr_sectors: %d\n",
+ __func__, (long)rq->sector, rq->nr_sectors,
+ rq->current_nr_sectors);
if (rq->errors >= ERROR_MAX) {
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);
+ printk(KERN_ERR PFX "%s: I/O error\n", drive->name);
+
idefloppy_end_request(drive, 0, 0);
return ide_stopped;
}
if (blk_fs_request(rq)) {
if (((long)rq->sector % floppy->bs_factor) ||
(rq->nr_sectors % floppy->bs_factor)) {
- printk(KERN_ERR "%s: unsupported r/w request size\n",
- drive->name);
+ printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
+ drive->name);
idefloppy_end_request(drive, 0, 0);
return ide_stopped;
}
- pc = idefloppy_next_pc_storage(drive);
- idefloppy_create_rw_cmd(floppy, pc, rq, block);
+ pc = &floppy->queued_pc;
+ idefloppy_create_rw_cmd(drive, pc, rq, block);
} else if (blk_special_request(rq)) {
pc = (struct ide_atapi_pc *) rq->buffer;
} else if (blk_pc_request(rq)) {
- pc = idefloppy_next_pc_storage(drive);
+ pc = &floppy->queued_pc;
idefloppy_blockpc_cmd(floppy, pc, rq);
} else {
- blk_dump_rq_flags(rq,
- "ide-floppy: unsupported command in queue");
+ blk_dump_rq_flags(rq, PFX "unsupported command in queue");
idefloppy_end_request(drive, 0, 0);
return ide_stopped;
}
- pc->rq = rq;
- return idefloppy_issue_pc(drive, pc);
-}
+ ide_init_sg_cmd(drive, rq);
+ ide_map_sg(drive, rq);
-/*
- * 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, struct ide_atapi_pc *pc)
-{
- struct ide_floppy_obj *floppy = drive->driver_data;
- struct request rq;
+ pc->sg = hwif->sg_table;
+ pc->sg_cnt = hwif->sg_nents;
- ide_init_drive_cmd(&rq);
- rq.buffer = (char *) pc;
- rq.cmd_type = REQ_TYPE_SPECIAL;
- rq.rq_disk = floppy->disk;
+ pc->rq = rq;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
+ return idefloppy_issue_pc(drive, pc);
}
/*
@@ -903,35 +395,40 @@ static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
+ struct gendisk *disk = floppy->disk;
struct ide_atapi_pc pc;
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);
+ ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
- " parameters\n");
+ if (ide_queue_pc_tail(drive, disk, &pc)) {
+ printk(KERN_ERR PFX "Can't get flexible disk page params\n");
return 1;
}
- floppy->wp = !!(pc.buf[3] & 0x80);
- set_disk_ro(floppy->disk, floppy->wp);
+
+ if (pc.buf[3] & 0x80)
+ drive->atapi_flags |= IDE_AFLAG_WP;
+ else
+ drive->atapi_flags &= ~IDE_AFLAG_WP;
+
+ set_disk_ro(disk, !!(drive->atapi_flags & IDE_AFLAG_WP));
+
page = &pc.buf[8];
- transfer_rate = be16_to_cpu(*(u16 *)&pc.buf[8 + 2]);
- sector_size = be16_to_cpu(*(u16 *)&pc.buf[8 + 6]);
- cyls = be16_to_cpu(*(u16 *)&pc.buf[8 + 8]);
- rpm = be16_to_cpu(*(u16 *)&pc.buf[8 + 28]);
+ transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]);
+ sector_size = be16_to_cpup((__be16 *)&pc.buf[8 + 6]);
+ cyls = be16_to_cpup((__be16 *)&pc.buf[8 + 8]);
+ rpm = be16_to_cpup((__be16 *)&pc.buf[8 + 28]);
heads = pc.buf[8 + 4];
sectors = pc.buf[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, "
+ printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, "
"%d sector size, %d rpm\n",
drive->name, capacity / 1024, cyls, heads,
sectors, transfer_rate / 8, sector_size, rpm);
@@ -943,7 +440,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
lba_capacity = floppy->blocks * floppy->block_size;
if (capacity < lba_capacity) {
- printk(KERN_NOTICE "%s: The disk reports a capacity of %d "
+ printk(KERN_NOTICE PFX "%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 ?
@@ -952,23 +449,6 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
return 0;
}
-static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
-
- floppy->srfp = 0;
- idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE,
- MODE_SENSE_CURRENT);
-
- pc.flags |= PC_FLAG_SUPPRESS_ERROR;
- if (idefloppy_queue_pc_tail(drive, &pc))
- return 1;
-
- floppy->srfp = pc.buf[8 + 2] & 0x40;
- return (0);
-}
-
/*
* Determine if a media is present in the floppy drive, and if so, its LBA
* capacity.
@@ -976,6 +456,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
static int ide_floppy_get_capacity(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
+ struct gendisk *disk = floppy->disk;
struct ide_atapi_pc pc;
u8 *cap_desc;
u8 header_len, desc_cnt;
@@ -987,9 +468,9 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
floppy->bs_factor = 1;
set_capacity(floppy->disk, 0);
- idefloppy_create_read_capacity_cmd(&pc);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ ide_floppy_create_read_capacity_cmd(&pc);
+ if (ide_queue_pc_tail(drive, disk, &pc)) {
+ printk(KERN_ERR PFX "Can't get floppy parameters\n");
return 1;
}
header_len = pc.buf[3];
@@ -999,11 +480,12 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
for (i = 0; i < desc_cnt; i++) {
unsigned int desc_start = 4 + i*8;
- blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]);
- length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]);
+ blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
+ length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
- debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
- i, blocks * length / 1024, blocks, length);
+ ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
+ "%d sector size\n",
+ i, blocks * length / 1024, blocks, length);
if (i)
continue;
@@ -1014,7 +496,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
switch (pc.buf[desc_start + 4] & 0x03) {
/* Clik! drive returns this instead of CAPACITY_CURRENT */
case CAPACITY_UNFORMATTED:
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
/*
* If it is not a clik drive, break out
* (maintains previous driver behaviour)
@@ -1023,23 +505,24 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
case CAPACITY_CURRENT:
/* Normal Zip/LS-120 disks */
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);
+ printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d "
+ "sector size\n",
+ drive->name, blocks * length / 1024,
+ blocks, length);
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);
+ printk(KERN_NOTICE PFX "%s: %d bytes block size"
+ " not supported\n", drive->name, length);
} else {
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);
+ printk(KERN_NOTICE PFX "%s: Warning: "
+ "non 512 bytes block size not "
+ "fully supported\n",
+ drive->name);
rc = 0;
}
break;
@@ -1048,142 +531,28 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
* This is a KERN_ERR so it appears on screen
* for the user to see
*/
- printk(KERN_ERR "%s: No disk in drive\n", drive->name);
+ printk(KERN_ERR PFX "%s: No disk in drive\n",
+ drive->name);
break;
case CAPACITY_INVALID:
- printk(KERN_ERR "%s: Invalid capacity for disk "
+ printk(KERN_ERR PFX "%s: Invalid capacity for disk "
"in drive\n", drive->name);
break;
}
- debug_log("Descriptor 0 Code: %d\n",
- pc.buf[desc_start + 4] & 0x03);
+ ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d\n",
+ pc.buf[desc_start + 4] & 0x03);
}
/* Clik! disk does not support get_flexible_disk_page */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+ if (!(drive->atapi_flags & IDE_AFLAG_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 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.
- */
+ set_capacity(disk, floppy->blocks * floppy->bs_factor);
-static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
-{
- struct ide_atapi_pc 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))
- return (-EFAULT);
-
- if (u_array_size <= 0)
- return (-EINVAL);
-
- 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_len = pc.buf[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.
- */
- for (i = 1; i < desc_cnt; i++) {
- unsigned int desc_start = 4 + i*8;
-
- if (u_index >= u_array_size)
- break; /* User-supplied buffer too small */
-
- blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]);
- length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]);
-
- if (put_user(blocks, argp))
- return(-EFAULT);
- ++argp;
-
- if (put_user(length, argp))
- return (-EFAULT);
- ++argp;
-
- ++u_index;
- }
-
- if (put_user(u_index, arg))
- return (-EFAULT);
- 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.
- */
-
-static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
- int progress_indication = 0x10000;
-
- if (floppy->srfp) {
- idefloppy_create_request_sense_cmd(&pc);
- if (idefloppy_queue_pc_tail(drive, &pc))
- return (-EIO);
-
- if (floppy->sense_key == 2 &&
- floppy->asc == 4 &&
- floppy->ascq == 4)
- progress_indication = floppy->progress_indication;
-
- /* Else assume format_unit has finished, and we're at 0x10000 */
- } else {
- unsigned long flags;
- u8 stat;
-
- local_irq_save(flags);
- stat = ide_read_status(drive);
- local_irq_restore(flags);
-
- progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
- }
- if (put_user(progress_indication, arg))
- return (-EFAULT);
-
- return (0);
+ return rc;
}
-static sector_t idefloppy_capacity(ide_drive_t *drive)
+sector_t ide_floppy_capacity(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
unsigned long capacity = floppy->blocks * floppy->bs_factor;
@@ -1191,76 +560,14 @@ static sector_t idefloppy_capacity(ide_drive_t *drive)
return capacity;
}
-/*
- * 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)
-{
- u8 gcw[2];
- u8 device_type, protocol, removable, drq_type, packet_size;
-
- *((u16 *) &gcw) = id->config;
-
- device_type = gcw[1] & 0x1F;
- removable = (gcw[0] & 0x80) >> 7;
- protocol = (gcw[1] & 0xC0) >> 6;
- drq_type = (gcw[0] & 0x60) >> 5;
- packet_size = gcw[0] & 0x03;
-
-#ifdef CONFIG_PPC
- /* kludge for Apple PowerBook internal zip */
- if (device_type == 5 &&
- !strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP"))
- device_type = 0;
-#endif
-
- if (protocol != 2)
- printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n",
- protocol);
- else if (device_type != 0)
- printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set "
- "to floppy\n", device_type);
- else if (!removable)
- printk(KERN_ERR "ide-floppy: The removable flag is not set\n");
- else if (drq_type == 3)
- printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not "
- "supported\n", drq_type);
- else if (packet_size != 0)
- printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 "
- "bytes\n", packet_size);
- else
- return 1;
- return 0;
-}
-
-#ifdef CONFIG_IDE_PROC_FS
-static void idefloppy_add_settings(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- 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
-
static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
{
- u8 gcw[2];
+ u16 *id = drive->id;
- *((u16 *) &gcw) = drive->id->config;
- floppy->pc = floppy->pc_stack;
+ drive->pc_callback = ide_floppy_callback;
+ drive->pc_update_buffers = idefloppy_update_buffers;
+ drive->pc_io_buffers = ide_io_buffers;
- if (((gcw[0] & 0x60) >> 5) == 1)
- 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.
@@ -1270,10 +577,10 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
* 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)) {
- floppy->flags |= IDEFLOPPY_FLAG_ZIP_DRIVE;
+ if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) {
+ drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
/* This value will be visible in the /proc/ide/hdx/settings */
- floppy->ticks = IDEFLOPPY_TICKS_DELAY;
+ drive->pc_delay = IDEFLOPPY_PC_DELAY;
blk_queue_max_sectors(drive->queue, 64);
}
@@ -1281,13 +588,16 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
* 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) {
+ if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) {
blk_queue_max_sectors(drive->queue, 64);
- floppy->flags |= IDEFLOPPY_FLAG_CLIK_DRIVE;
+ drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
+ /* IOMEGA Clik! drives do not support lock/unlock commands */
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
}
(void) ide_floppy_get_capacity(drive);
- idefloppy_add_settings(drive);
+
+ ide_proc_register_driver(drive, floppy->driver);
}
static void ide_floppy_remove(ide_drive_t *drive)
@@ -1304,7 +614,7 @@ static void ide_floppy_remove(ide_drive_t *drive)
static void idefloppy_cleanup_obj(struct kref *kref)
{
- struct ide_floppy_obj *floppy = to_ide_floppy(kref);
+ struct ide_floppy_obj *floppy = to_ide_drv(kref, ide_floppy_obj);
ide_drive_t *drive = floppy->drive;
struct gendisk *g = floppy->disk;
@@ -1314,24 +624,6 @@ static void idefloppy_cleanup_obj(struct kref *kref)
kfree(floppy);
}
-#ifdef CONFIG_IDE_PROC_FS
-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);
-}
-
-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 },
- { NULL, 0, NULL, NULL }
-};
-#endif /* CONFIG_IDE_PROC_FS */
-
static int ide_floppy_probe(ide_drive_t *);
static ide_driver_t idefloppy_driver = {
@@ -1343,14 +635,12 @@ static ide_driver_t idefloppy_driver = {
.probe = ide_floppy_probe,
.remove = ide_floppy_remove,
.version = IDEFLOPPY_VERSION,
- .media = ide_floppy,
- .supports_dsc_overlap = 0,
.do_request = idefloppy_do_request,
.end_request = idefloppy_end_request,
.error = __ide_error,
- .abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
- .proc = idefloppy_proc,
+ .proc = ide_floppy_proc,
+ .settings = ide_floppy_settings,
#endif
};
@@ -1359,28 +649,24 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_floppy_obj *floppy;
ide_drive_t *drive;
- struct ide_atapi_pc pc;
int ret = 0;
- debug_log("Reached %s\n", __func__);
-
floppy = ide_floppy_get(disk);
if (!floppy)
return -ENXIO;
drive = floppy->drive;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
floppy->openers++;
if (floppy->openers == 1) {
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
/* Just in case */
- idefloppy_create_test_unit_ready_cmd(&pc);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- idefloppy_create_start_stop_cmd(&pc, 1);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
+ if (ide_do_test_unit_ready(drive, disk))
+ ide_do_start_stop(drive, disk, 1);
if (ide_floppy_get_capacity(drive)
&& (filp->f_flags & O_NDELAY) == 0
@@ -1394,18 +680,15 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
goto out_put_floppy;
}
- if (floppy->wp && (filp->f_mode & 2)) {
+ if ((drive->atapi_flags & IDE_AFLAG_WP) && (filp->f_mode & 2)) {
ret = -EROFS;
goto out_put_floppy;
}
- floppy->flags |= IDEFLOPPY_FLAG_MEDIA_CHANGED;
- /* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
- idefloppy_create_prevent_cmd(&pc, 1);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
+
+ drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
+ ide_set_media_lock(drive, disk, 1);
check_disk_change(inode->i_bdev);
- } else if (floppy->flags & IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS) {
+ } else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) {
ret = -EBUSY;
goto out_put_floppy;
}
@@ -1420,20 +703,14 @@ out_put_floppy:
static int idefloppy_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
ide_drive_t *drive = floppy->drive;
- struct ide_atapi_pc pc;
- debug_log("Reached %s\n", __func__);
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
if (floppy->openers == 1) {
- /* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
- idefloppy_create_prevent_cmd(&pc, 0);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
-
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ ide_set_media_lock(drive, disk, 0);
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
}
floppy->openers--;
@@ -1445,7 +722,8 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+ struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
+ ide_floppy_obj);
ide_drive_t *drive = floppy->drive;
geo->heads = drive->bios_head;
@@ -1454,145 +732,26 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy,
- struct ide_atapi_pc *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;
- struct ide_atapi_pc 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;
- struct ide_atapi_pc pc;
- void __user *argp = (void __user *)arg;
- int err;
-
- switch (cmd) {
- case CDROMEJECT:
- /* fall through */
- case CDROM_LOCKDOOR:
- return ide_floppy_lockdoor(floppy, &pc, arg, cmd);
- case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
- return 0;
- case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
- return ide_floppy_get_format_capacities(drive, argp);
- case IDEFLOPPY_IOCTL_FORMAT_START:
- if (!(file->f_mode & 2))
- return -EPERM;
-
- return ide_floppy_format_unit(floppy, (int __user *)arg);
- case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
- return idefloppy_get_format_progress(drive, argp);
- }
-
- /*
- * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
- * and CDROM_SEND_PACKET (legacy) ioctls
- */
- if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
- err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
- bdev->bd_disk, cmd, argp);
- else
- err = -ENOTTY;
-
- if (err == -ENOTTY)
- err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
-
- return err;
-}
-
static int idefloppy_media_changed(struct gendisk *disk)
{
- struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
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;
+ if (drive->dev_flags & IDE_DFLAG_ATTACH) {
+ drive->dev_flags &= ~IDE_DFLAG_ATTACH;
return 0;
}
- ret = !!(floppy->flags & IDEFLOPPY_FLAG_MEDIA_CHANGED);
- floppy->flags &= ~IDEFLOPPY_FLAG_MEDIA_CHANGED;
+ ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
+ drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
return ret;
}
static int idefloppy_revalidate_disk(struct gendisk *disk)
{
- struct ide_floppy_obj *floppy = ide_floppy_g(disk);
- set_capacity(disk, idefloppy_capacity(floppy->drive));
+ struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
+ set_capacity(disk, ide_floppy_capacity(floppy->drive));
return 0;
}
@@ -1600,7 +759,7 @@ static struct block_device_operations idefloppy_ops = {
.owner = THIS_MODULE,
.open = idefloppy_open,
.release = idefloppy_release,
- .ioctl = idefloppy_ioctl,
+ .ioctl = ide_floppy_ioctl,
.getgeo = idefloppy_getgeo,
.media_changed = idefloppy_media_changed,
.revalidate_disk = idefloppy_revalidate_disk
@@ -1613,24 +772,19 @@ static int ide_floppy_probe(ide_drive_t *drive)
if (!strstr("ide-floppy", drive->driver_req))
goto failed;
- if (!drive->present)
- 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);
- goto failed;
- }
- if (drive->scsi) {
- printk(KERN_INFO "ide-floppy: passing drive %s to ide-scsi"
- " emulation.\n", drive->name);
+
+ if (!ide_check_atapi_device(drive, DRV_NAME)) {
+ printk(KERN_ERR PFX "%s: not supported by this version of "
+ DRV_NAME "\n", drive->name);
goto failed;
}
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);
+ printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n",
+ drive->name);
goto failed;
}
@@ -1640,8 +794,6 @@ static int ide_floppy_probe(ide_drive_t *drive)
ide_init_disk(g, drive);
- ide_proc_register_driver(drive, &idefloppy_driver);
-
kref_init(&floppy->kref);
floppy->drive = drive;
@@ -1652,13 +804,16 @@ static int ide_floppy_probe(ide_drive_t *drive)
drive->driver_data = floppy;
+ drive->debug_mask = debug_mask;
+
idefloppy_setup(drive, floppy);
+ drive->dev_flags |= IDE_DFLAG_ATTACH;
g->minors = 1 << PARTN_BITS;
g->driverfs_dev = &drive->gendev;
- g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
+ if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
+ g->flags = GENHD_FL_REMOVABLE;
g->fops = &idefloppy_ops;
- drive->attach = 1;
add_disk(g);
return 0;
@@ -1675,11 +830,12 @@ static void __exit idefloppy_exit(void)
static int __init idefloppy_init(void)
{
- printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
+ printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n");
return driver_register(&idefloppy_driver.gen_driver);
}
MODULE_ALIAS("ide:*m-floppy*");
+MODULE_ALIAS("ide-floppy");
module_init(idefloppy_init);
module_exit(idefloppy_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-floppy.h b/drivers/ide/ide-floppy.h
new file mode 100644
index 00000000000..17cf865e583
--- /dev/null
+++ b/drivers/ide/ide-floppy.h
@@ -0,0 +1,62 @@
+#ifndef __IDE_FLOPPY_H
+#define __IDE_FLOPPY_H
+
+/*
+ * 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;
+ ide_driver_t *driver;
+ struct gendisk *disk;
+ struct kref kref;
+ unsigned int openers; /* protected by BKL for now */
+
+ /* Last failed packet command */
+ struct ide_atapi_pc *failed_pc;
+ /* used for blk_{fs,pc}_request() requests */
+ struct ide_atapi_pc queued_pc;
+
+ /* Last error information */
+ u8 sense_key, asc, ascq;
+
+ int progress_indication;
+
+ /* Device information */
+ /* Current format */
+ int blocks, block_size, bs_factor;
+ /* Last format capacity descriptor */
+ u8 cap_desc[8];
+ /* Copy of the flexible disk page */
+ u8 flexible_disk_page[32];
+} idefloppy_floppy_t;
+
+/*
+ * Pages of the SELECT SENSE / MODE SENSE packet commands.
+ * See SFF-8070i spec.
+ */
+#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b
+#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05
+
+/* 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
+
+/* ide-floppy.c */
+void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8);
+void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *);
+sector_t ide_floppy_capacity(ide_drive_t *);
+
+/* ide-floppy_ioctl.c */
+int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long);
+
+#ifdef CONFIG_IDE_PROC_FS
+/* ide-floppy_proc.c */
+extern ide_proc_entry_t ide_floppy_proc[];
+extern const struct ide_proc_devset ide_floppy_settings[];
+#endif
+
+#endif /*__IDE_FLOPPY_H */
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
new file mode 100644
index 00000000000..a3a7a0809e2
--- /dev/null
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -0,0 +1,293 @@
+/*
+ * ide-floppy IOCTLs handling.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/cdrom.h>
+
+#include <asm/unaligned.h>
+
+#include <scsi/scsi_ioctl.h>
+
+#include "ide-floppy.h"
+
+/*
+ * 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)
+{
+ struct ide_floppy_obj *floppy = drive->driver_data;
+ struct ide_atapi_pc 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))
+ return -EFAULT;
+
+ if (u_array_size <= 0)
+ return -EINVAL;
+
+ ide_floppy_create_read_capacity_cmd(&pc);
+ if (ide_queue_pc_tail(drive, floppy->disk, &pc)) {
+ printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ return -EIO;
+ }
+
+ header_len = pc.buf[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.
+ */
+ for (i = 1; i < desc_cnt; i++) {
+ unsigned int desc_start = 4 + i*8;
+
+ if (u_index >= u_array_size)
+ break; /* User-supplied buffer too small */
+
+ blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
+ length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
+
+ if (put_user(blocks, argp))
+ return -EFAULT;
+
+ ++argp;
+
+ if (put_user(length, argp))
+ return -EFAULT;
+
+ ++argp;
+
+ ++u_index;
+ }
+
+ if (put_user(u_index, arg))
+ return -EFAULT;
+
+ return 0;
+}
+
+static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
+ int l, int flags)
+{
+ ide_init_pc(pc);
+ pc->c[0] = GPCMD_FORMAT_UNIT;
+ pc->c[1] = 0x17;
+
+ memset(pc->buf, 0, 12);
+ pc->buf[1] = 0xA2;
+ /* Default format list header, u8 1: FOV/DCRT/IMM bits set */
+
+ if (flags & 1) /* Verify bit on... */
+ pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */
+ pc->buf[3] = 8;
+
+ put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
+ put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
+ pc->buf_size = 12;
+ pc->flags |= PC_FLAG_WRITING;
+}
+
+static int ide_floppy_get_sfrp_bit(ide_drive_t *drive)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_atapi_pc pc;
+
+ drive->atapi_flags &= ~IDE_AFLAG_SRFP;
+
+ ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE);
+ pc.flags |= PC_FLAG_SUPPRESS_ERROR;
+
+ if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ return 1;
+
+ if (pc.buf[8 + 2] & 0x40)
+ drive->atapi_flags |= IDE_AFLAG_SRFP;
+
+ return 0;
+}
+
+static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_atapi_pc pc;
+ int blocks, length, flags, err = 0;
+
+ if (floppy->openers > 1) {
+ /* Don't format if someone is using the disk */
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
+ return -EBUSY;
+ }
+
+ drive->atapi_flags |= IDE_AFLAG_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)ide_floppy_get_sfrp_bit(drive);
+ ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags);
+
+ if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ err = -EIO;
+
+out:
+ if (err)
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
+ return err;
+}
+
+/*
+ * 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 ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_atapi_pc pc;
+ int progress_indication = 0x10000;
+
+ if (drive->atapi_flags & IDE_AFLAG_SRFP) {
+ ide_create_request_sense_cmd(drive, &pc);
+ if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ return -EIO;
+
+ if (floppy->sense_key == 2 &&
+ floppy->asc == 4 &&
+ floppy->ascq == 4)
+ progress_indication = floppy->progress_indication;
+
+ /* Else assume format_unit has finished, and we're at 0x10000 */
+ } else {
+ ide_hwif_t *hwif = drive->hwif;
+ unsigned long flags;
+ u8 stat;
+
+ local_irq_save(flags);
+ stat = hwif->tp_ops->read_status(hwif);
+ local_irq_restore(flags);
+
+ progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000;
+ }
+
+ if (put_user(progress_indication, arg))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned long arg, unsigned int cmd)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct gendisk *disk = floppy->disk;
+ int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
+
+ if (floppy->openers > 1)
+ return -EBUSY;
+
+ ide_set_media_lock(drive, disk, prevent);
+
+ if (cmd == CDROMEJECT)
+ ide_do_start_stop(drive, disk, 2);
+
+ return 0;
+}
+
+static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
+ unsigned int cmd, void __user *argp)
+{
+ switch (cmd) {
+ case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
+ return 0;
+ case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
+ return ide_floppy_get_format_capacities(drive, argp);
+ case IDEFLOPPY_IOCTL_FORMAT_START:
+ if (!(file->f_mode & 2))
+ return -EPERM;
+ return ide_floppy_format_unit(drive, (int __user *)argp);
+ case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
+ return ide_floppy_get_format_progress(drive, argp);
+ default:
+ return -ENOTTY;
+ }
+}
+
+int ide_floppy_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_drv_g(bdev->bd_disk,
+ ide_floppy_obj);
+ ide_drive_t *drive = floppy->drive;
+ struct ide_atapi_pc pc;
+ void __user *argp = (void __user *)arg;
+ int err;
+
+ if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
+ return ide_floppy_lockdoor(drive, &pc, arg, cmd);
+
+ err = ide_floppy_format_ioctl(drive, file, cmd, argp);
+ if (err != -ENOTTY)
+ return err;
+
+ /*
+ * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
+ * and CDROM_SEND_PACKET (legacy) ioctls
+ */
+ if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
+ err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
+ bdev->bd_disk, cmd, argp);
+
+ if (err == -ENOTTY)
+ err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
+
+ return err;
+}
diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c
new file mode 100644
index 00000000000..76f0c6c4eca
--- /dev/null
+++ b/drivers/ide/ide-floppy_proc.c
@@ -0,0 +1,33 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+#include "ide-floppy.h"
+
+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)ide_floppy_capacity(drive));
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+ide_proc_entry_t ide_floppy_proc[] = {
+ { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL },
+ { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
+ { NULL, 0, NULL, NULL }
+};
+
+ide_devset_rw_field(bios_cyl, bios_cyl);
+ide_devset_rw_field(bios_head, bios_head);
+ide_devset_rw_field(bios_sect, bios_sect);
+ide_devset_rw_field(ticks, pc_delay);
+
+const struct ide_proc_devset ide_floppy_settings[] = {
+ IDE_PROC_DEVSET(bios_cyl, 0, 1023),
+ IDE_PROC_DEVSET(bios_head, 0, 255),
+ IDE_PROC_DEVSET(bios_sect, 0, 63),
+ IDE_PROC_DEVSET(ticks, 0, 255),
+ { 0 },
+};
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
index 2d92214096a..81a5282ce1e 100644
--- a/drivers/ide/ide-generic.c
+++ b/drivers/ide/ide-generic.c
@@ -19,38 +19,36 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ide.h>
+#include <linux/pci_ids.h>
+
+/* FIXME: convert m32r to use ide_platform host driver */
+#ifdef CONFIG_M32R
+#include <asm/m32r.h>
+#endif
#define DRV_NAME "ide_generic"
-static int probe_mask = 0x03;
+static int probe_mask;
module_param(probe_mask, int, 0);
MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports");
static ssize_t store_add(struct class *cls, const char *buf, size_t n)
{
- ide_hwif_t *hwif;
unsigned int base, ctl;
- int irq;
- hw_regs_t hw;
- u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
+ int irq, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
return -EINVAL;
- hwif = ide_find_port();
- if (hwif == NULL)
- return -ENOENT;
-
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, base, ctl);
hw.irq = irq;
hw.chipset = ide_generic;
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
+ rc = ide_host_add(NULL, hws, NULL);
+ if (rc)
+ return rc;
return n;
};
@@ -88,20 +86,78 @@ static int __init ide_generic_sysfs_init(void)
return 0;
}
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \
+ || defined(CONFIG_PLAT_OPSPUT)
+static const u16 legacy_bases[] = { 0x1f0 };
+static const int legacy_irqs[] = { PLD_IRQ_CFIREQ };
+#elif defined(CONFIG_PLAT_MAPPI3)
+static const u16 legacy_bases[] = { 0x1f0, 0x170 };
+static const int legacy_irqs[] = { PLD_IRQ_CFIREQ, PLD_IRQ_IDEIREQ };
+#elif defined(CONFIG_ALPHA)
+static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168 };
+static const int legacy_irqs[] = { 14, 15, 11, 10 };
+#else
+static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
+static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 };
+#endif
+
+static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary)
+{
+ struct pci_dev *p = NULL;
+ u16 val;
+
+ for_each_pci_dev(p) {
+
+ if (pci_resource_start(p, 0) == 0x1f0)
+ *primary = 1;
+ if (pci_resource_start(p, 2) == 0x170)
+ *secondary = 1;
+
+ /* Cyrix CS55{1,2}0 pre SFF MWDMA ATA on the bridge */
+ if (p->vendor == PCI_VENDOR_ID_CYRIX &&
+ (p->device == PCI_DEVICE_ID_CYRIX_5510 ||
+ p->device == PCI_DEVICE_ID_CYRIX_5520))
+ *primary = *secondary = 1;
+
+ /* Intel MPIIX - PIO ATA on non PCI side of bridge */
+ if (p->vendor == PCI_VENDOR_ID_INTEL &&
+ p->device == PCI_DEVICE_ID_INTEL_82371MX) {
+
+ pci_read_config_word(p, 0x6C, &val);
+ if (val & 0x8000) {
+ /* ATA port enabled */
+ if (val & 0x4000)
+ *secondary = 1;
+ else
+ *primary = 1;
+ }
+ }
+ }
+}
+
static int __init ide_generic_init(void)
{
- u8 idx[MAX_HWIFS];
- int i;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ unsigned long io_addr;
+ int i, rc = 0, primary = 0, secondary = 0;
+
+ ide_generic_check_pci_legacy_iobases(&primary, &secondary);
+
+ if (!probe_mask) {
+ printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" "
+ "module parameter for probing all legacy ISA IDE ports\n");
- printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module "
- "parameter for probing all legacy ISA IDE ports\n");
+ if (primary == 0)
+ probe_mask |= 0x1;
- for (i = 0; i < MAX_HWIFS; i++) {
- ide_hwif_t *hwif;
- unsigned long io_addr = ide_default_io_base(i);
- hw_regs_t hw;
+ if (secondary == 0)
+ probe_mask |= 0x2;
+ } else
+ printk(KERN_INFO DRV_NAME ": enforcing probing of I/O ports "
+ "upon user request\n");
- idx[i] = 0xff;
+ for (i = 0; i < ARRAY_SIZE(legacy_bases); i++) {
+ io_addr = legacy_bases[i];
if ((probe_mask & (1 << i)) && io_addr) {
if (!request_region(io_addr, 8, DRV_NAME)) {
@@ -119,33 +175,28 @@ static int __init ide_generic_init(void)
continue;
}
- /*
- * Skip probing if the corresponding
- * slot is already occupied.
- */
- hwif = ide_find_port();
- if (hwif == NULL || hwif->index != i) {
- idx[i] = 0xff;
- continue;
- }
-
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
- hw.irq = ide_default_irq(io_addr);
+#ifdef CONFIG_IA64
+ hw.irq = isa_irq_to_vector(legacy_irqs[i]);
+#else
+ hw.irq = legacy_irqs[i];
+#endif
hw.chipset = ide_generic;
- ide_init_port_hw(hwif, &hw);
- idx[i] = i;
+ rc = ide_host_add(NULL, hws, NULL);
+ if (rc) {
+ release_region(io_addr + 0x206, 1);
+ release_region(io_addr, 8);
+ }
}
}
- ide_device_add_all(idx, NULL);
-
if (ide_generic_sysfs_init())
printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
"class\n");
- return 0;
+ return rc;
}
module_init(ide_generic_init);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 696525342e9..77c6eaeacef 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -40,6 +40,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <linux/completion.h>
#include <linux/reboot.h>
#include <linux/cdrom.h>
@@ -77,8 +78,9 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
* decide whether to reenable DMA -- 3 is a random magic for now,
* if we DMA timeout more than 3 times, just stay in PIO
*/
- if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
- drive->state = 0;
+ if ((drive->dev_flags & IDE_DFLAG_DMA_PIO_RETRY) &&
+ drive->retry_pio <= 3) {
+ drive->dev_flags &= ~IDE_DFLAG_DMA_PIO_RETRY;
ide_dma_on(drive);
}
@@ -130,21 +132,6 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
}
EXPORT_SYMBOL(ide_end_request);
-/*
- * Power Management state machine. This one is rather trivial for now,
- * we should probably add more, like switching back to PIO on suspend
- * to help some BIOSes, re-do the door locking on resume, etc...
- */
-
-enum {
- ide_pm_flush_cache = ide_pm_state_start_suspend,
- idedisk_pm_standby,
-
- idedisk_pm_restore_pio = ide_pm_state_start_resume,
- idedisk_pm_idle,
- ide_pm_restore_dma,
-};
-
static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
{
struct request_pm_state *pm = rq->data;
@@ -153,20 +140,20 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s
return;
switch (pm->pm_step) {
- case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */
+ case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
if (pm->pm_state == PM_EVENT_FREEZE)
- pm->pm_step = ide_pm_state_completed;
+ pm->pm_step = IDE_PM_COMPLETED;
else
- pm->pm_step = idedisk_pm_standby;
+ pm->pm_step = IDE_PM_STANDBY;
break;
- case idedisk_pm_standby: /* Suspend step 2 (standby) complete */
- pm->pm_step = ide_pm_state_completed;
+ case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
+ pm->pm_step = IDE_PM_COMPLETED;
break;
- case idedisk_pm_restore_pio: /* Resume step 1 complete */
- pm->pm_step = idedisk_pm_idle;
+ case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
+ pm->pm_step = IDE_PM_IDLE;
break;
- case idedisk_pm_idle: /* Resume step 2 (idle) complete */
- pm->pm_step = ide_pm_restore_dma;
+ case IDE_PM_IDLE: /* Resume step 2 (idle)*/
+ pm->pm_step = IDE_PM_RESTORE_DMA;
break;
}
}
@@ -179,40 +166,37 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
memset(args, 0, sizeof(*args));
switch (pm->pm_step) {
- case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */
+ case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
if (drive->media != ide_disk)
break;
/* Not supported? Switch to next step now. */
- if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
+ if (ata_id_flush_enabled(drive->id) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
ide_complete_power_step(drive, rq, 0, 0);
return ide_stopped;
}
- if (ide_id_has_flush_cache_ext(drive->id))
- args->tf.command = WIN_FLUSH_CACHE_EXT;
+ if (ata_id_flush_ext_enabled(drive->id))
+ args->tf.command = ATA_CMD_FLUSH_EXT;
else
- args->tf.command = WIN_FLUSH_CACHE;
+ args->tf.command = ATA_CMD_FLUSH;
goto out_do_tf;
-
- case idedisk_pm_standby: /* Suspend step 2 (standby) */
- args->tf.command = WIN_STANDBYNOW1;
+ case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
+ args->tf.command = ATA_CMD_STANDBYNOW1;
goto out_do_tf;
-
- case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */
+ case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
ide_set_max_pio(drive);
/*
- * skip idedisk_pm_idle for ATAPI devices
+ * skip IDE_PM_IDLE for ATAPI devices
*/
if (drive->media != ide_disk)
- pm->pm_step = ide_pm_restore_dma;
+ pm->pm_step = IDE_PM_RESTORE_DMA;
else
ide_complete_power_step(drive, rq, 0, 0);
return ide_stopped;
-
- case idedisk_pm_idle: /* Resume step 2 (idle) */
- args->tf.command = WIN_IDLEIMMEDIATE;
+ case IDE_PM_IDLE: /* Resume step 2 (idle) */
+ args->tf.command = ATA_CMD_IDLEIMMEDIATE;
goto out_do_tf;
-
- case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */
+ case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
/*
* Right now, all we do is call ide_set_dma(drive),
* we could be smarter and check for current xfer_speed
@@ -221,12 +205,13 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
if (drive->hwif->dma_ops == NULL)
break;
/*
- * TODO: respect ->using_dma setting
+ * TODO: respect IDE_DFLAG_USING_DMA
*/
ide_set_dma(drive);
break;
}
- pm->pm_step = ide_pm_state_completed;
+
+ pm->pm_step = IDE_PM_COMPLETED;
return ide_stopped;
out_do_tf:
@@ -286,7 +271,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
if (blk_pm_suspend_request(rq)) {
blk_stop_queue(drive->queue);
} else {
- drive->blocked = 0;
+ drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
blk_start_queue(drive->queue);
}
HWGROUP(drive)->rq = NULL;
@@ -322,7 +307,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
ide_task_t *task = (ide_task_t *)rq->special;
if (rq->errors == 0)
- rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT);
+ rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT);
if (task) {
struct ide_taskfile *tf = &task->tf;
@@ -330,7 +315,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
tf->error = err;
tf->status = stat;
- drive->hwif->tf_read(drive, task);
+ drive->hwif->tp_ops->tf_read(drive, task);
if (task->tf_flags & IDE_TFLAG_DYN)
kfree(task);
@@ -342,7 +327,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
drive->name, rq->pm->pm_step, stat, err);
#endif
ide_complete_power_step(drive, rq, stat, err);
- if (pm->pm_step == ide_pm_state_completed)
+ if (pm->pm_step == IDE_PM_COMPLETED)
ide_complete_pm_request(drive, rq);
return;
}
@@ -358,31 +343,6 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
EXPORT_SYMBOL(ide_end_drive_cmd);
-/**
- * try_to_flush_leftover_data - flush junk
- * @drive: drive to flush
- *
- * try_to_flush_leftover_data() is invoked in response to a drive
- * unexpectedly having its DRQ_STAT bit set. As an alternative to
- * resetting the drive, this routine tries to clear the condition
- * by read a sector's worth of data from the drive. Of course,
- * this may not help if the drive is *waiting* for data from *us*.
- */
-static void try_to_flush_leftover_data (ide_drive_t *drive)
-{
- int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS;
-
- if (drive->media != ide_disk)
- return;
- while (i > 0) {
- u32 buffer[16];
- u32 wcount = (i > 16) ? 16 : i;
-
- i -= wcount;
- drive->hwif->input_data(drive, NULL, buffer, wcount * 4);
- }
-}
-
static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
{
if (rq->rq_disk) {
@@ -398,39 +358,42 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
{
ide_hwif_t *hwif = drive->hwif;
- if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
+ if ((stat & ATA_BUSY) ||
+ ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
- } else if (stat & ERR_STAT) {
+ } else if (stat & ATA_ERR) {
/* err has different meaning on cdrom and tape */
- if (err == ABRT_ERR) {
- if (drive->select.b.lba &&
- /* some newer drives don't support WIN_SPECIFY */
- hwif->INB(hwif->io_ports.command_addr) ==
- WIN_SPECIFY)
+ if (err == ATA_ABORTED) {
+ if ((drive->dev_flags & IDE_DFLAG_LBA) &&
+ /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
+ hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */
drive->crc_count++;
- } else if (err & (BBD_ERR | ECC_ERR)) {
+ } else if (err & (ATA_BBK | ATA_UNC)) {
/* retries won't help these */
rq->errors = ERROR_MAX;
- } else if (err & TRK0_ERR) {
+ } else if (err & ATA_TRK0NF) {
/* help it find track zero */
rq->errors |= ERROR_RECAL;
}
}
- if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ &&
- (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0)
- try_to_flush_leftover_data(drive);
+ if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
+ (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
+ int nsect = drive->mult_count ? drive->mult_count : 1;
+
+ ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
+ }
if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
ide_kill_rq(drive, rq);
return ide_stopped;
}
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
rq->errors |= ERROR_RESET;
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
@@ -450,17 +413,17 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
{
ide_hwif_t *hwif = drive->hwif;
- if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
+ if ((stat & ATA_BUSY) ||
+ ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else {
/* add decoding error stuff */
}
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
/* force an abort */
- hwif->OUTBSYNC(drive, WIN_IDLEIMMEDIATE,
- hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
if (rq->errors >= ERROR_MAX) {
ide_kill_rq(drive, rq);
@@ -526,75 +489,26 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
EXPORT_SYMBOL_GPL(ide_error);
-ide_startstop_t __ide_abort(ide_drive_t *drive, struct request *rq)
-{
- if (drive->media != ide_disk)
- rq->errors |= ERROR_RESET;
-
- ide_kill_rq(drive, rq);
-
- return ide_stopped;
-}
-
-EXPORT_SYMBOL_GPL(__ide_abort);
-
-/**
- * ide_abort - abort pending IDE operations
- * @drive: drive the error occurred on
- * @msg: message to report
- *
- * ide_abort kills and cleans up when we are about to do a
- * host initiated reset on active commands. Longer term we
- * want handlers to have sensible abort handling themselves
- *
- * This differs fundamentally from ide_error because in
- * this case the command is doing just fine when we
- * blow it away.
- */
-
-ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
-{
- struct request *rq;
-
- if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
- return ide_stopped;
-
- /* retry only "normal" I/O: */
- if (!blk_fs_request(rq)) {
- rq->errors = 1;
- ide_end_drive_cmd(drive, BUSY_STAT, 0);
- return ide_stopped;
- }
-
- if (rq->rq_disk) {
- ide_driver_t *drv;
-
- drv = *(ide_driver_t **)rq->rq_disk->private_data;
- return drv->abort(drive, rq);
- } else
- return __ide_abort(drive, rq);
-}
-
static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
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;
+ tf->device = (drive->head - 1) | drive->select;
+ tf->command = ATA_CMD_INIT_DEV_PARAMS;
}
static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
tf->nsect = drive->sect;
- tf->command = WIN_RESTORE;
+ tf->command = ATA_CMD_RESTORE;
}
static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
tf->nsect = drive->mult_req;
- tf->command = WIN_SETMULT;
+ tf->command = ATA_CMD_SET_MULTI;
}
static ide_startstop_t ide_disk_special(ide_drive_t *drive)
@@ -613,8 +527,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
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_tf_set_setmult_cmd(drive, &args.tf);
} else if (s->all) {
int special = s->all;
@@ -631,37 +543,14 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
return ide_started;
}
-/*
- * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
- */
-static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
-{
- switch (req_pio) {
- case 202:
- case 201:
- case 200:
- case 102:
- case 101:
- case 100:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
- case 9:
- case 8:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
- case 7:
- case 6:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
- default:
- return 0;
- }
-}
-
/**
* do_special - issue some special commands
* @drive: drive the command is for
*
- * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
- * commands to a drive. It used to do much more, but has been scaled
- * back.
+ * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS,
+ * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive.
+ *
+ * It used to do much more, but has been scaled back.
*/
static ide_startstop_t do_special (ide_drive_t *drive)
@@ -671,45 +560,12 @@ static ide_startstop_t do_special (ide_drive_t *drive)
#ifdef DEBUG
printk("%s: do_special: 0x%02x\n", drive->name, s->all);
#endif
- if (s->b.set_tune) {
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_port_ops *port_ops = hwif->port_ops;
- u8 req_pio = drive->tune_req;
-
- s->b.set_tune = 0;
-
- if (set_pio_mode_abuse(drive->hwif, req_pio)) {
- /*
- * take ide_lock for drive->[no_]unmask/[no_]io_32bit
- */
- if (req_pio == 8 || req_pio == 9) {
- unsigned long flags;
-
- spin_lock_irqsave(&ide_lock, flags);
- port_ops->set_pio_mode(drive, req_pio);
- spin_unlock_irqrestore(&ide_lock, flags);
- } else
- port_ops->set_pio_mode(drive, req_pio);
- } else {
- int keep_dma = drive->using_dma;
-
- ide_set_pio(drive, req_pio);
-
- if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
- if (keep_dma)
- ide_dma_on(drive);
- }
- }
-
- return ide_stopped;
- } else {
- if (drive->media == ide_disk)
- return ide_disk_special(drive);
+ if (drive->media == ide_disk)
+ return ide_disk_special(drive);
- s->all = 0;
- drive->mult_req = 0;
- return ide_stopped;
- }
+ s->all = 0;
+ drive->mult_req = 0;
+ return ide_stopped;
}
void ide_map_sg(ide_drive_t *drive, struct request *rq)
@@ -783,21 +639,96 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
#ifdef DEBUG
printk("%s: DRIVE_CMD (null)\n", drive->name);
#endif
- ide_end_drive_cmd(drive, ide_read_status(drive), ide_read_error(drive));
+ ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif),
+ ide_read_error(drive));
return ide_stopped;
}
+int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
+ int arg)
+{
+ struct request_queue *q = drive->queue;
+ struct request *rq;
+ int ret = 0;
+
+ if (!(setting->flags & DS_SYNC))
+ return setting->set(drive, arg);
+
+ rq = blk_get_request(q, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd_len = 5;
+ rq->cmd[0] = REQ_DEVSET_EXEC;
+ *(int *)&rq->cmd[1] = arg;
+ rq->special = setting->set;
+
+ if (blk_execute_rq(q, NULL, rq, 0))
+ ret = rq->errors;
+ blk_put_request(rq);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ide_devset_execute);
+
+static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
+{
+ u8 cmd = rq->cmd[0];
+
+ if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) {
+ ide_task_t task;
+ struct ide_taskfile *tf = &task.tf;
+
+ memset(&task, 0, sizeof(task));
+ if (cmd == REQ_PARK_HEADS) {
+ drive->sleep = *(unsigned long *)rq->special;
+ drive->dev_flags |= IDE_DFLAG_SLEEPING;
+ tf->command = ATA_CMD_IDLEIMMEDIATE;
+ tf->feature = 0x44;
+ tf->lbal = 0x4c;
+ tf->lbam = 0x4e;
+ tf->lbah = 0x55;
+ task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
+ } else /* cmd == REQ_UNPARK_HEADS */
+ tf->command = ATA_CMD_CHK_POWER;
+
+ task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ task.rq = rq;
+ drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
+ return do_rw_taskfile(drive, &task);
+ }
+
+ switch (cmd) {
+ case REQ_DEVSET_EXEC:
+ {
+ int err, (*setfunc)(ide_drive_t *, int) = rq->special;
+
+ err = setfunc(drive, *(int *)&rq->cmd[1]);
+ if (err)
+ rq->errors = err;
+ else
+ err = 1;
+ ide_end_request(drive, err, 0);
+ return ide_stopped;
+ }
+ case REQ_DRIVE_RESET:
+ return ide_do_reset(drive);
+ default:
+ blk_dump_rq_flags(rq, "ide_special_rq - bad request");
+ ide_end_request(drive, 0, 0);
+ return ide_stopped;
+ }
+}
+
static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
{
struct request_pm_state *pm = rq->data;
if (blk_pm_suspend_request(rq) &&
- pm->pm_step == ide_pm_state_start_suspend)
+ pm->pm_step == IDE_PM_START_SUSPEND)
/* Mark drive blocked when starting the suspend sequence. */
- drive->blocked = 1;
+ drive->dev_flags |= IDE_DFLAG_BLOCKED;
else if (blk_pm_resume_request(rq) &&
- pm->pm_step == ide_pm_state_start_resume) {
+ pm->pm_step == IDE_PM_START_RESUME) {
/*
* The first thing we do on wakeup is to wait for BSY bit to
* go away (with a looong timeout) as a drive on this hwif may
@@ -806,16 +737,17 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
* the bus may be broken enough to walk on our toes at this
* point.
*/
+ ide_hwif_t *hwif = drive->hwif;
int rc;
#ifdef DEBUG_PM
printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
#endif
- rc = ide_wait_not_busy(HWIF(drive), 35000);
+ rc = ide_wait_not_busy(hwif, 35000);
if (rc)
printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
SELECT_DRIVE(drive);
- ide_set_irq(drive, 1);
- rc = ide_wait_not_busy(HWIF(drive), 100000);
+ hwif->tp_ops->set_irq(hwif, 1);
+ rc = ide_wait_not_busy(hwif, 100000);
if (rc)
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
}
@@ -825,9 +757,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
* start_request - start of I/O and command issuing for IDE
*
* start_request() initiates handling of a new I/O request. It
- * accepts commands and I/O (read/write) requests. It also does
- * the final remapping for weird stuff like EZDrive. Once
- * device mapper can work sector level the EZDrive stuff can go away
+ * accepts commands and I/O (read/write) requests.
*
* FIXME: this function needs a rename
*/
@@ -835,7 +765,6 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
- sector_t block;
BUG_ON(!blk_rq_started(rq));
@@ -850,21 +779,12 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
goto kill_rq;
}
- block = rq->sector;
- if (blk_fs_request(rq) &&
- (drive->media == ide_disk || drive->media == ide_floppy)) {
- block += drive->sect0;
- }
- /* Yecch - this will shift the entire interval,
- possibly killing some innocent following sector */
- if (block == 0 && drive->remap_0_to_1 == 1)
- block = 1; /* redirect MBR access to EZ-Drive partn table */
-
if (blk_pm_request(rq))
ide_check_pm_state(drive, rq);
SELECT_DRIVE(drive);
- if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
+ if (ide_wait_stat(&startstop, drive, drive->ready_stat,
+ ATA_BUSY | ATA_DRQ, WAIT_READY)) {
printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
return startstop;
}
@@ -888,13 +808,23 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
#endif
startstop = ide_start_power_step(drive, rq);
if (startstop == ide_stopped &&
- pm->pm_step == ide_pm_state_completed)
+ pm->pm_step == IDE_PM_COMPLETED)
ide_complete_pm_request(drive, rq);
return startstop;
- }
+ } else if (!rq->rq_disk && blk_special_request(rq))
+ /*
+ * TODO: Once all ULDs have been modified to
+ * check for specific op codes rather than
+ * blindly accepting any special request, the
+ * check for ->rq_disk above may be replaced
+ * by a more suitable mechanism or even
+ * dropped entirely.
+ */
+ return ide_special_rq(drive, rq);
drv = *(ide_driver_t **)rq->rq_disk->private_data;
- return drv->do_request(drive, rq, block);
+
+ return drv->do_request(drive, rq, rq->sector);
}
return do_special(drive);
kill_rq:
@@ -916,7 +846,7 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
if (timeout > WAIT_WORSTCASE)
timeout = WAIT_WORSTCASE;
drive->sleep = timeout + jiffies;
- drive->sleeping = 1;
+ drive->dev_flags |= IDE_DFLAG_SLEEPING;
}
EXPORT_SYMBOL(ide_stall_queue);
@@ -956,18 +886,23 @@ repeat:
}
do {
- if ((!drive->sleeping || time_after_eq(jiffies, drive->sleep))
- && !elv_queue_empty(drive->queue)) {
- if (!best
- || (drive->sleeping && (!best->sleeping || time_before(drive->sleep, best->sleep)))
- || (!best->sleeping && time_before(WAKEUP(drive), WAKEUP(best))))
- {
+ u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING);
+ u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING));
+
+ if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) &&
+ !elv_queue_empty(drive->queue)) {
+ if (best == NULL ||
+ (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) ||
+ (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) {
if (!blk_queue_plugged(drive->queue))
best = drive;
}
}
} while ((drive = drive->next) != hwgroup->drive);
- if (best && best->nice1 && !best->sleeping && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
+
+ if (best && (best->dev_flags & IDE_DFLAG_NICE1) &&
+ (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 &&
+ best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
long t = (signed long)(WAKEUP(best) - jiffies);
if (t >= WAIT_MIN_SLEEP) {
/*
@@ -976,7 +911,7 @@ repeat:
*/
drive = best->next;
do {
- if (!drive->sleeping
+ if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0
&& time_before(jiffies - best->service_time, WAKEUP(drive))
&& time_before(WAKEUP(drive), jiffies + t))
{
@@ -1047,7 +982,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
hwgroup->rq = NULL;
drive = hwgroup->drive;
do {
- if (drive->sleeping && (!sleeping || time_before(drive->sleep, sleep))) {
+ if ((drive->dev_flags & IDE_DFLAG_SLEEPING) &&
+ (sleeping == 0 ||
+ time_before(drive->sleep, sleep))) {
sleeping = 1;
sleep = drive->sleep;
}
@@ -1092,11 +1029,11 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* quirk_list may not like intr setups/cleanups
*/
if (drive->quirk_list != 1)
- ide_set_irq(drive, 0);
+ hwif->tp_ops->set_irq(hwif, 0);
}
hwgroup->hwif = hwif;
hwgroup->drive = drive;
- drive->sleeping = 0;
+ drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
drive->service_start = jiffies;
if (blk_queue_plugged(drive->queue)) {
@@ -1130,7 +1067,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* We count how many times we loop here to make sure we service
* all drives in the hwgroup without looping for ever
*/
- if (drive->blocked && !blk_pm_request(rq) && !(rq->cmd_flags & REQ_PREEMPT)) {
+ if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
+ blk_pm_request(rq) == 0 &&
+ (rq->cmd_flags & REQ_PREEMPT) == 0) {
drive = drive->next ? drive->next : hwgroup->drive;
if (loops++ < 4 && !blk_queue_plugged(drive->queue))
goto again;
@@ -1192,7 +1131,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
(void)hwif->dma_ops->dma_end(drive);
ret = ide_error(drive, "dma timeout error",
- ide_read_status(drive));
+ hwif->tp_ops->read_status(hwif));
} else {
printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
hwif->dma_ops->dma_timeout(drive);
@@ -1203,8 +1142,8 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
* a timeout -- we'll reenable after we finish this next request
* (or rather the first chunk of it) in pio.
*/
+ drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
drive->retry_pio++;
- drive->state = DMA_PIO_RETRY;
ide_dma_off_quietly(drive);
/*
@@ -1317,7 +1256,7 @@ void ide_timer_expiry (unsigned long data)
} else
startstop =
ide_error(drive, "irq timeout",
- ide_read_status(drive));
+ hwif->tp_ops->read_status(hwif));
}
drive->service_time = jiffies - drive->service_start;
spin_lock_irq(&ide_lock);
@@ -1373,8 +1312,9 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
*/
do {
if (hwif->irq == irq) {
- stat = hwif->INB(hwif->io_ports.status_addr);
- if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
+ stat = hwif->tp_ops->read_status(hwif);
+
+ if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
/* Try to not flood the console with msgs */
static unsigned long last_msgtime, count;
++count;
@@ -1463,7 +1403,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
* Whack the status register, just in case
* we have a leftover pending IRQ.
*/
- (void) hwif->INB(hwif->io_ports.status_addr);
+ (void)hwif->tp_ops->read_status(hwif);
#endif /* CONFIG_BLK_DEV_IDEPCI */
}
spin_unlock_irqrestore(&ide_lock, flags);
@@ -1500,23 +1440,16 @@ irqreturn_t ide_intr (int irq, void *dev_id)
del_timer(&hwgroup->timer);
spin_unlock(&ide_lock);
- /* Some controllers might set DMA INTR no matter DMA or PIO;
- * bmdma status might need to be cleared even for
- * PIO interrupts to prevent spurious/lost irq.
- */
- if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma))
- /* ide_dma_end() needs bmdma status for error checking.
- * So, skip clearing bmdma status here and leave it
- * to ide_dma_end() if this is dma interrupt.
- */
- hwif->ide_dma_clear_irq(drive);
+ if (hwif->port_ops && hwif->port_ops->clear_irq)
+ hwif->port_ops->clear_irq(drive);
- if (drive->unmask)
+ if (drive->dev_flags & IDE_DFLAG_UNMASK)
local_irq_enable_in_hardirq();
+
/* service this interrupt, may set handler for next interrupt */
startstop = handler(drive);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&ide_lock);
/*
* Note that handler() may have set things up for another
* interrupt to occur soon, but it cannot happen until
@@ -1539,94 +1472,37 @@ irqreturn_t ide_intr (int irq, void *dev_id)
}
/**
- * ide_init_drive_cmd - initialize a drive command request
- * @rq: request object
- *
- * Initialize a request before we fill it in and send it down to
- * ide_do_drive_cmd. Commands must be set up by this function. Right
- * now it doesn't do a lot, but if that changes abusers will have a
- * nasty surprise.
- */
-
-void ide_init_drive_cmd (struct request *rq)
-{
- blk_rq_init(NULL, rq);
-}
-
-EXPORT_SYMBOL(ide_init_drive_cmd);
-
-/**
* ide_do_drive_cmd - issue IDE special command
* @drive: device to issue command
* @rq: request to issue
- * @action: action for processing
*
* This function issues a special IDE device request
* onto the request queue.
*
- * If action is ide_wait, then the rq is queued at the end of the
- * request queue, and the function sleeps until it has been processed.
- * This is for use when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of
- * the request queue, displacing the currently-being-processed
- * request and this function returns immediately without waiting
- * for the new rq to be completed. This is VERY DANGEROUS, and is
- * intended for careful use by the ATAPI tape/cdrom driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the
- * request queue, and the function returns immediately without waiting
- * for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code.
+ * the rq is queued at the head of the request queue, displacing
+ * the currently-being-processed request and this function
+ * returns immediately without waiting for the new rq to be
+ * completed. This is VERY DANGEROUS, and is intended for
+ * careful use by the ATAPI tape/cdrom driver code.
*/
-
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
+
+void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
- DECLARE_COMPLETION_ONSTACK(wait);
- int where = ELEVATOR_INSERT_BACK, err;
- int must_wait = (action == ide_wait || action == ide_head_wait);
-
- rq->errors = 0;
-
- /*
- * we need to hold an extra reference to request for safe inspection
- * after completion
- */
- if (must_wait) {
- rq->ref_count++;
- rq->end_io_data = &wait;
- rq->end_io = blk_end_sync_rq;
- }
spin_lock_irqsave(&ide_lock, flags);
- if (action == ide_preempt)
- hwgroup->rq = NULL;
- if (action == ide_preempt || action == ide_head_wait) {
- where = ELEVATOR_INSERT_FRONT;
- rq->cmd_flags |= REQ_PREEMPT;
- }
- __elv_add_request(drive->queue, rq, where, 0);
- ide_do_request(hwgroup, IDE_NO_IRQ);
+ hwgroup->rq = NULL;
+ __elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 1);
+ __generic_unplug_device(drive->queue);
spin_unlock_irqrestore(&ide_lock, flags);
-
- err = 0;
- if (must_wait) {
- wait_for_completion(&wait);
- if (rq->errors)
- err = -EIO;
-
- blk_put_request(rq);
- }
-
- return err;
}
EXPORT_SYMBOL(ide_do_drive_cmd);
void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
{
+ ide_hwif_t *hwif = drive->hwif;
ide_task_t task;
memset(&task, 0, sizeof(task));
@@ -1637,7 +1513,9 @@ void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
task.tf.lbah = (bcount >> 8) & 0xff;
ide_tf_dump(drive->name, &task.tf);
- drive->hwif->tf_load(drive, &task);
+ hwif->tp_ops->set_irq(hwif, 1);
+ SELECT_MASK(drive, 0);
+ hwif->tp_ops->tf_load(drive, &task);
}
EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
@@ -1649,9 +1527,9 @@ void ide_pad_transfer(ide_drive_t *drive, int write, int len)
while (len > 0) {
if (write)
- hwif->output_data(drive, NULL, buf, min(4, len));
+ hwif->tp_ops->output_data(drive, NULL, buf, min(4, len));
else
- hwif->input_data(drive, NULL, buf, min(4, len));
+ hwif->tp_ops->input_data(drive, NULL, buf, min(4, len));
len -= 4;
}
}
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
new file mode 100644
index 00000000000..a90945f4979
--- /dev/null
+++ b/drivers/ide/ide-ioctls.c
@@ -0,0 +1,299 @@
+/*
+ * IDE ioctls handling.
+ */
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+static const struct ide_ioctl_devset ide_ioctl_settings[] = {
+{ HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit },
+{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings },
+{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, &ide_devset_unmaskirq },
+{ HDIO_GET_DMA, HDIO_SET_DMA, &ide_devset_using_dma },
+{ -1, HDIO_SET_PIO_MODE, &ide_devset_pio_mode },
+{ 0 }
+};
+
+int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
+ unsigned int cmd, unsigned long arg,
+ const struct ide_ioctl_devset *s)
+{
+ const struct ide_devset *ds;
+ unsigned long flags;
+ int err = -EOPNOTSUPP;
+
+ for (; (ds = s->setting); s++) {
+ if (ds->get && s->get_ioctl == cmd)
+ goto read_val;
+ else if (ds->set && s->set_ioctl == cmd)
+ goto set_val;
+ }
+
+ return err;
+
+read_val:
+ mutex_lock(&ide_setting_mtx);
+ spin_lock_irqsave(&ide_lock, flags);
+ err = ds->get(drive);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ mutex_unlock(&ide_setting_mtx);
+ return err >= 0 ? put_user(err, (long __user *)arg) : err;
+
+set_val:
+ if (bdev != bdev->bd_contains)
+ err = -EINVAL;
+ else {
+ if (!capable(CAP_SYS_ADMIN))
+ err = -EACCES;
+ else {
+ mutex_lock(&ide_setting_mtx);
+ err = ide_devset_execute(drive, ds, arg);
+ mutex_unlock(&ide_setting_mtx);
+ }
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(ide_setting_ioctl);
+
+static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
+ unsigned long arg)
+{
+ u16 *id = NULL;
+ int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
+ int rc = 0;
+
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
+ rc = -ENOMSG;
+ goto out;
+ }
+
+ id = kmalloc(size, GFP_KERNEL);
+ if (id == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(id, drive->id, size);
+ ata_id_to_hd_driveid(id);
+
+ if (copy_to_user((void __user *)arg, id, size))
+ rc = -EFAULT;
+
+ kfree(id);
+out:
+ return rc;
+}
+
+static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)
+{
+ return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)
+ << IDE_NICE_DSC_OVERLAP) |
+ (!!(drive->dev_flags & IDE_DFLAG_NICE1)
+ << IDE_NICE_1), (long __user *)arg);
+}
+
+static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
+{
+ if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
+ return -EPERM;
+
+ if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
+ (drive->media == ide_disk || drive->media == ide_floppy ||
+ (drive->dev_flags & IDE_DFLAG_SCSI)))
+ return -EPERM;
+
+ if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)
+ drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
+
+ if ((arg >> IDE_NICE_1) & 1)
+ drive->dev_flags |= IDE_DFLAG_NICE1;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_NICE1;
+
+ return 0;
+}
+
+static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
+{
+ u8 *buf = NULL;
+ int bufsize = 0, err = 0;
+ u8 args[4], xfer_rate = 0;
+ ide_task_t tfargs;
+ struct ide_taskfile *tf = &tfargs.tf;
+ u16 *id = drive->id;
+
+ if (NULL == (void *) arg) {
+ struct request *rq;
+
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
+ err = blk_execute_rq(drive->queue, NULL, rq, 0);
+ blk_put_request(rq);
+
+ return err;
+ }
+
+ if (copy_from_user(args, (void __user *)arg, 4))
+ return -EFAULT;
+
+ memset(&tfargs, 0, sizeof(ide_task_t));
+ tf->feature = args[2];
+ if (args[0] == ATA_CMD_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]) {
+ tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
+ bufsize = SECTOR_SIZE * args[3];
+ buf = kzalloc(bufsize, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ }
+
+ if (tf->command == ATA_CMD_SET_FEATURES &&
+ tf->feature == SETFEATURES_XFER &&
+ tf->nsect >= XFER_SW_DMA_0 &&
+ (id[ATA_ID_UDMA_MODES] ||
+ id[ATA_ID_MWDMA_MODES] ||
+ id[ATA_ID_SWDMA_MODES])) {
+ xfer_rate = args[1];
+ 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_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 */
+ ide_set_xfer_rate(drive, xfer_rate);
+ ide_driveid_update(drive);
+ }
+abort:
+ if (copy_to_user((void __user *)arg, &args, 4))
+ err = -EFAULT;
+ if (buf) {
+ if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
+ err = -EFAULT;
+ kfree(buf);
+ }
+ return err;
+}
+
+static int ide_task_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
+{
+ void __user *p = (void __user *)arg;
+ int err = 0;
+ u8 args[7];
+ ide_task_t task;
+
+ if (copy_from_user(args, p, 7))
+ return -EFAULT;
+
+ 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;
+
+ err = ide_no_data_taskfile(drive, &task);
+
+ args[0] = task.tf.command;
+ memcpy(&args[1], &task.tf_array[7], 6);
+
+ if (copy_to_user(p, args, 7))
+ err = -EFAULT;
+
+ return err;
+}
+
+static int generic_drive_reset(ide_drive_t *drive)
+{
+ struct request *rq;
+ int ret = 0;
+
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd_len = 1;
+ rq->cmd[0] = REQ_DRIVE_RESET;
+ rq->cmd_flags |= REQ_SOFTBARRIER;
+ if (blk_execute_rq(drive->queue, NULL, rq, 1))
+ ret = rq->errors;
+ blk_put_request(rq);
+ return ret;
+}
+
+int generic_ide_ioctl(ide_drive_t *drive, struct file *file,
+ struct block_device *bdev,
+ unsigned int cmd, unsigned long arg)
+{
+ int err;
+
+ err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
+ if (err != -EOPNOTSUPP)
+ return err;
+
+ switch (cmd) {
+ case HDIO_OBSOLETE_IDENTITY:
+ case HDIO_GET_IDENTITY:
+ if (bdev != bdev->bd_contains)
+ return -EINVAL;
+ return ide_get_identity_ioctl(drive, cmd, arg);
+ case HDIO_GET_NICE:
+ return ide_get_nice_ioctl(drive, arg);
+ case HDIO_SET_NICE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return ide_set_nice_ioctl(drive, arg);
+#ifdef CONFIG_IDE_TASK_IOCTL
+ case HDIO_DRIVE_TASKFILE:
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ if (drive->media == ide_disk)
+ return ide_taskfile_ioctl(drive, cmd, arg);
+ return -ENOMSG;
+#endif
+ case HDIO_DRIVE_CMD:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ide_cmd_ioctl(drive, cmd, arg);
+ case HDIO_DRIVE_TASK:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ide_task_ioctl(drive, cmd, arg);
+ case HDIO_DRIVE_RESET:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return generic_drive_reset(drive);
+ case HDIO_GET_BUSSTATE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (put_user(BUSSTATE_ON, (long __user *)arg))
+ return -EFAULT;
+ return 0;
+ case HDIO_SET_BUSSTATE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL(generic_ide_ioctl);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 0daf923541f..b762deb2dac 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -18,7 +18,6 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/bitops.h>
#include <linux/nmi.h>
@@ -42,18 +41,6 @@ static void ide_outb (u8 val, unsigned long port)
outb(val, port);
}
-static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port)
-{
- outb(addr, port);
-}
-
-void default_hwif_iops (ide_hwif_t *hwif)
-{
- hwif->OUTB = ide_outb;
- hwif->OUTBSYNC = ide_outbsync;
- hwif->INB = ide_inb;
-}
-
/*
* MMIO operations, typically used for SATA controllers
*/
@@ -68,34 +55,22 @@ static void ide_mm_outb (u8 value, unsigned long port)
writeb(value, (void __iomem *) port);
}
-static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port)
-{
- writeb(value, (void __iomem *) port);
-}
-
-void default_hwif_mmiops (ide_hwif_t *hwif)
-{
- hwif->OUTB = ide_mm_outb;
- /* Most systems will need to override OUTBSYNC, alas however
- this one is controller specific! */
- hwif->OUTBSYNC = ide_mm_outbsync;
- hwif->INB = ide_mm_inb;
-}
-
-EXPORT_SYMBOL(default_hwif_mmiops);
-
void SELECT_DRIVE (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
+ ide_task_t task;
if (port_ops && port_ops->selectproc)
port_ops->selectproc(drive);
- hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_OUT_DEVICE;
+
+ drive->hwif->tp_ops->tf_load(drive, &task);
}
-static void SELECT_MASK(ide_drive_t *drive, int mask)
+void SELECT_MASK(ide_drive_t *drive, int mask)
{
const struct ide_port_ops *port_ops = drive->hwif->port_ops;
@@ -103,7 +78,61 @@ static void SELECT_MASK(ide_drive_t *drive, int mask)
port_ops->maskproc(drive, mask);
}
-static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+ else
+ outb(cmd, hwif->io_ports.command_addr);
+}
+EXPORT_SYMBOL_GPL(ide_exec_command);
+
+u8 ide_read_status(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)hwif->io_ports.status_addr);
+ else
+ return inb(hwif->io_ports.status_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_status);
+
+u8 ide_read_altstatus(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)hwif->io_ports.ctl_addr);
+ else
+ return inb(hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
+
+u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ return inb(hwif->dma_base + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ide_read_sff_dma_status);
+
+void ide_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+ else
+ outb(ctl, hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_set_irq);
+
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -120,11 +149,6 @@ static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
- 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) {
u16 data = (tf->hob_data << 8) | tf->data;
@@ -157,11 +181,12 @@ static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
tf_outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
- tf_outb((tf->device & HIHI) | drive->select.all,
+ tf_outb((tf->device & HIHI) | drive->select,
io_ports->device_addr);
}
+EXPORT_SYMBOL_GPL(ide_tf_load);
-static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -191,8 +216,10 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
}
/* be sure we're looking at the low order bits */
- tf_outb(drive->ctl & ~0x80, io_ports->ctl_addr);
+ tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = tf_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = tf_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -205,7 +232,7 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
tf->device = tf_inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
- tf_outb(drive->ctl | 0x80, io_ports->ctl_addr);
+ tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = tf_inb(io_ports->feature_addr);
@@ -219,6 +246,7 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
tf->hob_lbah = tf_inb(io_ports->lbah_addr);
}
}
+EXPORT_SYMBOL_GPL(ide_tf_read);
/*
* Some localbus EIDE interfaces require a special access sequence
@@ -241,8 +269,8 @@ static void ata_vlb_sync(unsigned long port)
* so if an odd len is specified, be sure that there's at least one
* extra byte allocated for the buffer.
*/
-static void ata_input_data(ide_drive_t *drive, struct request *rq,
- void *buf, unsigned int len)
+void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+ unsigned int len)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -282,12 +310,13 @@ static void ata_input_data(ide_drive_t *drive, struct request *rq,
insw(data_addr, buf, len / 2);
}
}
+EXPORT_SYMBOL_GPL(ide_input_data);
/*
* This is used for most PIO data transfers *to* the IDE interface
*/
-static void ata_output_data(ide_drive_t *drive, struct request *rq,
- void *buf, unsigned int len)
+void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+ unsigned int len)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -325,107 +354,59 @@ static void ata_output_data(ide_drive_t *drive, struct request *rq,
outsw(data_addr, buf, len / 2);
}
}
+EXPORT_SYMBOL_GPL(ide_output_data);
-void default_hwif_transport(ide_hwif_t *hwif)
+u8 ide_read_error(ide_drive_t *drive)
{
- hwif->tf_load = ide_tf_load;
- hwif->tf_read = ide_tf_read;
+ ide_task_t task;
- hwif->input_data = ata_input_data;
- hwif->output_data = ata_output_data;
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_FEATURE;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.error;
+}
+EXPORT_SYMBOL_GPL(ide_read_error);
+
+void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
+ IDE_TFLAG_IN_NSECT;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ *bcount = (task.tf.lbah << 8) | task.tf.lbam;
+ *ireason = task.tf.nsect & 3;
}
+EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
+
+const struct ide_tp_ops default_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
-void ide_fix_driveid (struct hd_driveid *id)
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
+
+void ide_fix_driveid(u16 *id)
{
#ifndef __LITTLE_ENDIAN
# ifdef __BIG_ENDIAN
int i;
- u16 *stringcast;
-
- id->config = __le16_to_cpu(id->config);
- id->cyls = __le16_to_cpu(id->cyls);
- id->reserved2 = __le16_to_cpu(id->reserved2);
- id->heads = __le16_to_cpu(id->heads);
- id->track_bytes = __le16_to_cpu(id->track_bytes);
- id->sector_bytes = __le16_to_cpu(id->sector_bytes);
- id->sectors = __le16_to_cpu(id->sectors);
- id->vendor0 = __le16_to_cpu(id->vendor0);
- id->vendor1 = __le16_to_cpu(id->vendor1);
- id->vendor2 = __le16_to_cpu(id->vendor2);
- stringcast = (u16 *)&id->serial_no[0];
- for (i = 0; i < (20/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- id->buf_type = __le16_to_cpu(id->buf_type);
- id->buf_size = __le16_to_cpu(id->buf_size);
- id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
- stringcast = (u16 *)&id->fw_rev[0];
- for (i = 0; i < (8/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- stringcast = (u16 *)&id->model[0];
- for (i = 0; i < (40/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- id->dword_io = __le16_to_cpu(id->dword_io);
- id->reserved50 = __le16_to_cpu(id->reserved50);
- id->field_valid = __le16_to_cpu(id->field_valid);
- id->cur_cyls = __le16_to_cpu(id->cur_cyls);
- id->cur_heads = __le16_to_cpu(id->cur_heads);
- id->cur_sectors = __le16_to_cpu(id->cur_sectors);
- id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
- id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
- id->lba_capacity = __le32_to_cpu(id->lba_capacity);
- id->dma_1word = __le16_to_cpu(id->dma_1word);
- id->dma_mword = __le16_to_cpu(id->dma_mword);
- id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
- id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
- id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
- id->eide_pio = __le16_to_cpu(id->eide_pio);
- id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
- for (i = 0; i < 2; ++i)
- id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
- for (i = 0; i < 4; ++i)
- id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
- id->queue_depth = __le16_to_cpu(id->queue_depth);
- for (i = 0; i < 4; ++i)
- id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
- id->major_rev_num = __le16_to_cpu(id->major_rev_num);
- id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
- id->command_set_1 = __le16_to_cpu(id->command_set_1);
- id->command_set_2 = __le16_to_cpu(id->command_set_2);
- id->cfsse = __le16_to_cpu(id->cfsse);
- id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1);
- id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2);
- id->csf_default = __le16_to_cpu(id->csf_default);
- id->dma_ultra = __le16_to_cpu(id->dma_ultra);
- id->trseuc = __le16_to_cpu(id->trseuc);
- id->trsEuc = __le16_to_cpu(id->trsEuc);
- id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
- id->mprc = __le16_to_cpu(id->mprc);
- id->hw_config = __le16_to_cpu(id->hw_config);
- id->acoustic = __le16_to_cpu(id->acoustic);
- id->msrqs = __le16_to_cpu(id->msrqs);
- id->sxfert = __le16_to_cpu(id->sxfert);
- id->sal = __le16_to_cpu(id->sal);
- id->spg = __le32_to_cpu(id->spg);
- id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);
- for (i = 0; i < 22; i++)
- id->words104_125[i] = __le16_to_cpu(id->words104_125[i]);
- id->last_lun = __le16_to_cpu(id->last_lun);
- id->word127 = __le16_to_cpu(id->word127);
- id->dlf = __le16_to_cpu(id->dlf);
- id->csfo = __le16_to_cpu(id->csfo);
- for (i = 0; i < 26; i++)
- id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);
- id->word156 = __le16_to_cpu(id->word156);
- for (i = 0; i < 3; i++)
- id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);
- id->cfa_power = __le16_to_cpu(id->cfa_power);
- for (i = 0; i < 14; i++)
- id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);
- for (i = 0; i < 31; i++)
- id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);
- for (i = 0; i < 48; i++)
- id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);
- id->integrity_word = __le16_to_cpu(id->integrity_word);
+
+ for (i = 0; i < 256; i++)
+ id[i] = __le16_to_cpu(id[i]);
# else
# error "Please fix <asm/byteorder.h>"
# endif
@@ -436,21 +417,21 @@ void ide_fix_driveid (struct hd_driveid *id)
* 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.
+ * returned by the ATA_CMD_ID_ATA[PI] commands.
*/
void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
{
- u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
+ u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */
if (byteswap) {
/* convert from big-endian to host byte order */
- for (p = end ; p != s;) {
- unsigned short *pp = (unsigned short *) (p -= 2);
- *pp = ntohs(*pp);
- }
+ for (p = s ; p != end ; p += 2)
+ be16_to_cpus((u16 *) p);
}
+
/* strip leading blanks */
+ p = s;
while (s != end && *s == ' ')
++s;
/* compress internal blanks and strip trailing blanks */
@@ -488,12 +469,12 @@ int drive_is_ready (ide_drive_t *drive)
* about possible isa-pnp and pci-pnp issues yet.
*/
if (hwif->io_ports.ctl_addr)
- stat = ide_read_altstatus(drive);
+ stat = hwif->tp_ops->read_altstatus(hwif);
else
/* Note: this may clear a pending IRQ!! */
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
- if (stat & BUSY_STAT)
+ if (stat & ATA_BUSY)
/* drive busy: definitely not interrupting */
return 0;
@@ -516,25 +497,27 @@ EXPORT_SYMBOL(drive_is_ready);
*/
static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
unsigned long flags;
int i;
u8 stat;
udelay(1); /* spec allows drive 400ns to assert "BUSY" */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
- if (stat & BUSY_STAT) {
+ if (stat & ATA_BUSY) {
local_irq_set(flags);
timeout += jiffies;
- while ((stat = ide_read_status(drive)) & BUSY_STAT) {
+ while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) {
if (time_after(jiffies, timeout)) {
/*
* One last read after the timeout in case
* heavy interrupt load made us not make any
* progress during the timeout..
*/
- stat = ide_read_status(drive);
- if (!(stat & BUSY_STAT))
+ stat = tp_ops->read_status(hwif);
+ if ((stat & ATA_BUSY) == 0)
break;
local_irq_restore(flags);
@@ -553,7 +536,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
*/
for (i = 0; i < 10; i++) {
udelay(1);
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (OK_STAT(stat, good, bad)) {
*rstat = stat;
@@ -595,18 +578,18 @@ EXPORT_SYMBOL(ide_wait_stat);
/**
* ide_in_drive_list - look for drive in black/white list
* @id: drive identifier
- * @drive_table: list to inspect
+ * @table: list to inspect
*
* Look for a drive in the blacklist and the whitelist tables
* Returns 1 if the drive is found in the table.
*/
-int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
+int ide_in_drive_list(u16 *id, const struct drive_list_entry *table)
{
- for ( ; drive_table->id_model; drive_table++)
- if ((!strcmp(drive_table->id_model, id->model)) &&
- (!drive_table->id_firmware ||
- strstr(id->fw_rev, drive_table->id_firmware)))
+ for ( ; table->id_model; table++)
+ if ((!strcmp(table->id_model, (char *)&id[ATA_ID_PROD])) &&
+ (!table->id_firmware ||
+ strstr((char *)&id[ATA_ID_FW_REV], table->id_firmware)))
return 1;
return 0;
}
@@ -637,7 +620,7 @@ static const struct drive_list_entry ivb_list[] = {
u8 eighty_ninty_three (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
int ivb = ide_in_drive_list(id, ivb_list);
if (hwif->cbl == ATA_CBL_PATA40_SHORT)
@@ -647,7 +630,7 @@ 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)
+ if (ata_id_is_sata(id) && !ivb)
return 1;
if (hwif->cbl != ATA_CBL_PATA80 && !ivb)
@@ -659,11 +642,12 @@ u8 eighty_ninty_three (ide_drive_t *drive)
* - force bit13 (80c cable present) check also for !ivb devices
* (unless the slave device is pre-ATA3)
*/
- if ((id->hw_config & 0x4000) || (ivb && (id->hw_config & 0x2000)))
+ if ((id[ATA_ID_HW_CONFIG] & 0x4000) ||
+ (ivb && (id[ATA_ID_HW_CONFIG] & 0x2000)))
return 1;
no_80w:
- if (drive->udma33_warned == 1)
+ if (drive->dev_flags & IDE_DFLAG_UDMA33_WARNED)
return 0;
printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
@@ -671,7 +655,7 @@ no_80w:
drive->name,
hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
- drive->udma33_warned = 1;
+ drive->dev_flags |= IDE_DFLAG_UDMA33_WARNED;
return 0;
}
@@ -679,8 +663,9 @@ no_80w:
int ide_driveid_update(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid *id;
- unsigned long timeout, flags;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ u16 *id;
+ unsigned long flags;
u8 stat;
/*
@@ -689,50 +674,45 @@ int ide_driveid_update(ide_drive_t *drive)
*/
SELECT_MASK(drive, 1);
- ide_set_irq(drive, 1);
+ tp_ops->set_irq(hwif, 0);
msleep(50);
- hwif->OUTBSYNC(drive, WIN_IDENTIFY, hwif->io_ports.command_addr);
- timeout = jiffies + WAIT_WORSTCASE;
- do {
- if (time_after(jiffies, timeout)) {
- SELECT_MASK(drive, 0);
- return 0; /* drive timed-out */
- }
+ tp_ops->exec_command(hwif, ATA_CMD_ID_ATA);
- msleep(50); /* give drive a breather */
- stat = ide_read_altstatus(drive);
- } while (stat & BUSY_STAT);
+ if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) {
+ SELECT_MASK(drive, 0);
+ return 0;
+ }
- msleep(50); /* wait for IRQ and DRQ_STAT */
- stat = ide_read_status(drive);
+ msleep(50); /* wait for IRQ and ATA_DRQ */
+ stat = tp_ops->read_status(hwif);
- if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
+ if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) {
SELECT_MASK(drive, 0);
printk("%s: CHECK for good STATUS\n", drive->name);
return 0;
}
local_irq_save(flags);
SELECT_MASK(drive, 0);
- id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
+ id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
if (!id) {
local_irq_restore(flags);
return 0;
}
- hwif->input_data(drive, NULL, id, SECTOR_SIZE);
- (void)ide_read_status(drive); /* clear drive IRQ */
+ tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
+ (void)tp_ops->read_status(hwif); /* clear drive IRQ */
local_irq_enable();
local_irq_restore(flags);
ide_fix_driveid(id);
- if (id) {
- drive->id->dma_ultra = id->dma_ultra;
- drive->id->dma_mword = id->dma_mword;
- drive->id->dma_1word = id->dma_1word;
- /* anything more ? */
- kfree(id);
-
- if (drive->using_dma && ide_id_dma_bug(drive))
- ide_dma_off(drive);
- }
+
+ drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES];
+ drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES];
+ drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES];
+ /* anything more ? */
+
+ kfree(id);
+
+ if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive))
+ ide_dma_off(drive);
return 1;
}
@@ -740,12 +720,11 @@ 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;
- struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ u16 *id = drive->id, i;
int error = 0;
u8 stat;
-
-// while (HWGROUP(drive)->busy)
-// msleep(50);
+ ide_task_t task;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_ops) /* check if host supports DMA */
@@ -753,7 +732,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
#endif
/* Skip setting PIO flow-control modes on pre-EIDE drives */
- if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08))
+ if ((speed & 0xf8) == XFER_PIO_0 && ata_id_has_iordy(drive->id) == 0)
goto skip;
/*
@@ -778,15 +757,22 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
SELECT_DRIVE(drive);
SELECT_MASK(drive, 0);
udelay(1);
- ide_set_irq(drive, 0);
- hwif->OUTB(speed, io_ports->nsect_addr);
- hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr);
- hwif->OUTBSYNC(drive, WIN_SETFEATURES, io_ports->command_addr);
+ tp_ops->set_irq(hwif, 0);
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT;
+ task.tf.feature = SETFEATURES_XFER;
+ task.tf.nsect = speed;
+
+ tp_ops->tf_load(drive, &task);
+
+ tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
+
if (drive->quirk_list == 2)
- ide_set_irq(drive, 1);
+ tp_ops->set_irq(hwif, 1);
error = __ide_wait_stat(drive, drive->ready_stat,
- BUSY_STAT|DRQ_STAT|ERR_STAT,
+ ATA_BUSY | ATA_DRQ | ATA_ERR,
WAIT_CMD, &stat);
SELECT_MASK(drive, 0);
@@ -798,36 +784,29 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
return error;
}
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
+ id[ATA_ID_UDMA_MODES] &= ~0xFF00;
+ id[ATA_ID_MWDMA_MODES] &= ~0x0F00;
+ id[ATA_ID_SWDMA_MODES] &= ~0x0F00;
skip:
#ifdef CONFIG_BLK_DEV_IDEDMA
- if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
- drive->using_dma)
+ if (speed >= XFER_SW_DMA_0 && (drive->dev_flags & IDE_DFLAG_USING_DMA))
hwif->dma_ops->dma_host_set(drive, 1);
else if (hwif->dma_ops) /* check if host supports DMA */
ide_dma_off_quietly(drive);
#endif
- switch(speed) {
- case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break;
- case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break;
- case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break;
- case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break;
- case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break;
- case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break;
- case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break;
- case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break;
- case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
- case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
- case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
- case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
- case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
- case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
- default: break;
+ if (speed >= XFER_UDMA_0) {
+ i = 1 << (speed - XFER_UDMA_0);
+ id[ATA_ID_UDMA_MODES] |= (i << 8 | i);
+ } else if (speed >= XFER_MW_DMA_0) {
+ i = 1 << (speed - XFER_MW_DMA_0);
+ id[ATA_ID_MWDMA_MODES] |= (i << 8 | i);
+ } else if (speed >= XFER_SW_DMA_0) {
+ i = 1 << (speed - XFER_SW_DMA_0);
+ id[ATA_ID_SWDMA_MODES] |= (i << 8 | i);
}
+
if (!drive->init_speed)
drive->init_speed = speed;
drive->current_speed = speed;
@@ -889,7 +868,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
spin_lock_irqsave(&ide_lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
- hwif->OUTBSYNC(drive, cmd, hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, cmd);
/*
* Drive takes 400nS to respond, we must avoid the IRQ being
* serviced before that.
@@ -907,12 +886,20 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
- hwif->OUTBSYNC(drive, WIN_PACKETCMD, hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET);
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
+static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
+{
+ struct request *rq = drive->hwif->hwgroup->rq;
+
+ if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
+ ide_end_request(drive, err ? err : 1, 0);
+}
+
/* needed below */
static ide_startstop_t do_reset1 (ide_drive_t *, int);
@@ -924,14 +911,15 @@ static ide_startstop_t do_reset1 (ide_drive_t *, int);
*/
static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
u8 stat;
SELECT_DRIVE(drive);
udelay (10);
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
- if (OK_STAT(stat, 0, BUSY_STAT))
+ if (OK_STAT(stat, 0, ATA_BUSY))
printk("%s: ATAPI reset complete\n", drive->name);
else {
if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -948,10 +936,29 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
}
/* done polling */
hwgroup->polling = 0;
- hwgroup->resetting = 0;
+ ide_complete_drive_reset(drive, 0);
return ide_stopped;
}
+static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
+{
+ static const char *err_master_vals[] =
+ { NULL, "passed", "formatter device error",
+ "sector buffer error", "ECC circuitry error",
+ "controlling MPU error" };
+
+ u8 err_master = err & 0x7f;
+
+ printk(KERN_ERR "%s: reset: master: ", hwif->name);
+ if (err_master && err_master < 6)
+ printk(KERN_CONT "%s", err_master_vals[err_master]);
+ else
+ printk(KERN_CONT "error (0x%02x?)", err);
+ if (err & 0x80)
+ printk(KERN_CONT "; slave: failed");
+ printk(KERN_CONT "\n");
+}
+
/*
* reset_pollfunc() gets invoked to poll the interface for completion every 50ms
* during an ide reset operation. If the drives have not yet responded,
@@ -964,18 +971,20 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
const struct ide_port_ops *port_ops = hwif->port_ops;
u8 tmp;
+ int err = 0;
if (port_ops && port_ops->reset_poll) {
- if (port_ops->reset_poll(drive)) {
+ err = port_ops->reset_poll(drive);
+ if (err) {
printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
hwif->name, drive->name);
- return ide_stopped;
+ goto out;
}
}
- tmp = ide_read_status(drive);
+ tmp = hwif->tp_ops->read_status(hwif);
- if (!OK_STAT(tmp, 0, BUSY_STAT)) {
+ if (!OK_STAT(tmp, 0, ATA_BUSY)) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
/* continue polling */
@@ -983,49 +992,40 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
}
printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
drive->failures++;
+ err = -EIO;
} else {
- printk("%s: reset: ", hwif->name);
tmp = ide_read_error(drive);
if (tmp == 1) {
- printk("success\n");
+ printk(KERN_INFO "%s: reset: success\n", hwif->name);
drive->failures = 0;
} else {
+ ide_reset_report_error(hwif, tmp);
drive->failures++;
- printk("master: ");
- switch (tmp & 0x7f) {
- case 1: printk("passed");
- break;
- case 2: printk("formatter device error");
- break;
- case 3: printk("sector buffer error");
- break;
- case 4: printk("ECC circuitry error");
- break;
- case 5: printk("controlling MPU error");
- break;
- default:printk("error (0x%02x?)", tmp);
- }
- if (tmp & 0x80)
- printk("; slave: failed");
- printk("\n");
+ err = -EIO;
}
}
+out:
hwgroup->polling = 0; /* done polling */
- hwgroup->resetting = 0; /* done reset attempt */
+ ide_complete_drive_reset(drive, err);
return ide_stopped;
}
static void ide_disk_pre_reset(ide_drive_t *drive)
{
- int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
+ int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
drive->special.all = 0;
drive->special.b.set_geometry = legacy;
drive->special.b.recalibrate = legacy;
+
drive->mult_count = 0;
- if (!drive->keep_settings && !drive->using_dma)
+ drive->dev_flags &= ~IDE_DFLAG_PARKED;
+
+ if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
drive->mult_req = 0;
+
if (drive->mult_req != drive->mult_count)
drive->special.b.set_multmode = 1;
}
@@ -1037,18 +1037,18 @@ static void pre_reset(ide_drive_t *drive)
if (drive->media == ide_disk)
ide_disk_pre_reset(drive);
else
- drive->post_reset = 1;
+ drive->dev_flags |= IDE_DFLAG_POST_RESET;
- if (drive->using_dma) {
+ if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
if (drive->crc_count)
ide_check_dma_crc(drive);
else
ide_dma_off(drive);
}
- if (!drive->keep_settings) {
- if (!drive->using_dma) {
- drive->unmask = 0;
+ if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
+ if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
drive->io_32bit = 0;
}
return;
@@ -1080,12 +1080,13 @@ static void pre_reset(ide_drive_t *drive)
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
{
unsigned int unit;
- unsigned long flags;
+ unsigned long flags, timeout;
ide_hwif_t *hwif;
ide_hwgroup_t *hwgroup;
struct ide_io_ports *io_ports;
+ const struct ide_tp_ops *tp_ops;
const struct ide_port_ops *port_ops;
- u8 ctl;
+ DEFINE_WAIT(wait);
spin_lock_irqsave(&ide_lock, flags);
hwif = HWIF(drive);
@@ -1093,16 +1094,17 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
io_ports = &hwif->io_ports;
+ tp_ops = hwif->tp_ops;
+
/* We must not reset with running handlers */
BUG_ON(hwgroup->handler != NULL);
/* For an ATAPI device, first try an ATAPI SRST. */
if (drive->media != ide_disk && !do_not_try_atapi) {
- hwgroup->resetting = 1;
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
- hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr);
+ tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
ndelay(400);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
@@ -1111,6 +1113,31 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
return ide_started;
}
+ /* We must not disturb devices in the IDE_DFLAG_PARKED state. */
+ do {
+ unsigned long now;
+
+ prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
+ timeout = jiffies;
+ for (unit = 0; unit < MAX_DRIVES; unit++) {
+ ide_drive_t *tdrive = &hwif->drives[unit];
+
+ if (tdrive->dev_flags & IDE_DFLAG_PRESENT &&
+ tdrive->dev_flags & IDE_DFLAG_PARKED &&
+ time_after(tdrive->sleep, timeout))
+ timeout = tdrive->sleep;
+ }
+
+ now = jiffies;
+ if (time_before_eq(timeout, now))
+ break;
+
+ spin_unlock_irqrestore(&ide_lock, flags);
+ timeout = schedule_timeout_uninterruptible(timeout - now);
+ spin_lock_irqsave(&ide_lock, flags);
+ } while (timeout);
+ finish_wait(&ide_park_wq, &wait);
+
/*
* First, reset any device state data we were maintaining
* for any of the drives on this interface.
@@ -1120,10 +1147,10 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
if (io_ports->ctl_addr == 0) {
spin_unlock_irqrestore(&ide_lock, flags);
+ ide_complete_drive_reset(drive, -ENXIO);
return ide_stopped;
}
- hwgroup->resetting = 1;
/*
* Note that we also set nIEN while resetting the device,
* to mask unwanted interrupts from the interface during the reset.
@@ -1131,16 +1158,15 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
* immediate interrupt due to the edge transition it produces.
* This single interrupt gives us a "fast poll" for drives that
* recover from reset very quickly, saving us the first 50ms wait time.
+ *
+ * TODO: add ->softreset method and stop abusing ->set_irq
*/
/* set SRST and nIEN */
- hwif->OUTBSYNC(drive, drive->ctl|6, io_ports->ctl_addr);
+ tp_ops->set_irq(hwif, 4);
/* more than enough time */
udelay(10);
- if (drive->quirk_list == 2)
- ctl = drive->ctl; /* clear SRST and nIEN */
- else
- ctl = drive->ctl | 2; /* clear SRST, leave nIEN */
- hwif->OUTBSYNC(drive, ctl, io_ports->ctl_addr);
+ /* clear SRST, leave nIEN (unless device is on the quirk list) */
+ tp_ops->set_irq(hwif, drive->quirk_list == 2);
/* more than enough time */
udelay(10);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
@@ -1185,8 +1211,8 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
* about locking issues (2.5 work ?).
*/
mdelay(1);
- stat = hwif->INB(hwif->io_ports.status_addr);
- if ((stat & BUSY_STAT) == 0)
+ stat = hwif->tp_ops->read_status(hwif);
+ if ((stat & ATA_BUSY) == 0)
return 0;
/*
* Assume a value of 0xff means nothing is connected to
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 47af80df687..9fc4cfb2a27 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -1,26 +1,10 @@
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
#include <linux/interrupt.h>
-#include <linux/major.h>
-#include <linux/errno.h>
-#include <linux/genhd.h>
-#include <linux/blkpg.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
static const char *udma_str[] =
{ "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
"UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
@@ -90,142 +74,6 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
return min(speed, mode);
}
-/*
- * Standard (generic) timings for PIO modes, from ATA2 specification.
- * These timings are for access to the IDE data port register *only*.
- * Some drives may specify a mode, while also specifying a different
- * value for cycle_time (from drive identification data).
- */
-const ide_pio_timings_t ide_pio_timings[6] = {
- { 70, 165, 600 }, /* PIO Mode 0 */
- { 50, 125, 383 }, /* PIO Mode 1 */
- { 30, 100, 240 }, /* PIO Mode 2 */
- { 30, 80, 180 }, /* PIO Mode 3 with IORDY */
- { 25, 70, 120 }, /* PIO Mode 4 with IORDY */
- { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */
-};
-
-EXPORT_SYMBOL_GPL(ide_pio_timings);
-
-/*
- * Shared data/functions for determining best PIO mode for an IDE drive.
- * Most of this stuff originally lived in cmd640.c, and changes to the
- * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid
- * breaking the fragile cmd640.c support.
- */
-
-/*
- * Black list. Some drives incorrectly report their maximal PIO mode,
- * at least in respect to CMD640. Here we keep info on some known drives.
- */
-static struct ide_pio_info {
- const char *name;
- int pio;
-} ide_pio_blacklist [] = {
- { "Conner Peripherals 540MB - CFS540A", 3 },
-
- { "WDC AC2700", 3 },
- { "WDC AC2540", 3 },
- { "WDC AC2420", 3 },
- { "WDC AC2340", 3 },
- { "WDC AC2250", 0 },
- { "WDC AC2200", 0 },
- { "WDC AC21200", 4 },
- { "WDC AC2120", 0 },
- { "WDC AC2850", 3 },
- { "WDC AC1270", 3 },
- { "WDC AC1170", 1 },
- { "WDC AC1210", 1 },
- { "WDC AC280", 0 },
- { "WDC AC31000", 3 },
- { "WDC AC31200", 3 },
-
- { "Maxtor 7131 AT", 1 },
- { "Maxtor 7171 AT", 1 },
- { "Maxtor 7213 AT", 1 },
- { "Maxtor 7245 AT", 1 },
- { "Maxtor 7345 AT", 1 },
- { "Maxtor 7546 AT", 3 },
- { "Maxtor 7540 AV", 3 },
-
- { "SAMSUNG SHD-3121A", 1 },
- { "SAMSUNG SHD-3122A", 1 },
- { "SAMSUNG SHD-3172A", 1 },
-
- { "ST5660A", 3 },
- { "ST3660A", 3 },
- { "ST3630A", 3 },
- { "ST3655A", 3 },
- { "ST3391A", 3 },
- { "ST3390A", 1 },
- { "ST3600A", 1 },
- { "ST3290A", 0 },
- { "ST3144A", 0 },
- { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */
- /* drive) according to Seagates FIND-ATA program */
-
- { "QUANTUM ELS127A", 0 },
- { "QUANTUM ELS170A", 0 },
- { "QUANTUM LPS240A", 0 },
- { "QUANTUM LPS210A", 3 },
- { "QUANTUM LPS270A", 3 },
- { "QUANTUM LPS365A", 3 },
- { "QUANTUM LPS540A", 3 },
- { "QUANTUM LIGHTNING 540A", 3 },
- { "QUANTUM LIGHTNING 730A", 3 },
-
- { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */
- { "QUANTUM FIREBALL_640", 3 },
- { "QUANTUM FIREBALL_1080", 3 },
- { "QUANTUM FIREBALL_1280", 3 },
- { NULL, 0 }
-};
-
-/**
- * ide_scan_pio_blacklist - check for a blacklisted drive
- * @model: Drive model string
- *
- * This routine searches the ide_pio_blacklist for an entry
- * matching the start/whole of the supplied model name.
- *
- * Returns -1 if no match found.
- * Otherwise returns the recommended PIO mode from ide_pio_blacklist[].
- */
-
-static int ide_scan_pio_blacklist (char *model)
-{
- struct ide_pio_info *p;
-
- for (p = ide_pio_blacklist; p->name != NULL; p++) {
- if (strncmp(p->name, model, strlen(p->name)) == 0)
- return p->pio;
- }
- return -1;
-}
-
-unsigned int ide_pio_cycle_time(ide_drive_t *drive, u8 pio)
-{
- struct hd_driveid *id = drive->id;
- int cycle_time = 0;
-
- if (id->field_valid & 2) {
- if (id->capability & 8)
- cycle_time = id->eide_pio_iordy;
- else
- cycle_time = id->eide_pio;
- }
-
- /* conservative "downgrade" for all pre-ATA2 drives */
- if (pio < 3) {
- if (cycle_time && cycle_time < ide_pio_timings[pio].cycle_time)
- cycle_time = 0; /* use standard timing */
- }
-
- return cycle_time ? cycle_time : ide_pio_timings[pio].cycle_time;
-}
-
-EXPORT_SYMBOL_GPL(ide_pio_cycle_time);
-
/**
* ide_get_best_pio_mode - get PIO mode from drive
* @drive: drive to consider
@@ -241,29 +89,31 @@ EXPORT_SYMBOL_GPL(ide_pio_cycle_time);
u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
{
- int pio_mode;
- struct hd_driveid* id = drive->id;
- int overridden = 0;
+ u16 *id = drive->id;
+ int pio_mode = -1, overridden = 0;
if (mode_wanted != 255)
return min_t(u8, mode_wanted, max_mode);
- if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0 &&
- (pio_mode = ide_scan_pio_blacklist(id->model)) != -1) {
+ if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
+ pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
+
+ if (pio_mode != -1) {
printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
} else {
- pio_mode = id->tPIO;
+ pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
pio_mode = 2;
overridden = 1;
}
- if (id->field_valid & 2) { /* drive implements ATA2? */
- if (id->capability & 8) { /* IORDY supported? */
- if (id->eide_pio_modes & 7) {
+
+ if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
+ if (ata_id_has_iordy(id)) {
+ if (id[ATA_ID_PIO_MODES] & 7) {
overridden = 0;
- if (id->eide_pio_modes & 4)
+ if (id[ATA_ID_PIO_MODES] & 4)
pio_mode = 5;
- else if (id->eide_pio_modes & 2)
+ else if (id[ATA_ID_PIO_MODES] & 2)
pio_mode = 4;
else
pio_mode = 3;
@@ -417,22 +267,11 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
rate = ide_rate_filter(drive, rate);
+ BUG_ON(rate < XFER_PIO_0);
+
if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
return ide_set_pio_mode(drive, rate);
- /*
- * TODO: transfer modes 0x00-0x07 passed from the user-space are
- * currently handled here which needs fixing (please note that such
- * 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);
}
@@ -478,7 +317,7 @@ 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;
+ u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
memset(&task, 0, sizeof(task));
if (lba48)
@@ -487,7 +326,7 @@ static void ide_dump_sector(ide_drive_t *drive)
else
task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
- drive->hwif->tf_read(drive, &task);
+ drive->hwif->tp_ops->tf_read(drive, &task);
if (lba48 || (tf->device & ATA_LBA))
printk(", LBAsect=%llu",
@@ -500,16 +339,16 @@ static void ide_dump_sector(ide_drive_t *drive)
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 ");
+ if (err & ATA_ABORTED) printk("DriveStatusError ");
+ if (err & ATA_ICRC)
+ printk((err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
+ if (err & ATA_UNC) printk("UncorrectableError ");
+ if (err & ATA_IDNF) printk("SectorIdNotFound ");
+ if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
+ if (err & ATA_AMNF) printk("AddrMarkNotFound ");
printk("}");
- if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
- (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
+ if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK ||
+ (err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) {
ide_dump_sector(drive);
if (HWGROUP(drive) && HWGROUP(drive)->rq)
printk(", sector=%llu",
@@ -521,12 +360,12 @@ static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
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);
+ if (err & ATAPI_ILI) printk("IllegalLengthIndication ");
+ if (err & ATAPI_EOM) printk("EndOfMedia ");
+ if (err & ATA_ABORTED) printk("AbortedCommand ");
+ if (err & ATA_MCR) printk("MediaChangeRequested ");
+ if (err & ATAPI_LFS) printk("LastFailedSense=0x%02x ",
+ (err & ATAPI_LFS) >> 4);
printk("}\n");
}
@@ -548,19 +387,19 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
local_irq_save(flags);
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
- if (stat & BUSY_STAT)
+ if (stat & ATA_BUSY)
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 (stat & ATA_DRDY) printk("DriveReady ");
+ if (stat & ATA_DF) printk("DeviceFault ");
+ if (stat & ATA_DSC) printk("SeekComplete ");
+ if (stat & ATA_DRQ) printk("DataRequest ");
+ if (stat & ATA_CORR) printk("CorrectedError ");
+ if (stat & ATA_IDX) printk("Index ");
+ if (stat & ATA_ERR) printk("Error ");
}
printk("}\n");
- if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
+ if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) {
err = ide_read_error(drive);
printk("%s: %s: error=0x%02x ", drive->name, msg, err);
if (drive->media == ide_disk)
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
new file mode 100644
index 00000000000..03b00e57e93
--- /dev/null
+++ b/drivers/ide/ide-park.c
@@ -0,0 +1,121 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/jiffies.h>
+#include <linux/blkdev.h>
+
+DECLARE_WAIT_QUEUE_HEAD(ide_park_wq);
+
+static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
+{
+ struct request_queue *q = drive->queue;
+ struct request *rq;
+ int rc;
+
+ timeout += jiffies;
+ spin_lock_irq(&ide_lock);
+ if (drive->dev_flags & IDE_DFLAG_PARKED) {
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+ int reset_timer;
+
+ reset_timer = time_before(timeout, drive->sleep);
+ drive->sleep = timeout;
+ wake_up_all(&ide_park_wq);
+ if (reset_timer && hwgroup->sleeping &&
+ del_timer(&hwgroup->timer)) {
+ hwgroup->sleeping = 0;
+ hwgroup->busy = 0;
+ blk_start_queueing(q);
+ }
+ spin_unlock_irq(&ide_lock);
+ return;
+ }
+ spin_unlock_irq(&ide_lock);
+
+ rq = blk_get_request(q, READ, __GFP_WAIT);
+ rq->cmd[0] = REQ_PARK_HEADS;
+ rq->cmd_len = 1;
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->special = &timeout;
+ rc = blk_execute_rq(q, NULL, rq, 1);
+ blk_put_request(rq);
+ if (rc)
+ goto out;
+
+ /*
+ * Make sure that *some* command is sent to the drive after the
+ * timeout has expired, so power management will be reenabled.
+ */
+ rq = blk_get_request(q, READ, GFP_NOWAIT);
+ if (unlikely(!rq))
+ goto out;
+
+ rq->cmd[0] = REQ_UNPARK_HEADS;
+ rq->cmd_len = 1;
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+
+out:
+ return;
+}
+
+ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ unsigned long now;
+ unsigned int msecs;
+
+ if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
+ return -EOPNOTSUPP;
+
+ spin_lock_irq(&ide_lock);
+ now = jiffies;
+ if (drive->dev_flags & IDE_DFLAG_PARKED &&
+ time_after(drive->sleep, now))
+ msecs = jiffies_to_msecs(drive->sleep - now);
+ else
+ msecs = 0;
+ spin_unlock_irq(&ide_lock);
+
+ return snprintf(buf, 20, "%u\n", msecs);
+}
+
+ssize_t ide_park_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+#define MAX_PARK_TIMEOUT 30000
+ ide_drive_t *drive = to_ide_device(dev);
+ long int input;
+ int rc;
+
+ rc = strict_strtol(buf, 10, &input);
+ if (rc || input < -2)
+ return -EINVAL;
+ if (input > MAX_PARK_TIMEOUT) {
+ input = MAX_PARK_TIMEOUT;
+ rc = -EOVERFLOW;
+ }
+
+ mutex_lock(&ide_setting_mtx);
+ if (input >= 0) {
+ if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
+ rc = -EOPNOTSUPP;
+ else if (input || drive->dev_flags & IDE_DFLAG_PARKED)
+ issue_park_cmd(drive, msecs_to_jiffies(input));
+ } else {
+ if (drive->media == ide_disk)
+ switch (input) {
+ case -1:
+ drive->dev_flags &= ~IDE_DFLAG_NO_UNLOAD;
+ break;
+ case -2:
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+ break;
+ }
+ else
+ rc = -EOPNOTSUPP;
+ }
+ mutex_unlock(&ide_setting_mtx);
+
+ return rc ? rc : len;
+}
diff --git a/drivers/ide/ide-pio-blacklist.c b/drivers/ide/ide-pio-blacklist.c
new file mode 100644
index 00000000000..a8c2c8f8660
--- /dev/null
+++ b/drivers/ide/ide-pio-blacklist.c
@@ -0,0 +1,94 @@
+/*
+ * PIO blacklist. Some drives incorrectly report their maximal PIO mode,
+ * at least in respect to CMD640. Here we keep info on some known drives.
+ *
+ * Changes to the ide_pio_blacklist[] should be made with EXTREME CAUTION
+ * to avoid breaking the fragile cmd640.c support.
+ */
+
+#include <linux/string.h>
+
+static struct ide_pio_info {
+ const char *name;
+ int pio;
+} ide_pio_blacklist [] = {
+ { "Conner Peripherals 540MB - CFS540A", 3 },
+
+ { "WDC AC2700", 3 },
+ { "WDC AC2540", 3 },
+ { "WDC AC2420", 3 },
+ { "WDC AC2340", 3 },
+ { "WDC AC2250", 0 },
+ { "WDC AC2200", 0 },
+ { "WDC AC21200", 4 },
+ { "WDC AC2120", 0 },
+ { "WDC AC2850", 3 },
+ { "WDC AC1270", 3 },
+ { "WDC AC1170", 1 },
+ { "WDC AC1210", 1 },
+ { "WDC AC280", 0 },
+ { "WDC AC31000", 3 },
+ { "WDC AC31200", 3 },
+
+ { "Maxtor 7131 AT", 1 },
+ { "Maxtor 7171 AT", 1 },
+ { "Maxtor 7213 AT", 1 },
+ { "Maxtor 7245 AT", 1 },
+ { "Maxtor 7345 AT", 1 },
+ { "Maxtor 7546 AT", 3 },
+ { "Maxtor 7540 AV", 3 },
+
+ { "SAMSUNG SHD-3121A", 1 },
+ { "SAMSUNG SHD-3122A", 1 },
+ { "SAMSUNG SHD-3172A", 1 },
+
+ { "ST5660A", 3 },
+ { "ST3660A", 3 },
+ { "ST3630A", 3 },
+ { "ST3655A", 3 },
+ { "ST3391A", 3 },
+ { "ST3390A", 1 },
+ { "ST3600A", 1 },
+ { "ST3290A", 0 },
+ { "ST3144A", 0 },
+ { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on drive)
+ according to Seagate's FIND-ATA program */
+
+ { "QUANTUM ELS127A", 0 },
+ { "QUANTUM ELS170A", 0 },
+ { "QUANTUM LPS240A", 0 },
+ { "QUANTUM LPS210A", 3 },
+ { "QUANTUM LPS270A", 3 },
+ { "QUANTUM LPS365A", 3 },
+ { "QUANTUM LPS540A", 3 },
+ { "QUANTUM LIGHTNING 540A", 3 },
+ { "QUANTUM LIGHTNING 730A", 3 },
+
+ { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */
+ { "QUANTUM FIREBALL_640", 3 },
+ { "QUANTUM FIREBALL_1080", 3 },
+ { "QUANTUM FIREBALL_1280", 3 },
+ { NULL, 0 }
+};
+
+/**
+ * ide_scan_pio_blacklist - check for a blacklisted drive
+ * @model: Drive model string
+ *
+ * This routine searches the ide_pio_blacklist for an entry
+ * matching the start/whole of the supplied model name.
+ *
+ * Returns -1 if no match found.
+ * Otherwise returns the recommended PIO mode from ide_pio_blacklist[].
+ */
+
+int ide_scan_pio_blacklist(char *model)
+{
+ struct ide_pio_info *p;
+
+ for (p = ide_pio_blacklist; p->name != NULL; p++) {
+ if (strncmp(p->name, model, strlen(p->name)) == 0)
+ return p->pio;
+ }
+ return -1;
+}
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index adbd0178416..bac9b392b68 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -29,9 +29,12 @@ static struct pnp_device_id idepnp_devices[] = {
static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
+ struct ide_host *host;
unsigned long base, ctl;
+ int rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+ printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n");
if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
return -1;
@@ -57,33 +60,25 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
hw.irq = pnp_irq(dev, 0);
hw.chipset = ide_generic;
- hwif = ide_find_port();
- 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);
-
- printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
- pnp_set_drvdata(dev, hwif);
+ rc = ide_host_add(NULL, hws, &host);
+ if (rc)
+ goto out;
- ide_device_add(idx, NULL);
-
- return 0;
- }
+ pnp_set_drvdata(dev, host);
+ return 0;
+out:
release_region(ctl, 1);
release_region(base, 8);
- return -1;
+ return rc;
}
static void idepnp_remove(struct pnp_dev *dev)
{
- ide_hwif_t *hwif = pnp_get_drvdata(dev);
+ struct ide_host *host = pnp_get_drvdata(dev);
- ide_unregister(hwif);
+ ide_host_remove(host);
release_region(pnp_port_start(dev, 1), 1);
release_region(pnp_port_start(dev, 0), 8);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 380fa0c8cc8..f27baa5f140 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -50,59 +50,54 @@
static void generic_id(ide_drive_t *drive)
{
- drive->id->cyls = drive->cyl;
- drive->id->heads = drive->head;
- drive->id->sectors = drive->sect;
- drive->id->cur_cyls = drive->cyl;
- drive->id->cur_heads = drive->head;
- drive->id->cur_sectors = drive->sect;
+ u16 *id = drive->id;
+
+ id[ATA_ID_CUR_CYLS] = id[ATA_ID_CYLS] = drive->cyl;
+ id[ATA_ID_CUR_HEADS] = id[ATA_ID_HEADS] = drive->head;
+ id[ATA_ID_CUR_SECTORS] = id[ATA_ID_SECTORS] = drive->sect;
}
static void ide_disk_init_chs(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
/* Extract geometry if we did not already have one for the drive */
if (!drive->cyl || !drive->head || !drive->sect) {
- drive->cyl = drive->bios_cyl = id->cyls;
- drive->head = drive->bios_head = id->heads;
- drive->sect = drive->bios_sect = id->sectors;
+ drive->cyl = drive->bios_cyl = id[ATA_ID_CYLS];
+ drive->head = drive->bios_head = id[ATA_ID_HEADS];
+ drive->sect = drive->bios_sect = id[ATA_ID_SECTORS];
}
/* Handle logical geometry translation by the drive */
- if ((id->field_valid & 1) && id->cur_cyls &&
- id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
- drive->cyl = id->cur_cyls;
- drive->head = id->cur_heads;
- drive->sect = id->cur_sectors;
+ if (ata_id_current_chs_valid(id)) {
+ drive->cyl = id[ATA_ID_CUR_CYLS];
+ drive->head = id[ATA_ID_CUR_HEADS];
+ drive->sect = id[ATA_ID_CUR_SECTORS];
}
/* Use physical geometry if what we have still makes no sense */
- if (drive->head > 16 && id->heads && id->heads <= 16) {
- drive->cyl = id->cyls;
- drive->head = id->heads;
- drive->sect = id->sectors;
+ if (drive->head > 16 && id[ATA_ID_HEADS] && id[ATA_ID_HEADS] <= 16) {
+ drive->cyl = id[ATA_ID_CYLS];
+ drive->head = id[ATA_ID_HEADS];
+ drive->sect = id[ATA_ID_SECTORS];
}
}
static void ide_disk_init_mult_count(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
-
- drive->mult_count = 0;
- if (id->max_multsect) {
-#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 : 0;
- drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
-#else /* original, pre IDE-NFG, per request of AC */
- 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))
+ u16 *id = drive->id;
+ u8 max_multsect = id[ATA_ID_MAX_MULTSECT] & 0xff;
+
+ if (max_multsect) {
+ if ((max_multsect / 2) > 1)
+ id[ATA_ID_MULTSECT] = max_multsect | 0x100;
+ else
+ id[ATA_ID_MULTSECT] &= ~0x1ff;
+
+ drive->mult_req = id[ATA_ID_MULTSECT] & 0xff;
+
+ if (drive->mult_req)
drive->special.b.set_multmode = 1;
-#endif
}
}
@@ -119,14 +114,15 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
static inline void do_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
- int bswap = 1;
- struct hd_driveid *id;
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
+ int bswap = 1, is_cfa;
- id = drive->id;
/* read 512 bytes of id info */
- hwif->input_data(drive, NULL, id, SECTOR_SIZE);
+ hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
+
+ drive->dev_flags |= IDE_DFLAG_ID_READ;
- drive->id_read = 1;
local_irq_enable();
#ifdef DEBUG
printk(KERN_INFO "%s: dumping identify data\n", drive->name);
@@ -134,92 +130,86 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
#endif
ide_fix_driveid(id);
-#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
- /*
- * EATA SCSI controllers do a hardware ATA emulation:
- * Ignore them if there is a driver for them available.
- */
- if ((id->model[0] == 'P' && id->model[1] == 'M') ||
- (id->model[0] == 'S' && id->model[1] == 'K')) {
- printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
- goto err_misc;
- }
-#endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */
-
/*
- * WIN_IDENTIFY returns little-endian info,
- * WIN_PIDENTIFY *usually* returns little-endian info.
+ * ATA_CMD_ID_ATA returns little-endian info,
+ * ATA_CMD_ID_ATAPI *usually* returns little-endian info.
*/
- if (cmd == WIN_PIDENTIFY) {
- if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
- || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
- || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
+ if (cmd == ATA_CMD_ID_ATAPI) {
+ if ((m[0] == 'N' && m[1] == 'E') || /* NEC */
+ (m[0] == 'F' && m[1] == 'X') || /* Mitsumi */
+ (m[0] == 'P' && m[1] == 'i')) /* Pioneer */
/* Vertos drives may still be weird */
- bswap ^= 1;
+ bswap ^= 1;
}
- ide_fixstring(id->model, sizeof(id->model), bswap);
- ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap);
- ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap);
+
+ ide_fixstring(m, ATA_ID_PROD_LEN, bswap);
+ ide_fixstring((char *)&id[ATA_ID_FW_REV], ATA_ID_FW_REV_LEN, bswap);
+ ide_fixstring((char *)&id[ATA_ID_SERNO], ATA_ID_SERNO_LEN, bswap);
/* we depend on this a lot! */
- id->model[sizeof(id->model)-1] = '\0';
+ m[ATA_ID_PROD_LEN - 1] = '\0';
- if (strstr(id->model, "E X A B Y T E N E S T"))
+ if (strstr(m, "E X A B Y T E N E S T"))
goto err_misc;
- printk("%s: %s, ", drive->name, id->model);
- drive->present = 1;
- drive->dead = 0;
+ printk(KERN_INFO "%s: %s, ", drive->name, m);
+
+ drive->dev_flags |= IDE_DFLAG_PRESENT;
+ drive->dev_flags &= ~IDE_DFLAG_DEAD;
/*
* Check for an ATAPI device
*/
- if (cmd == WIN_PIDENTIFY) {
- u8 type = (id->config >> 8) & 0x1f;
- printk("ATAPI ");
+ if (cmd == ATA_CMD_ID_ATAPI) {
+ u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;
+
+ printk(KERN_CONT "ATAPI ");
switch (type) {
case ide_floppy:
- if (!strstr(id->model, "CD-ROM")) {
- if (!strstr(id->model, "oppy") &&
- !strstr(id->model, "poyp") &&
- !strstr(id->model, "ZIP"))
- printk("cdrom or floppy?, assuming ");
+ if (!strstr(m, "CD-ROM")) {
+ if (!strstr(m, "oppy") &&
+ !strstr(m, "poyp") &&
+ !strstr(m, "ZIP"))
+ printk(KERN_CONT "cdrom or floppy?, assuming ");
if (drive->media != ide_cdrom) {
- printk ("FLOPPY");
- drive->removable = 1;
+ printk(KERN_CONT "FLOPPY");
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
break;
}
}
/* Early cdrom models used zero */
type = ide_cdrom;
case ide_cdrom:
- drive->removable = 1;
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
#ifdef CONFIG_PPC
/* kludge for Apple PowerBook internal zip */
- if (!strstr(id->model, "CD-ROM") &&
- strstr(id->model, "ZIP")) {
- printk ("FLOPPY");
+ if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
+ printk(KERN_CONT "FLOPPY");
type = ide_floppy;
break;
}
#endif
- printk ("CD/DVD-ROM");
+ printk(KERN_CONT "CD/DVD-ROM");
break;
case ide_tape:
- printk ("TAPE");
+ printk(KERN_CONT "TAPE");
break;
case ide_optical:
- printk ("OPTICAL");
- drive->removable = 1;
+ printk(KERN_CONT "OPTICAL");
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
break;
default:
- printk("UNKNOWN (type %d)", type);
+ printk(KERN_CONT "UNKNOWN (type %d)", type);
break;
}
- printk (" drive\n");
+ printk(KERN_CONT " drive\n");
drive->media = type;
/* an ATAPI device ignores DRDY */
drive->ready_stat = 0;
+ if (ata_id_cdb_intr(id))
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
+ /* we don't do head unloading on ATAPI devices */
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
return;
}
@@ -227,22 +217,24 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
* Not an ATAPI device: looks like a "regular" hard disk
*/
- /*
- * 0x848a = CompactFlash device
- * These are *not* removable in Linux definition of the term
- */
+ is_cfa = ata_id_is_cfa(id);
- if ((id->config != 0x848a) && (id->config & (1<<7)))
- drive->removable = 1;
+ /* CF devices are *not* removable in Linux definition of the term */
+ if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
drive->media = ide_disk;
- printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
+
+ if (!ata_id_has_unload(drive->id))
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+
+ printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA");
return;
err_misc:
kfree(id);
- drive->present = 0;
+ drive->dev_flags &= ~IDE_DFLAG_PRESENT;
return;
}
@@ -265,6 +257,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int use_altstatus = 0, rc;
unsigned long timeout;
u8 s = 0, a = 0;
@@ -273,9 +266,9 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
msleep(50);
if (io_ports->ctl_addr) {
- a = ide_read_altstatus(drive);
- s = ide_read_status(drive);
- if ((a ^ s) & ~INDEX_STAT)
+ a = tp_ops->read_altstatus(hwif);
+ s = tp_ops->read_status(hwif);
+ if ((a ^ s) & ~ATA_IDX)
/* ancient Seagate drives, broken interfaces */
printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
"instead of ALTSTATUS(0x%02x)\n",
@@ -288,31 +281,29 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* set features register for atapi
* identify command to be sure of reply
*/
- if ((cmd == WIN_PIDENTIFY))
- /* disable dma & overlap */
- hwif->OUTB(0, io_ports->feature_addr);
+ if (cmd == ATA_CMD_ID_ATAPI) {
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ /* disable DMA & overlap */
+ task.tf_flags = IDE_TFLAG_OUT_FEATURE;
+
+ tp_ops->tf_load(drive, &task);
+ }
/* ask drive for ID */
- hwif->OUTBSYNC(drive, cmd, io_ports->command_addr);
+ tp_ops->exec_command(hwif, cmd);
- timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- timeout += jiffies;
- do {
- if (time_after(jiffies, timeout)) {
- /* drive timed-out */
- return 1;
- }
- /* give drive a breather */
- msleep(50);
- s = use_altstatus ? ide_read_altstatus(drive)
- : ide_read_status(drive);
- } while (s & BUSY_STAT);
+ timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- /* wait for IRQ and DRQ_STAT */
+ if (ide_busy_sleep(hwif, timeout, use_altstatus))
+ return 1;
+
+ /* wait for IRQ and ATA_DRQ */
msleep(50);
- s = ide_read_status(drive);
+ s = tp_ops->read_status(hwif);
- if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
+ if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
unsigned long flags;
/* local CPU only; some systems need this */
@@ -322,7 +313,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* drive responded with ID */
rc = 0;
/* clear drive IRQ */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
local_irq_restore(flags);
} else {
/* drive refused ID */
@@ -344,6 +335,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
static int try_to_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int retval;
int autoprobe = 0;
unsigned long cookie = 0;
@@ -359,7 +351,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
autoprobe = 1;
cookie = probe_irq_on();
}
- ide_set_irq(drive, autoprobe);
+ tp_ops->set_irq(hwif, autoprobe);
}
retval = actual_try_to_identify(drive, cmd);
@@ -367,9 +359,9 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
if (autoprobe) {
int irq;
- ide_set_irq(drive, 0);
+ tp_ops->set_irq(hwif, 0);
/* clear drive IRQ */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
udelay(5);
irq = probe_irq_off(cookie);
if (!hwif->irq) {
@@ -379,7 +371,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
/* Mmmm.. multiple IRQs..
* don't know which was ours
*/
- printk("%s: IRQ probe failed (0x%lx)\n",
+ printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n",
drive->name, cookie);
}
}
@@ -387,19 +379,33 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
return retval;
}
-static int ide_busy_sleep(ide_hwif_t *hwif)
+int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus)
{
- unsigned long timeout = jiffies + WAIT_WORSTCASE;
u8 stat;
+ timeout += jiffies;
+
do {
- msleep(50);
- stat = hwif->INB(hwif->io_ports.status_addr);
- if ((stat & BUSY_STAT) == 0)
+ msleep(50); /* give drive a breather */
+ stat = altstatus ? hwif->tp_ops->read_altstatus(hwif)
+ : hwif->tp_ops->read_status(hwif);
+ if ((stat & ATA_BUSY) == 0)
return 0;
} while (time_before(jiffies, timeout));
- return 1;
+ return 1; /* drive timed-out */
+}
+
+static u8 ide_read_device(ide_drive_t *drive)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_DEVICE;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.device;
}
/**
@@ -426,19 +432,18 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
static int do_probe (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
- struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int rc;
- u8 stat;
+ u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
+
+ /* avoid waiting for inappropriate probes */
+ if (present && drive->media != ide_disk && cmd == ATA_CMD_ID_ATA)
+ return 4;
- if (drive->present) {
- /* avoid waiting for inappropriate probes */
- if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))
- return 4;
- }
#ifdef DEBUG
- printk("probing for %s: present=%d, media=%d, probetype=%s\n",
- drive->name, drive->present, drive->media,
- (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
+ printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n",
+ drive->name, present, drive->media,
+ (cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI");
#endif
/* needed for some systems
@@ -447,46 +452,46 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
msleep(50);
SELECT_DRIVE(drive);
msleep(50);
- if (hwif->INB(io_ports->device_addr) != drive->select.all &&
- !drive->present) {
- if (drive->select.b.unit != 0) {
+
+ if (ide_read_device(drive) != drive->select && present == 0) {
+ if (drive->dn & 1) {
/* exit with drive0 selected */
SELECT_DRIVE(&hwif->drives[0]);
- /* allow BUSY_STAT to assert & clear */
+ /* allow ATA_BUSY to assert & clear */
msleep(50);
}
/* no i/f present: mmm.. this should be a 4 -ml */
return 3;
}
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
- if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
- drive->present || cmd == WIN_PIDENTIFY) {
+ if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
+ present || cmd == ATA_CMD_ID_ATAPI) {
/* send cmd and wait */
if ((rc = try_to_identify(drive, cmd))) {
/* failed: try again */
rc = try_to_identify(drive,cmd);
}
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
- if (stat == (BUSY_STAT | READY_STAT))
+ if (stat == (ATA_BUSY | ATA_DRDY))
return 4;
- if (rc == 1 && cmd == WIN_PIDENTIFY) {
+ if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
printk(KERN_ERR "%s: no response (status = 0x%02x), "
"resetting drive\n", drive->name, stat);
msleep(50);
- hwif->OUTB(drive->select.all, io_ports->device_addr);
+ SELECT_DRIVE(drive);
msleep(50);
- hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr);
- (void)ide_busy_sleep(hwif);
+ tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
+ (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
rc = try_to_identify(drive, cmd);
}
/* ensure drive IRQ is clear */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (rc == 1)
printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
@@ -495,12 +500,12 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
/* not present or maybe ATAPI */
rc = 3;
}
- if (drive->select.b.unit != 0) {
+ if (drive->dn & 1) {
/* exit with drive0 selected */
SELECT_DRIVE(&hwif->drives[0]);
msleep(50);
/* ensure drive irq is clear */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
}
return rc;
}
@@ -511,32 +516,29 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
static void enable_nest (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u8 stat;
- printk("%s: enabling %s -- ", hwif->name, drive->id->model);
+ printk(KERN_INFO "%s: enabling %s -- ",
+ hwif->name, (char *)&drive->id[ATA_ID_PROD]);
+
SELECT_DRIVE(drive);
msleep(50);
- hwif->OUTBSYNC(drive, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST);
- if (ide_busy_sleep(hwif)) {
+ if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) {
printk(KERN_CONT "failed (timeout)\n");
return;
}
msleep(50);
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
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) {
- /* look for ATAPI device */
- (void) do_probe(drive, WIN_PIDENTIFY);
- }
}
/**
@@ -547,12 +549,14 @@ static void enable_nest (ide_drive_t *drive)
* and presents things to the user as needed.
*
* Returns: 0 no device was found
- * 1 device was found (note: drive->present might
- * still be 0)
+ * 1 device was found
+ * (note: IDE_DFLAG_PRESENT might still be not set)
*/
static inline u8 probe_for_drive (ide_drive_t *drive)
{
+ char *m;
+
/*
* In order to keep things simple we have an id
* block for all drives at all times. If the device
@@ -562,31 +566,36 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
* Also note that 0 everywhere means "can't do X"
*/
- drive->id = kzalloc(SECTOR_WORDS *4, GFP_KERNEL);
- drive->id_read = 0;
- if(drive->id == NULL)
- {
+ drive->dev_flags &= ~IDE_DFLAG_ID_READ;
+
+ drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
+ if (drive->id == NULL) {
printk(KERN_ERR "ide: out of memory for id data.\n");
return 0;
}
- strcpy(drive->id->model, "UNKNOWN");
-
+
+ m = (char *)&drive->id[ATA_ID_PROD];
+ strcpy(m, "UNKNOWN");
+
/* skip probing? */
- if (!drive->noprobe)
- {
+ if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) {
+retry:
/* if !(success||timed-out) */
- if (do_probe(drive, WIN_IDENTIFY) >= 2) {
+ if (do_probe(drive, ATA_CMD_ID_ATA) >= 2)
/* look for ATAPI device */
- (void) do_probe(drive, WIN_PIDENTIFY);
- }
- if (!drive->present)
+ (void)do_probe(drive, ATA_CMD_ID_ATAPI);
+
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
/* drive not found */
return 0;
- if (strstr(drive->id->model, "E X A B Y T E N E S T"))
+
+ if (strstr(m, "E X A B Y T E N E S T")) {
enable_nest(drive);
-
+ goto retry;
+ }
+
/* identification failed? */
- if (!drive->id_read) {
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
if (drive->media == ide_disk) {
printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n",
drive->name, drive->cyl,
@@ -596,15 +605,17 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
} else {
/* nuke it */
printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
- drive->present = 0;
+ drive->dev_flags &= ~IDE_DFLAG_PRESENT;
}
}
/* drive was found */
}
- if(!drive->present)
+
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
return 0;
+
/* The drive wasn't being helpful. Add generic info only */
- if (drive->id_read == 0) {
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
generic_id(drive);
return 1;
}
@@ -614,10 +625,10 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
ide_disk_init_mult_count(drive);
}
- return drive->present;
+ return !!(drive->dev_flags & IDE_DFLAG_PRESENT);
}
-static void hwif_release_dev (struct device *dev)
+static void hwif_release_dev(struct device *dev)
{
ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev);
@@ -646,8 +657,6 @@ static int ide_register_port(ide_hwif_t *hwif)
goto out;
}
- get_device(&hwif->gendev);
-
hwif->portdev = device_create_drvdata(ide_port_class, &hwif->gendev,
MKDEV(0, 0), hwif, hwif->name);
if (IS_ERR(hwif->portdev)) {
@@ -707,9 +716,10 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
ide_drive_t *drive = &hwif->drives[unit];
/* Ignore disks that we will not probe for later. */
- if (!drive->noprobe || drive->present) {
+ if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_PRESENT)) {
SELECT_DRIVE(drive);
- ide_set_irq(drive, 1);
+ hwif->tp_ops->set_irq(hwif, 1);
mdelay(2);
rc = ide_wait_not_busy(hwif, 35000);
if (rc)
@@ -728,36 +738,38 @@ out:
/**
* ide_undecoded_slave - look for bad CF adapters
- * @drive1: drive
+ * @dev1: slave device
*
* 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_drive_t *drive1)
+void ide_undecoded_slave(ide_drive_t *dev1)
{
- ide_drive_t *drive0 = &drive1->hwif->drives[0];
+ ide_drive_t *dev0 = &dev1->hwif->drives[0];
- if ((drive1->dn & 1) == 0 || drive0->present == 0)
+ if ((dev1->dn & 1) == 0 || (dev0->dev_flags & IDE_DFLAG_PRESENT) == 0)
return;
/* If the models don't match they are not the same product */
- if (strcmp(drive0->id->model, drive1->id->model))
+ if (strcmp((char *)&dev0->id[ATA_ID_PROD],
+ (char *)&dev1->id[ATA_ID_PROD]))
return;
/* Serial numbers do not match */
- if (strncmp(drive0->id->serial_no, drive1->id->serial_no, 20))
+ if (strncmp((char *)&dev0->id[ATA_ID_SERNO],
+ (char *)&dev1->id[ATA_ID_SERNO], ATA_ID_SERNO_LEN))
return;
/* No serial number, thankfully very rare for CF */
- if (drive0->id->serial_no[0] == 0)
+ if (*(char *)&dev0->id[ATA_ID_SERNO] == 0)
return;
/* Appears to be an IDE flash adapter with decode bugs */
printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
- drive1->present = 0;
+ dev1->dev_flags &= ~IDE_DFLAG_PRESENT;
}
EXPORT_SYMBOL_GPL(ide_undecoded_slave);
@@ -770,7 +782,8 @@ static int ide_probe_port(ide_hwif_t *hwif)
BUG_ON(hwif->present);
- if (hwif->drives[0].noprobe && hwif->drives[1].noprobe)
+ if ((hwif->drives[0].dev_flags & IDE_DFLAG_NOPROBE) &&
+ (hwif->drives[1].dev_flags & IDE_DFLAG_NOPROBE))
return -EACCES;
/*
@@ -792,9 +805,9 @@ static int ide_probe_port(ide_hwif_t *hwif)
*/
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- drive->dn = (hwif->channel ? 2 : 0) + unit;
+
(void) probe_for_drive(drive);
- if (drive->present)
+ if (drive->dev_flags & IDE_DFLAG_PRESENT)
rc = 0;
}
@@ -818,17 +831,19 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
for (unit = 0; unit < MAX_DRIVES; unit++) {
ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present && port_ops && port_ops->quirkproc)
- port_ops->quirkproc(drive);
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
+ if (port_ops && port_ops->quirkproc)
+ port_ops->quirkproc(drive);
+ }
}
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present) {
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
ide_set_max_pio(drive);
- drive->nice1 = 1;
+ drive->dev_flags |= IDE_DFLAG_NICE1;
if (hwif->dma_ops)
ide_set_dma(drive);
@@ -838,14 +853,14 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
- drive->no_io_32bit = 1;
+ if ((hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) ||
+ drive->id[ATA_ID_DWORD_IO])
+ drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
else
- drive->no_io_32bit = drive->id->dword_io ? 1 : 0;
+ drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
}
}
-#if MAX_HWIFS > 1
/*
* save_match() is used to simplify logic in init_irq() below.
*
@@ -864,13 +879,12 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
if (!new->hwgroup)
return;
- printk("%s: potential irq problem with %s and %s\n",
+ printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n",
hwif->name, new->name, m->name);
}
if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
*match = new;
}
-#endif /* MAX_HWIFS > 1 */
/*
* init request queue
@@ -949,26 +963,72 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
* - allocate the block device queue
* - link drive into the hwgroup
*/
-static void ide_port_setup_devices(ide_hwif_t *hwif)
+static int ide_port_setup_devices(ide_hwif_t *hwif)
{
- int i;
+ int i, j = 0;
mutex_lock(&ide_cfg_mtx);
for (i = 0; i < MAX_DRIVES; i++) {
ide_drive_t *drive = &hwif->drives[i];
- if (!drive->present)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
if (ide_init_queue(drive)) {
printk(KERN_ERR "ide: failed to init %s\n",
drive->name);
+ kfree(drive->id);
+ drive->id = NULL;
+ drive->dev_flags &= ~IDE_DFLAG_PRESENT;
continue;
}
+ j++;
+
ide_add_drive_to_hwgroup(drive);
}
mutex_unlock(&ide_cfg_mtx);
+
+ return j;
+}
+
+static ide_hwif_t *ide_ports[MAX_HWIFS];
+
+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+{
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+
+ ide_ports[hwif->index] = NULL;
+
+ 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);
}
/*
@@ -986,20 +1046,16 @@ static int init_irq (ide_hwif_t *hwif)
ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL;
-
- BUG_ON(in_interrupt());
- BUG_ON(irqs_disabled());
- BUG_ON(hwif == NULL);
-
mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL;
-#if MAX_HWIFS > 1
+
/*
* Group up with any other hwifs that share our irq(s).
*/
for (index = 0; index < MAX_HWIFS; index++) {
- ide_hwif_t *h = &ide_hwifs[index];
- if (h->hwgroup) { /* scan only initialized hwif's */
+ ide_hwif_t *h = ide_ports[index];
+
+ if (h && h->hwgroup) { /* scan only initialized ports */
if (hwif->irq == h->irq) {
hwif->sharing_irq = h->sharing_irq = 1;
if (hwif->chipset != ide_pci ||
@@ -1017,7 +1073,7 @@ static int init_irq (ide_hwif_t *hwif)
}
}
}
-#endif /* MAX_HWIFS > 1 */
+
/*
* If we are still without a hwgroup, then form a new one
*/
@@ -1053,6 +1109,8 @@ static int init_irq (ide_hwif_t *hwif)
hwgroup->timer.data = (unsigned long) hwgroup;
}
+ ide_ports[hwif->index] = hwif;
+
/*
* Allocate the irq, if not already obtained for another hwif
*/
@@ -1062,12 +1120,12 @@ static int init_irq (ide_hwif_t *hwif)
sa = IRQF_SHARED;
#endif /* __mc68000__ */
- if (IDE_CHIPSET_IS_PCI(hwif->chipset))
+ if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 ||
+ hwif->chipset == ide_ali14xx)
sa = IRQF_SHARED;
if (io_ports->ctl_addr)
- /* clear nIEN */
- hwif->OUTB(0x08, io_ports->ctl_addr);
+ hwif->tp_ops->set_irq(hwif, 1);
if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
goto out_unlink;
@@ -1082,17 +1140,17 @@ static int init_irq (ide_hwif_t *hwif)
}
#if !defined(__mc68000__)
- printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
+ printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
io_ports->data_addr, io_ports->status_addr,
io_ports->ctl_addr, hwif->irq);
#else
- printk("%s at 0x%08lx on irq %d", hwif->name,
+ printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name,
io_ports->data_addr, hwif->irq);
#endif /* __mc68000__ */
if (match)
- printk(" (%sed with %s)",
+ printk(KERN_CONT " (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name);
- printk("\n");
+ printk(KERN_CONT "\n");
mutex_unlock(&ide_cfg_mtx);
return 0;
@@ -1114,12 +1172,13 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data)
ide_hwif_t *hwif = data;
int unit = *part >> PARTN_BITS;
ide_drive_t *drive = &hwif->drives[unit];
- if (!drive->present)
+
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
return NULL;
if (drive->media == ide_disk)
request_module("ide-disk");
- if (drive->scsi)
+ if (drive->dev_flags & IDE_DFLAG_SCSI)
request_module("ide-scsi");
if (drive->media == ide_cdrom || drive->media == ide_optical)
request_module("ide-cd");
@@ -1135,7 +1194,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data)
{
struct gendisk *p = data;
*part &= (1 << PARTN_BITS) - 1;
- return &p->dev.kobj;
+ return &disk_to_dev(p)->kobj;
}
static int exact_lock(dev_t dev, void *data)
@@ -1166,7 +1225,7 @@ EXPORT_SYMBOL_GPL(ide_unregister_region);
void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- unsigned int unit = (drive->select.all >> 4) & 1;
+ unsigned int unit = drive->dn & 1;
disk->major = hwif->major;
disk->first_minor = unit << PARTN_BITS;
@@ -1209,7 +1268,7 @@ static void drive_release_dev (struct device *dev)
ide_remove_drive_from_hwgroup(drive);
kfree(drive->id);
drive->id = NULL;
- drive->present = 0;
+ drive->dev_flags &= ~IDE_DFLAG_PRESENT;
/* Messed up locking ... */
spin_unlock_irq(&ide_lock);
blk_cleanup_queue(drive->queue);
@@ -1220,18 +1279,14 @@ static void drive_release_dev (struct device *dev)
complete(&drive->gendev_rel_comp);
}
-#ifndef ide_default_irq
-#define ide_default_irq(irq) 0
-#endif
-
static int hwif_init(ide_hwif_t *hwif)
{
int old_irq;
if (!hwif->irq) {
- hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+ hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
if (!hwif->irq) {
- printk("%s: DISABLED, NO IRQ\n", hwif->name);
+ printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name);
return 0;
}
}
@@ -1259,18 +1314,18 @@ static int hwif_init(ide_hwif_t *hwif)
* It failed to initialise. Find the default IRQ for
* this port and try that.
*/
- hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+ hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
if (!hwif->irq) {
- printk("%s: Disabled unable to get IRQ %d.\n",
+ printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n",
hwif->name, old_irq);
goto out;
}
if (init_irq(hwif)) {
- printk("%s: probed IRQ %d and default IRQ %d failed.\n",
+ printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n",
hwif->name, old_irq, hwif->irq);
goto out;
}
- printk("%s: probed IRQ %d failed, using default.\n",
+ printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n",
hwif->name, hwif->irq);
done:
@@ -1292,11 +1347,9 @@ static void hwif_register_devices(ide_hwif_t *hwif)
struct device *dev = &drive->gendev;
int ret;
- if (!drive->present)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
- 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;
@@ -1318,16 +1371,18 @@ static void ide_port_init_devices(ide_hwif_t *hwif)
for (i = 0; i < MAX_DRIVES; i++) {
ide_drive_t *drive = &hwif->drives[i];
+ drive->dn = i + hwif->channel * 2;
+
if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
drive->io_32bit = 1;
if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS)
- drive->unmask = 1;
+ drive->dev_flags |= IDE_DFLAG_UNMASK;
if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
- drive->no_unmask = 1;
- }
+ drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
- if (port_ops && port_ops->port_init_devs)
- port_ops->port_init_devs(hwif);
+ if (port_ops && port_ops->init_dev)
+ port_ops->init_dev(drive);
+ }
}
static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
@@ -1349,6 +1404,9 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
hwif->host_flags |= d->host_flags;
hwif->pio_mask = d->pio_mask;
+ if (d->tp_ops)
+ hwif->tp_ops = d->tp_ops;
+
/* ->set_pio_mode for DTC2278 is currently limited to port 0 */
if (hwif->chipset != ide_dtc2278 || hwif->channel == 0)
hwif->port_ops = d->port_ops;
@@ -1367,6 +1425,7 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
if (rc < 0) {
printk(KERN_INFO "%s: DMA disabled\n", hwif->name);
+ hwif->dma_base = 0;
hwif->swdma_mask = 0;
hwif->mwdma_mask = 0;
hwif->ultra_mask = 0;
@@ -1439,7 +1498,7 @@ static struct device_attribute *ide_port_attrs[] = {
static int ide_sysfs_register_port(ide_hwif_t *hwif)
{
- int i, rc;
+ int i, uninitialized_var(rc);
for (i = 0; ide_port_attrs[i]; i++) {
rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
@@ -1450,18 +1509,20 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif)
return rc;
}
+static unsigned int ide_indexes;
+
/**
- * ide_find_port_slot - find free ide_hwifs[] slot
+ * ide_find_port_slot - find free port slot
* @d: IDE port info
*
- * Return the new hwif. If we are out of free slots return NULL.
+ * Return the new port slot index or -ENOENT if we are out of free slots.
*/
-ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
+static int ide_find_port_slot(const struct ide_port_info *d)
{
- ide_hwif_t *hwif;
- int i;
+ int idx = -ENOENT;
u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
+ u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;;
/*
* Claim an unassigned slot.
@@ -1473,68 +1534,122 @@ ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
* Unless there is a bootable card that does not use the standard
* ports 0x1f0/0x170 (the ide0/ide1 defaults).
*/
+ mutex_lock(&ide_cfg_mtx);
if (bootable) {
- i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
-
- for (; i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- return hwif;
- }
+ if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
+ idx = ffz(ide_indexes | i);
} else {
- for (i = 2; i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- return hwif;
- }
- for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- return hwif;
+ if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
+ idx = ffz(ide_indexes | 3);
+ else if ((ide_indexes & 3) != 3)
+ idx = ffz(ide_indexes);
+ }
+ if (idx >= 0)
+ ide_indexes |= (1 << idx);
+ mutex_unlock(&ide_cfg_mtx);
+
+ return idx;
+}
+
+static void ide_free_port_slot(int idx)
+{
+ mutex_lock(&ide_cfg_mtx);
+ ide_indexes &= ~(1 << idx);
+ mutex_unlock(&ide_cfg_mtx);
+}
+
+struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
+{
+ struct ide_host *host;
+ int i;
+
+ host = kzalloc(sizeof(*host), GFP_KERNEL);
+ if (host == NULL)
+ return NULL;
+
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ ide_hwif_t *hwif;
+ int idx;
+
+ if (hws[i] == NULL)
+ continue;
+
+ hwif = kzalloc(sizeof(*hwif), GFP_KERNEL);
+ if (hwif == NULL)
+ continue;
+
+ idx = ide_find_port_slot(d);
+ if (idx < 0) {
+ printk(KERN_ERR "%s: no free slot for interface\n",
+ d ? d->name : "ide");
+ kfree(hwif);
+ continue;
}
+
+ ide_init_port_data(hwif, idx);
+
+ hwif->host = host;
+
+ host->ports[i] = hwif;
+ host->n_ports++;
}
- return NULL;
+ if (host->n_ports == 0) {
+ kfree(host);
+ return NULL;
+ }
+
+ if (hws[0])
+ host->dev[0] = hws[0]->dev;
+
+ if (d) {
+ host->init_chipset = d->init_chipset;
+ host->host_flags = d->host_flags;
+ }
+
+ return host;
}
-EXPORT_SYMBOL_GPL(ide_find_port_slot);
+EXPORT_SYMBOL_GPL(ide_host_alloc);
-int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
+ hw_regs_t **hws)
{
ide_hwif_t *hwif, *mate = NULL;
- int i, rc = 0;
+ int i, j = 0;
+
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ hwif = host->ports[i];
- for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff) {
+ if (hwif == NULL) {
mate = NULL;
continue;
}
- hwif = &ide_hwifs[idx[i]];
-
+ ide_init_port_hw(hwif, hws[i]);
ide_port_apply_params(hwif);
if (d == NULL) {
mate = NULL;
- continue;
- }
+ } else {
+ if ((i & 1) && mate) {
+ hwif->mate = mate;
+ mate->mate = hwif;
+ }
- if ((i & 1) && mate) {
- hwif->mate = mate;
- mate->mate = hwif;
- }
+ mate = (i & 1) ? NULL : hwif;
- mate = (i & 1) ? NULL : hwif;
+ ide_init_port(hwif, i & 1, d);
+ ide_port_cable_detect(hwif);
+ }
- ide_init_port(hwif, i & 1, d);
- ide_port_cable_detect(hwif);
ide_port_init_devices(hwif);
}
- for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (ide_probe_port(hwif) == 0)
hwif->present = 1;
@@ -1547,22 +1662,26 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
ide_port_tune_devices(hwif);
}
- for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (hwif_init(hwif) == 0) {
printk(KERN_INFO "%s: failed to initialize IDE "
"interface\n", hwif->name);
hwif->present = 0;
- rc = -1;
continue;
}
if (hwif->present)
- ide_port_setup_devices(hwif);
+ if (ide_port_setup_devices(hwif) == 0) {
+ hwif->present = 0;
+ continue;
+ }
+
+ j++;
ide_acpi_init(hwif);
@@ -1570,11 +1689,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
ide_acpi_port_init_devices(hwif);
}
- for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (hwif->chipset == ide_unknown)
hwif->chipset = ide_generic;
@@ -1583,11 +1702,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
hwif_register_devices(hwif);
}
- for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
ide_sysfs_register_port(hwif);
ide_proc_register_port(hwif);
@@ -1596,21 +1715,64 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
ide_proc_port_register_devices(hwif);
}
- return rc;
+ return j ? 0 : -1;
+}
+EXPORT_SYMBOL_GPL(ide_host_register);
+
+int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
+ struct ide_host **hostp)
+{
+ struct ide_host *host;
+ int rc;
+
+ host = ide_host_alloc(d, hws);
+ if (host == NULL)
+ return -ENOMEM;
+
+ rc = ide_host_register(host, d, hws);
+ if (rc) {
+ ide_host_free(host);
+ return rc;
+ }
+
+ if (hostp)
+ *hostp = host;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_host_add);
+
+void ide_host_free(struct ide_host *host)
+{
+ ide_hwif_t *hwif;
+ int i;
+
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ hwif = host->ports[i];
+
+ if (hwif == NULL)
+ continue;
+
+ ide_free_port_slot(hwif->index);
+ kfree(hwif);
+ }
+
+ kfree(host);
}
-EXPORT_SYMBOL_GPL(ide_device_add_all);
+EXPORT_SYMBOL_GPL(ide_host_free);
-int ide_device_add(u8 idx[4], const struct ide_port_info *d)
+void ide_host_remove(struct ide_host *host)
{
- u8 idx_all[MAX_HWIFS];
int i;
- for (i = 0; i < MAX_HWIFS; i++)
- idx_all[i] = (i < 4) ? idx[i] : 0xff;
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ if (host->ports[i])
+ ide_unregister(host->ports[i]);
+ }
- return ide_device_add_all(idx_all, d);
+ ide_host_free(host);
}
-EXPORT_SYMBOL_GPL(ide_device_add);
+EXPORT_SYMBOL_GPL(ide_host_remove);
void ide_port_scan(ide_hwif_t *hwif)
{
@@ -1631,11 +1793,10 @@ void ide_port_scan(ide_hwif_t *hwif)
}
EXPORT_SYMBOL_GPL(ide_port_scan);
-static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
- const struct ide_port_info *d,
+static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
+ u8 port_no, const struct ide_port_info *d,
unsigned long config)
{
- ide_hwif_t *hwif;
unsigned long base, ctl;
int irq;
@@ -1665,33 +1826,25 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
ide_std_init_ports(hw, base, ctl);
hw->irq = irq;
hw->chipset = d->chipset;
+ hw->config = config;
- hwif = ide_find_port_slot(d);
- if (hwif) {
- ide_init_port_hw(hwif, hw);
- if (config)
- hwif->config_data = config;
- idx[port_no] = hwif->index;
- }
+ hws[port_no] = hw;
}
int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
{
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw[2];
+ hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
memset(&hw, 0, sizeof(hw));
if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
- ide_legacy_init_one(idx, &hw[0], 0, d, config);
- ide_legacy_init_one(idx, &hw[1], 1, d, config);
+ ide_legacy_init_one(hws, &hw[0], 0, d, config);
+ ide_legacy_init_one(hws, &hw[1], 1, d, config);
- if (idx[0] == 0xff && idx[1] == 0xff &&
+ if (hws[0] == NULL && hws[1] == NULL &&
(d->host_flags & IDE_HFLAG_SINGLE))
return -ENOENT;
- ide_device_add(idx, d);
-
- return 0;
+ return ide_host_add(d, hws, NULL);
}
EXPORT_SYMBOL_GPL(ide_legacy_device_add);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 55ec7f79877..b26926487cc 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -12,14 +12,6 @@
* "settings" files. e.g. "cat /proc/ide0/hda/settings"
* To write a new value "val" into a specific setting "name", use:
* echo "name:val" >/proc/ide/ide0/hda/settings
- *
- * Also useful, "cat /proc/ide0/hda/[identify, smart_values,
- * smart_thresholds, capabilities]" will issue an IDENTIFY /
- * PACKET_IDENTIFY / SMART_READ_VALUES / SMART_READ_THRESHOLDS /
- * SENSE CAPABILITIES command to /dev/hda, and then dump out the
- * returned data as 256 16-bit words. The "hdparm" utility will
- * be updated someday soon to use this mechanism.
- *
*/
#include <linux/module.h>
@@ -31,7 +23,6 @@
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/ctype.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/seq_file.h>
@@ -76,7 +67,7 @@ static int proc_ide_read_mate
ide_hwif_t *hwif = (ide_hwif_t *) data;
int len;
- if (hwif && hwif->mate && hwif->mate->present)
+ if (hwif && hwif->mate)
len = sprintf(page, "%s\n", hwif->mate->name);
else
len = sprintf(page, "(none)\n");
@@ -105,17 +96,18 @@ static int proc_ide_read_identify
len = sprintf(page, "\n");
if (drive) {
- unsigned short *val = (unsigned short *) page;
+ __le16 *val = (__le16 *)page;
err = taskfile_lib_get_identify(drive, page);
if (!err) {
- char *out = ((char *)page) + (SECTOR_WORDS * 4);
+ char *out = (char *)page + SECTOR_SIZE;
+
page = out;
do {
out += sprintf(out, "%04x%c",
- le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+ le16_to_cpup(val), (++i & 7) ? ' ' : '\n');
val += 1;
- } while (i < (SECTOR_WORDS * 2));
+ } while (i < SECTOR_SIZE / 2);
len = out - page;
}
}
@@ -123,140 +115,25 @@ static int proc_ide_read_identify
}
/**
- * __ide_add_setting - add an ide setting option
- * @drive: drive to use
- * @name: setting name
- * @rw: true if the function is read write
- * @data_type: type of data
- * @min: range minimum
- * @max: range maximum
- * @mul_factor: multiplication scale
- * @div_factor: divison scale
- * @data: private data field
- * @set: setting
- * @auto_remove: setting auto removal flag
- *
- * Removes the setting named from the device if it is present.
- * The function takes the settings_lock to protect against
- * parallel changes. This function must not be called from IRQ
- * context. Returns 0 on success or -1 on failure.
- *
- * BUGS: This code is seriously over-engineered. There is also
- * magic about how the driver specific features are setup. If
- * a driver is attached we assume the driver settings are auto
- * remove.
- */
-
-static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
-{
- ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
-
- mutex_lock(&ide_setting_mtx);
- while ((*p) && strcmp((*p)->name, name) < 0)
- p = &((*p)->next);
- if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
- goto abort;
- if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
- goto abort;
- strcpy(setting->name, name);
- setting->rw = rw;
- setting->data_type = data_type;
- setting->min = min;
- setting->max = max;
- setting->mul_factor = mul_factor;
- setting->div_factor = div_factor;
- setting->data = data;
- setting->set = set;
-
- setting->next = *p;
- if (auto_remove)
- setting->auto_remove = 1;
- *p = setting;
- mutex_unlock(&ide_setting_mtx);
- return 0;
-abort:
- mutex_unlock(&ide_setting_mtx);
- kfree(setting);
- return -1;
-}
-
-int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
-{
- return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1);
-}
-
-EXPORT_SYMBOL(ide_add_setting);
-
-/**
- * __ide_remove_setting - remove an ide setting option
- * @drive: drive to use
- * @name: setting name
- *
- * Removes the setting named from the device if it is present.
- * The caller must hold the setting semaphore.
- */
-
-static void __ide_remove_setting(ide_drive_t *drive, char *name)
-{
- ide_settings_t **p, *setting;
-
- p = (ide_settings_t **) &drive->settings;
-
- while ((*p) && strcmp((*p)->name, name))
- p = &((*p)->next);
- setting = (*p);
- if (setting == NULL)
- return;
-
- (*p) = setting->next;
-
- kfree(setting->name);
- kfree(setting);
-}
-
-/**
- * auto_remove_settings - remove driver specific settings
- * @drive: drive
- *
- * Automatically remove all the driver specific settings for this
- * drive. This function may not be called from IRQ context. The
- * caller must hold ide_setting_mtx.
- */
-
-static void auto_remove_settings(ide_drive_t *drive)
-{
- ide_settings_t *setting;
-repeat:
- setting = drive->settings;
- while (setting) {
- if (setting->auto_remove) {
- __ide_remove_setting(drive, setting->name);
- goto repeat;
- }
- setting = setting->next;
- }
-}
-
-/**
- * ide_find_setting_by_name - find a drive specific setting
- * @drive: drive to scan
+ * ide_find_setting - find a specific setting
+ * @st: setting table pointer
* @name: setting name
*
- * Scan's the device setting table for a matching entry and returns
+ * Scan's the setting table for a matching entry and returns
* this or NULL if no entry is found. The caller must hold the
* setting semaphore
*/
-static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
+static
+const struct ide_proc_devset *ide_find_setting(const struct ide_proc_devset *st,
+ char *name)
{
- ide_settings_t *setting = drive->settings;
-
- while (setting) {
- if (strcmp(setting->name, name) == 0)
+ while (st->name) {
+ if (strcmp(st->name, name) == 0)
break;
- setting = setting->next;
+ st++;
}
- return setting;
+ return st->name ? st : NULL;
}
/**
@@ -272,26 +149,20 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
* be told apart
*/
-static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
+static int ide_read_setting(ide_drive_t *drive,
+ const struct ide_proc_devset *setting)
{
- int val = -EINVAL;
- unsigned long flags;
+ const struct ide_devset *ds = setting->setting;
+ int val = -EINVAL;
+
+ if (ds->get) {
+ unsigned long flags;
- if ((setting->rw & SETTING_READ)) {
spin_lock_irqsave(&ide_lock, flags);
- switch (setting->data_type) {
- case TYPE_BYTE:
- val = *((u8 *) setting->data);
- break;
- case TYPE_SHORT:
- val = *((u16 *) setting->data);
- break;
- case TYPE_INT:
- val = *((u32 *) setting->data);
- break;
- }
+ val = ds->get(drive);
spin_unlock_irqrestore(&ide_lock, flags);
}
+
return val;
}
@@ -313,43 +184,33 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
* The current scheme of polling is kludgy, though safe enough.
*/
-static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
+static int ide_write_setting(ide_drive_t *drive,
+ const struct ide_proc_devset *setting, int val)
{
+ const struct ide_devset *ds = setting->setting;
+
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (setting->set)
- return setting->set(drive, val);
- if (!(setting->rw & SETTING_WRITE))
+ if (!ds->set)
return -EPERM;
- if (val < setting->min || val > setting->max)
+ if ((ds->flags & DS_SYNC)
+ && (val < setting->min || val > setting->max))
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- switch (setting->data_type) {
- case TYPE_BYTE:
- *((u8 *) setting->data) = val;
- break;
- case TYPE_SHORT:
- *((u16 *) setting->data) = val;
- break;
- case TYPE_INT:
- *((u32 *) setting->data) = val;
- break;
- }
- spin_unlock_irq(&ide_lock);
- return 0;
+ return ide_devset_execute(drive, ds, val);
}
+ide_devset_get(xfer_rate, current_speed);
+
static int set_xfer_rate (ide_drive_t *drive, int arg)
{
ide_task_t task;
int err;
- if (arg < 0 || arg > 70)
+ if (arg < XFER_PIO_0 || arg > XFER_UDMA_6)
return -EINVAL;
memset(&task, 0, sizeof(task));
- task.tf.command = WIN_SETFEATURES;
+ task.tf.command = ATA_CMD_SET_FEATURES;
task.tf.feature = SETFEATURES_XFER;
task.tf.nsect = (u8)arg;
task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
@@ -357,36 +218,30 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
err = ide_no_data_taskfile(drive, &task);
- if (!err && arg) {
+ if (!err) {
ide_set_xfer_rate(drive, (u8) arg);
ide_driveid_update(drive);
}
return err;
}
-/**
- * ide_add_generic_settings - generic ide settings
- * @drive: drive being configured
- *
- * Add the generic parts of the system settings to the /proc files.
- * The caller must not be holding the ide_setting_mtx.
- */
-
-void ide_add_generic_settings (ide_drive_t *drive)
-{
-/*
- * drive setting name read/write access data type min max mul_factor div_factor data pointer set function
- */
- __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0);
- __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0);
- __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0);
- __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0);
- __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0);
- __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0);
- __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0);
- __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0);
- __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0);
-}
+ide_devset_rw(current_speed, xfer_rate);
+ide_devset_rw_field(init_speed, init_speed);
+ide_devset_rw_flag(nice1, IDE_DFLAG_NICE1);
+ide_devset_rw_field(number, dn);
+
+static const struct ide_proc_devset ide_generic_settings[] = {
+ IDE_PROC_DEVSET(current_speed, 0, 70),
+ IDE_PROC_DEVSET(init_speed, 0, 70),
+ IDE_PROC_DEVSET(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1)),
+ IDE_PROC_DEVSET(keepsettings, 0, 1),
+ IDE_PROC_DEVSET(nice1, 0, 1),
+ IDE_PROC_DEVSET(number, 0, 3),
+ IDE_PROC_DEVSET(pio_mode, 0, 255),
+ IDE_PROC_DEVSET(unmaskirq, 0, 1),
+ IDE_PROC_DEVSET(using_dma, 0, 1),
+ { 0 },
+};
static void proc_ide_settings_warn(void)
{
@@ -403,19 +258,32 @@ static void proc_ide_settings_warn(void)
static int proc_ide_read_settings
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
+ const struct ide_proc_devset *setting, *g, *d;
+ const struct ide_devset *ds;
ide_drive_t *drive = (ide_drive_t *) data;
- ide_settings_t *setting = (ide_settings_t *) drive->settings;
char *out = page;
int len, rc, mul_factor, div_factor;
proc_ide_settings_warn();
mutex_lock(&ide_setting_mtx);
+ g = ide_generic_settings;
+ d = drive->settings;
out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
- while (setting) {
- mul_factor = setting->mul_factor;
- div_factor = setting->div_factor;
+ while (g->name || (d && d->name)) {
+ /* read settings in the alphabetical order */
+ if (g->name && d && d->name) {
+ if (strcmp(d->name, g->name) < 0)
+ setting = d++;
+ else
+ setting = g++;
+ } else if (d && d->name) {
+ setting = d++;
+ } else
+ setting = g++;
+ mul_factor = setting->mulf ? setting->mulf(drive) : 1;
+ div_factor = setting->divf ? setting->divf(drive) : 1;
out += sprintf(out, "%-24s", setting->name);
rc = ide_read_setting(drive, setting);
if (rc >= 0)
@@ -423,12 +291,12 @@ static int proc_ide_read_settings
else
out += sprintf(out, "%-16s", "write-only");
out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
- if (setting->rw & SETTING_READ)
+ ds = setting->setting;
+ if (ds->get)
out += sprintf(out, "r");
- if (setting->rw & SETTING_WRITE)
+ if (ds->set)
out += sprintf(out, "w");
out += sprintf(out, "\n");
- setting = setting->next;
}
len = out - page;
mutex_unlock(&ide_setting_mtx);
@@ -442,9 +310,10 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
{
ide_drive_t *drive = (ide_drive_t *) data;
char name[MAX_LEN + 1];
- int for_real = 0;
+ int for_real = 0, mul_factor, div_factor;
unsigned long n;
- ide_settings_t *setting;
+
+ const struct ide_proc_devset *setting;
char *buf, *s;
if (!capable(CAP_SYS_ADMIN))
@@ -512,13 +381,21 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
}
mutex_lock(&ide_setting_mtx);
- setting = ide_find_setting_by_name(drive, name);
+ /* generic settings first, then driver specific ones */
+ setting = ide_find_setting(ide_generic_settings, name);
if (!setting) {
- mutex_unlock(&ide_setting_mtx);
- goto parse_error;
+ if (drive->settings)
+ setting = ide_find_setting(drive->settings, name);
+ if (!setting) {
+ mutex_unlock(&ide_setting_mtx);
+ goto parse_error;
+ }
+ }
+ if (for_real) {
+ mul_factor = setting->mulf ? setting->mulf(drive) : 1;
+ div_factor = setting->divf ? setting->divf(drive) : 1;
+ ide_write_setting(drive, setting, val * div_factor / mul_factor);
}
- if (for_real)
- ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
mutex_unlock(&ide_setting_mtx);
}
} while (!for_real++);
@@ -561,11 +438,10 @@ static int proc_ide_read_dmodel
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
ide_drive_t *drive = (ide_drive_t *) data;
- struct hd_driveid *id = drive->id;
+ char *m = (char *)&drive->id[ATA_ID_PROD];
int len;
- len = sprintf(page, "%.40s\n",
- (id && id->model[0]) ? (char *)id->model : "(none)");
+ len = sprintf(page, "%.40s\n", m[0] ? m : "(none)");
PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
}
@@ -690,6 +566,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t
void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
{
+ mutex_lock(&ide_setting_mtx);
+ drive->settings = driver->settings;
+ mutex_unlock(&ide_setting_mtx);
+
ide_add_proc_entries(drive->proc, driver->proc, drive);
}
@@ -726,7 +606,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
* OTOH both ide_{read,write}_setting are only ever used under
* ide_setting_mtx.
*/
- auto_remove_settings(drive);
+ drive->settings = NULL;
spin_unlock_irqrestore(&ide_lock, flags);
mutex_unlock(&ide_setting_mtx);
}
@@ -742,9 +622,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
for (d = 0; d < MAX_DRIVES; d++) {
ide_drive_t *drive = &hwif->drives[d];
- if (!drive->present)
- continue;
- if (drive->proc)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc)
continue;
drive->proc = proc_mkdir(drive->name, parent);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 1e1f26331a2..25ac60f5327 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -15,6 +15,8 @@
* Documentation/ide/ChangeLog.ide-tape.1995-2002
*/
+#define DRV_NAME "ide-tape"
+
#define IDETAPE_VERSION "1.20"
#include <linux/module.h>
@@ -54,8 +56,6 @@ enum {
DBG_CHRDEV = (1 << 2),
/* all remaining procedures */
DBG_PROCS = (1 << 3),
- /* buffer alloc info (pc_stack & rq_stack) */
- DBG_PCRQ_STACK = (1 << 4),
};
/* define to see debug info */
@@ -81,26 +81,6 @@ enum {
#define IDETAPE_MAX_PC_RETRIES 3
/*
- * With each packet command, we allocate a buffer of IDETAPE_PC_BUFFER_SIZE
- * bytes. This is used for several packet commands (Not for READ/WRITE commands)
- */
-#define IDETAPE_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.
- */
-#define IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES)
-
-/*
- * Some drives (for example, Seagate STT3401A Travan) require a very long
- * timeout, because they don't return an interrupt or clear their busy bit
- * until after the command completes (even retension commands).
- */
-#define IDETAPE_WAIT_CMD (900*HZ)
-
-/*
* The following parameter is used to select the point in the internal tape fifo
* in which we will start to refill the buffer. Decreasing the following
* parameter will improve the system's latency and interactive response, while
@@ -144,9 +124,6 @@ enum {
/*************************** End of tunable parameters ***********************/
-/* Read/Write error simulation */
-#define SIMULATE_ERRORS 0
-
/* tape directions */
enum {
IDETAPE_DIR_NONE = (1 << 0),
@@ -175,20 +152,6 @@ struct idetape_bh {
#define IDETAPE_LU_RETENSION_MASK 2
#define IDETAPE_LU_EOT_MASK 4
-/*
- * Special requests for our block device strategy routine.
- *
- * In order to service a character device command, we add special requests to
- * the tail of our block device request queue and wait for their completion.
- */
-
-enum {
- REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */
- REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */
- REQ_IDETAPE_READ = (1 << 2),
- REQ_IDETAPE_WRITE = (1 << 3),
-};
-
/* Error codes returned in rq->errors to the higher part of the driver. */
#define IDETAPE_ERROR_GENERAL 101
#define IDETAPE_ERROR_FILEMARK 102
@@ -198,23 +161,6 @@ enum {
#define IDETAPE_BLOCK_DESCRIPTOR 0
#define IDETAPE_CAPABILITIES_PAGE 0x2a
-/* Tape flag bits values. */
-enum {
- IDETAPE_FLAG_IGNORE_DSC = (1 << 0),
- /* 0 When the tape position is unknown */
- IDETAPE_FLAG_ADDRESS_VALID = (1 << 1),
- /* Device already opened */
- IDETAPE_FLAG_BUSY = (1 << 2),
- /* Attempt to auto-detect the current user block size */
- IDETAPE_FLAG_DETECT_BS = (1 << 3),
- /* Currently on a filemark */
- IDETAPE_FLAG_FILEMARK = (1 << 4),
- /* DRQ interrupt device */
- IDETAPE_FLAG_DRQ_INTERRUPT = (1 << 5),
- /* 0 = no tape is loaded, so we don't rewind after ejecting */
- IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 6),
-};
-
/*
* 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 the struct defined below.
@@ -226,31 +172,15 @@ typedef struct ide_tape_obj {
struct kref kref;
/*
- * Since a typical character device operation requires more
- * than one packet command, we provide here enough memory
- * for the maximum of interconnected packet commands.
- * The packet commands are stored in the circular array pc_stack.
- * pc_stack_index points to the last used entry, and warps around
- * to the start when we get to the last array entry.
- *
- * pc points to the current processed packet command.
- *
* failed_pc points to the last failed packet command, or contains
* NULL if we do not need to retry any packet command. This is
* required since an additional packet command is needed before the
* retry, to get detailed information on what went wrong.
*/
- /* Current packet command */
- struct ide_atapi_pc *pc;
/* Last failed packet command */
struct ide_atapi_pc *failed_pc;
- /* Packet command stack */
- struct ide_atapi_pc pc_stack[IDETAPE_PC_STACK];
- /* Next free packet command storage space */
- int pc_stack_index;
- struct request rq_stack[IDETAPE_PC_STACK];
- /* We implement a circular array */
- int rq_stack_index;
+ /* used by REQ_IDETAPE_{READ,WRITE} requests */
+ struct ide_atapi_pc queued_pc;
/*
* DSC polling variables.
@@ -315,8 +245,6 @@ typedef struct ide_tape_obj {
/* Wasted space in each stage */
int excess_bh_size;
- /* Status/Action flags: long for set_bit */
- unsigned long flags;
/* protects the ide-tape queue */
spinlock_t lock;
@@ -339,29 +267,31 @@ static DEFINE_MUTEX(idetape_ref_mutex);
static struct class *idetape_sysfs_class;
-#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
-
-#define ide_tape_g(disk) \
- container_of((disk)->private_data, struct ide_tape_obj, driver)
+static void ide_tape_release(struct kref *);
static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
{
struct ide_tape_obj *tape = NULL;
mutex_lock(&idetape_ref_mutex);
- tape = ide_tape_g(disk);
- if (tape)
- kref_get(&tape->kref);
+ tape = ide_drv_g(disk, ide_tape_obj);
+ if (tape) {
+ if (ide_device_get(tape->drive))
+ tape = NULL;
+ else
+ kref_get(&tape->kref);
+ }
mutex_unlock(&idetape_ref_mutex);
return tape;
}
-static void ide_tape_release(struct kref *);
-
static void ide_tape_put(struct ide_tape_obj *tape)
{
+ ide_drive_t *drive = tape->drive;
+
mutex_lock(&idetape_ref_mutex);
kref_put(&tape->kref, ide_tape_release);
+ ide_device_put(drive);
mutex_unlock(&idetape_ref_mutex);
}
@@ -371,8 +301,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
*/
static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
-#define ide_tape_f(file) ((file)->private_data)
-
static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
{
struct ide_tape_obj *tape = NULL;
@@ -401,7 +329,7 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
count = min(
(unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
bcount);
- drive->hwif->input_data(drive, NULL, bh->b_data +
+ drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
atomic_read(&bh->b_count), count);
bcount -= count;
atomic_add(count, &bh->b_count);
@@ -427,7 +355,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
return;
}
count = min((unsigned int)pc->b_count, (unsigned int)bcount);
- drive->hwif->output_data(drive, NULL, pc->b_data, count);
+ drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
bcount -= count;
pc->b_data += count;
pc->b_count -= count;
@@ -442,7 +370,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
}
}
-static void idetape_update_buffers(struct ide_atapi_pc *pc)
+static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
{
struct idetape_bh *bh = pc->bh;
int count;
@@ -466,59 +394,6 @@ static void idetape_update_buffers(struct ide_atapi_pc *pc)
}
/*
- * idetape_next_pc_storage returns a pointer to a place in which we can
- * safely store a packet command, even though we intend to leave the
- * driver. A storage space for a maximum of IDETAPE_PC_STACK packet
- * commands is allocated at initialization time.
- */
-static struct ide_atapi_pc *idetape_next_pc_storage(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- debug_log(DBG_PCRQ_STACK, "pc_stack_index=%d\n", tape->pc_stack_index);
-
- if (tape->pc_stack_index == IDETAPE_PC_STACK)
- tape->pc_stack_index = 0;
- return (&tape->pc_stack[tape->pc_stack_index++]);
-}
-
-/*
- * idetape_next_rq_storage is used along with idetape_next_pc_storage.
- * Since we queue packet commands in the request queue, we need to
- * allocate a request, along with the allocation of a packet command.
- */
-
-/**************************************************************
- * *
- * This should get fixed to use kmalloc(.., GFP_ATOMIC) *
- * followed later on by kfree(). -ml *
- * *
- **************************************************************/
-
-static struct request *idetape_next_rq_storage(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- debug_log(DBG_PCRQ_STACK, "rq_stack_index=%d\n", tape->rq_stack_index);
-
- if (tape->rq_stack_index == IDETAPE_PC_STACK)
- tape->rq_stack_index = 0;
- return (&tape->rq_stack[tape->rq_stack_index++]);
-}
-
-static void idetape_init_pc(struct ide_atapi_pc *pc)
-{
- memset(pc->c, 0, 12);
- pc->retries = 0;
- pc->flags = 0;
- pc->req_xfer = 0;
- pc->buf = pc->pc_buf;
- pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
- pc->bh = NULL;
- pc->b_data = NULL;
-}
-
-/*
* called on each failed packet command retry to analyze the request sense. We
* currently do not utilize this information.
*/
@@ -538,8 +413,8 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
if (pc->flags & PC_FLAG_DMA_ERROR) {
pc->xferred = pc->req_xfer -
tape->blk_size *
- be32_to_cpu(get_unaligned((u32 *)&sense[3]));
- idetape_update_buffers(pc);
+ get_unaligned_be32(&sense[3]);
+ idetape_update_buffers(drive, pc);
}
/*
@@ -600,7 +475,6 @@ static void ide_tape_kfree_buffer(idetape_tape_t *tape)
bh = bh->b_reqnext;
kfree(prev_bh);
}
- kfree(tape->merge_bh);
}
static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
@@ -634,83 +508,70 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
return 0;
}
-static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive)
+static void ide_tape_handle_dsc(ide_drive_t *);
+
+static void ide_tape_callback(ide_drive_t *drive, int dsc)
{
idetape_tape_t *tape = drive->driver_data;
+ struct ide_atapi_pc *pc = drive->pc;
+ int uptodate = pc->error ? 0 : 1;
debug_log(DBG_PROCS, "Enter %s\n", __func__);
- if (!tape->pc->error) {
- idetape_analyze_error(drive, tape->pc->buf);
- idetape_end_request(drive, 1, 0);
- } else {
- printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - "
- "Aborting request!\n");
- idetape_end_request(drive, 0, 0);
- }
- return ide_stopped;
-}
+ if (dsc)
+ ide_tape_handle_dsc(drive);
-static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
-{
- idetape_init_pc(pc);
- pc->c[0] = REQUEST_SENSE;
- pc->c[4] = 20;
- pc->req_xfer = 20;
- pc->idetape_callback = &idetape_request_sense_callback;
-}
+ if (tape->failed_pc == pc)
+ tape->failed_pc = NULL;
-static void idetape_init_rq(struct request *rq, u8 cmd)
-{
- blk_rq_init(NULL, rq);
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[0] = cmd;
-}
+ if (pc->c[0] == REQUEST_SENSE) {
+ if (uptodate)
+ idetape_analyze_error(drive, pc->buf);
+ else
+ printk(KERN_ERR "ide-tape: Error in REQUEST SENSE "
+ "itself - Aborting request!\n");
+ } else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
+ struct request *rq = drive->hwif->hwgroup->rq;
+ int blocks = pc->xferred / tape->blk_size;
-/*
- * 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. The function below is called from the request
- * handling part of the driver (the "bottom" part). Safe storage for the request
- * should be allocated with ide_tape_next_{pc,rq}_storage() prior to that.
- *
- * Memory for those requests is pre-allocated at initialization time, and is
- * limited to IDETAPE_PC_STACK requests. We assume that we have enough space for
- * the maximum possible number of inter-dependent packet commands.
- *
- * The higher level of the driver - The ioctl handler and the character device
- * handling functions should queue request to the lower level part and wait for
- * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail.
- */
-static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
- struct request *rq)
-{
- struct ide_tape_obj *tape = drive->driver_data;
+ tape->avg_size += blocks * tape->blk_size;
- idetape_init_rq(rq, REQ_IDETAPE_PC1);
- rq->buffer = (char *) pc;
- rq->rq_disk = tape->disk;
- (void) ide_do_drive_cmd(drive, rq, ide_preempt);
-}
+ if (time_after_eq(jiffies, tape->avg_time + HZ)) {
+ tape->avg_speed = tape->avg_size * HZ /
+ (jiffies - tape->avg_time) / 1024;
+ tape->avg_size = 0;
+ tape->avg_time = jiffies;
+ }
-/*
- * idetape_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.
- */
-static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
- struct ide_atapi_pc *pc;
- struct request *rq;
+ tape->first_frame += blocks;
+ rq->current_nr_sectors -= blocks;
- (void)ide_read_error(drive);
- pc = idetape_next_pc_storage(drive);
- rq = idetape_next_rq_storage(drive);
- idetape_create_request_sense_cmd(pc);
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
- idetape_queue_pc_head(drive, pc, rq);
- return ide_stopped;
+ if (pc->error)
+ uptodate = pc->error;
+ } else if (pc->c[0] == READ_POSITION && uptodate) {
+ u8 *readpos = pc->buf;
+
+ debug_log(DBG_SENSE, "BOP - %s\n",
+ (readpos[0] & 0x80) ? "Yes" : "No");
+ debug_log(DBG_SENSE, "EOP - %s\n",
+ (readpos[0] & 0x40) ? "Yes" : "No");
+
+ if (readpos[0] & 0x4) {
+ printk(KERN_INFO "ide-tape: Block location is unknown"
+ "to the tape\n");
+ clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
+ uptodate = 0;
+ } else {
+ debug_log(DBG_SENSE, "Block Location - %u\n",
+ be32_to_cpup((__be32 *)&readpos[4]));
+
+ tape->partition = readpos[1];
+ tape->first_frame = be32_to_cpup((__be32 *)&readpos[4]);
+ set_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
+ }
+ }
+
+ idetape_end_request(drive, uptodate, 0);
}
/*
@@ -727,195 +588,42 @@ static void idetape_postpone_request(ide_drive_t *drive)
ide_stall_queue(drive, tape->dsc_poll_freq);
}
-typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int);
-
-/*
- * This is the usual interrupt handler which will be called during a packet
- * command. We will transfer some of the data (as requested by the drive) and
- * will re-point interrupt handler to us. When data transfer is finished, we
- * will act according to the algorithm described before
- * idetape_issue_pc.
- */
-static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+static void ide_tape_handle_dsc(ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
- struct ide_atapi_pc *pc = tape->pc;
- xfer_func_t *xferfunc;
- idetape_io_buf *iobuf;
- unsigned int temp;
-#if SIMULATE_ERRORS
- static int error_sim_count;
-#endif
- u16 bcount;
- u8 stat, ireason;
-
- debug_log(DBG_PROCS, "Enter %s - interrupt handler\n", __func__);
-
- /* Clear the interrupt */
- stat = ide_read_status(drive);
-
- if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
- if (hwif->dma_ops->dma_end(drive) || (stat & ERR_STAT)) {
- /*
- * A DMA error is sometimes expected. For example,
- * if the tape is crossing a filemark during a
- * READ command, it will issue an irq and position
- * itself before the filemark, so that only a partial
- * data transfer will occur (which causes the DMA
- * error). In that case, we will later ask the tape
- * how much bytes of the original request were
- * actually transferred (we can't receive that
- * information from the DMA engine on most chipsets).
- */
-
- /*
- * On the contrary, a DMA error is never expected;
- * it usually indicates a hardware error or abort.
- * If the tape crosses a filemark during a READ
- * command, it will issue an irq and position itself
- * after the filemark (not before). Only a partial
- * data transfer will occur, but no DMA error.
- * (AS, 19 Apr 2001)
- */
- pc->flags |= PC_FLAG_DMA_ERROR;
- } else {
- pc->xferred = pc->req_xfer;
- idetape_update_buffers(pc);
- }
- debug_log(DBG_PROCS, "DMA finished\n");
- }
-
- /* No more interrupts */
- if ((stat & DRQ_STAT) == 0) {
- debug_log(DBG_SENSE, "Packet command completed, %d bytes"
- " transferred\n", pc->xferred);
-
- pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
- local_irq_enable();
-
-#if SIMULATE_ERRORS
- 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);
- stat |= ERR_STAT;
- }
-#endif
- if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
- stat &= ~ERR_STAT;
- if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
- /* Error detected */
- debug_log(DBG_ERR, "%s: I/O error\n", tape->name);
-
- if (pc->c[0] == REQUEST_SENSE) {
- printk(KERN_ERR "ide-tape: I/O error in request"
- " sense command\n");
- return ide_do_reset(drive);
- }
- debug_log(DBG_ERR, "[cmd %x]: check condition\n",
- pc->c[0]);
-
- /* Retry operation */
- return idetape_retry_pc(drive);
- }
- pc->error = 0;
- if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
- (stat & SEEK_STAT) == 0) {
- /* Media access command */
- tape->dsc_polling_start = jiffies;
- tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
- tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
- /* Allow ide.c to handle other requests */
- idetape_postpone_request(drive);
- return ide_stopped;
- }
- if (tape->failed_pc == pc)
- tape->failed_pc = NULL;
- /* Command finished - Call the callback function */
- return pc->idetape_callback(drive);
- }
-
- if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
- pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
- printk(KERN_ERR "ide-tape: The tape wants to issue more "
- "interrupts in DMA mode\n");
- printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
- ide_dma_off(drive);
- return ide_do_reset(drive);
- }
- /* Get the number of bytes to transfer on this interrupt. */
- bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
- hwif->INB(hwif->io_ports.lbam_addr);
-
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
-
- if (ireason & CD) {
- printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__);
- return ide_do_reset(drive);
- }
- if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
- /* Hopefully, we will never get here */
- printk(KERN_ERR "ide-tape: We wanted to %s, ",
- (ireason & IO) ? "Write" : "Read");
- printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n",
- (ireason & IO) ? "Read" : "Write");
- return ide_do_reset(drive);
- }
- if (!(pc->flags & PC_FLAG_WRITING)) {
- /* Reading - Check that we have enough space */
- temp = pc->xferred + bcount;
- if (temp > pc->req_xfer) {
- if (temp > pc->buf_size) {
- printk(KERN_ERR "ide-tape: The tape wants to "
- "send us more data than expected "
- "- discarding data\n");
- ide_pad_transfer(drive, 0, bcount);
- ide_set_handler(drive, &idetape_pc_intr,
- IDETAPE_WAIT_CMD, NULL);
- return ide_started;
- }
- debug_log(DBG_SENSE, "The tape wants to send us more "
- "data than expected - allowing transfer\n");
- }
- iobuf = &idetape_input_buffers;
- xferfunc = hwif->input_data;
- } else {
- iobuf = &idetape_output_buffers;
- xferfunc = hwif->output_data;
- }
+ /* Media access command */
+ tape->dsc_polling_start = jiffies;
+ tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
+ tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
+ /* Allow ide.c to handle other requests */
+ idetape_postpone_request(drive);
+}
- if (pc->bh)
- iobuf(drive, pc, bcount);
+static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned int bcount, int write)
+{
+ if (write)
+ idetape_output_buffers(drive, pc, bcount);
else
- xferfunc(drive, NULL, pc->cur_pos, bcount);
+ idetape_input_buffers(drive, pc, bcount);
- /* Update the current position */
- pc->xferred += bcount;
- pc->cur_pos += bcount;
-
- debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n",
- pc->c[0], bcount);
-
- /* And set the interrupt handler again */
- ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
- return ide_started;
+ return bcount;
}
/*
* Packet Command Interface
*
- * The current Packet Command is available in tape->pc, and will not change
+ * The current Packet Command is available in drive->pc, and will not change
* until we finish handling it. Each packet command is associated with a
* callback function that will be called when the command is finished.
*
* The handling will be done in three stages:
*
* 1. idetape_issue_pc will send the packet command to the drive, and will set
- * the interrupt handler to idetape_pc_intr.
+ * the interrupt handler to ide_pc_intr.
*
- * 2. On each interrupt, idetape_pc_intr will be called. This step will be
+ * 2. On each interrupt, ide_pc_intr will be called. This step will be
* repeated until the device signals us that no more interrupts will be issued.
*
* 3. ATAPI Tape media access commands have immediate status with a delayed
@@ -939,60 +647,13 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
* again, the callback function will be called and then we will handle the next
* request.
*/
-static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- idetape_tape_t *tape = drive->driver_data;
- struct ide_atapi_pc *pc = tape->pc;
- 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 = hwif->INB(hwif->io_ports.nsect_addr);
- 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 = hwif->INB(hwif->io_ports.nsect_addr);
- if (retries == 0) {
- printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
- "issuing a packet command, ignoring\n");
- ireason |= CD;
- ireason &= ~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);
- }
- /* Set the interrupt routine */
- ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
-#ifdef CONFIG_BLK_DEV_IDEDMA
- /* Begin DMA, if necessary */
- if (pc->flags & PC_FLAG_DMA_IN_PROGRESS)
- hwif->dma_ops->dma_start(drive);
-#endif
- /* Send the actual packet */
- hwif->output_data(drive, NULL, pc->c, 12);
-
- return ide_started;
-}
static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
- ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
- int dma_ok = 0;
- u16 bcount;
- if (tape->pc->c[0] == REQUEST_SENSE &&
+ if (drive->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");
@@ -1000,8 +661,9 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
tape->failed_pc = pc;
+
/* Set the current packet command */
- tape->pc = pc;
+ drive->pc = pc;
if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
(pc->flags & PC_FLAG_ABORT)) {
@@ -1025,56 +687,20 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
pc->error = IDETAPE_ERROR_GENERAL;
}
tape->failed_pc = NULL;
- return pc->idetape_callback(drive);
+ drive->pc_callback(drive, 0);
+ return ide_stopped;
}
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
pc->retries++;
- /* We haven't transferred any data yet */
- pc->xferred = 0;
- pc->cur_pos = pc->buf;
- /* Request to transfer the entire buffer at once */
- bcount = pc->req_xfer;
-
- if (pc->flags & PC_FLAG_DMA_ERROR) {
- pc->flags &= ~PC_FLAG_DMA_ERROR;
- printk(KERN_WARNING "ide-tape: DMA disabled, "
- "reverting to PIO\n");
- ide_dma_off(drive);
- }
- if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
- dma_ok = !hwif->dma_ops->dma_setup(drive);
-
- ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
- IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
-
- if (dma_ok)
- /* Will begin DMA later */
- pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
- if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags)) {
- ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
- IDETAPE_WAIT_CMD, NULL);
- return ide_started;
- } else {
- ide_execute_pkt_cmd(drive);
- return idetape_transfer_pc(drive);
- }
-}
-
-static ide_startstop_t idetape_pc_callback(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
- idetape_end_request(drive, tape->pc->error ? 0 : 1, 0);
- return ide_stopped;
+ return ide_issue_pc(drive, WAIT_TAPE_CMD, NULL);
}
/* A mode sense command is used to "sense" tape parameters. */
static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = MODE_SENSE;
if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
/* DBD = 1 - Don't return block descriptors */
@@ -1096,111 +722,79 @@ static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
pc->req_xfer = 24;
else
pc->req_xfer = 50;
- pc->idetape_callback = &idetape_pc_callback;
}
static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
- struct ide_atapi_pc *pc = tape->pc;
+ struct ide_atapi_pc *pc = drive->pc;
u8 stat;
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
- if (stat & SEEK_STAT) {
- if (stat & ERR_STAT) {
+ if (stat & ATA_DSC) {
+ if (stat & ATA_ERR) {
/* Error detected */
if (pc->c[0] != TEST_UNIT_READY)
printk(KERN_ERR "ide-tape: %s: I/O error, ",
tape->name);
/* Retry operation */
- return idetape_retry_pc(drive);
+ ide_retry_pc(drive, tape->disk);
+ return ide_stopped;
}
pc->error = 0;
- if (tape->failed_pc == pc)
- tape->failed_pc = NULL;
} else {
pc->error = IDETAPE_ERROR_GENERAL;
tape->failed_pc = NULL;
}
- return pc->idetape_callback(drive);
-}
-
-static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
- struct request *rq = HWGROUP(drive)->rq;
- int blocks = tape->pc->xferred / tape->blk_size;
-
- tape->avg_size += blocks * tape->blk_size;
-
- if (time_after_eq(jiffies, tape->avg_time + HZ)) {
- tape->avg_speed = tape->avg_size * HZ /
- (jiffies - tape->avg_time) / 1024;
- tape->avg_size = 0;
- tape->avg_time = jiffies;
- }
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
- tape->first_frame += blocks;
- rq->current_nr_sectors -= blocks;
-
- if (!tape->pc->error)
- idetape_end_request(drive, 1, 0);
- else
- idetape_end_request(drive, tape->pc->error, 0);
+ drive->pc_callback(drive, 0);
return ide_stopped;
}
-static void idetape_create_read_cmd(idetape_tape_t *tape,
- struct ide_atapi_pc *pc,
- unsigned int length, struct idetape_bh *bh)
+static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
+ struct ide_atapi_pc *pc, struct request *rq,
+ u8 opcode)
{
- idetape_init_pc(pc);
- pc->c[0] = READ_6;
- put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
- pc->c[1] = 1;
- pc->idetape_callback = &idetape_rw_callback;
- pc->bh = bh;
- atomic_set(&bh->b_count, 0);
- pc->buf = NULL;
- pc->buf_size = length * tape->blk_size;
- pc->req_xfer = pc->buf_size;
- if (pc->req_xfer == tape->buffer_size)
- pc->flags |= PC_FLAG_DMA_RECOMMENDED;
-}
+ struct idetape_bh *bh = (struct idetape_bh *)rq->special;
+ unsigned int length = rq->current_nr_sectors;
-static void idetape_create_write_cmd(idetape_tape_t *tape,
- struct ide_atapi_pc *pc,
- unsigned int length, struct idetape_bh *bh)
-{
- idetape_init_pc(pc);
- pc->c[0] = WRITE_6;
+ ide_init_pc(pc);
put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
- pc->idetape_callback = &idetape_rw_callback;
- pc->flags |= PC_FLAG_WRITING;
pc->bh = bh;
- pc->b_data = bh->b_data;
- pc->b_count = atomic_read(&bh->b_count);
pc->buf = NULL;
pc->buf_size = length * tape->blk_size;
pc->req_xfer = pc->buf_size;
if (pc->req_xfer == tape->buffer_size)
- pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ pc->flags |= PC_FLAG_DMA_OK;
+
+ if (opcode == READ_6) {
+ pc->c[0] = READ_6;
+ atomic_set(&bh->b_count, 0);
+ } else if (opcode == WRITE_6) {
+ pc->c[0] = WRITE_6;
+ pc->flags |= PC_FLAG_WRITING;
+ pc->b_data = bh->b_data;
+ pc->b_count = atomic_read(&bh->b_count);
+ }
+
+ memcpy(rq->cmd, pc->c, 12);
}
static ide_startstop_t idetape_do_request(ide_drive_t *drive,
struct request *rq, sector_t block)
{
+ ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc *pc = NULL;
struct request *postponed_rq = tape->postponed_rq;
u8 stat;
- debug_log(DBG_SENSE, "sector: %ld, nr_sectors: %ld,"
- " current_nr_sectors: %d\n",
- rq->sector, rq->nr_sectors, rq->current_nr_sectors);
+ debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu,"
+ " current_nr_sectors: %u\n",
+ (unsigned long long)rq->sector, rq->nr_sectors,
+ rq->current_nr_sectors);
if (!blk_special_request(rq)) {
/* We do not support buffer cache originated requests. */
@@ -1211,8 +805,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
}
/* Retry a failed packet command */
- if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE)
- return idetape_issue_pc(drive, tape->failed_pc);
+ if (tape->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
+ pc = tape->failed_pc;
+ goto out;
+ }
if (postponed_rq != NULL)
if (rq != postponed_rq) {
@@ -1228,18 +824,19 @@ 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.
*/
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
- if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
+ (rq->cmd[13] & REQ_IDETAPE_PC2) == 0)
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
- if (drive->post_reset == 1) {
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
- drive->post_reset = 0;
+ if (drive->dev_flags & IDE_DFLAG_POST_RESET) {
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
+ drive->dev_flags &= ~IDE_DFLAG_POST_RESET;
}
- if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) &&
- (stat & SEEK_STAT) == 0) {
+ if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
+ (stat & ATA_DSC) == 0) {
if (postponed_rq == NULL) {
tape->dsc_polling_start = jiffies;
tape->dsc_poll_freq = tape->best_dsc_rw_freq;
@@ -1247,7 +844,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
} else if (time_after(jiffies, tape->dsc_timeout)) {
printk(KERN_ERR "ide-tape: %s: DSC timeout\n",
tape->name);
- if (rq->cmd[0] & REQ_IDETAPE_PC2) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC2) {
idetape_media_access_finished(drive);
return ide_stopped;
} else {
@@ -1260,29 +857,28 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
idetape_postpone_request(drive);
return ide_stopped;
}
- if (rq->cmd[0] & REQ_IDETAPE_READ) {
- pc = idetape_next_pc_storage(drive);
- idetape_create_read_cmd(tape, pc, rq->current_nr_sectors,
- (struct idetape_bh *)rq->special);
+ if (rq->cmd[13] & REQ_IDETAPE_READ) {
+ pc = &tape->queued_pc;
+ ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
- pc = idetape_next_pc_storage(drive);
- idetape_create_write_cmd(tape, pc, rq->current_nr_sectors,
- (struct idetape_bh *)rq->special);
+ if (rq->cmd[13] & REQ_IDETAPE_WRITE) {
+ pc = &tape->queued_pc;
+ ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_PC1) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC1) {
pc = (struct ide_atapi_pc *) rq->buffer;
- rq->cmd[0] &= ~(REQ_IDETAPE_PC1);
- rq->cmd[0] |= REQ_IDETAPE_PC2;
+ rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
+ rq->cmd[13] |= REQ_IDETAPE_PC2;
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_PC2) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC2) {
idetape_media_access_finished(drive);
return ide_stopped;
}
BUG();
+
out:
return idetape_issue_pc(drive, pc);
}
@@ -1447,40 +1043,6 @@ static void idetape_init_merge_buffer(idetape_tape_t *tape)
}
}
-static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
- u8 *readpos = tape->pc->buf;
-
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
- if (!tape->pc->error) {
- debug_log(DBG_SENSE, "BOP - %s\n",
- (readpos[0] & 0x80) ? "Yes" : "No");
- debug_log(DBG_SENSE, "EOP - %s\n",
- (readpos[0] & 0x40) ? "Yes" : "No");
-
- if (readpos[0] & 0x4) {
- printk(KERN_INFO "ide-tape: Block location is unknown"
- "to the tape\n");
- clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
- idetape_end_request(drive, 0, 0);
- } else {
- debug_log(DBG_SENSE, "Block Location - %u\n",
- be32_to_cpu(*(u32 *)&readpos[4]));
-
- tape->partition = readpos[1];
- tape->first_frame =
- be32_to_cpu(*(u32 *)&readpos[4]);
- set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
- idetape_end_request(drive, 1, 0);
- }
- } else {
- idetape_end_request(drive, 0, 0);
- }
- return ide_stopped;
-}
-
/*
* Write a filemark if write_filemark=1. Flush the device buffers without
* writing a filemark otherwise.
@@ -1488,75 +1050,30 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc, int write_filemark)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = WRITE_FILEMARKS;
pc->c[4] = write_filemark;
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
- pc->idetape_callback = &idetape_pc_callback;
-}
-
-static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
-{
- idetape_init_pc(pc);
- pc->c[0] = TEST_UNIT_READY;
- pc->idetape_callback = &idetape_pc_callback;
-}
-
-/*
- * We add a special packet command request to the tail of the request queue, and
- * wait for it to be serviced. This is not to be called from within the request
- * handling part of the driver! We allocate here data on the stack and it is
- * valid until the request is finished. This is not the case for the bottom part
- * of the driver, where we are always leaving the functions to wait for an
- * interrupt or a timer event.
- *
- * From the bottom part of the driver, we should allocate safe memory using
- * idetape_next_pc_storage() and ide_tape_next_rq_storage(), and add the request
- * to the request list without waiting for it to be serviced! In that case, we
- * usually use idetape_queue_pc_head().
- */
-static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
- struct ide_tape_obj *tape = drive->driver_data;
- struct request rq;
-
- idetape_init_rq(&rq, REQ_IDETAPE_PC1);
- rq.buffer = (char *) pc;
- rq.rq_disk = tape->disk;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
-static void idetape_create_load_unload_cmd(ide_drive_t *drive,
- struct ide_atapi_pc *pc, int cmd)
-{
- idetape_init_pc(pc);
- pc->c[0] = START_STOP;
- pc->c[4] = cmd;
- pc->flags |= PC_FLAG_WAIT_FOR_DSC;
- pc->idetape_callback = &idetape_pc_callback;
}
static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
{
idetape_tape_t *tape = drive->driver_data;
- struct ide_atapi_pc pc;
+ struct gendisk *disk = tape->disk;
int load_attempted = 0;
/* Wait for the tape to become ready */
- set_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
timeout += jiffies;
while (time_before(jiffies, timeout)) {
- idetape_create_test_unit_ready_cmd(&pc);
- if (!idetape_queue_pc_tail(drive, &pc))
+ if (ide_do_test_unit_ready(drive, disk) == 0)
return 0;
if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
|| (tape->asc == 0x3A)) {
/* no media */
if (load_attempted)
return -ENOMEDIUM;
- idetape_create_load_unload_cmd(drive, &pc,
- IDETAPE_LU_LOAD_MASK);
- idetape_queue_pc_tail(drive, &pc);
+ ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK);
load_attempted = 1;
/* not about to be ready */
} else if (!(tape->sense_key == 2 && tape->asc == 4 &&
@@ -1569,11 +1086,12 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
static int idetape_flush_tape_buffers(ide_drive_t *drive)
{
+ struct ide_tape_obj *tape = drive->driver_data;
struct ide_atapi_pc pc;
int rc;
idetape_create_write_filemark_cmd(drive, &pc, 0);
- rc = idetape_queue_pc_tail(drive, &pc);
+ rc = ide_queue_pc_tail(drive, tape->disk, &pc);
if (rc)
return rc;
idetape_wait_ready(drive, 60 * 5 * HZ);
@@ -1582,10 +1100,9 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive)
static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = READ_POSITION;
pc->req_xfer = 20;
- pc->idetape_callback = &idetape_read_position_callback;
}
static int idetape_read_position(ide_drive_t *drive)
@@ -1597,7 +1114,7 @@ static int idetape_read_position(ide_drive_t *drive)
debug_log(DBG_PROCS, "Enter %s\n", __func__);
idetape_create_read_position_cmd(&pc);
- if (idetape_queue_pc_tail(drive, &pc))
+ if (ide_queue_pc_tail(drive, tape->disk, &pc))
return -1;
position = tape->first_frame;
return position;
@@ -1607,29 +1124,12 @@ static void idetape_create_locate_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc,
unsigned int block, u8 partition, int skip)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = POSITION_TO_ELEMENT;
pc->c[1] = 2;
put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
pc->c[8] = partition;
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
- pc->idetape_callback = &idetape_pc_callback;
-}
-
-static int idetape_create_prevent_cmd(ide_drive_t *drive,
- struct ide_atapi_pc *pc, int prevent)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- /* device supports locking according to capabilities page */
- if (!(tape->caps[6] & 0x01))
- return 0;
-
- idetape_init_pc(pc);
- pc->c[0] = ALLOW_MEDIUM_REMOVAL;
- pc->c[4] = prevent;
- pc->idetape_callback = &idetape_pc_callback;
- return 1;
}
static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
@@ -1639,7 +1139,7 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
if (tape->chrdev_dir != IDETAPE_DIR_READ)
return;
- clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
+ clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags);
tape->merge_bh_size = 0;
if (tape->merge_bh != NULL) {
ide_tape_kfree_buffer(tape);
@@ -1659,6 +1159,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
u8 partition, int skip)
{
idetape_tape_t *tape = drive->driver_data;
+ struct gendisk *disk = tape->disk;
int retval;
struct ide_atapi_pc pc;
@@ -1666,12 +1167,12 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
__ide_tape_discard_merge_buffer(drive);
idetape_wait_ready(drive, 60 * 5 * HZ);
idetape_create_locate_cmd(drive, &pc, block, partition, skip);
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_queue_pc_tail(drive, disk, &pc);
if (retval)
return (retval);
idetape_create_read_position_cmd(&pc);
- return (idetape_queue_pc_tail(drive, &pc));
+ return ide_queue_pc_tail(drive, disk, &pc);
}
static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
@@ -1700,63 +1201,66 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
struct idetape_bh *bh)
{
idetape_tape_t *tape = drive->driver_data;
- struct request rq;
+ struct request *rq;
+ int ret, errors;
debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
- idetape_init_rq(&rq, cmd);
- rq.rq_disk = tape->disk;
- rq.special = (void *)bh;
- rq.sector = tape->first_frame;
- rq.nr_sectors = blocks;
- rq.current_nr_sectors = blocks;
- (void) ide_do_drive_cmd(drive, &rq, ide_wait);
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd[13] = cmd;
+ rq->rq_disk = tape->disk;
+ rq->special = (void *)bh;
+ rq->sector = tape->first_frame;
+ rq->nr_sectors = blocks;
+ rq->current_nr_sectors = blocks;
+ blk_execute_rq(drive->queue, tape->disk, rq, 0);
+
+ errors = rq->errors;
+ ret = tape->blk_size * (blocks - rq->current_nr_sectors);
+ blk_put_request(rq);
if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
return 0;
if (tape->merge_bh)
idetape_init_merge_buffer(tape);
- if (rq.errors == IDETAPE_ERROR_GENERAL)
+ if (errors == IDETAPE_ERROR_GENERAL)
return -EIO;
- return (tape->blk_size * (blocks-rq.current_nr_sectors));
+ return ret;
}
static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = INQUIRY;
pc->c[4] = 254;
pc->req_xfer = 254;
- pc->idetape_callback = &idetape_pc_callback;
}
static void idetape_create_rewind_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = REZERO_UNIT;
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
- pc->idetape_callback = &idetape_pc_callback;
}
static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = ERASE;
pc->c[1] = 1;
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
- pc->idetape_callback = &idetape_pc_callback;
}
static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = SPACE;
put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
pc->c[1] = cmd;
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
- pc->idetape_callback = &idetape_pc_callback;
}
/* Queue up a character device originated write request. */
@@ -1851,7 +1355,7 @@ static int idetape_init_read(ide_drive_t *drive)
* No point in issuing this if DSC overlap isn't supported, some
* drives (Seagate STT3401A) will return an error.
*/
- if (drive->dsc_overlap) {
+ if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
bytes_read = idetape_queue_rw_tail(drive,
REQ_IDETAPE_READ, 0,
tape->merge_bh);
@@ -1875,7 +1379,7 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
/* If we are at a filemark, return a read length of 0 */
- if (test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
return 0;
idetape_init_read(drive);
@@ -1915,20 +1419,20 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
*/
static int idetape_rewind_tape(ide_drive_t *drive)
{
+ struct ide_tape_obj *tape = drive->driver_data;
+ struct gendisk *disk = tape->disk;
int retval;
struct ide_atapi_pc pc;
- idetape_tape_t *tape;
- tape = drive->driver_data;
debug_log(DBG_SENSE, "Enter %s\n", __func__);
idetape_create_rewind_cmd(drive, &pc);
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_queue_pc_tail(drive, disk, &pc);
if (retval)
return retval;
idetape_create_read_position_cmd(&pc);
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_queue_pc_tail(drive, disk, &pc);
if (retval)
return retval;
return 0;
@@ -1971,6 +1475,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
int mt_count)
{
idetape_tape_t *tape = drive->driver_data;
+ struct gendisk *disk = tape->disk;
struct ide_atapi_pc pc;
int retval, count = 0;
int sprev = !!(tape->caps[4] & 0x20);
@@ -1985,7 +1490,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
if (tape->chrdev_dir == IDETAPE_DIR_READ) {
tape->merge_bh_size = 0;
- if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
++count;
ide_tape_discard_merge_buffer(drive, 0);
}
@@ -1995,7 +1500,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
case MTBSF:
idetape_create_space_cmd(&pc, mt_count - count,
IDETAPE_SPACE_OVER_FILEMARK);
- return idetape_queue_pc_tail(drive, &pc);
+ return ide_queue_pc_tail(drive, disk, &pc);
case MTFSFM:
case MTBSFM:
if (!sprev)
@@ -2031,7 +1536,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct ide_tape_obj *tape = ide_tape_f(file);
+ struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
ssize_t bytes_read, temp, actually_read = 0, rc;
ssize_t ret = 0;
@@ -2040,7 +1545,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
if (tape->chrdev_dir != IDETAPE_DIR_READ) {
- if (test_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags))
+ if (test_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags))
if (count > tape->blk_size &&
(count % tape->blk_size) == 0)
tape->user_bs_factor = count / tape->blk_size;
@@ -2080,7 +1585,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
tape->merge_bh_size = bytes_read-temp;
}
finish:
- if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) {
+ if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
idetape_space_over_filemarks(drive, MTFSF, 1);
@@ -2093,7 +1598,7 @@ finish:
static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct ide_tape_obj *tape = ide_tape_f(file);
+ struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
ssize_t actually_written = 0;
ssize_t ret = 0;
@@ -2126,7 +1631,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
* point in issuing this if DSC overlap isn't supported, some
* drives (Seagate STT3401A) will return an error.
*/
- if (drive->dsc_overlap) {
+ if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
ssize_t retval = idetape_queue_rw_tail(drive,
REQ_IDETAPE_WRITE, 0,
tape->merge_bh);
@@ -2184,11 +1689,12 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
static int idetape_write_filemark(ide_drive_t *drive)
{
+ struct ide_tape_obj *tape = drive->driver_data;
struct ide_atapi_pc pc;
/* Write a filemark */
idetape_create_write_filemark_cmd(drive, &pc, 1);
- if (idetape_queue_pc_tail(drive, &pc)) {
+ if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
printk(KERN_ERR "ide-tape: Couldn't write a filemark\n");
return -EIO;
}
@@ -2211,6 +1717,7 @@ static int idetape_write_filemark(ide_drive_t *drive)
static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
{
idetape_tape_t *tape = drive->driver_data;
+ struct gendisk *disk = tape->disk;
struct ide_atapi_pc pc;
int i, retval;
@@ -2247,9 +1754,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
return 0;
case MTLOAD:
ide_tape_discard_merge_buffer(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
- IDETAPE_LU_LOAD_MASK);
- return idetape_queue_pc_tail(drive, &pc);
+ return ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK);
case MTUNLOAD:
case MTOFFL:
/*
@@ -2257,41 +1762,37 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
* attempting to eject.
*/
if (tape->door_locked) {
- if (idetape_create_prevent_cmd(drive, &pc, 0))
- if (!idetape_queue_pc_tail(drive, &pc))
- tape->door_locked = DOOR_UNLOCKED;
+ if (!ide_set_media_lock(drive, disk, 0))
+ tape->door_locked = DOOR_UNLOCKED;
}
ide_tape_discard_merge_buffer(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
- !IDETAPE_LU_LOAD_MASK);
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_do_start_stop(drive, disk, !IDETAPE_LU_LOAD_MASK);
if (!retval)
- clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
return retval;
case MTNOP:
ide_tape_discard_merge_buffer(drive, 0);
return idetape_flush_tape_buffers(drive);
case MTRETEN:
ide_tape_discard_merge_buffer(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
+ return ide_do_start_stop(drive, disk,
IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
- return idetape_queue_pc_tail(drive, &pc);
case MTEOM:
idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
- return idetape_queue_pc_tail(drive, &pc);
+ return ide_queue_pc_tail(drive, disk, &pc);
case MTERASE:
(void)idetape_rewind_tape(drive);
idetape_create_erase_cmd(&pc);
- return idetape_queue_pc_tail(drive, &pc);
+ return ide_queue_pc_tail(drive, disk, &pc);
case MTSETBLK:
if (mt_count) {
if (mt_count < tape->blk_size ||
mt_count % tape->blk_size)
return -EIO;
tape->user_bs_factor = mt_count / tape->blk_size;
- clear_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ clear_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
} else
- set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ set_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
return 0;
case MTSEEK:
ide_tape_discard_merge_buffer(drive, 0);
@@ -2303,17 +1804,13 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
case MTFSR:
case MTBSR:
case MTLOCK:
- if (!idetape_create_prevent_cmd(drive, &pc, 1))
- return 0;
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_set_media_lock(drive, disk, 1);
if (retval)
return retval;
tape->door_locked = DOOR_EXPLICITLY_LOCKED;
return 0;
case MTUNLOCK:
- if (!idetape_create_prevent_cmd(drive, &pc, 0))
- return 0;
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_set_media_lock(drive, disk, 0);
if (retval)
return retval;
tape->door_locked = DOOR_UNLOCKED;
@@ -2333,7 +1830,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
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);
+ struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
struct mtop mtop;
struct mtget mtget;
@@ -2395,7 +1892,7 @@ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
struct ide_atapi_pc pc;
idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
- if (idetape_queue_pc_tail(drive, &pc)) {
+ if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
if (tape->blk_size == 0) {
printk(KERN_WARNING "ide-tape: Cannot deal with zero "
@@ -2415,15 +1912,17 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
unsigned int minor = iminor(inode), i = minor & ~0xc0;
ide_drive_t *drive;
idetape_tape_t *tape;
- struct ide_atapi_pc pc;
int retval;
if (i >= MAX_HWIFS * MAX_DRIVES)
return -ENXIO;
+ lock_kernel();
tape = ide_tape_chrdev_get(i);
- if (!tape)
+ if (!tape) {
+ unlock_kernel();
return -ENXIO;
+ }
debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
@@ -2438,20 +1937,20 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
filp->private_data = tape;
- if (test_and_set_bit(IDETAPE_FLAG_BUSY, &tape->flags)) {
+ if (test_and_set_bit(IDE_AFLAG_BUSY, &drive->atapi_flags)) {
retval = -EBUSY;
goto out_put_tape;
}
retval = idetape_wait_ready(drive, 60 * HZ);
if (retval) {
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
goto out_put_tape;
}
idetape_read_position(drive);
- if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags))
+ if (!test_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags))
(void)idetape_rewind_tape(drive);
/* Read block size and write protect status from drive. */
@@ -2467,7 +1966,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
if (tape->write_prot) {
if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
(filp->f_flags & O_ACCMODE) == O_RDWR) {
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
retval = -EROFS;
goto out_put_tape;
}
@@ -2475,17 +1974,17 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
/* Lock the tape drive door so user can't eject. */
if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
- if (idetape_create_prevent_cmd(drive, &pc, 1)) {
- if (!idetape_queue_pc_tail(drive, &pc)) {
- if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
- tape->door_locked = DOOR_LOCKED;
- }
+ if (!ide_set_media_lock(drive, tape->disk, 1)) {
+ if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
+ tape->door_locked = DOOR_LOCKED;
}
}
+ unlock_kernel();
return 0;
out_put_tape:
ide_tape_put(tape);
+ unlock_kernel();
return retval;
}
@@ -2508,9 +2007,8 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
static int idetape_chrdev_release(struct inode *inode, struct file *filp)
{
- struct ide_tape_obj *tape = ide_tape_f(filp);
+ struct ide_tape_obj *tape = filp->private_data;
ide_drive_t *drive = tape->drive;
- struct ide_atapi_pc pc;
unsigned int minor = iminor(inode);
lock_kernel();
@@ -2525,69 +2023,28 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
ide_tape_discard_merge_buffer(drive, 1);
}
- if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags))
+ if (minor < 128 && test_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags))
(void) idetape_rewind_tape(drive);
if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
if (tape->door_locked == DOOR_LOCKED) {
- if (idetape_create_prevent_cmd(drive, &pc, 0)) {
- if (!idetape_queue_pc_tail(drive, &pc))
- tape->door_locked = DOOR_UNLOCKED;
- }
+ if (!ide_set_media_lock(drive, tape->disk, 0))
+ tape->door_locked = DOOR_UNLOCKED;
}
}
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
ide_tape_put(tape);
unlock_kernel();
return 0;
}
-/*
- * check the contents of the ATAPI IDENTIFY command results. We return:
- *
- * 1 - If the tape can be supported by us, based on the information we have so
- * far.
- *
- * 0 - If this tape driver is not currently supported by us.
- */
-static int idetape_identify_device(ide_drive_t *drive)
-{
- u8 gcw[2], protocol, device_type, removable, packet_size;
-
- if (drive->id_read == 0)
- return 1;
-
- *((unsigned short *) &gcw) = drive->id->config;
-
- protocol = (gcw[1] & 0xC0) >> 6;
- device_type = gcw[1] & 0x1F;
- removable = !!(gcw[0] & 0x80);
- packet_size = gcw[0] & 0x3;
-
- /* Check that we can support this device */
- if (protocol != 2)
- printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n",
- protocol);
- else if (device_type != 1)
- printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set "
- "to tape\n", device_type);
- else if (!removable)
- printk(KERN_ERR "ide-tape: The removable flag is not set\n");
- else if (packet_size != 0) {
- printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12"
- " bytes\n", packet_size);
- } else
- return 1;
- return 0;
-}
-
static void idetape_get_inquiry_results(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc pc;
- char fw_rev[6], vendor_id[10], product_id[18];
+ char fw_rev[4], vendor_id[8], product_id[16];
idetape_create_inquiry_cmd(&pc);
- if (idetape_queue_pc_tail(drive, &pc)) {
+ if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
tape->name);
return;
@@ -2596,11 +2053,11 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
memcpy(product_id, &pc.buf[16], 16);
memcpy(fw_rev, &pc.buf[32], 4);
- ide_fixstring(vendor_id, 10, 0);
- ide_fixstring(product_id, 18, 0);
- ide_fixstring(fw_rev, 6, 0);
+ ide_fixstring(vendor_id, 8, 0);
+ ide_fixstring(product_id, 16, 0);
+ ide_fixstring(fw_rev, 4, 0);
- printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n",
+ printk(KERN_INFO "ide-tape: %s <-> %s: %.8s %.16s rev %.4s\n",
drive->name, tape->name, vendor_id, product_id, fw_rev);
}
@@ -2616,7 +2073,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
u8 speed, max_speed;
idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
- if (idetape_queue_pc_tail(drive, &pc)) {
+ if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
" some default values\n");
tape->blk_size = 512;
@@ -2628,26 +2085,31 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
caps = pc.buf + 4 + pc.buf[3];
/* convert to host order and save for later use */
- speed = be16_to_cpu(*(u16 *)&caps[14]);
- max_speed = be16_to_cpu(*(u16 *)&caps[8]);
+ speed = be16_to_cpup((__be16 *)&caps[14]);
+ max_speed = be16_to_cpup((__be16 *)&caps[8]);
- 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]);
+ *(u16 *)&caps[8] = max_speed;
+ *(u16 *)&caps[12] = be16_to_cpup((__be16 *)&caps[12]);
+ *(u16 *)&caps[14] = speed;
+ *(u16 *)&caps[16] = be16_to_cpup((__be16 *)&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]);
+ *(u16 *)&caps[14] = 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]);
+ *(u16 *)&caps[8] = 650;
}
memcpy(&tape->caps, caps, 20);
+
+ /* device lacks locking support according to capabilities page */
+ if ((caps[6] & 1) == 0)
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
+
if (caps[7] & 0x02)
tape->blk_size = 512;
else if (caps[7] & 0x04)
@@ -2655,28 +2117,56 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
}
#ifdef CONFIG_IDE_PROC_FS
-static void idetape_add_settings(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
- 1, 2, (u16 *)&tape->caps[16], NULL);
- ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
- 1, 1, (u16 *)&tape->caps[14], NULL);
- ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff,
- 1, 1024, &tape->buffer_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_freq,
- NULL);
- ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1,
- 1, &drive->dsc_overlap, NULL);
- ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff,
- 1, 1, &tape->avg_speed, NULL);
- ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1,
- 1, &tape->debug_mask, NULL);
-}
-#else
-static inline void idetape_add_settings(ide_drive_t *drive) { ; }
+#define ide_tape_devset_get(name, field) \
+static int get_##name(ide_drive_t *drive) \
+{ \
+ idetape_tape_t *tape = drive->driver_data; \
+ return tape->field; \
+}
+
+#define ide_tape_devset_set(name, field) \
+static int set_##name(ide_drive_t *drive, int arg) \
+{ \
+ idetape_tape_t *tape = drive->driver_data; \
+ tape->field = arg; \
+ return 0; \
+}
+
+#define ide_tape_devset_rw_field(_name, _field) \
+ide_tape_devset_get(_name, _field) \
+ide_tape_devset_set(_name, _field) \
+IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
+
+#define ide_tape_devset_r_field(_name, _field) \
+ide_tape_devset_get(_name, _field) \
+IDE_DEVSET(_name, 0, get_##_name, NULL)
+
+static int mulf_tdsc(ide_drive_t *drive) { return 1000; }
+static int divf_tdsc(ide_drive_t *drive) { return HZ; }
+static int divf_buffer(ide_drive_t *drive) { return 2; }
+static int divf_buffer_size(ide_drive_t *drive) { return 1024; }
+
+ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
+
+ide_tape_devset_rw_field(debug_mask, debug_mask);
+ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq);
+
+ide_tape_devset_r_field(avg_speed, avg_speed);
+ide_tape_devset_r_field(speed, caps[14]);
+ide_tape_devset_r_field(buffer, caps[16]);
+ide_tape_devset_r_field(buffer_size, buffer_size);
+
+static const struct ide_proc_devset idetape_settings[] = {
+ __IDE_PROC_DEVSET(avg_speed, 0, 0xffff, NULL, NULL),
+ __IDE_PROC_DEVSET(buffer, 0, 0xffff, NULL, divf_buffer),
+ __IDE_PROC_DEVSET(buffer_size, 0, 0xffff, NULL, divf_buffer_size),
+ __IDE_PROC_DEVSET(debug_mask, 0, 0xffff, NULL, NULL),
+ __IDE_PROC_DEVSET(dsc_overlap, 0, 1, NULL, NULL),
+ __IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL),
+ __IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
+ mulf_tdsc, divf_tdsc),
+ { 0 },
+};
#endif
/*
@@ -2695,30 +2185,31 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
unsigned long t;
int speed;
int buffer_size;
- u8 gcw[2];
u16 *ctl = (u16 *)&tape->caps[12];
+ drive->pc_callback = ide_tape_callback;
+ drive->pc_update_buffers = idetape_update_buffers;
+ drive->pc_io_buffers = ide_tape_io_buffers;
+
spin_lock_init(&tape->lock);
- drive->dsc_overlap = 1;
+
+ drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+
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;
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
}
+
/* Seagate Travan drives do not support DSC overlap. */
- if (strstr(drive->id->model, "Seagate STT3401"))
- drive->dsc_overlap = 0;
+ if (strstr((char *)&drive->id[ATA_ID_PROD], "Seagate STT3401"))
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
+
tape->minor = minor;
tape->name[0] = 'h';
tape->name[1] = 't';
tape->name[2] = '0' + minor;
tape->chrdev_dir = IDETAPE_DIR_NONE;
- tape->pc = tape->pc_stack;
- *((unsigned short *) &gcw) = drive->id->config;
-
- /* Command packet DRQ type */
- if (((gcw[0] & 0x60) >> 5) == 1)
- set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags);
idetape_get_inquiry_results(drive);
idetape_get_mode_sense_results(drive);
@@ -2746,18 +2237,17 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
* Ensure that the number we got makes sense; limit it within
* IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
*/
- tape->best_dsc_rw_freq = max_t(unsigned long,
- min_t(unsigned long, t, IDETAPE_DSC_RW_MAX),
- IDETAPE_DSC_RW_MIN);
+ tape->best_dsc_rw_freq = clamp_t(unsigned long, t, IDETAPE_DSC_RW_MIN,
+ IDETAPE_DSC_RW_MAX);
printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
"%lums tDSC%s\n",
drive->name, tape->name, *(u16 *)&tape->caps[14],
(*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
tape->buffer_size / 1024,
tape->best_dsc_rw_freq * 1000 / HZ,
- drive->using_dma ? ", DMA":"");
+ (drive->dev_flags & IDE_DFLAG_USING_DMA) ? ", DMA" : "");
- idetape_add_settings(drive);
+ ide_proc_register_driver(drive, tape->driver);
}
static void ide_tape_remove(ide_drive_t *drive)
@@ -2773,13 +2263,13 @@ static void ide_tape_remove(ide_drive_t *drive)
static void ide_tape_release(struct kref *kref)
{
- struct ide_tape_obj *tape = to_ide_tape(kref);
+ struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj);
ide_drive_t *drive = tape->drive;
struct gendisk *g = tape->disk;
BUG_ON(tape->merge_bh_size);
- drive->dsc_overlap = 0;
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
drive->driver_data = NULL;
device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
device_destroy(idetape_sysfs_class,
@@ -2821,14 +2311,12 @@ static ide_driver_t idetape_driver = {
.probe = ide_tape_probe,
.remove = ide_tape_remove,
.version = IDETAPE_VERSION,
- .media = ide_tape,
- .supports_dsc_overlap = 1,
.do_request = idetape_do_request,
.end_request = idetape_end_request,
.error = __ide_error,
- .abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
.proc = idetape_proc,
+ .settings = idetape_settings,
#endif
};
@@ -2857,7 +2345,7 @@ static int idetape_open(struct inode *inode, struct file *filp)
static int idetape_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_tape_obj *tape = ide_tape_g(disk);
+ struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
ide_tape_put(tape);
@@ -2868,7 +2356,7 @@ static int idetape_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- struct ide_tape_obj *tape = ide_tape_g(bdev->bd_disk);
+ struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj);
ide_drive_t *drive = tape->drive;
int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
if (err == -EINVAL)
@@ -2891,20 +2379,16 @@ static int ide_tape_probe(ide_drive_t *drive)
if (!strstr("ide-tape", drive->driver_req))
goto failed;
- if (!drive->present)
- goto failed;
+
if (drive->media != ide_tape)
goto failed;
- if (!idetape_identify_device(drive)) {
+
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) &&
+ ide_check_atapi_device(drive, DRV_NAME) == 0) {
printk(KERN_ERR "ide-tape: %s: not supported by this version of"
" the driver\n", drive->name);
goto failed;
}
- if (drive->scsi) {
- printk(KERN_INFO "ide-tape: passing drive %s to ide-scsi"
- " emulation.\n", drive->name);
- goto failed;
- }
tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL);
if (tape == NULL) {
printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct\n",
@@ -2918,8 +2402,6 @@ static int ide_tape_probe(ide_drive_t *drive)
ide_init_disk(g, drive);
- ide_proc_register_driver(drive, &idetape_driver);
-
kref_init(&tape->kref);
tape->drive = drive;
@@ -2938,10 +2420,12 @@ static int ide_tape_probe(ide_drive_t *drive)
idetape_setup(drive, tape, minor);
- 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);
+ device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor), NULL,
+ "%s", tape->name);
+ device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+ "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 ab545ffa154..bf4fb9d8d17 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -8,28 +8,18 @@
* The big the bad and the ugly.
*/
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
-#include <linux/major.h>
#include <linux/errno.h>
-#include <linux/genhd.h>
-#include <linux/blkpg.h>
#include <linux/slab.h>
-#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/bitops.h>
#include <linux/scatterlist.h>
-#include <asm/byteorder.h>
-#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -54,37 +44,15 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
memset(&args, 0, sizeof(ide_task_t));
args.tf.nsect = 0x01;
if (drive->media == ide_disk)
- args.tf.command = WIN_IDENTIFY;
+ args.tf.command = ATA_CMD_ID_ATA;
else
- args.tf.command = WIN_PIDENTIFY;
+ args.tf.command = ATA_CMD_ID_ATAPI;
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
args.data_phase = TASKFILE_IN;
return ide_raw_taskfile(drive, &args, buf, 1);
}
-static int inline task_dma_ok(ide_task_t *task)
-{
- if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED))
- return 1;
-
- switch (task->tf.command) {
- case WIN_WRITEDMA_ONCE:
- case WIN_WRITEDMA:
- case WIN_WRITEDMA_EXT:
- case WIN_READDMA_ONCE:
- case WIN_READDMA:
- case WIN_READDMA_EXT:
- case WIN_IDENTIFY_DMA:
- return 1;
- }
-
- 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 *);
@@ -93,6 +61,7 @@ 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;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
const struct ide_dma_ops *dma_ops = hwif->dma_ops;
if (task->data_phase == TASKFILE_MULTI_IN ||
@@ -107,15 +76,19 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
if (task->tf_flags & IDE_TFLAG_FLAGGED)
task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
+ memcpy(&hwif->task, task, sizeof(*task));
+
if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
ide_tf_dump(drive->name, tf);
- hwif->tf_load(drive, task);
+ tp_ops->set_irq(hwif, 1);
+ SELECT_MASK(drive, 0);
+ tp_ops->tf_load(drive, task);
}
switch (task->data_phase) {
case TASKFILE_MULTI_OUT:
case TASKFILE_OUT:
- hwif->OUTBSYNC(drive, tf->command, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, tf->command);
ndelay(400); /* FIXME */
return pre_task_out_intr(drive, task->rq);
case TASKFILE_MULTI_IN:
@@ -125,19 +98,11 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
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 ||
+ if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 ||
dma_ops->dma_setup(drive))
return ide_stopped;
dma_ops->dma_exec_cmd(drive, tf->command);
@@ -148,79 +113,63 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
EXPORT_SYMBOL_GPL(do_rw_taskfile);
/*
- * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
- */
-static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
-{
- u8 stat = ide_read_status(drive);
-
- if (OK_STAT(stat, READY_STAT, BAD_STAT))
- drive->mult_count = drive->mult_req;
- else {
- drive->mult_req = drive->mult_count = 0;
- drive->special.b.recalibrate = 1;
- (void) ide_dump_status(drive, "set_multmode", stat);
- }
- return ide_stopped;
-}
-
-/*
- * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
- */
-static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
-{
- int retries = 5;
- u8 stat;
-
- while (((stat = ide_read_status(drive)) & BUSY_STAT) && retries--)
- udelay(10);
-
- if (OK_STAT(stat, READY_STAT, BAD_STAT))
- return ide_stopped;
-
- if (stat & (ERR_STAT|DRQ_STAT))
- return ide_error(drive, "set_geometry_intr", stat);
-
- BUG_ON(HWGROUP(drive)->handler != NULL);
- ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
- return ide_started;
-}
-
-/*
- * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
- */
-static ide_startstop_t recal_intr(ide_drive_t *drive)
-{
- u8 stat = ide_read_status(drive);
-
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
- return ide_error(drive, "recal_intr", stat);
- return ide_stopped;
-}
-
-/*
* Handler for commands without a data phase
*/
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{
- ide_task_t *args = HWGROUP(drive)->rq->special;
+ ide_hwif_t *hwif = drive->hwif;
+ ide_task_t *task = &hwif->task;
+ struct ide_taskfile *tf = &task->tf;
+ int custom = (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
+ int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1;
u8 stat;
local_irq_enable_in_hardirq();
- stat = ide_read_status(drive);
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+ while (1) {
+ stat = hwif->tp_ops->read_status(hwif);
+ if ((stat & ATA_BUSY) == 0 || retries-- == 0)
+ break;
+ udelay(10);
+ };
+
+ if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
+ if (custom && tf->command == ATA_CMD_SET_MULTI) {
+ drive->mult_req = drive->mult_count = 0;
+ drive->special.b.recalibrate = 1;
+ (void)ide_dump_status(drive, __func__, stat);
+ return ide_stopped;
+ } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
+ if ((stat & (ATA_ERR | ATA_DRQ)) == 0) {
+ ide_set_handler(drive, &task_no_data_intr,
+ WAIT_WORSTCASE, NULL);
+ return ide_started;
+ }
+ }
return ide_error(drive, "task_no_data_intr", stat);
/* calls ide_end_drive_cmd */
+ }
- if (args)
+ if (!custom)
+ ide_end_drive_cmd(drive, stat, ide_read_error(drive));
+ else if (tf->command == ATA_CMD_IDLEIMMEDIATE) {
+ hwif->tp_ops->tf_read(drive, task);
+ if (tf->lbal != 0xc4) {
+ printk(KERN_ERR "%s: head unload failed!\n",
+ drive->name);
+ ide_tf_dump(drive->name, tf);
+ } else
+ drive->dev_flags |= IDE_DFLAG_PARKED;
ide_end_drive_cmd(drive, stat, ide_read_error(drive));
+ } else if (tf->command == ATA_CMD_SET_MULTI)
+ drive->mult_count = drive->mult_req;
return ide_stopped;
}
static u8 wait_drive_not_busy(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
int retries;
u8 stat;
@@ -229,15 +178,15 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
* take up to 6 ms on some ATAPI devices, so we will wait max 10 ms.
*/
for (retries = 0; retries < 1000; retries++) {
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
- if (stat & BUSY_STAT)
+ if (stat & ATA_BUSY)
udelay(10);
else
break;
}
- if (stat & BUSY_STAT)
+ if (stat & ATA_BUSY)
printk(KERN_ERR "%s: drive still BUSY!\n", drive->name);
return stat;
@@ -284,9 +233,9 @@ static void ide_pio_sector(ide_drive_t *drive, struct request *rq,
/* do the actual data transfer */
if (write)
- hwif->output_data(drive, rq, buf, SECTOR_SIZE);
+ hwif->tp_ops->output_data(drive, rq, buf, SECTOR_SIZE);
else
- hwif->input_data(drive, rq, buf, SECTOR_SIZE);
+ hwif->tp_ops->input_data(drive, rq, buf, SECTOR_SIZE);
kunmap_atomic(buf, KM_BIO_SRC_IRQ);
#ifdef CONFIG_HIGHMEM
@@ -396,7 +345,7 @@ void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat)
{
/* Command all done? */
- if (OK_STAT(stat, READY_STAT, BUSY_STAT)) {
+ if (OK_STAT(stat, ATA_DRDY, ATA_BUSY)) {
task_end_request(drive, rq, stat);
return ide_stopped;
}
@@ -412,15 +361,15 @@ static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq
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 = ide_read_status(drive);
+ struct request *rq = hwif->hwgroup->rq;
+ u8 stat = hwif->tp_ops->read_status(hwif);
/* Error? */
- if (stat & ERR_STAT)
+ if (stat & ATA_ERR)
return task_error(drive, rq, __func__, stat);
/* Didn't want any data? Odd. */
- if (!(stat & DRQ_STAT))
+ if ((stat & ATA_DRQ) == 0)
return task_in_unexpected(drive, rq, stat);
ide_pio_datablock(drive, rq, 0);
@@ -447,13 +396,13 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
- u8 stat = ide_read_status(drive);
+ u8 stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
return task_error(drive, rq, __func__, stat);
/* Deal with unexpected ATA data phase. */
- if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft)
+ if (((stat & ATA_DRQ) == 0) ^ !hwif->nleft)
return task_error(drive, rq, __func__, stat);
if (!hwif->nleft) {
@@ -472,16 +421,15 @@ 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, DRQ_STAT,
+ if (ide_wait_stat(&startstop, drive, ATA_DRQ,
drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
- drive->name,
- drive->hwif->data_phase ? "MULT" : "",
- drive->addressing ? "_EXT" : "");
+ drive->name, drive->hwif->data_phase ? "MULT" : "",
+ (drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : "");
return startstop;
}
- if (!drive->unmask)
+ if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0)
local_irq_disable();
ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
@@ -492,11 +440,12 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
{
- struct request rq;
+ struct request *rq;
+ int error;
- blk_rq_init(NULL, &rq);
- rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
- rq.buffer = buf;
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
+ rq->buffer = buf;
/*
* (ks) We transfer currently only whole sectors.
@@ -504,16 +453,19 @@ int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
* if we would find a solution to transfer any size.
* To support special commands like READ LONG.
*/
- rq.hard_nr_sectors = rq.nr_sectors = nsect;
- rq.hard_cur_sectors = rq.current_nr_sectors = nsect;
+ rq->hard_nr_sectors = rq->nr_sectors = nsect;
+ rq->hard_cur_sectors = rq->current_nr_sectors = nsect;
if (task->tf_flags & IDE_TFLAG_WRITE)
- rq.cmd_flags |= REQ_RW;
+ rq->cmd_flags |= REQ_RW;
+
+ rq->special = task;
+ task->rq = rq;
- rq.special = task;
- task->rq = &rq;
+ error = blk_execute_rq(drive->queue, NULL, rq, 0);
+ blk_put_request(rq);
- return ide_do_drive_cmd(drive, &rq, ide_wait);
+ return error;
}
EXPORT_SYMBOL(ide_raw_taskfile);
@@ -593,7 +545,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
IDE_TFLAG_IN_TF;
- if (drive->addressing == 1)
+ if (drive->dev_flags & IDE_DFLAG_LBA48)
args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
if (req_task->out_flags.all) {
@@ -696,7 +648,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
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)
+ if (drive->dev_flags & IDE_DFLAG_LBA48)
req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
}
@@ -728,108 +680,3 @@ abort:
return err;
}
#endif
-
-int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
-{
- 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);
- }
-
- if (copy_from_user(args, (void __user *)arg, 4))
- return -EFAULT;
-
- memset(&tfargs, 0, sizeof(ide_task_t));
- 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]) {
- tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
- bufsize = SECTOR_WORDS * 4 * args[3];
- buf = kzalloc(bufsize, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
- }
-
- 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 (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_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 */
- ide_set_xfer_rate(drive, xfer_rate);
- ide_driveid_update(drive);
- }
-abort:
- if (copy_to_user((void __user *)arg, &args, 4))
- err = -EFAULT;
- if (buf) {
- if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
- err = -EFAULT;
- kfree(buf);
- }
- return err;
-}
-
-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];
- ide_task_t task;
-
- if (copy_from_user(args, p, 7))
- return -EFAULT;
-
- 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;
-
- err = ide_no_data_taskfile(drive, &task);
-
- args[0] = task.tf.command;
- memcpy(&args[1], &task.tf_array[7], 6);
-
- if (copy_to_user(p, args, 7))
- err = -EFAULT;
-
- return err;
-}
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timings.c
index 3b12ffe7707..81f527af8fa 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timings.c
@@ -1,11 +1,7 @@
-#ifndef _IDE_TIMING_H
-#define _IDE_TIMING_H
-
/*
* Copyright (c) 1999-2001 Vojtech Pavlik
- */
-
-/*
+ * Copyright (c) 2007-2008 Bartlomiej Zolnierkiewicz
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -26,28 +22,14 @@
*/
#include <linux/kernel.h>
-#include <linux/hdreg.h>
-
-#define XFER_PIO_5 0x0d
-#define XFER_UDMA_SLOW 0x4f
-
-struct ide_timing {
- short mode;
- short setup; /* t1 */
- short act8b; /* t2 for 8-bit io */
- short rec8b; /* t2i for 8-bit io */
- short cyc8b; /* t0 for 8-bit io */
- short active; /* t2 or tD */
- short recover; /* t2i or tK */
- short cycle; /* t0 */
- short udma; /* t2CYCTYP/2 */
-};
+#include <linux/ide.h>
+#include <linux/module.h>
/*
* PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
* These were taken from ATA/ATAPI-6 standard, rev 0a, except
* for PIO 5, which is a nonstandard extension and UDMA6, which
- * is currently supported only by Maxtor drives.
+ * is currently supported only by Maxtor drives.
*/
static struct ide_timing ide_timing[] = {
@@ -61,12 +43,10 @@ static struct ide_timing ide_timing[] = {
{ XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
{ XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
- { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 },
-
{ XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
{ XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
{ XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
-
+
{ XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
{ XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
{ XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
@@ -81,30 +61,46 @@ static struct ide_timing ide_timing[] = {
{ XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 },
- { -1 }
+ { 0xff }
};
-#define IDE_TIMING_SETUP 0x01
-#define IDE_TIMING_ACT8B 0x02
-#define IDE_TIMING_REC8B 0x04
-#define IDE_TIMING_CYC8B 0x08
-#define IDE_TIMING_8BIT 0x0e
-#define IDE_TIMING_ACTIVE 0x10
-#define IDE_TIMING_RECOVER 0x20
-#define IDE_TIMING_CYCLE 0x40
-#define IDE_TIMING_UDMA 0x80
-#define IDE_TIMING_ALL 0xff
-
-#define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin)
-#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
-#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
-
-#define XFER_MODE 0xf0
-#define XFER_MWDMA 0x20
-#define XFER_EPIO 0x01
-#define XFER_PIO 0x00
-
-static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int T, int UT)
+struct ide_timing *ide_timing_find_mode(u8 speed)
+{
+ struct ide_timing *t;
+
+ for (t = ide_timing; t->mode != speed; t++)
+ if (t->mode == 0xff)
+ return NULL;
+ return t;
+}
+EXPORT_SYMBOL_GPL(ide_timing_find_mode);
+
+u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio)
+{
+ u16 *id = drive->id;
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+ u16 cycle = 0;
+
+ if (id[ATA_ID_FIELD_VALID] & 2) {
+ if (ata_id_has_iordy(drive->id))
+ cycle = id[ATA_ID_EIDE_PIO_IORDY];
+ else
+ cycle = id[ATA_ID_EIDE_PIO];
+
+ /* conservative "downgrade" for all pre-ATA2 drives */
+ if (pio < 3 && cycle < t->cycle)
+ cycle = 0; /* use standard timing */
+ }
+
+ return cycle ? cycle : t->cycle;
+}
+EXPORT_SYMBOL_GPL(ide_pio_cycle_time);
+
+#define ENOUGH(v, unit) (((v) - 1) / (unit) + 1)
+#define EZ(v, unit) ((v) ? ENOUGH(v, unit) : 0)
+
+static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q,
+ int T, int UT)
{
q->setup = EZ(t->setup * 1000, T);
q->act8b = EZ(t->act8b * 1000, T);
@@ -116,92 +112,82 @@ static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int
q->udma = EZ(t->udma * 1000, UT);
}
-static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
+void ide_timing_merge(struct ide_timing *a, struct ide_timing *b,
+ struct ide_timing *m, unsigned int what)
{
- if (what & IDE_TIMING_SETUP ) m->setup = max(a->setup, b->setup);
- if (what & IDE_TIMING_ACT8B ) m->act8b = max(a->act8b, b->act8b);
- if (what & IDE_TIMING_REC8B ) m->rec8b = max(a->rec8b, b->rec8b);
- if (what & IDE_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
- if (what & IDE_TIMING_ACTIVE ) m->active = max(a->active, b->active);
- if (what & IDE_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
- if (what & IDE_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
- if (what & IDE_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
+ if (what & IDE_TIMING_SETUP)
+ m->setup = max(a->setup, b->setup);
+ if (what & IDE_TIMING_ACT8B)
+ m->act8b = max(a->act8b, b->act8b);
+ if (what & IDE_TIMING_REC8B)
+ m->rec8b = max(a->rec8b, b->rec8b);
+ if (what & IDE_TIMING_CYC8B)
+ m->cyc8b = max(a->cyc8b, b->cyc8b);
+ if (what & IDE_TIMING_ACTIVE)
+ m->active = max(a->active, b->active);
+ if (what & IDE_TIMING_RECOVER)
+ m->recover = max(a->recover, b->recover);
+ if (what & IDE_TIMING_CYCLE)
+ m->cycle = max(a->cycle, b->cycle);
+ if (what & IDE_TIMING_UDMA)
+ m->udma = max(a->udma, b->udma);
}
+EXPORT_SYMBOL_GPL(ide_timing_merge);
-static struct ide_timing* ide_timing_find_mode(short speed)
+int ide_timing_compute(ide_drive_t *drive, u8 speed,
+ struct ide_timing *t, int T, int UT)
{
- struct ide_timing *t;
-
- for (t = ide_timing; t->mode != speed; t++)
- if (t->mode < 0)
- return NULL;
- return t;
-}
-
-static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing *t, int T, int UT)
-{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
struct ide_timing *s, p;
-/*
- * Find the mode.
- */
-
- if (!(s = ide_timing_find_mode(speed)))
+ /*
+ * Find the mode.
+ */
+ s = ide_timing_find_mode(speed);
+ if (s == NULL)
return -EINVAL;
-/*
- * Copy the timing from the table.
- */
-
+ /*
+ * Copy the timing from the table.
+ */
*t = *s;
-/*
- * If the drive is an EIDE drive, it can tell us it needs extended
- * PIO/MWDMA cycle timing.
- */
-
- if (id && id->field_valid & 2) { /* EIDE drive */
-
+ /*
+ * If the drive is an EIDE drive, it can tell us it needs extended
+ * PIO/MWDMA cycle timing.
+ */
+ if (id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
memset(&p, 0, sizeof(p));
- switch (speed & XFER_MODE) {
-
- case XFER_PIO:
- if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = id->eide_pio;
- else p.cycle = p.cyc8b = id->eide_pio_iordy;
- break;
-
- case XFER_MWDMA:
- p.cycle = id->eide_dma_min;
- break;
- }
+ if (speed <= XFER_PIO_2)
+ p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
+ else if (speed <= XFER_PIO_5)
+ p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
+ else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
+ p.cycle = id[ATA_ID_EIDE_DMA_MIN];
ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B);
}
-/*
- * Convert the timing to bus clock counts.
- */
-
+ /*
+ * Convert the timing to bus clock counts.
+ */
ide_timing_quantize(t, t, T, UT);
-/*
- * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
- * and some other commands. We have to ensure that the DMA cycle timing is
- * slower/equal than the fastest PIO timing.
- */
-
- if ((speed & XFER_MODE) != XFER_PIO) {
+ /*
+ * Even in DMA/UDMA modes we still use PIO access for IDENTIFY,
+ * S.M.A.R.T and some other commands. We have to ensure that the
+ * DMA cycle timing is slower/equal than the fastest PIO timing.
+ */
+ if (speed >= XFER_SW_DMA_0) {
u8 pio = ide_get_best_pio_mode(drive, 255, 5);
ide_timing_compute(drive, XFER_PIO_0 + pio, &p, T, UT);
ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
}
-/*
- * Lengthen active & recovery time so that cycle time is correct.
- */
-
+ /*
+ * Lengthen active & recovery time so that cycle time is correct.
+ */
if (t->act8b + t->rec8b < t->cyc8b) {
t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
t->rec8b = t->cyc8b - t->act8b;
@@ -214,5 +200,4 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
return 0;
}
-
-#endif
+EXPORT_SYMBOL_GPL(ide_timing_compute);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index c758dcb13b1..04f8f13cb9d 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- * Copyrifht (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
*/
/*
@@ -44,35 +44,21 @@
* inspiration from lots of linux users, esp. hamish@zot.apana.org.au
*/
-#define _IDE_C /* Tell ide.h it's really us */
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
-#include <linux/blkpg.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <linux/completion.h>
-#include <linux/reboot.h>
-#include <linux/cdrom.h>
-#include <linux/seq_file.h>
#include <linux/device.h>
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
/* default maximum number of failures */
@@ -86,15 +72,10 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
IDE6_MAJOR, IDE7_MAJOR,
IDE8_MAJOR, IDE9_MAJOR };
-static int idebus_parameter; /* holds the "idebus=" parameter */
-static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
-
DEFINE_MUTEX(ide_cfg_mtx);
- __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
-int noautodma = 0;
-
-ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
+__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
+EXPORT_SYMBOL(ide_lock);
static void ide_port_init_devices_data(ide_hwif_t *);
@@ -115,16 +96,12 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
hwif->name[2] = 'e';
hwif->name[3] = '0' + index;
- hwif->bus_state = BUSSTATE_ON;
-
init_completion(&hwif->gendev_rel_comp);
- default_hwif_iops(hwif);
- default_hwif_transport(hwif);
+ hwif->tp_ops = &default_tp_ops;
ide_port_init_devices_data(hwif);
}
-EXPORT_SYMBOL_GPL(ide_init_port_data);
static void ide_port_init_devices_data(ide_hwif_t *hwif)
{
@@ -137,10 +114,9 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
memset(drive, 0, sizeof(*drive));
drive->media = ide_disk;
- drive->select.all = (unit<<4)|0xa0;
+ drive->select = (unit << 4) | ATA_DEVICE_OBS;
drive->hwif = hwif;
- drive->ctl = 0x08;
- drive->ready_stat = READY_STAT;
+ drive->ready_stat = ATA_DRDY;
drive->bad_wstat = BAD_W_STAT;
drive->special.b.recalibrate = 1;
drive->special.b.set_geometry = 1;
@@ -154,108 +130,6 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
}
}
-/*
- * init_ide_data() sets reasonable default values into all fields
- * of all instances of the hwifs and drives, but only on the first call.
- * Subsequent calls have no effect (they don't wipe out anything).
- *
- * This routine is normally called at driver initialization time,
- * but may also be called MUCH earlier during kernel "command-line"
- * parameter processing. As such, we cannot depend on any other parts
- * of the kernel (such as memory allocation) to be functioning yet.
- *
- * This is too bad, as otherwise we could dynamically allocate the
- * ide_drive_t structs as needed, rather than always consuming memory
- * for the max possible number (MAX_HWIFS * MAX_DRIVES) of them.
- *
- * FIXME: We should stuff the setup data into __init and copy the
- * relevant hwifs/allocate them properly during boot.
- */
-#define MAGIC_COOKIE 0x12345678
-static void __init init_ide_data (void)
-{
- unsigned int index;
- static unsigned long magic_cookie = MAGIC_COOKIE;
-
- if (magic_cookie != MAGIC_COOKIE)
- return; /* already initialized */
- magic_cookie = 0;
-
- /* Initialise all interface structures */
- for (index = 0; index < MAX_HWIFS; ++index) {
- ide_hwif_t *hwif = &ide_hwifs[index];
-
- ide_init_port_data(hwif, index);
- }
-}
-
-/**
- * ide_system_bus_speed - guess bus speed
- *
- * ide_system_bus_speed() returns what we think is the system VESA/PCI
- * bus speed (in MHz). This is used for calculating interface PIO timings.
- * The default is 40 for known PCI systems, 50 otherwise.
- * The "idebus=xx" parameter can be used to override this value.
- * The actual value to be used is computed/displayed the first time
- * through. Drivers should only use this as a last resort.
- *
- * Returns a guessed speed in MHz.
- */
-
-static int ide_system_bus_speed(void)
-{
-#ifdef CONFIG_PCI
- static struct pci_device_id pci_default[] = {
- { PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID) },
- { }
- };
-#else
-#define pci_default 0
-#endif /* CONFIG_PCI */
-
- /* 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;
-}
-
-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);
-}
-
/* Called with ide_lock held. */
static void __ide_port_unregister_devices(ide_hwif_t *hwif)
{
@@ -264,7 +138,7 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
for (i = 0; i < MAX_DRIVES; i++) {
ide_drive_t *drive = &hwif->drives[i];
- if (drive->present) {
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
spin_unlock_irq(&ide_lock);
device_unregister(&drive->gendev);
wait_for_completion(&drive->gendev_rel_comp);
@@ -315,13 +189,14 @@ void ide_unregister(ide_hwif_t *hwif)
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
+
mutex_lock(&ide_cfg_mtx);
- spin_lock_irq(&ide_lock);
- if (!hwif->present)
- goto abort;
- __ide_port_unregister_devices(hwif);
- hwif->present = 0;
+ spin_lock_irq(&ide_lock);
+ if (hwif->present) {
+ __ide_port_unregister_devices(hwif);
+ hwif->present = 0;
+ }
spin_unlock_irq(&ide_lock);
ide_proc_unregister_port(hwif);
@@ -351,30 +226,22 @@ void ide_unregister(ide_hwif_t *hwif)
blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
kfree(hwif->sg_table);
unregister_blkdev(hwif->major, hwif->name);
- spin_lock_irq(&ide_lock);
- if (hwif->dma_base)
- ide_release_dma_engine(hwif);
+ ide_release_dma_engine(hwif);
- /* restore hwif data to pristine status */
- ide_init_port_data(hwif, hwif->index);
-
-abort:
- spin_unlock_irq(&ide_lock);
mutex_unlock(&ide_cfg_mtx);
}
-EXPORT_SYMBOL(ide_unregister);
-
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->chipset = hw->chipset;
- hwif->gendev.parent = hw->dev;
+ hwif->dev = hw->dev;
+ hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
hwif->ack_intr = hw->ack_intr;
+ hwif->config_data = hw->config;
}
-EXPORT_SYMBOL_GPL(ide_init_port_hw);
/*
* Locks for IDE setting functionality
@@ -382,95 +249,51 @@ EXPORT_SYMBOL_GPL(ide_init_port_hw);
DEFINE_MUTEX(ide_setting_mtx);
-EXPORT_SYMBOL_GPL(ide_setting_mtx);
-
-/**
- * ide_spin_wait_hwgroup - wait for group
- * @drive: drive in the group
- *
- * Wait for an IDE device group to go non busy and then return
- * holding the ide_lock which guards the hwgroup->busy status
- * and right to use it.
- */
-
-int ide_spin_wait_hwgroup (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- unsigned long timeout = jiffies + (3 * HZ);
-
- spin_lock_irq(&ide_lock);
-
- while (hwgroup->busy) {
- unsigned long lflags;
- spin_unlock_irq(&ide_lock);
- local_irq_set(lflags);
- if (time_after(jiffies, timeout)) {
- local_irq_restore(lflags);
- printk(KERN_ERR "%s: channel busy\n", drive->name);
- return -EBUSY;
- }
- local_irq_restore(lflags);
- spin_lock_irq(&ide_lock);
- }
- return 0;
-}
-
-EXPORT_SYMBOL(ide_spin_wait_hwgroup);
+ide_devset_get(io_32bit, io_32bit);
-int set_io_32bit(ide_drive_t *drive, int arg)
+static int set_io_32bit(ide_drive_t *drive, int arg)
{
- if (drive->no_io_32bit)
+ if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
return -EPERM;
if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
-
drive->io_32bit = arg;
- spin_unlock_irq(&ide_lock);
-
return 0;
}
+ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
+
static int set_ksettings(ide_drive_t *drive, int arg)
{
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- drive->keep_settings = arg;
- spin_unlock_irq(&ide_lock);
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
return 0;
}
-int set_using_dma(ide_drive_t *drive, int arg)
+ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
+
+static int set_using_dma(ide_drive_t *drive, int arg)
{
#ifdef CONFIG_BLK_DEV_IDEDMA
- ide_hwif_t *hwif = drive->hwif;
int err = -EPERM;
if (arg < 0 || arg > 1)
return -EINVAL;
- if (!drive->id || !(drive->id->capability & 1))
- goto out;
-
- if (hwif->dma_ops == NULL)
+ if (ata_id_has_dma(drive->id) == 0)
goto out;
- err = -EBUSY;
- if (ide_spin_wait_hwgroup(drive))
+ if (drive->hwif->dma_ops == NULL)
goto out;
- /*
- * set ->busy flag, unlock and let it ride
- */
- hwif->hwgroup->busy = 1;
- spin_unlock_irq(&ide_lock);
err = 0;
@@ -480,12 +303,6 @@ int set_using_dma(ide_drive_t *drive, int arg)
} else
ide_dma_off(drive);
- /*
- * lock, clear ->busy flag and unlock before leaving
- */
- spin_lock_irq(&ide_lock);
- hwif->hwgroup->busy = 0;
- spin_unlock_irq(&ide_lock);
out:
return err;
#else
@@ -496,9 +313,32 @@ out:
#endif
}
-int set_pio_mode(ide_drive_t *drive, int arg)
+/*
+ * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
+ */
+static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
+{
+ switch (req_pio) {
+ case 202:
+ case 201:
+ case 200:
+ case 102:
+ case 101:
+ case 100:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
+ case 9:
+ case 8:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
+ case 7:
+ case 6:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
+ default:
+ return 0;
+ }
+}
+
+static int set_pio_mode(ide_drive_t *drive, int arg)
{
- struct request rq;
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
@@ -509,109 +349,117 @@ int set_pio_mode(ide_drive_t *drive, int arg)
(hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
return -ENOSYS;
- if (drive->special.b.set_tune)
- return -EBUSY;
+ if (set_pio_mode_abuse(drive->hwif, arg)) {
+ if (arg == 8 || arg == 9) {
+ unsigned long flags;
+
+ /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
+ spin_lock_irqsave(&ide_lock, flags);
+ port_ops->set_pio_mode(drive, arg);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ } else
+ port_ops->set_pio_mode(drive, arg);
+ } else {
+ int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
+
+ ide_set_pio(drive, arg);
- ide_init_drive_cmd(&rq);
- rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+ if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
+ if (keep_dma)
+ ide_dma_on(drive);
+ }
+ }
- drive->tune_req = (u8) arg;
- drive->special.b.set_tune = 1;
- (void) ide_do_drive_cmd(drive, &rq, ide_wait);
return 0;
}
+ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
+
static int set_unmaskirq(ide_drive_t *drive, int arg)
{
- if (drive->no_unmask)
+ if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
return -EPERM;
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- drive->unmask = arg;
- spin_unlock_irq(&ide_lock);
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_UNMASK;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
return 0;
}
-/**
- * system_bus_clock - clock guess
- *
- * External version of the bus clock guess used by very old IDE drivers
- * for things like VLB timings. Should not be used.
- */
-
-int system_bus_clock (void)
-{
- return system_bus_speed;
-}
-
-EXPORT_SYMBOL(system_bus_clock);
+ide_ext_devset_rw_sync(io_32bit, io_32bit);
+ide_ext_devset_rw_sync(keepsettings, ksettings);
+ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
+ide_ext_devset_rw_sync(using_dma, using_dma);
+__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
{
- ide_drive_t *drive = dev->driver_data;
+ ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
ide_hwif_t *hwif = HWIF(drive);
- struct request rq;
+ struct request *rq;
struct request_pm_state rqpm;
ide_task_t args;
int ret;
- /* Call ACPI _GTM only once */
- if (!(drive->dn % 2))
+ /* call ACPI _GTM only once */
+ if ((drive->dn & 1) == 0 || pair == NULL)
ide_acpi_get_timing(hwif);
- blk_rq_init(NULL, &rq);
memset(&rqpm, 0, sizeof(rqpm));
memset(&args, 0, sizeof(args));
- rq.cmd_type = REQ_TYPE_PM_SUSPEND;
- rq.special = &args;
- rq.data = &rqpm;
- rqpm.pm_step = ide_pm_state_start_suspend;
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_PM_SUSPEND;
+ rq->special = &args;
+ rq->data = &rqpm;
+ rqpm.pm_step = IDE_PM_START_SUSPEND;
if (mesg.event == PM_EVENT_PRETHAW)
mesg.event = PM_EVENT_FREEZE;
rqpm.pm_state = mesg.event;
- ret = ide_do_drive_cmd(drive, &rq, ide_wait);
- /* only call ACPI _PS3 after both drivers are suspended */
- if (!ret && (((drive->dn % 2) && hwif->drives[0].present
- && hwif->drives[1].present)
- || !hwif->drives[0].present
- || !hwif->drives[1].present))
+ ret = blk_execute_rq(drive->queue, NULL, rq, 0);
+ blk_put_request(rq);
+
+ /* call ACPI _PS3 only after both devices are suspended */
+ if (ret == 0 && ((drive->dn & 1) || pair == NULL))
ide_acpi_set_state(hwif, 0);
+
return ret;
}
static int generic_ide_resume(struct device *dev)
{
- ide_drive_t *drive = dev->driver_data;
+ ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
ide_hwif_t *hwif = HWIF(drive);
- struct request rq;
+ struct request *rq;
struct request_pm_state rqpm;
ide_task_t args;
int err;
- /* Call ACPI _STM only once */
- if (!(drive->dn % 2)) {
+ /* call ACPI _PS0 / _STM only once */
+ if ((drive->dn & 1) == 0 || pair == NULL) {
ide_acpi_set_state(hwif, 1);
ide_acpi_push_timing(hwif);
}
ide_acpi_exec_tfs(drive);
- blk_rq_init(NULL, &rq);
memset(&rqpm, 0, sizeof(rqpm));
memset(&args, 0, sizeof(args));
- rq.cmd_type = REQ_TYPE_PM_RESUME;
- rq.special = &args;
- rq.data = &rqpm;
- rqpm.pm_step = ide_pm_state_start_resume;
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_PM_RESUME;
+ rq->cmd_flags |= REQ_PREEMPT;
+ rq->special = &args;
+ rq->data = &rqpm;
+ rqpm.pm_step = IDE_PM_START_RESUME;
rqpm.pm_state = PM_EVENT_ON;
- err = ide_do_drive_cmd(drive, &rq, ide_head_wait);
+ err = blk_execute_rq(drive->queue, NULL, rq, 1);
+ blk_put_request(rq);
if (err == 0 && dev->driver) {
ide_driver_t *drv = to_ide_driver(dev->driver);
@@ -623,352 +471,52 @@ static int generic_ide_resume(struct device *dev)
return err;
}
-int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
- unsigned int cmd, unsigned long arg)
+/**
+ * ide_device_get - get an additional reference to a ide_drive_t
+ * @drive: device to get a reference to
+ *
+ * Gets a reference to the ide_drive_t and increments the use count of the
+ * underlying LLDD module.
+ */
+int ide_device_get(ide_drive_t *drive)
{
- unsigned long flags;
- ide_driver_t *drv;
- void __user *p = (void __user *)arg;
- int err = 0, (*setfunc)(ide_drive_t *, int);
- u8 *val;
-
- switch (cmd) {
- case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val;
- case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
- case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val;
- case HDIO_GET_DMA: val = &drive->using_dma; goto read_val;
- case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val;
- case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val;
- case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val;
- case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val;
- case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val;
- }
+ struct device *host_dev;
+ struct module *module;
- switch (cmd) {
- case HDIO_OBSOLETE_IDENTITY:
- case HDIO_GET_IDENTITY:
- if (bdev != bdev->bd_contains)
- return -EINVAL;
- if (drive->id_read == 0)
- return -ENOMSG;
- if (copy_to_user(p, drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
- return -EFAULT;
- return 0;
-
- case HDIO_GET_NICE:
- return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP |
- drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP |
- 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))
- return -EACCES;
- switch(drive->media) {
- case ide_disk:
- return ide_taskfile_ioctl(drive, cmd, arg);
- default:
- return -ENOMSG;
- }
-#endif /* CONFIG_IDE_TASK_IOCTL */
-
- case HDIO_DRIVE_CMD:
- if (!capable(CAP_SYS_RAWIO))
- return -EACCES;
- return ide_cmd_ioctl(drive, cmd, arg);
-
- case HDIO_DRIVE_TASK:
- if (!capable(CAP_SYS_RAWIO))
- return -EACCES;
- return ide_task_ioctl(drive, cmd, arg);
- case HDIO_SET_NICE:
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
- return -EPERM;
- drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
- drv = *(ide_driver_t **)bdev->bd_disk->private_data;
- if (drive->dsc_overlap && !drv->supports_dsc_overlap) {
- drive->dsc_overlap = 0;
- return -EPERM;
- }
- drive->nice1 = (arg >> IDE_NICE_1) & 1;
- return 0;
- case HDIO_DRIVE_RESET:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- /*
- * Abort the current command on the
- * group if there is one, taking
- * care not to allow anything else
- * to be queued and to die on the
- * spot if we miss one somehow
- */
+ if (!get_device(&drive->gendev))
+ return -ENXIO;
- spin_lock_irqsave(&ide_lock, flags);
-
- if (HWGROUP(drive)->resetting) {
- spin_unlock_irqrestore(&ide_lock, flags);
- return -EBUSY;
- }
-
- ide_abort(drive, "drive reset");
+ host_dev = drive->hwif->host->dev[0];
+ module = host_dev ? host_dev->driver->owner : NULL;
- BUG_ON(HWGROUP(drive)->handler);
-
- /* Ensure nothing gets queued after we
- drop the lock. Reset will clear the busy */
-
- HWGROUP(drive)->busy = 1;
- spin_unlock_irqrestore(&ide_lock, flags);
- (void) ide_do_reset(drive);
-
- return 0;
- case HDIO_GET_BUSSTATE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (put_user(HWIF(drive)->bus_state, (long __user *)arg))
- return -EFAULT;
- return 0;
-
- case HDIO_SET_BUSSTATE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- return -EOPNOTSUPP;
- default:
- return -EINVAL;
+ if (module && !try_module_get(module)) {
+ put_device(&drive->gendev);
+ return -ENXIO;
}
-read_val:
- mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
- err = *val;
- spin_unlock_irqrestore(&ide_lock, flags);
- mutex_unlock(&ide_setting_mtx);
- return err >= 0 ? put_user(err, (long __user *)arg) : err;
-
-set_val:
- if (bdev != bdev->bd_contains)
- err = -EINVAL;
- else {
- if (!capable(CAP_SYS_ADMIN))
- err = -EACCES;
- else {
- mutex_lock(&ide_setting_mtx);
- err = setfunc(drive, arg);
- mutex_unlock(&ide_setting_mtx);
- }
- }
- return err;
-}
-
-EXPORT_SYMBOL(generic_ide_ioctl);
-
-/*
- * stridx() returns the offset of c within s,
- * or -1 if c is '\0' or not found within s.
- */
-static int __init stridx (const char *s, char c)
-{
- char *i = strchr(s, c);
- return (i && c) ? i - s : -1;
-}
-
-/*
- * match_parm() does parsing for ide_setup():
- *
- * 1. the first char of s must be '='.
- * 2. if the remainder matches one of the supplied keywords,
- * the index (1 based) of the keyword is negated and returned.
- * 3. if the remainder is a series of no more than max_vals numbers
- * separated by commas, the numbers are saved in vals[] and a
- * count of how many were saved is returned. Base10 is assumed,
- * and base16 is allowed when prefixed with "0x".
- * 4. otherwise, zero is returned.
- */
-static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals)
-{
- static const char *decimal = "0123456789";
- static const char *hex = "0123456789abcdef";
- int i, n;
-
- if (*s++ == '=') {
- /*
- * Try matching against the supplied keywords,
- * and return -(index+1) if we match one
- */
- if (keywords != NULL) {
- for (i = 0; *keywords != NULL; ++i) {
- if (!strcmp(s, *keywords++))
- return -(i+1);
- }
- }
- /*
- * Look for a series of no more than "max_vals"
- * numeric values separated by commas, in base10,
- * or base16 when prefixed with "0x".
- * Return a count of how many were found.
- */
- for (n = 0; (i = stridx(decimal, *s)) >= 0;) {
- vals[n] = i;
- while ((i = stridx(decimal, *++s)) >= 0)
- vals[n] = (vals[n] * 10) + i;
- if (*s == 'x' && !vals[n]) {
- while ((i = stridx(hex, *++s)) >= 0)
- vals[n] = (vals[n] * 0x10) + i;
- }
- if (++n == max_vals)
- break;
- if (*s == ',' || *s == ';')
- ++s;
- }
- if (!*s)
- return n;
- }
- return 0; /* zero = nothing matched */
+ return 0;
}
+EXPORT_SYMBOL_GPL(ide_device_get);
-/*
- * ide_setup() gets called VERY EARLY during initialization,
- * to handle kernel "command line" strings beginning with "hdx=" or "ide".
+/**
+ * ide_device_put - release a reference to a ide_drive_t
+ * @drive: device to release a reference on
*
- * Remember to update Documentation/ide/ide.txt if you change something here.
+ * Release a reference to the ide_drive_t and decrements the use count of
+ * the underlying LLDD module.
*/
-static int __init ide_setup(char *s)
+void ide_device_put(ide_drive_t *drive)
{
- ide_hwif_t *hwif;
- ide_drive_t *drive;
- unsigned int hw, unit;
- int vals[3];
- const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
-
- if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */
- return 0; /* driver and not us */
-
- if (strncmp(s,"ide",3) && strncmp(s,"idebus",6) && strncmp(s,"hd",2))
- return 0;
-
- printk(KERN_INFO "ide_setup: %s", s);
- init_ide_data ();
-
-#ifdef CONFIG_BLK_DEV_IDEDOUBLER
- if (!strcmp(s, "ide=doubler")) {
- extern int ide_doubler;
-
- printk(" : Enabled support for IDE doublers\n");
- ide_doubler = 1;
- goto obsolete_option;
- }
-#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
-
- if (!strcmp(s, "ide=nodma")) {
- printk(" : Prevented DMA\n");
- noautodma = 1;
- goto obsolete_option;
- }
-
-#ifdef CONFIG_BLK_DEV_IDEACPI
- if (!strcmp(s, "ide=noacpi")) {
- //printk(" : Disable IDE ACPI support.\n");
- ide_noacpi = 1;
- goto obsolete_option;
- }
- if (!strcmp(s, "ide=acpigtf")) {
- //printk(" : Enable IDE ACPI _GTF support.\n");
- ide_acpigtf = 1;
- goto obsolete_option;
- }
- if (!strcmp(s, "ide=acpionboot")) {
- //printk(" : Call IDE ACPI methods on boot.\n");
- ide_acpionboot = 1;
- goto obsolete_option;
- }
-#endif /* CONFIG_BLK_DEV_IDEACPI */
-
- /*
- * Look for drive options: "hdx="
- */
- if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
- const char *hd_words[] = {
- "none", "noprobe", "nowerr", "cdrom", "nodma",
- "-6", "-7", "-8", "-9", "-10",
- "noflush", "remap", "remap63", "scsi", NULL };
- unit = s[2] - 'a';
- hw = unit / MAX_DRIVES;
- unit = unit % MAX_DRIVES;
- hwif = &ide_hwifs[hw];
- drive = &hwif->drives[unit];
- if (strncmp(s + 4, "ide-", 4) == 0) {
- strlcpy(drive->driver_req, s + 4, sizeof(drive->driver_req));
- goto obsolete_option;
- }
- switch (match_parm(&s[3], hd_words, vals, 3)) {
- case -1: /* "none" */
- case -2: /* "noprobe" */
- drive->noprobe = 1;
- goto obsolete_option;
- case -3: /* "nowerr" */
- drive->bad_wstat = BAD_R_STAT;
- goto obsolete_option;
- case -4: /* "cdrom" */
- drive->present = 1;
- drive->media = ide_cdrom;
- /* an ATAPI device ignores DRDY */
- drive->ready_stat = 0;
- goto obsolete_option;
- case -5: /* nodma */
- drive->nodma = 1;
- goto obsolete_option;
- case -11: /* noflush */
- drive->noflush = 1;
- goto obsolete_option;
- case -12: /* "remap" */
- drive->remap_0_to_1 = 1;
- goto obsolete_option;
- case -13: /* "remap63" */
- drive->sect0 = 63;
- goto obsolete_option;
- case -14: /* "scsi" */
- drive->scsi = 1;
- goto obsolete_option;
- case 3: /* cyl,head,sect */
- drive->media = ide_disk;
- drive->ready_stat = READY_STAT;
- drive->cyl = drive->bios_cyl = vals[0];
- drive->head = drive->bios_head = vals[1];
- drive->sect = drive->bios_sect = vals[2];
- drive->present = 1;
- drive->forced_geom = 1;
- goto obsolete_option;
- default:
- goto bad_option;
- }
- }
-
- if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e')
- goto bad_option;
- /*
- * Look for bus speed option: "idebus="
- */
- if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') {
- if (match_parm(&s[6], NULL, vals, 1) != 1)
- goto bad_option;
- if (vals[0] >= 20 && vals[0] <= 66) {
- idebus_parameter = vals[0];
- } else
- printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
- goto obsolete_option;
- }
+#ifdef CONFIG_MODULE_UNLOAD
+ struct device *host_dev = drive->hwif->host->dev[0];
+ struct module *module = host_dev ? host_dev->driver->owner : NULL;
-bad_option:
- printk(" -- BAD OPTION\n");
- return 1;
-obsolete_option:
- printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n");
- return 1;
+ if (module)
+ module_put(module);
+#endif
+ put_device(&drive->gendev);
}
-
-EXPORT_SYMBOL(ide_lock);
+EXPORT_SYMBOL_GPL(ide_device_put);
static int ide_bus_match(struct device *dev, struct device_driver *drv)
{
@@ -1015,21 +563,21 @@ 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);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);
}
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);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_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);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);
}
static struct device_attribute ide_dev_attrs[] = {
@@ -1039,6 +587,7 @@ static struct device_attribute ide_dev_attrs[] = {
__ATTR_RO(model),
__ATTR_RO(firmware),
__ATTR(serial, 0400, serial_show, NULL),
+ __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
__ATTR_NULL
};
@@ -1094,13 +643,6 @@ struct bus_type ide_bus_type = {
EXPORT_SYMBOL_GPL(ide_bus_type);
-static void ide_port_class_release(struct device *portdev)
-{
- ide_hwif_t *hwif = dev_get_drvdata(portdev);
-
- put_device(&hwif->gendev);
-}
-
int ide_vlb_clk;
EXPORT_SYMBOL_GPL(ide_vlb_clk);
@@ -1153,7 +695,7 @@ MODULE_PARM_DESC(noprobe, "skip probing for a device");
static unsigned int ide_nowerr;
module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0);
-MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device");
+MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device");
static unsigned int ide_cdroms;
@@ -1200,31 +742,31 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0);
MODULE_PARM_DESC(chs, "force device as a disk (using CHS)");
-static void ide_dev_apply_params(ide_drive_t *drive)
+static void ide_dev_apply_params(ide_drive_t *drive, u8 unit)
{
- int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit;
+ int i = drive->hwif->index * MAX_DRIVES + unit;
if (ide_nodma & (1 << i)) {
printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name);
- drive->nodma = 1;
+ drive->dev_flags |= IDE_DFLAG_NODMA;
}
if (ide_noflush & (1 << i)) {
printk(KERN_INFO "ide: disabling flush requests for %s\n",
drive->name);
- drive->noflush = 1;
+ drive->dev_flags |= IDE_DFLAG_NOFLUSH;
}
if (ide_noprobe & (1 << i)) {
printk(KERN_INFO "ide: skipping probe for %s\n", drive->name);
- drive->noprobe = 1;
+ drive->dev_flags |= IDE_DFLAG_NOPROBE;
}
if (ide_nowerr & (1 << i)) {
- printk(KERN_INFO "ide: ignoring the WRERR_STAT bit for %s\n",
+ printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n",
drive->name);
drive->bad_wstat = BAD_R_STAT;
}
if (ide_cdroms & (1 << i)) {
printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name);
- drive->present = 1;
+ drive->dev_flags |= IDE_DFLAG_PRESENT;
drive->media = ide_cdrom;
/* an ATAPI device ignores DRDY */
drive->ready_stat = 0;
@@ -1233,13 +775,14 @@ static void ide_dev_apply_params(ide_drive_t *drive)
drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl;
drive->head = drive->bios_head = ide_disks_chs[i].head;
drive->sect = drive->bios_sect = ide_disks_chs[i].sect;
- drive->forced_geom = 1;
+
printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n",
drive->name,
drive->cyl, drive->head, drive->sect);
- drive->present = 1;
+
+ drive->dev_flags |= IDE_DFLAG_FORCED_GEOM | IDE_DFLAG_PRESENT;
drive->media = ide_disk;
- drive->ready_stat = READY_STAT;
+ drive->ready_stat = ATA_DRDY;
}
}
@@ -1277,7 +820,7 @@ void ide_port_apply_params(ide_hwif_t *hwif)
}
for (i = 0; i < MAX_DRIVES; i++)
- ide_dev_apply_params(&hwif->drives[i]);
+ ide_dev_apply_params(&hwif->drives[i], i);
}
/*
@@ -1288,11 +831,6 @@ static int __init ide_init(void)
int ret;
printk(KERN_INFO "Uniform Multi-Platform E-IDE driver\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) {
@@ -1305,9 +843,6 @@ static int __init ide_init(void)
ret = PTR_ERR(ide_port_class);
goto out_port_class;
}
- ide_port_class->dev_release = ide_port_class_release;
-
- init_ide_data();
proc_ide_create();
@@ -1319,32 +854,7 @@ out_port_class:
return ret;
}
-#ifdef MODULE
-static char *options = NULL;
-module_param(options, charp, 0);
-MODULE_LICENSE("GPL");
-
-static void __init parse_options (char *line)
-{
- char *next = line;
-
- if (line == NULL || !*line)
- return;
- while ((line = next) != NULL) {
- if ((next = strchr(line,' ')) != NULL)
- *next++ = 0;
- if (!ide_setup(line))
- printk (KERN_INFO "Unknown option '%s'\n", line);
- }
-}
-
-int __init init_module (void)
-{
- parse_options(options);
- return ide_init();
-}
-
-void __exit cleanup_module (void)
+static void __exit ide_exit(void)
{
proc_ide_destroy();
@@ -1353,10 +863,7 @@ void __exit cleanup_module (void)
bus_unregister(&ide_bus_type);
}
-#else /* !MODULE */
-
-__setup("", ide_setup);
-
module_init(ide_init);
+module_exit(ide_exit);
-#endif /* MODULE */
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
index 90c65cf9744..90da1f953ed 100644
--- a/drivers/ide/legacy/ali14xx.c
+++ b/drivers/ide/legacy/ali14xx.c
@@ -43,7 +43,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -116,11 +115,12 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
int time1, time2;
u8 param1, param2, param3, param4;
unsigned long flags;
- int bus_speed = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
+ int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
/* calculate timing, according to PIO mode */
time1 = ide_pio_cycle_time(drive, pio);
- time2 = ide_pio_timings[pio].active_time;
+ time2 = t->active;
param3 = param1 = (time2 * bus_speed + 999) / 1000;
param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
if (pio < 3) {
@@ -131,7 +131,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->name, pio, time1, time2, param1, param2, param3, param4);
/* stuff timing parameters into controller registers */
- driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
+ driveNum = (drive->hwif->index << 1) + (drive->dn & 1);
spin_lock_irqsave(&ali14xx_lock, flags);
outb_p(regOn, basePort);
outReg(param1, regTab[driveNum].reg1);
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 9a1d27ef3f8..c5a3c9ef6a5 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -20,7 +20,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/zorro.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -37,6 +36,8 @@
#define CATWEASEL_NUM_HWIFS 3
#define XSURF_NUM_HWIFS 2
+#define MAX_NUM_HWIFS 3
+
/*
* Bases of the IDE interfaces (relative to the board address)
*/
@@ -148,18 +149,14 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
static int __init buddha_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
- int i;
-
struct zorro_dev *z = NULL;
u_long buddha_board = 0;
BuddhaType type;
- int buddha_num_hwifs;
+ int buddha_num_hwifs, i;
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
unsigned long board;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
buddha_num_hwifs = BUDDHA_NUM_HWIFS;
@@ -221,20 +218,13 @@ fail_base2:
ack_intr = xsurf_ack_intr;
}
- buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
+ buddha_setup_ports(&hw[i], base, ctl, irq_port,
+ ack_intr);
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
-
- ide_init_port_data(hwif, index);
- ide_init_port_hw(hwif, &hw);
-
- idx[i] = index;
- }
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
+ ide_host_add(NULL, hws, NULL);
}
return 0;
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
index af791a02a12..689b2e49341 100644
--- a/drivers/ide/legacy/dtc2278.c
+++ b/drivers/ide/legacy/dtc2278.c
@@ -10,7 +10,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index af11028b479..39d500d84b0 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -13,7 +13,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -66,6 +65,27 @@ static void falconide_output_data(ide_drive_t *drive, struct request *rq,
outsw_swapw(data_addr, buf, (len + 1) / 2);
}
+/* Atari has a byte-swapped IDE interface */
+static const struct ide_tp_ops falconide_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = falconide_input_data,
+ .output_data = falconide_output_data,
+};
+
+static const struct ide_port_info falconide_port_info = {
+ .tp_ops = &falconide_tp_ops,
+ .host_flags = IDE_HFLAG_NO_DMA,
+};
+
static void __init falconide_setup_ports(hw_regs_t *hw)
{
int i;
@@ -91,11 +111,12 @@ static void __init falconide_setup_ports(hw_regs_t *hw)
static int __init falconide_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int rc;
if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
- return 0;
+ return -ENODEV;
printk(KERN_INFO "ide: Falcon IDE controller\n");
@@ -106,24 +127,25 @@ static int __init falconide_init(void)
falconide_setup_ports(&hw);
- hwif = ide_find_port();
- 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);
+ host = ide_host_alloc(&falconide_port_info, hws);
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
- /* Atari has a byte-swapped IDE interface */
- hwif->input_data = falconide_input_data;
- hwif->output_data = falconide_output_data;
+ ide_get_lock(NULL, NULL);
+ rc = ide_host_register(host, &falconide_port_info, hws);
+ ide_release_lock();
- ide_get_lock(NULL, NULL);
- ide_device_add(idx, NULL);
- ide_release_lock();
- }
+ if (rc)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
+err:
+ release_mem_region(ATA_HD_BASE, 0x40);
+ return rc;
}
module_init(falconide_init);
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index fed7d812761..69150688656 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -12,7 +12,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/zorro.h>
@@ -31,6 +30,8 @@
#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */
+#define GAYLE_IDEREG_SIZE 0x2000
+
/*
* Offsets from one of the above bases
*/
@@ -56,17 +57,13 @@
#define GAYLE_NUM_HWIFS 1
#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS
#define GAYLE_HAS_CONTROL_REG 1
-#define GAYLE_IDEREG_SIZE 0x2000
#else /* CONFIG_BLK_DEV_IDEDOUBLER */
#define GAYLE_NUM_HWIFS 2
#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \
GAYLE_NUM_HWIFS-1)
#define GAYLE_HAS_CONTROL_REG (!ide_doubler)
-#define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000)
-
-int ide_doubler = 0; /* support IDE doublers? */
-EXPORT_SYMBOL_GPL(ide_doubler);
+static int ide_doubler;
module_param_named(doubler, ide_doubler, bool, 0);
MODULE_PARM_DESC(doubler, "enable support for IDE doublers");
#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
@@ -126,8 +123,11 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
static int __init gayle_init(void)
{
- int a4000, i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ unsigned long phys_base, res_start, res_n;
+ unsigned long base, ctrlport, irqport;
+ ide_ack_intr_t *ack_intr;
+ int a4000, i, rc;
+ hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (!MACH_IS_AMIGA)
return -ENODEV;
@@ -150,13 +150,6 @@ found:
#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;
- unsigned long phys_base, res_start, res_n;
-
if (a4000) {
phys_base = GAYLE_BASE_4000;
irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
@@ -170,34 +163,26 @@ found:
* FIXME: we now have selectable modes between mmio v/s iomio
*/
- phys_base += i*GAYLE_NEXT_PORT;
-
res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
res_n = GAYLE_IDEREG_SIZE;
if (!request_mem_region(res_start, res_n, "IDE"))
- continue;
+ return -EBUSY;
- base = (unsigned long)ZTWO_VADDR(phys_base);
+ for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+ base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
- gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
-
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
-
- ide_init_port_data(hwif, index);
- ide_init_port_hw(hwif, &hw);
+ gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
- idx[i] = index;
- } else
- release_mem_region(res_start, res_n);
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
+ rc = ide_host_add(NULL, hws, NULL);
+ if (rc)
+ release_mem_region(res_start, res_n);
- return 0;
+ return rc;
}
module_init(gayle_init);
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
deleted file mode 100644
index abdedf56643..00000000000
--- a/drivers/ide/legacy/hd.c
+++ /dev/null
@@ -1,815 +0,0 @@
-/*
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * This is the low-level hd interrupt support. It traverses the
- * request-list, using interrupts to jump between functions. As
- * all the functions are called within interrupts, we may not
- * sleep. Special care is recommended.
- *
- * modified by Drew Eckhardt to check nr of hd's from the CMOS.
- *
- * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
- * in the early extended-partition checks and added DM partitions
- *
- * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
- * and general streamlining by Mark Lord.
- *
- * Removed 99% of above. Use Mark's ide driver for those options.
- * This is now a lightweight ST-506 driver. (Paul Gortmaker)
- *
- * Modified 1995 Russell King for ARM processor.
- *
- * Bugfix: max_sectors must be <= 255 or the wheels tend to come
- * off in a hurry once you queue things up - Paul G. 02/2001
- */
-
-/* Uncomment the following if you want verbose error reports. */
-/* #define VERBOSE_ERRORS */
-
-#include <linux/blkdev.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/genhd.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/mc146818rtc.h> /* CMOS defines */
-#include <linux/init.h>
-#include <linux/blkpg.h>
-#include <linux/hdreg.h>
-
-#define REALLY_SLOW_IO
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#ifdef __arm__
-#undef HD_IRQ
-#endif
-#include <asm/irq.h>
-#ifdef __arm__
-#define HD_IRQ IRQ_HARDDISK
-#endif
-
-/* Hd controller regster ports */
-
-#define HD_DATA 0x1f0 /* _CTL when writing */
-#define HD_ERROR 0x1f1 /* see err-bits */
-#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
-#define HD_SECTOR 0x1f3 /* starting sector */
-#define HD_LCYL 0x1f4 /* starting cylinder */
-#define HD_HCYL 0x1f5 /* high byte of starting cyl */
-#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
-#define HD_STATUS 0x1f7 /* see status-bits */
-#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
-#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
-#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
-
-#define HD_CMD 0x3f6 /* used for resets */
-#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
-
-/* Bits of HD_STATUS */
-#define ERR_STAT 0x01
-#define INDEX_STAT 0x02
-#define ECC_STAT 0x04 /* Corrected error */
-#define DRQ_STAT 0x08
-#define SEEK_STAT 0x10
-#define SERVICE_STAT SEEK_STAT
-#define WRERR_STAT 0x20
-#define READY_STAT 0x40
-#define BUSY_STAT 0x80
-
-/* Bits for HD_ERROR */
-#define MARK_ERR 0x01 /* Bad address mark */
-#define TRK0_ERR 0x02 /* couldn't find track 0 */
-#define ABRT_ERR 0x04 /* Command aborted */
-#define MCR_ERR 0x08 /* media change request */
-#define ID_ERR 0x10 /* ID field not found */
-#define MC_ERR 0x20 /* media changed */
-#define ECC_ERR 0x40 /* Uncorrectable ECC error */
-#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
-#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
-
-static DEFINE_SPINLOCK(hd_lock);
-static struct request_queue *hd_queue;
-
-#define MAJOR_NR HD_MAJOR
-#define QUEUE (hd_queue)
-#define CURRENT elv_next_request(hd_queue)
-
-#define TIMEOUT_VALUE (6*HZ)
-#define HD_DELAY 0
-
-#define MAX_ERRORS 16 /* Max read/write errors/sector */
-#define RESET_FREQ 8 /* Reset controller every 8th retry */
-#define RECAL_FREQ 4 /* Recalibrate every 4th retry */
-#define MAX_HD 2
-
-#define STAT_OK (READY_STAT|SEEK_STAT)
-#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
-
-static void recal_intr(void);
-static void bad_rw_intr(void);
-
-static int reset;
-static int hd_error;
-
-/*
- * This struct defines the HD's and their types.
- */
-struct hd_i_struct {
- unsigned int head, sect, cyl, wpcom, lzone, ctl;
- int unit;
- int recalibrate;
- int special_op;
-};
-
-#ifdef HD_TYPE
-static struct hd_i_struct hd_info[] = { HD_TYPE };
-static int NR_HD = ARRAY_SIZE(hd_info);
-#else
-static struct hd_i_struct hd_info[MAX_HD];
-static int NR_HD;
-#endif
-
-static struct gendisk *hd_gendisk[MAX_HD];
-
-static struct timer_list device_timer;
-
-#define TIMEOUT_VALUE (6*HZ)
-
-#define SET_TIMER \
- do { \
- mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \
- } while (0)
-
-static void (*do_hd)(void) = NULL;
-#define SET_HANDLER(x) \
-if ((do_hd = (x)) != NULL) \
- SET_TIMER; \
-else \
- del_timer(&device_timer);
-
-
-#if (HD_DELAY > 0)
-
-#include <asm/i8253.h>
-
-unsigned long last_req;
-
-unsigned long read_timer(void)
-{
- unsigned long t, flags;
- int i;
-
- spin_lock_irqsave(&i8253_lock, flags);
- t = jiffies * 11932;
- outb_p(0, 0x43);
- i = inb_p(0x40);
- i |= inb(0x40) << 8;
- spin_unlock_irqrestore(&i8253_lock, flags);
- return(t - i);
-}
-#endif
-
-static void __init hd_setup(char *str, int *ints)
-{
- int hdind = 0;
-
- if (ints[0] != 3)
- return;
- if (hd_info[0].head != 0)
- hdind = 1;
- hd_info[hdind].head = ints[2];
- hd_info[hdind].sect = ints[3];
- hd_info[hdind].cyl = ints[1];
- hd_info[hdind].wpcom = 0;
- hd_info[hdind].lzone = ints[1];
- hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
- NR_HD = hdind+1;
-}
-
-static void dump_status(const char *msg, unsigned int stat)
-{
- char *name = "hd?";
- if (CURRENT)
- name = CURRENT->rq_disk->disk_name;
-
-#ifdef VERBOSE_ERRORS
- printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
- if (stat & BUSY_STAT) printk("Busy ");
- if (stat & READY_STAT) printk("DriveReady ");
- if (stat & WRERR_STAT) printk("WriteFault ");
- 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 ((stat & ERR_STAT) == 0) {
- hd_error = 0;
- } else {
- hd_error = inb(HD_ERROR);
- printk("%s: %s: error=0x%02x { ", name, msg, hd_error & 0xff);
- if (hd_error & BBD_ERR) printk("BadSector ");
- if (hd_error & ECC_ERR) printk("UncorrectableError ");
- if (hd_error & ID_ERR) printk("SectorIdNotFound ");
- if (hd_error & ABRT_ERR) printk("DriveStatusError ");
- if (hd_error & TRK0_ERR) printk("TrackZeroNotFound ");
- if (hd_error & MARK_ERR) printk("AddrMarkNotFound ");
- printk("}");
- if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
- printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
- inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
- if (CURRENT)
- printk(", sector=%ld", CURRENT->sector);
- }
- printk("\n");
- }
-#else
- printk("%s: %s: status=0x%02x.\n", name, msg, stat & 0xff);
- if ((stat & ERR_STAT) == 0) {
- hd_error = 0;
- } else {
- hd_error = inb(HD_ERROR);
- printk("%s: %s: error=0x%02x.\n", name, msg, hd_error & 0xff);
- }
-#endif
-}
-
-static void check_status(void)
-{
- int i = inb_p(HD_STATUS);
-
- if (!OK_STATUS(i)) {
- dump_status("check_status", i);
- bad_rw_intr();
- }
-}
-
-static int controller_busy(void)
-{
- int retries = 100000;
- unsigned char status;
-
- do {
- status = inb_p(HD_STATUS);
- } while ((status & BUSY_STAT) && --retries);
- return status;
-}
-
-static int status_ok(void)
-{
- unsigned char status = inb_p(HD_STATUS);
-
- if (status & BUSY_STAT)
- return 1; /* Ancient, but does it make sense??? */
- if (status & WRERR_STAT)
- return 0;
- if (!(status & READY_STAT))
- return 0;
- if (!(status & SEEK_STAT))
- return 0;
- return 1;
-}
-
-static int controller_ready(unsigned int drive, unsigned int head)
-{
- int retry = 100;
-
- do {
- if (controller_busy() & BUSY_STAT)
- return 0;
- outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
- if (status_ok())
- return 1;
- } while (--retry);
- return 0;
-}
-
-static void hd_out(struct hd_i_struct *disk,
- unsigned int nsect,
- unsigned int sect,
- unsigned int head,
- unsigned int cyl,
- unsigned int cmd,
- void (*intr_addr)(void))
-{
- unsigned short port;
-
-#if (HD_DELAY > 0)
- while (read_timer() - last_req < HD_DELAY)
- /* nothing */;
-#endif
- if (reset)
- return;
- if (!controller_ready(disk->unit, head)) {
- reset = 1;
- return;
- }
- SET_HANDLER(intr_addr);
- outb_p(disk->ctl, HD_CMD);
- port = HD_DATA;
- outb_p(disk->wpcom >> 2, ++port);
- outb_p(nsect, ++port);
- outb_p(sect, ++port);
- outb_p(cyl, ++port);
- outb_p(cyl >> 8, ++port);
- outb_p(0xA0 | (disk->unit << 4) | head, ++port);
- outb_p(cmd, ++port);
-}
-
-static void hd_request (void);
-
-static int drive_busy(void)
-{
- unsigned int i;
- unsigned char c;
-
- for (i = 0; i < 500000 ; i++) {
- c = inb_p(HD_STATUS);
- if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
- return 0;
- }
- dump_status("reset timed out", c);
- return 1;
-}
-
-static void reset_controller(void)
-{
- int i;
-
- outb_p(4, HD_CMD);
- for (i = 0; i < 1000; i++) barrier();
- outb_p(hd_info[0].ctl & 0x0f, HD_CMD);
- for (i = 0; i < 1000; i++) barrier();
- if (drive_busy())
- printk("hd: controller still busy\n");
- else if ((hd_error = inb(HD_ERROR)) != 1)
- printk("hd: controller reset failed: %02x\n", hd_error);
-}
-
-static void reset_hd(void)
-{
- static int i;
-
-repeat:
- if (reset) {
- reset = 0;
- i = -1;
- reset_controller();
- } else {
- check_status();
- if (reset)
- goto repeat;
- }
- if (++i < NR_HD) {
- struct hd_i_struct *disk = &hd_info[i];
- disk->special_op = disk->recalibrate = 1;
- hd_out(disk, disk->sect, disk->sect, disk->head-1,
- disk->cyl, WIN_SPECIFY, &reset_hd);
- if (reset)
- goto repeat;
- } else
- hd_request();
-}
-
-/*
- * Ok, don't know what to do with the unexpected interrupts: on some machines
- * doing a reset and a retry seems to result in an eternal loop. Right now I
- * ignore it, and just set the timeout.
- *
- * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
- * drive enters "idle", "standby", or "sleep" mode, so if the status looks
- * "good", we just ignore the interrupt completely.
- */
-static void unexpected_hd_interrupt(void)
-{
- unsigned int stat = inb_p(HD_STATUS);
-
- if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
- dump_status("unexpected interrupt", stat);
- SET_TIMER;
- }
-}
-
-/*
- * bad_rw_intr() now tries to be a bit smarter and does things
- * according to the error returned by the controller.
- * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
- */
-static void bad_rw_intr(void)
-{
- struct request *req = CURRENT;
- if (req != NULL) {
- struct hd_i_struct *disk = req->rq_disk->private_data;
- if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
- end_request(req, 0);
- disk->special_op = disk->recalibrate = 1;
- } else if (req->errors % RESET_FREQ == 0)
- reset = 1;
- else if ((hd_error & TRK0_ERR) || req->errors % RECAL_FREQ == 0)
- disk->special_op = disk->recalibrate = 1;
- /* Otherwise just retry */
- }
-}
-
-static inline int wait_DRQ(void)
-{
- int retries;
- int stat;
-
- for (retries = 0; retries < 100000; retries++) {
- stat = inb_p(HD_STATUS);
- if (stat & DRQ_STAT)
- return 0;
- }
- dump_status("wait_DRQ", stat);
- return -1;
-}
-
-static void read_intr(void)
-{
- struct request *req;
- int i, retries = 100000;
-
- do {
- i = (unsigned) inb_p(HD_STATUS);
- if (i & BUSY_STAT)
- continue;
- if (!OK_STATUS(i))
- break;
- if (i & DRQ_STAT)
- goto ok_to_read;
- } while (--retries > 0);
- dump_status("read_intr", i);
- bad_rw_intr();
- hd_request();
- return;
-ok_to_read:
- req = CURRENT;
- insw(HD_DATA, req->buffer, 256);
- req->sector++;
- req->buffer += 512;
- req->errors = 0;
- i = --req->nr_sectors;
- --req->current_nr_sectors;
-#ifdef DEBUG
- printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n",
- req->rq_disk->disk_name, req->sector, req->nr_sectors,
- req->buffer+512);
-#endif
- if (req->current_nr_sectors <= 0)
- end_request(req, 1);
- if (i > 0) {
- SET_HANDLER(&read_intr);
- return;
- }
- (void) inb_p(HD_STATUS);
-#if (HD_DELAY > 0)
- last_req = read_timer();
-#endif
- if (elv_next_request(QUEUE))
- hd_request();
- return;
-}
-
-static void write_intr(void)
-{
- struct request *req = CURRENT;
- int i;
- int retries = 100000;
-
- do {
- i = (unsigned) inb_p(HD_STATUS);
- if (i & BUSY_STAT)
- continue;
- if (!OK_STATUS(i))
- break;
- if ((req->nr_sectors <= 1) || (i & DRQ_STAT))
- goto ok_to_write;
- } while (--retries > 0);
- dump_status("write_intr", i);
- bad_rw_intr();
- hd_request();
- return;
-ok_to_write:
- req->sector++;
- i = --req->nr_sectors;
- --req->current_nr_sectors;
- req->buffer += 512;
- if (!i || (req->bio && req->current_nr_sectors <= 0))
- end_request(req, 1);
- if (i > 0) {
- SET_HANDLER(&write_intr);
- outsw(HD_DATA, req->buffer, 256);
- local_irq_enable();
- } else {
-#if (HD_DELAY > 0)
- last_req = read_timer();
-#endif
- hd_request();
- }
- return;
-}
-
-static void recal_intr(void)
-{
- check_status();
-#if (HD_DELAY > 0)
- last_req = read_timer();
-#endif
- hd_request();
-}
-
-/*
- * This is another of the error-routines I don't know what to do with. The
- * best idea seems to just set reset, and start all over again.
- */
-static void hd_times_out(unsigned long dummy)
-{
- char *name;
-
- do_hd = NULL;
-
- if (!CURRENT)
- return;
-
- disable_irq(HD_IRQ);
- local_irq_enable();
- reset = 1;
- name = CURRENT->rq_disk->disk_name;
- printk("%s: timeout\n", name);
- if (++CURRENT->errors >= MAX_ERRORS) {
-#ifdef DEBUG
- printk("%s: too many errors\n", name);
-#endif
- end_request(CURRENT, 0);
- }
- local_irq_disable();
- hd_request();
- enable_irq(HD_IRQ);
-}
-
-static int do_special_op(struct hd_i_struct *disk, struct request *req)
-{
- if (disk->recalibrate) {
- disk->recalibrate = 0;
- hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr);
- return reset;
- }
- if (disk->head > 16) {
- printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
- end_request(req, 0);
- }
- disk->special_op = 0;
- return 1;
-}
-
-/*
- * The driver enables interrupts as much as possible. In order to do this,
- * (a) the device-interrupt is disabled before entering hd_request(),
- * and (b) the timeout-interrupt is disabled before the sti().
- *
- * Interrupts are still masked (by default) whenever we are exchanging
- * data/cmds with a drive, because some drives seem to have very poor
- * tolerance for latency during I/O. The IDE driver has support to unmask
- * interrupts for non-broken hardware, so use that driver if required.
- */
-static void hd_request(void)
-{
- unsigned int block, nsect, sec, track, head, cyl;
- struct hd_i_struct *disk;
- struct request *req;
-
- if (do_hd)
- return;
-repeat:
- del_timer(&device_timer);
- local_irq_enable();
-
- req = CURRENT;
- if (!req) {
- do_hd = NULL;
- return;
- }
-
- if (reset) {
- local_irq_disable();
- reset_hd();
- return;
- }
- disk = req->rq_disk->private_data;
- block = req->sector;
- nsect = req->nr_sectors;
- if (block >= get_capacity(req->rq_disk) ||
- ((block+nsect) > get_capacity(req->rq_disk))) {
- printk("%s: bad access: block=%d, count=%d\n",
- req->rq_disk->disk_name, block, nsect);
- end_request(req, 0);
- goto repeat;
- }
-
- if (disk->special_op) {
- if (do_special_op(disk, req))
- goto repeat;
- return;
- }
- sec = block % disk->sect + 1;
- track = block / disk->sect;
- head = track % disk->head;
- cyl = track / disk->head;
-#ifdef DEBUG
- printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
- req->rq_disk->disk_name,
- req_data_dir(req) == READ ? "read" : "writ",
- cyl, head, sec, nsect, req->buffer);
-#endif
- if (blk_fs_request(req)) {
- switch (rq_data_dir(req)) {
- case READ:
- hd_out(disk, nsect, sec, head, cyl, WIN_READ,
- &read_intr);
- if (reset)
- goto repeat;
- break;
- case WRITE:
- hd_out(disk, nsect, sec, head, cyl, WIN_WRITE,
- &write_intr);
- if (reset)
- goto repeat;
- if (wait_DRQ()) {
- bad_rw_intr();
- goto repeat;
- }
- outsw(HD_DATA, req->buffer, 256);
- break;
- default:
- printk("unknown hd-command\n");
- end_request(req, 0);
- break;
- }
- }
-}
-
-static void do_hd_request(struct request_queue *q)
-{
- disable_irq(HD_IRQ);
- hd_request();
- enable_irq(HD_IRQ);
-}
-
-static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- struct hd_i_struct *disk = bdev->bd_disk->private_data;
-
- geo->heads = disk->head;
- geo->sectors = disk->sect;
- geo->cylinders = disk->cyl;
- return 0;
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-
-static irqreturn_t hd_interrupt(int irq, void *dev_id)
-{
- void (*handler)(void) = do_hd;
-
- do_hd = NULL;
- del_timer(&device_timer);
- if (!handler)
- handler = unexpected_hd_interrupt;
- handler();
- local_irq_enable();
- return IRQ_HANDLED;
-}
-
-static struct block_device_operations hd_fops = {
- .getgeo = hd_getgeo,
-};
-
-/*
- * This is the hard disk IRQ description. The IRQF_DISABLED in sa_flags
- * means we run the IRQ-handler with interrupts disabled: this is bad for
- * interrupt latency, but anything else has led to problems on some
- * machines.
- *
- * We enable interrupts in some of the routines after making sure it's
- * safe.
- */
-
-static int __init hd_init(void)
-{
- int drive;
-
- if (register_blkdev(MAJOR_NR, "hd"))
- return -1;
-
- hd_queue = blk_init_queue(do_hd_request, &hd_lock);
- if (!hd_queue) {
- unregister_blkdev(MAJOR_NR, "hd");
- return -ENOMEM;
- }
-
- blk_queue_max_sectors(hd_queue, 255);
- init_timer(&device_timer);
- device_timer.function = hd_times_out;
- blk_queue_hardsect_size(hd_queue, 512);
-
- if (!NR_HD) {
- /*
- * We don't know anything about the drive. This means
- * that you *MUST* specify the drive parameters to the
- * kernel yourself.
- *
- * If we were on an i386, we used to read this info from
- * the BIOS or CMOS. This doesn't work all that well,
- * since this assumes that this is a primary or secondary
- * drive, and if we're using this legacy driver, it's
- * probably an auxilliary controller added to recover
- * legacy data off an ST-506 drive. Either way, it's
- * definitely safest to have the user explicitly specify
- * the information.
- */
- printk("hd: no drives specified - use hd=cyl,head,sectors"
- " on kernel command line\n");
- goto out;
- }
-
- for (drive = 0 ; drive < NR_HD ; drive++) {
- struct gendisk *disk = alloc_disk(64);
- struct hd_i_struct *p = &hd_info[drive];
- if (!disk)
- goto Enomem;
- disk->major = MAJOR_NR;
- disk->first_minor = drive << 6;
- disk->fops = &hd_fops;
- sprintf(disk->disk_name, "hd%c", 'a'+drive);
- disk->private_data = p;
- set_capacity(disk, p->head * p->sect * p->cyl);
- disk->queue = hd_queue;
- p->unit = drive;
- hd_gendisk[drive] = disk;
- printk("%s: %luMB, CHS=%d/%d/%d\n",
- disk->disk_name, (unsigned long)get_capacity(disk)/2048,
- p->cyl, p->head, p->sect);
- }
-
- if (request_irq(HD_IRQ, hd_interrupt, IRQF_DISABLED, "hd", NULL)) {
- printk("hd: unable to get IRQ%d for the hard disk driver\n",
- HD_IRQ);
- goto out1;
- }
- if (!request_region(HD_DATA, 8, "hd")) {
- printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
- goto out2;
- }
- if (!request_region(HD_CMD, 1, "hd(cmd)")) {
- printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
- goto out3;
- }
-
- /* Let them fly */
- for (drive = 0; drive < NR_HD; drive++)
- add_disk(hd_gendisk[drive]);
-
- return 0;
-
-out3:
- release_region(HD_DATA, 8);
-out2:
- free_irq(HD_IRQ, NULL);
-out1:
- for (drive = 0; drive < NR_HD; drive++)
- put_disk(hd_gendisk[drive]);
- NR_HD = 0;
-out:
- del_timer(&device_timer);
- unregister_blkdev(MAJOR_NR, "hd");
- blk_cleanup_queue(hd_queue);
- return -1;
-Enomem:
- while (drive--)
- put_disk(hd_gendisk[drive]);
- goto out;
-}
-
-static int __init parse_hd_setup(char *line)
-{
- int ints[6];
-
- (void) get_options(line, ARRAY_SIZE(ints), ints);
- hd_setup(NULL, ints);
-
- return 1;
-}
-__setup("hd=", parse_hd_setup);
-
-module_init(hd_init);
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index 4fe516df9f7..c7e5c2246b7 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -3,34 +3,12 @@
*/
/*
- *
- * Version 0.01 Initial version hacked out of ide.c
- *
- * Version 0.02 Added support for PIO modes, auto-tune
- *
- * Version 0.03 Some cleanups
- *
- * Version 0.05 PIO mode cycle timings auto-tune using bus-speed
- *
- * Version 0.06 Prefetch mode now defaults no OFF. To set
- * prefetch mode OFF/ON use "hdparm -p8/-p9".
- * Unmask irq is disabled when prefetch mode
- * is enabled.
- *
- * Version 0.07 Trying to fix CD-ROM detection problem.
- * "Prefetch" mode bit OFF for ide disks and
- * ON for anything else.
- *
- * Version 0.08 Need to force prefetch for CDs and other non-disk
- * devices. (not sure which devices exactly need
- * prefetch)
- *
* HT-6560B EIDE-controller support
* To activate controller support use kernel parameter "ide0=ht6560b".
* Use hdparm utility to enable PIO mode support.
*
* Author: Mikko Ala-Fossi <maf@iki.fi>
- * Jan Evert van Grootheest <janevert@caiway.nl>
+ * Jan Evert van Grootheest <j.e.van.grootheest@caiway.nl>
*
* Try: http://www.maf.iki.fi/~maf/ht6560b/
*/
@@ -46,7 +24,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -143,7 +120,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
* Need to enforce prefetch sometimes because otherwise
* it'll hang (hard).
*/
- if (drive->media != ide_disk || !drive->present)
+ if (drive->media != ide_disk ||
+ (drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
select |= HT_PREFETCH_MODE;
if (select != current_select || timing != current_timing) {
@@ -212,10 +190,11 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
{
int active_time, recovery_time;
int active_cycles, recovery_cycles;
- int bus_speed = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
+ int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
if (pio) {
unsigned int cycle_time;
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
cycle_time = ide_pio_cycle_time(drive, pio);
@@ -224,10 +203,8 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
* actual cycle time for recovery and activity
* according system bus speed.
*/
- active_time = ide_pio_timings[pio].active_time;
- recovery_time = cycle_time
- - active_time
- - ide_pio_timings[pio].setup_time;
+ active_time = t->active;
+ recovery_time = cycle_time - active_time - t->setup;
/*
* Cycle times should be Vesa bus cycles
*/
@@ -273,11 +250,11 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
*/
if (state) {
drive->drive_data |= t; /* enable prefetch mode */
- drive->no_unmask = 1;
- drive->unmask = 0;
+ drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
} else {
drive->drive_data &= ~t; /* disable prefetch mode */
- drive->no_unmask = 0;
+ drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
}
spin_unlock_irqrestore(&ht6560b_lock, flags);
@@ -311,16 +288,16 @@ 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)
+static void __init ht6560b_init_dev(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->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;
+ drive->drive_data = t;
}
static int probe_ht6560b;
@@ -329,7 +306,7 @@ module_param_named(probe, probe_ht6560b, bool, 0);
MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
static const struct ide_port_ops ht6560b_port_ops = {
- .port_init_devs = ht6560b_port_init_devs,
+ .init_dev = ht6560b_init_dev,
.set_pio_mode = ht6560b_set_pio_mode,
.selectproc = ht6560b_selectproc,
};
diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
index ecae916a338..9e85b1ec960 100644
--- a/drivers/ide/legacy/ide-4drives.c
+++ b/drivers/ide/legacy/ide-4drives.c
@@ -11,12 +11,25 @@ static int probe_4drives;
module_param_named(probe, probe_4drives, bool, 0);
MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
+static void ide_4drives_init_dev(ide_drive_t *drive)
+{
+ if (drive->hwif->channel)
+ drive->select ^= 0x20;
+}
+
+static const struct ide_port_ops ide_4drives_port_ops = {
+ .init_dev = ide_4drives_init_dev,
+};
+
+static const struct ide_port_info ide_4drives_port_info = {
+ .port_ops = &ide_4drives_port_ops,
+ .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA,
+};
+
static int __init ide_4drives_init(void)
{
- ide_hwif_t *hwif, *mate;
unsigned long base = 0x1f0, ctl = 0x3f6;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL };
if (probe_4drives == 0)
return -ENODEV;
@@ -40,29 +53,7 @@ static int __init ide_4drives_init(void)
hw.irq = 14;
hw.chipset = ide_4drives;
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
- idx[0] = hwif->index;
- }
-
- mate = ide_find_port();
- if (mate) {
- ide_init_port_hw(mate, &hw);
- mate->drives[0].select.all ^= 0x20;
- mate->drives[1].select.all ^= 0x20;
- idx[1] = mate->index;
-
- if (hwif) {
- hwif->mate = mate;
- mate->mate = hwif;
- hwif->serialized = mate->serialized = 1;
- }
- }
-
- ide_device_add(idx, NULL);
-
- return 0;
+ return ide_host_add(&ide_4drives_port_info, hws, NULL);
}
module_init(ide_4drives_init);
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 3381424d70a..cb199c815b5 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -38,7 +38,6 @@
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/ide.h>
-#include <linux/hdreg.h>
#include <linux/major.h>
#include <linux/delay.h>
#include <asm/io.h>
@@ -63,11 +62,9 @@ MODULE_LICENSE("Dual MPL/GPL");
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
-#ifdef PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#ifdef CONFIG_PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, 0);
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -76,7 +73,7 @@ static char *version =
typedef struct ide_info_t {
struct pcmcia_device *p_dev;
- ide_hwif_t *hwif;
+ struct ide_host *host;
int ndev;
dev_node_t node;
} ide_info_t;
@@ -134,7 +131,7 @@ static int ide_probe(struct pcmcia_device *link)
static void ide_detach(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- ide_hwif_t *hwif = info->hwif;
+ ide_hwif_t *hwif = info->host->ports[0];
unsigned long data_addr, ctl_addr;
DEBUG(0, "ide_detach(0x%p)\n", link);
@@ -154,13 +151,18 @@ static const struct ide_port_ops idecs_port_ops = {
.quirkproc = ide_undecoded_slave,
};
-static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
+static const struct ide_port_info idecs_port_info = {
+ .port_ops = &idecs_port_ops,
+ .host_flags = IDE_HFLAG_NO_DMA,
+};
+
+static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
unsigned long irq, struct pcmcia_device *handle)
{
+ struct ide_host *host;
ide_hwif_t *hwif;
- hw_regs_t hw;
- int i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ int i, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!request_region(io, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -181,32 +183,24 @@ static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
hw.chipset = ide_pci;
hw.dev = &handle->dev;
- hwif = ide_find_port();
- if (hwif == NULL)
+ rc = ide_host_add(&idecs_port_info, hws, &host);
+ if (rc)
goto out_release;
- i = hwif->index;
-
- ide_init_port_data(hwif, i);
- ide_init_port_hw(hwif, &hw);
- hwif->port_ops = &idecs_port_ops;
-
- idx[0] = i;
-
- ide_device_add(idx, NULL);
+ hwif = host->ports[0];
if (hwif->present)
- return hwif;
+ return host;
/* retry registration in case device is still spinning up */
for (i = 0; i < 10; i++) {
msleep(100);
ide_port_scan(hwif);
if (hwif->present)
- return hwif;
+ return host;
}
- return hwif;
+ return host;
out_release:
release_region(ctl, 1);
@@ -225,103 +219,91 @@ out_release:
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+struct pcmcia_config_check {
+ unsigned long ctl_base;
+ int skip_vcc;
+ int is_kme;
+};
+
+static int pcmcia_check_one_config(struct pcmcia_device *pdev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ struct pcmcia_config_check *stk = priv_data;
+
+ /* Check for matching Vcc, unless we're desperate */
+ if (!stk->skip_vcc) {
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ pdev->conf.ConfigIndex = cfg->index;
+ pdev->io.BasePort1 = io->win[0].base;
+ pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ if (io->nwin == 2) {
+ pdev->io.NumPorts1 = 8;
+ pdev->io.BasePort2 = io->win[1].base;
+ pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
+ if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ return -ENODEV;
+ stk->ctl_base = pdev->io.BasePort2;
+ } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
+ pdev->io.NumPorts1 = io->win[0].len;
+ pdev->io.NumPorts2 = 0;
+ if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ return -ENODEV;
+ stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+ } else
+ return -ENODEV;
+ /* If we've got this far, we're done */
+ return 0;
+ }
+ return -ENODEV;
+}
+
static int ide_config(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- tuple_t tuple;
- struct {
- u_short buf[128];
- cisparse_t parse;
- config_info_t conf;
- cistpl_cftable_entry_t dflt;
- } *stk = NULL;
- cistpl_cftable_entry_t *cfg;
- int pass, last_ret = 0, last_fn = 0, is_kme = 0;
+ struct pcmcia_config_check *stk = NULL;
+ int last_ret = 0, last_fn = 0, is_kme = 0;
unsigned long io_base, ctl_base;
- ide_hwif_t *hwif;
+ struct ide_host *host;
DEBUG(0, "ide_config(0x%p)\n", link);
- stk = kzalloc(sizeof(*stk), GFP_KERNEL);
- if (!stk) goto err_mem;
- cfg = &stk->parse.cftable_entry;
-
- tuple.TupleData = (cisdata_t *)&stk->buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
-
is_kme = ((link->manf_id == MANFID_KME) &&
((link->card_id == PRODID_KME_KXLC005_A) ||
(link->card_id == PRODID_KME_KXLC005_B)));
- /* Not sure if this is right... look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
-
- pass = io_base = ctl_base = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
- if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
-
- /* Check for matching Vcc, unless we're desperate */
- if (!pass) {
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
- goto next_entry;
- } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
- goto next_entry;
- }
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
- link->conf.ConfigIndex = cfg->index;
- link->io.BasePort1 = io->win[0].base;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- if (io->nwin == 2) {
- link->io.NumPorts1 = 8;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = (is_kme) ? 2 : 1;
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- io_base = link->io.BasePort1;
- ctl_base = link->io.BasePort2;
- } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
- link->io.NumPorts1 = io->win[0].len;
- link->io.NumPorts2 = 0;
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- io_base = link->io.BasePort1;
- ctl_base = link->io.BasePort1 + 0x0e;
- } else goto next_entry;
- /* If we've got this far, we're done */
- break;
- }
-
- next_entry:
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
- memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
- if (pass) {
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- memset(&stk->dflt, 0, sizeof(stk->dflt));
- pass++;
- }
+ stk = kzalloc(sizeof(*stk), GFP_KERNEL);
+ if (!stk)
+ goto err_mem;
+ stk->is_kme = is_kme;
+ stk->skip_vcc = io_base = ctl_base = 0;
+
+ if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
+ stk->skip_vcc = 1;
+ if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+ goto failed; /* No suitable config found */
}
+ io_base = link->io.BasePort1;
+ ctl_base = stk->ctl_base;
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
@@ -333,21 +315,21 @@ static int ide_config(struct pcmcia_device *link)
if (is_kme)
outb(0x81, ctl_base+1);
- hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
- if (hwif == NULL && link->io.NumPorts1 == 0x20) {
+ host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
+ if (host == NULL && link->io.NumPorts1 == 0x20) {
outb(0x02, ctl_base + 0x10);
- hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
+ host = idecs_register(io_base + 0x10, ctl_base + 0x10,
link->irq.AssignedIRQ, link);
}
- if (hwif == NULL)
+ if (host == NULL)
goto failed;
info->ndev = 1;
- sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2);
- info->node.major = hwif->major;
+ sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
+ info->node.major = host->ports[0]->major;
info->node.minor = 0;
- info->hwif = hwif;
+ info->host = host;
link->dev_node = &info->node;
printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
@@ -375,18 +357,18 @@ failed:
======================================================================*/
-void ide_release(struct pcmcia_device *link)
+static void ide_release(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- ide_hwif_t *hwif = info->hwif;
+ struct ide_host *host = info->host;
DEBUG(0, "ide_release(0x%p)\n", link);
- if (info->ndev) {
+ if (info->ndev)
/* FIXME: if this fails we need to queue the cleanup somehow
-- need to investigate the required PCMCIA magic */
- ide_unregister(hwif);
- }
+ ide_host_remove(host);
+
info->ndev = 0;
pcmcia_disable_device(link);
@@ -409,8 +391,10 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */
+ PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index d3bc3f24e05..051b4ab0f35 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -44,16 +44,19 @@ static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
hw->chipset = ide_generic;
}
+static const struct ide_port_info platform_ide_port_info = {
+ .host_flags = IDE_HFLAG_NO_DMA,
+};
+
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;
+ struct ide_host *host;
+ int ret = 0, mmio = 0;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ struct ide_port_info d = platform_ide_port_info;
pdata = pdev->dev.platform_data;
@@ -89,28 +92,18 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
res_alt->start, res_alt->end - res_alt->start + 1);
}
- hwif = ide_find_port();
- if (!hwif) {
- ret = -ENODEV;
- goto out;
- }
-
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)
+ d.host_flags |= IDE_HFLAG_MMIO;
- if (mmio) {
- hwif->host_flags = IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
- }
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
+ ret = ide_host_add(&d, hws, &host);
+ if (ret)
+ goto out;
- platform_set_drvdata(pdev, hwif);
+ platform_set_drvdata(pdev, host);
return 0;
@@ -120,9 +113,9 @@ out:
static int __devexit plat_ide_remove(struct platform_device *pdev)
{
- ide_hwif_t *hwif = pdev->dev.driver_data;
+ struct ide_host *host = pdev->dev.driver_data;
- ide_unregister(hwif);
+ ide_host_remove(host);
return 0;
}
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index 2e84290d0bc..43f97cc1d30 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -15,7 +15,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/delay.h>
#include <linux/ide.h>
@@ -91,11 +90,10 @@ static const char *mac_ide_name[] =
static int __init macide_init(void)
{
- ide_hwif_t *hwif;
ide_ack_intr_t *ack_intr;
unsigned long base;
int irq;
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!MACH_IS_MAC)
return -ENODEV;
@@ -125,18 +123,7 @@ static int __init macide_init(void)
macide_setup_ports(&hw, base, irq, ack_intr);
- hwif = ide_find_port();
- 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;
+ return ide_host_add(NULL, hws, NULL);
}
module_init(macide_init);
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index 8ff6e2d2083..4af4a8ce4cd 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -14,8 +14,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-
#include <linux/ide.h>
/*
@@ -96,6 +94,27 @@ static void q40ide_output_data(ide_drive_t *drive, struct request *rq,
outsw_swapw(data_addr, buf, (len + 1) / 2);
}
+/* Q40 has a byte-swapped IDE interface */
+static const struct ide_tp_ops q40ide_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = q40ide_input_data,
+ .output_data = q40ide_output_data,
+};
+
+static const struct ide_port_info q40ide_port_info = {
+ .tp_ops = &q40ide_tp_ops,
+ .host_flags = IDE_HFLAG_NO_DMA,
+};
+
/*
* the static array is needed to have the name reported in /proc/ioports,
* hwif->name unfortunately isn't available yet
@@ -111,9 +130,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
static int __init q40ide_init(void)
{
int i;
- ide_hwif_t *hwif;
- const char *name;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (!MACH_IS_Q40)
return -ENODEV;
@@ -121,9 +138,8 @@ static int __init q40ide_init(void)
printk(KERN_INFO "ide: Q40 IDE controller\n");
for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
- hw_regs_t hw;
+ const char *name = q40_ide_names[i];
- name = q40_ide_names[i];
if (!request_region(pcide_bases[i], 8, name)) {
printk("could not reserve ports %lx-%lx for %s\n",
pcide_bases[i],pcide_bases[i]+8,name);
@@ -135,27 +151,13 @@ static int __init q40ide_init(void)
release_region(pcide_bases[i], 8);
continue;
}
- q40_ide_setup_ports(&hw, pcide_bases[i],
- NULL,
-// m68kide_iops,
+ q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL,
q40ide_default_irq(pcide_bases[i]));
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_data(hwif, hwif->index);
- ide_init_port_hw(hwif, &hw);
-
- /* Q40 has a byte-swapped IDE interface */
- hwif->input_data = q40ide_input_data;
- hwif->output_data = q40ide_output_data;
-
- idx[i] = hwif->index;
- }
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
-
- return 0;
+ return ide_host_add(&q40ide_port_info, hws, NULL);
}
module_init(q40ide_init);
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
index 6424af15432..bc27c7aba93 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/legacy/qd65xx.c
@@ -27,7 +27,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/system.h>
@@ -110,7 +109,7 @@ static void qd65xx_select(ide_drive_t *drive)
static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
{
- int clk = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
+ int clk = ide_vlb_clk ? ide_vlb_clk : 50;
u8 act_cyc, rec_cyc;
if (clk <= 33) {
@@ -132,7 +131,7 @@ static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery
static u8 qd6580_compute_timing (int active_time, int recovery_time)
{
- int clk = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
+ int clk = ide_vlb_clk ? ide_vlb_clk : 50;
u8 act_cyc, rec_cyc;
act_cyc = 17 - IDE_IN(active_time * clk / 1000 + 1, 2, 17);
@@ -151,12 +150,14 @@ static int qd_find_disk_type (ide_drive_t *drive,
int *active_time, int *recovery_time)
{
struct qd65xx_timing_s *p;
- char model[40];
+ char *m = (char *)&drive->id[ATA_ID_PROD];
+ char model[ATA_ID_PROD_LEN];
- if (!*drive->id->model) return 0;
+ if (*m == 0)
+ return 0;
- strncpy(model,drive->id->model,40);
- ide_fixstring(model,40,1); /* byte-swap */
+ strncpy(model, m, ATA_ID_PROD_LEN);
+ ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */
for (p = qd65xx_timing ; p->offset != -1 ; p++) {
if (!strncmp(p->model, model+p->offset, 4)) {
@@ -185,20 +186,20 @@ static void qd_set_timing (ide_drive_t *drive, u8 timing)
static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
+ u16 *id = drive->id;
int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */
/*
* FIXME: use "pio" value
*/
- if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)
- && drive->id->tPIO && (drive->id->field_valid & 0x02)
- && drive->id->eide_pio >= 240) {
-
+ if (!qd_find_disk_type(drive, &active_time, &recovery_time) &&
+ (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) &&
+ id[ATA_ID_EIDE_PIO] >= 240) {
printk(KERN_INFO "%s: PIO mode%d\n", drive->name,
- drive->id->tPIO);
+ id[ATA_ID_OLD_PIO_MODES] & 0xff);
active_time = 110;
- recovery_time = drive->id->eide_pio - 120;
+ recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120;
}
qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time));
@@ -207,6 +208,7 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = drive->hwif;
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
unsigned int cycle_time;
int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */
@@ -236,7 +238,7 @@ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
active_time = 110;
recovery_time = cycle_time - 120;
} else {
- active_time = ide_pio_timings[pio].active_time;
+ active_time = t->active;
recovery_time = cycle_time - active_time;
}
}
@@ -281,17 +283,18 @@ static int __init qd_testreg(int port)
return (readreg != QD_TESTVAL);
}
-static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
+static void __init qd6500_init_dev(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
u8 base = (hwif->config_data & 0xff00) >> 8;
u8 config = QD_CONFIG(hwif);
- hwif->drives[0].drive_data = QD6500_DEF_DATA;
- hwif->drives[1].drive_data = QD6500_DEF_DATA;
+ drive->drive_data = QD6500_DEF_DATA;
}
-static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
+static void __init qd6580_init_dev(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
u16 t1, t2;
u8 base = (hwif->config_data & 0xff00) >> 8;
u8 config = QD_CONFIG(hwif);
@@ -302,18 +305,17 @@ static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
} else
t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
- hwif->drives[0].drive_data = t1;
- hwif->drives[1].drive_data = t2;
+ drive->drive_data = (drive->dn & 1) ? t2 : t1;
}
static const struct ide_port_ops qd6500_port_ops = {
- .port_init_devs = qd6500_port_init_devs,
+ .init_dev = qd6500_init_dev,
.set_pio_mode = qd6500_set_pio_mode,
.selectproc = qd65xx_select,
};
static const struct ide_port_ops qd6580_port_ops = {
- .port_init_devs = qd6580_port_init_devs,
+ .init_dev = qd6580_init_dev,
.set_pio_mode = qd6580_set_pio_mode,
.selectproc = qd65xx_select,
};
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
index b54a14a5775..1da076e0c91 100644
--- a/drivers/ide/legacy/umc8672.c
+++ b/drivers/ide/legacy/umc8672.c
@@ -45,7 +45,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile
index 677c7b2bac9..5873fa0b876 100644
--- a/drivers/ide/mips/Makefile
+++ b/drivers/ide/mips/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o
obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o
EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index 1a6c27b3249..0ec8fd1e4dc 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -213,10 +213,8 @@ static int auide_build_dmatable(ide_drive_t *drive)
{
int i, iswrite, count = 0;
ide_hwif_t *hwif = HWIF(drive);
-
struct request *rq = HWGROUP(drive)->rq;
-
- _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
+ _auide_hwif *ahwif = &auide_hwif;
struct scatterlist *sg;
iswrite = (rq_data_dir(rq) == WRITE);
@@ -324,11 +322,7 @@ static int auide_dma_setup(ide_drive_t *drive)
}
static int auide_dma_test_irq(ide_drive_t *drive)
-{
- if (drive->waiting_for_dma == 0)
- printk(KERN_WARNING "%s: ide_dma_test_irq \
- called while not waiting\n", drive->name);
-
+{
/* If dbdma didn't execute the STOP command yet, the
* active bit is still set
*/
@@ -346,11 +340,6 @@ static void auide_dma_host_set(ide_drive_t *drive, int on)
{
}
-static void auide_dma_lost_irq(ide_drive_t *drive)
-{
- printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-}
-
static void auide_ddma_tx_callback(int irq, void *param)
{
_auide_hwif *ahwif = (_auide_hwif*)param;
@@ -377,18 +366,6 @@ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 de
}
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-static void auide_dma_timeout(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
-
- printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-
- if (auide_dma_test_irq(drive))
- return;
-
- auide_dma_end(drive);
-}
-
static const struct ide_dma_ops au1xxx_dma_ops = {
.dma_host_set = auide_dma_host_set,
.dma_setup = auide_dma_setup,
@@ -396,13 +373,13 @@ static const struct ide_dma_ops au1xxx_dma_ops = {
.dma_start = auide_dma_start,
.dma_end = auide_dma_end,
.dma_test_irq = auide_dma_test_irq,
- .dma_lost_irq = auide_dma_lost_irq,
- .dma_timeout = auide_dma_timeout,
+ .dma_lost_irq = ide_dma_lost_irq,
+ .dma_timeout = ide_dma_timeout,
};
static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
{
- _auide_hwif *auide = (_auide_hwif *)hwif->hwif_data;
+ _auide_hwif *auide = &auide_hwif;
dbdev_tab_t source_dev_tab, target_dev_tab;
u32 dev_id, tsize, devwidth, flags;
@@ -450,10 +427,9 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
NUM_DESCRIPTORS);
auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
NUM_DESCRIPTORS);
-
- hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev,
- PRD_ENTRIES * PRD_BYTES, /* 1 Page */
- &hwif->dmatable_dma, GFP_KERNEL);
+
+ /* FIXME: check return value */
+ (void)ide_allocate_dma_engine(hwif);
au1xxx_dbdma_start( auide->tx_chan );
au1xxx_dbdma_start( auide->rx_chan );
@@ -463,7 +439,7 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
#else
static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
{
- _auide_hwif *auide = (_auide_hwif *)hwif->hwif_data;
+ _auide_hwif *auide = &auide_hwif;
dbdev_tab_t source_dev_tab;
int flags;
@@ -521,6 +497,23 @@ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
*ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT);
}
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+static const struct ide_tp_ops au1xxx_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = au1xxx_input_data,
+ .output_data = au1xxx_output_data,
+};
+#endif
+
static const struct ide_port_ops au1xxx_port_ops = {
.set_pio_mode = au1xxx_set_pio_mode,
.set_dma_mode = auide_set_dma_mode,
@@ -528,6 +521,9 @@ static const struct ide_port_ops au1xxx_port_ops = {
static const struct ide_port_info au1xxx_port_info = {
.init_dma = auide_ddma_init,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+ .tp_ops = &au1xxx_tp_ops,
+#endif
.port_ops = &au1xxx_port_ops,
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
.dma_ops = &au1xxx_dma_ops,
@@ -545,11 +541,10 @@ static int au_ide_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
_auide_hwif *ahwif = &auide_hwif;
- ide_hwif_t *hwif;
struct resource *res;
+ struct ide_host *host;
int ret = 0;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
char *mode = "MWDMA2";
@@ -586,41 +581,19 @@ static int au_ide_probe(struct device *dev)
goto out;
}
- hwif = ide_find_port();
- if (hwif == NULL) {
- ret = -ENOENT;
- goto out;
- }
-
memset(&hw, 0, sizeof(hw));
auide_setup_ports(&hw, ahwif);
hw.irq = ahwif->irq;
hw.dev = dev;
hw.chipset = ide_au1xxx;
- ide_init_port_hw(hwif, &hw);
-
- hwif->dev = dev;
-
- /* If the user has selected DDMA assisted copies,
- then set up a few local I/O function entry points
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
- hwif->input_data = au1xxx_input_data;
- hwif->output_data = au1xxx_output_data;
-#endif
- hwif->select_data = 0; /* no chipset-specific code */
- hwif->config_data = 0; /* no chipset-specific code */
-
- auide_hwif.hwif = hwif;
- hwif->hwif_data = &auide_hwif;
-
- idx[0] = hwif->index;
+ ret = ide_host_add(&au1xxx_port_info, hws, &host);
+ if (ret)
+ goto out;
- ide_device_add(idx, &au1xxx_port_info);
+ auide_hwif.hwif = host->ports[0];
- dev_set_drvdata(dev, hwif);
+ dev_set_drvdata(dev, host);
printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
@@ -632,10 +605,10 @@ static int au_ide_remove(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct resource *res;
- ide_hwif_t *hwif = dev_get_drvdata(dev);
+ struct ide_host *host = dev_get_drvdata(dev);
_auide_hwif *ahwif = &auide_hwif;
- ide_unregister(hwif);
+ ide_host_remove(host);
iounmap((void *)ahwif->regbase);
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
deleted file mode 100644
index 52fee3d2771..00000000000
--- a/drivers/ide/mips/swarm.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved.
- * Author: Maciej W. Rozycki <macro@mips.com>
- * Copyright (c) 2006, 2008 Maciej W. Rozycki
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- * Derived loosely from ide-pmac.c, so:
- * Copyright (C) 1998 Paul Mackerras.
- * Copyright (C) 1995-1998 Mark Lord
- */
-
-/*
- * Boards with SiByte processors so far have supported IDE devices via
- * the Generic Bus, PCI bus, and built-in PCMCIA interface. In all
- * cases, byte-swapping must be avoided for these devices (whereas
- * other PCI devices, for example, will require swapping). Any
- * SiByte-targetted kernel including IDE support will include this
- * file. Probing of a Generic Bus for an IDE device is controlled by
- * the definition of "SIBYTE_HAVE_IDE", which is provided by
- * <asm/sibyte/board.h> for Broadcom boards.
- */
-
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-
-#include <asm/io.h>
-
-#include <asm/sibyte/board.h>
-#include <asm/sibyte/sb1250_genbus.h>
-#include <asm/sibyte/sb1250_regs.h>
-
-#define DRV_NAME "ide-swarm"
-
-static char swarm_ide_string[] = DRV_NAME;
-
-static struct resource swarm_ide_resource = {
- .name = "SWARM GenBus IDE",
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device *swarm_ide_dev;
-
-/*
- * swarm_ide_probe - if the board header indicates the existence of
- * Generic Bus IDE, allocate a HWIF for it.
- */
-static int __devinit swarm_ide_probe(struct device *dev)
-{
- ide_hwif_t *hwif;
- u8 __iomem *base;
- phys_t offset, size;
- hw_regs_t hw;
- int i;
- u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
-
- if (!SIBYTE_HAVE_IDE)
- return -ENODEV;
-
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR DRV_NAME ": no free slot for interface\n");
- return -ENOMEM;
- }
-
- base = ioremap(A_IO_EXT_BASE, 0x800);
- offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
- size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
- iounmap(base);
-
- offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE;
- size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE;
- if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) {
- printk(KERN_INFO DRV_NAME
- ": IDE interface at GenBus disabled\n");
- return -EBUSY;
- }
-
- printk(KERN_INFO DRV_NAME ": IDE interface at GenBus slot %i\n",
- IDE_CS);
-
- swarm_ide_resource.start = offset;
- swarm_ide_resource.end = offset + size - 1;
- if (request_resource(&iomem_resource, &swarm_ide_resource)) {
- printk(KERN_ERR DRV_NAME
- ": can't request I/O memory resource\n");
- return -EBUSY;
- }
-
- base = ioremap(offset, size);
-
- /* Setup MMIO ops. */
- hwif->host_flags = IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
-
- for (i = 0; i <= 7; i++)
- hw.io_ports_array[i] =
- (unsigned long)(base + ((0x1f0 + i) << 5));
- hw.io_ports.ctl_addr =
- (unsigned long)(base + (0x3f6 << 5));
- hw.irq = K_INT_GB_IDE;
- hw.chipset = ide_generic;
-
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
-
- dev_set_drvdata(dev, hwif);
-
- return 0;
-}
-
-static struct device_driver swarm_ide_driver = {
- .name = swarm_ide_string,
- .bus = &platform_bus_type,
- .probe = swarm_ide_probe,
-};
-
-static void swarm_ide_platform_release(struct device *device)
-{
- struct platform_device *pldev;
-
- /* free device */
- pldev = to_platform_device(device);
- kfree(pldev);
-}
-
-static int __devinit swarm_ide_init_module(void)
-{
- struct platform_device *pldev;
- int err;
-
- printk(KERN_INFO "SWARM IDE driver\n");
-
- if (driver_register(&swarm_ide_driver)) {
- printk(KERN_ERR "Driver registration failed\n");
- err = -ENODEV;
- goto out;
- }
-
- if (!(pldev = kzalloc(sizeof (*pldev), GFP_KERNEL))) {
- err = -ENOMEM;
- goto out_unregister_driver;
- }
-
- pldev->name = swarm_ide_string;
- pldev->id = 0;
- pldev->dev.release = swarm_ide_platform_release;
-
- if (platform_device_register(pldev)) {
- err = -ENODEV;
- goto out_free_pldev;
- }
-
- if (!pldev->dev.driver) {
- /*
- * The driver was not bound to this device, there was
- * no hardware at this address. Unregister it, as the
- * release fuction will take care of freeing the
- * allocated structure
- */
- platform_device_unregister (pldev);
- }
-
- swarm_ide_dev = pldev;
-
- return 0;
-
-out_free_pldev:
- kfree(pldev);
-
-out_unregister_driver:
- driver_unregister(&swarm_ide_driver);
-out:
- return err;
-}
-
-module_init(swarm_ide_init_module);
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index 7f46c224b7c..4142c698e0d 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -7,12 +7,13 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
+#define DRV_NAME "aec62xx"
+
struct chipset_bus_clock_list_entry {
u8 xfer_speed;
u8 chipset_settings;
@@ -59,10 +60,6 @@ static const struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
{ 0, 0x00, 0x00 }
};
-#define BUSCLOCK(D) \
- ((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D)))
-
-
/*
* TO DO: active tuning and correction of cards without a bios.
*/
@@ -88,6 +85,8 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
u16 d_conf = 0;
u8 ultra = 0, ultra_conf = 0;
u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
@@ -96,7 +95,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
local_irq_save(flags);
/* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */
pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
- tmp0 = pci_bus_clock_list(speed, BUSCLOCK(dev));
+ tmp0 = pci_bus_clock_list(speed, bus_clock);
d_conf = ((tmp0 & 0xf0) << 4) | (tmp0 & 0xf);
pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
@@ -104,7 +103,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
tmp2 = 0x00;
pci_read_config_byte(dev, 0x54, &ultra);
tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
- ultra_conf = pci_bus_clock_list_ultra(speed, BUSCLOCK(dev));
+ ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
pci_write_config_byte(dev, 0x54, tmp2);
local_irq_restore(flags);
@@ -114,7 +113,9 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- u8 unit = (drive->select.b.unit & 0x01);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
+ u8 unit = drive->dn & 1;
u8 tmp1 = 0, tmp2 = 0;
u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
unsigned long flags;
@@ -122,12 +123,12 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
local_irq_save(flags);
/* high 4-bits: Active, low 4-bits: Recovery */
pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
- drive_conf = pci_bus_clock_list(speed, BUSCLOCK(dev));
+ drive_conf = pci_bus_clock_list(speed, bus_clock);
pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
pci_read_config_byte(dev, (0x44|hwif->channel), &ultra);
tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
- ultra_conf = pci_bus_clock_list_ultra(speed, BUSCLOCK(dev));
+ ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
pci_write_config_byte(dev, (0x44|hwif->channel), tmp2);
local_irq_restore(flags);
@@ -138,15 +139,8 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
}
-static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_aec62xx(struct pci_dev *dev)
{
- int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
-
- if (bus_speed <= 33)
- pci_set_drvdata(dev, (void *) aec6xxx_33_base);
- else
- pci_set_drvdata(dev, (void *) aec6xxx_34_base);
-
/* These are necessary to get AEC6280 Macintosh cards to work */
if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
(dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
@@ -165,7 +159,7 @@ 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)
+static u8 atp86x_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
@@ -187,57 +181,56 @@ static const struct ide_port_ops atp86x_port_ops = {
};
static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "AEC6210",
+ { /* 0: AEC6210 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp850_port_ops,
.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,
.udma_mask = ATA_UDMA2,
- },{ /* 1 */
- .name = "AEC6260",
+ },
+ { /* 1: AEC6260 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.port_ops = &atp86x_port_ops,
.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,
.udma_mask = ATA_UDMA4,
- },{ /* 2 */
- .name = "AEC6260R",
+ },
+ { /* 2: AEC6260R */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_NON_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
- },{ /* 3 */
- .name = "AEC6280",
+ },
+ { /* 3: AEC6280 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.port_ops = &atp86x_port_ops,
.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,
- },{ /* 4 */
- .name = "AEC6280R",
+ },
+ { /* 4: AEC6280R */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp86x_port_ops,
.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,
@@ -259,10 +252,17 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
+ const struct chipset_bus_clock_list_entry *bus_clock;
struct ide_port_info d;
u8 idx = id->driver_data;
+ int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
int err;
+ if (bus_speed <= 33)
+ bus_clock = aec6xxx_33_base;
+ else
+ bus_clock = aec6xxx_34_base;
+
err = pci_enable_device(dev);
if (err)
return err;
@@ -273,18 +273,25 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi
unsigned long dma_base = pci_resource_start(dev, 4);
if (inb(dma_base + 2) & 0x10) {
- d.name = (idx == 4) ? "AEC6880R" : "AEC6880";
+ printk(KERN_INFO DRV_NAME " %s: AEC6880%s card detected"
+ "\n", pci_name(dev), (idx == 4) ? "R" : "");
d.udma_mask = ATA_UDMA6;
}
}
- err = ide_setup_pci_device(dev, &d);
+ err = ide_pci_init_one(dev, &d, (void *)bus_clock);
if (err)
pci_disable_device(dev);
return err;
}
+static void __devexit aec62xx_remove(struct pci_dev *dev)
+{
+ ide_pci_remove(dev);
+ pci_disable_device(dev);
+}
+
static const struct pci_device_id aec62xx_pci_tbl[] = {
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 },
@@ -295,18 +302,27 @@ static const struct pci_device_id aec62xx_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver aec62xx_pci_driver = {
.name = "AEC62xx_IDE",
.id_table = aec62xx_pci_tbl,
.probe = aec62xx_init_one,
+ .remove = __devexit_p(aec62xx_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init aec62xx_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&aec62xx_pci_driver);
+}
+
+static void __exit aec62xx_ide_exit(void)
+{
+ pci_unregister_driver(&aec62xx_pci_driver);
}
module_init(aec62xx_ide_init);
+module_exit(aec62xx_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for ARTOP AEC62xx IDE");
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index f2129d5e07f..daf9dce39e5 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -31,13 +31,14 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/dmi.h>
#include <asm/io.h>
+#define DRV_NAME "alim15x3"
+
/*
* Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking
* (this is DANGEROUS and could result in data corruption).
@@ -69,22 +70,19 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- int s_time, a_time, c_time;
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+ int s_time = t->setup, a_time = t->active, c_time = t->cycle;
u8 s_clc, a_clc, r_clc;
unsigned long flags;
- int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
+ int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
int port = hwif->channel ? 0x5c : 0x58;
int portFIFO = hwif->channel ? 0x55 : 0x54;
- u8 cd_dma_fifo = 0;
- int unit = drive->select.b.unit & 1;
+ u8 cd_dma_fifo = 0, unit = drive->dn & 1;
- s_time = ide_pio_timings[pio].setup_time;
- a_time = ide_pio_timings[pio].active_time;
if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
s_clc = 0;
if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
a_clc = 0;
- c_time = ide_pio_timings[pio].cycle_time;
if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
r_clc = 1;
@@ -113,7 +111,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
pci_write_config_byte(dev, port, s_clc);
- pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);
+ pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
local_irq_restore(flags);
}
@@ -134,8 +132,8 @@ static u8 ali_udma_filter(ide_drive_t *drive)
if (m5229_revision > 0x20 && m5229_revision < 0xC2) {
if (drive->media != ide_disk)
return 0;
- if (chip_is_1543c_e && strstr(drive->id->model, "WDC ") &&
- wdc_udma == 0)
+ if (wdc_udma == 0 && chip_is_1543c_e &&
+ strstr((char *)&drive->id[ATA_ID_PROD], "WDC "))
return 0;
}
@@ -155,7 +153,7 @@ static void ali_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 speed1 = speed;
- u8 unit = (drive->select.b.unit & 0x01);
+ u8 unit = drive->dn & 1;
u8 tmpbyte = 0x00;
int m5229_udma = (hwif->channel) ? 0x57 : 0x56;
@@ -209,13 +207,12 @@ static int ali15x3_dma_setup(ide_drive_t *drive)
/**
* init_chipset_ali15x3 - Initialise an ALi IDE controller
* @dev: PCI device
- * @name: Name of the controller
*
* This function initializes the ALI IDE controller and where
* appropriate also sets up the 1533 southbridge.
*/
-
-static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const char *name)
+
+static unsigned int init_chipset_ali15x3(struct pci_dev *dev)
{
unsigned long flags;
u8 tmpbyte;
@@ -372,7 +369,7 @@ static int ali_cable_override(struct pci_dev *pdev)
* FIXME: frobs bits that are not defined on newer ALi devicea
*/
-static u8 __devinit ali_cable_detect(ide_hwif_t *hwif)
+static u8 ali_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long flags;
@@ -473,7 +470,15 @@ static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long base = ide_pci_dma_base(hwif, d);
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
if (!hwif->channel)
@@ -485,7 +490,7 @@ static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
@@ -502,14 +507,14 @@ static const struct ide_dma_ops ali_dma_ops = {
.dma_setup = ali15x3_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
};
static const struct ide_port_info ali15x3_chipset __devinitdata = {
- .name = "ALI15X3",
+ .name = DRV_NAME,
.init_chipset = init_chipset_ali15x3,
.init_hwif = init_hwif_ali15x3,
.init_dma = init_dma_ali15x3,
@@ -559,7 +564,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
if (idx == 0)
d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
@@ -570,18 +575,27 @@ static const struct pci_device_id alim15x3_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver alim15x3_pci_driver = {
.name = "ALI15x3_IDE",
.id_table = alim15x3_pci_tbl,
.probe = alim15x3_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init ali15x3_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&alim15x3_pci_driver);
+}
+
+static void __exit ali15x3_ide_exit(void)
+{
+ return pci_unregister_driver(&alim15x3_pci_driver);
}
module_init(ali15x3_ide_init);
+module_exit(ali15x3_ide_exit);
MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index efcf54338be..81ec73134ed 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -21,7 +21,7 @@
#include <linux/init.h>
#include <linux/ide.h>
-#include "ide-timing.h"
+#define DRV_NAME "amd74xx"
enum {
AMD_IDE_CONFIG = 0x41,
@@ -53,20 +53,20 @@ static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
u8 t = 0, offset = amd_offset(dev);
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));
+ t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t);
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));
+ ((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1));
pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn),
- ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
+ ((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1));
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;
- case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
+ case ATA_UDMA2: t = timing->udma ? (0xc0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break;
+ case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 2, 10)]) : 0x03; break;
+ case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 1, 10)]) : 0x03; break;
+ case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 1, 15)]) : 0x03; break;
default: return;
}
@@ -92,7 +92,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
ide_timing_compute(drive, speed, &t, T, UT);
- if (peer->present) {
+ if (peer->dev_flags & IDE_DFLAG_PRESENT) {
ide_timing_compute(peer, peer->current_speed, &p, T, UT);
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
}
@@ -112,15 +112,13 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
amd_set_drive(drive, XFER_PIO_0 + pio);
}
-static void __devinit amd7409_cable_detect(struct pci_dev *dev,
- const char *name)
+static void amd7409_cable_detect(struct pci_dev *dev)
{
/* no host side cable detection */
amd_80w = 0x03;
}
-static void __devinit amd7411_cable_detect(struct pci_dev *dev,
- const char *name)
+static void amd7411_cable_detect(struct pci_dev *dev)
{
int i;
u32 u = 0;
@@ -131,9 +129,9 @@ static void __devinit amd7411_cable_detect(struct pci_dev *dev,
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);
+ printk(KERN_WARNING DRV_NAME " %s: BIOS didn't set "
+ "cable bits correctly. Enabling workaround.\n",
+ pci_name(dev));
amd_80w |= (1 << (1 - (i >> 4)));
}
}
@@ -142,8 +140,7 @@ static void __devinit amd7411_cable_detect(struct pci_dev *dev,
* The initialization callback. Initialize drive independent registers.
*/
-static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
- const char *name)
+static unsigned int init_chipset_amd74xx(struct pci_dev *dev)
{
u8 t = 0, offset = amd_offset(dev);
@@ -156,9 +153,9 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
; /* no UDMA > 2 */
else if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
- amd7409_cable_detect(dev, name);
+ amd7409_cable_detect(dev);
else
- amd7411_cable_detect(dev, name);
+ amd7411_cable_detect(dev);
/*
* Take care of prefetch & postwrite.
@@ -175,28 +172,10 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
t |= 0xf0;
pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
-/*
- * Determine the system bus clock.
- */
-
- amd_clock = (ide_pci_clk ? ide_pci_clk : system_bus_clock()) * 1000;
-
- switch (amd_clock) {
- case 33000: amd_clock = 33333; break;
- case 37000: amd_clock = 37500; break;
- case 41000: amd_clock = 41666; break;
- }
-
- if (amd_clock < 20000 || amd_clock > 50000) {
- printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
- name, amd_clock);
- amd_clock = 33333;
- }
-
return dev->irq;
}
-static u8 __devinit amd_cable_detect(ide_hwif_t *hwif)
+static u8 amd_cable_detect(ide_hwif_t *hwif)
{
if ((amd_80w >> hwif->channel) & 1)
return ATA_CBL_PATA80;
@@ -220,14 +199,13 @@ static const struct ide_port_ops amd_port_ops = {
#define IDE_HFLAGS_AMD \
(IDE_HFLAG_PIO_NO_BLACKLIST | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_POST_SET_MODE | \
IDE_HFLAG_IO_32BIT | \
IDE_HFLAG_UNMASK_IRQS)
-#define DECLARE_AMD_DEV(name_str, swdma, udma) \
+#define DECLARE_AMD_DEV(swdma, udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_amd74xx, \
.init_hwif = init_hwif_amd74xx, \
.enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
@@ -239,9 +217,9 @@ static const struct ide_port_ops amd_port_ops = {
.udma_mask = udma, \
}
-#define DECLARE_NV_DEV(name_str, udma) \
+#define DECLARE_NV_DEV(udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_amd74xx, \
.init_hwif = init_hwif_amd74xx, \
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
@@ -254,31 +232,15 @@ static const struct ide_port_ops amd_port_ops = {
}
static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
- /* 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),
+ /* 0: AMD7401 */ DECLARE_AMD_DEV(0x00, ATA_UDMA2),
+ /* 1: AMD7409 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
+ /* 2: AMD7411/7441 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
+ /* 3: AMD8111 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA6),
+
+ /* 4: NFORCE */ DECLARE_NV_DEV(ATA_UDMA5),
+ /* 5: >= NFORCE2 */ DECLARE_NV_DEV(ATA_UDMA6),
+
+ /* 6: AMD5536 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
};
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -295,63 +257,89 @@ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_
if (dev->revision <= 7)
d.swdma_mask = 0;
d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
- } else if (idx == 4) {
+ } else if (idx == 3) {
if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
d.udma_mask = ATA_UDMA5;
}
- 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]);
+ printk(KERN_INFO "%s %s: UDMA%s controller\n",
+ d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]);
- return ide_setup_pci_device(dev, &d);
+ /*
+ * Determine the system bus clock.
+ */
+ amd_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
+
+ switch (amd_clock) {
+ case 33000: amd_clock = 33333; break;
+ case 37000: amd_clock = 37500; break;
+ case 41000: amd_clock = 41666; break;
+ }
+
+ if (amd_clock < 20000 || amd_clock > 50000) {
+ printk(KERN_WARNING "%s: User given PCI clock speed impossible"
+ " (%d), using 33 MHz instead.\n",
+ d.name, amd_clock);
+ amd_clock = 33333;
+ }
+
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id amd74xx_pci_tbl[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7411), 2 },
- { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_OPUS_7441), 3 },
- { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_8111_IDE), 4 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE), 5 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE), 6 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE), 7 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_OPUS_7441), 2 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_8111_IDE), 3 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE), 4 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE), 5 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), 8 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), 5 },
#endif
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE), 9 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE), 10 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE), 5 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), 11 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), 12 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), 5 },
#endif
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE), 13 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE), 14 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 15 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 16 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 17 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 18 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 19 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 20 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 21 },
- { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 22 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 5 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 6 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver amd74xx_pci_driver = {
.name = "AMD_IDE",
.id_table = amd74xx_pci_tbl,
.probe = amd74xx_probe,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init amd74xx_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&amd74xx_pci_driver);
+}
+
+static void __exit amd74xx_ide_exit(void)
+{
+ pci_unregister_driver(&amd74xx_pci_driver);
}
module_init(amd74xx_ide_init);
+module_exit(amd74xx_ide_exit);
MODULE_AUTHOR("Vojtech Pavlik");
MODULE_DESCRIPTION("AMD PCI IDE driver");
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 8b637181681..b2735d28f5c 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -7,10 +7,11 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "atiixp"
+
#define ATIIXP_IDE_PIO_TIMING 0x40
#define ATIIXP_IDE_MDMA_TIMING 0x44
#define ATIIXP_IDE_PIO_CONTROL 0x48
@@ -117,7 +118,7 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
spin_unlock_irqrestore(&atiixp_lock, flags);
}
-static u8 __devinit atiixp_cable_detect(ide_hwif_t *hwif)
+static u8 atiixp_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
u8 udma_mode = 0, ch = hwif->channel;
@@ -137,16 +138,17 @@ static const struct ide_port_ops atiixp_port_ops = {
};
static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
- { /* 0 */
- .name = "ATIIXP",
+ { /* 0: IXP200/300/400/700 */
+ .name = DRV_NAME,
.enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
.port_ops = &atiixp_port_ops,
.host_flags = IDE_HFLAG_LEGACY_IRQS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 1 */
- .name = "SB600_PATA",
+ },
+ { /* 1: IXP600 */
+ .name = DRV_NAME,
.enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
.port_ops = &atiixp_port_ops,
.host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
@@ -167,7 +169,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &atiixp_pci_info[id->driver_data]);
+ return ide_pci_init_one(dev, &atiixp_pci_info[id->driver_data], NULL);
}
static const struct pci_device_id atiixp_pci_tbl[] = {
@@ -180,18 +182,27 @@ static const struct pci_device_id atiixp_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver atiixp_pci_driver = {
.name = "ATIIXP_IDE",
.id_table = atiixp_pci_tbl,
.probe = atiixp_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init atiixp_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&atiixp_pci_driver);
+}
+
+static void __exit atiixp_ide_exit(void)
+{
+ pci_unregister_driver(&atiixp_pci_driver);
}
module_init(atiixp_ide_init);
+module_exit(atiixp_ide_exit);
MODULE_AUTHOR("HUI YU");
MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index b38a1980dcd..e4306647d00 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -103,7 +103,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -181,11 +180,6 @@ static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
static DEFINE_SPINLOCK(cmd640_lock);
/*
- * These are initialized to point at the devices we control
- */
-static ide_hwif_t *cmd_hwif0, *cmd_hwif1;
-
-/*
* Interface to access cmd640x registers
*/
static unsigned int cmd640_key;
@@ -380,6 +374,21 @@ static void cmd640_dump_regs(void)
}
#endif
+static void __set_prefetch_mode(ide_drive_t *drive, int mode)
+{
+ if (mode) { /* want prefetch on? */
+#if CMD640_PREFETCH_MASKS
+ drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
+#endif
+ drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
+ } else {
+ drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
+ drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
+ drive->io_32bit = 0;
+ }
+}
+
#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED
/*
* Check whether prefetch is on for a drive,
@@ -389,19 +398,10 @@ static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
{
u8 b = get_cmd640_reg(prefetch_regs[index]);
- if (b & prefetch_masks[index]) { /* is prefetch off? */
- drive->no_unmask = 0;
- drive->no_io_32bit = 1;
- drive->io_32bit = 0;
- } else {
-#if CMD640_PREFETCH_MASKS
- drive->no_unmask = 1;
- drive->unmask = 0;
-#endif
- drive->no_io_32bit = 0;
- }
+ __set_prefetch_mode(drive, (b & prefetch_masks[index]) ? 0 : 1);
}
#else
+
/*
* Sets prefetch mode for a drive.
*/
@@ -413,19 +413,11 @@ static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
spin_lock_irqsave(&cmd640_lock, flags);
b = __get_cmd640_reg(reg);
- if (mode) { /* want prefetch on? */
-#if CMD640_PREFETCH_MASKS
- drive->no_unmask = 1;
- drive->unmask = 0;
-#endif
- drive->no_io_32bit = 0;
+ __set_prefetch_mode(drive, mode);
+ if (mode)
b &= ~prefetch_masks[index]; /* enable prefetch */
- } else {
- drive->no_unmask = 0;
- drive->no_io_32bit = 1;
- drive->io_32bit = 0;
+ else
b |= prefetch_masks[index]; /* disable prefetch */
- }
__put_cmd640_reg(reg, b);
spin_unlock_irqrestore(&cmd640_lock, flags);
}
@@ -476,10 +468,10 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index)
*/
if (index > 1) {
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
+ ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)];
unsigned int mate = index ^ 1;
- if (peer->present) {
+ if (peer->dev_flags & IDE_DFLAG_PRESENT) {
if (setup_count < setup_counts[mate])
setup_count = setup_counts[mate];
if (active_count < active_counts[mate])
@@ -521,21 +513,23 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index)
static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
u8 pio_mode, unsigned int cycle_time)
{
+ struct ide_timing *t;
int setup_time, active_time, recovery_time, clock_time;
u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
int bus_speed;
- if (cmd640_vlb && ide_vlb_clk)
- bus_speed = ide_vlb_clk;
- else if (!cmd640_vlb && ide_pci_clk)
- bus_speed = ide_pci_clk;
+ if (cmd640_vlb)
+ bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
else
- bus_speed = system_bus_clock();
+ bus_speed = ide_pci_clk ? ide_pci_clk : 33;
if (pio_mode > 5)
pio_mode = 5;
- setup_time = ide_pio_timings[pio_mode].setup_time;
- active_time = ide_pio_timings[pio_mode].active_time;
+
+ t = ide_timing_find_mode(XFER_PIO_0 + pio_mode);
+ setup_time = t->setup;
+ active_time = t->active;
+
recovery_time = cycle_time - (setup_time + active_time);
clock_time = 1000 / bus_speed;
cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
@@ -609,11 +603,40 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
display_clocks(index);
}
+#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+
+static void cmd640_init_dev(ide_drive_t *drive)
+{
+ unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1);
+
+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ /*
+ * Reset timing to the slowest speed and turn off prefetch.
+ * This way, the drive identify code has a better chance.
+ */
+ setup_counts[i] = 4; /* max possible */
+ active_counts[i] = 16; /* max possible */
+ recovery_counts[i] = 16; /* max possible */
+ program_drive_counts(drive, i);
+ set_prefetch_mode(drive, i, 0);
+ printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch cleared\n", i);
+#else
+ /*
+ * Set the drive unmask flags to match the prefetch setting.
+ */
+ check_prefetch(drive, i);
+ printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n",
+ i, (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) ? "off" : "on");
+#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+}
+
static const struct ide_port_ops cmd640_port_ops = {
+ .init_dev = cmd640_init_dev,
+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
.set_pio_mode = cmd640_set_pio_mode,
+#endif
};
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
static int pci_conf1(void)
{
@@ -656,10 +679,8 @@ static const struct ide_port_info cmd640_port_info __initdata = {
IDE_HFLAG_NO_DMA |
IDE_HFLAG_ABUSE_PREFETCH |
IDE_HFLAG_ABUSE_FAST_DEVSEL,
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
.port_ops = &cmd640_port_ops,
.pio_mask = ATA_PIO5,
-#endif
};
static int cmd640x_init_one(unsigned long base, unsigned long ctl)
@@ -685,15 +706,10 @@ static int cmd640x_init_one(unsigned long base, unsigned long ctl)
*/
static int __init cmd640x_init(void)
{
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
- int second_port_toggled = 0;
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
int second_port_cmd640 = 0, rc;
const char *bus_type, *port2;
- unsigned int index;
u8 b, cfr;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw[2];
+ hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
if (cmd640_vlb && probe_for_cmd640_vlb()) {
bus_type = "VLB";
@@ -756,15 +772,10 @@ static int __init cmd640x_init(void)
printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
"\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
- cmd_hwif0 = ide_find_port();
-
/*
* Initialize data for primary port
*/
- if (cmd_hwif0) {
- ide_init_port_hw(cmd_hwif0, &hw[0]);
- idx[0] = cmd_hwif0->index;
- }
+ hws[0] = &hw[0];
/*
* Ensure compatibility by always using the slowest timings
@@ -776,95 +787,45 @@ static int __init cmd640x_init(void)
put_cmd640_reg(CMDTIM, 0);
put_cmd640_reg(BRST, 0x40);
- cmd_hwif1 = ide_find_port();
+ b = get_cmd640_reg(CNTRL);
/*
* Try to enable the secondary interface, if not already enabled
*/
- if (cmd_hwif1 &&
- cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) {
- port2 = "not probed";
+ if (secondary_port_responding()) {
+ if ((b & CNTRL_ENA_2ND)) {
+ second_port_cmd640 = 1;
+ port2 = "okay";
+ } else if (cmd640_vlb) {
+ second_port_cmd640 = 1;
+ port2 = "alive";
+ } else
+ port2 = "not cmd640";
} else {
- b = get_cmd640_reg(CNTRL);
+ put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */
if (secondary_port_responding()) {
- if ((b & CNTRL_ENA_2ND)) {
- second_port_cmd640 = 1;
- port2 = "okay";
- } else if (cmd640_vlb) {
- second_port_cmd640 = 1;
- port2 = "alive";
- } else
- port2 = "not cmd640";
+ second_port_cmd640 = 1;
+ port2 = "enabled";
} else {
- put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */
- if (secondary_port_responding()) {
- second_port_cmd640 = 1;
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
- second_port_toggled = 1;
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
- port2 = "enabled";
- } else {
- put_cmd640_reg(CNTRL, b); /* restore original setting */
- port2 = "not responding";
- }
+ put_cmd640_reg(CNTRL, b); /* restore original setting */
+ port2 = "not responding";
}
}
/*
* Initialize data for secondary cmd640 port, if enabled
*/
- if (second_port_cmd640 && cmd_hwif1) {
- ide_init_port_hw(cmd_hwif1, &hw[1]);
- idx[1] = cmd_hwif1->index;
- }
+ if (second_port_cmd640)
+ hws[1] = &hw[1];
+
printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
second_port_cmd640 ? "" : "not ", port2);
- /*
- * Establish initial timings/prefetch for all drives.
- * Do not unnecessarily disturb any prior BIOS setup of these.
- */
- for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) {
- ide_drive_t *drive;
-
- if (index > 1) {
- if (cmd_hwif1 == NULL)
- continue;
- drive = &cmd_hwif1->drives[index & 1];
- } else {
- if (cmd_hwif0 == NULL)
- continue;
- drive = &cmd_hwif0->drives[index & 1];
- }
-
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
- /*
- * Reset timing to the slowest speed and turn off prefetch.
- * This way, the drive identify code has a better chance.
- */
- setup_counts [index] = 4; /* max possible */
- active_counts [index] = 16; /* max possible */
- recovery_counts [index] = 16; /* max possible */
- program_drive_counts(drive, index);
- set_prefetch_mode(drive, index, 0);
- printk("cmd640: drive%d timings/prefetch cleared\n", index);
-#else
- /*
- * Set the drive unmask flags to match the prefetch setting
- */
- check_prefetch(drive, index);
- printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
- index, drive->no_io_32bit ? "off" : "on");
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
- }
-
#ifdef CMD640_DUMP_REGS
cmd640_dump_regs();
#endif
- ide_device_add(idx, &cmd640_port_info);
-
- return 1;
+ return ide_host_add(&cmd640_port_info, hws, NULL);
}
module_param_named(probe_vlb, cmd640_vlb, bool, 0);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 08674711d08..935385c77e0 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -13,12 +13,13 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
+#define DRV_NAME "cmd64x"
+
#define CMD_DEBUG 0
#if CMD_DEBUG
@@ -69,7 +70,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 = to_pci_dev(drive->hwif->dev);
- int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : system_bus_clock());
+ int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33);
u8 cycle_count, active_count, recovery_count, drwtim;
static const u8 recovery_values[] =
{15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
@@ -116,6 +117,7 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
unsigned int cycle_time;
u8 setup_count, arttim = 0;
@@ -124,11 +126,10 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
cycle_time = ide_pio_cycle_time(drive, pio);
- program_cycle_times(drive, cycle_time,
- ide_pio_timings[pio].active_time);
+ program_cycle_times(drive, cycle_time, t->active);
- setup_count = quantize_timing(ide_pio_timings[pio].setup_time,
- 1000 / (ide_pci_clk ? ide_pci_clk : system_bus_clock()));
+ setup_count = quantize_timing(t->setup,
+ 1000 / (ide_pci_clk ? ide_pci_clk : 33));
/*
* The primary channel has individual address setup timing registers
@@ -227,7 +228,7 @@ static int cmd648_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);
+ int err = ide_dma_end(drive);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
u8 mrdmode = inb(base + 1);
@@ -247,7 +248,7 @@ static int cmd64x_dma_end(ide_drive_t *drive)
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
u8 irq_stat = 0;
- int err = __ide_dma_end(drive);
+ int err = ide_dma_end(drive);
(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
/* clear the interrupt bit */
@@ -262,7 +263,7 @@ static int cmd648_dma_test_irq(ide_drive_t *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 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 mrdmode = inb(base + 1);
#ifdef DEBUG
@@ -286,7 +287,7 @@ static int cmd64x_dma_test_irq(ide_drive_t *drive)
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 irq_stat = 0;
(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
@@ -317,41 +318,23 @@ static int cmd646_1_dma_end(ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* get DMA status */
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* read DMA command state */
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
/* clear the INTR & ERROR bits */
- outb(dma_stat | 6, hwif->dma_status);
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
/* and free any DMA resources */
ide_destroy_dmatable(drive);
/* verify good DMA status */
return (dma_stat & 7) != 4;
}
-static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_cmd64x(struct pci_dev *dev)
{
u8 mrdmode = 0;
- if (dev->device == PCI_DEVICE_ID_CMD_646) {
-
- switch (dev->revision) {
- case 0x07:
- case 0x05:
- printk("%s: UltraDMA capable\n", name);
- break;
- case 0x03:
- default:
- printk("%s: MultiWord DMA force limited\n", name);
- break;
- case 0x01:
- printk("%s: MultiWord DMA limited, "
- "IRQ workaround enabled\n", name);
- break;
- }
- }
-
/* Set a good latency timer and cache line size value. */
(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
/* FIXME: pci_set_master() to ensure a good latency timer value */
@@ -370,7 +353,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
return 0;
}
-static u8 __devinit cmd64x_cable_detect(ide_hwif_t *hwif)
+static u8 cmd64x_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01;
@@ -425,8 +408,8 @@ static const struct ide_dma_ops cmd648_dma_ops = {
};
static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "CMD643",
+ { /* 0: CMD643 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
@@ -436,8 +419,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* no udma */
- },{ /* 1 */
- .name = "CMD646",
+ },
+ { /* 1: CMD646 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.chipset = ide_cmd646,
@@ -447,8 +431,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
- },{ /* 2 */
- .name = "CMD648",
+ },
+ { /* 2: CMD648 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
@@ -457,8 +442,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
- },{ /* 3 */
- .name = "CMD649",
+ },
+ { /* 3: CMD649 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
@@ -507,7 +493,7 @@ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_devic
}
}
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id cmd64x_pci_tbl[] = {
@@ -519,18 +505,27 @@ static const struct pci_device_id cmd64x_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver cmd64x_pci_driver = {
.name = "CMD64x_IDE",
.id_table = cmd64x_pci_tbl,
.probe = cmd64x_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cmd64x_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cmd64x_pci_driver);
+}
+
+static void __exit cmd64x_ide_exit(void)
+{
+ pci_unregister_driver(&cmd64x_pci_driver);
}
module_init(cmd64x_ide_init);
+module_exit(cmd64x_ide_exit);
MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 992b1cf8db6..5efb467f8fa 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -35,12 +35,13 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/dma-mapping.h>
+#define DRV_NAME "cs5520"
+
struct pio_clocks
{
int address;
@@ -62,8 +63,6 @@ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
struct pci_dev *pdev = to_pci_dev(hwif->dev);
int controller = drive->dn > 1 ? 1 : 0;
- /* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
-
/* 8bit CAT/CRT - 8bit command timing for channel */
pci_write_config_byte(pdev, 0x62 + controller,
(cs5520_pio_clocks[pio].recovery << 4) |
@@ -89,52 +88,17 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
cs5520_set_pio_mode(drive, 0);
}
-/*
- * 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 void cs5520_dma_host_set(ide_drive_t *drive, int on)
-{
- drive->vdma = on;
- ide_dma_host_set(drive, on);
-}
-
static const struct ide_port_ops cs5520_port_ops = {
.set_pio_mode = cs5520_set_pio_mode,
.set_dma_mode = cs5520_set_dma_mode,
};
-static const struct ide_dma_ops cs5520_dma_ops = {
- .dma_host_set = cs5520_dma_host_set,
- .dma_setup = ide_dma_setup,
- .dma_exec_cmd = ide_dma_exec_cmd,
- .dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
- .dma_test_irq = ide_dma_test_irq,
- .dma_lost_irq = ide_dma_lost_irq,
- .dma_timeout = ide_dma_timeout,
-};
-
-/* FIXME: VDMA is disabled because it caused system hangs */
-#define DECLARE_CS_DEV(name_str) \
- { \
- .name = name_str, \
- .port_ops = &cs5520_port_ops, \
- .dma_ops = &cs5520_dma_ops, \
- .host_flags = IDE_HFLAG_ISA_PORTS | \
- IDE_HFLAG_CS5520 | \
- IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE, \
- .pio_mask = ATA_PIO4, \
- }
-
-static const struct ide_port_info cyrix_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_CS_DEV("Cyrix 5510"),
- /* 1 */ DECLARE_CS_DEV("Cyrix 5520")
+static const struct ide_port_info cyrix_chipset __devinitdata = {
+ .name = DRV_NAME,
+ .enablebits = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } },
+ .port_ops = &cs5520_port_ops,
+ .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_CS5520,
+ .pio_mask = ATA_PIO4,
};
/*
@@ -145,8 +109,8 @@ static const struct ide_port_info cyrix_chipsets[] __devinitdata = {
static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- const struct ide_port_info *d = &cyrix_chipsets[id->driver_data];
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ const struct ide_port_info *d = &cyrix_chipset;
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
ide_setup_pci_noise(dev, d);
@@ -159,7 +123,8 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
}
pci_set_master(dev);
if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
- printk(KERN_WARNING "cs5520: No suitable DMA available.\n");
+ printk(KERN_WARNING "%s: No suitable DMA available.\n",
+ d->name);
return -ENODEV;
}
@@ -168,11 +133,9 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
* do all the device setup for us
*/
- ide_pci_setup_ports(dev, d, 14, &idx[0]);
-
- ide_device_add(idx, d);
+ ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]);
- return 0;
+ return ide_host_add(d, hws, NULL);
}
static const struct pci_device_id cs5520_pci_tbl[] = {
@@ -182,15 +145,17 @@ static const struct pci_device_id cs5520_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver cs5520_pci_driver = {
.name = "Cyrix_IDE",
.id_table = cs5520_pci_tbl,
.probe = cs5520_init_one,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cs5520_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cs5520_pci_driver);
}
module_init(cs5520_ide_init);
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index f5534c1ff34..53f079cc00a 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -15,13 +15,14 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <asm/io.h>
+#define DRV_NAME "cs5530"
+
/*
* Here are the standard PIO mode 0-4 timings for each "format".
* Format-0 uses fast data reg timings, with slower command reg timings.
@@ -79,17 +80,19 @@ static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio)
static u8 cs5530_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
- struct hd_driveid *mateid = mate->id;
+ ide_drive_t *mate = ide_get_pair_dev(drive);
+ u16 *mateid = mate->id;
u8 mask = hwif->ultra_mask;
- if (mate->present == 0)
+ if (mate == NULL)
goto out;
- if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
- if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+ if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
+ if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
+ (mateid[ATA_ID_UDMA_MODES] & 7))
goto out;
- if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+ if ((mateid[ATA_ID_FIELD_VALID] & 2) &&
+ (mateid[ATA_ID_MWDMA_MODES] & 7))
mask = 0;
}
out:
@@ -127,12 +130,11 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
/**
* init_chipset_5530 - set up 5530 bridge
* @dev: PCI device
- * @name: device name
*
* Initialize the cs5530 bridge for reliable IDE DMA operation.
*/
-static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_cs5530(struct pci_dev *dev)
{
struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
@@ -151,11 +153,11 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
}
}
if (!master_0) {
- printk(KERN_ERR "%s: unable to locate PCI MASTER function\n", name);
+ printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
goto out;
}
if (!cs5530_0) {
- printk(KERN_ERR "%s: unable to locate CS5530 LEGACY function\n", name);
+ printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
goto out;
}
@@ -243,7 +245,7 @@ static const struct ide_port_ops cs5530_port_ops = {
};
static const struct ide_port_info cs5530_chipset __devinitdata = {
- .name = "CS5530",
+ .name = DRV_NAME,
.init_chipset = init_chipset_cs5530,
.init_hwif = init_hwif_cs5530,
.port_ops = &cs5530_port_ops,
@@ -256,7 +258,7 @@ static const struct ide_port_info cs5530_chipset __devinitdata = {
static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &cs5530_chipset);
+ return ide_pci_init_one(dev, &cs5530_chipset, NULL);
}
static const struct pci_device_id cs5530_pci_tbl[] = {
@@ -265,18 +267,27 @@ static const struct pci_device_id cs5530_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver cs5530_pci_driver = {
.name = "CS5530 IDE",
.id_table = cs5530_pci_tbl,
.probe = cs5530_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cs5530_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cs5530_pci_driver);
+}
+
+static void __exit cs5530_ide_exit(void)
+{
+ pci_unregister_driver(&cs5530_pci_driver);
}
module_init(cs5530_ide_init);
+module_exit(cs5530_ide_exit);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE");
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 99fe91a191b..983d957a018 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -26,7 +26,7 @@
#include <linux/pci.h>
#include <linux/ide.h>
-#include "ide-timing.h"
+#define DRV_NAME "cs5535"
#define MSR_ATAC_BASE 0x51300000
#define ATAC_GLD_MSR_CAP (MSR_ATAC_BASE+0)
@@ -75,19 +75,17 @@ static unsigned int cs5535_udma_timings[5] =
*/
static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
{
-
u32 reg = 0, dummy;
- int unit = drive->select.b.unit;
-
+ u8 unit = drive->dn & 1;
/* Set the PIO timings */
- if ((speed & XFER_MODE) == XFER_PIO) {
- ide_drive_t *pair = ide_get_paired_drive(drive);
+ if (speed < XFER_SW_DMA_0) {
+ ide_drive_t *pair = ide_get_pair_dev(drive);
u8 cmd, pioa;
cmd = pioa = speed - XFER_PIO_0;
- if (pair->present) {
+ if (pair) {
u8 piob = ide_get_best_pio_mode(pair, 255, 4);
if (piob < cmd)
@@ -155,7 +153,7 @@ 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(ide_hwif_t *hwif)
+static u8 cs5535_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 bit;
@@ -173,10 +171,9 @@ static const struct ide_port_ops cs5535_port_ops = {
};
static const struct ide_port_info cs5535_chipset __devinitdata = {
- .name = "CS5535",
+ .name = DRV_NAME,
.port_ops = &cs5535_port_ops,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
- IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
@@ -185,7 +182,7 @@ static const struct ide_port_info cs5535_chipset __devinitdata = {
static int __devinit cs5535_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &cs5535_chipset);
+ return ide_pci_init_one(dev, &cs5535_chipset, NULL);
}
static const struct pci_device_id cs5535_pci_tbl[] = {
@@ -195,18 +192,27 @@ static const struct pci_device_id cs5535_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl);
-static struct pci_driver driver = {
- .name = "CS5535_IDE",
- .id_table = cs5535_pci_tbl,
- .probe = cs5535_init_one,
+static struct pci_driver cs5535_pci_driver = {
+ .name = "CS5535_IDE",
+ .id_table = cs5535_pci_tbl,
+ .probe = cs5535_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cs5535_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cs5535_pci_driver);
+}
+
+static void __exit cs5535_ide_exit(void)
+{
+ pci_unregister_driver(&cs5535_pci_driver);
}
module_init(cs5535_ide_init);
+module_exit(cs5535_ide_exit);
MODULE_AUTHOR("AMD");
MODULE_DESCRIPTION("PCI driver module for AMD/NS CS5535 IDE");
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index 77cc22c2ad4..5297f07d293 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -48,18 +48,13 @@
#include <asm/io.h>
-/* the current version */
-#define CY82_VERSION "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)"
+#define DRV_NAME "cy82c693"
/*
* The following are used to debug the driver.
*/
-#define CY82C693_DEBUG_LOGS 0
#define CY82C693_DEBUG_INFO 0
-/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */
-#undef CY82C693_SETDMA_CLOCK
-
/*
* NOTE: the value for busmaster timeout is tricky and I got it by
* trial and error! By using a to low value will cause DMA timeouts
@@ -87,7 +82,6 @@
#define CY82_INDEX_PORT 0x22
#define CY82_DATA_PORT 0x23
-#define CY82_INDEX_CTRLREG1 0x01
#define CY82_INDEX_CHANNEL0 0x30
#define CY82_INDEX_CHANNEL1 0x31
#define CY82_INDEX_TIMEOUT 0x32
@@ -133,23 +127,22 @@ static int calc_clk(int time, int bus_speed)
*/
static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
{
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
int clk1, clk2;
- int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
+ int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
/* we don't check against CY82C693's min and max speed,
* so you can play with the idebus=xx parameter
*/
/* let's calc the address setup time clocks */
- p_pclk->address_time = (u8)calc_clk(ide_pio_timings[pio].setup_time, bus_speed);
+ p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed);
/* let's calc the active and recovery time clocks */
- clk1 = calc_clk(ide_pio_timings[pio].active_time, bus_speed);
+ clk1 = calc_clk(t->active, bus_speed);
/* calc recovery timing */
- clk2 = ide_pio_timings[pio].cycle_time -
- ide_pio_timings[pio].active_time -
- ide_pio_timings[pio].setup_time;
+ clk2 = t->cycle - t->active - t->setup;
clk2 = calc_clk(clk2, bus_speed);
@@ -178,17 +171,6 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
-#if CY82C693_DEBUG_LOGS
- /* for debug let's show the previous values */
-
- outb(index, CY82_INDEX_PORT);
- data = inb(CY82_DATA_PORT);
-
- printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
- drive->name, HWIF(drive)->channel, drive->select.b.unit,
- (data&0x3), ((data>>2)&1));
-#endif /* CY82C693_DEBUG_LOGS */
-
data = (mode & 3) | (single << 2);
outb(index, CY82_INDEX_PORT);
@@ -196,8 +178,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
#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 & 3, single);
+ drive->name, hwif->channel, drive->dn & 1, mode & 3, single);
#endif /* CY82C693_DEBUG_INFO */
/*
@@ -238,50 +219,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
}
-#if CY82C693_DEBUG_LOGS
- /* for debug let's show the register values */
-
- if (drive->select.b.unit == 0) {
- /*
- * get master drive registers
- * address setup control register
- * is 32 bit !!!
- */
- pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
- addrCtrl &= 0x0F;
-
- /* now let's get the remaining registers */
- pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r);
- pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w);
- pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8);
- } else {
- /*
- * set slave drive registers
- * address setup control register
- * is 32 bit !!!
- */
- pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
-
- addrCtrl &= 0xF0;
- addrCtrl >>= 4;
-
- /* now let's get the remaining registers */
- pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r);
- pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w);
- pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8);
- }
-
- printk(KERN_INFO "%s (ch=%d, dev=%d): PIO timing is "
- "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
- drive->name, hwif->channel, drive->select.b.unit,
- addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
-#endif /* CY82C693_DEBUG_LOGS */
-
/* let's calc the values for this PIO mode */
compute_clocks(pio, &pclk);
/* now let's write the clocks registers */
- if (drive->select.b.unit == 0) {
+ if ((drive->dn & 1) == 0) {
/*
* set master drive
* address setup control register
@@ -323,63 +265,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
#if CY82C693_DEBUG_INFO
printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
"(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
- drive->name, hwif->channel, drive->select.b.unit,
+ drive->name, hwif->channel, drive->dn & 1,
addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
#endif /* CY82C693_DEBUG_INFO */
}
-/*
- * this function is called during init and is used to setup the cy82c693 chip
- */
-static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const char *name)
-{
- if (PCI_FUNC(dev->devfn) != 1)
- return 0;
-
-#ifdef CY82C693_SETDMA_CLOCK
- u8 data = 0;
-#endif /* CY82C693_SETDMA_CLOCK */
-
- /* write info about this verion of the driver */
- printk(KERN_INFO CY82_VERSION "\n");
-
-#ifdef CY82C693_SETDMA_CLOCK
- /* okay let's set the DMA clock speed */
-
- outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
- data = inb(CY82_DATA_PORT);
-
-#if CY82C693_DEBUG_INFO
- printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n",
- name, data);
-#endif /* CY82C693_DEBUG_INFO */
-
- /*
- * for some reason sometimes the DMA controller
- * speed is set to ATCLK/2 ???? - we fix this here
- *
- * note: i don't know what causes this strange behaviour,
- * but even changing the dma speed doesn't solve it :-(
- * the ide performance is still only half the normal speed
- *
- * if anybody knows what goes wrong with my machine, please
- * let me know - ASK
- */
-
- data |= 0x03;
-
- outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
- outb(data, CY82_DATA_PORT);
-
-#if CY82C693_DEBUG_INFO
- printk(KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
- name, data);
-#endif /* CY82C693_DEBUG_INFO */
-
-#endif /* CY82C693_SETDMA_CLOCK */
- return 0;
-}
-
static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
{
static ide_hwif_t *primary;
@@ -399,8 +289,7 @@ static const struct ide_port_ops cy82c693_port_ops = {
};
static const struct ide_port_info cy82c693_chipset __devinitdata = {
- .name = "CY82C693",
- .init_chipset = init_chipset_cy82c693,
+ .name = DRV_NAME,
.init_iops = init_iops_cy82c693,
.port_ops = &cy82c693_port_ops,
.chipset = ide_cy82c693,
@@ -420,30 +309,49 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
PCI_FUNC(dev->devfn) == 1) {
dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
- ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
- /* We leak pci refs here but thats ok - we can't be unloaded */
+ ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL);
+ if (ret)
+ pci_dev_put(dev2);
}
return ret;
}
+static void __devexit cy82c693_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+ ide_pci_remove(dev);
+ pci_dev_put(dev2);
+}
+
static const struct pci_device_id cy82c693_pci_tbl[] = {
{ PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver cy82c693_pci_driver = {
.name = "Cypress_IDE",
.id_table = cy82c693_pci_tbl,
.probe = cy82c693_init_one,
+ .remove = __devexit_p(cy82c693_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cy82c693_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cy82c693_pci_driver);
+}
+
+static void __exit cy82c693_ide_exit(void)
+{
+ pci_unregister_driver(&cy82c693_pci_driver);
}
module_init(cy82c693_ide_init);
+module_exit(cy82c693_ide_exit);
MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
index af0f30051d5..8689a706f53 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/pci/delkin_cb.c
@@ -19,7 +19,6 @@
#include <linux/types.h>
#include <linux/module.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/pci.h>
@@ -56,11 +55,10 @@ static const struct ide_port_info delkin_cb_port_info = {
static int __devinit
delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
+ struct ide_host *host;
unsigned long base;
- hw_regs_t hw;
- ide_hwif_t *hwif = NULL;
int i, rc;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
rc = pci_enable_device(dev);
if (rc) {
@@ -87,35 +85,26 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
hw.dev = &dev->dev;
hw.chipset = ide_pci; /* this enables IRQ sharing */
- hwif = ide_find_port();
- if (hwif == NULL)
+ rc = ide_host_add(&delkin_cb_port_info, hws, &host);
+ if (rc)
goto out_disable;
- i = hwif->index;
-
- ide_init_port_data(hwif, i);
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = i;
-
- ide_device_add(idx, &delkin_cb_port_info);
-
- pci_set_drvdata(dev, hwif);
+ pci_set_drvdata(dev, host);
return 0;
out_disable:
pci_release_regions(dev);
pci_disable_device(dev);
- return -ENODEV;
+ return rc;
}
static void
delkin_cb_remove (struct pci_dev *dev)
{
- ide_hwif_t *hwif = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
- ide_unregister(hwif);
+ ide_host_remove(host);
pci_release_regions(dev);
pci_disable_device(dev);
@@ -128,7 +117,7 @@ static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver delkin_cb_pci_driver = {
.name = "Delkin-ASKA-Workbit Cardbus IDE",
.id_table = delkin_cb_pci_tbl,
.probe = delkin_cb_probe,
@@ -137,12 +126,12 @@ static struct pci_driver driver = {
static int __init delkin_cb_init(void)
{
- return pci_register_driver(&driver);
+ return pci_register_driver(&delkin_cb_pci_driver);
}
static void __exit delkin_cb_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&delkin_cb_pci_driver);
}
module_init(delkin_cb_init);
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 041720e2276..474f96a7c07 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -22,11 +22,12 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "ide_pci_generic"
+
static int ide_generic_all; /* Set to claim all devices */
module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
@@ -34,9 +35,9 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
-#define DECLARE_GENERIC_PCI_DEV(name_str, extra_flags) \
+#define DECLARE_GENERIC_PCI_DEV(extra_flags) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
extra_flags, \
.swdma_mask = ATA_SWDMA2, \
@@ -45,10 +46,11 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
}
static const struct ide_port_info generic_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_GENERIC_PCI_DEV("Unknown", 0),
+ /* 0: Unknown */
+ DECLARE_GENERIC_PCI_DEV(0),
- { /* 1 */
- .name = "NS87410",
+ { /* 1: NS87410 */
+ .name = DRV_NAME,
.enablebits = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
.host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
.swdma_mask = ATA_SWDMA2,
@@ -56,17 +58,15 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
.udma_mask = ATA_UDMA6,
},
- /* 2 */ DECLARE_GENERIC_PCI_DEV("SAMURAI", 0),
- /* 3 */ DECLARE_GENERIC_PCI_DEV("HT6565", 0),
- /* 4 */ DECLARE_GENERIC_PCI_DEV("UM8673F", IDE_HFLAGS_UMC),
- /* 5 */ DECLARE_GENERIC_PCI_DEV("UM8886A", IDE_HFLAGS_UMC),
- /* 6 */ DECLARE_GENERIC_PCI_DEV("UM8886BF", IDE_HFLAGS_UMC),
- /* 7 */ DECLARE_GENERIC_PCI_DEV("HINT_IDE", 0),
- /* 8 */ DECLARE_GENERIC_PCI_DEV("VIA_IDE", IDE_HFLAG_NO_AUTODMA),
- /* 9 */ DECLARE_GENERIC_PCI_DEV("OPTI621V", IDE_HFLAG_NO_AUTODMA),
-
- { /* 10 */
- .name = "VIA8237SATA",
+ /* 2: SAMURAI / HT6565 / HINT_IDE */
+ DECLARE_GENERIC_PCI_DEV(0),
+ /* 3: UM8673F / UM8886A / UM8886BF */
+ DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC),
+ /* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */
+ DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA),
+
+ { /* 5: VIA8237SATA */
+ .name = DRV_NAME,
.host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
IDE_HFLAG_OFF_BOARD,
.swdma_mask = ATA_SWDMA2,
@@ -74,12 +74,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
.udma_mask = ATA_UDMA6,
},
- /* 11 */ DECLARE_GENERIC_PCI_DEV("Piccolo0102", IDE_HFLAG_NO_AUTODMA),
- /* 12 */ DECLARE_GENERIC_PCI_DEV("Piccolo0103", IDE_HFLAG_NO_AUTODMA),
- /* 13 */ DECLARE_GENERIC_PCI_DEV("Piccolo0105", IDE_HFLAG_NO_AUTODMA),
-
- { /* 14 */
- .name = "Revolution",
+ { /* 6: Revolution */
+ .name = DRV_NAME,
.host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
IDE_HFLAG_TRUST_BIOS_FOR_DMA |
IDE_HFLAG_OFF_BOARD,
@@ -134,12 +130,12 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi
u16 command;
pci_read_config_word(dev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_IO)) {
- printk(KERN_INFO "Skipping disabled %s IDE "
- "controller.\n", d->name);
+ printk(KERN_INFO "%s %s: skipping disabled "
+ "controller\n", d->name, pci_name(dev));
goto out;
}
}
- ret = ide_setup_pci_device(dev, d);
+ ret = ide_pci_init_one(dev, d, NULL);
out:
return ret;
}
@@ -147,20 +143,20 @@ out:
static const struct pci_device_id generic_pci_tbl[] = {
{ PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), 1 },
{ PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), 2 },
- { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 3 },
- { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 4 },
- { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 5 },
- { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 6 },
- { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 7 },
- { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 8 },
- { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 9 },
+ { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 2 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 3 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 3 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 3 },
+ { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 2 },
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 4 },
+ { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 4 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 10 },
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 5 },
#endif
- { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 11 },
- { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 12 },
- { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 13 },
- { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 14 },
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 4 },
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 4 },
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 4 },
+ { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 6 },
/*
* Must come last. If you add entries adjust
* this table and generic_chipsets[] appropriately.
@@ -170,18 +166,27 @@ static const struct pci_device_id generic_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver generic_pci_driver = {
.name = "PCI_IDE",
.id_table = generic_pci_tbl,
.probe = generic_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init generic_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&generic_pci_driver);
+}
+
+static void __exit generic_ide_exit(void)
+{
+ pci_unregister_driver(&generic_pci_driver);
}
module_init(generic_ide_init);
+module_exit(generic_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for generic PCI IDE");
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index 84c36c11719..fb1a3aa57f0 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -27,12 +27,13 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
-#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
+#define DRV_NAME "hpt34x"
+
#define HPT343_DEBUG_DRIVE_INFO 0
static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed)
@@ -77,7 +78,7 @@ static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio)
*/
#define HPT34X_PCI_INIT_REG 0x80
-static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_hpt34x(struct pci_dev *dev)
{
int i = 0;
unsigned long hpt34xIoBase = pci_resource_start(dev, 4);
@@ -123,19 +124,18 @@ static const struct ide_port_ops hpt34x_port_ops = {
#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",
+ { /* 0: HPT343 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_hpt34x,
.port_ops = &hpt34x_port_ops,
.host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE,
.pio_mask = ATA_PIO5,
},
- { /* 1 */
- .name = "HPT345",
+ { /* 1: HPT345 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_hpt34x,
.port_ops = &hpt34x_port_ops,
.host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
@@ -157,7 +157,7 @@ static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_devic
d = &hpt34x_chipsets[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0];
- return ide_setup_pci_device(dev, d);
+ return ide_pci_init_one(dev, d, NULL);
}
static const struct pci_device_id hpt34x_pci_tbl[] = {
@@ -166,18 +166,27 @@ static const struct pci_device_id hpt34x_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver hpt34x_pci_driver = {
.name = "HPT34x_IDE",
.id_table = hpt34x_pci_tbl,
.probe = hpt34x_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init hpt34x_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&hpt34x_pci_driver);
+}
+
+static void __exit hpt34x_ide_exit(void)
+{
+ pci_unregister_driver(&hpt34x_pci_driver);
}
module_init(hpt34x_ide_init);
+module_exit(hpt34x_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for Highpoint 34x IDE");
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index c929dadaaaf..9cf171cb937 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -122,7 +122,6 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -131,6 +130,8 @@
#include <asm/uaccess.h>
#include <asm/io.h>
+#define DRV_NAME "hpt366"
+
/* various tuning parameters */
#define HPT_RESET_STATE_ENGINE
#undef HPT_DELAY_INTERRUPT
@@ -603,14 +604,22 @@ static const struct hpt_info hpt371n __devinitdata = {
static int check_in_drive_list(ide_drive_t *drive, const char **list)
{
- struct hd_driveid *id = drive->id;
+ char *m = (char *)&drive->id[ATA_ID_PROD];
while (*list)
- if (!strcmp(*list++,id->model))
+ if (!strcmp(*list++, m))
return 1;
return 0;
}
+static struct hpt_info *hpt3xx_get_info(struct device *dev)
+{
+ struct ide_host *host = dev_get_drvdata(dev);
+ struct hpt_info *info = (struct hpt_info *)host->host_priv;
+
+ return dev == host->dev[1] ? info + 1 : info;
+}
+
/*
* The Marvell bridge chips used on the HighPoint SATA cards do not seem
* to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
@@ -619,8 +628,7 @@ 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 pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
u8 mask = hwif->ultra_mask;
switch (info->chip_type) {
@@ -646,7 +654,7 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
case HPT372A:
case HPT372N:
case HPT374 :
- if (ide_dev_is_sata(drive->id))
+ if (ata_id_is_sata(drive->id))
mask &= ~0x0e;
/* Fall thru */
default:
@@ -659,15 +667,14 @@ 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 pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
switch (info->chip_type) {
case HPT372 :
case HPT372A:
case HPT372N:
case HPT374 :
- if (ide_dev_is_sata(drive->id))
+ if (ata_id_is_sata(drive->id))
return 0x00;
/* Fall thru */
default:
@@ -694,8 +701,9 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
{
- struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
struct hpt_timings *t = info->timings;
u8 itr_addr = 0x40 + (drive->dn * 4);
u32 old_itr = 0;
@@ -722,11 +730,11 @@ static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void hpt3xx_quirkproc(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ char *m = (char *)&drive->id[ATA_ID_PROD];
const char **list = quirk_drives;
while (*list)
- if (strstr(id->model, *list++)) {
+ if (strstr(m, *list++)) {
drive->quirk_list = 1;
return;
}
@@ -738,7 +746,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
if (drive->quirk_list) {
if (info->chip_type >= HPT370) {
@@ -759,8 +767,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
enable_irq (hwif->irq);
}
} else
- outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
- hwif->io_ports.ctl_addr);
+ outb(ATA_DEVCTL_OBS | (mask ? 2 : 0), hwif->io_ports.ctl_addr);
}
/*
@@ -802,9 +809,9 @@ static void hpt370_irq_timeout(ide_drive_t *drive)
printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
/* get DMA command mode */
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~0x1, hwif->dma_command);
+ outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD);
hpt370_clear_engine(drive);
}
@@ -819,16 +826,16 @@ static void hpt370_dma_start(ide_drive_t *drive)
static int hpt370_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
if (dma_stat & 0x01) {
/* wait a little */
udelay(20);
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
if (dma_stat & 0x01)
hpt370_irq_timeout(drive);
}
- return __ide_dma_end(drive);
+ return ide_dma_end(drive);
}
static void hpt370_dma_timeout(ide_drive_t *drive)
@@ -851,14 +858,11 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
return 0;
}
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* return 1 if INTR asserted */
if (dma_stat & 4)
return 1;
- if (!drive->waiting_for_dma)
- printk(KERN_WARNING "%s: (%s) called while not waiting\n",
- drive->name, __func__);
return 0;
}
@@ -873,7 +877,7 @@ static int hpt374_dma_end(ide_drive_t *drive)
pci_read_config_byte(dev, mcr_addr, &mcr);
if (bwsr & mask)
pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
- return __ide_dma_end(drive);
+ return ide_dma_end(drive);
}
/**
@@ -936,7 +940,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
* Perform a calibration cycle on the DPLL.
* Returns 1 if this succeeds
*/
-static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
+static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
{
u32 dpll = (f_high << 16) | f_low | 0x100;
u8 scr2;
@@ -964,24 +968,45 @@ static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f
return 1;
}
-static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
+static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]);
+ u8 chip_type = info->chip_type;
+ u8 new_mcr, old_mcr = 0;
+
+ /*
+ * Disable the "fast interrupt" prediction. Don't hold off
+ * on interrupts. (== 0x01 despite what the docs say)
+ */
+ pci_read_config_byte(dev, mcr_addr + 1, &old_mcr);
+
+ if (chip_type >= HPT374)
+ new_mcr = old_mcr & ~0x07;
+ else if (chip_type >= HPT370) {
+ new_mcr = old_mcr;
+ new_mcr &= ~0x02;
+#ifdef HPT_DELAY_INTERRUPT
+ new_mcr &= ~0x01;
+#else
+ new_mcr |= 0x01;
+#endif
+ } else /* HPT366 and HPT368 */
+ new_mcr = old_mcr & ~0x80;
+
+ if (new_mcr != old_mcr)
+ pci_write_config_byte(dev, mcr_addr + 1, new_mcr);
+}
+
+static unsigned int init_chipset_hpt366(struct pci_dev *dev)
{
- struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL);
unsigned long io_base = pci_resource_start(dev, 4);
+ struct hpt_info *info = hpt3xx_get_info(&dev->dev);
+ const char *name = DRV_NAME;
u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */
u8 chip_type;
enum ata_clock clock;
- if (info == NULL) {
- printk(KERN_ERR "%s: out of memory!\n", name);
- return -ENOMEM;
- }
-
- /*
- * Copy everything from a static "template" structure
- * to just allocated per-chip hpt_info structure.
- */
- memcpy(info, pci_get_drvdata(dev), sizeof(struct hpt_info));
chip_type = info->chip_type;
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
@@ -1049,8 +1074,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
if ((temp & 0xFFFFF000) != 0xABCDE000) {
int i;
- printk(KERN_WARNING "%s: no clock data saved by BIOS\n",
- name);
+ printk(KERN_WARNING "%s %s: no clock data saved by "
+ "BIOS\n", name, pci_name(dev));
/* Calculate the average value of f_CNT. */
for (temp = i = 0; i < 128; i++) {
@@ -1075,8 +1100,9 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
else
pci_clk = 66;
- printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, "
- "assuming %d MHz PCI\n", name, dpll_clk, f_cnt, pci_clk);
+ printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, "
+ "assuming %d MHz PCI\n", name, pci_name(dev),
+ dpll_clk, f_cnt, pci_clk);
} else {
u32 itr1 = 0;
@@ -1142,8 +1168,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
}
if (info->timings->clock_table[clock] == NULL) {
- printk(KERN_ERR "%s: unknown bus timing!\n", name);
- kfree(info);
+ printk(KERN_ERR "%s %s: unknown bus timing!\n",
+ name, pci_name(dev));
return -EIO;
}
@@ -1169,17 +1195,19 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
f_low += adjust >> 1;
}
if (adjust == 8) {
- printk(KERN_ERR "%s: DPLL did not stabilize!\n", name);
- kfree(info);
+ printk(KERN_ERR "%s %s: DPLL did not stabilize!\n",
+ name, pci_name(dev));
return -EIO;
}
- printk("%s: using %d MHz DPLL clock\n", name, dpll_clk);
+ printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n",
+ name, pci_name(dev), dpll_clk);
} else {
/* Mark the fact that we're not using the DPLL. */
dpll_clk = 0;
- printk("%s: using %d MHz PCI clock\n", name, pci_clk);
+ printk(KERN_INFO "%s %s: using %d MHz PCI clock\n",
+ name, pci_name(dev), pci_clk);
}
/* Store the clock frequencies. */
@@ -1187,9 +1215,6 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
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);
-
if (chip_type >= HPT370) {
u8 mcr1, mcr4;
@@ -1210,16 +1235,18 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
* NOTE: This register is only writeable via I/O space.
*/
if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ)
-
outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c);
+ hpt3xx_disable_fast_irq(dev, 0x50);
+ hpt3xx_disable_fast_irq(dev, 0x54);
+
return dev->irq;
}
-static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
+static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
u8 chip_type = info->chip_type;
u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02;
@@ -1263,10 +1290,9 @@ static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
int serialize = HPT_SERIALIZE_IO;
u8 chip_type = info->chip_type;
- u8 new_mcr, old_mcr = 0;
/* Cache the channel's MISC. control registers' offset */
hwif->select_data = hwif->channel ? 0x54 : 0x50;
@@ -1289,29 +1315,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
/* Serialize access to this device if needed */
if (serialize && hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
-
- /*
- * Disable the "fast interrupt" prediction. Don't hold off
- * on interrupts. (== 0x01 despite what the docs say)
- */
- pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr);
-
- if (info->chip_type >= HPT374)
- new_mcr = old_mcr & ~0x07;
- else if (info->chip_type >= HPT370) {
- new_mcr = old_mcr;
- new_mcr &= ~0x02;
-
-#ifdef HPT_DELAY_INTERRUPT
- new_mcr &= ~0x01;
-#else
- new_mcr |= 0x01;
-#endif
- } else /* HPT366 and HPT368 */
- new_mcr = old_mcr & ~0x80;
-
- if (new_mcr != old_mcr)
- pci_write_config_byte(dev, hwif->select_data + 1, new_mcr);
}
static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
@@ -1321,7 +1324,15 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
unsigned long flags, base = ide_pci_dma_base(hwif, d);
u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
dma_old = inb(base + 2);
@@ -1347,7 +1358,7 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
@@ -1357,7 +1368,8 @@ static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
if (dev2->irq != dev->irq) {
/* FIXME: we need a core pci_set_interrupt() */
dev2->irq = dev->irq;
- printk(KERN_INFO "HPT374: PCI config space interrupt fixed\n");
+ printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt "
+ "fixed\n", pci_name(dev2));
}
}
@@ -1392,8 +1404,8 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
if (pin1 != pin2 && dev->irq == dev2->irq) {
- printk(KERN_INFO "HPT36x: onboard version of chipset, "
- "pin1=%d pin2=%d\n", pin1, pin2);
+ printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, "
+ "pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2);
return 1;
}
@@ -1402,7 +1414,6 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
#define IDE_HFLAGS_HPT3XX \
(IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_OFF_BOARD)
static const struct ide_port_ops hpt3xx_port_ops = {
@@ -1442,15 +1453,15 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = hpt366_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
};
static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "HPT36x",
+ { /* 0: HPT36x */
+ .name = DRV_NAME,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
@@ -1466,53 +1477,9 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
- },{ /* 1 */
- .name = "HPT372A",
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .port_ops = &hpt3xx_port_ops,
- .dma_ops = &hpt37x_dma_ops,
- .host_flags = IDE_HFLAGS_HPT3XX,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- },{ /* 2 */
- .name = "HPT302",
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .port_ops = &hpt3xx_port_ops,
- .dma_ops = &hpt37x_dma_ops,
- .host_flags = IDE_HFLAGS_HPT3XX,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- },{ /* 3 */
- .name = "HPT371",
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .port_ops = &hpt3xx_port_ops,
- .dma_ops = &hpt37x_dma_ops,
- .host_flags = IDE_HFLAGS_HPT3XX,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- },{ /* 4 */
- .name = "HPT374",
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .udma_mask = ATA_UDMA5,
- .port_ops = &hpt3xx_port_ops,
- .dma_ops = &hpt37x_dma_ops,
- .host_flags = IDE_HFLAGS_HPT3XX,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- },{ /* 5 */
- .name = "HPT372N",
+ },
+ { /* 1: HPT3xx */
+ .name = DRV_NAME,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
@@ -1536,10 +1503,12 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
const struct hpt_info *info = NULL;
+ struct hpt_info *dyn_info;
struct pci_dev *dev2 = NULL;
struct ide_port_info d;
u8 idx = id->driver_data;
u8 rev = dev->revision;
+ int ret;
if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1))
return -ENODEV;
@@ -1576,24 +1545,35 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
break;
}
- d = hpt366_chipsets[idx];
+ printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name);
+
+ d = hpt366_chipsets[min_t(u8, idx, 1)];
- d.name = info->chip_name;
d.udma_mask = info->udma_mask;
/* fixup ->dma_ops for HPT370/HPT370A */
if (info == &hpt370 || info == &hpt370a)
d.dma_ops = &hpt370_dma_ops;
- pci_set_drvdata(dev, (void *)info);
-
if (info == &hpt36x || info == &hpt374)
dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
- if (dev2) {
- int ret;
+ dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL);
+ if (dyn_info == NULL) {
+ printk(KERN_ERR "%s %s: out of memory!\n",
+ d.name, pci_name(dev));
+ pci_dev_put(dev2);
+ return -ENOMEM;
+ }
- pci_set_drvdata(dev2, (void *)info);
+ /*
+ * Copy everything from a static "template" structure
+ * to just allocated per-chip hpt_info structure.
+ */
+ memcpy(dyn_info, info, sizeof(*dyn_info));
+
+ if (dev2) {
+ memcpy(dyn_info + 1, info, sizeof(*dyn_info));
if (info == &hpt374)
hpt374_init(dev, dev2);
@@ -1602,13 +1582,30 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
}
- ret = ide_setup_pci_devices(dev, dev2, &d);
- if (ret < 0)
+ ret = ide_pci_init_two(dev, dev2, &d, dyn_info);
+ if (ret < 0) {
pci_dev_put(dev2);
+ kfree(dyn_info);
+ }
return ret;
}
- return ide_setup_pci_device(dev, &d);
+ ret = ide_pci_init_one(dev, &d, dyn_info);
+ if (ret < 0)
+ kfree(dyn_info);
+
+ return ret;
+}
+
+static void __devexit hpt366_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct ide_info *info = host->host_priv;
+ struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+ ide_pci_remove(dev);
+ pci_dev_put(dev2);
+ kfree(info);
}
static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
@@ -1622,18 +1619,27 @@ static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
};
MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver hpt366_pci_driver = {
.name = "HPT366_IDE",
.id_table = hpt366_pci_tbl,
.probe = hpt366_init_one,
+ .remove = __devexit_p(hpt366_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init hpt366_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&hpt366_pci_driver);
+}
+
+static void __exit hpt366_ide_exit(void)
+{
+ pci_unregister_driver(&hpt366_pci_driver);
}
module_init(hpt366_ide_init);
+module_exit(hpt366_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index 9053c8771e6..7c2feeb3c5e 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -10,10 +10,11 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "it8213"
+
/**
* it8213_set_pio_mode - set host controller for PIO mode
* @drive: drive
@@ -139,7 +140,7 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
}
-static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif)
+static u8 it8213_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 reg42h = 0;
@@ -155,23 +156,17 @@ static const struct ide_port_ops it8213_port_ops = {
.cable_detect = it8213_cable_detect,
};
-#define DECLARE_ITE_DEV(name_str) \
- { \
- .name = name_str, \
- .enablebits = { {0x41, 0x80, 0x80} }, \
- .port_ops = &it8213_port_ops, \
- .host_flags = IDE_HFLAG_SINGLE, \
- .pio_mask = ATA_PIO4, \
- .swdma_mask = ATA_SWDMA2_ONLY, \
- .mwdma_mask = ATA_MWDMA12_ONLY, \
- .udma_mask = ATA_UDMA6, \
- }
-
-static const struct ide_port_info it8213_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_ITE_DEV("IT8213"),
+static const struct ide_port_info it8213_chipset __devinitdata = {
+ .name = DRV_NAME,
+ .enablebits = { {0x41, 0x80, 0x80} },
+ .port_ops = &it8213_port_ops,
+ .host_flags = IDE_HFLAG_SINGLE,
+ .pio_mask = ATA_PIO4,
+ .swdma_mask = ATA_SWDMA2_ONLY,
+ .mwdma_mask = ATA_MWDMA12_ONLY,
+ .udma_mask = ATA_UDMA6,
};
-
/**
* it8213_init_one - pci layer discovery entry
* @dev: PCI device
@@ -184,8 +179,7 @@ static const struct ide_port_info it8213_chipsets[] __devinitdata = {
static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]);
- return 0;
+ return ide_pci_init_one(dev, &it8213_chipset, NULL);
}
static const struct pci_device_id it8213_pci_tbl[] = {
@@ -195,18 +189,27 @@ static const struct pci_device_id it8213_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver it8213_pci_driver = {
.name = "ITE8213_IDE",
.id_table = it8213_pci_tbl,
.probe = it8213_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init it8213_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&it8213_pci_driver);
+}
+
+static void __exit it8213_ide_exit(void)
+{
+ pci_unregister_driver(&it8213_pci_driver);
}
module_init(it8213_ide_init);
+module_exit(it8213_ide_exit);
MODULE_AUTHOR("Jack Lee, Alan Cox");
MODULE_DESCRIPTION("PCI driver module for the ITE 8213");
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 6ab04115286..995e18bb313 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -63,10 +63,11 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "it821x"
+
struct it821x_dev
{
unsigned int smart:1, /* Are we in smart raid mode */
@@ -137,8 +138,7 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
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;
- u8 conf;
+ u8 unit = drive->dn & 1, conf;
/* Program UDMA timing bits */
if(itdev->clock_mode == ATA_66)
@@ -167,13 +167,11 @@ 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);
+ ide_drive_t *pair;
+ int clock, altclock, sel = 0;
+ u8 unit = drive->dn & 1, v;
- u8 unit = drive->select.b.unit;
- ide_drive_t *pair = &hwif->drives[1-unit];
-
- int clock, altclock;
- u8 v;
- int sel = 0;
+ pair = &hwif->drives[1 - unit];
if(itdev->want[0][0] > itdev->want[1][0]) {
clock = itdev->want[0][1];
@@ -239,16 +237,17 @@ static void it821x_clock_strategy(ide_drive_t *drive)
static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
- ide_drive_t *pair = &hwif->drives[1 - unit];
- u8 set_pio = pio;
+ ide_drive_t *pair;
+ u8 unit = drive->dn & 1, set_pio = pio;
/* Spec says 89 ref driver uses 88 */
static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
+ pair = &hwif->drives[1 - unit];
+
/*
* Compute the best PIO mode we can for a given device. We must
* pick a speed that does not cause problems with the other device
@@ -285,9 +284,7 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
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;
- u8 conf;
+ u8 unit = drive->dn & 1, channel = hwif->channel, conf;
static u16 dma[] = { 0x8866, 0x3222, 0x3121 };
static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY };
@@ -324,9 +321,7 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
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;
- u8 conf;
+ u8 unit = drive->dn & 1, channel = hwif->channel, conf;
static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
@@ -368,7 +363,8 @@ static void it821x_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
+ u8 unit = drive->dn & 1;
+
if(itdev->mwdma[unit] != MWDMA_OFF)
it821x_program(drive, itdev->mwdma[unit]);
else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10)
@@ -388,9 +384,10 @@ static void it821x_dma_start(ide_drive_t *drive)
static int it821x_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- int unit = drive->select.b.unit;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int ret = __ide_dma_end(drive);
+ int ret = ide_dma_end(drive);
+ u8 unit = drive->dn & 1;
+
if(itdev->mwdma[unit] != MWDMA_OFF)
it821x_program(drive, itdev->pio[unit]);
return ret;
@@ -426,7 +423,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
* the needed logic onboard.
*/
-static u8 __devinit it821x_cable_detect(ide_hwif_t *hwif)
+static u8 it821x_cable_detect(ide_hwif_t *hwif)
{
/* The reference driver also only does disk side */
return ATA_CBL_PATA80;
@@ -441,11 +438,10 @@ static u8 __devinit it821x_cable_detect(ide_hwif_t *hwif)
* final tuning that is needed, or fixups to work around bugs.
*/
-static void __devinit it821x_quirkproc(ide_drive_t *drive)
+static void it821x_quirkproc(ide_drive_t *drive)
{
struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif);
- struct hd_driveid *id = drive->id;
- u16 *idbits = (u16 *)drive->id;
+ u16 *id = drive->id;
if (!itdev->smart) {
/*
@@ -454,7 +450,7 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
* IRQ mask as we may well be in PIO (eg rev 0x10)
* for now and we know unmasking is safe on this chipset.
*/
- drive->unmask = 1;
+ drive->dev_flags |= IDE_DFLAG_UNMASK;
} else {
/*
* Perform fixups on smart mode. We need to "lose" some
@@ -464,36 +460,36 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
*/
/* Check for RAID v native */
- if(strstr(id->model, "Integrated Technology Express")) {
+ if (strstr((char *)&id[ATA_ID_PROD],
+ "Integrated Technology Express")) {
/* In raid mode the ident block is slightly buggy
We need to set the bits so that the IDE layer knows
LBA28. LBA48 and DMA ar valid */
- id->capability |= 3; /* LBA28, DMA */
- id->command_set_2 |= 0x0400; /* LBA48 valid */
- id->cfs_enable_2 |= 0x0400; /* LBA48 on */
+ id[ATA_ID_CAPABILITY] |= (3 << 8); /* LBA28, DMA */
+ id[ATA_ID_COMMAND_SET_2] |= 0x0400; /* LBA48 valid */
+ id[ATA_ID_CFS_ENABLE_2] |= 0x0400; /* LBA48 on */
/* Reporting logic */
printk(KERN_INFO "%s: IT8212 %sRAID %d volume",
- drive->name,
- idbits[147] ? "Bootable ":"",
- idbits[129]);
- if(idbits[129] != 1)
- printk("(%dK stripe)", idbits[146]);
- printk(".\n");
+ drive->name, id[147] ? "Bootable " : "",
+ id[ATA_ID_CSFO]);
+ if (id[ATA_ID_CSFO] != 1)
+ printk(KERN_CONT "(%dK stripe)", id[146]);
+ printk(KERN_CONT ".\n");
} else {
/* Non RAID volume. Fixups to stop the core code
doing unsupported things */
- id->field_valid &= 3;
- id->queue_depth = 0;
- id->command_set_1 = 0;
- id->command_set_2 &= 0xC400;
- id->cfsse &= 0xC000;
- id->cfs_enable_1 = 0;
- id->cfs_enable_2 &= 0xC400;
- id->csf_default &= 0xC000;
- id->word127 = 0;
- id->dlf = 0;
- id->csfo = 0;
- id->cfa_power = 0;
+ id[ATA_ID_FIELD_VALID] &= 3;
+ id[ATA_ID_QUEUE_DEPTH] = 0;
+ id[ATA_ID_COMMAND_SET_1] = 0;
+ id[ATA_ID_COMMAND_SET_2] &= 0xC400;
+ id[ATA_ID_CFSSE] &= 0xC000;
+ id[ATA_ID_CFS_ENABLE_1] = 0;
+ id[ATA_ID_CFS_ENABLE_2] &= 0xC400;
+ id[ATA_ID_CSF_DEFAULT] &= 0xC000;
+ id[127] = 0;
+ id[ATA_ID_DLF] = 0;
+ id[ATA_ID_CSFO] = 0;
+ id[ATA_ID_CFA_POWER] = 0;
printk(KERN_INFO "%s: Performing identify fixups.\n",
drive->name);
}
@@ -503,8 +499,8 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
* IDE core that DMA is supported (it821x hardware
* takes care of DMA mode programming).
*/
- if (id->capability & 1) {
- id->dma_mword |= 0x0101;
+ if (ata_id_has_dma(id)) {
+ id[ATA_ID_MWDMA_MODES] |= 0x0101;
drive->current_speed = XFER_MW_DMA_0;
}
}
@@ -512,8 +508,14 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
}
static struct ide_dma_ops it821x_pass_through_dma_ops = {
+ .dma_host_set = ide_dma_host_set,
+ .dma_setup = ide_dma_setup,
+ .dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = it821x_dma_start,
.dma_end = it821x_dma_end,
+ .dma_test_irq = ide_dma_test_irq,
+ .dma_timeout = ide_dma_timeout,
+ .dma_lost_irq = ide_dma_lost_irq,
};
/**
@@ -528,8 +530,9 @@ static struct ide_dma_ops it821x_pass_through_dma_ops = {
static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev);
- struct it821x_dev *idev = itdevs[hwif->channel];
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct it821x_dev *itdevs = host->host_priv;
+ struct it821x_dev *idev = itdevs + hwif->channel;
u8 conf;
ide_set_hwifdata(hwif, idev);
@@ -562,7 +565,8 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
idev->timing10 = 1;
hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
if (idev->smart == 0)
- printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n");
+ printk(KERN_WARNING DRV_NAME " %s: revision 0x10, "
+ "workarounds activated\n", pci_name(dev));
}
if (idev->smart == 0) {
@@ -578,7 +582,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
hwif->mwdma_mask = ATA_MWDMA2;
}
-static void __devinit it8212_disable_raid(struct pci_dev *dev)
+static void it8212_disable_raid(struct pci_dev *dev)
{
/* Reset local CPU, and set BIOS not ready */
pci_write_config_byte(dev, 0x5E, 0x01);
@@ -595,18 +599,20 @@ static void __devinit it8212_disable_raid(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
}
-static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_it821x(struct pci_dev *dev)
{
u8 conf;
static char *mode[2] = { "pass through", "smart" };
/* Force the card into bypass mode if so requested */
if (it8212_noraid) {
- printk(KERN_INFO "it8212: forcing bypass mode.\n");
+ printk(KERN_INFO DRV_NAME " %s: forcing bypass mode\n",
+ pci_name(dev));
it8212_disable_raid(dev);
}
pci_read_config_byte(dev, 0x50, &conf);
- printk(KERN_INFO "it821x: controller in %s mode.\n", mode[conf & 1]);
+ printk(KERN_INFO DRV_NAME " %s: controller in %s mode\n",
+ pci_name(dev), mode[conf & 1]);
return 0;
}
@@ -618,17 +624,12 @@ static const struct ide_port_ops it821x_port_ops = {
.cable_detect = it821x_cable_detect,
};
-#define DECLARE_ITE_DEV(name_str) \
- { \
- .name = name_str, \
- .init_chipset = init_chipset_it821x, \
- .init_hwif = init_hwif_it821x, \
- .port_ops = &it821x_port_ops, \
- .pio_mask = ATA_PIO4, \
- }
-
-static const struct ide_port_info it821x_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_ITE_DEV("IT8212"),
+static const struct ide_port_info it821x_chipset __devinitdata = {
+ .name = DRV_NAME,
+ .init_chipset = init_chipset_it821x,
+ .init_hwif = init_hwif_it821x,
+ .port_ops = &it821x_port_ops,
+ .pio_mask = ATA_PIO4,
};
/**
@@ -642,23 +643,29 @@ 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)
{
- struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev;
- unsigned int i;
-
- for (i = 0; i < 2; i++) {
- itdev = kzalloc(sizeof(*itdev), GFP_KERNEL);
- if (itdev == NULL) {
- kfree(itdevs[0]);
- printk(KERN_ERR "it821x: out of memory\n");
- return -ENOMEM;
- }
+ struct it821x_dev *itdevs;
+ int rc;
- itdevs[i] = itdev;
+ itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL);
+ if (itdevs == NULL) {
+ printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev));
+ return -ENOMEM;
}
- pci_set_drvdata(dev, itdevs);
+ rc = ide_pci_init_one(dev, &it821x_chipset, itdevs);
+ if (rc)
+ kfree(itdevs);
+
+ return rc;
+}
+
+static void __devexit it821x_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct it821x_dev *itdevs = host->host_priv;
- return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
+ ide_pci_remove(dev);
+ kfree(itdevs);
}
static const struct pci_device_id it821x_pci_tbl[] = {
@@ -669,18 +676,27 @@ static const struct pci_device_id it821x_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, it821x_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver it821x_pci_driver = {
.name = "ITE821x IDE",
.id_table = it821x_pci_tbl,
.probe = it821x_init_one,
+ .remove = __devexit_p(it821x_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init it821x_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&it821x_pci_driver);
+}
+
+static void __exit it821x_ide_exit(void)
+{
+ pci_unregister_driver(&it821x_pci_driver);
}
module_init(it821x_ide_init);
+module_exit(it821x_ide_exit);
module_param_named(noraid, it8212_noraid, int, S_IRUGO);
MODULE_PARM_DESC(noraid, "Force card into bypass mode");
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 96ef7394f28..9a68433cf46 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -8,10 +8,11 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "jmicron"
+
typedef enum {
PORT_PATA0 = 0,
PORT_PATA1 = 1,
@@ -25,7 +26,7 @@ typedef enum {
* Returns the cable type.
*/
-static u8 __devinit jmicron_cable_detect(ide_hwif_t *hwif)
+static u8 jmicron_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
@@ -102,7 +103,7 @@ static const struct ide_port_ops jmicron_port_ops = {
};
static const struct ide_port_info jmicron_chipset __devinitdata = {
- .name = "JMB",
+ .name = DRV_NAME,
.enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
.port_ops = &jmicron_port_ops,
.pio_mask = ATA_PIO5,
@@ -121,7 +122,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)
{
- return ide_setup_pci_device(dev, &jmicron_chipset);
+ return ide_pci_init_one(dev, &jmicron_chipset, NULL);
}
/* All JMB PATA controllers have and will continue to have the same
@@ -148,18 +149,27 @@ static struct pci_device_id jmicron_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver jmicron_pci_driver = {
.name = "JMicron IDE",
.id_table = jmicron_pci_tbl,
.probe = jmicron_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init jmicron_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&jmicron_pci_driver);
+}
+
+static void __exit jmicron_ide_exit(void)
+{
+ pci_unregister_driver(&jmicron_pci_driver);
}
module_init(jmicron_ide_init);
+module_exit(jmicron_ide_exit);
MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes");
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index fec4955f449..13789060f40 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -11,7 +11,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
@@ -19,6 +18,8 @@
#include <asm/io.h>
+#define DRV_NAME "ns87415"
+
#ifdef CONFIG_SUPERIO
/* SUPERIO 87560 is a PoS chip that NatSem denies exists.
* Unfortunately, it's built-in on all Astro-based PA-RISC workstations
@@ -28,10 +29,6 @@
*/
#include <asm/superio.h>
-static unsigned long superio_ide_status[2];
-static unsigned long superio_ide_select[2];
-static unsigned long superio_ide_dma_status[2];
-
#define SUPERIO_IDE_MAX_RETRIES 25
/* Because of a defect in Super I/O, all reads of the PCI DMA status
@@ -40,27 +37,28 @@ static unsigned long superio_ide_dma_status[2];
*/
static u8 superio_ide_inb (unsigned long port)
{
- if (port == superio_ide_status[0] ||
- port == superio_ide_status[1] ||
- port == superio_ide_select[0] ||
- port == superio_ide_select[1] ||
- port == superio_ide_dma_status[0] ||
- port == superio_ide_dma_status[1]) {
- u8 tmp;
- int retries = SUPERIO_IDE_MAX_RETRIES;
+ u8 tmp;
+ int retries = SUPERIO_IDE_MAX_RETRIES;
- /* printk(" [ reading port 0x%x with retry ] ", port); */
+ /* printk(" [ reading port 0x%x with retry ] ", port); */
- do {
- tmp = inb(port);
- if (tmp == 0)
- udelay(50);
- } while (tmp == 0 && retries-- > 0);
+ do {
+ tmp = inb(port);
+ if (tmp == 0)
+ udelay(50);
+ } while (tmp == 0 && retries-- > 0);
- return tmp;
- }
+ return tmp;
+}
- return inb(port);
+static u8 superio_read_status(ide_hwif_t *hwif)
+{
+ return superio_ide_inb(hwif->io_ports.status_addr);
+}
+
+static u8 superio_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
}
static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
@@ -76,8 +74,10 @@ static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
}
/* be sure we're looking at the low order bits */
- outb(drive->ctl & ~0x80, io_ports->ctl_addr);
+ outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -90,7 +90,7 @@ static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
tf->device = superio_ide_inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
- outb(drive->ctl | 0x80, io_ports->ctl_addr);
+ outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = inb(io_ports->feature_addr);
@@ -105,43 +105,39 @@ static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
}
}
-static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
-{
- struct pci_dev *pdev = to_pci_dev(hwif->dev);
- u32 base, dmabase;
- u8 port = hwif->channel, tmp;
+static const struct ide_tp_ops superio_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = superio_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = superio_read_sff_dma_status,
- base = pci_resource_start(pdev, port * 2) & ~3;
- dmabase = pci_resource_start(pdev, 4) & ~3;
+ .set_irq = ide_set_irq,
- superio_ide_status[port] = base + 7;
- superio_ide_select[port] = base + 6;
- superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);
-
- /* Clear error/interrupt, enable dma */
- tmp = superio_ide_inb(superio_ide_dma_status[port]);
- outb(tmp | 0x66, superio_ide_dma_status[port]);
+ .tf_load = ide_tf_load,
+ .tf_read = superio_tf_read,
- hwif->tf_read = superio_tf_read;
-
- /* We need to override inb to workaround a SuperIO errata */
- hwif->INB = superio_ide_inb;
-}
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
-static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
+static void __devinit superio_init_iops(struct hwif_s *hwif)
{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ u32 dma_stat;
+ u8 port = hwif->channel, tmp;
- if (PCI_SLOT(dev->devfn) == 0xE)
- /* Built-in - assume it's under superio. */
- superio_ide_init_iops(hwif);
+ dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa);
+
+ /* Clear error/interrupt, enable dma */
+ tmp = superio_ide_inb(dma_stat);
+ outb(tmp | 0x66, dma_stat);
}
#endif
static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
/*
- * This routine either enables/disables (according to drive->present)
+ * This routine either enables/disables (according to IDE_DFLAG_PRESENT)
* the IRQ associated with the port (HWIF(drive)),
* and selects either PIO or DMA handshaking for the next I/O operation.
*/
@@ -157,11 +153,15 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
/* Adjust IRQ enable bit */
bit = 1 << (8 + hwif->channel);
- new = drive->present ? (new & ~bit) : (new | bit);
+
+ if (drive->dev_flags & IDE_DFLAG_PRESENT)
+ new &= ~bit;
+ else
+ new |= bit;
/* Select PIO or DMA, DMA may only be selected for one drive/channel. */
- bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
- other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1));
+ bit = 1 << (20 + (drive->dn & 1) + (hwif->channel << 1));
+ other = 1 << (20 + (1 - (drive->dn & 1)) + (hwif->channel << 1));
new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
if (new != *old) {
@@ -191,7 +191,8 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
static void ns87415_selectproc (ide_drive_t *drive)
{
- ns87415_prepare_drive (drive, drive->using_dma);
+ ns87415_prepare_drive(drive,
+ !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
}
static int ns87415_dma_end(ide_drive_t *drive)
@@ -200,14 +201,14 @@ static int ns87415_dma_end(ide_drive_t *drive)
u8 dma_stat = 0, dma_cmd = 0;
drive->waiting_for_dma = 0;
- dma_stat = hwif->INB(hwif->dma_status);
- /* get dma command mode */
- dma_cmd = hwif->INB(hwif->dma_command);
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ /* get DMA command mode */
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
/* from ERRATA: clear the INTR & ERROR bits */
- dma_cmd = hwif->INB(hwif->dma_command);
- outb(dma_cmd | 6, hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD);
/* and free any DMA resources */
ide_destroy_dmatable(drive);
/* verify good DMA status */
@@ -225,10 +226,6 @@ static int ns87415_dma_setup(ide_drive_t *drive)
return 1;
}
-#ifndef ide_default_irq
-#define ide_default_irq(irq) 0
-#endif
-
static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -280,22 +277,22 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
outb(8, hwif->io_ports.ctl_addr);
do {
udelay(50);
- stat = hwif->INB(hwif->io_ports.status_addr);
- if (stat == 0xff)
- break;
- } while ((stat & BUSY_STAT) && --timeout);
+ stat = hwif->tp_ops->read_status(hwif);
+ if (stat == 0xff)
+ break;
+ } while ((stat & ATA_BUSY) && --timeout);
#endif
}
if (!using_inta)
- hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+ hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
else if (!hwif->irq && hwif->mate && hwif->mate->irq)
hwif->irq = hwif->mate->irq; /* share IRQ with mate */
if (!hwif->dma_base)
return;
- outb(0x60, hwif->dma_status);
+ outb(0x60, hwif->dma_base + ATA_DMA_STATUS);
}
static const struct ide_port_ops ns87415_port_ops = {
@@ -314,10 +311,7 @@ static const struct ide_dma_ops ns87415_dma_ops = {
};
static const struct ide_port_info ns87415_chipset __devinitdata = {
- .name = "NS87415",
-#ifdef CONFIG_SUPERIO
- .init_iops = init_iops_ns87415,
-#endif
+ .name = DRV_NAME,
.init_hwif = init_hwif_ns87415,
.port_ops = &ns87415_port_ops,
.dma_ops = &ns87415_dma_ops,
@@ -327,7 +321,16 @@ static const struct ide_port_info ns87415_chipset __devinitdata = {
static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &ns87415_chipset);
+ struct ide_port_info d = ns87415_chipset;
+
+#ifdef CONFIG_SUPERIO
+ if (PCI_SLOT(dev->devfn) == 0xE) {
+ /* Built-in - assume it's under superio. */
+ d.init_iops = superio_init_iops;
+ d.tp_ops = &superio_tp_ops;
+ }
+#endif
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id ns87415_pci_tbl[] = {
@@ -336,18 +339,27 @@ static const struct pci_device_id ns87415_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver ns87415_pci_driver = {
.name = "NS87415_IDE",
.id_table = ns87415_pci_tbl,
.probe = ns87415_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init ns87415_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&ns87415_pci_driver);
+}
+
+static void __exit ns87415_ide_exit(void)
+{
+ pci_unregister_driver(&ns87415_pci_driver);
}
module_init(ns87415_ide_init);
+module_exit(ns87415_ide_exit);
MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for NS87415 IDE");
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 725c80508d9..6048eda3cd6 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -85,11 +85,12 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
+#define DRV_NAME "opti621"
+
#define READ_REG 0 /* index of Read cycle timing register */
#define WRITE_REG 1 /* index of Write cycle timing register */
#define CNTRL_REG 3 /* index of Control register */
@@ -135,7 +136,7 @@ static u8 read_reg(int reg)
static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *pair = ide_get_paired_drive(drive);
+ ide_drive_t *pair = ide_get_pair_dev(drive);
unsigned long flags;
u8 tim, misc, addr_pio = pio, clk;
@@ -151,7 +152,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->drive_data = XFER_PIO_0 + pio;
- if (pair->present) {
+ if (pair) {
if (pair->drive_data && pair->drive_data < drive->drive_data)
addr_pio = pair->drive_data - XFER_PIO_0;
}
@@ -178,7 +179,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
misc = addr_timings[clk][addr_pio];
/* select Index-0/1 for Register-A/B */
- write_reg(drive->select.b.unit, MISC_REG);
+ write_reg(drive->dn & 1, MISC_REG);
/* set read cycle timings */
write_reg(tim, READ_REG);
/* set write cycle timings */
@@ -200,7 +201,7 @@ static const struct ide_port_ops opti621_port_ops = {
};
static const struct ide_port_info opti621_chipset __devinitdata = {
- .name = "OPTI621/X",
+ .name = DRV_NAME,
.enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
.port_ops = &opti621_port_ops,
.host_flags = IDE_HFLAG_NO_DMA,
@@ -209,7 +210,7 @@ static const struct ide_port_info opti621_chipset __devinitdata = {
static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &opti621_chipset);
+ return ide_pci_init_one(dev, &opti621_chipset, NULL);
}
static const struct pci_device_id opti621_pci_tbl[] = {
@@ -219,18 +220,27 @@ static const struct pci_device_id opti621_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver opti621_pci_driver = {
.name = "Opti621_IDE",
.id_table = opti621_pci_tbl,
.probe = opti621_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init opti621_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&opti621_pci_driver);
+}
+
+static void __exit opti621_ide_exit(void)
+{
+ pci_unregister_driver(&opti621_pci_driver);
}
module_init(opti621_ide_init);
+module_exit(opti621_ide_exit);
MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord");
MODULE_DESCRIPTION("PCI driver module for Opti621 IDE");
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 070df8ab3b2..211ae46e3e0 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -19,7 +19,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
@@ -31,6 +30,8 @@
#include <asm/pci-bridge.h>
#endif
+#define DRV_NAME "pdc202xx_new"
+
#undef DEBUG
#ifdef DEBUG
@@ -191,7 +192,7 @@ static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
}
-static u8 __devinit pdcnew_cable_detect(ide_hwif_t *hwif)
+static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
{
if (get_indexed_reg(hwif, 0x0b) & 0x04)
return ATA_CBL_PATA40;
@@ -201,10 +202,10 @@ static u8 __devinit pdcnew_cable_detect(ide_hwif_t *hwif)
static void pdcnew_quirkproc(ide_drive_t *drive)
{
- const char **list, *model = drive->id->model;
+ const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
for (list = pdc_quirk_drives; *list != NULL; list++)
- if (strstr(model, *list) != NULL) {
+ if (strstr(m, *list) != NULL) {
drive->quirk_list = 2;
return;
}
@@ -225,7 +226,7 @@ static void pdcnew_reset(ide_drive_t *drive)
* read_counter - Read the byte count registers
* @dma_base: for the port address
*/
-static long __devinit read_counter(u32 dma_base)
+static long read_counter(u32 dma_base)
{
u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08;
u8 cnt0, cnt1, cnt2, cnt3;
@@ -265,7 +266,7 @@ static long __devinit read_counter(u32 dma_base)
* @dma_base: for the port address
* E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock.
*/
-static long __devinit detect_pll_input_clock(unsigned long dma_base)
+static long detect_pll_input_clock(unsigned long dma_base)
{
struct timeval start_time, end_time;
long start_count, end_count;
@@ -308,7 +309,7 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base)
}
#ifdef CONFIG_PPC_PMAC
-static void __devinit apple_kiwi_init(struct pci_dev *pdev)
+static void apple_kiwi_init(struct pci_dev *pdev)
{
struct device_node *np = pci_device_to_OF_node(pdev);
u8 conf;
@@ -324,8 +325,9 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev)
}
#endif /* CONFIG_PPC_PMAC */
-static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_pdcnew(struct pci_dev *dev)
{
+ const char *name = DRV_NAME;
unsigned long dma_base = pci_resource_start(dev, 4);
unsigned long sec_dma_base = dma_base + 0x08;
long pll_input, pll_output, ratio;
@@ -358,12 +360,13 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
* registers setting.
*/
pll_input = detect_pll_input_clock(dma_base);
- printk("%s: PLL input clock is %ld kHz\n", name, pll_input / 1000);
+ printk(KERN_INFO "%s %s: PLL input clock is %ld kHz\n",
+ name, pci_name(dev), pll_input / 1000);
/* Sanity check */
if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) {
- printk(KERN_ERR "%s: Bad PLL input clock %ld Hz, giving up!\n",
- name, pll_input);
+ printk(KERN_ERR "%s %s: Bad PLL input clock %ld Hz, giving up!"
+ "\n", name, pci_name(dev), pll_input);
goto out;
}
@@ -399,7 +402,8 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
r = 0x00;
} else {
/* Invalid ratio */
- printk(KERN_ERR "%s: Bad ratio %ld, giving up!\n", name, ratio);
+ printk(KERN_ERR "%s %s: Bad ratio %ld, giving up!\n",
+ name, pci_name(dev), ratio);
goto out;
}
@@ -409,7 +413,8 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
if (unlikely(f < 0 || f > 127)) {
/* Invalid F */
- printk(KERN_ERR "%s: F[%d] invalid!\n", name, f);
+ printk(KERN_ERR "%s %s: F[%d] invalid!\n",
+ name, pci_name(dev), f);
goto out;
}
@@ -455,8 +460,8 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
if (dev2->irq != dev->irq) {
dev2->irq = dev->irq;
- printk(KERN_INFO "PDC20270: PCI config space "
- "interrupt fixed\n");
+ printk(KERN_INFO DRV_NAME " %s: PCI config space "
+ "interrupt fixed\n", pci_name(dev));
}
return dev2;
@@ -473,9 +478,9 @@ static const struct ide_port_ops pdcnew_port_ops = {
.cable_detect = pdcnew_cable_detect,
};
-#define DECLARE_PDCNEW_DEV(name_str, udma) \
+#define DECLARE_PDCNEW_DEV(udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_pdcnew, \
.port_ops = &pdcnew_port_ops, \
.host_flags = IDE_HFLAG_POST_SET_MODE | \
@@ -487,13 +492,8 @@ static const struct ide_port_ops pdcnew_port_ops = {
}
static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_PDCNEW_DEV("PDC20268", ATA_UDMA5),
- /* 1 */ DECLARE_PDCNEW_DEV("PDC20269", ATA_UDMA6),
- /* 2 */ DECLARE_PDCNEW_DEV("PDC20270", ATA_UDMA5),
- /* 3 */ DECLARE_PDCNEW_DEV("PDC20271", ATA_UDMA6),
- /* 4 */ DECLARE_PDCNEW_DEV("PDC20275", ATA_UDMA6),
- /* 5 */ DECLARE_PDCNEW_DEV("PDC20276", ATA_UDMA6),
- /* 6 */ DECLARE_PDCNEW_DEV("PDC20277", ATA_UDMA6),
+ /* 0: PDC202{68,70} */ DECLARE_PDCNEW_DEV(ATA_UDMA5),
+ /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6),
};
/**
@@ -507,13 +507,10 @@ static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- const struct ide_port_info *d;
+ const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data];
struct pci_dev *bridge = dev->bus->self;
- u8 idx = id->driver_data;
-
- d = &pdcnew_chipsets[idx];
- if (idx == 2 && bridge &&
+ if (dev->device == PCI_DEVICE_ID_PROMISE_20270 && bridge &&
bridge->vendor == PCI_VENDOR_ID_DEC &&
bridge->device == PCI_DEVICE_ID_DEC_21150) {
struct pci_dev *dev2;
@@ -524,49 +521,67 @@ static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_de
dev2 = pdc20270_get_dev2(dev);
if (dev2) {
- int ret = ide_setup_pci_devices(dev, dev2, d);
+ int ret = ide_pci_init_two(dev, dev2, d, NULL);
if (ret < 0)
pci_dev_put(dev2);
return ret;
}
}
- if (idx == 5 && bridge &&
+ if (dev->device == PCI_DEVICE_ID_PROMISE_20276 && bridge &&
bridge->vendor == PCI_VENDOR_ID_INTEL &&
(bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
- printk(KERN_INFO "PDC20276: attached to I2O RAID controller, "
- "skipping\n");
+ printk(KERN_INFO DRV_NAME " %s: attached to I2O RAID controller,"
+ " skipping\n", pci_name(dev));
return -ENODEV;
}
- return ide_setup_pci_device(dev, d);
+ return ide_pci_init_one(dev, d, NULL);
+}
+
+static void __devexit pdc202new_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+ ide_pci_remove(dev);
+ pci_dev_put(dev2);
}
static const struct pci_device_id pdc202new_pci_tbl[] = {
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 },
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 2 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 3 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 4 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 5 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 6 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 0 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 1 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver pdc202new_pci_driver = {
.name = "Promise_IDE",
.id_table = pdc202new_pci_tbl,
.probe = pdc202new_init_one,
+ .remove = __devexit_p(pdc202new_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init pdc202new_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&pdc202new_pci_driver);
+}
+
+static void __exit pdc202new_ide_exit(void)
+{
+ pci_unregister_driver(&pdc202new_pci_driver);
}
module_init(pdc202new_ide_init);
+module_exit(pdc202new_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher");
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index fca89eda5c0..799557c25ee 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -13,13 +13,14 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <asm/io.h>
+#define DRV_NAME "pdc202xx_old"
+
#define PDC202XX_DEBUG_DRIVE_INFO 0
static const char *pdc_quirk_drives[] = {
@@ -84,7 +85,7 @@ static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
* Prefetch_EN / IORDY_EN / PA[3:0] bits of register A
*/
AP &= ~0x3f;
- if (drive->id->capability & 4)
+ if (ata_id_iordy_disable(drive->id))
AP |= 0x20; /* set IORDY_EN bit */
if (drive->media == ide_disk)
AP |= 0x10; /* set Prefetch_EN bit */
@@ -115,7 +116,7 @@ static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
}
-static u8 __devinit pdc2026x_cable_detect(ide_hwif_t *hwif)
+static u8 pdc2026x_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10);
@@ -152,10 +153,10 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
static void pdc202xx_quirkproc(ide_drive_t *drive)
{
- const char **list, *model = drive->id->model;
+ const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
for (list = pdc_quirk_drives; *list != NULL; list++)
- if (strstr(model, *list) != NULL) {
+ if (strstr(m, *list) != NULL) {
drive->quirk_list = 2;
return;
}
@@ -167,7 +168,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
{
if (drive->current_speed > XFER_UDMA_2)
pdc_old_enable_66MHz_clock(drive->hwif);
- if (drive->media != ide_disk || drive->addressing == 1) {
+ if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
struct request *rq = HWGROUP(drive)->rq;
ide_hwif_t *hwif = HWIF(drive);
unsigned long high_16 = hwif->extra_base - 16;
@@ -187,7 +188,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
static int pdc202xx_dma_end(ide_drive_t *drive)
{
- if (drive->media != ide_disk || drive->addressing == 1) {
+ if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
ide_hwif_t *hwif = HWIF(drive);
unsigned long high_16 = hwif->extra_base - 16;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
@@ -199,14 +200,14 @@ static int pdc202xx_dma_end(ide_drive_t *drive)
}
if (drive->current_speed > XFER_UDMA_2)
pdc_old_disable_66MHz_clock(drive->hwif);
- return __ide_dma_end(drive);
+ return ide_dma_end(drive);
}
static int pdc202xx_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long high_16 = hwif->extra_base - 16;
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 sc1d = inb(high_16 + 0x001d);
if (hwif->channel) {
@@ -263,8 +264,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
ide_dma_timeout(drive);
}
-static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
- const char *name)
+static unsigned int init_chipset_pdc202xx(struct pci_dev *dev)
{
unsigned long dmabase = pci_resource_start(dev, 4);
u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
@@ -304,15 +304,14 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
if (irq != irq2) {
pci_write_config_byte(dev,
(PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */
- printk(KERN_INFO "%s: PCI config space interrupt "
- "mirror fixed\n", name);
+ printk(KERN_INFO "%s %s: PCI config space interrupt "
+ "mirror fixed\n", name, pci_name(dev));
}
}
}
#define IDE_HFLAGS_PDC202XX \
(IDE_HFLAG_ERROR_STOPS_FIFO | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_OFF_BOARD)
static const struct ide_port_ops pdc20246_port_ops = {
@@ -334,7 +333,7 @@ static const struct ide_dma_ops pdc20246_dma_ops = {
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = pdc202xx_dma_test_irq,
.dma_lost_irq = pdc202xx_dma_lost_irq,
.dma_timeout = pdc202xx_dma_timeout,
@@ -351,9 +350,9 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
.dma_timeout = pdc202xx_dma_timeout,
};
-#define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
+#define DECLARE_PDC2026X_DEV(udma, extra_flags) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_pdc202xx, \
.port_ops = &pdc2026x_port_ops, \
.dma_ops = &pdc2026x_dma_ops, \
@@ -364,8 +363,8 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
}
static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "PDC20246",
+ { /* 0: PDC20246 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_pdc202xx,
.port_ops = &pdc20246_port_ops,
.dma_ops = &pdc20246_dma_ops,
@@ -375,10 +374,10 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
.udma_mask = ATA_UDMA2,
},
- /* 1 */ DECLARE_PDC2026X_DEV("PDC20262", ATA_UDMA4, 0),
- /* 2 */ DECLARE_PDC2026X_DEV("PDC20263", ATA_UDMA4, 0),
- /* 3 */ DECLARE_PDC2026X_DEV("PDC20265", ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
- /* 4 */ DECLARE_PDC2026X_DEV("PDC20267", ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
+ /* 1: PDC2026{2,3} */
+ DECLARE_PDC2026X_DEV(ATA_UDMA4, 0),
+ /* 2: PDC2026{5,7} */
+ DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
};
/**
@@ -397,47 +396,57 @@ static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_dev
d = &pdc202xx_chipsets[idx];
- if (idx < 3)
+ if (idx < 2)
pdc202ata4_fixup_irq(dev, d->name);
- if (idx == 3) {
+ if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) {
struct pci_dev *bridge = dev->bus->self;
if (bridge &&
bridge->vendor == PCI_VENDOR_ID_INTEL &&
(bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
- printk(KERN_INFO "ide: Skipping Promise PDC20265 "
- "attached to I2O RAID controller\n");
+ printk(KERN_INFO DRV_NAME " %s: skipping Promise "
+ "PDC20265 attached to I2O RAID controller\n",
+ pci_name(dev));
return -ENODEV;
}
}
- return ide_setup_pci_device(dev, d);
+ return ide_pci_init_one(dev, d, NULL);
}
static const struct pci_device_id pdc202xx_pci_tbl[] = {
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 },
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 2 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 3 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 4 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver pdc202xx_pci_driver = {
.name = "Promise_Old_IDE",
.id_table = pdc202xx_pci_tbl,
.probe = pdc202xx_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init pdc202xx_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&pdc202xx_pci_driver);
+}
+
+static void __exit pdc202xx_ide_exit(void)
+{
+ pci_unregister_driver(&pdc202xx_pci_driver);
}
module_init(pdc202xx_ide_init);
+module_exit(pdc202xx_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
MODULE_DESCRIPTION("PCI driver module for older Promise IDE");
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index f04738d14a6..d63f9fdca76 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -48,12 +48,13 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
+#define DRV_NAME "piix"
+
static int no_piix_dma;
/**
@@ -198,13 +199,12 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
/**
* init_chipset_ich - set up the ICH chipset
* @dev: PCI device to set up
- * @name: Name of the device
*
* Initialize the PCI device as required. For the ICH this turns
* out to be nice and simple.
*/
-static unsigned int __devinit init_chipset_ich(struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_ich(struct pci_dev *dev)
{
u32 extra = 0;
@@ -215,21 +215,30 @@ static unsigned int __devinit init_chipset_ich(struct pci_dev *dev, const char *
}
/**
- * piix_dma_clear_irq - clear BMDMA status
- * @drive: IDE drive to clear
+ * ich_clear_irq - clear BMDMA status
+ * @drive: IDE drive
*
- * Called from ide_intr() for PIO interrupts
- * to clear BMDMA status as needed by ICHx
+ * ICHx contollers set DMA INTR no matter DMA or PIO.
+ * BMDMA status might need to be cleared even for
+ * PIO interrupts to prevent spurious/lost IRQ.
*/
-static void piix_dma_clear_irq(ide_drive_t *drive)
+static void ich_clear_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 dma_stat;
+ /*
+ * ide_dma_end() needs BMDMA status for error checking.
+ * So, skip clearing BMDMA status here and leave it
+ * to ide_dma_end() if this is DMA interrupt.
+ */
+ if (drive->waiting_for_dma || hwif->dma_base == 0)
+ return;
+
/* clear the INTR & ERROR bits */
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* Should we force the bit as well ? */
- outb(dma_stat, hwif->dma_status);
+ outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
}
struct ich_laptop {
@@ -249,13 +258,14 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
+ { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
{ 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
/* end marker */
{ 0, }
};
-static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
+static u8 piix_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
const struct ich_laptop *lap = &ich_laptop[0];
@@ -293,30 +303,28 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
}
-static void __devinit init_hwif_ich(ide_hwif_t *hwif)
-{
- init_hwif_piix(hwif);
-
- /* ICHx need to clear the BMDMA status for all interrupts */
- if (hwif->dma_base)
- hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
-}
-
static const struct ide_port_ops piix_port_ops = {
.set_pio_mode = piix_set_pio_mode,
.set_dma_mode = piix_set_dma_mode,
.cable_detect = piix_cable_detect,
};
+static const struct ide_port_ops ich_port_ops = {
+ .set_pio_mode = piix_set_pio_mode,
+ .set_dma_mode = piix_set_dma_mode,
+ .clear_irq = ich_clear_irq,
+ .cable_detect = piix_cable_detect,
+};
+
#ifndef CONFIG_IA64
#define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
#else
#define IDE_HFLAGS_PIIX 0
#endif
-#define DECLARE_PIIX_DEV(name_str, udma) \
+#define DECLARE_PIIX_DEV(udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_hwif = init_hwif_piix, \
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
.port_ops = &piix_port_ops, \
@@ -327,13 +335,13 @@ static const struct ide_port_ops piix_port_ops = {
.udma_mask = udma, \
}
-#define DECLARE_ICH_DEV(name_str, udma) \
+#define DECLARE_ICH_DEV(udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_ich, \
- .init_hwif = init_hwif_ich, \
+ .init_hwif = init_hwif_piix, \
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
- .port_ops = &piix_port_ops, \
+ .port_ops = &ich_port_ops, \
.host_flags = IDE_HFLAGS_PIIX, \
.pio_mask = ATA_PIO4, \
.swdma_mask = ATA_SWDMA2_ONLY, \
@@ -342,45 +350,31 @@ static const struct ide_port_ops piix_port_ops = {
}
static const struct ide_port_info piix_pci_info[] __devinitdata = {
- /* 0 */ DECLARE_PIIX_DEV("PIIXa", 0x00), /* no udma */
- /* 1 */ DECLARE_PIIX_DEV("PIIXb", 0x00), /* no udma */
-
- /* 2 */
+ /* 0: MPIIX */
{ /*
* MPIIX actually has only a single IDE channel mapped to
* the primary or secondary ports depending on the value
* of the bit 14 of the IDETIM register at offset 0x6c
*/
- .name = "MPIIX",
+ .name = DRV_NAME,
.enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
.host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA |
IDE_HFLAGS_PIIX,
.pio_mask = ATA_PIO4,
/* This is a painful system best to let it self tune for now */
},
-
- /* 3 */ DECLARE_PIIX_DEV("PIIX3", 0x00), /* no udma */
- /* 4 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
- /* 5 */ DECLARE_ICH_DEV("ICH0", ATA_UDMA2),
- /* 6 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
- /* 7 */ DECLARE_ICH_DEV("ICH", ATA_UDMA4),
- /* 8 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA4),
- /* 9 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
- /* 10 */ DECLARE_ICH_DEV("ICH2", ATA_UDMA5),
- /* 11 */ DECLARE_ICH_DEV("ICH2M", ATA_UDMA5),
- /* 12 */ DECLARE_ICH_DEV("ICH3M", ATA_UDMA5),
- /* 13 */ DECLARE_ICH_DEV("ICH3", ATA_UDMA5),
- /* 14 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
- /* 15 */ DECLARE_ICH_DEV("ICH5", ATA_UDMA5),
- /* 16 */ DECLARE_ICH_DEV("C-ICH", ATA_UDMA5),
- /* 17 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
- /* 18 */ DECLARE_ICH_DEV("ICH5-SATA", ATA_UDMA5),
- /* 19 */ DECLARE_ICH_DEV("ICH5", ATA_UDMA5),
- /* 20 */ DECLARE_ICH_DEV("ICH6", ATA_UDMA5),
- /* 21 */ DECLARE_ICH_DEV("ICH7", ATA_UDMA5),
- /* 22 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
- /* 23 */ DECLARE_ICH_DEV("ESB2", ATA_UDMA5),
- /* 24 */ DECLARE_ICH_DEV("ICH8M", ATA_UDMA5),
+ /* 1: PIIXa/PIIXb/PIIX3 */
+ DECLARE_PIIX_DEV(0x00), /* no udma */
+ /* 2: PIIX4 */
+ DECLARE_PIIX_DEV(ATA_UDMA2),
+ /* 3: ICH0 */
+ DECLARE_ICH_DEV(ATA_UDMA2),
+ /* 4: ICH */
+ DECLARE_ICH_DEV(ATA_UDMA4),
+ /* 5: PIIX4 */
+ DECLARE_PIIX_DEV(ATA_UDMA4),
+ /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
+ DECLARE_ICH_DEV(ATA_UDMA5),
};
/**
@@ -394,7 +388,7 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = {
static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &piix_pci_info[id->driver_data]);
+ return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL);
}
/**
@@ -421,56 +415,65 @@ static void __devinit piix_check_450nx(void)
no_piix_dma = 2;
}
if(no_piix_dma)
- printk(KERN_WARNING "piix: 450NX errata present, disabling IDE DMA.\n");
+ printk(KERN_WARNING DRV_NAME ": 450NX errata present, disabling IDE DMA.\n");
if(no_piix_dma == 2)
- printk(KERN_WARNING "piix: A BIOS update may resolve this.\n");
+ printk(KERN_WARNING DRV_NAME ": A BIOS update may resolve this.\n");
}
static const struct pci_device_id piix_pci_tbl[] = {
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 0 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 2 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 3 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 4 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 5 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 6 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 7 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 8 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 9 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 10 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 11 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 12 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 13 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 14 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 15 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 16 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 17 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 1 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 0 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 1 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 2 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 3 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 2 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 4 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 5 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 2 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 6 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 18 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 6 },
#endif
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 19 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 20 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 21 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 22 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 23 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 24 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 6 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver piix_pci_driver = {
.name = "PIIX_IDE",
.id_table = piix_pci_tbl,
.probe = piix_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init piix_ide_init(void)
{
piix_check_450nx();
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&piix_pci_driver);
+}
+
+static void __exit piix_ide_exit(void)
+{
+ pci_unregister_driver(&piix_pci_driver);
}
module_init(piix_ide_init);
+module_exit(piix_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz");
MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE");
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 532154adba2..7daf0135cba 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -16,11 +16,12 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "rz1000"
+
static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -40,7 +41,7 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
}
static const struct ide_port_info rz1000_chipset __devinitdata = {
- .name = "RZ100x",
+ .name = DRV_NAME,
.init_hwif = init_hwif_rz1000,
.chipset = ide_rz1000,
.host_flags = IDE_HFLAG_NO_DMA,
@@ -48,7 +49,7 @@ static const struct ide_port_info rz1000_chipset __devinitdata = {
static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &rz1000_chipset);
+ return ide_pci_init_one(dev, &rz1000_chipset, NULL);
}
static const struct pci_device_id rz1000_pci_tbl[] = {
@@ -58,18 +59,25 @@ static const struct pci_device_id rz1000_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver rz1000_pci_driver = {
.name = "RZ1000_IDE",
.id_table = rz1000_pci_tbl,
.probe = rz1000_init_one,
+ .remove = ide_pci_remove,
};
static int __init rz1000_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&rz1000_pci_driver);
+}
+
+static void __exit rz1000_ide_exit(void)
+{
+ pci_unregister_driver(&rz1000_pci_driver);
}
module_init(rz1000_ide_init);
+module_exit(rz1000_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE");
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 14c787b5d95..f1a8758e3a9 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
@@ -22,6 +21,8 @@
#include <asm/io.h>
+#define DRV_NAME "sc1200"
+
#define SC1200_REV_A 0x00
#define SC1200_REV_B1 0x01
#define SC1200_REV_B3 0x02
@@ -102,17 +103,19 @@ static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
static u8 sc1200_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
- struct hd_driveid *mateid = mate->id;
+ ide_drive_t *mate = ide_get_pair_dev(drive);
+ u16 *mateid = mate->id;
u8 mask = hwif->ultra_mask;
- if (mate->present == 0)
+ if (mate == NULL)
goto out;
- if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
- if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+ if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
+ if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
+ (mateid[ATA_ID_UDMA_MODES] & 7))
goto out;
- if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+ if ((mateid[ATA_ID_FIELD_VALID] & 2) &&
+ (mateid[ATA_ID_MWDMA_MODES] & 7))
mask = 0;
}
out:
@@ -123,7 +126,6 @@ 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;
@@ -152,7 +154,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
else
timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
- if (unit == 0) { /* are we configuring drive0? */
+ if ((drive->dn & 1) == 0) {
pci_read_config_dword(dev, basereg + 4, &reg);
timings |= reg & 0x80000000; /* preserve PIO format bit */
pci_write_config_dword(dev, basereg + 4, timings);
@@ -213,7 +215,8 @@ 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);
ide_dma_off_quietly(drive);
- if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
+ if (ide_set_dma_mode(drive, mode) == 0 &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA))
hwif->dma_ops->dma_host_set(drive, 1);
return;
}
@@ -234,21 +237,11 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
* we only save state when going from full power to less
*/
if (state.event == PM_EVENT_ON) {
- struct sc1200_saved_state *ss;
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct sc1200_saved_state *ss = host->host_priv;
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);
- }
-
- /*
* save timing registers
* (this may be unnecessary if BIOS also does it)
*/
@@ -263,7 +256,8 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
static int sc1200_resume (struct pci_dev *dev)
{
- struct sc1200_saved_state *ss;
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct sc1200_saved_state *ss = host->host_priv;
unsigned int r;
int i;
@@ -271,16 +265,12 @@ static int sc1200_resume (struct pci_dev *dev)
if (i)
return i;
- 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]);
- }
+ for (r = 0; r < 8; r++)
+ pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
return 0;
}
@@ -304,7 +294,7 @@ static const struct ide_dma_ops sc1200_dma_ops = {
};
static const struct ide_port_info sc1200_chipset __devinitdata = {
- .name = "SC1200",
+ .name = DRV_NAME,
.port_ops = &sc1200_port_ops,
.dma_ops = &sc1200_dma_ops,
.host_flags = IDE_HFLAG_SERIALIZE |
@@ -317,7 +307,19 @@ static const struct ide_port_info sc1200_chipset __devinitdata = {
static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &sc1200_chipset);
+ struct sc1200_saved_state *ss = NULL;
+ int rc;
+
+#ifdef CONFIG_PM
+ ss = kmalloc(sizeof(*ss), GFP_KERNEL);
+ if (ss == NULL)
+ return -ENOMEM;
+#endif
+ rc = ide_pci_init_one(dev, &sc1200_chipset, ss);
+ if (rc)
+ kfree(ss);
+
+ return rc;
}
static const struct pci_device_id sc1200_pci_tbl[] = {
@@ -326,10 +328,11 @@ static const struct pci_device_id sc1200_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver sc1200_pci_driver = {
.name = "SC1200_IDE",
.id_table = sc1200_pci_tbl,
.probe = sc1200_init_one,
+ .remove = ide_pci_remove,
#ifdef CONFIG_PM
.suspend = sc1200_suspend,
.resume = sc1200_resume,
@@ -338,10 +341,16 @@ static struct pci_driver driver = {
static int __init sc1200_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&sc1200_pci_driver);
+}
+
+static void __exit sc1200_ide_exit(void)
+{
+ pci_unregister_driver(&sc1200_pci_driver);
}
module_init(sc1200_ide_init);
+module_exit(sc1200_ide_exit);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE");
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 910fb00deb7..9ce1d805992 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -26,7 +26,6 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -65,7 +64,7 @@
static struct scc_ports {
unsigned long ctl, dma;
- ide_hwif_t *hwif; /* for removing port from system */
+ struct ide_host *host; /* for removing port from system */
} scc_ports[MAX_HWIFS];
/* PIO transfer mode table */
@@ -126,6 +125,46 @@ static u8 scc_ide_inb(unsigned long port)
return (u8)data;
}
+static void scc_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+ out_be32((void *)hwif->io_ports.command_addr, cmd);
+ eieio();
+ in_be32((void *)(hwif->dma_base + 0x01c));
+ eieio();
+}
+
+static u8 scc_read_status(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)hwif->io_ports.status_addr);
+}
+
+static u8 scc_read_altstatus(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)hwif->io_ports.ctl_addr);
+}
+
+static u8 scc_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)(hwif->dma_base + 4));
+}
+
+static void scc_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ out_be32((void *)hwif->io_ports.ctl_addr, ctl);
+ eieio();
+ in_be32((void *)(hwif->dma_base + 0x01c));
+ eieio();
+}
+
static void scc_ide_insw(unsigned long port, void *addr, u32 count)
{
u16 *ptr = (u16 *)addr;
@@ -149,17 +188,6 @@ static void scc_ide_outb(u8 addr, unsigned long port)
}
static void
-scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port)
-{
- ide_hwif_t *hwif = HWIF(drive);
-
- out_be32((void*)port, addr);
- eieio();
- in_be32((void*)(hwif->dma_base + 0x01c));
- eieio();
-}
-
-static void
scc_ide_outsw(unsigned long port, void *addr, u32 count)
{
u16 *ptr = (u16 *)addr;
@@ -263,15 +291,15 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
static void scc_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = drive->hwif;
- u8 unit = (drive->select.b.unit & 0x01);
- u8 dma_stat = scc_ide_inb(hwif->dma_status);
+ u8 unit = drive->dn & 1;
+ u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
if (on)
dma_stat |= (1 << (5 + unit));
else
dma_stat &= ~(1 << (5 + unit));
- scc_ide_outb(dma_stat, hwif->dma_status);
+ scc_ide_outb(dma_stat, hwif->dma_base + 4);
}
/**
@@ -307,13 +335,13 @@ static int scc_dma_setup(ide_drive_t *drive)
out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
/* specify r/w */
- out_be32((void __iomem *)hwif->dma_command, reading);
+ out_be32((void __iomem *)hwif->dma_base, reading);
- /* read dma_status for INTR & ERROR flags */
- dma_stat = in_be32((void __iomem *)hwif->dma_status);
+ /* read DMA status for INTR & ERROR flags */
+ dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4));
/* clear INTR & ERROR flags */
- out_be32((void __iomem *)hwif->dma_status, dma_stat|6);
+ out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
drive->waiting_for_dma = 1;
return 0;
}
@@ -321,11 +349,10 @@ static int scc_dma_setup(ide_drive_t *drive)
static void scc_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- u8 dma_cmd = scc_ide_inb(hwif->dma_command);
+ u8 dma_cmd = scc_ide_inb(hwif->dma_base);
/* start DMA */
- scc_ide_outb(dma_cmd | 1, hwif->dma_command);
- hwif->dma = 1;
+ scc_ide_outb(dma_cmd | 1, hwif->dma_base);
wmb();
}
@@ -336,17 +363,16 @@ static int __scc_dma_end(ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* get DMA command mode */
- dma_cmd = scc_ide_inb(hwif->dma_command);
+ dma_cmd = scc_ide_inb(hwif->dma_base);
/* stop DMA */
- scc_ide_outb(dma_cmd & ~1, hwif->dma_command);
+ scc_ide_outb(dma_cmd & ~1, hwif->dma_base);
/* get DMA status */
- dma_stat = scc_ide_inb(hwif->dma_status);
+ dma_stat = scc_ide_inb(hwif->dma_base + 4);
/* clear the INTR & ERROR bits */
- scc_ide_outb(dma_stat | 6, hwif->dma_status);
+ scc_ide_outb(dma_stat | 6, hwif->dma_base + 4);
/* purge DMA mappings */
ide_destroy_dmatable(drive);
/* verify good DMA status */
- hwif->dma = 0;
wmb();
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
}
@@ -362,6 +388,7 @@ static int __scc_dma_end(ide_drive_t *drive)
static int scc_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ void __iomem *dma_base = (void __iomem *)hwif->dma_base;
unsigned long intsts_port = hwif->dma_base + 0x014;
u32 reg;
int dma_stat, data_loss = 0;
@@ -370,7 +397,7 @@ static int scc_dma_end(ide_drive_t *drive)
/* errata A308 workaround: Step5 (check data loss) */
/* We don't check non ide_disk because it is limited to UDMA4 */
if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr)
- & ERR_STAT) &&
+ & ATA_ERR) &&
drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
reg = in_be32((void __iomem *)intsts_port);
if (!(reg & INTSTS_ACTEINT)) {
@@ -400,7 +427,7 @@ static int scc_dma_end(ide_drive_t *drive)
printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
@@ -415,7 +442,7 @@ static int scc_dma_end(ide_drive_t *drive)
out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
@@ -423,12 +450,12 @@ static int scc_dma_end(ide_drive_t *drive)
printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
if (reg & INTSTS_ICERR) {
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
@@ -474,7 +501,7 @@ static int scc_dma_test_irq(ide_drive_t *drive)
/* SCC errata A252,A308 workaround: Step4 */
if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr)
- & ERR_STAT) &&
+ & ATA_ERR) &&
(int_stat & INTSTS_INTRQ))
return 1;
@@ -482,9 +509,6 @@ static int scc_dma_test_irq(ide_drive_t *drive)
if (int_stat & INTSTS_IOIRQS)
return 1;
- if (!drive->waiting_for_dma)
- printk(KERN_WARNING "%s: (%s) called while not waiting\n",
- drive->name, __func__);
return 0;
}
@@ -556,17 +580,9 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
const struct ide_port_info *d)
{
struct scc_ports *ports = pci_get_drvdata(dev);
- ide_hwif_t *hwif = NULL;
- hw_regs_t hw;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- int i;
-
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "%s: too many IDE interfaces, "
- "no room in table\n", SCC_PATA_NAME);
- return -ENOMEM;
- }
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int i, rc;
memset(&hw, 0, sizeof(hw));
for (i = 0; i <= 8; i++)
@@ -574,12 +590,12 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
hw.irq = dev->irq;
hw.dev = &dev->dev;
hw.chipset = ide_pci;
- ide_init_port_hw(hwif, &hw);
- hwif->dev = &dev->dev;
- idx[0] = hwif->index;
+ rc = ide_host_add(d, hws, &host);
+ if (rc)
+ return rc;
- ide_device_add(idx, d);
+ ports->host = host;
return 0;
}
@@ -662,8 +678,6 @@ static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
- ide_set_irq(drive, 1);
-
if (task->tf_flags & IDE_TFLAG_OUT_DATA)
out_be32((void *)io_ports->data_addr,
(tf->hob_data << 8) | tf->data);
@@ -691,7 +705,7 @@ static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
scc_ide_outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
- scc_ide_outb((tf->device & HIHI) | drive->select.all,
+ scc_ide_outb((tf->device & HIHI) | drive->select,
io_ports->device_addr);
}
@@ -708,8 +722,10 @@ static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
}
/* be sure we're looking at the low order bits */
- scc_ide_outb(drive->ctl & ~0x80, io_ports->ctl_addr);
+ scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = scc_ide_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = scc_ide_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -722,7 +738,7 @@ static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
tf->device = scc_ide_inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
- scc_ide_outb(drive->ctl | 0x80, io_ports->ctl_addr);
+ scc_ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = scc_ide_inb(io_ports->feature_addr);
@@ -783,19 +799,8 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
ide_set_hwifdata(hwif, ports);
- hwif->tf_load = scc_tf_load;
- hwif->tf_read = scc_tf_read;
-
- hwif->input_data = scc_input_data;
- hwif->output_data = scc_output_data;
-
- hwif->INB = scc_ide_inb;
- hwif->OUTB = scc_ide_outb;
- hwif->OUTBSYNC = scc_ide_outbsync;
-
hwif->dma_base = dma_base;
hwif->config_data = ports->ctl;
- hwif->mmio = 1;
}
/**
@@ -816,7 +821,13 @@ static void __devinit init_iops_scc(ide_hwif_t *hwif)
init_mmio_iops_scc(hwif);
}
-static u8 __devinit scc_cable_detect(ide_hwif_t *hwif)
+static int __devinit scc_init_dma(ide_hwif_t *hwif,
+ const struct ide_port_info *d)
+{
+ return ide_allocate_dma_engine(hwif);
+}
+
+static u8 scc_cable_detect(ide_hwif_t *hwif)
{
return ATA_CBL_PATA80;
}
@@ -834,11 +845,6 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
{
struct scc_ports *ports = ide_get_hwifdata(hwif);
- ports->hwif = hwif;
-
- hwif->dma_command = hwif->dma_base;
- hwif->dma_status = hwif->dma_base + 0x04;
-
/* PTERADD */
out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
@@ -848,6 +854,21 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
}
+static const struct ide_tp_ops scc_tp_ops = {
+ .exec_command = scc_exec_command,
+ .read_status = scc_read_status,
+ .read_altstatus = scc_read_altstatus,
+ .read_sff_dma_status = scc_read_sff_dma_status,
+
+ .set_irq = scc_set_irq,
+
+ .tf_load = scc_tf_load,
+ .tf_read = scc_tf_read,
+
+ .input_data = scc_input_data,
+ .output_data = scc_output_data,
+};
+
static const struct ide_port_ops scc_port_ops = {
.set_pio_mode = scc_set_pio_mode,
.set_dma_mode = scc_set_dma_mode,
@@ -870,7 +891,9 @@ static const struct ide_dma_ops scc_dma_ops = {
{ \
.name = name_str, \
.init_iops = init_iops_scc, \
+ .init_dma = scc_init_dma, \
.init_hwif = init_hwif_scc, \
+ .tp_ops = &scc_tp_ops, \
.port_ops = &scc_port_ops, \
.dma_ops = &scc_dma_ops, \
.host_flags = IDE_HFLAG_SINGLE, \
@@ -905,15 +928,9 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
static void __devexit scc_remove(struct pci_dev *dev)
{
struct scc_ports *ports = pci_get_drvdata(dev);
- ide_hwif_t *hwif = ports->hwif;
-
- if (hwif->dmatable_cpu) {
- pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
- hwif->dmatable_cpu, hwif->dmatable_dma);
- hwif->dmatable_cpu = NULL;
- }
+ struct ide_host *host = ports->host;
- ide_unregister(hwif);
+ ide_host_remove(host);
iounmap((void*)ports->dma);
iounmap((void*)ports->ctl);
@@ -927,23 +944,23 @@ static const struct pci_device_id scc_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver scc_pci_driver = {
.name = "SCC IDE",
.id_table = scc_pci_tbl,
.probe = scc_init_one,
- .remove = scc_remove,
+ .remove = __devexit_p(scc_remove),
};
static int scc_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&scc_pci_driver);
}
module_init(scc_ide_init);
/* -- No exit code?
static void scc_ide_exit(void)
{
- ide_pci_unregister_driver(&driver);
+ ide_pci_unregister_driver(&scc_pci_driver);
}
module_exit(scc_ide_exit);
*/
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index a1fb20826a5..437bc919daf 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -32,12 +32,13 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
+#define DRV_NAME "serverworks"
+
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
@@ -55,8 +56,10 @@ static struct pci_dev *isa_dev;
static int check_in_drive_lists (ide_drive_t *drive, const char **list)
{
+ char *m = (char *)&drive->id[ATA_ID_PROD];
+
while (*list)
- if (!strcmp(*list++, drive->id->model))
+ if (!strcmp(*list++, m))
return 1;
return 0;
}
@@ -150,7 +153,7 @@ static void svwks_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 unit = (drive->select.b.unit & 0x01);
+ u8 unit = drive->dn & 1;
u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0;
@@ -172,7 +175,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_write_config_byte(dev, 0x54, ultra_enable);
}
-static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_svwks(struct pci_dev *dev)
{
unsigned int reg;
u8 btr;
@@ -188,7 +191,8 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
pci_read_config_dword(isa_dev, 0x64, &reg);
reg &= ~0x00002000; /* disable 600ns interrupt mask */
if(!(reg & 0x00004000))
- printk(KERN_DEBUG "%s: UDMA not BIOS enabled.\n", name);
+ printk(KERN_DEBUG DRV_NAME " %s: UDMA not BIOS "
+ "enabled.\n", pci_name(dev));
reg |= 0x00004000; /* enable UDMA/33 support */
pci_write_config_dword(isa_dev, 0x64, reg);
}
@@ -269,7 +273,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
return dev->irq;
}
-static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
+static u8 ata66_svwks_svwks(ide_hwif_t *hwif)
{
return ATA_CBL_PATA80;
}
@@ -281,7 +285,7 @@ static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
* Bit 14 clear = primary IDE channel does not have 80-pin cable.
* Bit 14 set = primary IDE channel has 80-pin cable.
*/
-static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
+static u8 ata66_svwks_dell(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -300,7 +304,7 @@ static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
*
* WARNING: this only works on Alpine hardware!
*/
-static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
+static u8 ata66_svwks_cobalt(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -312,7 +316,7 @@ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
return ATA_CBL_PATA40;
}
-static u8 __devinit svwks_cable_detect(ide_hwif_t *hwif)
+static u8 svwks_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -349,45 +353,47 @@ static const struct ide_port_ops svwks_port_ops = {
.cable_detect = svwks_cable_detect,
};
-#define IDE_HFLAGS_SVWKS \
- (IDE_HFLAG_LEGACY_IRQS | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE)
+#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "SvrWks OSB4",
+ { /* 0: OSB4 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &osb4_port_ops,
.host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* UDMA is problematic on OSB4 */
- },{ /* 1 */
- .name = "SvrWks CSB5",
+ },
+ { /* 1: CSB5 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
.host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 2 */
- .name = "SvrWks CSB6",
+ },
+ { /* 2: CSB6 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
.host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 3 */
- .name = "SvrWks CSB6",
+ },
+ { /* 3: CSB6-2 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
.host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 4 */
- .name = "SvrWks HT1000",
+ },
+ { /* 4: HT1000 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
.host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
@@ -424,7 +430,7 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
d.host_flags &= ~IDE_HFLAG_SINGLE;
}
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id svwks_pci_tbl[] = {
@@ -437,18 +443,27 @@ static const struct pci_device_id svwks_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver svwks_pci_driver = {
.name = "Serverworks_IDE",
.id_table = svwks_pci_tbl,
.probe = svwks_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init svwks_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&svwks_pci_driver);
+}
+
+static void __exit svwks_ide_exit(void)
+{
+ pci_unregister_driver(&svwks_pci_driver);
}
module_init(svwks_ide_init);
+module_exit(svwks_ide_exit);
MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE");
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 16a0bce17d6..dd634541ce3 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2008 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -22,7 +23,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
@@ -111,7 +111,7 @@ sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
static void
sgiioc4_maskproc(ide_drive_t * drive, int mask)
{
- writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+ writeb(ATA_DEVCTL_OBS | (mask ? 2 : 0),
(void __iomem *)drive->hwif->io_ports.ctl_addr);
}
@@ -127,7 +127,7 @@ sgiioc4_checkirq(ide_hwif_t * hwif)
return 0;
}
-static u8 sgiioc4_INB(unsigned long);
+static u8 sgiioc4_read_status(ide_hwif_t *);
static int
sgiioc4_clearirq(ide_drive_t * drive)
@@ -141,18 +141,19 @@ sgiioc4_clearirq(ide_drive_t * drive)
intr_reg = readl((void __iomem *)other_ir);
if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
/*
- * Using sgiioc4_INB to read the Status register has a side
- * effect of clearing the interrupt. The first read should
+ * Using sgiioc4_read_status to read the Status register has a
+ * side effect of clearing the interrupt. The first read should
* clear it if it is set. The second read should return
* a "clear" status if it got cleared. If not, then spin
* for a bit trying to clear it.
*/
- u8 stat = sgiioc4_INB(io_ports->status_addr);
+ u8 stat = sgiioc4_read_status(hwif);
int count = 0;
- stat = sgiioc4_INB(io_ports->status_addr);
- while ((stat & 0x80) && (count++ < 100)) {
+
+ stat = sgiioc4_read_status(hwif);
+ while ((stat & ATA_BUSY) && (count++ < 100)) {
udelay(1);
- stat = sgiioc4_INB(io_ports->status_addr);
+ stat = sgiioc4_read_status(hwif);
}
if (intr_reg & 0x02) {
@@ -304,13 +305,13 @@ sgiioc4_dma_lost_irq(ide_drive_t * drive)
ide_dma_lost_irq(drive);
}
-static u8
-sgiioc4_INB(unsigned long port)
+static u8 sgiioc4_read_status(ide_hwif_t *hwif)
{
+ unsigned long port = hwif->io_ports.status_addr;
u8 reg = (u8) readb((void __iomem *) port);
if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */
- if (reg & 0x51) { /* Not busy...check for interrupt */
+ if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */
unsigned long other_ir = port - 0x110;
unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
@@ -338,51 +339,44 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
if (dma_base == 0)
return -1;
- printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
- dma_base, dma_base + num_ports - 1);
+ printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
- if (!request_mem_region(dma_base, num_ports, hwif->name)) {
- printk(KERN_ERR
- "%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
- "ALREADY in use\n",
- __func__, hwif->name, (void *) dma_base,
- (void *) dma_base + num_ports - 1);
+ if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) {
+ printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx "
+ "already in use\n", __func__, hwif->name,
+ dma_base, dma_base + num_ports - 1);
return -1;
}
virt_dma_base = ioremap(dma_base, num_ports);
if (virt_dma_base == NULL) {
- printk(KERN_ERR
- "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
- __func__, hwif->name, dma_base, dma_base + num_ports - 1);
+ printk(KERN_ERR "%s(%s) -- ERROR: unable to map addresses "
+ "0x%lx to 0x%lx\n", __func__, hwif->name,
+ dma_base, dma_base + num_ports - 1);
goto dma_remap_failure;
}
hwif->dma_base = (unsigned long) virt_dma_base;
- hwif->dmatable_cpu = pci_alloc_consistent(dev,
- IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
- &hwif->dmatable_dma);
+ hwif->sg_max_nents = IOC4_PRD_ENTRIES;
- if (!hwif->dmatable_cpu)
- goto dma_pci_alloc_failure;
+ hwif->prd_max_nents = IOC4_PRD_ENTRIES;
+ hwif->prd_ent_size = IOC4_PRD_BYTES;
- hwif->sg_max_nents = IOC4_PRD_ENTRIES;
+ if (ide_allocate_dma_engine(hwif))
+ goto dma_pci_alloc_failure;
pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
- (dma_addr_t *) &(hwif->dma_status));
-
+ (dma_addr_t *)&hwif->extra_base);
if (pad) {
ide_set_hwifdata(hwif, pad);
return 0;
}
- 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",
+ ide_release_dma_engine(hwif);
+
+ printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n",
__func__, hwif->name);
- printk(KERN_INFO
- "Changing from DMA to PIO mode for Drive %s\n", hwif->name);
+ printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name);
dma_pci_alloc_failure:
iounmap(virt_dma_base);
@@ -439,7 +433,7 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
/* Address of the Ending DMA */
memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE);
- ending_dma_addr = cpu_to_le32(hwif->dma_status);
+ ending_dma_addr = cpu_to_le32(hwif->extra_base);
writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4));
writel(dma_direction, (void __iomem *)ioc4_dma_addr);
@@ -550,6 +544,21 @@ static int sgiioc4_dma_setup(ide_drive_t *drive)
return 0;
}
+static const struct ide_tp_ops sgiioc4_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = sgiioc4_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
+
static const struct ide_port_ops sgiioc4_port_ops = {
.set_dma_mode = sgiioc4_set_dma_mode,
/* reset DMA engine, clear IRQs */
@@ -569,8 +578,10 @@ static const struct ide_dma_ops sgiioc4_dma_ops = {
};
static const struct ide_port_info sgiioc4_port_info __devinitdata = {
+ .name = DRV_NAME,
.chipset = ide_pci,
.init_dma = ide_dma_sgiioc4,
+ .tp_ops = &sgiioc4_tp_ops,
.port_ops = &sgiioc4_port_ops,
.dma_ops = &sgiioc4_dma_ops,
.host_flags = IDE_HFLAG_MMIO,
@@ -583,17 +594,10 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
unsigned long cmd_base, irqport;
unsigned long bar0, cmd_phys_base, ctl;
void __iomem *virt_base;
- ide_hwif_t *hwif;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
struct ide_port_info d = sgiioc4_port_info;
-
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n",
- DRV_NAME);
- return -ENOMEM;
- }
+ int rc;
/* Get the CmdBlk and CtrlBlk Base Registers */
bar0 = pci_resource_start(dev, 0);
@@ -608,14 +612,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
- if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
- hwif->name)) {
- printk(KERN_ERR
- "%s : %s -- ERROR, Addresses "
- "0x%p to 0x%p ALREADY in use\n",
- __func__, hwif->name, (void *) cmd_phys_base,
- (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
- return -ENOMEM;
+ if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
+ DRV_NAME) == NULL) {
+ printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx "
+ "already in use\n", DRV_NAME, pci_name(dev),
+ cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
+ return -EBUSY;
}
/* Initialize the IO registers */
@@ -624,24 +626,27 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
hw.irq = dev->irq;
hw.chipset = ide_pci;
hw.dev = &dev->dev;
- ide_init_port_hw(hwif, &hw);
-
- hwif->dev = &dev->dev;
-
- /* The IOC4 uses MMIO rather than Port IO. */
- default_hwif_mmiops(hwif);
/* Initializing chipset IRQ Registers */
writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
- hwif->INB = &sgiioc4_INB;
-
- idx[0] = hwif->index;
+ host = ide_host_alloc(&d, hws);
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
- if (ide_device_add(idx, &d))
- return -EIO;
+ rc = ide_host_register(host, &d, hws);
+ if (rc)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
+err:
+ release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
+ iounmap(virt_base);
+ return rc;
}
static unsigned int __devinit
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 0006b9e5856..eb4faf92c57 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -39,11 +39,12 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/io.h>
+#define DRV_NAME "siimage"
+
/**
* pdev_is_sata - check if device is SATA
* @pdev: PCI device to check
@@ -94,7 +95,7 @@ static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
unsigned long base = (unsigned long)hwif->hwif_data;
base += 0xA0 + r;
- if (hwif->mmio)
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
base += hwif->channel << 6;
else
base += hwif->channel << 4;
@@ -115,21 +116,23 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long base = (unsigned long)hwif->hwif_data;
+ u8 unit = drive->dn & 1;
base += 0xA0 + r;
- if (hwif->mmio)
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
base += hwif->channel << 6;
else
base += hwif->channel << 4;
- base |= drive->select.b.unit << drive->select.b.unit;
+ base |= unit << unit;
return base;
}
static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
{
+ struct ide_host *host = pci_get_drvdata(dev);
u8 tmp = 0;
- if (pci_get_drvdata(dev))
+ if (host->host_priv)
tmp = readb((void __iomem *)addr);
else
pci_read_config_byte(dev, addr, &tmp);
@@ -139,9 +142,10 @@ static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
{
+ struct ide_host *host = pci_get_drvdata(dev);
u16 tmp = 0;
- if (pci_get_drvdata(dev))
+ if (host->host_priv)
tmp = readw((void __iomem *)addr);
else
pci_read_config_word(dev, addr, &tmp);
@@ -151,7 +155,9 @@ static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writeb(val, (void __iomem *)addr);
else
pci_write_config_byte(dev, addr, val);
@@ -159,7 +165,9 @@ static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writew(val, (void __iomem *)addr);
else
pci_write_config_word(dev, addr, val);
@@ -167,7 +175,9 @@ static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writel(val, (void __iomem *)addr);
else
pci_write_config_dword(dev, addr, val);
@@ -190,7 +200,9 @@ static u8 sil_pata_udma_filter(ide_drive_t *drive)
unsigned long base = (unsigned long)hwif->hwif_data;
u8 scsc, mask = 0;
- scsc = sil_ioread8(dev, base + (hwif->mmio ? 0x4A : 0x8A));
+ base += (hwif->host_flags & IDE_HFLAG_MMIO) ? 0x4A : 0x8A;
+
+ scsc = sil_ioread8(dev, base);
switch (scsc & 0x30) {
case 0x10: /* 133 */
@@ -211,7 +223,9 @@ static u8 sil_pata_udma_filter(ide_drive_t *drive)
static u8 sil_sata_udma_filter(ide_drive_t *drive)
{
- return strstr(drive->id->model, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6;
+ char *m = (char *)&drive->id[ATA_ID_PROD];
+
+ return strstr(m, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6;
}
/**
@@ -231,20 +245,21 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- ide_drive_t *pair = ide_get_paired_drive(drive);
+ ide_drive_t *pair = ide_get_pair_dev(drive);
u32 speedt = 0;
u16 speedp = 0;
unsigned long addr = siimage_seldev(drive, 0x04);
unsigned long tfaddr = siimage_selreg(hwif, 0x02);
unsigned long base = (unsigned long)hwif->hwif_data;
u8 tf_pio = pio;
- u8 addr_mask = hwif->channel ? (hwif->mmio ? 0xF4 : 0x84)
- : (hwif->mmio ? 0xB4 : 0x80);
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+ u8 addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84)
+ : (mmio ? 0xB4 : 0x80);
u8 mode = 0;
- u8 unit = drive->select.b.unit;
+ u8 unit = drive->dn & 1;
/* trim *taskfile* PIO to the slowest of the master/slave */
- if (pair->present) {
+ if (pair) {
u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
if (pair_pio < tf_pio)
@@ -287,16 +302,16 @@ static void sil_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);
- u16 ultra = 0, multi = 0;
- u8 mode = 0, unit = drive->select.b.unit;
unsigned long base = (unsigned long)hwif->hwif_data;
- u8 scsc = 0, addr_mask = hwif->channel ?
- (hwif->mmio ? 0xF4 : 0x84) :
- (hwif->mmio ? 0xB4 : 0x80);
+ u16 ultra = 0, multi = 0;
+ u8 mode = 0, unit = drive->dn & 1;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+ u8 scsc = 0, addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84)
+ : (mmio ? 0xB4 : 0x80);
unsigned long ma = siimage_seldev(drive, 0x08);
unsigned long ua = siimage_seldev(drive, 0x0C);
- scsc = sil_ioread8 (dev, base + (hwif->mmio ? 0x4A : 0x8A));
+ scsc = sil_ioread8 (dev, base + (mmio ? 0x4A : 0x8A));
mode = sil_ioread8 (dev, base + addr_mask);
multi = sil_ioread16(dev, ma);
ultra = sil_ioread16(dev, ua);
@@ -331,7 +346,7 @@ static int siimage_io_dma_test_irq(ide_drive_t *drive)
unsigned long addr = siimage_selreg(hwif, 1);
/* return 1 if INTR asserted */
- if (hwif->INB(hwif->dma_status) & 4)
+ if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4)
return 1;
/* return 1 if Device INTR asserted */
@@ -379,7 +394,7 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
}
/* return 1 if INTR asserted */
- if (readb((void __iomem *)hwif->dma_status) & 0x04)
+ if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
return 1;
/* return 1 if Device INTR asserted */
@@ -391,7 +406,7 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
static int siimage_dma_test_irq(ide_drive_t *drive)
{
- if (drive->hwif->mmio)
+ if (drive->hwif->host_flags & IDE_HFLAG_MMIO)
return siimage_mmio_dma_test_irq(drive);
else
return siimage_io_dma_test_irq(drive);
@@ -418,8 +433,7 @@ static int sil_sata_reset_poll(ide_drive_t *drive)
if ((sata_stat & 0x03) != 0x03) {
printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
hwif->name, sata_stat);
- HWGROUP(drive)->polling = 0;
- return ide_started;
+ return -ENXIO;
}
}
@@ -443,66 +457,24 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
}
/**
- * setup_mmio_siimage - switch controller into MMIO mode
- * @dev: PCI device we are configuring
- * @name: device name
- *
- * Attempt to put the device into MMIO mode. There are some slight
- * complications here with certain systems where the MMIO BAR isn't
- * mapped, so we have to be sure that we can fall back to I/O.
- */
-
-static unsigned int setup_mmio_siimage(struct pci_dev *dev, const char *name)
-{
- resource_size_t bar5 = pci_resource_start(dev, 5);
- unsigned long barsize = pci_resource_len(dev, 5);
- void __iomem *ioaddr;
-
- /*
- * Drop back to PIO if we can't map the MMIO. Some systems
- * seem to get terminally confused in the PCI spaces.
- */
- if (!request_mem_region(bar5, barsize, name)) {
- printk(KERN_WARNING "siimage: IDE controller MMIO ports not "
- "available.\n");
- return 0;
- }
-
- ioaddr = ioremap(bar5, barsize);
- if (ioaddr == NULL) {
- release_mem_region(bar5, barsize);
- return 0;
- }
-
- pci_set_master(dev);
- pci_set_drvdata(dev, (void *) ioaddr);
-
- return 1;
-}
-
-/**
* init_chipset_siimage - set up an SI device
* @dev: PCI device
- * @name: device name
*
* Perform the initial PCI set up for this device. Attempt to switch
* to 133 MHz clocking if the system isn't already set up to do it.
*/
-static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
- const char *name)
+static unsigned int init_chipset_siimage(struct pci_dev *dev)
{
+ struct ide_host *host = pci_get_drvdata(dev);
+ void __iomem *ioaddr = host->host_priv;
unsigned long base, scsc_addr;
- void __iomem *ioaddr = NULL;
- u8 rev = dev->revision, tmp, BA5_EN;
+ u8 rev = dev->revision, tmp;
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
- pci_read_config_byte(dev, 0x8A, &BA5_EN);
-
- if ((BA5_EN & 0x01) || pci_resource_start(dev, 5))
- if (setup_mmio_siimage(dev, name))
- ioaddr = pci_get_drvdata(dev);
+ if (ioaddr)
+ pci_set_master(dev);
base = (unsigned long)ioaddr;
@@ -569,7 +541,8 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
{ "== 100", "== 133", "== 2X PCI", "DISABLED!" };
tmp >>= 4;
- printk(KERN_INFO "%s: BASE CLOCK %s\n", name, clk_str[tmp & 3]);
+ printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s\n",
+ pci_name(dev), clk_str[tmp & 3]);
}
return 0;
@@ -590,7 +563,8 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- void *addr = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ void *addr = host->host_priv;
u8 ch = hwif->channel;
struct ide_io_ports *io_ports = &hwif->io_ports;
unsigned long base;
@@ -599,7 +573,7 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
* Fill in the basic hwif bits
*/
hwif->host_flags |= IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
+
hwif->hwif_data = addr;
/*
@@ -640,14 +614,12 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
hwif->irq = dev->irq;
hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00);
-
- hwif->mmio = 1;
}
static int is_dev_seagate_sata(ide_drive_t *drive)
{
- const char *s = &drive->id->model[0];
- unsigned len = strnlen(s, sizeof(drive->id->model));
+ const char *s = (const char *)&drive->id[ATA_ID_PROD];
+ unsigned len = strnlen(s, ATA_ID_PROD_LEN);
if ((len > 4) && (!memcmp(s, "ST", 2)))
if ((!memcmp(s + len - 2, "AS", 2)) ||
@@ -669,7 +641,7 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
* that can occur before we know what drives are present.
*/
-static void __devinit sil_quirkproc(ide_drive_t *drive)
+static void sil_quirkproc(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
@@ -691,16 +663,15 @@ static void __devinit sil_quirkproc(ide_drive_t *drive)
static void __devinit init_iops_siimage(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct ide_host *host = pci_get_drvdata(dev);
hwif->hwif_data = NULL;
/* Pessimal until we finish probing */
hwif->rqsize = 15;
- if (pci_get_drvdata(dev) == NULL)
- return;
-
- init_mmio_iops_siimage(hwif);
+ if (host->host_priv)
+ init_mmio_iops_siimage(hwif);
}
/**
@@ -710,7 +681,7 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
* Check for the presence of an ATA66 capable cable on the interface.
*/
-static u8 __devinit sil_cable_detect(ide_hwif_t *hwif)
+static u8 sil_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long addr = siimage_selreg(hwif, 0);
@@ -742,15 +713,15 @@ static const struct ide_dma_ops sil_dma_ops = {
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = siimage_dma_test_irq,
.dma_timeout = ide_dma_timeout,
.dma_lost_irq = ide_dma_lost_irq,
};
-#define DECLARE_SII_DEV(name_str, p_ops) \
+#define DECLARE_SII_DEV(p_ops) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_siimage, \
.init_iops = init_iops_siimage, \
.port_ops = p_ops, \
@@ -761,9 +732,8 @@ static const struct ide_dma_ops sil_dma_ops = {
}
static const struct ide_port_info siimage_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_SII_DEV("SiI680", &sil_pata_port_ops),
- /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA", &sil_sata_port_ops),
- /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA", &sil_sata_port_ops)
+ /* 0: SiI680 */ DECLARE_SII_DEV(&sil_pata_port_ops),
+ /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
};
/**
@@ -778,8 +748,13 @@ static const struct ide_port_info siimage_chipsets[] __devinitdata = {
static int __devinit siimage_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
+ void __iomem *ioaddr = NULL;
+ resource_size_t bar5 = pci_resource_start(dev, 5);
+ unsigned long barsize = pci_resource_len(dev, 5);
+ int rc;
struct ide_port_info d;
u8 idx = id->driver_data;
+ u8 BA5_EN;
d = siimage_chipsets[idx];
@@ -787,7 +762,7 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
static int first = 1;
if (first) {
- printk(KERN_INFO "siimage: For full SATA support you "
+ printk(KERN_INFO DRV_NAME ": For full SATA support you "
"should use the libata sata_sil module.\n");
first = 0;
}
@@ -795,31 +770,87 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
}
- return ide_setup_pci_device(dev, &d);
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ pci_read_config_byte(dev, 0x8A, &BA5_EN);
+ if ((BA5_EN & 0x01) || bar5) {
+ /*
+ * Drop back to PIO if we can't map the MMIO. Some systems
+ * seem to get terminally confused in the PCI spaces.
+ */
+ if (!request_mem_region(bar5, barsize, d.name)) {
+ printk(KERN_WARNING DRV_NAME " %s: MMIO ports not "
+ "available\n", pci_name(dev));
+ } else {
+ ioaddr = ioremap(bar5, barsize);
+ if (ioaddr == NULL)
+ release_mem_region(bar5, barsize);
+ }
+ }
+
+ rc = ide_pci_init_one(dev, &d, ioaddr);
+ if (rc) {
+ if (ioaddr) {
+ iounmap(ioaddr);
+ release_mem_region(bar5, barsize);
+ }
+ pci_disable_device(dev);
+ }
+
+ return rc;
+}
+
+static void __devexit siimage_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ void __iomem *ioaddr = host->host_priv;
+
+ ide_pci_remove(dev);
+
+ if (ioaddr) {
+ resource_size_t bar5 = pci_resource_start(dev, 5);
+ unsigned long barsize = pci_resource_len(dev, 5);
+
+ iounmap(ioaddr);
+ release_mem_region(bar5, barsize);
+ }
+
+ pci_disable_device(dev);
}
static const struct pci_device_id siimage_pci_tbl[] = {
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), 0 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112), 1 },
- { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 2 },
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 },
#endif
{ 0, },
};
MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver siimage_pci_driver = {
.name = "SiI_IDE",
.id_table = siimage_pci_tbl,
.probe = siimage_init_one,
+ .remove = __devexit_p(siimage_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init siimage_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&siimage_pci_driver);
+}
+
+static void __exit siimage_ide_exit(void)
+{
+ pci_unregister_driver(&siimage_pci_driver);
}
module_init(siimage_ide_init);
+module_exit(siimage_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Alan Cox");
MODULE_DESCRIPTION("PCI driver module for SiI IDE");
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index e127eb25ab6..ad32e18c5ba 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -47,12 +47,11 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
-#include "ide-timing.h"
+#define DRV_NAME "sis5513"
/* registers layout and init values are chipset family dependant */
@@ -382,8 +381,9 @@ static int __devinit sis_find_family(struct pci_dev *dev)
}
pci_dev_put(host);
- printk(KERN_INFO "SIS5513: %s %s controller\n",
- SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
+ printk(KERN_INFO DRV_NAME " %s: %s %s controller\n",
+ pci_name(dev), SiSHostChipInfo[i].name,
+ chipset_capability[chipset_family]);
}
if (!chipset_family) { /* Belongs to pci-quirks */
@@ -398,7 +398,8 @@ static int __devinit sis_find_family(struct pci_dev *dev)
pci_write_config_dword(dev, 0x54, idemisc);
if (trueid == 0x5518) {
- printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n");
+ printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n",
+ pci_name(dev));
chipset_family = ATA_133;
/* Check for 5513 compability mapping
@@ -407,7 +408,8 @@ static int __devinit sis_find_family(struct pci_dev *dev)
*/
if ((idemisc & 0x40000000) == 0) {
pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
- printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
+ printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n",
+ pci_name(dev));
}
}
}
@@ -431,10 +433,12 @@ static int __devinit sis_find_family(struct pci_dev *dev)
pci_dev_put(lpc_bridge);
if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
- printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
+ printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n",
+ pci_name(dev));
chipset_family = ATA_133a;
} else {
- printk(KERN_INFO "SIS5513: SiS 961 MuTIOL IDE UDMA100 controller\n");
+ printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n",
+ pci_name(dev));
chipset_family = ATA_100;
}
}
@@ -443,8 +447,7 @@ static int __devinit sis_find_family(struct pci_dev *dev)
return chipset_family;
}
-static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev,
- const char *name)
+static unsigned int init_chipset_sis5513(struct pci_dev *dev)
{
/* Make general config ops here
1/ tell IDE channels to operate in Compatibility mode only
@@ -514,7 +517,7 @@ static const struct sis_laptop sis_laptop[] = {
{ 0, }
};
-static u8 __devinit sis_cable_detect(ide_hwif_t *hwif)
+static u8 sis_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
const struct sis_laptop *lap = &sis_laptop[0];
@@ -557,7 +560,7 @@ static const struct ide_port_ops sis_ata133_port_ops = {
};
static const struct ide_port_info sis5513_chipset __devinitdata = {
- .name = "SIS5513",
+ .name = DRV_NAME,
.init_chipset = init_chipset_sis5513,
.enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
.host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
@@ -585,7 +588,13 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi
d.udma_mask = udma_rates[chipset_family];
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
+}
+
+static void __devexit sis5513_remove(struct pci_dev *dev)
+{
+ ide_pci_remove(dev);
+ pci_disable_device(dev);
}
static const struct pci_device_id sis5513_pci_tbl[] = {
@@ -596,18 +605,27 @@ static const struct pci_device_id sis5513_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver sis5513_pci_driver = {
.name = "SIS_IDE",
.id_table = sis5513_pci_tbl,
.probe = sis5513_init_one,
+ .remove = __devexit_p(sis5513_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init sis5513_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&sis5513_pci_driver);
+}
+
+static void __exit sis5513_ide_exit(void)
+{
+ pci_unregister_driver(&sis5513_pci_driver);
}
module_init(sis5513_ide_init);
+module_exit(sis5513_ide_exit);
MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
MODULE_DESCRIPTION("PCI driver module for SIS IDE");
@@ -616,7 +634,6 @@ MODULE_LICENSE("GPL");
/*
* TODO:
* - CLEANUP
- * - Use drivers/ide/ide-timing.h !
* - More checks in the config registers (force values instead of
* relying on the BIOS setting them correctly).
* - Further optimisations ?
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index ce84fa045d3..84dc33602ff 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -17,12 +17,13 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <asm/io.h>
+#define DRV_NAME "sl82c105"
+
#undef DEBUG
#ifdef DEBUG
@@ -47,10 +48,11 @@
*/
static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
{
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
unsigned int cmd_on, cmd_off;
u8 iordy = 0;
- cmd_on = (ide_pio_timings[pio].active_time + 29) / 30;
+ cmd_on = (t->active + 29) / 30;
cmd_off = (ide_pio_cycle_time(drive, pio) - 30 * cmd_on + 29) / 30;
if (cmd_on == 0)
@@ -59,7 +61,7 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
if (cmd_off == 0)
cmd_off = 1;
- if (pio > 2 || ide_dev_has_iordy(drive->id))
+ if (pio > 2 || ata_id_has_iordy(drive->id))
iordy = 0x40;
return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy;
@@ -156,9 +158,9 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive)
* Was DMA enabled? If so, disable it - we're resetting the
* host. The IDE layer will be handling the drive for us.
*/
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
if (dma_cmd & 1) {
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
printk("sl82c105: DMA was enabled\n");
}
@@ -205,7 +207,7 @@ static int sl82c105_dma_end(ide_drive_t *drive)
DBG(("%s(drive:%s)\n", __func__, drive->name));
- ret = __ide_dma_end(drive);
+ ret = ide_dma_end(drive);
pci_write_config_word(dev, reg, drive->drive_data);
@@ -269,7 +271,7 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev)
* channel 0 here at least, but channel 1 has to be enabled by
* firmware or arch code. We still set both to 16 bits mode.
*/
-static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const char *msg)
+static unsigned int init_chipset_sl82c105(struct pci_dev *dev)
{
u32 val;
@@ -300,7 +302,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = {
};
static const struct ide_port_info sl82c105_chipset __devinitdata = {
- .name = "W82C105",
+ .name = DRV_NAME,
.init_chipset = init_chipset_sl82c105,
.enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
.port_ops = &sl82c105_port_ops,
@@ -327,14 +329,14 @@ static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_dev
* Never ever EVER under any circumstances enable
* DMA when the bridge is this old.
*/
- printk(KERN_INFO "W82C105_IDE: Winbond W83C553 bridge "
+ printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge "
"revision %d, BM-DMA disabled\n", rev);
d.dma_ops = NULL;
d.mwdma_mask = 0;
d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA;
}
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id sl82c105_pci_tbl[] = {
@@ -343,18 +345,27 @@ static const struct pci_device_id sl82c105_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver sl82c105_pci_driver = {
.name = "W82C105_IDE",
.id_table = sl82c105_pci_tbl,
.probe = sl82c105_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init sl82c105_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&sl82c105_pci_driver);
+}
+
+static void __exit sl82c105_ide_exit(void)
+{
+ pci_unregister_driver(&sl82c105_pci_driver);
}
module_init(sl82c105_ide_init);
+module_exit(sl82c105_ide_exit);
MODULE_DESCRIPTION("PCI driver module for W82C105 IDE");
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index dae6e2c94d8..0f759e4ed77 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -11,10 +11,11 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "slc90e66"
+
static DEFINE_SPINLOCK(slc90e66_lock);
static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
@@ -114,7 +115,7 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
}
-static u8 __devinit slc90e66_cable_detect(ide_hwif_t *hwif)
+static u8 slc90e66_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02;
@@ -132,7 +133,7 @@ static const struct ide_port_ops slc90e66_port_ops = {
};
static const struct ide_port_info slc90e66_chipset __devinitdata = {
- .name = "SLC90E66",
+ .name = DRV_NAME,
.enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
.port_ops = &slc90e66_port_ops,
.host_flags = IDE_HFLAG_LEGACY_IRQS,
@@ -144,7 +145,7 @@ static const struct ide_port_info slc90e66_chipset __devinitdata = {
static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &slc90e66_chipset);
+ return ide_pci_init_one(dev, &slc90e66_chipset, NULL);
}
static const struct pci_device_id slc90e66_pci_tbl[] = {
@@ -153,18 +154,27 @@ static const struct pci_device_id slc90e66_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver slc90e66_pci_driver = {
.name = "SLC90e66_IDE",
.id_table = slc90e66_pci_tbl,
.probe = slc90e66_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init slc90e66_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&slc90e66_pci_driver);
+}
+
+static void __exit slc90e66_ide_exit(void)
+{
+ pci_unregister_driver(&slc90e66_pci_driver);
}
module_init(slc90e66_ide_init);
+module_exit(slc90e66_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE");
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 9b4b27a4c71..93e2cce4b29 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -11,6 +11,8 @@
#include <linux/pci.h>
#include <linux/ide.h>
+#define DRV_NAME "tc86c001"
+
static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -63,7 +65,7 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
ide_expiry_t *expiry = ide_get_hwifdata(hwif);
ide_hwgroup_t *hwgroup = HWGROUP(drive);
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* Restore a higher level driver's expiry handler first. */
hwgroup->expiry = expiry;
@@ -71,21 +73,24 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */
unsigned long sc_base = hwif->config_data;
unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
- u8 dma_cmd = inb(hwif->dma_command);
+ u8 dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
"attempting recovery...\n", drive->name);
/* Stop DMA */
- outb(dma_cmd & ~0x01, hwif->dma_command);
+ outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);
/* Setup the dummy DMA transfer */
outw(0, sc_base + 0x0a); /* Sector Count */
outw(0, twcr_port); /* Transfer Word Count 1 or 2 */
/* Start the dummy DMA transfer */
- outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
- outb(0x01, hwif->dma_command); /* set START_STOPBM */
+
+ /* clear R_OR_WCTR for write */
+ outb(0x00, hwif->dma_base + ATA_DMA_CMD);
+ /* set START_STOPBM */
+ outb(0x01, hwif->dma_base + ATA_DMA_CMD);
/*
* If an interrupt was pending, it should come thru shortly.
@@ -126,7 +131,7 @@ static void tc86c001_dma_start(ide_drive_t *drive)
ide_dma_start(drive);
}
-static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif)
+static u8 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);
@@ -170,16 +175,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
hwif->rqsize = 0xffff;
}
-static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
- const char *name)
-{
- int err = pci_request_region(dev, 5, name);
-
- if (err)
- printk(KERN_ERR "%s: system control regs already in use", name);
- return err;
-}
-
static const struct ide_port_ops tc86c001_port_ops = {
.set_pio_mode = tc86c001_set_pio_mode,
.set_dma_mode = tc86c001_set_mode,
@@ -191,20 +186,18 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = tc86c001_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
};
static const struct ide_port_info tc86c001_chipset __devinitdata = {
- .name = "TC86C001",
- .init_chipset = init_chipset_tc86c001,
+ .name = DRV_NAME,
.init_hwif = init_hwif_tc86c001,
.port_ops = &tc86c001_port_ops,
.dma_ops = &tc86c001_dma_ops,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
- IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
@@ -213,7 +206,37 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
static int __devinit tc86c001_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &tc86c001_chipset);
+ int rc;
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ goto out;
+
+ rc = pci_request_region(dev, 5, DRV_NAME);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME ": system control regs already in use");
+ goto out_disable;
+ }
+
+ rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL);
+ if (rc)
+ goto out_release;
+
+ goto out;
+
+out_release:
+ pci_release_region(dev, 5);
+out_disable:
+ pci_disable_device(dev);
+out:
+ return rc;
+}
+
+static void __devexit tc86c001_remove(struct pci_dev *dev)
+{
+ ide_pci_remove(dev);
+ pci_release_region(dev, 5);
+ pci_disable_device(dev);
}
static const struct pci_device_id tc86c001_pci_tbl[] = {
@@ -222,17 +245,25 @@ static const struct pci_device_id tc86c001_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver tc86c001_pci_driver = {
.name = "TC86C001",
.id_table = tc86c001_pci_tbl,
- .probe = tc86c001_init_one
+ .probe = tc86c001_init_one,
+ .remove = __devexit_p(tc86c001_remove),
};
static int __init tc86c001_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&tc86c001_pci_driver);
}
+
+static void __exit tc86c001_ide_exit(void)
+{
+ pci_unregister_driver(&tc86c001_pci_driver);
+}
+
module_init(tc86c001_ide_init);
+module_exit(tc86c001_ide_exit);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index db65a558d4e..b6ff40336aa 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -28,22 +28,22 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "triflex"
+
static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- u8 channel_offset = hwif->channel ? 0x74 : 0x70;
- u16 timing = 0;
u32 triflex_timings = 0;
- u8 unit = (drive->select.b.unit & 0x01);
-
+ u16 timing = 0;
+ u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1;
+
pci_read_config_dword(dev, channel_offset, &triflex_timings);
-
+
switch(speed) {
case XFER_MW_DMA_2:
timing = 0x0103;
@@ -93,7 +93,7 @@ static const struct ide_port_ops triflex_port_ops = {
};
static const struct ide_port_info triflex_device __devinitdata = {
- .name = "TRIFLEX",
+ .name = DRV_NAME,
.enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
.port_ops = &triflex_port_ops,
.pio_mask = ATA_PIO4,
@@ -104,7 +104,7 @@ static const struct ide_port_info triflex_device __devinitdata = {
static int __devinit triflex_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &triflex_device);
+ return ide_pci_init_one(dev, &triflex_device, NULL);
}
static const struct pci_device_id triflex_pci_tbl[] = {
@@ -113,18 +113,27 @@ static const struct pci_device_id triflex_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver triflex_pci_driver = {
.name = "TRIFLEX_IDE",
.id_table = triflex_pci_tbl,
.probe = triflex_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init triflex_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&triflex_pci_driver);
+}
+
+static void __exit triflex_ide_exit(void)
+{
+ pci_unregister_driver(&triflex_pci_driver);
}
module_init(triflex_ide_init);
+module_exit(triflex_ide_exit);
MODULE_AUTHOR("Torben Mathiasen");
MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index a8a3138682e..75ea6152656 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -135,12 +135,13 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/init.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <asm/io.h>
+#define DRV_NAME "trm290"
+
static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -160,7 +161,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
}
/* enable IRQ if not probing */
- if (drive->present) {
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
reg = inw(hwif->config_data + 3);
reg &= 0x13;
reg &= ~(1 << hwif->channel);
@@ -172,7 +173,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
static void trm290_selectproc (ide_drive_t *drive)
{
- trm290_prepare_drive(drive, drive->using_dma);
+ trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
}
static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
@@ -245,10 +246,10 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
u8 reg = 0;
if ((dev->class & 5) && cfg_base)
- printk(KERN_INFO "TRM290: chip");
+ printk(KERN_INFO DRV_NAME " %s: chip", pci_name(dev));
else {
cfg_base = 0x3df0;
- printk(KERN_INFO "TRM290: using default");
+ printk(KERN_INFO DRV_NAME " %s: using default", pci_name(dev));
}
printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
hwif->config_data = cfg_base;
@@ -325,7 +326,7 @@ static struct ide_dma_ops trm290_dma_ops = {
};
static const struct ide_port_info trm290_chipset __devinitdata = {
- .name = "TRM290",
+ .name = DRV_NAME,
.init_hwif = init_hwif_trm290,
.chipset = ide_trm290,
.port_ops = &trm290_port_ops,
@@ -340,7 +341,7 @@ static const struct ide_port_info trm290_chipset __devinitdata = {
static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &trm290_chipset);
+ return ide_pci_init_one(dev, &trm290_chipset, NULL);
}
static const struct pci_device_id trm290_pci_tbl[] = {
@@ -349,18 +350,25 @@ static const struct pci_device_id trm290_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver trm290_pci_driver = {
.name = "TRM290_IDE",
.id_table = trm290_pci_tbl,
.probe = trm290_init_one,
+ .remove = ide_pci_remove,
};
static int __init trm290_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&trm290_pci_driver);
+}
+
+static void __exit trm290_ide_exit(void)
+{
+ pci_unregister_driver(&trm290_pci_driver);
}
module_init(trm290_ide_init);
+module_exit(trm290_ide_exit);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE");
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 566e0ecb8db..2a812d3207e 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -35,7 +35,7 @@
#include <asm/processor.h>
#endif
-#include "ide-timing.h"
+#define DRV_NAME "via82cxxx"
#define VIA_IDE_ENABLE 0x40
#define VIA_IDE_CONFIG 0x41
@@ -115,26 +115,27 @@ struct via82cxxx_dev
static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct via82cxxx_dev *vdev = host->host_priv;
u8 t;
if (~vdev->via_config->flags & VIA_BAD_AST) {
pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
- t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+ t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
}
pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)),
- ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
+ ((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1));
pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
- ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
+ ((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1));
switch (vdev->via_config->udma_mask) {
- case ATA_UDMA2: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
- case ATA_UDMA4: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
- case ATA_UDMA5: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
- case ATA_UDMA6: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+ case ATA_UDMA2: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break;
+ case ATA_UDMA4: t = timing->udma ? (0xe8 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x0f; break;
+ case ATA_UDMA5: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break;
+ case ATA_UDMA6: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break;
default: return;
}
@@ -153,9 +154,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_hwif_t *hwif = drive->hwif;
- ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
+ ide_drive_t *peer = ide_get_pair_dev(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct via82cxxx_dev *vdev = host->host_priv;
struct ide_timing t, p;
unsigned int T, UT;
@@ -171,7 +173,7 @@ static void via_set_drive(ide_drive_t *drive, const u8 speed)
ide_timing_compute(drive, speed, &t, T, UT);
- if (peer->present) {
+ if (peer) {
ide_timing_compute(peer, peer->current_speed, &p, T, UT);
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
}
@@ -213,7 +215,7 @@ static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
/*
* Check and handle 80-wire cable presence
*/
-static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
+static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
{
int i;
@@ -260,37 +262,19 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
/**
* init_chipset_via82cxxx - initialization handler
* @dev: PCI device
- * @name: Name of interface
*
* The initialization callback. Here we determine the IDE chip type
* and initialize its drive independent registers.
*/
-static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const char *name)
+static unsigned int init_chipset_via82cxxx(struct pci_dev *dev)
{
- struct pci_dev *isa = NULL;
- struct via82cxxx_dev *vdev;
- struct via_isa_bridge *via_config;
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct via82cxxx_dev *vdev = host->host_priv;
+ struct via_isa_bridge *via_config = vdev->via_config;
u8 t, v;
u32 u;
- vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
- if (!vdev) {
- printk(KERN_ERR "VP_IDE: out of memory :(\n");
- return -ENOMEM;
- }
- pci_set_drvdata(dev, vdev);
-
- /*
- * Find the ISA bridge to see how good the IDE is.
- */
- vdev->via_config = via_config = via_config_find(&isa);
-
- /* We checked this earlier so if it fails here deeep badness
- is involved */
-
- BUG_ON(!via_config->id);
-
/*
* Detect cable and configure Clk66
*/
@@ -336,39 +320,6 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
pci_write_config_byte(dev, VIA_FIFO_CONFIG, t);
- /*
- * Determine system bus clock.
- */
-
- via_clock = (ide_pci_clk ? ide_pci_clk : system_bus_clock()) * 1000;
-
- switch (via_clock) {
- case 33000: via_clock = 33333; break;
- case 37000: via_clock = 37500; break;
- case 41000: via_clock = 41666; break;
- }
-
- if (via_clock < 20000 || via_clock > 50000) {
- printk(KERN_WARNING "VP_IDE: User given PCI clock speed "
- "impossible (%d), using 33 MHz instead.\n", via_clock);
- printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want "
- "to assume 80-wire cable.\n");
- via_clock = 33333;
- }
-
- /*
- * Print the boot message.
- */
-
- printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
- "controller on pci%s\n",
- via_config->name, isa->revision,
- via_config->udma_mask ? "U" : "MW",
- via_dma[via_config->udma_mask ?
- (fls(via_config->udma_mask) - 1) : 0],
- pci_name(dev));
-
- pci_dev_put(isa);
return 0;
}
@@ -401,10 +352,11 @@ static int via_cable_override(struct pci_dev *pdev)
return 0;
}
-static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
+static u8 via82cxxx_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
- struct via82cxxx_dev *vdev = pci_get_drvdata(pdev);
+ struct ide_host *host = pci_get_drvdata(pdev);
+ struct via82cxxx_dev *vdev = host->host_priv;
if (via_cable_override(pdev))
return ATA_CBL_PATA40_SHORT;
@@ -422,12 +374,11 @@ static const struct ide_port_ops via_port_ops = {
};
static const struct ide_port_info via82cxxx_chipset __devinitdata = {
- .name = "VP_IDE",
+ .name = DRV_NAME,
.init_chipset = init_chipset_via82cxxx,
.enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
.port_ops = &via_port_ops,
.host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_IO_32BIT,
.pio_mask = ATA_PIO5,
@@ -439,6 +390,8 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
{
struct pci_dev *isa = NULL;
struct via_isa_bridge *via_config;
+ struct via82cxxx_dev *vdev;
+ int rc;
u8 idx = id->driver_data;
struct ide_port_info d;
@@ -448,12 +401,42 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
* Find the ISA bridge and check we know what it is.
*/
via_config = via_config_find(&isa);
- pci_dev_put(isa);
if (!via_config->id) {
- printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n");
+ printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n",
+ pci_name(dev));
return -ENODEV;
}
+ /*
+ * Print the boot message.
+ */
+ printk(KERN_INFO DRV_NAME " %s: VIA %s (rev %02x) IDE %sDMA%s\n",
+ pci_name(dev), via_config->name, isa->revision,
+ via_config->udma_mask ? "U" : "MW",
+ via_dma[via_config->udma_mask ?
+ (fls(via_config->udma_mask) - 1) : 0]);
+
+ pci_dev_put(isa);
+
+ /*
+ * Determine system bus clock.
+ */
+ via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
+
+ switch (via_clock) {
+ case 33000: via_clock = 33333; break;
+ case 37000: via_clock = 37500; break;
+ case 41000: via_clock = 41666; break;
+ }
+
+ if (via_clock < 20000 || via_clock > 50000) {
+ printk(KERN_WARNING DRV_NAME ": User given PCI clock speed "
+ "impossible (%d), using 33 MHz instead.\n", via_clock);
+ printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want "
+ "to assume 80-wire cable.\n");
+ via_clock = 33333;
+ }
+
if (idx == 0)
d.host_flags |= IDE_HFLAG_NO_AUTODMA;
else
@@ -469,7 +452,29 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
d.udma_mask = via_config->udma_mask;
- return ide_setup_pci_device(dev, &d);
+ vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+ if (!vdev) {
+ printk(KERN_ERR DRV_NAME " %s: out of memory :(\n",
+ pci_name(dev));
+ return -ENOMEM;
+ }
+
+ vdev->via_config = via_config;
+
+ rc = ide_pci_init_one(dev, &d, vdev);
+ if (rc)
+ kfree(vdev);
+
+ return rc;
+}
+
+static void __devexit via_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct via82cxxx_dev *vdev = host->host_priv;
+
+ ide_pci_remove(dev);
+ kfree(vdev);
}
static const struct pci_device_id via_pci_tbl[] = {
@@ -482,18 +487,27 @@ static const struct pci_device_id via_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, via_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver via_pci_driver = {
.name = "VIA_IDE",
.id_table = via_pci_tbl,
.probe = via_init_one,
+ .remove = __devexit_p(via_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init via_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&via_pci_driver);
+}
+
+static void __exit via_ide_exit(void)
+{
+ pci_unregister_driver(&via_pci_driver);
}
module_init(via_ide_init);
+module_exit(via_ide_exit);
MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for VIA IDE");
diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile
index 65af5848b28..74e52adcdf4 100644
--- a/drivers/ide/ppc/Makefile
+++ b/drivers/ide/ppc/Makefile
@@ -1,3 +1,2 @@
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
deleted file mode 100644
index 236f9c38e51..00000000000
--- a/drivers/ide/ppc/mpc8xx.c
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de
- * Modified for direct IDE interface
- * by Thomas Lange, thomas@corelatus.com
- * Modified for direct IDE interface on 8xx without using the PCMCIA
- * controller
- * by Steven.Scholz@imc-berlin.de
- * Moved out of arch/ppc/kernel/m8xx_setup.c, other minor cleanups
- * by Mathew Locke <mattl@mvista.com>
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/ide.h>
-#include <linux/bootmem.h>
-
-#include <asm/mpc8xx.h>
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/ide.h>
-#include <asm/8xx_immap.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-
-#define DRV_NAME "ide-mpc8xx"
-
-static int identify (volatile u8 *p);
-static void print_fixed (volatile u8 *p);
-static void print_funcid (int func);
-static int check_ide_device (unsigned long base);
-
-static void ide_interrupt_ack (void *dev);
-static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio);
-
-typedef struct ide_ioport_desc {
- unsigned long base_off; /* Offset to PCMCIA memory */
- unsigned long reg_off[IDE_NR_PORTS]; /* controller register offsets */
- int irq; /* IRQ */
-} ide_ioport_desc_t;
-
-ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = {
-#ifdef IDE0_BASE_OFFSET
- { IDE0_BASE_OFFSET,
- {
- IDE0_DATA_REG_OFFSET,
- IDE0_ERROR_REG_OFFSET,
- IDE0_NSECTOR_REG_OFFSET,
- IDE0_SECTOR_REG_OFFSET,
- IDE0_LCYL_REG_OFFSET,
- IDE0_HCYL_REG_OFFSET,
- IDE0_SELECT_REG_OFFSET,
- IDE0_STATUS_REG_OFFSET,
- IDE0_CONTROL_REG_OFFSET,
- IDE0_IRQ_REG_OFFSET,
- },
- IDE0_INTERRUPT,
- },
-#ifdef IDE1_BASE_OFFSET
- { IDE1_BASE_OFFSET,
- {
- IDE1_DATA_REG_OFFSET,
- IDE1_ERROR_REG_OFFSET,
- IDE1_NSECTOR_REG_OFFSET,
- IDE1_SECTOR_REG_OFFSET,
- IDE1_LCYL_REG_OFFSET,
- IDE1_HCYL_REG_OFFSET,
- IDE1_SELECT_REG_OFFSET,
- IDE1_STATUS_REG_OFFSET,
- IDE1_CONTROL_REG_OFFSET,
- IDE1_IRQ_REG_OFFSET,
- },
- IDE1_INTERRUPT,
- },
-#endif /* IDE1_BASE_OFFSET */
-#endif /* IDE0_BASE_OFFSET */
-};
-
-ide_pio_timings_t ide_pio_clocks[6];
-int hold_time[6] = {30, 20, 15, 10, 10, 10 }; /* PIO Mode 5 with IORDY (nonstandard) */
-
-/*
- * Warning: only 1 (ONE) PCMCIA slot supported here,
- * which must be correctly initialized by the firmware (PPCBoot).
- */
-static int _slot_ = -1; /* will be read from PCMCIA registers */
-
-/* Make clock cycles and always round up */
-#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U )
-
-#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
-#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
-
-/*
- * The TQM850L hardware has two pins swapped! Grrrrgh!
- */
-#ifdef CONFIG_TQM850L
-#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXOE
-#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXRESET
-#else
-#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXRESET
-#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXOE
-#endif
-
-#if defined(CONFIG_BLK_DEV_MPC8xx_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
-#define PCMCIA_SCHLVL IDE0_INTERRUPT /* Status Change Interrupt Level */
-static int pcmcia_schlvl = PCMCIA_SCHLVL;
-#endif
-
-/*
- * See include/linux/ide.h for definition of hw_regs_t (p, base)
- */
-
-/*
- * m8xx_ide_init_ports() for a direct IDE interface _using_
- * MPC8xx's internal PCMCIA interface
- */
-#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
-static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
-{
- unsigned long *p = hw->io_ports_array;
- int i;
-
- typedef struct {
- ulong br;
- ulong or;
- } pcmcia_win_t;
- volatile pcmcia_win_t *win;
- volatile pcmconf8xx_t *pcmp;
-
- uint *pgcrx;
- u32 pcmcia_phy_base;
- u32 pcmcia_phy_end;
- static unsigned long pcmcia_base = 0;
- unsigned long base;
-
- *p = 0;
-
- pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
-
- if (!pcmcia_base) {
- /*
- * Read out PCMCIA registers. Since the reset values
- * are undefined, we sure hope that they have been
- * set up by firmware
- */
-
- /* Scan all registers for valid settings */
- pcmcia_phy_base = 0xFFFFFFFF;
- pcmcia_phy_end = 0;
- /* br0 is start of brX and orX regs */
- win = (pcmcia_win_t *) \
- (&(((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0));
- for (i = 0; i < 8; i++) {
- if (win->or & 1) { /* This bank is marked as valid */
- if (win->br < pcmcia_phy_base) {
- pcmcia_phy_base = win->br;
- }
- if ((win->br + PCMCIA_MEM_SIZE) > pcmcia_phy_end) {
- pcmcia_phy_end = win->br + PCMCIA_MEM_SIZE;
- }
- /* Check which slot that has been defined */
- _slot_ = (win->or >> 2) & 1;
-
- } /* Valid bank */
- win++;
- } /* for */
-
- printk ("PCMCIA slot %c: phys mem %08x...%08x (size %08x)\n",
- 'A' + _slot_,
- pcmcia_phy_base, pcmcia_phy_end,
- pcmcia_phy_end - pcmcia_phy_base);
-
- if (!request_mem_region(pcmcia_phy_base,
- pcmcia_phy_end - pcmcia_phy_base,
- DRV_NAME)) {
- printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
- return -EBUSY;
- }
-
- pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base,
- pcmcia_phy_end-pcmcia_phy_base);
-
-#ifdef DEBUG
- printk ("PCMCIA virt base: %08lx\n", pcmcia_base);
-#endif
- /* Compute clock cycles for PIO timings */
- for (i=0; i<6; ++i) {
- bd_t *binfo = (bd_t *)__res;
-
- hold_time[i] =
- PCMCIA_MK_CLKS (hold_time[i],
- binfo->bi_busfreq);
- ide_pio_clocks[i].setup_time =
- PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time,
- binfo->bi_busfreq);
- ide_pio_clocks[i].active_time =
- PCMCIA_MK_CLKS (ide_pio_timings[i].active_time,
- binfo->bi_busfreq);
- ide_pio_clocks[i].cycle_time =
- PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time,
- binfo->bi_busfreq);
-#if 0
- printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n",
- i,
- ide_pio_clocks[i].setup_time,
- ide_pio_clocks[i].active_time,
- ide_pio_clocks[i].hold_time,
- ide_pio_clocks[i].cycle_time,
- ide_pio_timings[i].setup_time,
- ide_pio_timings[i].active_time,
- ide_pio_timings[i].hold_time,
- ide_pio_timings[i].cycle_time);
-#endif
- }
- }
-
- if (_slot_ == -1) {
- printk ("PCMCIA slot has not been defined! Using A as default\n");
- _slot_ = 0;
- }
-
-#ifdef CONFIG_IDE_8xx_PCCARD
-
-#ifdef DEBUG
- printk ("PIPR = 0x%08X slot %c ==> mask = 0x%X\n",
- pcmp->pcmc_pipr,
- 'A' + _slot_,
- M8XX_PCMCIA_CD1(_slot_) | M8XX_PCMCIA_CD2(_slot_) );
-#endif /* DEBUG */
-
- if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) {
- printk ("No card in slot %c: PIPR=%08x\n",
- 'A' + _slot_, (u32) pcmp->pcmc_pipr);
- return -ENODEV; /* No card in slot */
- }
-
- check_ide_device (pcmcia_base);
-
-#endif /* CONFIG_IDE_8xx_PCCARD */
-
- base = pcmcia_base + ioport_dsc[data_port].base_off;
-#ifdef DEBUG
- printk ("base: %08x + %08x = %08x\n",
- pcmcia_base, ioport_dsc[data_port].base_off, base);
-#endif
-
- for (i = 0; i < IDE_NR_PORTS; ++i) {
-#ifdef DEBUG
- printk ("port[%d]: %08x + %08x = %08x\n",
- i,
- base,
- ioport_dsc[data_port].reg_off[i],
- i, base + ioport_dsc[data_port].reg_off[i]);
-#endif
- *p++ = base + ioport_dsc[data_port].reg_off[i];
- }
-
- hw->irq = ioport_dsc[data_port].irq;
- hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
-
-#ifdef CONFIG_IDE_8xx_PCCARD
- {
- unsigned int reg;
-
- if (_slot_)
- pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb;
- else
- pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcra;
-
- reg = *pgcrx;
- reg |= mk_int_int_mask (pcmcia_schlvl) << 24;
- reg |= mk_int_int_mask (pcmcia_schlvl) << 16;
- *pgcrx = reg;
- }
-#endif /* CONFIG_IDE_8xx_PCCARD */
-
- /* Enable Harddisk Interrupt,
- * and make it edge sensitive
- */
- /* (11-18) Set edge detect for irq, no wakeup from low power mode */
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=
- (0x80000000 >> ioport_dsc[data_port].irq);
-
-#ifdef CONFIG_IDE_8xx_PCCARD
- /* Make sure we don't get garbage irq */
- ((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pscr = 0xFFFF;
-
- /* Enable falling edge irq */
- pcmp->pcmc_per = 0x100000 >> (16 * _slot_);
-#endif /* CONFIG_IDE_8xx_PCCARD */
-
- hw->chipset = ide_generic;
-
- return 0;
-}
-#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
-
-/*
- * m8xx_ide_init_ports() for a direct IDE interface _not_ using
- * MPC8xx's internal PCMCIA interface
- */
-#if defined(CONFIG_IDE_EXT_DIRECT)
-static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
-{
- unsigned long *p = hw->io_ports_array;
- int i;
-
- u32 ide_phy_base;
- u32 ide_phy_end;
- static unsigned long ide_base = 0;
- unsigned long base;
-
- *p = 0;
-
- if (!ide_base) {
-
- /* TODO:
- * - add code to read ORx, BRx
- */
- ide_phy_base = CFG_ATA_BASE_ADDR;
- ide_phy_end = CFG_ATA_BASE_ADDR + 0x200;
-
- printk ("IDE phys mem : %08x...%08x (size %08x)\n",
- ide_phy_base, ide_phy_end,
- ide_phy_end - ide_phy_base);
-
- if (!request_mem_region(ide_phy_base, 0x200, DRV_NAME)) {
- printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
- return -EBUSY;
- }
-
- ide_base=(unsigned long)ioremap(ide_phy_base,
- ide_phy_end-ide_phy_base);
-
-#ifdef DEBUG
- printk ("IDE virt base: %08lx\n", ide_base);
-#endif
- }
-
- base = ide_base + ioport_dsc[data_port].base_off;
-#ifdef DEBUG
- printk ("base: %08x + %08x = %08x\n",
- ide_base, ioport_dsc[data_port].base_off, base);
-#endif
-
- for (i = 0; i < IDE_NR_PORTS; ++i) {
-#ifdef DEBUG
- printk ("port[%d]: %08x + %08x = %08x\n",
- i,
- base,
- ioport_dsc[data_port].reg_off[i],
- i, base + ioport_dsc[data_port].reg_off[i]);
-#endif
- *p++ = base + ioport_dsc[data_port].reg_off[i];
- }
-
- /* direct connected IDE drive, i.e. external IRQ */
- hw->irq = ioport_dsc[data_port].irq;
- hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
-
- /* Enable Harddisk Interrupt,
- * and make it edge sensitive
- */
- /* (11-18) Set edge detect for irq, no wakeup from low power mode */
- ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
- (0x80000000 >> ioport_dsc[data_port].irq);
-
- hw->chipset = ide_generic;
-
- return 0;
-}
-#endif /* CONFIG_IDE_8xx_DIRECT */
-
-
-/* -------------------------------------------------------------------- */
-
-
-/* PCMCIA Timing */
-#ifndef PCMCIA_SHT
-#define PCMCIA_SHT(t) ((t & 0x0F)<<16) /* Strobe Hold Time */
-#define PCMCIA_SST(t) ((t & 0x0F)<<12) /* Strobe Setup Time */
-#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length */
-#endif
-
-/* Calculate PIO timings */
-static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
- volatile pcmconf8xx_t *pcmp;
- ulong timing, mask, reg;
-
- pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
-
- mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF));
-
- timing = PCMCIA_SHT(hold_time[pio] )
- | PCMCIA_SST(ide_pio_clocks[pio].setup_time )
- | PCMCIA_SL (ide_pio_clocks[pio].active_time)
- ;
-
-#if 1
- printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing);
-#endif
- if ((reg = pcmp->pcmc_por0 & mask) != 0)
- pcmp->pcmc_por0 = reg | timing;
-
- if ((reg = pcmp->pcmc_por1 & mask) != 0)
- pcmp->pcmc_por1 = reg | timing;
-
- if ((reg = pcmp->pcmc_por2 & mask) != 0)
- pcmp->pcmc_por2 = reg | timing;
-
- if ((reg = pcmp->pcmc_por3 & mask) != 0)
- pcmp->pcmc_por3 = reg | timing;
-
- if ((reg = pcmp->pcmc_por4 & mask) != 0)
- pcmp->pcmc_por4 = reg | timing;
-
- if ((reg = pcmp->pcmc_por5 & mask) != 0)
- pcmp->pcmc_por5 = reg | timing;
-
- if ((reg = pcmp->pcmc_por6 & mask) != 0)
- pcmp->pcmc_por6 = reg | timing;
-
- if ((reg = pcmp->pcmc_por7 & mask) != 0)
- pcmp->pcmc_por7 = reg | timing;
-
-#elif defined(CONFIG_IDE_EXT_DIRECT)
-
- printk("%s[%d] %s: not implemented yet!\n",
- __FILE__, __LINE__, __func__);
-#endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */
-}
-
-static const struct ide_port_ops m8xx_port_ops = {
- .set_pio_mode = m8xx_ide_set_pio_mode,
-};
-
-static void
-ide_interrupt_ack (void *dev)
-{
-#ifdef CONFIG_IDE_8xx_PCCARD
- u_int pscr, pipr;
-
-#if (PCMCIA_SOCKETS_NO == 2)
- u_int _slot_;
-#endif
-
- /* get interrupt sources */
-
- pscr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr;
- pipr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;
-
- /*
- * report only if both card detect signals are the same
- * not too nice done,
- * we depend on that CD2 is the bit to the left of CD1...
- */
-
- if(_slot_==-1){
- printk("PCMCIA slot has not been defined! Using A as default\n");
- _slot_=0;
- }
-
- if(((pipr & M8XX_PCMCIA_CD2(_slot_)) >> 1) ^
- (pipr & M8XX_PCMCIA_CD1(_slot_)) ) {
- printk ("card detect interrupt\n");
- }
- /* clear the interrupt sources */
- ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;
-
-#else /* ! CONFIG_IDE_8xx_PCCARD */
- /*
- * Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the
- * MPC8xx's PCMCIA controller, so there is nothing to be done here
- * for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT.
- * The interrupt is handled somewhere else. -- Steven
- */
-#endif /* CONFIG_IDE_8xx_PCCARD */
-}
-
-
-
-/*
- * CIS Tupel codes
- */
-#define CISTPL_NULL 0x00
-#define CISTPL_DEVICE 0x01
-#define CISTPL_LONGLINK_CB 0x02
-#define CISTPL_INDIRECT 0x03
-#define CISTPL_CONFIG_CB 0x04
-#define CISTPL_CFTABLE_ENTRY_CB 0x05
-#define CISTPL_LONGLINK_MFC 0x06
-#define CISTPL_BAR 0x07
-#define CISTPL_PWR_MGMNT 0x08
-#define CISTPL_EXTDEVICE 0x09
-#define CISTPL_CHECKSUM 0x10
-#define CISTPL_LONGLINK_A 0x11
-#define CISTPL_LONGLINK_C 0x12
-#define CISTPL_LINKTARGET 0x13
-#define CISTPL_NO_LINK 0x14
-#define CISTPL_VERS_1 0x15
-#define CISTPL_ALTSTR 0x16
-#define CISTPL_DEVICE_A 0x17
-#define CISTPL_JEDEC_C 0x18
-#define CISTPL_JEDEC_A 0x19
-#define CISTPL_CONFIG 0x1a
-#define CISTPL_CFTABLE_ENTRY 0x1b
-#define CISTPL_DEVICE_OC 0x1c
-#define CISTPL_DEVICE_OA 0x1d
-#define CISTPL_DEVICE_GEO 0x1e
-#define CISTPL_DEVICE_GEO_A 0x1f
-#define CISTPL_MANFID 0x20
-#define CISTPL_FUNCID 0x21
-#define CISTPL_FUNCE 0x22
-#define CISTPL_SWIL 0x23
-#define CISTPL_END 0xff
-
-/*
- * CIS Function ID codes
- */
-#define CISTPL_FUNCID_MULTI 0x00
-#define CISTPL_FUNCID_MEMORY 0x01
-#define CISTPL_FUNCID_SERIAL 0x02
-#define CISTPL_FUNCID_PARALLEL 0x03
-#define CISTPL_FUNCID_FIXED 0x04
-#define CISTPL_FUNCID_VIDEO 0x05
-#define CISTPL_FUNCID_NETWORK 0x06
-#define CISTPL_FUNCID_AIMS 0x07
-#define CISTPL_FUNCID_SCSI 0x08
-
-/*
- * Fixed Disk FUNCE codes
- */
-#define CISTPL_IDE_INTERFACE 0x01
-
-#define CISTPL_FUNCE_IDE_IFACE 0x01
-#define CISTPL_FUNCE_IDE_MASTER 0x02
-#define CISTPL_FUNCE_IDE_SLAVE 0x03
-
-/* First feature byte */
-#define CISTPL_IDE_SILICON 0x04
-#define CISTPL_IDE_UNIQUE 0x08
-#define CISTPL_IDE_DUAL 0x10
-
-/* Second feature byte */
-#define CISTPL_IDE_HAS_SLEEP 0x01
-#define CISTPL_IDE_HAS_STANDBY 0x02
-#define CISTPL_IDE_HAS_IDLE 0x04
-#define CISTPL_IDE_LOW_POWER 0x08
-#define CISTPL_IDE_REG_INHIBIT 0x10
-#define CISTPL_IDE_HAS_INDEX 0x20
-#define CISTPL_IDE_IOIS16 0x40
-
-
-/* -------------------------------------------------------------------- */
-
-
-#define MAX_TUPEL_SZ 512
-#define MAX_FEATURES 4
-
-static int check_ide_device (unsigned long base)
-{
- volatile u8 *ident = NULL;
- volatile u8 *feature_p[MAX_FEATURES];
- volatile u8 *p, *start;
- int n_features = 0;
- u8 func_id = ~0;
- u8 code, len;
- unsigned short config_base = 0;
- int found = 0;
- int i;
-
-#ifdef DEBUG
- printk ("PCMCIA MEM: %08lX\n", base);
-#endif
- start = p = (volatile u8 *) base;
-
- while ((p - start) < MAX_TUPEL_SZ) {
-
- code = *p; p += 2;
-
- if (code == 0xFF) { /* End of chain */
- break;
- }
-
- len = *p; p += 2;
-#ifdef DEBUG_PCMCIA
- { volatile u8 *q = p;
- printk ("\nTuple code %02x length %d\n\tData:",
- code, len);
-
- for (i = 0; i < len; ++i) {
- printk (" %02x", *q);
- q+= 2;
- }
- }
-#endif /* DEBUG_PCMCIA */
- switch (code) {
- case CISTPL_VERS_1:
- ident = p + 4;
- break;
- case CISTPL_FUNCID:
- func_id = *p;
- break;
- case CISTPL_FUNCE:
- if (n_features < MAX_FEATURES)
- feature_p[n_features++] = p;
- break;
- case CISTPL_CONFIG:
- config_base = (*(p+6) << 8) + (*(p+4));
- default:
- break;
- }
- p += 2 * len;
- }
-
- found = identify (ident);
-
- if (func_id != ((u8)~0)) {
- print_funcid (func_id);
-
- if (func_id == CISTPL_FUNCID_FIXED)
- found = 1;
- else
- return (1); /* no disk drive */
- }
-
- for (i=0; i<n_features; ++i) {
- print_fixed (feature_p[i]);
- }
-
- if (!found) {
- printk ("unknown card type\n");
- return (1);
- }
-
- /* set level mode irq and I/O mapped device in config reg*/
- *((u8 *)(base + config_base)) = 0x41;
-
- return (0);
-}
-
-/* ------------------------------------------------------------------------- */
-
-static void print_funcid (int func)
-{
- switch (func) {
- case CISTPL_FUNCID_MULTI:
- printk (" Multi-Function");
- break;
- case CISTPL_FUNCID_MEMORY:
- printk (" Memory");
- break;
- case CISTPL_FUNCID_SERIAL:
- printk (" Serial Port");
- break;
- case CISTPL_FUNCID_PARALLEL:
- printk (" Parallel Port");
- break;
- case CISTPL_FUNCID_FIXED:
- printk (" Fixed Disk");
- break;
- case CISTPL_FUNCID_VIDEO:
- printk (" Video Adapter");
- break;
- case CISTPL_FUNCID_NETWORK:
- printk (" Network Adapter");
- break;
- case CISTPL_FUNCID_AIMS:
- printk (" AIMS Card");
- break;
- case CISTPL_FUNCID_SCSI:
- printk (" SCSI Adapter");
- break;
- default:
- printk (" Unknown");
- break;
- }
- printk (" Card\n");
-}
-
-/* ------------------------------------------------------------------------- */
-
-static void print_fixed (volatile u8 *p)
-{
- if (p == NULL)
- return;
-
- switch (*p) {
- case CISTPL_FUNCE_IDE_IFACE:
- { u8 iface = *(p+2);
-
- printk ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
- printk (" interface ");
- break;
- }
- case CISTPL_FUNCE_IDE_MASTER:
- case CISTPL_FUNCE_IDE_SLAVE:
- { u8 f1 = *(p+2);
- u8 f2 = *(p+4);
-
- printk ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
-
- if (f1 & CISTPL_IDE_UNIQUE)
- printk (" [unique]");
-
- printk ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
-
- if (f2 & CISTPL_IDE_HAS_SLEEP)
- printk (" [sleep]");
-
- if (f2 & CISTPL_IDE_HAS_STANDBY)
- printk (" [standby]");
-
- if (f2 & CISTPL_IDE_HAS_IDLE)
- printk (" [idle]");
-
- if (f2 & CISTPL_IDE_LOW_POWER)
- printk (" [low power]");
-
- if (f2 & CISTPL_IDE_REG_INHIBIT)
- printk (" [reg inhibit]");
-
- if (f2 & CISTPL_IDE_HAS_INDEX)
- printk (" [index]");
-
- if (f2 & CISTPL_IDE_IOIS16)
- printk (" [IOis16]");
-
- break;
- }
- }
- printk ("\n");
-}
-
-/* ------------------------------------------------------------------------- */
-
-
-#define MAX_IDENT_CHARS 64
-#define MAX_IDENT_FIELDS 4
-
-static u8 *known_cards[] = {
- "ARGOSY PnPIDE D5",
- NULL
-};
-
-static int identify (volatile u8 *p)
-{
- u8 id_str[MAX_IDENT_CHARS];
- u8 data;
- u8 *t;
- u8 **card;
- int i, done;
-
- if (p == NULL)
- return (0); /* Don't know */
-
- t = id_str;
- done =0;
-
- for (i=0; i<=4 && !done; ++i, p+=2) {
- while ((data = *p) != '\0') {
- if (data == 0xFF) {
- done = 1;
- break;
- }
- *t++ = data;
- if (t == &id_str[MAX_IDENT_CHARS-1]) {
- done = 1;
- break;
- }
- p += 2;
- }
- if (!done)
- *t++ = ' ';
- }
- *t = '\0';
- while (--t > id_str) {
- if (*t == ' ')
- *t = '\0';
- else
- break;
- }
- printk ("Card ID: %s\n", id_str);
-
- for (card=known_cards; *card; ++card) {
- if (strcmp(*card, id_str) == 0) { /* found! */
- return (1);
- }
- }
-
- return (0); /* don't know */
-}
-
-static int __init mpc8xx_ide_probe(void)
-{
- hw_regs_t hw;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-
-#ifdef IDE0_BASE_OFFSET
- memset(&hw, 0, sizeof(hw));
- if (!m8xx_ide_init_ports(&hw, 0)) {
- ide_hwif_t *hwif = ide_find_port();
-
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
- hwif->pio_mask = ATA_PIO4;
- hwif->port_ops = &m8xx_port_ops;
-
- idx[0] = hwif->index;
- }
- }
-#ifdef IDE1_BASE_OFFSET
- memset(&hw, 0, sizeof(hw));
- if (!m8xx_ide_init_ports(&hw, 1)) {
- ide_hwif_t *mate = ide_find_port();
-
- if (mate) {
- ide_init_port_hw(mate, &hw);
- mate->pio_mask = ATA_PIO4;
- mate->port_ops = &m8xx_port_ops;
-
- idx[1] = mate->index;
- }
- }
-#endif
-#endif
-
- ide_device_add(idx, NULL);
-
- return 0;
-}
-
-module_init(mpc8xx_ide_probe);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index ba2d5872796..2e19d629853 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -5,7 +5,7 @@
* for doing DMA.
*
* Copyright (C) 1998-2003 Paul Mackerras & Ben. Herrenschmidt
- * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -48,7 +48,7 @@
#include <asm/mediabay.h>
#endif
-#include "../ide-timing.h"
+#define DRV_NAME "ide-pmac"
#undef IDE_PMAC_DEBUG
@@ -426,12 +426,11 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
static void
pmac_ide_selectproc(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-
- if (pmif == NULL)
- return;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- if (drive->select.b.unit & 0x01)
+ if (drive->dn & 1)
writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
else
writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
@@ -446,12 +445,11 @@ pmac_ide_selectproc(ide_drive_t *drive)
static void
pmac_ide_kauai_selectproc(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-
- if (pmif == NULL)
- return;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- if (drive->select.b.unit & 0x01) {
+ if (drive->dn & 1) {
writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
} else {
@@ -467,10 +465,9 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
static void
pmac_ide_do_update_timings(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-
- if (pmif == NULL)
- return;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
if (pmif->kind == controller_sh_ata6 ||
pmif->kind == controller_un_ata6 ||
@@ -480,13 +477,27 @@ pmac_ide_do_update_timings(ide_drive_t *drive)
pmac_ide_selectproc(drive);
}
-static void
-pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port)
+static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd)
{
- u32 tmp;
-
- writeb(value, (void __iomem *) port);
- tmp = readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
+ writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+ (void)readl((void __iomem *)(hwif->io_ports.data_addr
+ + IDE_TIMING_CONFIG));
+}
+
+static void pmac_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+ (void)readl((void __iomem *)(hwif->io_ports.data_addr
+ + IDE_TIMING_CONFIG));
}
/*
@@ -495,17 +506,17 @@ pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port)
static void
pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+ struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio);
u32 *timings, t;
unsigned accessTicks, recTicks;
unsigned accessTime, recTime;
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
unsigned int cycle_time;
- if (pmif == NULL)
- return;
-
/* which drive is it ? */
- timings = &pmif->timings[drive->select.b.unit & 0x01];
+ timings = &pmif->timings[drive->dn & 1];
t = *timings;
cycle_time = ide_pio_cycle_time(drive, pio);
@@ -526,10 +537,9 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
case controller_kl_ata4:
/* 66Mhz cell */
- recTime = cycle_time - ide_pio_timings[pio].active_time
- - ide_pio_timings[pio].setup_time;
+ recTime = cycle_time - tim->active - tim->setup;
recTime = max(recTime, 150U);
- accessTime = ide_pio_timings[pio].active_time;
+ accessTime = tim->active;
accessTime = max(accessTime, 150U);
accessTicks = SYSCLK_TICKS_66(accessTime);
accessTicks = min(accessTicks, 0x1fU);
@@ -542,10 +552,9 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
default: {
/* 33Mhz cell */
int ebit = 0;
- recTime = cycle_time - ide_pio_timings[pio].active_time
- - ide_pio_timings[pio].setup_time;
+ recTime = cycle_time - tim->active - tim->setup;
recTime = max(recTime, 150U);
- accessTime = ide_pio_timings[pio].active_time;
+ accessTime = tim->active;
accessTime = max(accessTime, 150U);
accessTicks = SYSCLK_TICKS(accessTime);
accessTicks = min(accessTicks, 0x1fU);
@@ -648,9 +657,9 @@ static void
set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
u8 speed)
{
+ u16 *id = drive->id;
int cycleTime, accessTime = 0, recTime = 0;
unsigned accessTicks, recTicks;
- struct hd_driveid *id = drive->id;
struct mdma_timings_t* tm = NULL;
int i;
@@ -665,8 +674,8 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
}
/* Check if drive provides explicit DMA cycle time */
- if ((id->field_valid & 2) && id->eide_dma_time)
- cycleTime = max_t(int, id->eide_dma_time, cycleTime);
+ if ((id[ATA_ID_FIELD_VALID] & 2) && id[ATA_ID_EIDE_DMA_TIME])
+ cycleTime = max_t(int, id[ATA_ID_EIDE_DMA_TIME], cycleTime);
/* OHare limits according to some old Apple sources */
if ((intf_type == controller_ohare) && (cycleTime < 150))
@@ -781,10 +790,12 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- int unit = (drive->select.b.unit & 0x01);
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
int ret = 0;
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
u32 *timings, *timings2, tl[2];
+ u8 unit = drive->dn & 1;
timings = &pmif->timings[unit];
timings2 = &pmif->timings[unit+2];
@@ -855,11 +866,8 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
/* Suspend call back, should be called after the child devices
* have actually been suspended
*/
-static int
-pmac_ide_do_suspend(ide_hwif_t *hwif)
+static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-
/* We clear the timings */
pmif->timings[0] = 0;
pmif->timings[1] = 0;
@@ -887,11 +895,8 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
/* Resume call back, should be called before the child devices
* are resumed
*/
-static int
-pmac_ide_do_resume(ide_hwif_t *hwif)
+static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-
/* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
if (!pmif->mediabay) {
ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
@@ -919,7 +924,8 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)ide_get_hwifdata(hwif);
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct device_node *np = pmif->node;
const char *cable = of_get_property(np, "cable-type", NULL);
@@ -939,7 +945,40 @@ static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
return ATA_CBL_PATA40;
}
+static void pmac_ide_init_dev(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+
+ if (pmif->mediabay) {
+#ifdef CONFIG_PMAC_MEDIABAY
+ if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
+ drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
+ return;
+ }
+#endif
+ drive->dev_flags |= IDE_DFLAG_NOPROBE;
+ }
+}
+
+static const struct ide_tp_ops pmac_tp_ops = {
+ .exec_command = pmac_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = pmac_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
+
static const struct ide_port_ops pmac_ide_ata6_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_kauai_selectproc,
@@ -947,6 +986,7 @@ static const struct ide_port_ops pmac_ide_ata6_port_ops = {
};
static const struct ide_port_ops pmac_ide_ata4_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_selectproc,
@@ -954,6 +994,7 @@ static const struct ide_port_ops pmac_ide_ata4_port_ops = {
};
static const struct ide_port_ops pmac_ide_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_selectproc,
@@ -962,12 +1003,14 @@ static const struct ide_port_ops pmac_ide_port_ops = {
static const struct ide_dma_ops pmac_dma_ops;
static const struct ide_port_info pmac_port_info = {
+ .name = DRV_NAME,
.init_dma = pmac_ide_init_dma,
.chipset = ide_pmac,
+ .tp_ops = &pmac_tp_ops,
+ .port_ops = &pmac_ide_port_ops,
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
.dma_ops = &pmac_dma_ops,
#endif
- .port_ops = &pmac_ide_port_ops,
.host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_MMIO |
@@ -980,13 +1023,15 @@ static const struct ide_port_info pmac_port_info = {
* Setup, register & probe an IDE channel driven by this driver, this is
* called by one of the 2 probe functions (macio or PCI).
*/
-static int __devinit
-pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
{
struct device_node *np = pmif->node;
const int *bidp;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ struct ide_host *host;
+ ide_hwif_t *hwif;
+ hw_regs_t *hws[] = { hw, NULL, NULL, NULL };
struct ide_port_info d = pmac_port_info;
+ int rc;
pmif->broken_dma = pmif->broken_dma_warn = 0;
if (of_device_is_compatible(np, "shasta-ata")) {
@@ -1029,6 +1074,11 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
/* Make sure we have sane timings */
sanitize_timings(pmif);
+ host = ide_host_alloc(&d, hws);
+ if (host == NULL)
+ return -ENOMEM;
+ hwif = host->ports[0];
+
#ifndef CONFIG_PPC64
/* XXX FIXME: Media bay stuff need re-organizing */
if (np->parent && np->parent->name
@@ -1057,32 +1107,17 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
}
- /* Setup MMIO ops */
- default_hwif_mmiops(hwif);
- hwif->OUTBSYNC = pmac_outbsync;
-
- hwif->hwif_data = pmif;
- ide_init_port_hw(hwif, hw);
-
- printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
- hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
- pmif->mediabay ? " (mediabay)" : "", hwif->irq);
+ printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
+ "bus ID %d%s, irq %d\n", model_name[pmif->kind],
+ pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
+ pmif->mediabay ? " (mediabay)" : "", hw->irq);
- if (pmif->mediabay) {
-#ifdef CONFIG_PMAC_MEDIABAY
- if (check_media_bay_by_base(pmif->regbase, MB_CD)) {
-#else
- if (1) {
-#endif
- hwif->drives[0].noprobe = 1;
- hwif->drives[1].noprobe = 1;
- }
+ rc = ide_host_register(host, &d, hws);
+ if (rc) {
+ ide_host_free(host);
+ return rc;
}
- idx[0] = hwif->index;
-
- ide_device_add(idx, &d);
-
return 0;
}
@@ -1104,7 +1139,6 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
{
void __iomem *base;
unsigned long regbase;
- ide_hwif_t *hwif;
pmac_ide_hwif_t *pmif;
int irq, rc;
hw_regs_t hw;
@@ -1113,14 +1147,6 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
if (pmif == NULL)
return -ENOMEM;
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n");
- printk(KERN_ERR " %s\n", mdev->ofdev.node->full_name);
- rc = -ENODEV;
- goto out_free_pmif;
- }
-
if (macio_resource_count(mdev) == 0) {
printk(KERN_WARNING "ide-pmac: no address for %s\n",
mdev->ofdev.node->full_name);
@@ -1151,8 +1177,6 @@ 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->dev = &mdev->bus->pdev->dev;
-
pmif->mdev = mdev;
pmif->node = mdev->ofdev.node;
pmif->regbase = regbase;
@@ -1169,14 +1193,15 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
} else
pmif->dma_regs = NULL;
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
- dev_set_drvdata(&mdev->ofdev.dev, hwif);
+ dev_set_drvdata(&mdev->ofdev.dev, pmif);
memset(&hw, 0, sizeof(hw));
pmac_ide_init_ports(&hw, pmif->regbase);
hw.irq = irq;
- hw.dev = &mdev->ofdev.dev;
+ hw.dev = &mdev->bus->pdev->dev;
+ hw.parent = &mdev->ofdev.dev;
- rc = pmac_ide_setup_device(pmif, hwif, &hw);
+ rc = pmac_ide_setup_device(pmif, &hw);
if (rc != 0) {
/* The inteface is released to the common IDE layer */
dev_set_drvdata(&mdev->ofdev.dev, NULL);
@@ -1199,12 +1224,13 @@ out_free_pmif:
static int
pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
{
- ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
- int rc = 0;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+ int rc = 0;
if (mesg.event != mdev->ofdev.dev.power.power_state.event
&& (mesg.event & PM_EVENT_SLEEP)) {
- rc = pmac_ide_do_suspend(hwif);
+ rc = pmac_ide_do_suspend(pmif);
if (rc == 0)
mdev->ofdev.dev.power.power_state = mesg;
}
@@ -1215,11 +1241,12 @@ pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
static int
pmac_ide_macio_resume(struct macio_dev *mdev)
{
- ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+ int rc = 0;
+
if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
- rc = pmac_ide_do_resume(hwif);
+ rc = pmac_ide_do_resume(pmif);
if (rc == 0)
mdev->ofdev.dev.power.power_state = PMSG_ON;
}
@@ -1233,7 +1260,6 @@ pmac_ide_macio_resume(struct macio_dev *mdev)
static int __devinit
pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
{
- ide_hwif_t *hwif;
struct device_node *np;
pmac_ide_hwif_t *pmif;
void __iomem *base;
@@ -1251,14 +1277,6 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
if (pmif == NULL)
return -ENOMEM;
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n");
- printk(KERN_ERR " %s\n", np->full_name);
- rc = -ENODEV;
- goto out_free_pmif;
- }
-
if (pci_enable_device(pdev)) {
printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
"%s\n", np->full_name);
@@ -1274,7 +1292,6 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_free_pmif;
}
- hwif->dev = &pdev->dev;
pmif->mdev = NULL;
pmif->node = np;
@@ -1289,14 +1306,14 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
pmif->kauai_fcr = base;
pmif->irq = pdev->irq;
- pci_set_drvdata(pdev, hwif);
+ pci_set_drvdata(pdev, pmif);
memset(&hw, 0, sizeof(hw));
pmac_ide_init_ports(&hw, pmif->regbase);
hw.irq = pdev->irq;
hw.dev = &pdev->dev;
- rc = pmac_ide_setup_device(pmif, hwif, &hw);
+ rc = pmac_ide_setup_device(pmif, &hw);
if (rc != 0) {
/* The inteface is released to the common IDE layer */
pci_set_drvdata(pdev, NULL);
@@ -1315,12 +1332,12 @@ out_free_pmif:
static int
pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
- ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+ int rc = 0;
+
if (mesg.event != pdev->dev.power.power_state.event
&& (mesg.event & PM_EVENT_SLEEP)) {
- rc = pmac_ide_do_suspend(hwif);
+ rc = pmac_ide_do_suspend(pmif);
if (rc == 0)
pdev->dev.power.power_state = mesg;
}
@@ -1331,11 +1348,11 @@ pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
static int
pmac_ide_pci_resume(struct pci_dev *pdev)
{
- ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+ int rc = 0;
+
if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
- rc = pmac_ide_do_resume(hwif);
+ rc = pmac_ide_do_resume(pmif);
if (rc == 0)
pdev->dev.power.power_state = PMSG_ON;
}
@@ -1426,10 +1443,11 @@ out:
static int
pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct dbdma_cmd *table;
int i, count = 0;
- ide_hwif_t *hwif = HWIF(drive);
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
struct scatterlist *sg;
int wr = (rq_data_dir(rq) == WRITE);
@@ -1505,18 +1523,6 @@ use_pio_instead:
return 0; /* revert to PIO for this request */
}
-/* Teardown mappings after DMA has completed. */
-static void
-pmac_ide_destroy_dmatable (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- if (hwif->sg_nents) {
- ide_destroy_dmatable(drive);
- hwif->sg_nents = 0;
- }
-}
-
/*
* Prepare a DMA transfer. We build the DMA table, adjust the timings for
* a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
@@ -1525,14 +1531,10 @@ static int
pmac_ide_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct request *rq = HWGROUP(drive)->rq;
- u8 unit = (drive->select.b.unit & 0x01);
- u8 ata4;
-
- if (pmif == NULL)
- return 1;
- ata4 = (pmif->kind == controller_kl_ata4);
+ u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4);
if (!pmac_ide_build_dmatable(drive, rq)) {
ide_map_sg(drive, rq);
@@ -1565,7 +1567,9 @@ pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
static void
pmac_ide_dma_start(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
dma = pmif->dma_regs;
@@ -1581,18 +1585,18 @@ pmac_ide_dma_start(ide_drive_t *drive)
static int
pmac_ide_dma_end (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
- volatile struct dbdma_regs __iomem *dma;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+ volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
u32 dstat;
-
- if (pmif == NULL)
- return 0;
- dma = pmif->dma_regs;
drive->waiting_for_dma = 0;
dstat = readl(&dma->status);
writel(((RUN|WAKE|DEAD) << 16), &dma->control);
- pmac_ide_destroy_dmatable(drive);
+
+ ide_destroy_dmatable(drive);
+
/* verify good dma status. we don't check for ACTIVE beeing 0. We should...
* in theory, but with ATAPI decices doing buffer underruns, that would
* cause us to disable DMA, which isn't what we want
@@ -1609,14 +1613,12 @@ pmac_ide_dma_end (ide_drive_t *drive)
static int
pmac_ide_dma_test_irq (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
- volatile struct dbdma_regs __iomem *dma;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+ volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
unsigned long status, timeout;
- if (pmif == NULL)
- return 0;
- dma = pmif->dma_regs;
-
/* We have to things to deal with here:
*
* - The dbdma won't stop if the command was started
@@ -1635,9 +1637,6 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
status = readl(&dma->status);
if (!(status & ACTIVE))
return 1;
- if (!drive->waiting_for_dma)
- printk(KERN_WARNING "ide%d, ide_dma_test_irq \
- called while not waiting\n", HWIF(drive)->index);
/* If dbdma didn't execute the STOP command yet, the
* active bit is still set. We consider that we aren't
@@ -1669,15 +1668,12 @@ static void pmac_ide_dma_host_set(ide_drive_t *drive, int on)
static void
pmac_ide_dma_lost_irq (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
- volatile struct dbdma_regs __iomem *dma;
- unsigned long status;
-
- if (pmif == NULL)
- return;
- dma = pmif->dma_regs;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+ volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
+ unsigned long status = readl(&dma->status);
- status = readl(&dma->status);
printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
}
@@ -1699,7 +1695,8 @@ static const struct ide_dma_ops pmac_dma_ops = {
static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
const struct ide_port_info *d)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct pci_dev *dev = to_pci_dev(hwif->dev);
/* We won't need pci_dev if we switch to generic consistent
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 5171601fb25..9f1f9163a13 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -6,19 +6,15 @@
* May be copied or modified under the terms of the GNU General Public License
*/
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ide.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>
-#include <asm/irq.h>
/**
* ide_setup_pci_baseregs - place a PCI IDE controller native
@@ -43,17 +39,18 @@ static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
(progif & 5) != 5) {
if ((progif & 0xa) != 0xa) {
- printk(KERN_INFO "%s: device not capable of full "
- "native PCI mode\n", name);
+ printk(KERN_INFO "%s %s: device not capable of full "
+ "native PCI mode\n", name, pci_name(dev));
return -EOPNOTSUPP;
}
- printk("%s: placing both ports into native PCI mode\n", name);
+ printk(KERN_INFO "%s %s: placing both ports into native PCI "
+ "mode\n", name, pci_name(dev));
(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
(progif & 5) != 5) {
- printk(KERN_ERR "%s: rewrite of PROGIF failed, wanted "
- "0x%04x, got 0x%04x\n",
- name, progif|5, progif);
+ printk(KERN_ERR "%s %s: rewrite of PROGIF failed, "
+ "wanted 0x%04x, got 0x%04x\n",
+ name, pci_name(dev), progif | 5, progif);
return -EOPNOTSUPP;
}
}
@@ -61,14 +58,14 @@ 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)
+static int 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);
+
+ return (dma_stat & 0x80) ? 1 : 0;
}
/**
@@ -77,17 +74,14 @@ static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
* @d: IDE port info
*
* Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space.
- * Where a device has a partner that is already in DMA mode we check
- * and enforce IDE simplex rules.
*/
unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long dma_base = 0;
- u8 dma_stat = 0;
- if (hwif->mmio)
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
return hwif->dma_base;
if (hwif->mate && hwif->mate->dma_base) {
@@ -98,7 +92,8 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
dma_base = pci_resource_start(dev, baridx);
if (dma_base == 0) {
- printk(KERN_ERR "%s: DMA base is invalid\n", d->name);
+ printk(KERN_ERR "%s %s: DMA base is invalid\n",
+ d->name, pci_name(dev));
return 0;
}
}
@@ -106,11 +101,22 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
if (hwif->channel)
dma_base += 8;
- if (d->host_flags & IDE_HFLAG_CS5520)
+ return dma_base;
+}
+EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+
+int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u8 dma_stat;
+
+ if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520))
goto out;
if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
- ide_pci_clear_simplex(dma_base, d->name);
+ if (ide_pci_clear_simplex(hwif->dma_base, d->name))
+ printk(KERN_INFO "%s %s: simplex device: DMA forced\n",
+ d->name, pci_name(dev));
goto out;
}
@@ -124,15 +130,16 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
* 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);
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
- printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
- dma_base = 0;
+ printk(KERN_INFO "%s %s: simplex device: DMA disabled\n",
+ d->name, pci_name(dev));
+ return -1;
}
out:
- return dma_base;
+ return 0;
}
-EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+EXPORT_SYMBOL_GPL(ide_pci_check_simplex);
/*
* Set up BM-DMA capability (PnP BIOS should have done this)
@@ -148,8 +155,8 @@ int ide_pci_set_master(struct pci_dev *dev, const char *name)
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) ||
(pcicmd & PCI_COMMAND_MASTER) == 0) {
- printk(KERN_ERR "%s: error updating PCICMD on %s\n",
- name, pci_name(dev));
+ printk(KERN_ERR "%s %s: error updating PCICMD\n",
+ name, pci_name(dev));
return -EIO;
}
}
@@ -161,9 +168,9 @@ EXPORT_SYMBOL_GPL(ide_pci_set_master);
void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
{
- printk(KERN_INFO "%s: IDE controller (0x%04x:0x%04x rev 0x%02x) at "
- " PCI slot %s\n", d->name, dev->vendor, dev->device,
- dev->revision, pci_name(dev));
+ printk(KERN_INFO "%s %s: IDE controller (0x%04x:0x%04x rev 0x%02x)\n",
+ d->name, pci_name(dev),
+ dev->vendor, dev->device, dev->revision);
}
EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
@@ -188,11 +195,12 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
if (pci_enable_device(dev)) {
ret = pci_enable_device_io(dev);
if (ret < 0) {
- printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
- "Could not enable device.\n", d->name);
+ printk(KERN_WARNING "%s %s: couldn't enable device\n",
+ d->name, pci_name(dev));
goto out;
}
- printk(KERN_WARNING "%s: BIOS configuration fixed.\n", d->name);
+ printk(KERN_WARNING "%s %s: BIOS configuration fixed\n",
+ d->name, pci_name(dev));
}
/*
@@ -202,7 +210,8 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
*/
ret = pci_set_dma_mask(dev, DMA_32BIT_MASK);
if (ret < 0) {
- printk(KERN_ERR "%s: can't set dma mask\n", d->name);
+ printk(KERN_ERR "%s %s: can't set DMA mask\n",
+ d->name, pci_name(dev));
goto out;
}
@@ -220,7 +229,8 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
ret = pci_request_selected_regions(dev, bars, d->name);
if (ret < 0)
- printk(KERN_ERR "%s: can't reserve resources\n", d->name);
+ printk(KERN_ERR "%s %s: can't reserve resources\n",
+ d->name, pci_name(dev));
out:
return ret;
}
@@ -246,15 +256,18 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
*/
if (ide_setup_pci_baseregs(dev, d->name) ||
pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
- printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name);
+ printk(KERN_INFO "%s %s: device disabled (BIOS)\n",
+ d->name, pci_name(dev));
return -ENODEV;
}
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
- printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);
+ printk(KERN_ERR "%s %s: error accessing PCI regs\n",
+ d->name, pci_name(dev));
return -EIO;
}
if (!(pcicmd & PCI_COMMAND_IO)) {
- printk(KERN_ERR "%s: unable to enable IDE controller\n", d->name);
+ printk(KERN_ERR "%s %s: unable to enable IDE controller\n",
+ d->name, pci_name(dev));
return -ENXIO;
}
return 0;
@@ -288,67 +301,55 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
}
/**
- * ide_hwif_configure - configure an IDE interface
+ * ide_hw_configure - configure a hw_regs_t instance
* @dev: PCI device holding interface
* @d: IDE port info
* @port: port number
* @irq: PCI IRQ
+ * @hw: hw_regs_t instance corresponding to this port
*
* Perform the initial set up for the hardware interface structure. This
* is done per interface port rather than per PCI device. There may be
* more than one port per device.
*
- * Returns the new hardware interface structure, or NULL on a failure
+ * Returns zero on success or an error code.
*/
-static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
- const struct ide_port_info *d,
- unsigned int port, int irq)
+static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
+ unsigned int port, int irq, hw_regs_t *hw)
{
unsigned long ctl = 0, base = 0;
- ide_hwif_t *hwif;
- struct hw_regs_s hw;
if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
if (ide_pci_check_iomem(dev, d, 2 * port) ||
ide_pci_check_iomem(dev, d, 2 * port + 1)) {
- printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
- "as MEM for port %d!\n", d->name, port);
- return NULL;
+ printk(KERN_ERR "%s %s: I/O baseregs (BIOS) are "
+ "reported as MEM for port %d!\n",
+ d->name, pci_name(dev), port);
+ return -EINVAL;
}
ctl = pci_resource_start(dev, 2*port+1);
base = pci_resource_start(dev, 2*port);
- if ((ctl && !base) || (base && !ctl)) {
- printk(KERN_ERR "%s: inconsistent baseregs (BIOS) "
- "for port %d, skipping\n", d->name, port);
- return NULL;
- }
- }
- if (!ctl) {
+ } else {
/* Use default values */
ctl = port ? 0x374 : 0x3f4;
base = port ? 0x170 : 0x1f0;
}
- hwif = ide_find_port_slot(d);
- if (hwif == NULL) {
- printk(KERN_ERR "%s: too many IDE interfaces, no room in "
- "table\n", d->name);
- return NULL;
+ if (!base || !ctl) {
+ printk(KERN_ERR "%s %s: bad PCI BARs for port %d, skipping\n",
+ d->name, pci_name(dev), port);
+ return -EINVAL;
}
- memset(&hw, 0, sizeof(hw));
- hw.irq = irq;
- hw.dev = &dev->dev;
- hw.chipset = d->chipset ? d->chipset : ide_pci;
- ide_std_init_ports(&hw, base, ctl | 2);
-
- ide_init_port_hw(hwif, &hw);
+ memset(hw, 0, sizeof(*hw));
+ hw->irq = irq;
+ hw->dev = &dev->dev;
+ hw->chipset = d->chipset ? d->chipset : ide_pci;
+ ide_std_init_ports(hw, base, ctl | 2);
- hwif->dev = &dev->dev;
-
- return hwif;
+ return 0;
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -371,10 +372,18 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
(dev->class & 0x80))) {
unsigned long base = ide_pci_dma_base(hwif, d);
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
- if (hwif->mmio)
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
else
printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n",
@@ -385,7 +394,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
}
return 0;
@@ -397,14 +406,14 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
* @dev: PCI device
* @d: IDE port info
* @noisy: verbose flag
- * @config: returned as 1 if we configured the hardware
*
* Set up the PCI and controller side of the IDE interface. This brings
* up the PCI side of the device, checks that the device is enabled
* and enables it if need be
*/
-static int ide_setup_pci_controller(struct pci_dev *dev, const struct ide_port_info *d, int noisy, int *config)
+static int ide_setup_pci_controller(struct pci_dev *dev,
+ const struct ide_port_info *d, int noisy)
{
int ret;
u16 pcicmd;
@@ -418,15 +427,16 @@ static int ide_setup_pci_controller(struct pci_dev *dev, const struct ide_port_i
ret = pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
if (ret < 0) {
- printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);
+ printk(KERN_ERR "%s %s: error accessing PCI regs\n",
+ d->name, pci_name(dev));
goto out;
}
if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */
ret = ide_pci_configure(dev, d);
if (ret < 0)
goto out;
- *config = 1;
- printk(KERN_INFO "%s: device enabled (Linux)\n", d->name);
+ printk(KERN_INFO "%s %s: device enabled (Linux)\n",
+ d->name, pci_name(dev));
}
out:
@@ -438,7 +448,8 @@ out:
* @dev: PCI device
* @d: IDE port info
* @pciirq: IRQ line
- * @idx: ATA index table to update
+ * @hw: hw_regs_t instances corresponding to this PCI IDE device
+ * @hws: hw_regs_t pointers table to update
*
* Scan the interfaces attached to this device and do any
* necessary per port setup. Attach the devices and ask the
@@ -449,10 +460,10 @@ out:
* where the chipset setup is not the default PCI IDE one.
*/
-void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx)
+void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
+ int pciirq, hw_regs_t *hw, hw_regs_t **hws)
{
int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
- ide_hwif_t *hwif;
u8 tmp;
/*
@@ -464,15 +475,15 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
(tmp & e->mask) != e->val)) {
- printk(KERN_INFO "%s: IDE port disabled\n", d->name);
+ printk(KERN_INFO "%s %s: IDE port disabled\n",
+ d->name, pci_name(dev));
continue; /* port not enabled */
}
- hwif = ide_hwif_configure(dev, d, port, pciirq);
- if (hwif == NULL)
+ if (ide_hw_configure(dev, d, port, pciirq, hw + port))
continue;
- *(idx + port) = hwif->index;
+ *(hws + port) = hw + port;
}
}
EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
@@ -489,95 +500,195 @@ EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
*/
static int do_ide_setup_pci_device(struct pci_dev *dev,
const struct ide_port_info *d,
- u8 *idx, u8 noisy)
+ u8 noisy)
{
- int tried_config = 0;
int pciirq, ret;
- ret = ide_setup_pci_controller(dev, d, noisy, &tried_config);
- if (ret < 0)
- goto out;
-
/*
* Can we trust the reported IRQ?
*/
pciirq = dev->irq;
+ /*
+ * This allows offboard ide-pci cards the enable a BIOS,
+ * verify interrupt settings of split-mirror pci-config
+ * space, place chipset into init-mode, and/or preserve
+ * an interrupt if the card is not native ide support.
+ */
+ ret = d->init_chipset ? d->init_chipset(dev) : 0;
+ if (ret < 0)
+ goto out;
+
/* Is it an "IDE storage" device in non-PCI mode? */
if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 5) != 5) {
if (noisy)
- printk(KERN_INFO "%s: not 100%% native mode: "
- "will probe irqs later\n", d->name);
- /*
- * This allows offboard ide-pci cards the enable a BIOS,
- * verify interrupt settings of split-mirror pci-config
- * space, place chipset into init-mode, and/or preserve
- * an interrupt if the card is not native ide support.
- */
- ret = d->init_chipset ? d->init_chipset(dev, d->name) : 0;
- if (ret < 0)
- goto out;
+ printk(KERN_INFO "%s %s: not 100%% native mode: will "
+ "probe irqs later\n", d->name, pci_name(dev));
pciirq = ret;
- } else if (tried_config) {
- if (noisy)
- printk(KERN_INFO "%s: will probe irqs later\n", d->name);
- pciirq = 0;
- } else if (!pciirq) {
- if (noisy)
- printk(KERN_WARNING "%s: bad irq (%d): will probe later\n",
- d->name, pciirq);
- pciirq = 0;
- } else {
- if (d->init_chipset) {
- ret = d->init_chipset(dev, d->name);
- if (ret < 0)
- goto out;
- }
- if (noisy)
- printk(KERN_INFO "%s: 100%% native mode on irq %d\n",
- d->name, pciirq);
+ } else if (!pciirq && noisy) {
+ printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n",
+ d->name, pci_name(dev), pciirq);
+ } else if (noisy) {
+ printk(KERN_INFO "%s %s: 100%% native mode on irq %d\n",
+ d->name, pci_name(dev), pciirq);
}
- /* FIXME: silent failure can happen */
-
- ide_pci_setup_ports(dev, d, pciirq, idx);
+ ret = pciirq;
out:
return ret;
}
-int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
+int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d,
+ void *priv)
{
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ struct ide_host *host;
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
int ret;
- ret = do_ide_setup_pci_device(dev, d, &idx[0], 1);
+ ret = ide_setup_pci_controller(dev, d, 1);
+ if (ret < 0)
+ goto out;
+
+ ide_pci_setup_ports(dev, d, 0, &hw[0], &hws[0]);
+
+ host = ide_host_alloc(d, hws);
+ if (host == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->dev[0] = &dev->dev;
+
+ host->host_priv = priv;
- if (ret >= 0)
- ide_device_add(idx, d);
+ pci_set_drvdata(dev, host);
+ ret = do_ide_setup_pci_device(dev, d, 1);
+ if (ret < 0)
+ goto out;
+
+ /* fixup IRQ */
+ hw[1].irq = hw[0].irq = ret;
+
+ ret = ide_host_register(host, d, hws);
+ if (ret)
+ ide_host_free(host);
+out:
return ret;
}
-EXPORT_SYMBOL_GPL(ide_setup_pci_device);
+EXPORT_SYMBOL_GPL(ide_pci_init_one);
-int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
- const struct ide_port_info *d)
+int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
+ const struct ide_port_info *d, void *priv)
{
struct pci_dev *pdev[] = { dev1, dev2 };
+ struct ide_host *host;
int ret, i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
+
+ for (i = 0; i < 2; i++) {
+ ret = ide_setup_pci_controller(pdev[i], d, !i);
+ if (ret < 0)
+ goto out;
+
+ ide_pci_setup_ports(pdev[i], d, 0, &hw[i*2], &hws[i*2]);
+ }
+
+ host = ide_host_alloc(d, hws);
+ if (host == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->dev[0] = &dev1->dev;
+ host->dev[1] = &dev2->dev;
+
+ host->host_priv = priv;
+
+ pci_set_drvdata(pdev[0], host);
+ pci_set_drvdata(pdev[1], host);
for (i = 0; i < 2; i++) {
- ret = do_ide_setup_pci_device(pdev[i], d, &idx[i*2], !i);
+ ret = do_ide_setup_pci_device(pdev[i], d, !i);
+
/*
* FIXME: Mom, mom, they stole me the helper function to undo
* do_ide_setup_pci_device() on the first device!
*/
if (ret < 0)
goto out;
+
+ /* fixup IRQ */
+ hw[i*2 + 1].irq = hw[i*2].irq = ret;
}
- ide_device_add(idx, d);
+ ret = ide_host_register(host, d, hws);
+ if (ret)
+ ide_host_free(host);
out:
return ret;
}
-EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
+EXPORT_SYMBOL_GPL(ide_pci_init_two);
+
+void ide_pci_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+ int bars;
+
+ if (host->host_flags & IDE_HFLAG_SINGLE)
+ bars = (1 << 2) - 1;
+ else
+ bars = (1 << 4) - 1;
+
+ if ((host->host_flags & IDE_HFLAG_NO_DMA) == 0) {
+ if (host->host_flags & IDE_HFLAG_CS5520)
+ bars |= (1 << 2);
+ else
+ bars |= (1 << 4);
+ }
+
+ ide_host_remove(host);
+
+ if (dev2)
+ pci_release_selected_regions(dev2, bars);
+ pci_release_selected_regions(dev, bars);
+
+ if (dev2)
+ pci_disable_device(dev2);
+ pci_disable_device(dev);
+}
+EXPORT_SYMBOL_GPL(ide_pci_remove);
+
+#ifdef CONFIG_PM
+int ide_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_pci_suspend);
+
+int ide_pci_resume(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ int rc;
+
+ pci_set_power_state(dev, PCI_D0);
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ pci_restore_state(dev);
+ pci_set_master(dev);
+
+ if (host->init_chipset)
+ host->init_chipset(dev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_pci_resume);
+#endif