diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-15 13:46:29 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-15 13:46:29 +0200 |
commit | b2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (patch) | |
tree | 53ccb1c2c14751fe69cf93102e76e97021f6df07 /drivers/ide | |
parent | 4f962d4d65923d7b722192e729840cfb79af0a5a (diff) | |
parent | 278429cff8809958d25415ba0ed32b59866ab1a8 (diff) |
Merge branch 'linus' into stackprotector
Conflicts:
arch/x86/kernel/Makefile
include/asm-x86/pda.h
Diffstat (limited to 'drivers/ide')
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, ®); 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 &= ~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 |