diff options
Diffstat (limited to 'drivers/ide')
87 files changed, 5977 insertions, 9421 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 6eaece96524..45b26ed351c 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -152,9 +152,22 @@ config BLK_DEV_IDEDISK If unsure, say Y. config IDEDISK_MULTI_MODE - bool "Use multi-mode by default" - help - If you get this error, try to say Y here: + bool "Use multiple sector mode for Programmed Input/Output by default" + help + This setting is irrelevant for most IDE disks, with direct memory + access, to which multiple sector mode does not apply. Multiple sector + mode is a feature of most modern IDE hard drives, permitting the + transfer of multiple sectors per Programmed Input/Output interrupt, + rather than the usual one sector per interrupt. When this feature is + enabled, it can reduce operating system overhead for disk Programmed + Input/Output. On some systems, it also can increase the data + throughput of Programmed Input/Output. Some drives, however, seemed + to run slower with multiple sector mode enabled. Some drives claimed + to support multiple sector mode, but lost data at some settings. + Under rare circumstances, such failures could result in massive + filesystem corruption. + + If you get the following error, try to say Y here: hda: set_multmode: status=0x51 { DriveReady SeekComplete Error } hda: set_multmode: error=0x04 { DriveStatusError } @@ -190,16 +203,20 @@ config BLK_DEV_IDECD CD-ROM drive, you can say N to all other CD-ROM options, but be sure to say Y or M to "ISO 9660 CD-ROM file system support". - Note that older versions of LILO (LInux LOader) cannot properly deal - with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from - <http://lilo.go.dyndns.org/>. - To compile this driver as a module, choose M here: the module will be called ide-cd. +config BLK_DEV_IDECD_VERBOSE_ERRORS + bool "Verbose error logging for IDE/ATAPI CDROM driver" if EMBEDDED + depends on BLK_DEV_IDECD + default y + help + Turn this on to have the driver print out the meanings of the + ATAPI error codes. This will use up additional 8kB of kernel-space + memory, though. + config BLK_DEV_IDETAPE - tristate "Include IDE/ATAPI TAPE support (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Include IDE/ATAPI TAPE support" help If you have an IDE tape drive using the ATAPI protocol, say Y. ATAPI is a newer protocol used by IDE tape and CD-ROM drives, @@ -304,7 +321,6 @@ comment "IDE chipset support/bugfixes" config IDE_GENERIC tristate "generic/default IDE chipset support" - default H8300 help If unsure, say N. @@ -317,7 +333,7 @@ config BLK_DEV_PLATFORM If unsure, say N. config BLK_DEV_CMD640 - bool "CMD640 chipset bugfix/support" + tristate "CMD640 chipset bugfix/support" depends on X86 ---help--- The CMD-Technologies CMD640 IDE chip is used on many common 486 and @@ -351,9 +367,8 @@ config BLK_DEV_CMD640_ENHANCED Otherwise say N. config BLK_DEV_IDEPNP - bool "PNP EIDE support" + tristate "PNP EIDE support" depends on PNP - select IDE_GENERIC help If you have a PnP (Plug and Play) compatible EIDE card and would like the kernel to automatically detect and activate @@ -366,23 +381,25 @@ comment "PCI IDE chipsets support" config BLK_DEV_IDEPCI bool -config IDEPCI_SHARE_IRQ - bool "Sharing PCI IDE interrupts support" - depends on BLK_DEV_IDEPCI +config IDEPCI_PCIBUS_ORDER + bool "Probe IDE PCI devices in the PCI bus order (DEPRECATED)" + depends on BLK_DEV_IDE=y && BLK_DEV_IDEPCI + default y help - Some ATA/IDE chipsets have hardware support which allows for - sharing a single IRQ with other cards. To enable support for - this in the ATA/IDE driver, say Y here. + Probe IDE PCI devices in the order in which they appear on the + PCI bus (i.e. 00:1f.1 PCI device before 02:01.0 PCI device) + instead of the order in which IDE PCI host drivers are loaded. - It is safe to say Y to this question, in most cases. - If unsure, say N. + Please note that this method of assuring stable naming of + IDE devices is unreliable and use other means for achieving + it (i.e. udev). -config IDEPCI_PCIBUS_ORDER - def_bool BLK_DEV_IDE=y && BLK_DEV_IDEPCI + If in doubt, say N. +# TODO: split it on per host driver config options (or module parameters) config BLK_DEV_OFFBOARD - bool "Boot off-board chipsets first support" - depends on BLK_DEV_IDEPCI + bool "Boot off-board chipsets first support (DEPRECATED)" + depends on BLK_DEV_IDEPCI && (BLK_DEV_AEC62XX || BLK_DEV_GENERIC || BLK_DEV_HPT34X || BLK_DEV_HPT366 || BLK_DEV_PDC202XX_NEW || BLK_DEV_PDC202XX_OLD || BLK_DEV_TC86C001) help Normally, IDE controllers built into the motherboard (on-board controllers) are assigned to ide0 and ide1 while those on add-in PCI @@ -401,6 +418,10 @@ config BLK_DEV_OFFBOARD Note that, if you do this, the order of the hd* devices will be rearranged which may require modification of fstab and other files. + Please also note that this method of assuring stable naming of + IDE devices is unreliable and use other means for achieving it + (i.e. udev). + If in doubt, say N. config BLK_DEV_GENERIC @@ -474,6 +495,7 @@ config WDC_ALI15X3 config BLK_DEV_AMD74XX tristate "AMD and nVidia IDE support" + depends on !ARM select BLK_DEV_IDEDMA_PCI help This driver adds explicit support for AMD-7xx and AMD-8111 chips @@ -603,8 +625,8 @@ config BLK_DEV_SC1200 tristate "National SCx200 chipset support" select BLK_DEV_IDEDMA_PCI help - This driver adds support for the built in IDE on the National - SCx200 series of embedded x86 "Geode" systems + This driver adds support for the on-board IDE controller on the + National SCx200 series of embedded x86 "Geode" systems. config BLK_DEV_PIIX tristate "Intel PIIXn chipsets support" @@ -693,7 +715,6 @@ config BLK_DEV_SVWKS config BLK_DEV_SGIIOC4 tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support" depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4 - select IDEPCI_SHARE_IRQ select BLK_DEV_IDEDMA_PCI help This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4 @@ -780,22 +801,22 @@ config BLK_DEV_CELLEB depends on PPC_CELLEB select BLK_DEV_IDEDMA_PCI help - This driver provides support for the built-in IDE controller on + This driver provides support for the on-board IDE controller on Toshiba Cell Reference Board. If unsure, say Y. endif config BLK_DEV_IDE_PMAC - bool "Builtin PowerMac IDE support" + tristate "PowerMac on-board IDE support" depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y help - This driver provides support for the built-in IDE controller on + This driver provides support for the on-board IDE controller on most of the recent Apple Power Macintoshes and PowerBooks. If unsure, say Y. config BLK_DEV_IDE_PMAC_ATA100FIRST - bool "Probe internal ATA/100 (Kauai) first" + bool "Probe on-board ATA/100 (Kauai) first" depends on BLK_DEV_IDE_PMAC help This option will cause the ATA/100 controller found in UniNorth2 @@ -810,7 +831,7 @@ config BLK_DEV_IDEDMA_PMAC depends on BLK_DEV_IDE_PMAC select BLK_DEV_IDEDMA_PCI help - This option allows the driver for the built-in IDE controller on + This option allows the driver for the on-board IDE controller on Power Macintoshes and PowerBooks to use DMA (direct memory access) to transfer data to and from memory. Saying Y is safe and improves performance. @@ -841,8 +862,9 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ depends on BLK_DEV_IDE_AU1XXX config IDE_ARM - def_bool ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) - select IDE_GENERIC + tristate "ARM IDE support" + depends on ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) + default y config BLK_DEV_IDE_ICSIDE tristate "ICS IDE interface support" @@ -873,14 +895,54 @@ config BLK_DEV_IDE_BAST Say Y here if you want to support the onboard IDE channels on the Simtec BAST or the Thorcom VR1000 +config ETRAX_IDE + tristate "ETRAX IDE support" + depends on CRIS && BROKEN + select BLK_DEV_IDEDMA + help + Enables the ETRAX IDE driver. + + You can't use parallel ports or SCSI ports at the same time. + +config ETRAX_IDE_DELAY + int "Delay for drives to regain consciousness" + depends on ETRAX_IDE && ETRAX_ARCH_V10 + default 15 + help + Number of seconds to wait for IDE drives to spin up after an IDE + reset. + +choice + prompt "IDE reset pin" + depends on ETRAX_IDE && ETRAX_ARCH_V10 + default ETRAX_IDE_PB7_RESET + +config ETRAX_IDE_PB7_RESET + bool "Port_PB_Bit_7" + help + IDE reset on pin 7 on port B + +config ETRAX_IDE_G27_RESET + bool "Port_G_Bit_27" + help + IDE reset on pin 27 on port G + +endchoice + +config IDE_H8300 + tristate "H8300 IDE support" + depends on H8300 + default y + help + Enables the H8300 IDE driver. + config BLK_DEV_GAYLE - bool "Amiga Gayle IDE interface support" + tristate "Amiga Gayle IDE interface support" depends on AMIGA - select IDE_GENERIC help This is the IDE driver for the Amiga Gayle IDE interface. It supports both the `A1200 style' and `A4000 style' of the Gayle IDE interface, - This includes builtin IDE interfaces on some Amiga models (A600, + This includes on-board IDE interfaces on some Amiga models (A600, A1200, A4000, and A4000T), and IDE interfaces on the Zorro expansion bus (M-Tech E-Matrix 530 expansion card). Say Y if you have an Amiga with a Gayle IDE interface and want to use @@ -894,10 +956,10 @@ config BLK_DEV_IDEDOUBLER depends on BLK_DEV_GAYLE && EXPERIMENTAL ---help--- This driver provides support for the so-called `IDE doublers' (made - by various manufacturers, e.g. Eyetech) that can be connected to the - builtin IDE interface of some Amiga models. Using such an IDE - doubler, you can connect up to four instead of two IDE devices on - the Amiga's builtin IDE interface. + by various manufacturers, e.g. Eyetech) that can be connected to + the on-board IDE interface of some Amiga models. Using such an IDE + doubler, you can connect up to four instead of two IDE devices to + the Amiga's on-board IDE interface. Note that the normal Amiga Gayle IDE driver may not work correctly if you have an IDE doubler and don't enable this driver! @@ -906,55 +968,50 @@ config BLK_DEV_IDEDOUBLER runtime using the "ide=doubler" kernel boot parameter. config BLK_DEV_BUDDHA - bool "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)" + tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)" depends on ZORRO && EXPERIMENTAL - select IDE_GENERIC help - This is the IDE driver for the IDE interfaces on the Buddha, - Catweasel and X-Surf expansion boards. It supports up to two interfaces - on the Buddha, three on the Catweasel and two on the X-Surf. + This is the IDE driver for the IDE interfaces on the Buddha, Catweasel + and X-Surf expansion boards. It supports up to two interfaces on the + Buddha, three on the Catweasel and two on the X-Surf. Say Y if you have a Buddha or Catweasel expansion board and want to use IDE devices (hard disks, CD-ROM drives, etc.) that are connected to one of its IDE interfaces. config BLK_DEV_FALCON_IDE - bool "Falcon IDE interface support" + tristate "Falcon IDE interface support" depends on ATARI - select IDE_GENERIC help - This is the IDE driver for the builtin IDE interface on the Atari + This is the IDE driver for the on-board IDE interface on the Atari Falcon. Say Y if you have a Falcon and want to use IDE devices (hard - disks, CD-ROM drives, etc.) that are connected to the builtin IDE + disks, CD-ROM drives, etc.) that are connected to the on-board IDE interface. config BLK_DEV_MAC_IDE - bool "Macintosh Quadra/Powerbook IDE interface support" + tristate "Macintosh Quadra/Powerbook IDE interface support" depends on MAC - select IDE_GENERIC help - This is the IDE driver for the builtin IDE interface on some m68k + This is the IDE driver for the on-board IDE interface on some m68k Macintosh models. It supports both the `Quadra style' (used in Quadra/ Centris 630 and Performa 588 models) and `Powerbook style' (used in the Powerbook 150 and 190 models) IDE interface. Say Y if you have such an Macintosh model and want to use IDE devices (hard disks, CD-ROM drives, etc.) that are connected to the - builtin IDE interface. + on-board IDE interface. config BLK_DEV_Q40IDE - bool "Q40/Q60 IDE interface support" + tristate "Q40/Q60 IDE interface support" depends on Q40 - select IDE_GENERIC help Enable the on-board IDE controller in the Q40/Q60. This should normally be on; disable it only if you are running a custom hard drive subsystem through an expansion card. config BLK_DEV_MPC8xx_IDE - bool "MPC8xx IDE support" - depends on 8xx && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE - select IDE_GENERIC + tristate "MPC8xx IDE support" + depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE help This option provides support for IDE on Motorola MPC8xx Systems. Please see 'Type of MPC8xx IDE interface' for details. @@ -1013,8 +1070,8 @@ config BLK_DEV_ALI14XX boot parameter. It enables support for the secondary IDE interface of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster I/O speeds to be set as well. See the files - <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c> for - more info. + <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c> + for more info. config BLK_DEV_DTC2278 tristate "DTC-2278 support" @@ -1039,8 +1096,8 @@ config BLK_DEV_QD65XX help This driver is enabled at runtime using the "qd65xx.probe" kernel boot parameter. It permits faster I/O speeds to be set. See the - <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> for - more info. + <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> + for more info. config BLK_DEV_UMC8672 tristate "UMC-8672 support" diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 75dc6969e0a..a4a4323be91 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -7,48 +7,60 @@ # Note : at this point, these files are compiled on all systems. # In the future, some of these should be built conditionally. # -# First come modules that register themselves with the core +# link order is important here EXTRA_CFLAGS += -Idrivers/ide -obj-$(CONFIG_BLK_DEV_IDE) += pci/ - ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o -ide-core-$(CONFIG_BLK_DEV_CMD640) += pci/cmd640.o - -# Core IDE code - must come before legacy +# core IDE code ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o -ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o -# built-in only drivers from arm/ -ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o +obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o -# built-in only drivers from legacy/ -ide-core-$(CONFIG_BLK_DEV_BUDDHA) += legacy/buddha.o -ide-core-$(CONFIG_BLK_DEV_FALCON_IDE) += legacy/falconide.o -ide-core-$(CONFIG_BLK_DEV_GAYLE) += legacy/gayle.o -ide-core-$(CONFIG_BLK_DEV_MAC_IDE) += legacy/macide.o -ide-core-$(CONFIG_BLK_DEV_Q40IDE) += legacy/q40ide.o +ifeq ($(CONFIG_IDE_ARM), y) + ide-arm-core-y += arm/ide_arm.o + obj-y += ide-arm-core.o +endif -# built-in only drivers from ppc/ -ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o -ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o +obj-$(CONFIG_BLK_DEV_IDE) += legacy/ pci/ -# built-in only drivers from h8300/ -ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o +obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o -obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o +ifeq ($(CONFIG_BLK_DEV_CMD640), y) + cmd640-core-y += pci/cmd640.o + obj-y += cmd640-core.o +endif + +obj-$(CONFIG_BLK_DEV_IDE) += cris/ ppc/ +obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o +obj-$(CONFIG_IDE_H8300) += h8300/ obj-$(CONFIG_IDE_GENERIC) += ide-generic.o +ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o + obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o -obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o +obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o -obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ mips/ -obj-$(CONFIG_BLK_DEV_HD) += legacy/ -obj-$(CONFIG_ETRAX_IDE) += cris/ +ifeq ($(CONFIG_BLK_DEV_IDECS), y) + ide-cs-core-y += legacy/ide-cs.o + obj-y += ide-cs-core.o +endif + +ifeq ($(CONFIG_BLK_DEV_PLATFORM), y) + ide-platform-core-y += legacy/ide_platform.o + obj-y += ide-platform-core.o +endif + +obj-$(CONFIG_BLK_DEV_IDE) += arm/ mips/ + +# old hd driver must be last +ifeq ($(CONFIG_BLK_DEV_HD), y) + hd-core-y += legacy/hd.o + obj-y += hd-core.o +endif diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile index 6a78f0755f2..5f63ad21686 100644 --- a/drivers/ide/arm/Makefile +++ b/drivers/ide/arm/Makefile @@ -3,4 +3,8 @@ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o +ifeq ($(CONFIG_IDE_ARM), m) + obj-m += ide_arm.o +endif + EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c index 48db6167bb9..0e7574c0ee6 100644 --- a/drivers/ide/arm/bast-ide.c +++ b/drivers/ide/arm/bast-ide.c @@ -1,5 +1,4 @@ -/* linux/drivers/ide/arm/bast-ide.c - * +/* * Copyright (c) 2003-2004 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * @@ -29,8 +28,10 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq, ide_hwif_t **hwif) { + ide_hwif_t *hwif; hw_regs_t hw; int i; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; memset(&hw, 0, sizeof(hw)); @@ -45,8 +46,24 @@ bastide_register(unsigned int base, unsigned int aux, int irq, hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20); hw.irq = irq; - ide_register_hw(&hw, NULL, 0, hwif); + hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif == NULL) + goto out; + + i = hwif->index; + + if (hwif->present) + ide_unregister(i, 0, 0); + else if (!hwif->hold) + ide_init_port_data(hwif, i); + + ide_init_port_hw(hwif, &hw); + hwif->quirkproc = NULL; + + idx[0] = i; + ide_device_add(idx, NULL); +out: return 0; } diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 93f71fcfc04..fb00f3827ec 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/arm/icside.c - * * Copyright (c) 1996-2004 Russell King. * * Please note that this platform does not support 32-bit IDE IO. @@ -71,8 +69,6 @@ struct icside_state { void __iomem *irq_port; void __iomem *ioc_base; unsigned int type; - /* parent device... until the IDE core gets one of its own */ - struct device *dev; ide_hwif_t *hwif[2]; }; @@ -206,23 +202,6 @@ static void icside_maskproc(ide_drive_t *drive, int mask) * interfaces use the same IRQ, which should guarantee this. */ -static void icside_build_sglist(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = drive->hwif; - struct icside_state *state = hwif->hwif_data; - struct scatterlist *sg = hwif->sg_table; - - ide_map_sg(drive, rq); - - if (rq_data_dir(rq) == READ) - hwif->sg_dma_direction = DMA_FROM_DEVICE; - else - hwif->sg_dma_direction = DMA_TO_DEVICE; - - hwif->sg_nents = dma_map_sg(state->dev, sg, hwif->sg_nents, - hwif->sg_dma_direction); -} - /* * Configure the IOMD to give the appropriate timings for the transfer * mode being requested. We take the advice of the ATA standards, and @@ -272,8 +251,6 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) case XFER_SW_DMA_0: cycle_time = 480; break; - default: - return; } /* @@ -289,56 +266,39 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); } -static void icside_dma_host_off(ide_drive_t *drive) +static void icside_dma_host_set(ide_drive_t *drive, int on) { } -static void icside_dma_off_quietly(ide_drive_t *drive) -{ - drive->using_dma = 0; -} - -static void icside_dma_host_on(ide_drive_t *drive) -{ -} - -static int icside_dma_on(ide_drive_t *drive) -{ - drive->using_dma = 1; - - return 0; -} - static int icside_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct icside_state *state = hwif->hwif_data; + struct expansion_card *ec = ECARD_DEV(hwif->dev); drive->waiting_for_dma = 0; - disable_dma(ECARD_DEV(state->dev)->dma); + disable_dma(ec->dma); /* Teardown mappings after DMA has completed. */ - dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents, - hwif->sg_dma_direction); + ide_destroy_dmatable(drive); - return get_dma_residue(ECARD_DEV(state->dev)->dma) != 0; + return get_dma_residue(ec->dma) != 0; } static void icside_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct icside_state *state = hwif->hwif_data; + struct expansion_card *ec = ECARD_DEV(hwif->dev); /* We can not enable DMA on both channels simultaneously. */ - BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma)); - enable_dma(ECARD_DEV(state->dev)->dma); + BUG_ON(dma_channel_active(ec->dma)); + enable_dma(ec->dma); } static int icside_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct icside_state *state = hwif->hwif_data; + struct expansion_card *ec = ECARD_DEV(hwif->dev); struct request *rq = hwif->hwgroup->rq; unsigned int dma_mode; @@ -350,9 +310,9 @@ static int icside_dma_setup(ide_drive_t *drive) /* * We can not enable DMA on both channels. */ - BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma)); + BUG_ON(dma_channel_active(ec->dma)); - icside_build_sglist(drive, rq); + hwif->sg_nents = ide_build_sglist(drive, rq); /* * Ensure that we have the right interrupt routed. @@ -367,14 +327,14 @@ static int icside_dma_setup(ide_drive_t *drive) /* * Select the correct timing for this drive. */ - set_dma_speed(ECARD_DEV(state->dev)->dma, drive->drive_data); + set_dma_speed(ec->dma, drive->drive_data); /* * Tell the DMA engine about the SG table and * data direction. */ - set_dma_sg(ECARD_DEV(state->dev)->dma, hwif->sg_table, hwif->sg_nents); - set_dma_mode(ECARD_DEV(state->dev)->dma, dma_mode); + set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents); + set_dma_mode(ec->dma, dma_mode); drive->waiting_for_dma = 1; @@ -417,17 +377,11 @@ static void icside_dma_lost_irq(ide_drive_t *drive) static void icside_dma_init(ide_hwif_t *hwif) { - hwif->mwdma_mask = 7; /* MW0..2 */ - hwif->swdma_mask = 7; /* SW0..2 */ - hwif->dmatable_cpu = NULL; hwif->dmatable_dma = 0; hwif->set_dma_mode = icside_set_dma_mode; - hwif->dma_host_off = icside_dma_host_off; - hwif->dma_off_quietly = icside_dma_off_quietly; - hwif->dma_host_on = icside_dma_host_on; - hwif->ide_dma_on = icside_dma_on; + hwif->dma_host_set = icside_dma_host_set; hwif->dma_setup = icside_dma_setup; hwif->dma_exec_cmd = icside_dma_exec_cmd; hwif->dma_start = icside_dma_start; @@ -465,6 +419,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e hwif->noprobe = 0; hwif->chipset = ide_acorn; hwif->gendev.parent = &ec->dev; + hwif->dev = &ec->dev; } return hwif; @@ -501,11 +456,19 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) idx[0] = hwif->index; - ide_device_add(idx); + ide_device_add(idx, NULL); return 0; } +static const struct ide_port_info icside_v6_port_info __initdata = { + .host_flags = IDE_HFLAG_SERIALIZE | + IDE_HFLAG_NO_DMA | /* no SFF-style DMA */ + IDE_HFLAG_NO_AUTOTUNE, + .mwdma_mask = ATA_MWDMA2, + .swdma_mask = ATA_SWDMA2, +}; + static int __init icside_register_v6(struct icside_state *state, struct expansion_card *ec) { @@ -514,6 +477,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) unsigned int sel = 0; int ret; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + struct ide_port_info d = icside_v6_port_info; ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); if (!ioc_base) { @@ -563,30 +527,25 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) state->hwif[1] = mate; hwif->maskproc = icside_maskproc; - hwif->channel = 0; hwif->hwif_data = state; - hwif->mate = mate; - hwif->serialized = 1; hwif->config_data = (unsigned long)ioc_base; hwif->select_data = sel; mate->maskproc = icside_maskproc; - mate->channel = 1; mate->hwif_data = state; - mate->mate = hwif; - mate->serialized = 1; mate->config_data = (unsigned long)ioc_base; mate->select_data = sel | 1; if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) { icside_dma_init(hwif); icside_dma_init(mate); - } + } else + d.mwdma_mask = d.swdma_mask = 0; idx[0] = hwif->index; idx[1] = mate->index; - ide_device_add(idx); + ide_device_add(idx, &d); return 0; @@ -612,7 +571,6 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id) } state->type = ICS_TYPE_NOTYPE; - state->dev = &ec->dev; idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); if (idmem) { diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c index 8957cbadf5c..43a70e91363 100644 --- a/drivers/ide/arm/ide_arm.c +++ b/drivers/ide/arm/ide_arm.c @@ -24,12 +24,25 @@ # define IDE_ARM_IRQ IRQ_HARDDISK #endif -void __init ide_arm_init(void) +static int __init ide_arm_init(void) { + ide_hwif_t *hwif; hw_regs_t hw; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); hw.irq = IDE_ARM_IRQ; - ide_register_hw(&hw, NULL, 1, NULL); + + hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif) { + ide_init_port_hw(hwif, &hw); + idx[0] = hwif->index; + + ide_device_add(idx, NULL); + } + + return 0; } + +module_init(ide_arm_init); diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c index 0775a3afef4..efba00d2fc3 100644 --- a/drivers/ide/arm/rapide.c +++ b/drivers/ide/arm/rapide.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/arm/rapide.c - * * Copyright (c) 1996-2002 Russell King. */ @@ -13,26 +11,18 @@ #include <asm/ecard.h> -static ide_hwif_t * -rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq) +static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base, + void __iomem *ctrl, unsigned int sz, int irq) { unsigned long port = (unsigned long)base; - ide_hwif_t *hwif = ide_find_port(port); int i; - if (hwif == NULL) - goto out; - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hwif->io_ports[i] = port; + hw->io_ports[i] = port; port += sz; } - hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; - hwif->irq = irq; - hwif->mmio = 1; - default_hwif_mmiops(hwif); -out: - return hwif; + hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; + hw->irq = irq; } static int __devinit @@ -42,6 +32,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) void __iomem *base; int ret; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + hw_regs_t hw; ret = ecard_request_resources(ec); if (ret) @@ -53,15 +44,21 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) goto release; } - hwif = rapide_locate_hwif(base, base + 0x818, 1 << 6, ec->irq); + hwif = ide_find_port((unsigned long)base); if (hwif) { - hwif->hwif_data = base; - hwif->gendev.parent = &ec->dev; - hwif->noprobe = 0; + memset(&hw, 0, sizeof(hw)); + rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq); + hw.chipset = ide_generic; + hw.dev = &ec->dev; + + ide_init_port_hw(hwif, &hw); + + hwif->mmio = 1; + default_hwif_mmiops(hwif); idx[0] = hwif->index; - ide_device_add(idx); + ide_device_add(idx, NULL); ecard_set_drvdata(ec, hwif); goto out; @@ -79,8 +76,8 @@ static void __devexit rapide_remove(struct expansion_card *ec) ecard_set_drvdata(ec, NULL); - /* there must be a better way */ - ide_unregister(hwif - ide_hwifs); + ide_unregister(hwif->index, 0, 0); + ecard_release_resources(ec); } diff --git a/drivers/ide/cris/Makefile b/drivers/ide/cris/Makefile index 6176e8d6b2e..20b95960531 100644 --- a/drivers/ide/cris/Makefile +++ b/drivers/ide/cris/Makefile @@ -1,3 +1,3 @@ EXTRA_CFLAGS += -Idrivers/ide -obj-y += ide-cris.o +obj-$(CONFIG_IDE_ETRAX) += ide-cris.o diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index e196aefa207..00587a8c2ba 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -1,5 +1,4 @@ -/* $Id: cris-ide-driver.patch,v 1.1 2005/06/29 21:39:07 akpm Exp $ - * +/* * Etrax specific IDE functions, like init and PIO-mode setting etc. * Almost the entire ide.c is used for the rest of the Etrax ATA driver. * Copyright (c) 2000-2005 Axis Communications AB @@ -673,9 +672,8 @@ static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int); static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int); static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int); static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int); -static int cris_dma_on (ide_drive_t *drive); -static void cris_dma_off(ide_drive_t *drive) +static void cris_dma_host_set(ide_drive_t *drive, int on) { } @@ -747,9 +745,6 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed) strobe = ATA_DMA2_STROBE; hold = ATA_DMA2_HOLD; break; - default: - BUG(); - break; } if (speed >= XFER_UDMA_0) @@ -758,13 +753,20 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed) cris_ide_set_speed(TYPE_DMA, 0, strobe, hold); } -void __init -init_e100_ide (void) +static const struct ide_port_info cris_port_info __initdata = { + .chipset = ide_etrax100, + .host_flags = IDE_HFLAG_NO_ATAPI_DMA | + IDE_HFLAG_NO_DMA, /* no SFF-style DMA */ + .pio_mask = ATA_PIO4, + .udma_mask = cris_ultra_mask, + .mwdma_mask = ATA_MWDMA2, +}; + +static int __init init_e100_ide(void) { hw_regs_t hw; - int ide_offsets[IDE_NR_PORTS]; - int h; - int i; + int ide_offsets[IDE_NR_PORTS], h, i; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; printk("ide: ETRAX FS built-in ATA DMA controller\n"); @@ -774,23 +776,26 @@ init_e100_ide (void) /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */ ide_offsets[IDE_CONTROL_OFFSET] = cris_ide_reg_addr(6, 1, 0); - /* first fill in some stuff in the ide_hwifs fields */ + for (h = 0; h < 4; h++) { + ide_hwif_t *hwif = NULL; - for(h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; ide_setup_ports(&hw, cris_ide_base_address(h), ide_offsets, 0, 0, cris_ide_ack_intr, ide_default_irq(0)); - ide_register_hw(&hw, NULL, 1, &hwif); + hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif == NULL) + continue; + ide_init_port_data(hwif, hwif->index); + ide_init_port_hw(hwif, &hw); hwif->mmio = 1; - hwif->chipset = ide_etrax100; hwif->set_pio_mode = &cris_set_pio_mode; hwif->set_dma_mode = &cris_set_dma_mode; hwif->ata_input_data = &cris_ide_input_data; hwif->ata_output_data = &cris_ide_output_data; hwif->atapi_input_bytes = &cris_atapi_input_bytes; hwif->atapi_output_bytes = &cris_atapi_output_bytes; + hwif->dma_host_set = &cris_dma_host_set; hwif->ide_dma_end = &cris_dma_end; hwif->dma_setup = &cris_dma_setup; hwif->dma_exec_cmd = &cris_dma_exec_cmd; @@ -801,16 +806,9 @@ init_e100_ide (void) hwif->OUTBSYNC = &cris_ide_outbsync; hwif->INB = &cris_ide_inb; hwif->INW = &cris_ide_inw; - hwif->dma_host_off = &cris_dma_off; - hwif->dma_host_on = &cris_dma_on; - hwif->dma_off_quietly = &cris_dma_off; hwif->cbl = ATA_CBL_PATA40; - hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; - hwif->pio_mask = ATA_PIO4, - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->ultra_mask = cris_ultra_mask; - hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */ + + idx[h] = hwif->index; } /* Reset pulse */ @@ -823,14 +821,12 @@ init_e100_ide (void) cris_ide_set_speed(TYPE_PIO, ATA_PIO4_SETUP, ATA_PIO4_STROBE, ATA_PIO4_HOLD); cris_ide_set_speed(TYPE_DMA, 0, ATA_DMA2_STROBE, ATA_DMA2_HOLD); cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0); -} -static int cris_dma_on (ide_drive_t *drive) -{ + ide_device_add(idx, &cris_port_info); + return 0; } - static cris_dma_descr_type mydescr __attribute__ ((__aligned__(16))); /* @@ -1038,11 +1034,7 @@ static int cris_dma_setup(ide_drive_t *drive) static void cris_dma_exec_cmd(ide_drive_t *drive, u8 command) { - /* set the irq handler which will finish the request when DMA is done */ - ide_set_handler(drive, &cris_dma_intr, WAIT_CMD, NULL); - - /* issue cmd to drive */ - cris_ide_outb(command, IDE_COMMAND_REG); + ide_execute_command(drive, command, &cris_dma_intr, WAIT_CMD, NULL); } static void cris_dma_start(ide_drive_t *drive) @@ -1062,3 +1054,5 @@ static void cris_dma_start(ide_drive_t *drive) LED_DISK_READ(1); } } + +module_init(init_e100_ide); diff --git a/drivers/ide/h8300/Makefile b/drivers/ide/h8300/Makefile new file mode 100644 index 00000000000..5eba16f423f --- /dev/null +++ b/drivers/ide/h8300/Makefile @@ -0,0 +1,2 @@ + +obj-$(CONFIG_IDE_H8300) += ide-h8300.o diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c index 4a49b5c59ac..520aec07570 100644 --- a/drivers/ide/h8300/ide-h8300.c +++ b/drivers/ide/h8300/ide-h8300.c @@ -1,5 +1,4 @@ /* - * drivers/ide/h8300/ide-h8300.c * H8/300 generic IDE interface */ @@ -84,11 +83,12 @@ static inline void hwif_setup(ide_hwif_t *hwif) hwif->INSL = NULL; } -void __init h8300_ide_init(void) +static int __init h8300_ide_init(void) { hw_regs_t hw; ide_hwif_t *hwif; - int idx; + int index; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300")) goto out_busy; @@ -100,16 +100,28 @@ void __init h8300_ide_init(void) hw_setup(&hw); /* register if */ - idx = ide_register_hw(&hw, NULL, 1, &hwif); - if (idx == -1) { + hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif == NULL) { printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); - return; + return -ENOENT; } + index = hwif->index; + ide_init_port_data(hwif, index); + ide_init_port_hw(hwif, &hw); hwif_setup(hwif); - printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", idx); - return; + printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index); + + idx[0] = index; + + ide_device_add(idx, NULL); + + return 0; out_busy: printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); + + return -EBUSY; } + +module_init(h8300_ide_init); diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 89df48fdc69..25aaeae1e83 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -1,5 +1,4 @@ /* - * ide-acpi.c * Provides ACPI support for IDE drives. * * Copyright (C) 2005 Intel Corp. @@ -16,6 +15,7 @@ #include <acpi/acpi.h> #include <linux/ide.h> #include <linux/pci.h> +#include <linux/dmi.h> #include <acpi/acpi_bus.h> #include <acpi/acnames.h> @@ -39,7 +39,6 @@ struct GTM_buffer { }; struct ide_acpi_drive_link { - ide_drive_t *drive; acpi_handle obj_handle; u8 idbuff[512]; }; @@ -65,6 +64,39 @@ extern int ide_noacpi; extern int ide_noacpitfs; extern int ide_noacpionboot; +static bool ide_noacpi_psx; +static int no_acpi_psx(const struct dmi_system_id *id) +{ + ide_noacpi_psx = true; + printk(KERN_NOTICE"%s detected - disable ACPI _PSx.\n", id->ident); + return 0; +} + +static const struct dmi_system_id ide_acpi_dmi_table[] = { + /* Bug 9673. */ + /* We should check if this is because ACPI NVS isn't save/restored. */ + { + .callback = no_acpi_psx, + .ident = "HP nx9005", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies Ltd."), + DMI_MATCH(DMI_BIOS_VERSION, "KAM1.60") + }, + }, + + { } /* terminate list */ +}; + +static int ide_acpi_blacklist(void) +{ + static int done; + if (done) + return 0; + done = 1; + dmi_check_system(ide_acpi_dmi_table); + return 0; +} + /** * ide_get_dev_handle - finds acpi_handle and PCI device.function * @dev: device to locate @@ -247,16 +279,6 @@ static int do_drive_get_GTF(ide_drive_t *drive, port = hwif->channel ? drive->dn - 2: drive->dn; - if (!drive->acpidata) { - if (port == 0) { - drive->acpidata = &hwif->acpidata->master; - hwif->acpidata->master.drive = drive; - } else { - drive->acpidata = &hwif->acpidata->slave; - hwif->acpidata->slave.drive = drive; - } - } - DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", hwif->name, dev->bus_id, port, hwif->channel); @@ -349,27 +371,19 @@ static int taskfile_load_raw(ide_drive_t *drive, gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); memset(&args, 0, sizeof(ide_task_t)); - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.data_phase = TASKFILE_NO_DATA; - args.handler = &task_no_data_intr; /* convert gtf to IDE Taskfile */ - args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */ - args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */ - args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */ - args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */ - args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */ - args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */ - args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */ + memcpy(&args.tf_array[7], >f->tfa, 7); + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; if (ide_noacpitfs) { DEBPRINT("_GTF execution disabled\n"); return err; } - err = ide_raw_taskfile(drive, &args, NULL); + err = ide_no_data_taskfile(drive, &args); if (err) - printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n", + printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n", __FUNCTION__, err); return err; @@ -469,7 +483,6 @@ int ide_acpi_exec_tfs(ide_drive_t *drive) return ret; } -EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs); /** * ide_acpi_get_timing - get the channel (controller) timings @@ -555,7 +568,6 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) kfree(output.pointer); } -EXPORT_SYMBOL_GPL(ide_acpi_get_timing); /** * ide_acpi_push_timing - set the channel (controller) timings @@ -609,7 +621,6 @@ void ide_acpi_push_timing(ide_hwif_t *hwif) } DEBPRINT("_STM status: %d\n", status); } -EXPORT_SYMBOL_GPL(ide_acpi_push_timing); /** * ide_acpi_set_state - set the channel power state @@ -623,7 +634,7 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) { int unit; - if (ide_noacpi) + if (ide_noacpi || ide_noacpi_psx) return; DEBPRINT("ENTER:\n"); @@ -663,10 +674,7 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) */ void ide_acpi_init(ide_hwif_t *hwif) { - int unit; - int err; - struct ide_acpi_drive_link *master; - struct ide_acpi_drive_link *slave; + ide_acpi_blacklist(); hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); if (!hwif->acpidata) @@ -677,40 +685,38 @@ void ide_acpi_init(ide_hwif_t *hwif) DEBPRINT("no ACPI object for %s found\n", hwif->name); kfree(hwif->acpidata); hwif->acpidata = NULL; - return; } +} + +void ide_acpi_port_init_devices(ide_hwif_t *hwif) +{ + ide_drive_t *drive; + int i, err; + + if (hwif->acpidata == NULL) + return; /* * The ACPI spec mandates that we send information * for both drives, regardless whether they are connected * or not. */ - hwif->acpidata->master.drive = &hwif->drives[0]; hwif->drives[0].acpidata = &hwif->acpidata->master; - master = &hwif->acpidata->master; - - hwif->acpidata->slave.drive = &hwif->drives[1]; hwif->drives[1].acpidata = &hwif->acpidata->slave; - slave = &hwif->acpidata->slave; - /* * Send IDENTIFY for each drive */ - if (master->drive->present) { - err = taskfile_lib_get_identify(master->drive, master->idbuff); - if (err) { - DEBPRINT("identify device %s failed (%d)\n", - master->drive->name, err); - } - } + for (i = 0; i < MAX_DRIVES; i++) { + drive = &hwif->drives[i]; - if (slave->drive->present) { - err = taskfile_lib_get_identify(slave->drive, slave->idbuff); - if (err) { + if (!drive->present) + continue; + + err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff); + if (err) DEBPRINT("identify device %s failed (%d)\n", - slave->drive->name, err); - } + drive->name, err); } if (ide_noacpionboot) { @@ -726,13 +732,11 @@ void ide_acpi_init(ide_hwif_t *hwif) ide_acpi_get_timing(hwif); ide_acpi_push_timing(hwif); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; + for (i = 0; i < MAX_DRIVES; i++) { + drive = &hwif->drives[i]; - if (drive->present) { + if (drive->present) /* Execute ACPI startup code */ ide_acpi_exec_tfs(drive); - } } } -EXPORT_SYMBOL_GPL(ide_acpi_init); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 57a5f63d6ae..ee4d458e2bb 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1,14 +1,14 @@ /* - * linux/drivers/ide/ide-cd.c + * ATAPI CD-ROM driver. * - * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov> - * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> - * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de> + * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov> + * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> + * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de> + * Copyright (C) 2005, 2007 Bartlomiej Zolnierkiewicz * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. * - * ATAPI CD-ROM driver. To be used with ide.c. * See Documentation/cdrom/ide-cd for usage information. * * Suggestions are welcome. Patches that work are more welcome though. ;-) @@ -19,287 +19,11 @@ * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf * - * Drives that deviate from these standards will be accommodated as much - * as possible via compile time or command-line options. Since I only have - * a few drives, you generally need to send me patches... - * - * ---------------------------------- - * TO DO LIST: - * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on - * boot - * - * ---------------------------------- - * 1.00 Oct 31, 1994 -- Initial version. - * 1.01 Nov 2, 1994 -- Fixed problem with starting request in - * cdrom_check_status. - * 1.03 Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks) - * (from mlord) -- minor changes to cdrom_setup() - * -- renamed ide_dev_s to ide_drive_t, enable irq on command - * 2.00 Nov 27, 1994 -- Generalize packet command interface; - * add audio ioctls. - * 2.01 Dec 3, 1994 -- Rework packet command interface to handle devices - * which send an interrupt when ready for a command. - * 2.02 Dec 11, 1994 -- Cache the TOC in the driver. - * Don't use SCMD_PLAYAUDIO_TI; it's not included - * in the current version of ATAPI. - * Try to use LBA instead of track or MSF addressing - * when possible. - * Don't wait for READY_STAT. - * 2.03 Jan 10, 1995 -- Rewrite block read routines to handle block sizes - * other than 2k and to move multiple sectors in a - * single transaction. - * 2.04 Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives. - * Thanks to Nick Saw <cwsaw@pts7.pts.mot.com> for - * help in figuring this out. Ditto for Acer and - * Aztech drives, which seem to have the same problem. - * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml - * 2.05 Jun 8, 1995 -- Don't attempt to retry after an illegal request - * or data protect error. - * Use HWIF and DEV_HWIF macros as in ide.c. - * Always try to do a request_sense after - * a failed command. - * Include an option to give textual descriptions - * of ATAPI errors. - * Fix a bug in handling the sector cache which - * showed up if the drive returned data in 512 byte - * blocks (like Pioneer drives). Thanks to - * Richard Hirst <srh@gpt.co.uk> for diagnosing this. - * Properly supply the page number field in the - * MODE_SELECT command. - * PLAYAUDIO12 is broken on the Aztech; work around it. - * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c - * (my apologies to Scott, but now ide-cd.c is independent) - * 3.00 Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl. - * Implement CDROMREADAUDIO ioctl (UNTESTED). - * Use input_ide_data() and output_ide_data(). - * Add door locking. - * Fix usage count leak in cdrom_open, which happened - * when a read-write mount was attempted. - * Try to load the disk on open. - * Implement CDROMEJECT_SW ioctl (off by default). - * Read total cdrom capacity during open. - * Rearrange logic in cdrom_decode_status. Issue - * request sense commands for failed packet commands - * from here instead of from cdrom_queue_packet_command. - * Fix a race condition in retrieving error information. - * Suppress printing normal unit attention errors and - * some drive not ready errors. - * Implement CDROMVOLREAD ioctl. - * Implement CDROMREADMODE1/2 ioctls. - * Fix race condition in setting up interrupt handlers - * when the `serialize' option is used. - * 3.01 Sep 2, 1995 -- Fix ordering of reenabling interrupts in - * cdrom_queue_request. - * Another try at using ide_[input,output]_data. - * 3.02 Sep 16, 1995 -- Stick total disk capacity in partition table as well. - * Make VERBOSE_IDE_CD_ERRORS dump failed command again. - * Dump out more information for ILLEGAL REQUEST errs. - * Fix handling of errors occurring before the - * packet command is transferred. - * Fix transfers with odd bytelengths. - * 3.03 Oct 27, 1995 -- Some Creative drives have an id of just `CD'. - * `DCI-2S10' drives are broken too. - * 3.04 Nov 20, 1995 -- So are Vertos drives. - * 3.05 Dec 1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c - * 3.06 Dec 16, 1995 -- Add support needed for partitions. - * More workarounds for Vertos bugs (based on patches - * from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>). - * Try to eliminate byteorder assumptions. - * Use atapi_cdrom_subchnl struct definition. - * Add STANDARD_ATAPI compilation option. - * 3.07 Jan 29, 1996 -- More twiddling for broken drives: Sony 55D, - * Vertos 300. - * Add NO_DOOR_LOCKING configuration option. - * Handle drive_cmd requests w/NULL args (for hdparm -t). - * Work around sporadic Sony55e audio play problem. - * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix - * problem with "hde=cdrom" with no drive present. -ml - * 3.08 Mar 6, 1996 -- More Vertos workarounds. - * 3.09 Apr 5, 1996 -- Add CDROMCLOSETRAY ioctl. - * Switch to using MSF addressing for audio commands. - * Reformat to match kernel tabbing style. - * Add CDROM_GET_UPC ioctl. - * 3.10 Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI. - * 3.11 Apr 29, 1996 -- Patch from Heiko Eißfeldt <heiko@colossus.escape.de> - * to remove redundant verify_area calls. - * 3.12 May 7, 1996 -- Rudimentary changer support. Based on patches - * from Gerhard Zuber <zuber@berlin.snafu.de>. - * Let open succeed even if there's no loaded disc. - * 3.13 May 19, 1996 -- Fixes for changer code. - * 3.14 May 29, 1996 -- Add work-around for Vertos 600. - * (From Hennus Bergman <hennus@sky.ow.nl>.) - * 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers - * from Ben Galliart <bgallia@luc.edu> with - * special help from Jeff Lightfoot - * <jeffml@pobox.com> - * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification - * 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl. - * 3.17 Sep 17, 1996 -- Tweak audio reads for some drives. - * Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC. - * 3.18 Oct 31, 1996 -- Added module and DMA support. - * - * - * 4.00 Nov 5, 1996 -- New ide-cd maintainer, - * Erik B. Andersen <andersee@debian.org> - * -- Newer Creative drives don't always set the error - * register correctly. Make sure we see media changes - * regardless. - * -- Integrate with generic cdrom driver. - * -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on - * a patch from Ciro Cattuto <>. - * -- Call set_device_ro. - * -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE - * ioctls, based on patch by Erik Andersen - * -- Add some probes of drive capability during setup. - * - * 4.01 Nov 11, 1996 -- Split into ide-cd.c and ide-cd.h - * -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE - * ioctls in favor of a generalized approach - * using the generic cdrom driver. - * -- Fully integrated with the 2.1.X kernel. - * -- Other stuff that I forgot (lots of changes) - * - * 4.02 Dec 01, 1996 -- Applied patch from Gadi Oxman <gadio@netvision.net.il> - * to fix the drive door locking problems. - * - * 4.03 Dec 04, 1996 -- Added DSC overlap support. - * 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch - * by Ales Makarov (xmakarov@sun.felk.cvut.cz) - * - * 4.05 Nov 20, 1997 -- Modified to print more drive info on init - * Minor other changes - * Fix errors on CDROMSTOP (If you have a "Dolphin", - * you must define IHAVEADOLPHIN) - * Added identifier so new Sanyo CD-changer works - * Better detection if door locking isn't supported - * - * 4.06 Dec 17, 1997 -- fixed endless "tray open" messages -ml - * 4.07 Dec 17, 1997 -- fallback to set pc->stat on "tray open" - * 4.08 Dec 18, 1997 -- spew less noise when tray is empty - * -- fix speed display for ACER 24X, 18X - * 4.09 Jan 04, 1998 -- fix handling of the last block so we return - * an end of file instead of an I/O error (Gadi) - * 4.10 Jan 24, 1998 -- fixed a bug so now changers can change to a new - * slot when there is no disc in the current slot. - * -- Fixed a memory leak where info->changer_info was - * malloc'ed but never free'd when closing the device. - * -- Cleaned up the global namespace a bit by making more - * functions static that should already have been. - * 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl - * based on a patch for 2.0.33 by Jelle Foks - * <jelle@scintilla.utwente.nl>, a patch for 2.0.33 - * by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI - * version, and my own efforts. -erik - * -- Fixed a stupid bug which egcs was kind enough to - * inform me of where "Illegal mode for this track" - * was never returned due to a comparison on data - * types of limited range. - * 4.12 Mar 29, 1998 -- Fixed bug in CDROM_SELECT_SPEED so write speed is - * now set ionly for CD-R and CD-RW drives. I had - * removed this support because it produced errors. - * It produced errors _only_ for non-writers. duh. - * 4.13 May 05, 1998 -- Suppress useless "in progress of becoming ready" - * messages, since this is not an error. - * -- Change error messages to be const - * -- Remove a "\t" which looks ugly in the syslogs - * 4.14 July 17, 1998 -- Change to pointing to .ps version of ATAPI spec - * since the .pdf version doesn't seem to work... - * -- Updated the TODO list to something more current. - * - * 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess, - * patch thanks to "Eddie C. Dost" <ecd@skynet.be> - * - * 4.50 Oct 19, 1998 -- New maintainers! - * Jens Axboe <axboe@image.dk> - * Chris Zwilling <chris@cloudnet.com> - * - * 4.51 Dec 23, 1998 -- Jens Axboe <axboe@image.dk> - * - ide_cdrom_reset enabled since the ide subsystem - * handles resets fine now. <axboe@image.dk> - * - Transfer size fix for Samsung CD-ROMs, thanks to - * "Ville Hallik" <ville.hallik@mail.ee>. - * - other minor stuff. - * - * 4.52 Jan 19, 1999 -- Jens Axboe <axboe@image.dk> - * - Detect DVD-ROM/RAM drives - * - * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar - * drive in transfer size limit. - * - Fix the I/O error when doing eject without a medium - * loaded on some drives. - * - CDROMREADMODE2 is now implemented through - * CDROMREADRAW, since many drives don't support - * MODE2 (even though ATAPI 2.6 says they must). - * - Added ignore parameter to ide-cd (as a module), eg - * insmod ide-cd ignore='hda hdb' - * Useful when using ide-cd in conjunction with - * ide-scsi. TODO: non-modular way of doing the - * same. - * - * 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic - * packet interface to cdrom.c. - * - Unified audio ioctl support, most of it. - * - cleaned up various deprecated verify_area(). - * - Added ide_cdrom_packet() as the interface for - * the Uniform generic_packet(). - * - bunch of other stuff, will fill in logs later. - * - report 1 slot for non-changers, like the other - * cd-rom drivers. don't report select disc for - * non-changers as well. - * - mask out audio playing, if the device can't do it. - * - * 4.55 Sep 1, 1999 - Eliminated the rest of the audio ioctls, except - * for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers - * use this independently of the actual audio handling. - * They will disappear later when I get the time to - * do it cleanly. - * - Minimize the TOC reading - only do it when we - * know a media change has occurred. - * - Moved all the CDROMREADx ioctls to the Uniform layer. - * - Heiko Eißfeldt <heiko@colossus.escape.de> supplied - * some fixes for CDI. - * - CD-ROM leaving door locked fix from Andries - * Brouwer <Andries.Brouwer@cwi.nl> - * - Erik Andersen <andersen@xmission.com> unified - * commands across the various drivers and how - * sense errors are handled. - * - * 4.56 Sep 12, 1999 - Removed changer support - it is now in the - * Uniform layer. - * - Added partition based multisession handling. - * - Mode sense and mode select moved to the - * Uniform layer. - * - Fixed a problem with WPI CDS-32X drive - it - * failed the capabilities - * - * 4.57 Apr 7, 2000 - Fixed sense reporting. - * - Fixed possible oops in ide_cdrom_get_last_session() - * - Fix locking mania and make ide_cdrom_reset relock - * - Stop spewing errors to log when magicdev polls with - * TEST_UNIT_READY on some drives. - * - Various fixes from Tobias Ringstrom: - * tray if it was locked prior to the reset. - * - cdrom_read_capacity returns one frame too little. - * - Fix real capacity reporting. - * - * 4.58 May 1, 2000 - Clean up ACER50 stuff. - * - Fix small problem with ide_cdrom_capacity - * - * 4.59 Aug 11, 2000 - Fix changer problem in cdrom_read_toc, we weren't - * correctly sensing a disc change. - * - Rearranged some code - * - Use extended sense on drives that support it for - * correctly reporting tray status -- from - * Michael D Johnson <johnsom@orst.edu> - * 4.60 Dec 17, 2003 - Add mt rainier support - * - Bump timeout for packet commands, matches sr - * - Odd stuff - * 4.61 Jan 22, 2004 - support hardware sector sizes other than 2kB, - * Pascal Schmidt <der.eremit@email.de> - * - *************************************************************************/ - -#define IDECD_VERSION "4.61" + * For historical changelog please see: + * Documentation/ide/ChangeLog.ide-cd.1994-2004 + */ + +#define IDECD_VERSION "5.00" #include <linux/module.h> #include <linux/types.h> @@ -313,6 +37,7 @@ #include <linux/ide.h> #include <linux/completion.h> #include <linux/mutex.h> +#include <linux/bcd.h> #include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */ @@ -360,11 +85,11 @@ static void ide_cd_put(struct cdrom_info *cd) buffers. */ static void cdrom_saw_media_change (ide_drive_t *drive) { - struct cdrom_info *info = drive->driver_data; - - CDROM_STATE_FLAGS (drive)->media_changed = 1; - CDROM_STATE_FLAGS (drive)->toc_valid = 0; - info->nsectors_buffered = 0; + struct cdrom_info *cd = drive->driver_data; + + cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED; + cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID; + cd->nsectors_buffered = 0; } static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, @@ -465,134 +190,14 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, } } } -#if VERBOSE_IDE_CD_ERRORS - { - int i; - const char *s = "bad sense key!"; - char buf[80]; - - printk ("ATAPI device %s:\n", drive->name); - if (sense->error_code==0x70) - printk(" Error: "); - else if (sense->error_code==0x71) - printk(" Deferred Error: "); - else if (sense->error_code == 0x7f) - printk(" Vendor-specific Error: "); - else - printk(" Unknown Error Type: "); - - if (sense->sense_key < ARRAY_SIZE(sense_key_texts)) - s = sense_key_texts[sense->sense_key]; - - printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key); - - if (sense->asc == 0x40) { - sprintf(buf, "Diagnostic failure on component 0x%02x", - sense->ascq); - s = buf; - } else { - int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts); - unsigned long key = (sense->sense_key << 16); - key |= (sense->asc << 8); - if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd)) - key |= sense->ascq; - s = NULL; - - while (hi > lo) { - mid = (lo + hi) / 2; - if (sense_data_texts[mid].asc_ascq == key || - sense_data_texts[mid].asc_ascq == (0xff0000|key)) { - s = sense_data_texts[mid].text; - break; - } - else if (sense_data_texts[mid].asc_ascq > key) - hi = mid; - else - lo = mid+1; - } - } - - if (s == NULL) { - if (sense->asc > 0x80) - s = "(vendor-specific error)"; - else - s = "(reserved error code)"; - } - - printk(KERN_ERR " %s -- (asc=0x%02x, ascq=0x%02x)\n", - s, sense->asc, sense->ascq); - - if (failed_command != NULL) { - - int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts); - s = NULL; - - while (hi > lo) { - mid = (lo + hi) / 2; - if (packet_command_texts[mid].packet_command == - failed_command->cmd[0]) { - s = packet_command_texts[mid].text; - break; - } - if (packet_command_texts[mid].packet_command > - failed_command->cmd[0]) - hi = mid; - else - lo = mid+1; - } - - printk (KERN_ERR " The failed \"%s\" packet command was: \n \"", s); - for (i=0; i<sizeof (failed_command->cmd); i++) - printk ("%02x ", failed_command->cmd[i]); - printk ("\"\n"); - } - - /* The SKSV bit specifies validity of the sense_key_specific - * in the next two commands. It is bit 7 of the first byte. - * In the case of NOT_READY, if SKSV is set the drive can - * give us nice ETA readings. - */ - if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) { - int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100; - printk(KERN_ERR " Command is %02d%% complete\n", progress / 0xffff); - - } - - if (sense->sense_key == ILLEGAL_REQUEST && - (sense->sks[0] & 0x80) != 0) { - printk(KERN_ERR " Error in %s byte %d", - (sense->sks[0] & 0x40) != 0 ? - "command packet" : "command data", - (sense->sks[1] << 8) + sense->sks[2]); - if ((sense->sks[0] & 0x40) != 0) - printk (" bit %d", sense->sks[0] & 0x07); - - printk ("\n"); - } - } - -#else /* not VERBOSE_IDE_CD_ERRORS */ - - /* Suppress printing unit attention and `in progress of becoming ready' - errors when we're not being verbose. */ - - if (sense->sense_key == UNIT_ATTENTION || - (sense->sense_key == NOT_READY && (sense->asc == 4 || - sense->asc == 0x3a))) - return; - - printk(KERN_ERR "%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n", - drive->name, - sense->error_code, sense->sense_key, - sense->asc, sense->ascq); -#endif /* not VERBOSE_IDE_CD_ERRORS */ + ide_cd_log_error(drive->name, failed_command, sense); } /* * Initialize a ide-cd packet command request */ -static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq) +void ide_cd_init_rq(ide_drive_t *drive, struct request *rq) { struct cdrom_info *cd = drive->driver_data; @@ -611,7 +216,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, sense = &info->sense_data; /* stuff the sense request in front of our current request */ - cdrom_prepare_request(drive, rq); + ide_cd_init_rq(drive, rq); rq->data = sense; rq->cmd[0] = GPCMD_REQUEST_SENSE; @@ -655,9 +260,9 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) BUG(); } else { spin_lock_irqsave(&ide_lock, flags); - end_that_request_chunk(failed, 0, - failed->data_len); - end_that_request_last(failed, 0); + if (__blk_end_request(failed, -EIO, + failed->data_len)) + BUG(); spin_unlock_irqrestore(&ide_lock, flags); } } else @@ -718,7 +323,6 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) { /* All other functions, except for READ. */ - unsigned long flags; /* * if we have an error, pass back CHECK_CONDITION as the @@ -756,15 +360,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) * remove failed request completely and end it when the * request sense has completed */ - if (stat & ERR_STAT) { - spin_lock_irqsave(&ide_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - spin_unlock_irqrestore(&ide_lock, flags); - - cdrom_queue_request_sense(drive, rq->sense, rq); - } else - cdrom_end_request(drive, 0); + goto end_request; } else if (blk_fs_request(rq)) { int do_end_request = 0; @@ -844,23 +440,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) sense data. We need this in order to perform end of media processing */ - if (do_end_request) { - if (stat & ERR_STAT) { - unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - spin_unlock_irqrestore(&ide_lock, flags); + if (do_end_request) + goto end_request; - cdrom_queue_request_sense(drive, rq->sense, rq); - } else - cdrom_end_request(drive, 0); - } else { - /* If we got a CHECK_CONDITION status, - queue a request sense command. */ - if (stat & ERR_STAT) - cdrom_queue_request_sense(drive, NULL, NULL); - } + /* + * If we got a CHECK_CONDITION status, + * queue a request sense command. + */ + if (stat & ERR_STAT) + cdrom_queue_request_sense(drive, NULL, NULL); } else { blk_dump_rq_flags(rq, "ide-cd: bad rq"); cdrom_end_request(drive, 0); @@ -868,6 +456,21 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) /* Retry, or handle the next request. */ return 1; + +end_request: + if (stat & ERR_STAT) { + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + spin_unlock_irqrestore(&ide_lock, flags); + + cdrom_queue_request_sense(drive, rq->sense, rq); + } else + cdrom_end_request(drive, 0); + + return 1; } static int cdrom_timer_expiry(ide_drive_t *drive) @@ -917,21 +520,15 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) return startstop; + /* FIXME: for Virtual DMA we must check harder */ if (info->dma) info->dma = !hwif->dma_setup(drive); /* Set up the controller registers. */ - /* FIXME: for Virtual DMA we must check harder */ - HWIF(drive)->OUTB(info->dma, IDE_FEATURE_REG); - HWIF(drive)->OUTB(0, IDE_IREASON_REG); - HWIF(drive)->OUTB(0, IDE_SECTOR_REG); - - HWIF(drive)->OUTB(xferlen & 0xff, IDE_BCOUNTL_REG); - HWIF(drive)->OUTB(xferlen >> 8 , IDE_BCOUNTH_REG); - if (IDE_CONTROL_REG) - HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); - - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { + ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL | + IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma); + + if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) { /* waiting for CDB interrupt, not DMA yet. */ if (info->dma) drive->waiting_for_dma = 0; @@ -957,10 +554,6 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, by cdrom_start_packet_command. HANDLER is the interrupt handler to call when the command completes or there's data ready. */ -/* - * changed 5 parameters to 3 for dvd-ram - * struct packet_command *pc; now packet_command_t *pc; - */ #define ATAPI_MIN_CDB_BYTES 12 static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, struct request *rq, @@ -971,7 +564,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, struct cdrom_info *info = drive->driver_data; ide_startstop_t startstop; - if (CDROM_CONFIG_FLAGS(drive)->drq_interrupt) { + if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) { /* Here we should have been called after receiving an interrupt from the device. DRQ should how be set. */ @@ -1011,6 +604,25 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, * Block read functions. */ +static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len) +{ + while (len > 0) { + int dum = 0; + xf(drive, &dum, sizeof(dum)); + len -= sizeof(dum); + } +} + +static void ide_cd_drain_data(ide_drive_t *drive, int nsects) +{ + while (nsects > 0) { + static char dum[SECTOR_SIZE]; + + drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum)); + nsects--; + } +} + /* * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector * buffer. Once the first sector is added, any subsequent sectors are @@ -1049,11 +661,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, } /* Throw away any remaining data. */ - while (sectors_to_transfer > 0) { - static char dum[SECTOR_SIZE]; - HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum)); - --sectors_to_transfer; - } + ide_cd_drain_data(drive, sectors_to_transfer); } /* @@ -1062,23 +670,25 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, * ok; nonzero if the request has been terminated. */ static -int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) +int ide_cd_check_ireason(ide_drive_t *drive, int len, int ireason, int rw) { - if (ireason == 2) + /* + * ireason == 0: the drive wants to receive data from us + * ireason == 2: the drive is expecting to transfer data to us + */ + if (ireason == (!rw << 1)) return 0; - else if (ireason == 0) { - /* Whoops... The drive is expecting to receive data from us! */ - printk(KERN_ERR "%s: read_intr: Drive wants to transfer data the " - "wrong way!\n", drive->name); - - /* Throw some data at the drive so it doesn't hang - and quit this request. */ - while (len > 0) { - int dum = 0; - HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof (dum)); - len -= sizeof (dum); - } - } else if (ireason == 1) { + else if (ireason == (rw << 1)) { + ide_hwif_t *hwif = drive->hwif; + xfer_func_t *xf; + + /* Whoops... */ + printk(KERN_ERR "%s: %s: wrong transfer direction!\n", + drive->name, __FUNCTION__); + + xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes; + ide_cd_pad_transfer(drive, xf, len); + } else if (rw == 0 && ireason == 1) { /* Some drives (ASUS) seem to tell us that status * info is available. just get it and ignore. */ @@ -1086,8 +696,8 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) return 0; } else { /* Drive wants a command packet, or invalid ireason... */ - printk(KERN_ERR "%s: read_intr: bad interrupt reason %x\n", drive->name, - ireason); + printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n", + drive->name, __FUNCTION__, ireason); } cdrom_end_request(drive, 0); @@ -1095,134 +705,28 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) } /* - * Interrupt routine. Called when a read request has completed. + * Assume that the drive will always provide data in multiples of at least + * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise. */ -static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) +static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) { - int stat; - int ireason, len, sectors_to_transfer, nskip; - struct cdrom_info *info = drive->driver_data; - u8 lowcyl = 0, highcyl = 0; - int dma = info->dma, dma_error = 0; - - struct request *rq = HWGROUP(drive)->rq; - - /* - * handle dma case - */ - if (dma) { - info->dma = 0; - if ((dma_error = HWIF(drive)->ide_dma_end(drive))) - ide_dma_off(drive); - } - - if (cdrom_decode_status(drive, 0, &stat)) - return ide_stopped; - - if (dma) { - if (!dma_error) { - ide_end_request(drive, 1, rq->nr_sectors); - return ide_stopped; - } else - return ide_error(drive, "dma error", stat); - } - - /* Read the interrupt reason and the transfer length. */ - ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3; - lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); - highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); - - len = lowcyl + (256 * highcyl); - - /* If DRQ is clear, the command has completed. */ - if ((stat & DRQ_STAT) == 0) { - /* If we're not done filling the current buffer, complain. - Otherwise, complete the command normally. */ - if (rq->current_nr_sectors > 0) { - printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n", - drive->name, rq->current_nr_sectors); - rq->cmd_flags |= REQ_FAILED; - cdrom_end_request(drive, 0); - } else - cdrom_end_request(drive, 1); - return ide_stopped; - } - - /* Check that the drive is expecting to do the same thing we are. */ - if (cdrom_read_check_ireason (drive, len, ireason)) - return ide_stopped; - - /* Assume that the drive will always provide data in multiples - of at least SECTOR_SIZE, as it gets hairy to keep track - of the transfers otherwise. */ - if ((len % SECTOR_SIZE) != 0) { - printk (KERN_ERR "%s: cdrom_read_intr: Bad transfer size %d\n", - drive->name, len); - if (CDROM_CONFIG_FLAGS(drive)->limit_nframes) - printk (KERN_ERR " This drive is not supported by this version of the driver\n"); - else { - printk (KERN_ERR " Trying to limit transfer sizes\n"); - CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; - } - cdrom_end_request(drive, 0); - return ide_stopped; - } - - /* The number of sectors we need to read from the drive. */ - sectors_to_transfer = len / SECTOR_SIZE; - - /* First, figure out if we need to bit-bucket - any of the leading sectors. */ - nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer); - - while (nskip > 0) { - /* We need to throw away a sector. */ - static char dum[SECTOR_SIZE]; - HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum)); + struct cdrom_info *cd = drive->driver_data; - --rq->current_nr_sectors; - --nskip; - --sectors_to_transfer; - } + if ((len % SECTOR_SIZE) == 0) + return 0; - /* Now loop while we still have data to read from the drive. */ - while (sectors_to_transfer > 0) { - int this_transfer; + printk(KERN_ERR "%s: %s: Bad transfer size %d\n", + drive->name, __FUNCTION__, len); - /* If we've filled the present buffer but there's another - chained buffer after it, move on. */ - if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request(drive, 1); - - /* If the buffers are full, cache the rest of the data in our - internal buffer. */ - if (rq->current_nr_sectors == 0) { - cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer); - sectors_to_transfer = 0; - } else { - /* Transfer data to the buffers. - Figure out how many sectors we can transfer - to the current buffer. */ - this_transfer = min_t(int, sectors_to_transfer, - rq->current_nr_sectors); - - /* Read this_transfer sectors - into the current buffer. */ - while (this_transfer > 0) { - HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->nr_sectors; - --rq->current_nr_sectors; - ++rq->sector; - --this_transfer; - --sectors_to_transfer; - } - } + if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES) + printk(KERN_ERR " This drive is not supported by " + "this version of the driver\n"); + else { + printk(KERN_ERR " Trying to limit transfer sizes\n"); + cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES; } - /* Done moving data! Wait for another interrupt. */ - ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL); - return ide_started; + return 1; } /* @@ -1284,48 +788,58 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) return 0; } +static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); + /* - * Routine to send a read packet command to the drive. - * This is usually called directly from cdrom_start_read. + * Routine to send a read/write packet command to the drive. + * This is usually called directly from cdrom_start_{read,write}(). * However, for drq_interrupt devices, it is called from an interrupt * when the drive is ready to accept the command. */ -static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) +static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - unsigned short sectors_per_frame; - int nskip; - sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; + if (rq_data_dir(rq) == READ) { + unsigned short sectors_per_frame = + queue_hardsect_size(drive->queue) >> SECTOR_BITS; + int nskip = rq->sector & (sectors_per_frame - 1); - /* If the requested sector doesn't start on a cdrom block boundary, - we must adjust the start of the transfer so that it does, - and remember to skip the first few sectors. - If the CURRENT_NR_SECTORS field is larger than the size - of the buffer, it will mean that we're to skip a number - of sectors equal to the amount by which CURRENT_NR_SECTORS - is larger than the buffer size. */ - nskip = rq->sector & (sectors_per_frame - 1); - if (nskip > 0) { - /* Sanity check... */ - if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) && - (rq->sector & (sectors_per_frame - 1))) { - printk(KERN_ERR "%s: cdrom_start_read_continuation: buffer botch (%u)\n", - drive->name, rq->current_nr_sectors); - cdrom_end_request(drive, 0); - return ide_stopped; + /* + * If the requested sector doesn't start on a frame boundary, + * we must adjust the start of the transfer so that it does, + * and remember to skip the first few sectors. + * + * If the rq->current_nr_sectors field is larger than the size + * of the buffer, it will mean that we're to skip a number of + * sectors equal to the amount by which rq->current_nr_sectors + * is larger than the buffer size. + */ + if (nskip > 0) { + /* Sanity check... */ + if (rq->current_nr_sectors != + bio_cur_sectors(rq->bio)) { + printk(KERN_ERR "%s: %s: buffer botch (%u)\n", + drive->name, __FUNCTION__, + rq->current_nr_sectors); + cdrom_end_request(drive, 0); + return ide_stopped; + } + rq->current_nr_sectors += nskip; } - rq->current_nr_sectors += nskip; } - +#if 0 + else + /* the immediate bit */ + rq->cmd[1] = 1 << 3; +#endif /* Set up the command */ rq->timeout = ATAPI_WAIT_PC; /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr); + return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); } - #define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */ #define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */ #define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */ @@ -1338,7 +852,8 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive) if (cdrom_decode_status(drive, 0, &stat)) return ide_stopped; - CDROM_CONFIG_FLAGS(drive)->seeking = 1; + + info->cd_flags |= IDE_CD_FLAG_SEEKING; if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) { if (--retry == 0) { @@ -1394,184 +909,25 @@ static void restore_request (struct request *rq) rq->q->prep_rq_fn(rq->q, rq); } -/* - * Start a read request from the CD-ROM. - */ -static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) -{ - struct cdrom_info *info = drive->driver_data; - struct request *rq = HWGROUP(drive)->rq; - unsigned short sectors_per_frame; - - sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; - - /* We may be retrying this request after an error. Fix up - any weirdness which might be present in the request packet. */ - restore_request(rq); - - /* Satisfy whatever we can of this request from our cached sector. */ - if (cdrom_read_from_buffer(drive)) - return ide_stopped; - - /* Clear the local sector buffer. */ - info->nsectors_buffered = 0; - - /* use dma, if possible. */ - info->dma = drive->using_dma; - if ((rq->sector & (sectors_per_frame - 1)) || - (rq->nr_sectors & (sectors_per_frame - 1))) - info->dma = 0; - - /* Start sending the read request to the drive. */ - return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation); -} - /**************************************************************************** * Execute all other packet commands. */ -/* Interrupt routine for packet command completion. */ -static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) +static void ide_cd_request_sense_fixup(struct request *rq) { - int ireason, len, thislen; - struct request *rq = HWGROUP(drive)->rq; - u8 lowcyl = 0, highcyl = 0; - int stat; - - /* Check for errors. */ - if (cdrom_decode_status(drive, 0, &stat)) - return ide_stopped; - - /* Read the interrupt reason and the transfer length. */ - ireason = HWIF(drive)->INB(IDE_IREASON_REG); - lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); - highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); - - len = lowcyl + (256 * highcyl); - - /* If DRQ is clear, the command has completed. - Complain if we still have data left to transfer. */ - if ((stat & DRQ_STAT) == 0) { - /* Some of the trailing request sense fields are optional, and - some drives don't send them. Sigh. */ - if (rq->cmd[0] == GPCMD_REQUEST_SENSE && - rq->data_len > 0 && - rq->data_len <= 5) { - while (rq->data_len > 0) { - *(unsigned char *)rq->data++ = 0; - --rq->data_len; - } - } - - if (rq->data_len == 0) - cdrom_end_request(drive, 1); - else { - /* Comment this out, because this always happens - right after a reset occurs, and it is annoying to - always print expected stuff. */ - /* - printk ("%s: cdrom_pc_intr: data underrun %d\n", - drive->name, pc->buflen); - */ - rq->cmd_flags |= REQ_FAILED; - cdrom_end_request(drive, 0); - } - return ide_stopped; - } - - /* Figure out how much data to transfer. */ - thislen = rq->data_len; - if (thislen > len) thislen = len; - - /* The drive wants to be written to. */ - if ((ireason & 3) == 0) { - if (!rq->data) { - blk_dump_rq_flags(rq, "cdrom_pc_intr, write"); - goto confused; - } - /* Transfer the data. */ - HWIF(drive)->atapi_output_bytes(drive, rq->data, thislen); - - /* If we haven't moved enough data to satisfy the drive, - add some padding. */ - while (len > thislen) { - int dum = 0; - HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum)); - len -= sizeof(dum); - } - - /* Keep count of how much data we've moved. */ - rq->data += thislen; - rq->data_len -= thislen; - } - - /* Same drill for reading. */ - else if ((ireason & 3) == 2) { - if (!rq->data) { - blk_dump_rq_flags(rq, "cdrom_pc_intr, write"); - goto confused; - } - /* Transfer the data. */ - HWIF(drive)->atapi_input_bytes(drive, rq->data, thislen); - - /* If we haven't moved enough data to satisfy the drive, - add some padding. */ - while (len > thislen) { - int dum = 0; - HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum)); - len -= sizeof(dum); + /* + * Some of the trailing request sense fields are optional, + * and some drives don't send them. Sigh. + */ + if (rq->cmd[0] == GPCMD_REQUEST_SENSE && + rq->data_len > 0 && rq->data_len <= 5) + while (rq->data_len > 0) { + *(u8 *)rq->data++ = 0; + --rq->data_len; } - - /* Keep count of how much data we've moved. */ - rq->data += thislen; - rq->data_len -= thislen; - - if (blk_sense_request(rq)) - rq->sense_len += thislen; - } else { -confused: - printk (KERN_ERR "%s: cdrom_pc_intr: The drive " - "appears confused (ireason = 0x%02x). " - "Trying to recover by ending request.\n", - drive->name, ireason); - rq->cmd_flags |= REQ_FAILED; - cdrom_end_request(drive, 0); - return ide_stopped; - } - - /* Now we wait for another interrupt. */ - ide_set_handler(drive, &cdrom_pc_intr, ATAPI_WAIT_PC, cdrom_timer_expiry); - return ide_started; -} - -static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - - if (!rq->timeout) - rq->timeout = ATAPI_WAIT_PC; - - /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, rq, &cdrom_pc_intr); -} - - -static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) -{ - int len; - struct request *rq = HWGROUP(drive)->rq; - struct cdrom_info *info = drive->driver_data; - - info->dma = 0; - rq->cmd_flags &= ~REQ_FAILED; - len = rq->data_len; - - /* Start sending the command to the drive. */ - return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation); } - -static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) +int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq) { struct request_sense sense; int retries = 10; @@ -1620,84 +976,37 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) } /* - * Write handling + * Called from blk_end_request_callback() after the data of the request + * is completed and before the request is completed. + * By returning value '1', blk_end_request_callback() returns immediately + * without completing the request. */ -static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) +static int cdrom_newpc_intr_dummy_cb(struct request *rq) { - /* Two notes about IDE interrupt reason here - 0 means that - * the drive wants to receive data from us, 2 means that - * the drive is expecting to transfer data to us. - */ - if (ireason == 0) - return 0; - else if (ireason == 2) { - /* Whoops... The drive wants to send data. */ - printk(KERN_ERR "%s: write_intr: wrong transfer direction!\n", - drive->name); - - while (len > 0) { - int dum = 0; - HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum)); - len -= sizeof(dum); - } - } else { - /* Drive wants a command packet, or invalid ireason... */ - printk(KERN_ERR "%s: write_intr: bad interrupt reason %x\n", - drive->name, ireason); - } - - cdrom_end_request(drive, 0); return 1; } -static void post_transform_command(struct request *req) -{ - u8 *c = req->cmd; - char *ibuf; - - if (!blk_pc_request(req)) - return; - - if (req->bio) - ibuf = bio_data(req->bio); - else - ibuf = req->data; - - if (!ibuf) - return; - - /* - * set ansi-revision and response data as atapi - */ - if (c[0] == GPCMD_INQUIRY) { - ibuf[2] |= 2; - ibuf[3] = (ibuf[3] & 0xf0) | 2; - } -} - -typedef void (xfer_func_t)(ide_drive_t *, void *, u32); - -/* - * best way to deal with dma that is not sector aligned right now... note - * that in this path we are not using ->data or ->buffer at all. this irs - * can replace cdrom_pc_intr, cdrom_read_intr, and cdrom_write_intr in the - * future. - */ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; - int dma_error, dma, stat, ireason, len, thislen; - u8 lowcyl, highcyl; xfer_func_t *xferfunc; - unsigned long flags; + ide_expiry_t *expiry = NULL; + int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0; + int write = (rq_data_dir(rq) == WRITE) ? 1 : 0; + unsigned int timeout; + u8 lowcyl, highcyl; /* Check for errors. */ - dma_error = 0; dma = info->dma; if (dma) { info->dma = 0; dma_error = HWIF(drive)->ide_dma_end(drive); + if (dma_error) { + printk(KERN_ERR "%s: DMA %s error\n", drive->name, + write ? "write" : "read"); + ide_dma_off(drive); + } } if (cdrom_decode_status(drive, 0, &stat)) @@ -1707,14 +1016,12 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) * using dma, transfer is complete now */ if (dma) { - if (dma_error) { - printk(KERN_ERR "ide-cd: dma error\n"); - ide_dma_off(drive); + if (dma_error) return ide_error(drive, "dma error", stat); + if (blk_fs_request(rq)) { + ide_end_request(drive, 1, rq->nr_sectors); + return ide_stopped; } - - end_that_request_chunk(rq, 1, rq->data_len); - rq->data_len = 0; goto end_request; } @@ -1726,54 +1033,120 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); len = lowcyl + (256 * highcyl); - thislen = rq->data_len; + + thislen = blk_fs_request(rq) ? len : rq->data_len; if (thislen > len) thislen = len; /* * If DRQ is clear, the command has completed. */ - if ((stat & DRQ_STAT) == 0) + if ((stat & DRQ_STAT) == 0) { + if (blk_fs_request(rq)) { + /* + * If we're not done reading/writing, complain. + * Otherwise, complete the command normally. + */ + uptodate = 1; + if (rq->current_nr_sectors > 0) { + printk(KERN_ERR "%s: %s: data underrun " + "(%d blocks)\n", + drive->name, __FUNCTION__, + rq->current_nr_sectors); + if (!write) + rq->cmd_flags |= REQ_FAILED; + uptodate = 0; + } + cdrom_end_request(drive, uptodate); + return ide_stopped; + } else if (!blk_pc_request(rq)) { + ide_cd_request_sense_fixup(rq); + /* Complain if we still have data left to transfer. */ + uptodate = rq->data_len ? 0 : 1; + } goto end_request; + } /* * check which way to transfer data */ - if (rq_data_dir(rq) == WRITE) { - /* - * write to drive - */ - if (cdrom_write_check_ireason(drive, len, ireason)) + if (blk_fs_request(rq) || blk_pc_request(rq)) { + if (ide_cd_check_ireason(drive, len, ireason, write)) return ide_stopped; - xferfunc = HWIF(drive)->atapi_output_bytes; - } else { - /* - * read from drive - */ - if (cdrom_read_check_ireason(drive, len, ireason)) - return ide_stopped; + if (blk_fs_request(rq) && write == 0) { + int nskip; + + if (ide_cd_check_transfer_size(drive, len)) { + cdrom_end_request(drive, 0); + return ide_stopped; + } + + /* + * First, figure out if we need to bit-bucket + * any of the leading sectors. + */ + nskip = min_t(int, rq->current_nr_sectors + - bio_cur_sectors(rq->bio), + thislen >> 9); + if (nskip > 0) { + ide_cd_drain_data(drive, nskip); + rq->current_nr_sectors -= nskip; + thislen -= (nskip << 9); + } + } + } + if (ireason == 0) { + write = 1; + xferfunc = HWIF(drive)->atapi_output_bytes; + } else if (ireason == 2 || (ireason == 1 && + (blk_fs_request(rq) || blk_pc_request(rq)))) { + write = 0; xferfunc = HWIF(drive)->atapi_input_bytes; + } else { + printk(KERN_ERR "%s: %s: The drive " + "appears confused (ireason = 0x%02x). " + "Trying to recover by ending request.\n", + drive->name, __FUNCTION__, ireason); + goto end_request; } /* * transfer data */ while (thislen > 0) { - int blen = blen = rq->data_len; - char *ptr = rq->data; + u8 *ptr = blk_fs_request(rq) ? NULL : rq->data; + int blen = rq->data_len; /* * bio backed? */ if (rq->bio) { - ptr = bio_data(rq->bio); - blen = bio_iovec(rq->bio)->bv_len; + if (blk_fs_request(rq)) { + ptr = rq->buffer; + blen = rq->current_nr_sectors << 9; + } else { + ptr = bio_data(rq->bio); + blen = bio_iovec(rq->bio)->bv_len; + } } if (!ptr) { - printk(KERN_ERR "%s: confused, missing data\n", drive->name); + if (blk_fs_request(rq) && !write) + /* + * If the buffers are full, cache the rest + * of the data in our internal buffer. + */ + cdrom_buffer_sectors(drive, rq->sector, + thislen >> 9); + else { + printk(KERN_ERR "%s: confused, missing data\n", + drive->name); + blk_dump_rq_flags(rq, rq_data_dir(rq) + ? "cdrom_newpc_intr, write" + : "cdrom_newpc_intr, read"); + } break; } @@ -1784,186 +1157,117 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) thislen -= blen; len -= blen; - rq->data_len -= blen; - - if (rq->bio) - end_that_request_chunk(rq, 1, blen); - else - rq->data += blen; - } - - /* - * pad, if necessary - */ - if (len > 0) { - while (len > 0) { - int pad = 0; - - xferfunc(drive, &pad, sizeof(pad)); - len -= sizeof(pad); - } - } - - BUG_ON(HWGROUP(drive)->handler != NULL); - - ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL); - return ide_started; - -end_request: - if (!rq->data_len) - post_transform_command(rq); - - spin_lock_irqsave(&ide_lock, flags); - blkdev_dequeue_request(rq); - end_that_request_last(rq, 1); - HWGROUP(drive)->rq = NULL; - spin_unlock_irqrestore(&ide_lock, flags); - return ide_stopped; -} -static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) -{ - int stat, ireason, len, sectors_to_transfer, uptodate; - struct cdrom_info *info = drive->driver_data; - int dma_error = 0, dma = info->dma; - u8 lowcyl = 0, highcyl = 0; + if (blk_fs_request(rq)) { + rq->buffer += blen; + rq->nr_sectors -= (blen >> 9); + rq->current_nr_sectors -= (blen >> 9); + rq->sector += (blen >> 9); - struct request *rq = HWGROUP(drive)->rq; + if (rq->current_nr_sectors == 0 && rq->nr_sectors) + cdrom_end_request(drive, 1); + } else { + rq->data_len -= blen; - /* Check for errors. */ - if (dma) { - info->dma = 0; - if ((dma_error = HWIF(drive)->ide_dma_end(drive))) { - printk(KERN_ERR "ide-cd: write dma error\n"); - ide_dma_off(drive); + /* + * The request can't be completed until DRQ is cleared. + * So complete the data, but don't complete the request + * using the dummy function for the callback feature + * of blk_end_request_callback(). + */ + if (rq->bio) + blk_end_request_callback(rq, 0, blen, + cdrom_newpc_intr_dummy_cb); + else + rq->data += blen; } } - if (cdrom_decode_status(drive, 0, &stat)) - return ide_stopped; + if (write && blk_sense_request(rq)) + rq->sense_len += thislen; /* - * using dma, transfer is complete now + * pad, if necessary */ - if (dma) { - if (dma_error) - return ide_error(drive, "dma error", stat); + if (!blk_fs_request(rq) && len > 0) + ide_cd_pad_transfer(drive, xferfunc, len); - ide_end_request(drive, 1, rq->nr_sectors); - return ide_stopped; + if (blk_pc_request(rq)) { + timeout = rq->timeout; + } else { + timeout = ATAPI_WAIT_PC; + if (!blk_fs_request(rq)) + expiry = cdrom_timer_expiry; } - /* Read the interrupt reason and the transfer length. */ - ireason = HWIF(drive)->INB(IDE_IREASON_REG); - lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); - highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); + ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry); + return ide_started; - len = lowcyl + (256 * highcyl); +end_request: + if (blk_pc_request(rq)) { + unsigned long flags; - /* If DRQ is clear, the command has completed. */ - if ((stat & DRQ_STAT) == 0) { - /* If we're not done writing, complain. - * Otherwise, complete the command normally. - */ - uptodate = 1; - if (rq->current_nr_sectors > 0) { - printk(KERN_ERR "%s: write_intr: data underrun (%d blocks)\n", - drive->name, rq->current_nr_sectors); - uptodate = 0; - } + spin_lock_irqsave(&ide_lock, flags); + if (__blk_end_request(rq, 0, rq->data_len)) + BUG(); + HWGROUP(drive)->rq = NULL; + spin_unlock_irqrestore(&ide_lock, flags); + } else { + if (!uptodate) + rq->cmd_flags |= REQ_FAILED; cdrom_end_request(drive, uptodate); - return ide_stopped; } + return ide_stopped; +} - /* Check that the drive is expecting to do the same thing we are. */ - if (cdrom_write_check_ireason(drive, len, ireason)) - return ide_stopped; - - sectors_to_transfer = len / SECTOR_SIZE; - - /* - * now loop and write out the data - */ - while (sectors_to_transfer > 0) { - int this_transfer; - - if (!rq->current_nr_sectors) { - printk(KERN_ERR "ide-cd: write_intr: oops\n"); - break; - } +static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) +{ + struct cdrom_info *cd = drive->driver_data; + int write = rq_data_dir(rq) == WRITE; + unsigned short sectors_per_frame = + queue_hardsect_size(drive->queue) >> SECTOR_BITS; + if (write) { /* - * Figure out how many sectors we can transfer + * disk has become write protected */ - this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors); - - while (this_transfer > 0) { - HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->nr_sectors; - --rq->current_nr_sectors; - ++rq->sector; - --this_transfer; - --sectors_to_transfer; + if (cd->disk->policy) { + cdrom_end_request(drive, 0); + return ide_stopped; } - + } else { /* - * current buffer complete, move on + * We may be retrying this request after an error. Fix up any + * weirdness which might be present in the request packet. */ - if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request(drive, 1); - } - - /* re-arm handler */ - ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL); - return ide_started; -} - -static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; + restore_request(rq); -#if 0 /* the immediate bit */ - rq->cmd[1] = 1 << 3; -#endif - rq->timeout = ATAPI_WAIT_PC; - - return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr); -} - -static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) -{ - struct cdrom_info *info = drive->driver_data; - struct gendisk *g = info->disk; - unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; + /* Satisfy whatever we can of this request from our cache. */ + if (cdrom_read_from_buffer(drive)) + return ide_stopped; + } /* - * writes *must* be hardware frame aligned + * use DMA, if possible / writes *must* be hardware frame aligned */ if ((rq->nr_sectors & (sectors_per_frame - 1)) || (rq->sector & (sectors_per_frame - 1))) { - cdrom_end_request(drive, 0); - return ide_stopped; - } - - /* - * disk has become write protected - */ - if (g->policy) { - cdrom_end_request(drive, 0); - return ide_stopped; - } - - info->nsectors_buffered = 0; + if (write) { + cdrom_end_request(drive, 0); + return ide_stopped; + } + cd->dma = 0; + } else + cd->dma = drive->using_dma; - /* use dma, if possible. we don't need to check more, since we - * know that the transfer is always (at least!) frame aligned */ - info->dma = drive->using_dma ? 1 : 0; + /* Clear the local sector buffer. */ + cd->nsectors_buffered = 0; - info->devinfo.media_written = 1; + if (write) + cd->devinfo.media_written = 1; - /* Start sending the write request to the drive. */ - return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont); + /* Start sending the read/write request to the drive. */ + return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont); } static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive) @@ -1980,7 +1284,10 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) { struct cdrom_info *info = drive->driver_data; - rq->cmd_flags |= REQ_QUIET; + if (blk_pc_request(rq)) + rq->cmd_flags |= REQ_QUIET; + else + rq->cmd_flags &= ~REQ_FAILED; info->dma = 0; @@ -2017,7 +1324,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) struct cdrom_info *info = drive->driver_data; if (blk_fs_request(rq)) { - if (CDROM_CONFIG_FLAGS(drive)->seeking) { + if (info->cd_flags & IDE_CD_FLAG_SEEKING) { unsigned long elapsed = jiffies - info->start_seek; int stat = HWIF(drive)->INB(IDE_STATUS_REG); @@ -2028,22 +1335,16 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) } printk (KERN_ERR "%s: DSC timeout\n", drive->name); } - CDROM_CONFIG_FLAGS(drive)->seeking = 0; + info->cd_flags &= ~IDE_CD_FLAG_SEEKING; } if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) { action = cdrom_start_seek(drive, block); - } else { - if (rq_data_dir(rq) == READ) - action = cdrom_start_read(drive, block); - else - action = cdrom_start_write(drive, rq); - } + } else + action = cdrom_start_rw(drive, rq); info->last_block = block; return action; - } else if (rq->cmd_type == REQ_TYPE_SENSE || + } else if (blk_sense_request(rq) || blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) { - return cdrom_do_packet_command(drive); - } else if (blk_pc_request(rq)) { return cdrom_do_block_pc(drive, rq); } else if (blk_special_request(rq)) { /* @@ -2070,141 +1371,33 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) * can also be NULL, in which case no sense information is returned. */ -#if ! STANDARD_ATAPI -static inline -int bin2bcd (int x) -{ - return (x%10) | ((x/10) << 4); -} - - -static inline -int bcd2bin (int x) -{ - return (x >> 4) * 10 + (x & 0x0f); -} - static void msf_from_bcd (struct atapi_msf *msf) { - msf->minute = bcd2bin (msf->minute); - msf->second = bcd2bin (msf->second); - msf->frame = bcd2bin (msf->frame); -} - -#endif /* not STANDARD_ATAPI */ - - -static inline -void lba_to_msf (int lba, byte *m, byte *s, byte *f) -{ - lba += CD_MSF_OFFSET; - lba &= 0xffffff; /* negative lbas use only 24 bits */ - *m = lba / (CD_SECS * CD_FRAMES); - lba %= (CD_SECS * CD_FRAMES); - *s = lba / CD_FRAMES; - *f = lba % CD_FRAMES; -} - - -static inline -int msf_to_lba (byte m, byte s, byte f) -{ - return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; + msf->minute = BCD2BIN(msf->minute); + msf->second = BCD2BIN(msf->second); + msf->frame = BCD2BIN(msf->frame); } -static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) +int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) { struct request req; struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *cdi = &info->devinfo; - cdrom_prepare_request(drive, &req); + ide_cd_init_rq(drive, &req); req.sense = sense; req.cmd[0] = GPCMD_TEST_UNIT_READY; req.cmd_flags |= REQ_QUIET; -#if ! STANDARD_ATAPI - /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to - switch CDs instead of supporting the LOAD_UNLOAD opcode */ - + /* + * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to + * switch CDs instead of supporting the LOAD_UNLOAD opcode. + */ req.cmd[7] = cdi->sanyo_slot % 3; -#endif /* not STANDARD_ATAPI */ - return cdrom_queue_packet_command(drive, &req); -} - - -/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ -static int -cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense) -{ - struct request_sense my_sense; - struct request req; - int stat; - - if (sense == NULL) - sense = &my_sense; - - /* If the drive cannot lock the door, just pretend. */ - if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) { - stat = 0; - } else { - cdrom_prepare_request(drive, &req); - req.sense = sense; - req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; - req.cmd[4] = lockflag ? 1 : 0; - stat = cdrom_queue_packet_command(drive, &req); - } - - /* If we got an illegal field error, the drive - probably cannot lock the door. */ - if (stat != 0 && - sense->sense_key == ILLEGAL_REQUEST && - (sense->asc == 0x24 || sense->asc == 0x20)) { - printk (KERN_ERR "%s: door locking not supported\n", - drive->name); - CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; - stat = 0; - } - - /* no medium, that's alright. */ - if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a) - stat = 0; - - if (stat == 0) - CDROM_STATE_FLAGS(drive)->door_locked = lockflag; - - return stat; -} - - -/* Eject the disk if EJECTFLAG is 0. - If EJECTFLAG is 1, try to reload the disk. */ -static int cdrom_eject(ide_drive_t *drive, int ejectflag, - struct request_sense *sense) -{ - struct request req; - char loej = 0x02; - - if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag) - return -EDRIVE_CANT_DO_THIS; - - /* reload fails on some drives, if the tray is locked */ - if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) - return 0; - - cdrom_prepare_request(drive, &req); - - /* only tell drive to close tray if open, if it can do that */ - if (ejectflag && !CDROM_CONFIG_FLAGS(drive)->close_tray) - loej = 0; - - req.sense = sense; - req.cmd[0] = GPCMD_START_STOP_UNIT; - req.cmd[4] = loej | (ejectflag != 0); - return cdrom_queue_packet_command(drive, &req); + return ide_cd_queue_pc(drive, &req); } static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, @@ -2219,7 +1412,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, int stat; struct request req; - cdrom_prepare_request(drive, &req); + ide_cd_init_rq(drive, &req); req.sense = sense; req.cmd[0] = GPCMD_READ_CDVD_CAPACITY; @@ -2227,7 +1420,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, req.data_len = sizeof(capbuf); req.cmd_flags |= REQ_QUIET; - stat = cdrom_queue_packet_command(drive, &req); + stat = ide_cd_queue_pc(drive, &req); if (stat == 0) { *capacity = 1 + be32_to_cpu(capbuf.lba); *sectors_per_frame = @@ -2243,7 +1436,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, { struct request req; - cdrom_prepare_request(drive, &req); + ide_cd_init_rq(drive, &req); req.sense = sense; req.data = buf; @@ -2258,12 +1451,11 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, if (msf_flag) req.cmd[1] = 2; - return cdrom_queue_packet_command(drive, &req); + return ide_cd_queue_pc(drive, &req); } - /* Try to read the entire TOC for the disk into our internal buffer. */ -static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) +int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) { int stat, ntracks, i; struct cdrom_info *info = drive->driver_data; @@ -2290,7 +1482,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) If it is, just return. */ (void) cdrom_check_status(drive, sense); - if (CDROM_STATE_FLAGS(drive)->toc_valid) + if (info->cd_flags & IDE_CD_FLAG_TOC_VALID) return 0; /* Try to get the total cdrom capacity and sector size. */ @@ -2312,12 +1504,10 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) if (stat) return stat; -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) { - toc->hdr.first_track = bcd2bin(toc->hdr.first_track); - toc->hdr.last_track = bcd2bin(toc->hdr.last_track); + if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) { + toc->hdr.first_track = BCD2BIN(toc->hdr.first_track); + toc->hdr.last_track = BCD2BIN(toc->hdr.last_track); } -#endif /* not STANDARD_ATAPI */ ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; if (ntracks <= 0) @@ -2349,16 +1539,13 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) (ntracks + 1) * sizeof(struct atapi_toc_entry), sense); - if (stat) { + if (stat) return stat; - } -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) { - toc->hdr.first_track = bin2bcd(CDROM_LEADOUT); - toc->hdr.last_track = bin2bcd(CDROM_LEADOUT); - } else -#endif /* not STANDARD_ATAPI */ - { + + if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) { + toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT); + toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT); + } else { toc->hdr.first_track = CDROM_LEADOUT; toc->hdr.last_track = CDROM_LEADOUT; } @@ -2369,21 +1556,17 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) toc->hdr.toc_length = ntohs (toc->hdr.toc_length); -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) { - toc->hdr.first_track = bcd2bin(toc->hdr.first_track); - toc->hdr.last_track = bcd2bin(toc->hdr.last_track); + if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) { + toc->hdr.first_track = BCD2BIN(toc->hdr.first_track); + toc->hdr.last_track = BCD2BIN(toc->hdr.last_track); } -#endif /* not STANDARD_ATAPI */ - for (i=0; i<=ntracks; i++) { -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) { - if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) - toc->ent[i].track = bcd2bin(toc->ent[i].track); + for (i = 0; i <= ntracks; i++) { + if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) { + if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) + toc->ent[i].track = BCD2BIN(toc->ent[i].track); msf_from_bcd(&toc->ent[i].addr.msf); } -#endif /* not STANDARD_ATAPI */ toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute, toc->ent[i].addr.msf.second, toc->ent[i].addr.msf.frame); @@ -2403,8 +1586,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */ } -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) { + if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) { /* Re-read multisession information using MSF format */ stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, sizeof(ms_tmp), sense); @@ -2416,7 +1598,6 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) ms_tmp.ent.addr.msf.second, ms_tmp.ent.addr.msf.frame); } -#endif /* not STANDARD_ATAPI */ toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); @@ -2429,278 +1610,22 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) } /* Remember that we've read this stuff. */ - CDROM_STATE_FLAGS(drive)->toc_valid = 1; - - return 0; -} - - -static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf, - int buflen, struct request_sense *sense) -{ - struct request req; - - cdrom_prepare_request(drive, &req); - - req.sense = sense; - req.data = buf; - req.data_len = buflen; - req.cmd[0] = GPCMD_READ_SUBCHANNEL; - req.cmd[1] = 2; /* MSF addressing */ - req.cmd[2] = 0x40; /* request subQ data */ - req.cmd[3] = format; - req.cmd[7] = (buflen >> 8); - req.cmd[8] = (buflen & 0xff); - return cdrom_queue_packet_command(drive, &req); -} - -/* ATAPI cdrom drives are free to select the speed you request or any slower - rate :-( Requesting too fast a speed will _not_ produce an error. */ -static int cdrom_select_speed(ide_drive_t *drive, int speed, - struct request_sense *sense) -{ - struct request req; - cdrom_prepare_request(drive, &req); - - req.sense = sense; - if (speed == 0) - speed = 0xffff; /* set to max */ - else - speed *= 177; /* Nx to kbytes/s */ - - req.cmd[0] = GPCMD_SET_SPEED; - /* Read Drive speed in kbytes/second MSB */ - req.cmd[2] = (speed >> 8) & 0xff; - /* Read Drive speed in kbytes/second LSB */ - req.cmd[3] = speed & 0xff; - if (CDROM_CONFIG_FLAGS(drive)->cd_r || - CDROM_CONFIG_FLAGS(drive)->cd_rw || - CDROM_CONFIG_FLAGS(drive)->dvd_r) { - /* Write Drive speed in kbytes/second MSB */ - req.cmd[4] = (speed >> 8) & 0xff; - /* Write Drive speed in kbytes/second LSB */ - req.cmd[5] = speed & 0xff; - } - - return cdrom_queue_packet_command(drive, &req); -} - -static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end) -{ - struct request_sense sense; - struct request req; - - cdrom_prepare_request(drive, &req); - - req.sense = &sense; - req.cmd[0] = GPCMD_PLAY_AUDIO_MSF; - lba_to_msf(lba_start, &req.cmd[3], &req.cmd[4], &req.cmd[5]); - lba_to_msf(lba_end-1, &req.cmd[6], &req.cmd[7], &req.cmd[8]); - - return cdrom_queue_packet_command(drive, &req); -} - -static int cdrom_get_toc_entry(ide_drive_t *drive, int track, - struct atapi_toc_entry **ent) -{ - struct cdrom_info *info = drive->driver_data; - struct atapi_toc *toc = info->toc; - int ntracks; - - /* - * don't serve cached data, if the toc isn't valid - */ - if (!CDROM_STATE_FLAGS(drive)->toc_valid) - return -EINVAL; - - /* Check validity of requested track number. */ - ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; - if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0; - if (track == CDROM_LEADOUT) - *ent = &toc->ent[ntracks]; - else if (track < toc->hdr.first_track || - track > toc->hdr.last_track) - return -EINVAL; - else - *ent = &toc->ent[track - toc->hdr.first_track]; + info->cd_flags |= IDE_CD_FLAG_TOC_VALID; return 0; } -/* the generic packet interface to cdrom.c */ -static int ide_cdrom_packet(struct cdrom_device_info *cdi, - struct packet_command *cgc) -{ - struct request req; - ide_drive_t *drive = cdi->handle; - - if (cgc->timeout <= 0) - cgc->timeout = ATAPI_WAIT_PC; - - /* here we queue the commands from the uniform CD-ROM - layer. the packet must be complete, as we do not - touch it at all. */ - cdrom_prepare_request(drive, &req); - memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE); - if (cgc->sense) - memset(cgc->sense, 0, sizeof(struct request_sense)); - req.data = cgc->buffer; - req.data_len = cgc->buflen; - req.timeout = cgc->timeout; - - if (cgc->quiet) - req.cmd_flags |= REQ_QUIET; - - req.sense = cgc->sense; - cgc->stat = cdrom_queue_packet_command(drive, &req); - if (!cgc->stat) - cgc->buflen -= req.data_len; - return cgc->stat; -} - -static -int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, void *arg) - -{ - ide_drive_t *drive = cdi->handle; - struct cdrom_info *info = drive->driver_data; - int stat; - - switch (cmd) { - /* - * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since - * atapi doesn't support it - */ - case CDROMPLAYTRKIND: { - unsigned long lba_start, lba_end; - struct cdrom_ti *ti = arg; - struct atapi_toc_entry *first_toc, *last_toc; - - stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc); - if (stat) - return stat; - - stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc); - if (stat) - return stat; - - if (ti->cdti_trk1 != CDROM_LEADOUT) - ++last_toc; - lba_start = first_toc->addr.lba; - lba_end = last_toc->addr.lba; - - if (lba_end <= lba_start) - return -EINVAL; - - return cdrom_play_audio(drive, lba_start, lba_end); - } - - case CDROMREADTOCHDR: { - struct cdrom_tochdr *tochdr = arg; - struct atapi_toc *toc; - - /* Make sure our saved TOC is valid. */ - stat = cdrom_read_toc(drive, NULL); - if (stat) - return stat; - - toc = info->toc; - tochdr->cdth_trk0 = toc->hdr.first_track; - tochdr->cdth_trk1 = toc->hdr.last_track; - - return 0; - } - - case CDROMREADTOCENTRY: { - struct cdrom_tocentry *tocentry = arg; - struct atapi_toc_entry *toce; - - stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce); - if (stat) - return stat; - - tocentry->cdte_ctrl = toce->control; - tocentry->cdte_adr = toce->adr; - if (tocentry->cdte_format == CDROM_MSF) { - lba_to_msf (toce->addr.lba, - &tocentry->cdte_addr.msf.minute, - &tocentry->cdte_addr.msf.second, - &tocentry->cdte_addr.msf.frame); - } else - tocentry->cdte_addr.lba = toce->addr.lba; - - return 0; - } - - default: - return -EINVAL; - } -} - -static -int ide_cdrom_reset (struct cdrom_device_info *cdi) -{ - ide_drive_t *drive = cdi->handle; - struct request_sense sense; - struct request req; - int ret; - - cdrom_prepare_request(drive, &req); - req.cmd_type = REQ_TYPE_SPECIAL; - req.cmd_flags = REQ_QUIET; - ret = ide_do_drive_cmd(drive, &req, ide_wait); - - /* - * A reset will unlock the door. If it was previously locked, - * lock it again. - */ - if (CDROM_STATE_FLAGS(drive)->door_locked) - (void) cdrom_lockdoor(drive, 1, &sense); - - return ret; -} - - -static -int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position) -{ - ide_drive_t *drive = cdi->handle; - struct request_sense sense; - - if (position) { - int stat = cdrom_lockdoor(drive, 0, &sense); - if (stat) - return stat; - } - - return cdrom_eject(drive, !position, &sense); -} - -static -int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock) -{ - ide_drive_t *drive = cdi->handle; - return cdrom_lockdoor(drive, lock, NULL); -} - -static -int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap) +int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf) { struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *cdi = &info->devinfo; struct packet_command cgc; - int stat, attempts = 3, size = sizeof(*cap); + int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE; - /* - * ACER50 (and others?) require the full spec length mode sense - * page capabilities size, but older drives break. - */ - if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || - !strcmp(drive->id->model, "WPI CDS-32X"))) - size -= sizeof(cap->pad); + if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0) + size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE; - init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN); + init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN); do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); if (!stat) @@ -2709,177 +1634,33 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_pag return stat; } -static -void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page *cap) -{ - /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ - if (!drive->id->model[0] && - !strncmp(drive->id->fw_rev, "241N", 4)) { - CDROM_STATE_FLAGS(drive)->current_speed = - (((unsigned int)cap->curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS(drive)->max_speed = - (((unsigned int)cap->maxspeed) + (176/2)) / 176; - } else { - CDROM_STATE_FLAGS(drive)->current_speed = - (ntohs(cap->curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS(drive)->max_speed = - (ntohs(cap->maxspeed) + (176/2)) / 176; - } -} - -static -int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) -{ - ide_drive_t *drive = cdi->handle; - struct request_sense sense; - struct atapi_capabilities_page cap; - int stat; - - if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0) - return stat; - - if (!ide_cdrom_get_capabilities(drive, &cap)) { - ide_cdrom_update_speed(drive, &cap); - cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed; - } - return 0; -} - -/* - * add logic to try GET_EVENT command first to check for media and tray - * status. this should be supported by newer cd-r/w and all DVD etc - * drives - */ -static -int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) +void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf) { - ide_drive_t *drive = cdi->handle; - struct media_event_desc med; - struct request_sense sense; - int stat; - - if (slot_nr != CDSL_CURRENT) - return -EINVAL; - - stat = cdrom_check_status(drive, &sense); - if (!stat || sense.sense_key == UNIT_ATTENTION) - return CDS_DISC_OK; - - if (!cdrom_get_media_event(cdi, &med)) { - if (med.media_present) - return CDS_DISC_OK; - else if (med.door_open) - return CDS_TRAY_OPEN; - else - return CDS_NO_DISC; - } - - if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04) - return CDS_DISC_OK; - - /* - * If not using Mt Fuji extended media tray reports, - * just return TRAY_OPEN since ATAPI doesn't provide - * any other way to detect this... - */ - if (sense.sense_key == NOT_READY) { - if (sense.asc == 0x3a && sense.ascq == 1) - return CDS_NO_DISC; - else - return CDS_TRAY_OPEN; - } - return CDS_DRIVE_NOT_READY; -} - -static -int ide_cdrom_get_last_session (struct cdrom_device_info *cdi, - struct cdrom_multisession *ms_info) -{ - struct atapi_toc *toc; - ide_drive_t *drive = cdi->handle; - struct cdrom_info *info = drive->driver_data; - struct request_sense sense; - int ret; - - if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL) - if ((ret = cdrom_read_toc(drive, &sense))) - return ret; - - toc = info->toc; - ms_info->addr.lba = toc->last_session_lba; - ms_info->xa_flag = toc->xa_flag; - - return 0; -} - -static -int ide_cdrom_get_mcn (struct cdrom_device_info *cdi, - struct cdrom_mcn *mcn_info) -{ - int stat; - char mcnbuf[24]; - ide_drive_t *drive = cdi->handle; - -/* get MCN */ - if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL))) - return stat; - - memcpy (mcn_info->medium_catalog_number, mcnbuf+9, - sizeof (mcn_info->medium_catalog_number)-1); - mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1] - = '\0'; - - return 0; -} - - + struct cdrom_info *cd = drive->driver_data; + u16 curspeed, maxspeed; -/**************************************************************************** - * Other driver requests (open, close, check media change). - */ + curspeed = *(u16 *)&buf[8 + 14]; + maxspeed = *(u16 *)&buf[8 + 8]; -static -int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi, - int slot_nr) -{ - ide_drive_t *drive = cdi->handle; - int retval; - - if (slot_nr == CDSL_CURRENT) { - (void) cdrom_check_status(drive, NULL); - retval = CDROM_STATE_FLAGS(drive)->media_changed; - CDROM_STATE_FLAGS(drive)->media_changed = 0; - return retval; + if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) { + curspeed = le16_to_cpu(curspeed); + maxspeed = le16_to_cpu(maxspeed); } else { - return -EINVAL; + curspeed = be16_to_cpu(curspeed); + maxspeed = be16_to_cpu(maxspeed); } -} - - -static -int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose) -{ - return 0; -} - -/* - * Close down the device. Invalidate all cached blocks. - */ -static -void ide_cdrom_release_real (struct cdrom_device_info *cdi) -{ - ide_drive_t *drive = cdi->handle; - - if (!cdi->use_count) - CDROM_STATE_FLAGS(drive)->toc_valid = 0; + cd->current_speed = (curspeed + (176/2)) / 176; + cd->max_speed = (maxspeed + (176/2)) / 176; } +#define IDE_CD_CAPABILITIES \ + (CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | \ + CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | \ + CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R | \ + CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \ + CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM) - -/**************************************************************************** - * Device initialization. - */ static struct cdrom_device_ops ide_cdrom_dops = { .open = ide_cdrom_open_real, .release = ide_cdrom_release_real, @@ -2892,14 +1673,7 @@ static struct cdrom_device_ops ide_cdrom_dops = { .get_mcn = ide_cdrom_get_mcn, .reset = ide_cdrom_reset, .audio_ioctl = ide_cdrom_audio_ioctl, - .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | - CDC_SELECT_SPEED | CDC_SELECT_DISC | - CDC_MULTI_SESSION | CDC_MCN | - CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | - CDC_DRIVE_STATUS | CDC_CD_R | - CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM | - CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW | - CDC_MRW_W | CDC_RAM, + .capability = IDE_CD_CAPABILITIES, .generic_packet = ide_cdrom_packet, }; @@ -2909,33 +1683,13 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) struct cdrom_device_info *devinfo = &info->devinfo; devinfo->ops = &ide_cdrom_dops; - devinfo->mask = 0; - devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed; + devinfo->speed = info->current_speed; devinfo->capacity = nslots; devinfo->handle = drive; strcpy(devinfo->name, drive->name); - - /* set capability mask to match the probe. */ - if (!CDROM_CONFIG_FLAGS(drive)->cd_r) - devinfo->mask |= CDC_CD_R; - if (!CDROM_CONFIG_FLAGS(drive)->cd_rw) - devinfo->mask |= CDC_CD_RW; - if (!CDROM_CONFIG_FLAGS(drive)->dvd) - devinfo->mask |= CDC_DVD; - if (!CDROM_CONFIG_FLAGS(drive)->dvd_r) - devinfo->mask |= CDC_DVD_R; - if (!CDROM_CONFIG_FLAGS(drive)->dvd_ram) - devinfo->mask |= CDC_DVD_RAM; - if (!CDROM_CONFIG_FLAGS(drive)->is_changer) - devinfo->mask |= CDC_SELECT_DISC; - if (!CDROM_CONFIG_FLAGS(drive)->audio_play) - devinfo->mask |= CDC_PLAY_AUDIO; - if (!CDROM_CONFIG_FLAGS(drive)->close_tray) - devinfo->mask |= CDC_CLOSE_TRAY; - if (!CDROM_CONFIG_FLAGS(drive)->mo_drive) - devinfo->mask |= CDC_MO_DRIVE; - if (!CDROM_CONFIG_FLAGS(drive)->ram) - devinfo->mask |= CDC_RAM; + + if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT) + devinfo->mask |= CDC_SELECT_SPEED; devinfo->disk = info->disk; return register_cdrom(devinfo); @@ -2944,22 +1698,25 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) static int ide_cdrom_probe_capabilities (ide_drive_t *drive) { - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - struct atapi_capabilities_page cap; + struct cdrom_info *cd = drive->driver_data; + struct cdrom_device_info *cdi = &cd->devinfo; + u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE]; + mechtype_t mechtype; int nslots = 1; + cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | + CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO | + CDC_MO_DRIVE | CDC_RAM); + if (drive->media == ide_optical) { - CDROM_CONFIG_FLAGS(drive)->mo_drive = 1; - CDROM_CONFIG_FLAGS(drive)->ram = 1; + cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM); printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name); return nslots; } - if (CDROM_CONFIG_FLAGS(drive)->nec260 || - !strcmp(drive->id->model,"STINGRAY 8422 IDE 8X CD-ROM 7-27-95")) { - CDROM_CONFIG_FLAGS(drive)->no_eject = 0; - CDROM_CONFIG_FLAGS(drive)->audio_play = 1; + if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) { + cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT; + cdi->mask &= ~CDC_PLAY_AUDIO; return nslots; } @@ -2973,88 +1730,66 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) cdi->handle = drive; cdi->ops = &ide_cdrom_dops; - if (ide_cdrom_get_capabilities(drive, &cap)) + if (ide_cdrom_get_capabilities(drive, buf)) return 0; - if (cap.lock == 0) - CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; - if (cap.eject) - CDROM_CONFIG_FLAGS(drive)->no_eject = 0; - if (cap.cd_r_write) - CDROM_CONFIG_FLAGS(drive)->cd_r = 1; - if (cap.cd_rw_write) { - CDROM_CONFIG_FLAGS(drive)->cd_rw = 1; - CDROM_CONFIG_FLAGS(drive)->ram = 1; - } - if (cap.test_write) - CDROM_CONFIG_FLAGS(drive)->test_write = 1; - if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom) - CDROM_CONFIG_FLAGS(drive)->dvd = 1; - if (cap.dvd_ram_write) { - CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1; - CDROM_CONFIG_FLAGS(drive)->ram = 1; - } - if (cap.dvd_r_write) - CDROM_CONFIG_FLAGS(drive)->dvd_r = 1; - if (cap.audio_play) - CDROM_CONFIG_FLAGS(drive)->audio_play = 1; - if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup) - CDROM_CONFIG_FLAGS(drive)->close_tray = 0; - - /* Some drives used by Apple don't advertise audio play - * but they do support reading TOC & audio datas - */ - if (strcmp(drive->id->model, "MATSHITADVD-ROM SR-8187") == 0 || - strcmp(drive->id->model, "MATSHITADVD-ROM SR-8186") == 0 || - strcmp(drive->id->model, "MATSHITADVD-ROM SR-8176") == 0 || - strcmp(drive->id->model, "MATSHITADVD-ROM SR-8174") == 0) - CDROM_CONFIG_FLAGS(drive)->audio_play = 1; + if ((buf[8 + 6] & 0x01) == 0) + cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK; + if (buf[8 + 6] & 0x08) + cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT; + if (buf[8 + 3] & 0x01) + cdi->mask &= ~CDC_CD_R; + if (buf[8 + 3] & 0x02) + cdi->mask &= ~(CDC_CD_RW | CDC_RAM); + if (buf[8 + 2] & 0x38) + cdi->mask &= ~CDC_DVD; + if (buf[8 + 3] & 0x20) + cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM); + if (buf[8 + 3] & 0x10) + cdi->mask &= ~CDC_DVD_R; + if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK)) + cdi->mask &= ~CDC_PLAY_AUDIO; + + mechtype = buf[8 + 6] >> 5; + if (mechtype == mechtype_caddy || mechtype == mechtype_popup) + cdi->mask |= CDC_CLOSE_TRAY; -#if ! STANDARD_ATAPI if (cdi->sanyo_slot > 0) { - CDROM_CONFIG_FLAGS(drive)->is_changer = 1; + cdi->mask &= ~CDC_SELECT_DISC; nslots = 3; + } else if (mechtype == mechtype_individual_changer || + mechtype == mechtype_cartridge_changer) { + nslots = cdrom_number_of_slots(cdi); + if (nslots > 1) + cdi->mask &= ~CDC_SELECT_DISC; } - else -#endif /* not STANDARD_ATAPI */ - if (cap.mechtype == mechtype_individual_changer || - cap.mechtype == mechtype_cartridge_changer) { - if ((nslots = cdrom_number_of_slots(cdi)) > 1) { - CDROM_CONFIG_FLAGS(drive)->is_changer = 1; - CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 1; - } - } + ide_cdrom_update_speed(drive, buf); - ide_cdrom_update_speed(drive, &cap); - /* don't print speed if the drive reported 0. - */ printk(KERN_INFO "%s: ATAPI", drive->name); - if (CDROM_CONFIG_FLAGS(drive)->max_speed) - printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed); - printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM"); - if (CDROM_CONFIG_FLAGS(drive)->dvd_r|CDROM_CONFIG_FLAGS(drive)->dvd_ram) - printk(" DVD%s%s", - (CDROM_CONFIG_FLAGS(drive)->dvd_r)? "-R" : "", - (CDROM_CONFIG_FLAGS(drive)->dvd_ram)? "-RAM" : ""); + /* don't print speed if the drive reported 0 */ + if (cd->max_speed) + printk(KERN_CONT " %dX", cd->max_speed); - if (CDROM_CONFIG_FLAGS(drive)->cd_r|CDROM_CONFIG_FLAGS(drive)->cd_rw) - printk(" CD%s%s", - (CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "", - (CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : ""); + printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM"); - if (CDROM_CONFIG_FLAGS(drive)->is_changer) - printk(" changer w/%d slots", nslots); - else - printk(" drive"); + if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0) + printk(KERN_CONT " DVD%s%s", + (cdi->mask & CDC_DVD_R) ? "" : "-R", + (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM"); - printk(", %dkB Cache", be16_to_cpu(cap.buffer_size)); + if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0) + printk(KERN_CONT " CD%s%s", + (cdi->mask & CDC_CD_R) ? "" : "-R", + (cdi->mask & CDC_CD_RW) ? "" : "/RW"); - if (drive->using_dma) - ide_dma_verbose(drive); + if ((cdi->mask & CDC_SELECT_DISC) == 0) + printk(KERN_CONT " changer w/%d slots", nslots); + else + printk(KERN_CONT " drive"); - printk("\n"); + printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12])); return nslots; } @@ -3147,11 +1882,74 @@ static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq) return 0; } +struct cd_list_entry { + const char *id_model; + const char *id_firmware; + unsigned int cd_flags; +}; + +static const struct cd_list_entry ide_cd_quirks_list[] = { + /* Limit transfer size per interrupt. */ + { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES }, + { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_CD_FLAG_LIMIT_NFRAMES }, + /* SCR-3231 doesn't support the SET_CD_SPEED command. */ + { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT }, + /* Old NEC260 (not R) was released before ATAPI 1.2 spec. */ + { "NEC CD-ROM DRIVE:260", "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD | + IDE_CD_FLAG_PRE_ATAPI12, }, + /* Vertos 300, some versions of this drive like to talk BCD. */ + { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, }, + /* Vertos 600 ESD. */ + { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, }, + /* + * Sanyo 3 CD changer uses a non-standard command for CD changing + * (by default standard ATAPI support for CD changers is used). + */ + { "CD-ROM CDR-C3 G", NULL, IDE_CD_FLAG_SANYO_3CD }, + { "CD-ROM CDR-C3G", NULL, IDE_CD_FLAG_SANYO_3CD }, + { "CD-ROM CDR_C36", NULL, IDE_CD_FLAG_SANYO_3CD }, + /* Stingray 8X CD-ROM. */ + { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12}, + /* + * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length + * mode sense page capabilities size, but older drives break. + */ + { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE }, + { "WPI CDS-32X", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE }, + /* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */ + { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS }, + /* + * Some drives used by Apple don't advertise audio play + * but they do support reading TOC & audio datas. + */ + { "MATSHITADVD-ROM SR-8187", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK }, + { "MATSHITADVD-ROM SR-8186", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK }, + { "MATSHITADVD-ROM SR-8176", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK }, + { "MATSHITADVD-ROM SR-8174", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK }, + { NULL, NULL, 0 } +}; + +static unsigned int ide_cd_flags(struct hd_driveid *id) +{ + const struct cd_list_entry *cle = ide_cd_quirks_list; + + while (cle->id_model) { + if (strcmp(cle->id_model, id->model) == 0 && + (cle->id_firmware == NULL || + strstr(id->fw_rev, cle->id_firmware))) + return cle->cd_flags; + cle++; + } + + return 0; +} + static int ide_cdrom_setup (ide_drive_t *drive) { - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; + struct cdrom_info *cd = drive->driver_data; + struct cdrom_device_info *cdi = &cd->devinfo; + struct hd_driveid *id = drive->id; int nslots; blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn); @@ -3162,101 +1960,21 @@ int ide_cdrom_setup (ide_drive_t *drive) drive->special.all = 0; - CDROM_STATE_FLAGS(drive)->media_changed = 1; - CDROM_STATE_FLAGS(drive)->toc_valid = 0; - CDROM_STATE_FLAGS(drive)->door_locked = 0; + cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT | + ide_cd_flags(id); -#if NO_DOOR_LOCKING - CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; -#else - CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0; -#endif + if ((id->config & 0x0060) == 0x20) + cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT; - CDROM_CONFIG_FLAGS(drive)->drq_interrupt = ((drive->id->config & 0x0060) == 0x20); - CDROM_CONFIG_FLAGS(drive)->is_changer = 0; - CDROM_CONFIG_FLAGS(drive)->cd_r = 0; - CDROM_CONFIG_FLAGS(drive)->cd_rw = 0; - CDROM_CONFIG_FLAGS(drive)->test_write = 0; - CDROM_CONFIG_FLAGS(drive)->dvd = 0; - CDROM_CONFIG_FLAGS(drive)->dvd_r = 0; - CDROM_CONFIG_FLAGS(drive)->dvd_ram = 0; - CDROM_CONFIG_FLAGS(drive)->no_eject = 1; - CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 0; - CDROM_CONFIG_FLAGS(drive)->audio_play = 0; - CDROM_CONFIG_FLAGS(drive)->close_tray = 1; - - /* limit transfer size per interrupt. */ - CDROM_CONFIG_FLAGS(drive)->limit_nframes = 0; - /* a testament to the nice quality of Samsung drives... */ - if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430")) - CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432")) - CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; - /* the 3231 model does not support the SET_CD_SPEED command */ - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231")) - cdi->mask |= CDC_SELECT_SPEED; - -#if ! STANDARD_ATAPI - /* by default Sanyo 3 CD changer support is turned off and - ATAPI Rev 2.2+ standard support for CD changers is used */ - cdi->sanyo_slot = 0; - - CDROM_CONFIG_FLAGS(drive)->nec260 = 0; - CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 0; - CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 0; - CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 0; - CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 0; - - if (strcmp (drive->id->model, "V003S0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 300. - Some versions of this drive like to talk BCD. */ - CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; - } - - else if (strcmp (drive->id->model, "V006E0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 600 ESD. */ - CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1; - } - else if (strcmp(drive->id->model, "NEC CD-ROM DRIVE:260") == 0 && - strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */ - /* Old NEC260 (not R). - This drive was released before the 1.2 version - of the spec. */ - CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->nec260 = 1; - } - else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 && - strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */ - /* Wearnes */ - CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; - } - /* Sanyo 3 CD changer uses a non-standard command - for CD changing */ - else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) { - /* uses CD in slot 0 when value is set to 3 */ - cdi->sanyo_slot = 3; - } -#endif /* not STANDARD_ATAPI */ - - info->toc = NULL; - info->buffer = NULL; - info->sector_buffered = 0; - info->nsectors_buffered = 0; - info->changer_info = NULL; - info->last_block = 0; - info->start_seek = 0; + if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) && + id->fw_rev[4] == '1' && id->fw_rev[6] <= '2') + cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD | + IDE_CD_FLAG_TOCADDR_AS_BCD); + else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) && + id->fw_rev[4] == '1' && id->fw_rev[6] <= '2') + cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD; + else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD) + cdi->sanyo_slot = 3; /* 3 => use CD in slot 0 */ nslots = ide_cdrom_probe_capabilities (drive); @@ -3271,7 +1989,7 @@ int ide_cdrom_setup (ide_drive_t *drive) if (ide_cdrom_register(drive, nslots)) { printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); - info->devinfo.handle = NULL; + cd->devinfo.handle = NULL; return 1; } ide_cdrom_add_settings(drive); @@ -3311,7 +2029,6 @@ static void ide_cd_release(struct kref *kref) kfree(info->buffer); kfree(info->toc); - kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom(devinfo)) printk(KERN_ERR "%s: %s failed to unregister device from the cdrom " "driver.\n", __FUNCTION__, drive->name); @@ -3467,7 +2184,9 @@ static int idecd_revalidate_disk(struct gendisk *disk) { struct cdrom_info *info = ide_cd_g(disk); struct request_sense sense; - cdrom_read_toc(info->drive, &sense); + + ide_cd_read_toc(info->drive, &sense); + return 0; } @@ -3537,19 +2256,12 @@ static int ide_cd_probe(ide_drive_t *drive) g->driverfs_dev = &drive->gendev; g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { - struct cdrom_device_info *devinfo = &info->devinfo; ide_proc_unregister_driver(drive, &ide_cdrom_driver); - kfree(info->buffer); - kfree(info->toc); - kfree(info->changer_info); - if (devinfo->handle == drive && unregister_cdrom(devinfo)) - printk (KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree(info); - drive->driver_data = NULL; + ide_cd_release(&info->kref); goto failed; } - cdrom_read_toc(drive, &sense); + ide_cd_read_toc(drive, &sense); g->fops = &idecd_ops; g->flags |= GENHD_FL_REMOVABLE; add_disk(g); @@ -3572,6 +2284,7 @@ static int __init ide_cdrom_init(void) } MODULE_ALIAS("ide:*m-cdrom*"); +MODULE_ALIAS("ide-cd"); module_init(ide_cdrom_init); module_exit(ide_cdrom_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 228b29c5d2e..22e3751a681 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/ide_cd.h - * * Copyright (C) 1996-98 Erik Andersen * Copyright (C) 1998-2000 Jens Axboe */ @@ -10,31 +8,6 @@ #include <linux/cdrom.h> #include <asm/byteorder.h> -/* Turn this on to have the driver print out the meanings of the - ATAPI error codes. This will use up additional kernel-space - memory, though. */ - -#ifndef VERBOSE_IDE_CD_ERRORS -#define VERBOSE_IDE_CD_ERRORS 1 -#endif - - -/* Turning this on will remove code to work around various nonstandard - ATAPI implementations. If you know your drive follows the standard, - this will give you a slightly smaller kernel. */ - -#ifndef STANDARD_ATAPI -#define STANDARD_ATAPI 0 -#endif - - -/* Turning this on will disable the door-locking functionality. - This is apparently needed for supermount. */ - -#ifndef NO_DOOR_LOCKING -#define NO_DOOR_LOCKING 0 -#endif - /* * typical timeout for packet command */ @@ -49,67 +22,47 @@ #endif #define SECTORS_PER_FRAME (CD_FRAMESIZE >> SECTOR_BITS) #define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32) -#define SECTORS_BUFFER (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -#define SECTORS_MAX (131072 >> SECTOR_BITS) - -#define BLOCKS_PER_FRAME (CD_FRAMESIZE / BLOCK_SIZE) - -/* special command codes for strategy routine. */ -#define PACKET_COMMAND 4315 -#define REQUEST_SENSE_COMMAND 4316 -#define RESET_DRIVE_COMMAND 4317 - - -/* Configuration flags. These describe the capabilities of the drive. - They generally do not change after initialization, unless we learn - more about the drive from stuff failing. */ -struct ide_cd_config_flags { - __u8 drq_interrupt : 1; /* Device sends an interrupt when ready - for a packet command. */ - __u8 no_doorlock : 1; /* Drive cannot lock the door. */ - __u8 no_eject : 1; /* Drive cannot eject the disc. */ - __u8 nec260 : 1; /* Drive is a pre-1.2 NEC 260 drive. */ - __u8 playmsf_as_bcd : 1; /* PLAYMSF command takes BCD args. */ - __u8 tocaddr_as_bcd : 1; /* TOC addresses are in BCD. */ - __u8 toctracks_as_bcd : 1; /* TOC track numbers are in BCD. */ - __u8 subchan_as_bcd : 1; /* Subchannel info is in BCD. */ - __u8 is_changer : 1; /* Drive is a changer. */ - __u8 cd_r : 1; /* Drive can write to CD-R media . */ - __u8 cd_rw : 1; /* Drive can write to CD-R/W media . */ - __u8 dvd : 1; /* Drive is a DVD-ROM */ - __u8 dvd_r : 1; /* Drive can write DVD-R */ - __u8 dvd_ram : 1; /* Drive can write DVD-RAM */ - __u8 ram : 1; /* generic WRITE (dvd-ram/mrw) */ - __u8 test_write : 1; /* Drive can fake writes */ - __u8 supp_disc_present : 1; /* Changer can report exact contents - of slots. */ - __u8 limit_nframes : 1; /* Drive does not provide data in - multiples of SECTOR_SIZE when more - than one interrupt is needed. */ - __u8 seeking : 1; /* Seeking in progress */ - __u8 audio_play : 1; /* can do audio related commands */ - __u8 close_tray : 1; /* can close the tray */ - __u8 writing : 1; /* pseudo write in progress */ - __u8 mo_drive : 1; /* drive is an MO device */ - __u8 reserved : 2; - byte max_speed; /* Max speed of the drive */ -}; -#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags)) - -/* State flags. These give information about the current state of the - drive, and will change during normal operation. */ -struct ide_cd_state_flags { - __u8 media_changed : 1; /* Driver has noticed a media change. */ - __u8 toc_valid : 1; /* Saved TOC information is current. */ - __u8 door_locked : 1; /* We think that the drive door is locked. */ - __u8 writing : 1; /* the drive is currently writing */ - __u8 reserved : 4; - byte current_speed; /* Current speed of the drive */ +/* Capabilities Page size including 8 bytes of Mode Page Header */ +#define ATAPI_CAPABILITIES_PAGE_SIZE (8 + 20) +#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE 4 + +enum { + /* Device sends an interrupt when ready for a packet command. */ + IDE_CD_FLAG_DRQ_INTERRUPT = (1 << 0), + /* Drive cannot lock the door. */ + IDE_CD_FLAG_NO_DOORLOCK = (1 << 1), + /* Drive cannot eject the disc. */ + IDE_CD_FLAG_NO_EJECT = (1 << 2), + /* Drive is a pre ATAPI 1.2 drive. */ + IDE_CD_FLAG_PRE_ATAPI12 = (1 << 3), + /* TOC addresses are in BCD. */ + IDE_CD_FLAG_TOCADDR_AS_BCD = (1 << 4), + /* TOC track numbers are in BCD. */ + IDE_CD_FLAG_TOCTRACKS_AS_BCD = (1 << 5), + /* + * Drive does not provide data in multiples of SECTOR_SIZE + * when more than one interrupt is needed. + */ + IDE_CD_FLAG_LIMIT_NFRAMES = (1 << 6), + /* Seeking in progress. */ + IDE_CD_FLAG_SEEKING = (1 << 7), + /* Driver has noticed a media change. */ + IDE_CD_FLAG_MEDIA_CHANGED = (1 << 8), + /* Saved TOC information is current. */ + IDE_CD_FLAG_TOC_VALID = (1 << 9), + /* We think that the drive door is locked. */ + IDE_CD_FLAG_DOOR_LOCKED = (1 << 10), + /* SET_CD_SPEED command is unsupported. */ + IDE_CD_FLAG_NO_SPEED_SELECT = (1 << 11), + IDE_CD_FLAG_VERTOS_300_SSD = (1 << 12), + IDE_CD_FLAG_VERTOS_600_ESD = (1 << 13), + IDE_CD_FLAG_SANYO_3CD = (1 << 14), + IDE_CD_FLAG_FULL_CAPS_PAGE = (1 << 15), + IDE_CD_FLAG_PLAY_AUDIO_OK = (1 << 16), + IDE_CD_FLAG_LE_SPEED_FIELDS = (1 << 17), }; -#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags)) - /* Structure of a MSF cdrom address. */ struct atapi_msf { byte reserved; @@ -154,310 +107,6 @@ struct atapi_toc { /* One extra for the leadout. */ }; - -/* This structure is annoyingly close to, but not identical with, - the cdrom_subchnl structure from cdrom.h. */ -struct atapi_cdrom_subchnl { - u_char acdsc_reserved; - u_char acdsc_audiostatus; - u_short acdsc_length; - u_char acdsc_format; - -#if defined(__BIG_ENDIAN_BITFIELD) - u_char acdsc_ctrl: 4; - u_char acdsc_adr: 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - u_char acdsc_adr: 4; - u_char acdsc_ctrl: 4; -#else -#error "Please fix <asm/byteorder.h>" -#endif - u_char acdsc_trk; - u_char acdsc_ind; - union { - struct atapi_msf msf; - int lba; - } acdsc_absaddr; - union { - struct atapi_msf msf; - int lba; - } acdsc_reladdr; -}; - - - -/* This should probably go into cdrom.h along with the other - * generic stuff now in the Mt. Fuji spec. - */ -struct atapi_capabilities_page { - struct mode_page_header header; -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 parameters_saveable : 1; - __u8 reserved1 : 1; - __u8 page_code : 6; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 page_code : 6; - __u8 reserved1 : 1; - __u8 parameters_saveable : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - - byte page_length; - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved2 : 2; - /* Drive supports reading of DVD-RAM discs */ - __u8 dvd_ram_read : 1; - /* Drive supports reading of DVD-R discs */ - __u8 dvd_r_read : 1; - /* Drive supports reading of DVD-ROM discs */ - __u8 dvd_rom : 1; - /* Drive supports reading CD-R discs with addressing method 2 */ - __u8 method2 : 1; /* reserved in 1.2 */ - /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_read : 1; /* reserved in 1.2 */ - /* Drive supports read from CD-R discs (orange book, part II) */ - __u8 cd_r_read : 1; /* reserved in 1.2 */ -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive supports read from CD-R discs (orange book, part II) */ - __u8 cd_r_read : 1; /* reserved in 1.2 */ - /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_read : 1; /* reserved in 1.2 */ - /* Drive supports reading CD-R discs with addressing method 2 */ - __u8 method2 : 1; - /* Drive supports reading of DVD-ROM discs */ - __u8 dvd_rom : 1; - /* Drive supports reading of DVD-R discs */ - __u8 dvd_r_read : 1; - /* Drive supports reading of DVD-RAM discs */ - __u8 dvd_ram_read : 1; - __u8 reserved2 : 2; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved3 : 2; - /* Drive can write DVD-RAM discs */ - __u8 dvd_ram_write : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; - __u8 reserved3a : 1; - /* Drive can fake writes */ - __u8 test_write : 1; - /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_write : 1; /* reserved in 1.2 */ - /* Drive supports write to CD-R discs (orange book, part II) */ - __u8 cd_r_write : 1; /* reserved in 1.2 */ -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive can write to CD-R discs (orange book, part II) */ - __u8 cd_r_write : 1; /* reserved in 1.2 */ - /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_write : 1; /* reserved in 1.2 */ - /* Drive can fake writes */ - __u8 test_write : 1; - __u8 reserved3a : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; - /* Drive can write DVD-RAM discs */ - __u8 dvd_ram_write : 1; - __u8 reserved3 : 2; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved4 : 1; - /* Drive can read multisession discs. */ - __u8 multisession : 1; - /* Drive can read mode 2, form 2 data. */ - __u8 mode2_form2 : 1; - /* Drive can read mode 2, form 1 (XA) data. */ - __u8 mode2_form1 : 1; - /* Drive supports digital output on port 2. */ - __u8 digport2 : 1; - /* Drive supports digital output on port 1. */ - __u8 digport1 : 1; - /* Drive can deliver a composite audio/video data stream. */ - __u8 composite : 1; - /* Drive supports audio play operations. */ - __u8 audio_play : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive supports audio play operations. */ - __u8 audio_play : 1; - /* Drive can deliver a composite audio/video data stream. */ - __u8 composite : 1; - /* Drive supports digital output on port 1. */ - __u8 digport1 : 1; - /* Drive supports digital output on port 2. */ - __u8 digport2 : 1; - /* Drive can read mode 2, form 1 (XA) data. */ - __u8 mode2_form1 : 1; - /* Drive can read mode 2, form 2 data. */ - __u8 mode2_form2 : 1; - /* Drive can read multisession discs. */ - __u8 multisession : 1; - __u8 reserved4 : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved5 : 1; - /* Drive can return Media Catalog Number (UPC) info. */ - __u8 upc : 1; - /* Drive can return International Standard Recording Code info. */ - __u8 isrc : 1; - /* Drive supports C2 error pointers. */ - __u8 c2_pointers : 1; - /* R-W data will be returned deinterleaved and error corrected. */ - __u8 rw_corr : 1; - /* Subchannel reads can return combined R-W information. */ - __u8 rw_supported : 1; - /* Drive can continue a read cdda operation from a loss of streaming.*/ - __u8 cdda_accurate : 1; - /* Drive can read Red Book audio data. */ - __u8 cdda : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive can read Red Book audio data. */ - __u8 cdda : 1; - /* Drive can continue a read cdda operation from a loss of streaming.*/ - __u8 cdda_accurate : 1; - /* Subchannel reads can return combined R-W information. */ - __u8 rw_supported : 1; - /* R-W data will be returned deinterleaved and error corrected. */ - __u8 rw_corr : 1; - /* Drive supports C2 error pointers. */ - __u8 c2_pointers : 1; - /* Drive can return International Standard Recording Code info. */ - __u8 isrc : 1; - /* Drive can return Media Catalog Number (UPC) info. */ - __u8 upc : 1; - __u8 reserved5 : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - /* Drive mechanism types. */ - mechtype_t mechtype : 3; - __u8 reserved6 : 1; - /* Drive can eject a disc or changer cartridge. */ - __u8 eject : 1; - /* State of prevent/allow jumper. */ - __u8 prevent_jumper : 1; - /* Present state of door lock. */ - __u8 lock_state : 1; - /* Drive can lock the door. */ - __u8 lock : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - - /* Drive can lock the door. */ - __u8 lock : 1; - /* Present state of door lock. */ - __u8 lock_state : 1; - /* State of prevent/allow jumper. */ - __u8 prevent_jumper : 1; - /* Drive can eject a disc or changer cartridge. */ - __u8 eject : 1; - __u8 reserved6 : 1; - /* Drive mechanism types. */ - mechtype_t mechtype : 3; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved7 : 4; - /* Drive supports software slot selection. */ - __u8 sss : 1; /* reserved in 1.2 */ - /* Changer can report exact contents of slots. */ - __u8 disc_present : 1; /* reserved in 1.2 */ - /* Audio for each channel can be muted independently. */ - __u8 separate_mute : 1; - /* Audio level for each channel can be controlled independently. */ - __u8 separate_volume : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - - /* Audio level for each channel can be controlled independently. */ - __u8 separate_volume : 1; - /* Audio for each channel can be muted independently. */ - __u8 separate_mute : 1; - /* Changer can report exact contents of slots. */ - __u8 disc_present : 1; /* reserved in 1.2 */ - /* Drive supports software slot selection. */ - __u8 sss : 1; /* reserved in 1.2 */ - __u8 reserved7 : 4; -#else -#error "Please fix <asm/byteorder.h>" -#endif - - /* Note: the following four fields are returned in big-endian form. */ - /* Maximum speed (in kB/s). */ - unsigned short maxspeed; - /* Number of discrete volume levels. */ - unsigned short n_vol_levels; - /* Size of cache in drive, in kB. */ - unsigned short buffer_size; - /* Current speed (in kB/s). */ - unsigned short curspeed; - char pad[4]; -}; - - -struct atapi_mechstat_header { -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 fault : 1; - __u8 changer_state : 2; - __u8 curslot : 5; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 curslot : 5; - __u8 changer_state : 2; - __u8 fault : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 mech_state : 3; - __u8 door_open : 1; - __u8 reserved1 : 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 reserved1 : 4; - __u8 door_open : 1; - __u8 mech_state : 3; -#else -#error "Please fix <asm/byteorder.h>" -#endif - - byte curlba[3]; - byte nslots; - __u16 slot_tablelen; -}; - - -struct atapi_slot { -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 disc_present : 1; - __u8 reserved1 : 6; - __u8 change : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 change : 1; - __u8 reserved1 : 6; - __u8 disc_present : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - - byte reserved2[3]; -}; - -struct atapi_changer_info { - struct atapi_mechstat_header hdr; - struct atapi_slot slots[0]; -}; - /* Extra per-device info for cdrom drives. */ struct cdrom_info { ide_drive_t *drive; @@ -482,11 +131,11 @@ struct cdrom_info { int dma; unsigned long last_block; unsigned long start_seek; - /* Buffer to hold mechanism status and changer slot table. */ - struct atapi_changer_info *changer_info; - struct ide_cd_config_flags config_flags; - struct ide_cd_state_flags state_flags; + unsigned int cd_flags; + + u8 max_speed; /* Max speed of the drive. */ + u8 current_speed; /* Current speed of the drive. */ /* Per-device info needed by cdrom.c generic driver. */ struct cdrom_device_info devinfo; @@ -494,250 +143,30 @@ struct cdrom_info { unsigned long write_timeout; }; -/**************************************************************************** - * Descriptions of ATAPI error codes. - */ - -/* This stuff should be in cdrom.h, since it is now generic... */ - -/* ATAPI sense keys (from table 140 of ATAPI 2.6) */ -#define NO_SENSE 0x00 -#define RECOVERED_ERROR 0x01 -#define NOT_READY 0x02 -#define MEDIUM_ERROR 0x03 -#define HARDWARE_ERROR 0x04 -#define ILLEGAL_REQUEST 0x05 -#define UNIT_ATTENTION 0x06 -#define DATA_PROTECT 0x07 -#define BLANK_CHECK 0x08 -#define ABORTED_COMMAND 0x0b -#define MISCOMPARE 0x0e - - - -/* This stuff should be in cdrom.h, since it is now generic... */ -#if VERBOSE_IDE_CD_ERRORS - - /* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -static const struct { - unsigned short packet_command; - const char * const text; -} packet_command_texts[] = { - { GPCMD_TEST_UNIT_READY, "Test Unit Ready" }, - { GPCMD_REQUEST_SENSE, "Request Sense" }, - { GPCMD_FORMAT_UNIT, "Format Unit" }, - { GPCMD_INQUIRY, "Inquiry" }, - { GPCMD_START_STOP_UNIT, "Start/Stop Unit" }, - { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" }, - { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" }, - { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" }, - { GPCMD_READ_10, "Read 10" }, - { GPCMD_WRITE_10, "Write 10" }, - { GPCMD_SEEK, "Seek" }, - { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" }, - { GPCMD_VERIFY_10, "Verify 10" }, - { GPCMD_FLUSH_CACHE, "Flush Cache" }, - { GPCMD_READ_SUBCHANNEL, "Read Subchannel" }, - { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" }, - { GPCMD_READ_HEADER, "Read Header" }, - { GPCMD_PLAY_AUDIO_10, "Play Audio 10" }, - { GPCMD_GET_CONFIGURATION, "Get Configuration" }, - { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" }, - { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" }, - { GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" }, - { GPCMD_PAUSE_RESUME, "Pause/Resume" }, - { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" }, - { GPCMD_READ_DISC_INFO, "Read Disc Info" }, - { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" }, - { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" }, - { GPCMD_SEND_OPC, "Send OPC" }, - { GPCMD_MODE_SELECT_10, "Mode Select 10" }, - { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" }, - { GPCMD_MODE_SENSE_10, "Mode Sense 10" }, - { GPCMD_CLOSE_TRACK, "Close Track" }, - { GPCMD_BLANK, "Blank" }, - { GPCMD_SEND_EVENT, "Send Event" }, - { GPCMD_SEND_KEY, "Send Key" }, - { GPCMD_REPORT_KEY, "Report Key" }, - { GPCMD_LOAD_UNLOAD, "Load/Unload" }, - { GPCMD_SET_READ_AHEAD, "Set Read-ahead" }, - { GPCMD_READ_12, "Read 12" }, - { GPCMD_GET_PERFORMANCE, "Get Performance" }, - { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" }, - { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" }, - { GPCMD_SET_STREAMING, "Set Streaming" }, - { GPCMD_READ_CD_MSF, "Read CD MSF" }, - { GPCMD_SCAN, "Scan" }, - { GPCMD_SET_SPEED, "Set Speed" }, - { GPCMD_PLAY_CD, "Play CD" }, - { GPCMD_MECHANISM_STATUS, "Mechanism Status" }, - { GPCMD_READ_CD, "Read CD" }, -}; - - - -/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -static const char * const sense_key_texts[16] = { - "No sense data", - "Recovered error", - "Not ready", - "Medium error", - "Hardware error", - "Illegal request", - "Unit attention", - "Data protect", - "Blank check", - "(reserved)", - "(reserved)", - "Aborted command", - "(reserved)", - "(reserved)", - "Miscompare", - "(reserved)", -}; - -/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -static const struct { - unsigned long asc_ascq; - const char * const text; -} sense_data_texts[] = { - { 0x000000, "No additional sense information" }, - { 0x000011, "Play operation in progress" }, - { 0x000012, "Play operation paused" }, - { 0x000013, "Play operation successfully completed" }, - { 0x000014, "Play operation stopped due to error" }, - { 0x000015, "No current audio status to return" }, - { 0x010c0a, "Write error - padding blocks added" }, - { 0x011700, "Recovered data with no error correction applied" }, - { 0x011701, "Recovered data with retries" }, - { 0x011702, "Recovered data with positive head offset" }, - { 0x011703, "Recovered data with negative head offset" }, - { 0x011704, "Recovered data with retries and/or CIRC applied" }, - { 0x011705, "Recovered data using previous sector ID" }, - { 0x011800, "Recovered data with error correction applied" }, - { 0x011801, "Recovered data with error correction and retries applied"}, - { 0x011802, "Recovered data - the data was auto-reallocated" }, - { 0x011803, "Recovered data with CIRC" }, - { 0x011804, "Recovered data with L-EC" }, - { 0x015d00, - "Failure prediction threshold exceeded - Predicted logical unit failure" }, - { 0x015d01, - "Failure prediction threshold exceeded - Predicted media failure" }, - { 0x015dff, "Failure prediction threshold exceeded - False" }, - { 0x017301, "Power calibration area almost full" }, - { 0x020400, "Logical unit not ready - cause not reportable" }, - /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */ - { 0x020401, - "Logical unit not ready - in progress [sic] of becoming ready" }, - { 0x020402, "Logical unit not ready - initializing command required" }, - { 0x020403, "Logical unit not ready - manual intervention required" }, - { 0x020404, "Logical unit not ready - format in progress" }, - { 0x020407, "Logical unit not ready - operation in progress" }, - { 0x020408, "Logical unit not ready - long write in progress" }, - { 0x020600, "No reference position found (media may be upside down)" }, - { 0x023000, "Incompatible medium installed" }, - { 0x023a00, "Medium not present" }, - { 0x025300, "Media load or eject failed" }, - { 0x025700, "Unable to recover table of contents" }, - { 0x030300, "Peripheral device write fault" }, - { 0x030301, "No write current" }, - { 0x030302, "Excessive write errors" }, - { 0x030c00, "Write error" }, - { 0x030c01, "Write error - Recovered with auto reallocation" }, - { 0x030c02, "Write error - auto reallocation failed" }, - { 0x030c03, "Write error - recommend reassignment" }, - { 0x030c04, "Compression check miscompare error" }, - { 0x030c05, "Data expansion occurred during compress" }, - { 0x030c06, "Block not compressible" }, - { 0x030c07, "Write error - recovery needed" }, - { 0x030c08, "Write error - recovery failed" }, - { 0x030c09, "Write error - loss of streaming" }, - { 0x031100, "Unrecovered read error" }, - { 0x031106, "CIRC unrecovered error" }, - { 0x033101, "Format command failed" }, - { 0x033200, "No defect spare location available" }, - { 0x033201, "Defect list update failure" }, - { 0x035100, "Erase failure" }, - { 0x037200, "Session fixation error" }, - { 0x037201, "Session fixation error writin lead-in" }, - { 0x037202, "Session fixation error writin lead-out" }, - { 0x037300, "CD control error" }, - { 0x037302, "Power calibration area is full" }, - { 0x037303, "Power calibration area error" }, - { 0x037304, "Program memory area / RMA update failure" }, - { 0x037305, "Program memory area / RMA is full" }, - { 0x037306, "Program memory area / RMA is (almost) full" }, - - { 0x040200, "No seek complete" }, - { 0x040300, "Write fault" }, - { 0x040900, "Track following error" }, - { 0x040901, "Tracking servo failure" }, - { 0x040902, "Focus servo failure" }, - { 0x040903, "Spindle servo failure" }, - { 0x041500, "Random positioning error" }, - { 0x041501, "Mechanical positioning or changer error" }, - { 0x041502, "Positioning error detected by read of medium" }, - { 0x043c00, "Mechanical positioning or changer error" }, - { 0x044000, "Diagnostic failure on component (ASCQ)" }, - { 0x044400, "Internal CD/DVD logical unit failure" }, - { 0x04b600, "Media load mechanism failed" }, - { 0x051a00, "Parameter list length error" }, - { 0x052000, "Invalid command operation code" }, - { 0x052100, "Logical block address out of range" }, - { 0x052102, "Invalid address for write" }, - { 0x052400, "Invalid field in command packet" }, - { 0x052600, "Invalid field in parameter list" }, - { 0x052601, "Parameter not supported" }, - { 0x052602, "Parameter value invalid" }, - { 0x052700, "Write protected media" }, - { 0x052c00, "Command sequence error" }, - { 0x052c03, "Current program area is not empty" }, - { 0x052c04, "Current program area is empty" }, - { 0x053001, "Cannot read medium - unknown format" }, - { 0x053002, "Cannot read medium - incompatible format" }, - { 0x053900, "Saving parameters not supported" }, - { 0x054e00, "Overlapped commands attempted" }, - { 0x055302, "Medium removal prevented" }, - { 0x055500, "System resource failure" }, - { 0x056300, "End of user area encountered on this track" }, - { 0x056400, "Illegal mode for this track or incompatible medium" }, - { 0x056f00, "Copy protection key exchange failure - Authentication failure" }, - { 0x056f01, "Copy protection key exchange failure - Key not present" }, - { 0x056f02, "Copy protection key exchange failure - Key not established" }, - { 0x056f03, "Read of scrambled sector without authentication" }, - { 0x056f04, "Media region code is mismatched to logical unit" }, - { 0x056f05, "Drive region must be permanent / region reset count error" }, - { 0x057203, "Session fixation error - incomplete track in session" }, - { 0x057204, "Empty or partially written reserved track" }, - { 0x057205, "No more RZONE reservations are allowed" }, - { 0x05bf00, "Loss of streaming" }, - { 0x062800, "Not ready to ready transition, medium may have changed" }, - { 0x062900, "Power on, reset or hardware reset occurred" }, - { 0x062a00, "Parameters changed" }, - { 0x062a01, "Mode parameters changed" }, - { 0x062e00, "Insufficient time for operation" }, - { 0x063f00, "Logical unit operating conditions have changed" }, - { 0x063f01, "Microcode has been changed" }, - { 0x065a00, "Operator request or state change input (unspecified)" }, - { 0x065a01, "Operator medium removal request" }, - { 0x0bb900, "Play operation aborted" }, - - /* Here we use 0xff for the key (not a valid key) to signify - * that these can have _any_ key value associated with them... */ - { 0xff0401, "Logical unit is in process of becoming ready" }, - { 0xff0400, "Logical unit not ready, cause not reportable" }, - { 0xff0402, "Logical unit not ready, initializing command required" }, - { 0xff0403, "Logical unit not ready, manual intervention required" }, - { 0xff0500, "Logical unit does not respond to selection" }, - { 0xff0800, "Logical unit communication failure" }, - { 0xff0802, "Logical unit communication parity error" }, - { 0xff0801, "Logical unit communication time-out" }, - { 0xff2500, "Logical unit not supported" }, - { 0xff4c00, "Logical unit failed self-configuration" }, - { 0xff3e00, "Logical unit has not self-configured yet" }, -}; -#endif - +/* ide-cd_verbose.c */ +void ide_cd_log_error(const char *, struct request *, struct request_sense *); + +/* ide-cd.c functions used by ide-cd_ioctl.c */ +void ide_cd_init_rq(ide_drive_t *, struct request *); +int ide_cd_queue_pc(ide_drive_t *, struct request *); +int ide_cd_read_toc(ide_drive_t *, struct request_sense *); +int ide_cdrom_get_capabilities(ide_drive_t *, u8 *); +void ide_cdrom_update_speed(ide_drive_t *, u8 *); +int cdrom_check_status(ide_drive_t *, struct request_sense *); + +/* ide-cd_ioctl.c */ +int ide_cdrom_open_real(struct cdrom_device_info *, int); +void ide_cdrom_release_real(struct cdrom_device_info *); +int ide_cdrom_drive_status(struct cdrom_device_info *, int); +int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int); +int ide_cdrom_tray_move(struct cdrom_device_info *, int); +int ide_cdrom_lock_door(struct cdrom_device_info *, int); +int ide_cdrom_select_speed(struct cdrom_device_info *, int); +int ide_cdrom_get_last_session(struct cdrom_device_info *, + struct cdrom_multisession *); +int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *); +int ide_cdrom_reset(struct cdrom_device_info *cdi); +int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *); +int ide_cdrom_packet(struct cdrom_device_info *, struct packet_command *); #endif /* _IDE_CD_H */ diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c new file mode 100644 index 00000000000..b68284de4e8 --- /dev/null +++ b/drivers/ide/ide-cd_ioctl.c @@ -0,0 +1,475 @@ +/* + * cdrom.c IOCTLs handling for ide-cd driver. + * + * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov> + * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> + * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de> + */ + +#include <linux/kernel.h> +#include <linux/cdrom.h> +#include <linux/ide.h> +#include <scsi/scsi.h> + +#include "ide-cd.h" + +/**************************************************************************** + * Other driver requests (open, close, check media change). + */ +int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose) +{ + return 0; +} + +/* + * Close down the device. Invalidate all cached blocks. + */ +void ide_cdrom_release_real(struct cdrom_device_info *cdi) +{ + ide_drive_t *drive = cdi->handle; + struct cdrom_info *cd = drive->driver_data; + + if (!cdi->use_count) + cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID; +} + +/* + * add logic to try GET_EVENT command first to check for media and tray + * status. this should be supported by newer cd-r/w and all DVD etc + * drives + */ +int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr) +{ + ide_drive_t *drive = cdi->handle; + struct media_event_desc med; + struct request_sense sense; + int stat; + + if (slot_nr != CDSL_CURRENT) + return -EINVAL; + + stat = cdrom_check_status(drive, &sense); + if (!stat || sense.sense_key == UNIT_ATTENTION) + return CDS_DISC_OK; + + if (!cdrom_get_media_event(cdi, &med)) { + if (med.media_present) + return CDS_DISC_OK; + else if (med.door_open) + return CDS_TRAY_OPEN; + else + return CDS_NO_DISC; + } + + if (sense.sense_key == NOT_READY && sense.asc == 0x04 + && sense.ascq == 0x04) + return CDS_DISC_OK; + + /* + * If not using Mt Fuji extended media tray reports, + * just return TRAY_OPEN since ATAPI doesn't provide + * any other way to detect this... + */ + if (sense.sense_key == NOT_READY) { + if (sense.asc == 0x3a && sense.ascq == 1) + return CDS_NO_DISC; + else + return CDS_TRAY_OPEN; + } + return CDS_DRIVE_NOT_READY; +} + +int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi, + int slot_nr) +{ + ide_drive_t *drive = cdi->handle; + struct cdrom_info *cd = drive->driver_data; + int retval; + + if (slot_nr == CDSL_CURRENT) { + (void) cdrom_check_status(drive, NULL); + retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0; + cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED; + return retval; + } else { + return -EINVAL; + } +} + +/* Eject the disk if EJECTFLAG is 0. + If EJECTFLAG is 1, try to reload the disk. */ +static +int cdrom_eject(ide_drive_t *drive, int ejectflag, + struct request_sense *sense) +{ + struct cdrom_info *cd = drive->driver_data; + struct cdrom_device_info *cdi = &cd->devinfo; + struct request req; + char loej = 0x02; + + if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag) + return -EDRIVE_CANT_DO_THIS; + + /* reload fails on some drives, if the tray is locked */ + if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag) + return 0; + + ide_cd_init_rq(drive, &req); + + /* only tell drive to close tray if open, if it can do that */ + if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY)) + loej = 0; + + req.sense = sense; + req.cmd[0] = GPCMD_START_STOP_UNIT; + req.cmd[4] = loej | (ejectflag != 0); + + return ide_cd_queue_pc(drive, &req); +} + +/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ +static +int ide_cd_lockdoor(ide_drive_t *drive, int lockflag, + struct request_sense *sense) +{ + struct cdrom_info *cd = drive->driver_data; + struct request_sense my_sense; + struct request req; + int stat; + + if (sense == NULL) + sense = &my_sense; + + /* If the drive cannot lock the door, just pretend. */ + if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) { + stat = 0; + } else { + ide_cd_init_rq(drive, &req); + req.sense = sense; + req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; + req.cmd[4] = lockflag ? 1 : 0; + stat = ide_cd_queue_pc(drive, &req); + } + + /* If we got an illegal field error, the drive + probably cannot lock the door. */ + if (stat != 0 && + sense->sense_key == ILLEGAL_REQUEST && + (sense->asc == 0x24 || sense->asc == 0x20)) { + printk(KERN_ERR "%s: door locking not supported\n", + drive->name); + cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK; + stat = 0; + } + + /* no medium, that's alright. */ + if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a) + stat = 0; + + if (stat == 0) { + if (lockflag) + cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED; + else + cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED; + } + + return stat; +} + +int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position) +{ + ide_drive_t *drive = cdi->handle; + struct request_sense sense; + + if (position) { + int stat = ide_cd_lockdoor(drive, 0, &sense); + + if (stat) + return stat; + } + + return cdrom_eject(drive, !position, &sense); +} + +int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock) +{ + ide_drive_t *drive = cdi->handle; + + return ide_cd_lockdoor(drive, lock, NULL); +} + +/* + * ATAPI devices are free to select the speed you request or any slower + * rate. :-( Requesting too fast a speed will _not_ produce an error. + */ +int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed) +{ + ide_drive_t *drive = cdi->handle; + struct cdrom_info *cd = drive->driver_data; + struct request rq; + struct request_sense sense; + u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE]; + int stat; + + ide_cd_init_rq(drive, &rq); + + rq.sense = &sense; + + if (speed == 0) + speed = 0xffff; /* set to max */ + else + speed *= 177; /* Nx to kbytes/s */ + + rq.cmd[0] = GPCMD_SET_SPEED; + /* Read Drive speed in kbytes/second MSB/LSB */ + rq.cmd[2] = (speed >> 8) & 0xff; + rq.cmd[3] = speed & 0xff; + if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) != + (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) { + /* Write Drive speed in kbytes/second MSB/LSB */ + rq.cmd[4] = (speed >> 8) & 0xff; + rq.cmd[5] = speed & 0xff; + } + + stat = ide_cd_queue_pc(drive, &rq); + + if (!ide_cdrom_get_capabilities(drive, buf)) { + ide_cdrom_update_speed(drive, buf); + cdi->speed = cd->current_speed; + } + + return 0; +} + +int ide_cdrom_get_last_session(struct cdrom_device_info *cdi, + struct cdrom_multisession *ms_info) +{ + struct atapi_toc *toc; + ide_drive_t *drive = cdi->handle; + struct cdrom_info *info = drive->driver_data; + struct request_sense sense; + int ret; + + if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) { + ret = ide_cd_read_toc(drive, &sense); + if (ret) + return ret; + } + + toc = info->toc; + ms_info->addr.lba = toc->last_session_lba; + ms_info->xa_flag = toc->xa_flag; + + return 0; +} + +int ide_cdrom_get_mcn(struct cdrom_device_info *cdi, + struct cdrom_mcn *mcn_info) +{ + ide_drive_t *drive = cdi->handle; + int stat, mcnlen; + struct request rq; + char buf[24]; + + ide_cd_init_rq(drive, &rq); + + rq.data = buf; + rq.data_len = sizeof(buf); + + rq.cmd[0] = GPCMD_READ_SUBCHANNEL; + rq.cmd[1] = 2; /* MSF addressing */ + rq.cmd[2] = 0x40; /* request subQ data */ + rq.cmd[3] = 2; /* format */ + rq.cmd[8] = sizeof(buf); + + stat = ide_cd_queue_pc(drive, &rq); + if (stat) + return stat; + + mcnlen = sizeof(mcn_info->medium_catalog_number) - 1; + memcpy(mcn_info->medium_catalog_number, buf + 9, mcnlen); + mcn_info->medium_catalog_number[mcnlen] = '\0'; + + return 0; +} + +int ide_cdrom_reset(struct cdrom_device_info *cdi) +{ + ide_drive_t *drive = cdi->handle; + struct cdrom_info *cd = drive->driver_data; + struct request_sense sense; + struct request req; + int ret; + + ide_cd_init_rq(drive, &req); + req.cmd_type = REQ_TYPE_SPECIAL; + req.cmd_flags = REQ_QUIET; + ret = ide_do_drive_cmd(drive, &req, ide_wait); + + /* + * A reset will unlock the door. If it was previously locked, + * lock it again. + */ + if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) + (void)ide_cd_lockdoor(drive, 1, &sense); + + return ret; +} + +static int ide_cd_get_toc_entry(ide_drive_t *drive, int track, + struct atapi_toc_entry **ent) +{ + struct cdrom_info *info = drive->driver_data; + struct atapi_toc *toc = info->toc; + int ntracks; + + /* + * don't serve cached data, if the toc isn't valid + */ + if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0) + return -EINVAL; + + /* Check validity of requested track number. */ + ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; + + if (toc->hdr.first_track == CDROM_LEADOUT) + ntracks = 0; + + if (track == CDROM_LEADOUT) + *ent = &toc->ent[ntracks]; + else if (track < toc->hdr.first_track || track > toc->hdr.last_track) + return -EINVAL; + else + *ent = &toc->ent[track - toc->hdr.first_track]; + + return 0; +} + +static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg) +{ + struct cdrom_ti *ti = arg; + struct atapi_toc_entry *first_toc, *last_toc; + unsigned long lba_start, lba_end; + int stat; + struct request rq; + struct request_sense sense; + + stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc); + if (stat) + return stat; + + stat = ide_cd_get_toc_entry(drive, ti->cdti_trk1, &last_toc); + if (stat) + return stat; + + if (ti->cdti_trk1 != CDROM_LEADOUT) + ++last_toc; + lba_start = first_toc->addr.lba; + lba_end = last_toc->addr.lba; + + if (lba_end <= lba_start) + return -EINVAL; + + ide_cd_init_rq(drive, &rq); + + rq.sense = &sense; + rq.cmd[0] = GPCMD_PLAY_AUDIO_MSF; + lba_to_msf(lba_start, &rq.cmd[3], &rq.cmd[4], &rq.cmd[5]); + lba_to_msf(lba_end - 1, &rq.cmd[6], &rq.cmd[7], &rq.cmd[8]); + + return ide_cd_queue_pc(drive, &rq); +} + +static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg) +{ + struct cdrom_info *cd = drive->driver_data; + struct cdrom_tochdr *tochdr = arg; + struct atapi_toc *toc; + int stat; + + /* Make sure our saved TOC is valid. */ + stat = ide_cd_read_toc(drive, NULL); + if (stat) + return stat; + + toc = cd->toc; + tochdr->cdth_trk0 = toc->hdr.first_track; + tochdr->cdth_trk1 = toc->hdr.last_track; + + return 0; +} + +static int ide_cd_read_tocentry(ide_drive_t *drive, void *arg) +{ + struct cdrom_tocentry *tocentry = arg; + struct atapi_toc_entry *toce; + int stat; + + stat = ide_cd_get_toc_entry(drive, tocentry->cdte_track, &toce); + if (stat) + return stat; + + tocentry->cdte_ctrl = toce->control; + tocentry->cdte_adr = toce->adr; + if (tocentry->cdte_format == CDROM_MSF) { + lba_to_msf(toce->addr.lba, + &tocentry->cdte_addr.msf.minute, + &tocentry->cdte_addr.msf.second, + &tocentry->cdte_addr.msf.frame); + } else + tocentry->cdte_addr.lba = toce->addr.lba; + + return 0; +} + +int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi, + unsigned int cmd, void *arg) +{ + ide_drive_t *drive = cdi->handle; + + switch (cmd) { + /* + * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since + * atapi doesn't support it + */ + case CDROMPLAYTRKIND: + return ide_cd_fake_play_trkind(drive, arg); + case CDROMREADTOCHDR: + return ide_cd_read_tochdr(drive, arg); + case CDROMREADTOCENTRY: + return ide_cd_read_tocentry(drive, arg); + default: + return -EINVAL; + } +} + +/* the generic packet interface to cdrom.c */ +int ide_cdrom_packet(struct cdrom_device_info *cdi, + struct packet_command *cgc) +{ + struct request req; + ide_drive_t *drive = cdi->handle; + + if (cgc->timeout <= 0) + cgc->timeout = ATAPI_WAIT_PC; + + /* here we queue the commands from the uniform CD-ROM + layer. the packet must be complete, as we do not + touch it at all. */ + ide_cd_init_rq(drive, &req); + memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE); + if (cgc->sense) + memset(cgc->sense, 0, sizeof(struct request_sense)); + req.data = cgc->buffer; + req.data_len = cgc->buflen; + req.timeout = cgc->timeout; + + if (cgc->quiet) + req.cmd_flags |= REQ_QUIET; + + req.sense = cgc->sense; + cgc->stat = ide_cd_queue_pc(drive, &req); + if (!cgc->stat) + cgc->buflen -= req.data_len; + return cgc->stat; +} diff --git a/drivers/ide/ide-cd_verbose.c b/drivers/ide/ide-cd_verbose.c new file mode 100644 index 00000000000..6ed7ca07133 --- /dev/null +++ b/drivers/ide/ide-cd_verbose.c @@ -0,0 +1,359 @@ +/* + * Verbose error logging for ATAPI CD/DVD devices. + * + * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov> + * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> + * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de> + */ + +#include <linux/kernel.h> +#include <linux/blkdev.h> +#include <linux/cdrom.h> +#include <scsi/scsi.h> + +#ifndef CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS +void ide_cd_log_error(const char *name, struct request *failed_command, + struct request_sense *sense) +{ + /* Suppress printing unit attention and `in progress of becoming ready' + errors when we're not being verbose. */ + if (sense->sense_key == UNIT_ATTENTION || + (sense->sense_key == NOT_READY && (sense->asc == 4 || + sense->asc == 0x3a))) + return; + + printk(KERN_ERR "%s: error code: 0x%02x sense_key: 0x%02x " + "asc: 0x%02x ascq: 0x%02x\n", + name, sense->error_code, sense->sense_key, + sense->asc, sense->ascq); +} +#else +/* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +static const struct { + unsigned short packet_command; + const char * const text; +} packet_command_texts[] = { + { GPCMD_TEST_UNIT_READY, "Test Unit Ready" }, + { GPCMD_REQUEST_SENSE, "Request Sense" }, + { GPCMD_FORMAT_UNIT, "Format Unit" }, + { GPCMD_INQUIRY, "Inquiry" }, + { GPCMD_START_STOP_UNIT, "Start/Stop Unit" }, + { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" }, + { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" }, + { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" }, + { GPCMD_READ_10, "Read 10" }, + { GPCMD_WRITE_10, "Write 10" }, + { GPCMD_SEEK, "Seek" }, + { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" }, + { GPCMD_VERIFY_10, "Verify 10" }, + { GPCMD_FLUSH_CACHE, "Flush Cache" }, + { GPCMD_READ_SUBCHANNEL, "Read Subchannel" }, + { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" }, + { GPCMD_READ_HEADER, "Read Header" }, + { GPCMD_PLAY_AUDIO_10, "Play Audio 10" }, + { GPCMD_GET_CONFIGURATION, "Get Configuration" }, + { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" }, + { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" }, + { GPCMD_GET_EVENT_STATUS_NOTIFICATION, + "Get Event Status Notification" }, + { GPCMD_PAUSE_RESUME, "Pause/Resume" }, + { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" }, + { GPCMD_READ_DISC_INFO, "Read Disc Info" }, + { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" }, + { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" }, + { GPCMD_SEND_OPC, "Send OPC" }, + { GPCMD_MODE_SELECT_10, "Mode Select 10" }, + { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" }, + { GPCMD_MODE_SENSE_10, "Mode Sense 10" }, + { GPCMD_CLOSE_TRACK, "Close Track" }, + { GPCMD_BLANK, "Blank" }, + { GPCMD_SEND_EVENT, "Send Event" }, + { GPCMD_SEND_KEY, "Send Key" }, + { GPCMD_REPORT_KEY, "Report Key" }, + { GPCMD_LOAD_UNLOAD, "Load/Unload" }, + { GPCMD_SET_READ_AHEAD, "Set Read-ahead" }, + { GPCMD_READ_12, "Read 12" }, + { GPCMD_GET_PERFORMANCE, "Get Performance" }, + { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" }, + { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" }, + { GPCMD_SET_STREAMING, "Set Streaming" }, + { GPCMD_READ_CD_MSF, "Read CD MSF" }, + { GPCMD_SCAN, "Scan" }, + { GPCMD_SET_SPEED, "Set Speed" }, + { GPCMD_PLAY_CD, "Play CD" }, + { GPCMD_MECHANISM_STATUS, "Mechanism Status" }, + { GPCMD_READ_CD, "Read CD" }, +}; + +/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +static const char * const sense_key_texts[16] = { + "No sense data", + "Recovered error", + "Not ready", + "Medium error", + "Hardware error", + "Illegal request", + "Unit attention", + "Data protect", + "Blank check", + "(reserved)", + "(reserved)", + "Aborted command", + "(reserved)", + "(reserved)", + "Miscompare", + "(reserved)", +}; + +/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +static const struct { + unsigned long asc_ascq; + const char * const text; +} sense_data_texts[] = { + { 0x000000, "No additional sense information" }, + { 0x000011, "Play operation in progress" }, + { 0x000012, "Play operation paused" }, + { 0x000013, "Play operation successfully completed" }, + { 0x000014, "Play operation stopped due to error" }, + { 0x000015, "No current audio status to return" }, + { 0x010c0a, "Write error - padding blocks added" }, + { 0x011700, "Recovered data with no error correction applied" }, + { 0x011701, "Recovered data with retries" }, + { 0x011702, "Recovered data with positive head offset" }, + { 0x011703, "Recovered data with negative head offset" }, + { 0x011704, "Recovered data with retries and/or CIRC applied" }, + { 0x011705, "Recovered data using previous sector ID" }, + { 0x011800, "Recovered data with error correction applied" }, + { 0x011801, "Recovered data with error correction and retries applied"}, + { 0x011802, "Recovered data - the data was auto-reallocated" }, + { 0x011803, "Recovered data with CIRC" }, + { 0x011804, "Recovered data with L-EC" }, + { 0x015d00, "Failure prediction threshold exceeded" + " - Predicted logical unit failure" }, + { 0x015d01, "Failure prediction threshold exceeded" + " - Predicted media failure" }, + { 0x015dff, "Failure prediction threshold exceeded - False" }, + { 0x017301, "Power calibration area almost full" }, + { 0x020400, "Logical unit not ready - cause not reportable" }, + /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */ + { 0x020401, "Logical unit not ready" + " - in progress [sic] of becoming ready" }, + { 0x020402, "Logical unit not ready - initializing command required" }, + { 0x020403, "Logical unit not ready - manual intervention required" }, + { 0x020404, "Logical unit not ready - format in progress" }, + { 0x020407, "Logical unit not ready - operation in progress" }, + { 0x020408, "Logical unit not ready - long write in progress" }, + { 0x020600, "No reference position found (media may be upside down)" }, + { 0x023000, "Incompatible medium installed" }, + { 0x023a00, "Medium not present" }, + { 0x025300, "Media load or eject failed" }, + { 0x025700, "Unable to recover table of contents" }, + { 0x030300, "Peripheral device write fault" }, + { 0x030301, "No write current" }, + { 0x030302, "Excessive write errors" }, + { 0x030c00, "Write error" }, + { 0x030c01, "Write error - Recovered with auto reallocation" }, + { 0x030c02, "Write error - auto reallocation failed" }, + { 0x030c03, "Write error - recommend reassignment" }, + { 0x030c04, "Compression check miscompare error" }, + { 0x030c05, "Data expansion occurred during compress" }, + { 0x030c06, "Block not compressible" }, + { 0x030c07, "Write error - recovery needed" }, + { 0x030c08, "Write error - recovery failed" }, + { 0x030c09, "Write error - loss of streaming" }, + { 0x031100, "Unrecovered read error" }, + { 0x031106, "CIRC unrecovered error" }, + { 0x033101, "Format command failed" }, + { 0x033200, "No defect spare location available" }, + { 0x033201, "Defect list update failure" }, + { 0x035100, "Erase failure" }, + { 0x037200, "Session fixation error" }, + { 0x037201, "Session fixation error writin lead-in" }, + { 0x037202, "Session fixation error writin lead-out" }, + { 0x037300, "CD control error" }, + { 0x037302, "Power calibration area is full" }, + { 0x037303, "Power calibration area error" }, + { 0x037304, "Program memory area / RMA update failure" }, + { 0x037305, "Program memory area / RMA is full" }, + { 0x037306, "Program memory area / RMA is (almost) full" }, + { 0x040200, "No seek complete" }, + { 0x040300, "Write fault" }, + { 0x040900, "Track following error" }, + { 0x040901, "Tracking servo failure" }, + { 0x040902, "Focus servo failure" }, + { 0x040903, "Spindle servo failure" }, + { 0x041500, "Random positioning error" }, + { 0x041501, "Mechanical positioning or changer error" }, + { 0x041502, "Positioning error detected by read of medium" }, + { 0x043c00, "Mechanical positioning or changer error" }, + { 0x044000, "Diagnostic failure on component (ASCQ)" }, + { 0x044400, "Internal CD/DVD logical unit failure" }, + { 0x04b600, "Media load mechanism failed" }, + { 0x051a00, "Parameter list length error" }, + { 0x052000, "Invalid command operation code" }, + { 0x052100, "Logical block address out of range" }, + { 0x052102, "Invalid address for write" }, + { 0x052400, "Invalid field in command packet" }, + { 0x052600, "Invalid field in parameter list" }, + { 0x052601, "Parameter not supported" }, + { 0x052602, "Parameter value invalid" }, + { 0x052700, "Write protected media" }, + { 0x052c00, "Command sequence error" }, + { 0x052c03, "Current program area is not empty" }, + { 0x052c04, "Current program area is empty" }, + { 0x053001, "Cannot read medium - unknown format" }, + { 0x053002, "Cannot read medium - incompatible format" }, + { 0x053900, "Saving parameters not supported" }, + { 0x054e00, "Overlapped commands attempted" }, + { 0x055302, "Medium removal prevented" }, + { 0x055500, "System resource failure" }, + { 0x056300, "End of user area encountered on this track" }, + { 0x056400, "Illegal mode for this track or incompatible medium" }, + { 0x056f00, "Copy protection key exchange failure" + " - Authentication failure" }, + { 0x056f01, "Copy protection key exchange failure - Key not present" }, + { 0x056f02, "Copy protection key exchange failure" + " - Key not established" }, + { 0x056f03, "Read of scrambled sector without authentication" }, + { 0x056f04, "Media region code is mismatched to logical unit" }, + { 0x056f05, "Drive region must be permanent" + " / region reset count error" }, + { 0x057203, "Session fixation error - incomplete track in session" }, + { 0x057204, "Empty or partially written reserved track" }, + { 0x057205, "No more RZONE reservations are allowed" }, + { 0x05bf00, "Loss of streaming" }, + { 0x062800, "Not ready to ready transition, medium may have changed" }, + { 0x062900, "Power on, reset or hardware reset occurred" }, + { 0x062a00, "Parameters changed" }, + { 0x062a01, "Mode parameters changed" }, + { 0x062e00, "Insufficient time for operation" }, + { 0x063f00, "Logical unit operating conditions have changed" }, + { 0x063f01, "Microcode has been changed" }, + { 0x065a00, "Operator request or state change input (unspecified)" }, + { 0x065a01, "Operator medium removal request" }, + { 0x0bb900, "Play operation aborted" }, + /* Here we use 0xff for the key (not a valid key) to signify + * that these can have _any_ key value associated with them... */ + { 0xff0401, "Logical unit is in process of becoming ready" }, + { 0xff0400, "Logical unit not ready, cause not reportable" }, + { 0xff0402, "Logical unit not ready, initializing command required" }, + { 0xff0403, "Logical unit not ready, manual intervention required" }, + { 0xff0500, "Logical unit does not respond to selection" }, + { 0xff0800, "Logical unit communication failure" }, + { 0xff0802, "Logical unit communication parity error" }, + { 0xff0801, "Logical unit communication time-out" }, + { 0xff2500, "Logical unit not supported" }, + { 0xff4c00, "Logical unit failed self-configuration" }, + { 0xff3e00, "Logical unit has not self-configured yet" }, +}; + +void ide_cd_log_error(const char *name, struct request *failed_command, + struct request_sense *sense) +{ + int i; + const char *s = "bad sense key!"; + char buf[80]; + + printk(KERN_ERR "ATAPI device %s:\n", name); + if (sense->error_code == 0x70) + printk(KERN_CONT " Error: "); + else if (sense->error_code == 0x71) + printk(" Deferred Error: "); + else if (sense->error_code == 0x7f) + printk(KERN_CONT " Vendor-specific Error: "); + else + printk(KERN_CONT " Unknown Error Type: "); + + if (sense->sense_key < ARRAY_SIZE(sense_key_texts)) + s = sense_key_texts[sense->sense_key]; + + printk(KERN_CONT "%s -- (Sense key=0x%02x)\n", s, sense->sense_key); + + if (sense->asc == 0x40) { + sprintf(buf, "Diagnostic failure on component 0x%02x", + sense->ascq); + s = buf; + } else { + int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts); + unsigned long key = (sense->sense_key << 16); + + key |= (sense->asc << 8); + if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd)) + key |= sense->ascq; + s = NULL; + + while (hi > lo) { + mid = (lo + hi) / 2; + if (sense_data_texts[mid].asc_ascq == key || + sense_data_texts[mid].asc_ascq == (0xff0000|key)) { + s = sense_data_texts[mid].text; + break; + } else if (sense_data_texts[mid].asc_ascq > key) + hi = mid; + else + lo = mid + 1; + } + } + + if (s == NULL) { + if (sense->asc > 0x80) + s = "(vendor-specific error)"; + else + s = "(reserved error code)"; + } + + printk(KERN_ERR " %s -- (asc=0x%02x, ascq=0x%02x)\n", + s, sense->asc, sense->ascq); + + if (failed_command != NULL) { + int lo = 0, mid, hi = ARRAY_SIZE(packet_command_texts); + s = NULL; + + while (hi > lo) { + mid = (lo + hi) / 2; + if (packet_command_texts[mid].packet_command == + failed_command->cmd[0]) { + s = packet_command_texts[mid].text; + break; + } + if (packet_command_texts[mid].packet_command > + failed_command->cmd[0]) + hi = mid; + else + lo = mid + 1; + } + + printk(KERN_ERR " The failed \"%s\" packet command " + "was: \n \"", s); + for (i = 0; i < sizeof(failed_command->cmd); i++) + printk(KERN_CONT "%02x ", failed_command->cmd[i]); + printk(KERN_CONT "\"\n"); + } + + /* The SKSV bit specifies validity of the sense_key_specific + * in the next two commands. It is bit 7 of the first byte. + * In the case of NOT_READY, if SKSV is set the drive can + * give us nice ETA readings. + */ + if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) { + int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100; + + printk(KERN_ERR " Command is %02d%% complete\n", + progress / 0xffff); + } + + if (sense->sense_key == ILLEGAL_REQUEST && + (sense->sks[0] & 0x80) != 0) { + printk(KERN_ERR " Error in %s byte %d", + (sense->sks[0] & 0x40) != 0 ? + "command packet" : "command data", + (sense->sks[1] << 8) + sense->sks[2]); + + if ((sense->sks[0] & 0x40) != 0) + printk(KERN_CONT " bit %d", sense->sks[0] & 0x07); + + printk(KERN_CONT "\n"); + } +} +#endif diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 00123d99527..3c69822507e 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1,10 +1,9 @@ /* - * linux/drivers/ide/ide-disk.c Version 1.18 Mar 05, 2003 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - * Copyright (C) 1998-2002 Linux ATA Development - * Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2003 Red Hat <alan@redhat.com> + * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) + * Copyright (C) 1998-2002 Linux ATA Development + * Andre Hedrick <andre@linux-ide.org> + * Copyright (C) 2003 Red Hat <alan@redhat.com> + * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz */ /* @@ -13,32 +12,6 @@ * and Andre Hedrick <andre@linux-ide.org> * * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. - * - * Version 1.00 move disk only code from ide.c to ide-disk.c - * support optional byte-swapping of all data - * Version 1.01 fix previous byte-swapping code - * Version 1.02 remove ", LBA" from drive identification msgs - * Version 1.03 fix display of id->buf_size for big-endian - * Version 1.04 add /proc configurable settings and S.M.A.R.T support - * Version 1.05 add capacity support for ATA3 >= 8GB - * Version 1.06 get boot-up messages to show full cyl count - * Version 1.07 disable door-locking if it fails - * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB, - * process of adding new ATA4 compliance. - * fixed problems in allowing fdisk to see - * the entire disk. - * Version 1.09 added increment of rq->sector in ide_multwrite - * added UDMA 3/4 reporting - * Version 1.10 request queue changes, Ultra DMA 100 - * Version 1.11 added 48-bit lba - * Version 1.12 adding taskfile io access method - * Version 1.13 added standby and flush-cache for notifier - * Version 1.14 added acoustic-wcache - * Version 1.15 convert all calls to ide_raw_taskfile - * since args will return register content. - * Version 1.16 added suspend-resume-checkpower - * Version 1.17 do flush on standby, do flush on ATA < ATA6 - * fix wcache setup. */ #define IDEDISK_VERSION "1.18" @@ -155,6 +128,50 @@ static int lba_capacity_is_ok (struct hd_driveid *id) return 0; /* lba_capacity value may be bad */ } +static const u8 ide_rw_cmds[] = { + WIN_MULTREAD, + WIN_MULTWRITE, + WIN_MULTREAD_EXT, + WIN_MULTWRITE_EXT, + WIN_READ, + WIN_WRITE, + WIN_READ_EXT, + WIN_WRITE_EXT, + WIN_READDMA, + WIN_WRITEDMA, + WIN_READDMA_EXT, + WIN_WRITEDMA_EXT, +}; + +static const u8 ide_data_phases[] = { + TASKFILE_MULTI_IN, + TASKFILE_MULTI_OUT, + TASKFILE_IN, + TASKFILE_OUT, + TASKFILE_IN_DMA, + TASKFILE_OUT_DMA, +}; + +static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma) +{ + u8 index, lba48, write; + + lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0; + write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0; + + if (dma) + index = drive->vdma ? 4 : 8; + else + index = drive->mult_count ? 0 : 4; + + task->tf.command = ide_rw_cmds[index + lba48 + write]; + + if (dma) + index = 8; /* fixup index */ + + task->data_phase = ide_data_phases[index / 2 + write]; +} + /* * __ide_do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. @@ -163,11 +180,11 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, { ide_hwif_t *hwif = HWIF(drive); unsigned int dma = drive->using_dma; + u16 nsectors = (u16)rq->nr_sectors; u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - ata_nsector_t nsectors; - - nsectors.all = (u16) rq->nr_sectors; + ide_task_t task; + struct ide_taskfile *tf = &task.tf; + ide_startstop_t rc; if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) { if (block + rq->nr_sectors > 1ULL << 28) @@ -181,121 +198,71 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, ide_map_sg(drive, rq); } - if (IDE_CONTROL_REG) - hwif->OUTB(drive->ctl, IDE_CONTROL_REG); - - /* FIXME: SELECT_MASK(drive, 0) ? */ + memset(&task, 0, sizeof(task)); + task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */ + task.tf_flags |= (IDE_TFLAG_TF | IDE_TFLAG_DEVICE); if (drive->select.b.lba) { if (lba48) { - task_ioreg_t tasklets[10]; - pr_debug("%s: LBA=0x%012llx\n", drive->name, (unsigned long long)block); - tasklets[0] = 0; - tasklets[1] = 0; - tasklets[2] = nsectors.b.low; - tasklets[3] = nsectors.b.high; - tasklets[4] = (task_ioreg_t) block; - tasklets[5] = (task_ioreg_t) (block>>8); - tasklets[6] = (task_ioreg_t) (block>>16); - tasklets[7] = (task_ioreg_t) (block>>24); - if (sizeof(block) == 4) { - tasklets[8] = (task_ioreg_t) 0; - tasklets[9] = (task_ioreg_t) 0; - } else { - tasklets[8] = (task_ioreg_t)((u64)block >> 32); - tasklets[9] = (task_ioreg_t)((u64)block >> 40); + tf->hob_nsect = (nsectors >> 8) & 0xff; + tf->hob_lbal = (u8)(block >> 24); + if (sizeof(block) != 4) { + tf->hob_lbam = (u8)((u64)block >> 32); + tf->hob_lbah = (u8)((u64)block >> 40); } -#ifdef DEBUG - printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", - drive->name, tasklets[3], tasklets[2], - tasklets[9], tasklets[8], tasklets[7], - tasklets[6], tasklets[5], tasklets[4]); -#endif - hwif->OUTB(tasklets[1], IDE_FEATURE_REG); - hwif->OUTB(tasklets[3], IDE_NSECTOR_REG); - hwif->OUTB(tasklets[7], IDE_SECTOR_REG); - hwif->OUTB(tasklets[8], IDE_LCYL_REG); - hwif->OUTB(tasklets[9], IDE_HCYL_REG); - - hwif->OUTB(tasklets[0], IDE_FEATURE_REG); - hwif->OUTB(tasklets[2], IDE_NSECTOR_REG); - hwif->OUTB(tasklets[4], IDE_SECTOR_REG); - hwif->OUTB(tasklets[5], IDE_LCYL_REG); - hwif->OUTB(tasklets[6], IDE_HCYL_REG); - hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG); + + tf->nsect = nsectors & 0xff; + tf->lbal = (u8) block; + tf->lbam = (u8)(block >> 8); + tf->lbah = (u8)(block >> 16); + + task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); } else { - hwif->OUTB(0x00, IDE_FEATURE_REG); - hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); - hwif->OUTB(block, IDE_SECTOR_REG); - hwif->OUTB(block>>=8, IDE_LCYL_REG); - hwif->OUTB(block>>=8, IDE_HCYL_REG); - hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); + tf->nsect = nsectors & 0xff; + tf->lbal = block; + tf->lbam = block >>= 8; + tf->lbah = block >>= 8; + tf->device = (block >> 8) & 0xf; } } else { unsigned int sect,head,cyl,track; track = (int)block / drive->sect; sect = (int)block % drive->sect + 1; - hwif->OUTB(sect, IDE_SECTOR_REG); head = track % drive->head; cyl = track / drive->head; pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); - hwif->OUTB(0x00, IDE_FEATURE_REG); - hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); - hwif->OUTB(cyl, IDE_LCYL_REG); - hwif->OUTB(cyl>>8, IDE_HCYL_REG); - hwif->OUTB(head|drive->select.all,IDE_SELECT_REG); + tf->nsect = nsectors & 0xff; + tf->lbal = sect; + tf->lbam = cyl; + tf->lbah = cyl >> 8; + tf->device = head; } - if (dma) { - if (!hwif->dma_setup(drive)) { - if (rq_data_dir(rq)) { - command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; - if (drive->vdma) - command = lba48 ? WIN_WRITE_EXT: WIN_WRITE; - } else { - command = lba48 ? WIN_READDMA_EXT : WIN_READDMA; - if (drive->vdma) - command = lba48 ? WIN_READ_EXT: WIN_READ; - } - hwif->dma_exec_cmd(drive, command); - hwif->dma_start(drive); - return ide_started; - } - /* fallback to PIO */ - ide_init_sg_cmd(drive, rq); - } + if (rq_data_dir(rq)) + task.tf_flags |= IDE_TFLAG_WRITE; - if (rq_data_dir(rq) == READ) { + ide_tf_set_cmd(drive, &task, dma); + if (!dma) + hwif->data_phase = task.data_phase; + task.rq = rq; - if (drive->mult_count) { - hwif->data_phase = TASKFILE_MULTI_IN; - command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD; - } else { - hwif->data_phase = TASKFILE_IN; - command = lba48 ? WIN_READ_EXT : WIN_READ; - } - - ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL); - return ide_started; - } else { - if (drive->mult_count) { - hwif->data_phase = TASKFILE_MULTI_OUT; - command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; - } else { - hwif->data_phase = TASKFILE_OUT; - command = lba48 ? WIN_WRITE_EXT : WIN_WRITE; - } + rc = do_rw_taskfile(drive, &task); - /* FIXME: ->OUTBSYNC ? */ - hwif->OUTB(command, IDE_COMMAND_REG); - - return pre_task_out_intr(drive, rq); + if (rc == ide_stopped && dma) { + /* fallback to PIO */ + task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK; + ide_tf_set_cmd(drive, &task, 0); + hwif->data_phase = task.data_phase; + ide_init_sg_cmd(drive, rq); + rc = do_rw_taskfile(drive, &task); } + + return rc; } /* @@ -333,57 +300,29 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. */ -static unsigned long idedisk_read_native_max_address(ide_drive_t *drive) +static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48) { ide_task_t args; - unsigned long addr = 0; + struct ide_taskfile *tf = &args.tf; + u64 addr = 0; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_SELECT_OFFSET] = 0x40; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; + if (lba48) + tf->command = WIN_READ_NATIVE_MAX_EXT; + else + tf->command = WIN_READ_NATIVE_MAX; + tf->device = ATA_LBA; + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + if (lba48) + args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); /* submit command request */ - ide_raw_taskfile(drive, &args, NULL); + ide_no_data_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { - addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) - | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) - | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) - | ((args.tfRegister[IDE_SECTOR_OFFSET] )); - addr++; /* since the return value is (maxlba - 1), we add 1 */ - } - return addr; -} + if ((tf->status & 0x01) == 0) + addr = ide_get_lba_addr(tf, lba48) + 1; -static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive) -{ - ide_task_t args; - unsigned long long addr = 0; - - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(ide_task_t)); - - args.tfRegister[IDE_SELECT_OFFSET] = 0x40; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; - /* submit command request */ - ide_raw_taskfile(drive, &args, NULL); - - /* if OK, compute maximum address value */ - if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { - u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) | - (args.hobRegister[IDE_LCYL_OFFSET] << 8) | - args.hobRegister[IDE_SECTOR_OFFSET]; - u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | - ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | - (args.tfRegister[IDE_SECTOR_OFFSET]); - addr = ((__u64)high << 24) | low; - addr++; /* since the return value is (maxlba - 1), we add 1 */ - } return addr; } @@ -391,67 +330,37 @@ static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive * Sets maximum virtual LBA address of the drive. * Returns new maximum virtual LBA address (> 0) or 0 on failure. */ -static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req) +static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) { ide_task_t args; - unsigned long addr_set = 0; - - addr_req--; - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); - args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff); - args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff); - args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; - /* submit command request */ - ide_raw_taskfile(drive, &args, NULL); - /* if OK, read new maximum address value */ - if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { - addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) - | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) - | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) - | ((args.tfRegister[IDE_SECTOR_OFFSET] )); - addr_set++; - } - return addr_set; -} - -static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req) -{ - ide_task_t args; - unsigned long long addr_set = 0; + struct ide_taskfile *tf = &args.tf; + u64 addr_set = 0; addr_req--; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); - args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff); - args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff); - args.tfRegister[IDE_SELECT_OFFSET] = 0x40; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT; - args.hobRegister[IDE_SECTOR_OFFSET] = (addr_req >>= 8) & 0xff; - args.hobRegister[IDE_LCYL_OFFSET] = (addr_req >>= 8) & 0xff; - args.hobRegister[IDE_HCYL_OFFSET] = (addr_req >>= 8) & 0xff; - args.hobRegister[IDE_SELECT_OFFSET] = 0x40; - args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; + tf->lbal = (addr_req >> 0) & 0xff; + tf->lbam = (addr_req >>= 8) & 0xff; + tf->lbah = (addr_req >>= 8) & 0xff; + if (lba48) { + tf->hob_lbal = (addr_req >>= 8) & 0xff; + tf->hob_lbam = (addr_req >>= 8) & 0xff; + tf->hob_lbah = (addr_req >>= 8) & 0xff; + tf->command = WIN_SET_MAX_EXT; + } else { + tf->device = (addr_req >>= 8) & 0x0f; + tf->command = WIN_SET_MAX; + } + tf->device |= ATA_LBA; + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + if (lba48) + args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); /* submit command request */ - ide_raw_taskfile(drive, &args, NULL); + ide_no_data_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { - u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) | - (args.hobRegister[IDE_LCYL_OFFSET] << 8) | - args.hobRegister[IDE_SECTOR_OFFSET]; - u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | - ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | - (args.tfRegister[IDE_SECTOR_OFFSET]); - addr_set = ((__u64)high << 24) | low; - addr_set++; - } + if ((tf->status & 0x01) == 0) + addr_set = ide_get_lba_addr(tf, lba48) + 1; + return addr_set; } @@ -497,10 +406,8 @@ static void idedisk_check_hpa(ide_drive_t *drive) int lba48 = idedisk_supports_lba48(drive->id); capacity = drive->capacity64; - if (lba48) - set_max = idedisk_read_native_max_address_ext(drive); - else - set_max = idedisk_read_native_max_address(drive); + + set_max = idedisk_read_native_max_address(drive, lba48); if (ide_in_drive_list(drive->id, hpa_list)) { /* @@ -521,10 +428,8 @@ static void idedisk_check_hpa(ide_drive_t *drive) capacity, sectors_to_MB(capacity), set_max, sectors_to_MB(set_max)); - if (lba48) - set_max = idedisk_set_max_address_ext(drive, set_max); - else - set_max = idedisk_set_max_address(drive, set_max); + set_max = idedisk_set_max_address(drive, set_max, lba48); + if (set_max) { drive->capacity64 = set_max; printk(KERN_INFO "%s: Host Protected Area disabled.\n", @@ -582,32 +487,32 @@ static sector_t idedisk_capacity (ide_drive_t *drive) static int smart_enable(ide_drive_t *drive) { ide_task_t args; + struct ide_taskfile *tf = &args.tf; memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_FEATURE_OFFSET] = SMART_ENABLE; - args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; - args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; - return ide_raw_taskfile(drive, &args, NULL); + tf->feature = SMART_ENABLE; + tf->lbam = SMART_LCYL_PASS; + tf->lbah = SMART_HCYL_PASS; + tf->command = WIN_SMART; + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + return ide_no_data_taskfile(drive, &args); } static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) { ide_task_t args; + struct ide_taskfile *tf = &args.tf; memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_FEATURE_OFFSET] = sub_cmd; - args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; - args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; - args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; - args.command_type = IDE_DRIVE_TASK_IN; - args.data_phase = TASKFILE_IN; - args.handler = &task_in_intr; + tf->feature = sub_cmd; + tf->nsect = 0x01; + tf->lbam = SMART_LCYL_PASS; + tf->lbah = SMART_HCYL_PASS; + tf->command = WIN_SMART; + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + args.data_phase = TASKFILE_IN; (void) smart_enable(drive); - return ide_raw_taskfile(drive, &args, buf); + return ide_raw_taskfile(drive, &args, buf, 1); } static int proc_idedisk_read_cache @@ -685,19 +590,20 @@ static ide_proc_entry_t idedisk_proc[] = { static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) { ide_drive_t *drive = q->queuedata; + ide_task_t task; - memset(rq->cmd, 0, sizeof(rq->cmd)); - + memset(&task, 0, sizeof(task)); if (ide_id_has_flush_cache_ext(drive->id) && (drive->capacity64 >= (1UL << 28))) - rq->cmd[0] = WIN_FLUSH_CACHE_EXT; + task.tf.command = WIN_FLUSH_CACHE_EXT; else - rq->cmd[0] = WIN_FLUSH_CACHE; + task.tf.command = WIN_FLUSH_CACHE; + task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; + task.data_phase = TASKFILE_NO_DATA; - - rq->cmd_type = REQ_TYPE_ATA_TASK; + rq->cmd_type = REQ_TYPE_ATA_TASKFILE; rq->cmd_flags |= REQ_SOFTBARRIER; - rq->buffer = rq->cmd; + rq->special = &task; } /* @@ -713,8 +619,10 @@ static int set_multcount(ide_drive_t *drive, int arg) if (drive->special.b.set_multmode) return -EBUSY; + ide_init_drive_cmd (&rq); - rq.cmd_type = REQ_TYPE_ATA_CMD; + rq.cmd_type = REQ_TYPE_ATA_TASKFILE; + drive->mult_req = arg; drive->special.b.set_multmode = 1; (void) ide_do_drive_cmd (drive, &rq, ide_wait); @@ -779,12 +687,11 @@ static int write_cache(ide_drive_t *drive, int arg) if (ide_id_has_flush_cache(drive->id)) { memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? + args.tf.feature = arg ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; - err = ide_raw_taskfile(drive, &args, NULL); + args.tf.command = WIN_SETFEATURES; + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + err = ide_no_data_taskfile(drive, &args); if (err == 0) drive->wcache = arg; } @@ -800,12 +707,11 @@ static int do_idedisk_flushcache (ide_drive_t *drive) memset(&args, 0, sizeof(ide_task_t)); if (ide_id_has_flush_cache_ext(drive->id)) - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; + args.tf.command = WIN_FLUSH_CACHE_EXT; else - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; - return ide_raw_taskfile(drive, &args, NULL); + args.tf.command = WIN_FLUSH_CACHE; + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + return ide_no_data_taskfile(drive, &args); } static int set_acoustic (ide_drive_t *drive, int arg) @@ -816,13 +722,11 @@ static int set_acoustic (ide_drive_t *drive, int arg) return -EINVAL; memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : - SETFEATURES_DIS_AAM; - args.tfRegister[IDE_NSECTOR_OFFSET] = arg; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; - ide_raw_taskfile(drive, &args, NULL); + args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM; + args.tf.nsect = arg; + args.tf.command = WIN_SETFEATURES; + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + ide_no_data_taskfile(drive, &args); drive->acoustic = arg; return 0; } @@ -858,7 +762,6 @@ static void idedisk_add_settings(ide_drive_t *drive) ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); - ide_add_setting(drive, "bswap", SETTING_READ, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount); ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); @@ -961,11 +864,8 @@ static void idedisk_setup (ide_drive_t *drive) if (id->buf_size) printk (" w/%dKiB Cache", id->buf_size/2); - printk(", CHS=%d/%d/%d", - drive->bios_cyl, drive->bios_head, drive->bios_sect); - if (drive->using_dma) - ide_dma_verbose(drive); - printk("\n"); + printk(KERN_CONT ", CHS=%d/%d/%d\n", + drive->bios_cyl, drive->bios_head, drive->bios_sect); /* write cache enabled? */ if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5))) @@ -1070,6 +970,17 @@ static ide_driver_t idedisk_driver = { #endif }; +static int idedisk_set_doorlock(ide_drive_t *drive, int on) +{ + ide_task_t task; + + memset(&task, 0, sizeof(task)); + task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK; + task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + + return ide_no_data_taskfile(drive, &task); +} + static int idedisk_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; @@ -1084,18 +995,13 @@ static int idedisk_open(struct inode *inode, struct file *filp) idkp->openers++; if (drive->removable && idkp->openers == 1) { - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; check_disk_change(inode->i_bdev); /* * Ignore the return code from door_lock, * since the open() has already succeeded, * and the door_lock is irrelevant at this point. */ - if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) + if (drive->doorlocking && idedisk_set_doorlock(drive, 1)) drive->doorlocking = 0; } return 0; @@ -1111,12 +1017,7 @@ static int idedisk_release(struct inode *inode, struct file *filp) ide_cacheflush_p(drive); if (drive->removable && idkp->openers == 1) { - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; - if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) + if (drive->doorlocking && idedisk_set_doorlock(drive, 0)) drive->doorlocking = 0; } diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 428f7a8a00b..3cf59f2c392 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -1,15 +1,13 @@ /* - * linux/drivers/ide/ide-dma.c Version 4.10 June 9, 2000 + * Copyright (C) 1995-1998 Mark Lord + * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> + * Copyright (C) 2004, 2007 Bartlomiej Zolnierkiewicz * - * Copyright (c) 1999-2000 Andre Hedrick <andre@linux-ide.org> * May be copied or modified under the terms of the GNU General Public License */ /* * Special Thanks to Mark for his Six years of work. - * - * Copyright (c) 1995-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License */ /* @@ -85,6 +83,7 @@ #include <linux/ide.h> #include <linux/delay.h> #include <linux/scatterlist.h> +#include <linux/dma-mapping.h> #include <asm/io.h> #include <asm/irq.h> @@ -130,6 +129,7 @@ static const struct drive_list_entry drive_blacklist [] = { { "_NEC DV5800A", NULL }, { "SAMSUNG CD-ROM SN-124", "N001" }, { "Seagate STT20000A", NULL }, + { "CD-ROM CDR_U200", "1.09" }, { NULL , NULL } }; @@ -152,13 +152,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive) if (!dma_stat) { struct request *rq = HWGROUP(drive)->rq; - if (rq->rq_disk) { - ide_driver_t *drv; - - drv = *(ide_driver_t **)rq->rq_disk->private_data; - drv->end_request(drive, 1, rq->nr_sectors); - } else - ide_end_request(drive, 1, rq->nr_sectors); + task_end_request(drive, rq, stat); return ide_stopped; } printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", @@ -174,16 +168,15 @@ static int ide_dma_good_drive(ide_drive_t *drive) return ide_in_drive_list(drive->id, drive_whitelist); } -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI /** * ide_build_sglist - map IDE scatter gather for DMA I/O * @drive: the drive to build the DMA table for * @rq: the request holding the sg list * - * Perform the PCI mapping magic necessary to access the source or - * target buffers of a request via PCI DMA. The lower layers of the + * Perform the DMA mapping magic necessary to access the source or + * target buffers of a request via DMA. The lower layers of the * kernel provide the necessary cache management so that we can - * operate in a portable fashion + * operate in a portable fashion. */ int ide_build_sglist(ide_drive_t *drive, struct request *rq) @@ -191,20 +184,20 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) ide_hwif_t *hwif = HWIF(drive); struct scatterlist *sg = hwif->sg_table; - BUG_ON((rq->cmd_type == REQ_TYPE_ATA_TASKFILE) && rq->nr_sectors > 256); - ide_map_sg(drive, rq); if (rq_data_dir(rq) == READ) - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; + hwif->sg_dma_direction = DMA_FROM_DEVICE; else - hwif->sg_dma_direction = PCI_DMA_TODEVICE; + hwif->sg_dma_direction = DMA_TO_DEVICE; - return pci_map_sg(hwif->pci_dev, sg, hwif->sg_nents, hwif->sg_dma_direction); + return dma_map_sg(hwif->dev, sg, hwif->sg_nents, + hwif->sg_dma_direction); } EXPORT_SYMBOL_GPL(ide_build_sglist); +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI /** * ide_build_dmatable - build IDE DMA table * @@ -289,16 +282,17 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq) *--table |= cpu_to_le32(0x80000000); return count; } + printk(KERN_ERR "%s: empty DMA table?\n", drive->name); + use_pio_instead: - pci_unmap_sg(hwif->pci_dev, - hwif->sg_table, - hwif->sg_nents, - hwif->sg_dma_direction); + ide_destroy_dmatable(drive); + return 0; /* revert to PIO for this request */ } EXPORT_SYMBOL_GPL(ide_build_dmatable); +#endif /** * ide_destroy_dmatable - clean up DMA mapping @@ -313,15 +307,15 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable); void ide_destroy_dmatable (ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; - struct scatterlist *sg = HWIF(drive)->sg_table; - int nents = HWIF(drive)->sg_nents; + ide_hwif_t *hwif = drive->hwif; - pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction); + dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents, + hwif->sg_dma_direction); } EXPORT_SYMBOL_GPL(ide_destroy_dmatable); +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI /** * config_drive_for_dma - attempt to activate IDE DMA * @drive: the drive to place in DMA mode @@ -340,7 +334,7 @@ static int config_drive_for_dma (ide_drive_t *drive) if (drive->media != ide_disk) { if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA) - return -1; + return 0; } /* @@ -407,23 +401,29 @@ static int dma_timer_expiry (ide_drive_t *drive) } /** - * ide_dma_host_off - Generic DMA kill + * ide_dma_host_set - Enable/disable DMA on a host * @drive: drive to control * - * Perform the generic IDE controller DMA off operation. This - * works for most IDE bus mastering controllers + * Enable/disable DMA on an IDE controller following generic + * bus-mastering IDE controller behaviour. */ -void ide_dma_host_off(ide_drive_t *drive) +void ide_dma_host_set(ide_drive_t *drive, int on) { ide_hwif_t *hwif = HWIF(drive); u8 unit = (drive->select.b.unit & 0x01); u8 dma_stat = hwif->INB(hwif->dma_status); - hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status); + if (on) + dma_stat |= (1 << (5 + unit)); + else + dma_stat &= ~(1 << (5 + unit)); + + hwif->OUTB(dma_stat, hwif->dma_status); } -EXPORT_SYMBOL(ide_dma_host_off); +EXPORT_SYMBOL_GPL(ide_dma_host_set); +#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ /** * ide_dma_off_quietly - Generic DMA kill @@ -437,11 +437,10 @@ void ide_dma_off_quietly(ide_drive_t *drive) drive->using_dma = 0; ide_toggle_bounce(drive, 0); - drive->hwif->dma_host_off(drive); + drive->hwif->dma_host_set(drive, 0); } EXPORT_SYMBOL(ide_dma_off_quietly); -#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ /** * ide_dma_off - disable DMA on a device @@ -454,56 +453,27 @@ EXPORT_SYMBOL(ide_dma_off_quietly); void ide_dma_off(ide_drive_t *drive) { printk(KERN_INFO "%s: DMA disabled\n", drive->name); - drive->hwif->dma_off_quietly(drive); + ide_dma_off_quietly(drive); } EXPORT_SYMBOL(ide_dma_off); -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI -/** - * ide_dma_host_on - Enable DMA on a host - * @drive: drive to enable for DMA - * - * Enable DMA on an IDE controller following generic bus mastering - * IDE controller behaviour - */ - -void ide_dma_host_on(ide_drive_t *drive) -{ - if (drive->using_dma) { - ide_hwif_t *hwif = HWIF(drive); - u8 unit = (drive->select.b.unit & 0x01); - u8 dma_stat = hwif->INB(hwif->dma_status); - - hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status); - } -} - -EXPORT_SYMBOL(ide_dma_host_on); - /** - * __ide_dma_on - Enable DMA on a device + * ide_dma_on - Enable DMA on a device * @drive: drive to enable DMA on * * Enable IDE DMA for a device on this IDE controller. */ - -int __ide_dma_on (ide_drive_t *drive) -{ - /* consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - return 1; +void ide_dma_on(ide_drive_t *drive) +{ drive->using_dma = 1; ide_toggle_bounce(drive, 1); - drive->hwif->dma_host_on(drive); - - return 0; + drive->hwif->dma_host_set(drive, 1); } -EXPORT_SYMBOL(__ide_dma_on); - +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI /** * ide_dma_setup - begin a DMA phase * @drive: target device @@ -610,12 +580,6 @@ static int __ide_dma_test_irq(ide_drive_t *drive) ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = hwif->INB(hwif->dma_status); -#if 0 /* do not set unless you know what you are doing */ - if (dma_stat & 4) { - u8 stat = hwif->INB(IDE_STATUS_REG); - hwif->OUTB(hwif->dma_status, dma_stat & 0xE4); - } -#endif /* return 1 if INTR asserted */ if ((dma_stat & 4) == 4) return 1; @@ -752,15 +716,19 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) mode = XFER_MW_DMA_1; } - printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); + mode = min(mode, req_mode); + + printk(KERN_INFO "%s: %s mode selected\n", drive->name, + mode ? ide_xfer_verbose(mode) : "no DMA"); - return min(mode, req_mode); + return mode; } EXPORT_SYMBOL_GPL(ide_find_dma_mode); static int ide_tune_dma(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; u8 speed; if (noautodma || drive->nodma || (drive->id->capability & 1) == 0) @@ -770,15 +738,24 @@ static int ide_tune_dma(ide_drive_t *drive) if (__ide_dma_bad_drive(drive)) return 0; - if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) + if (ide_id_dma_bug(drive)) + return 0; + + if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) return config_drive_for_dma(drive); speed = ide_max_dma_mode(drive); - if (!speed) - return 0; + if (!speed) { + /* is this really correct/needed? */ + if ((hwif->host_flags & IDE_HFLAG_CY82C693) && + ide_dma_good_drive(drive)) + return 1; + else + return 0; + } - if (drive->hwif->host_flags & IDE_HFLAG_NO_SET_MODE) + if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) return 0; if (ide_set_dma_mode(drive, speed)) @@ -804,79 +781,62 @@ static int ide_dma_check(ide_drive_t *drive) return vdma ? 0 : -1; } -void ide_dma_verbose(ide_drive_t *drive) +int ide_id_dma_bug(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; if (id->field_valid & 4) { if ((id->dma_ultra >> 8) && (id->dma_mword >> 8)) - goto bug_dma_off; - if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) { - if (((id->dma_ultra >> 11) & 0x1F) && - eighty_ninty_three(drive)) { - if ((id->dma_ultra >> 15) & 1) { - printk(", UDMA(mode 7)"); - } else if ((id->dma_ultra >> 14) & 1) { - printk(", UDMA(133)"); - } else if ((id->dma_ultra >> 13) & 1) { - printk(", UDMA(100)"); - } else if ((id->dma_ultra >> 12) & 1) { - printk(", UDMA(66)"); - } else if ((id->dma_ultra >> 11) & 1) { - printk(", UDMA(44)"); - } else - goto mode_two; - } else { - mode_two: - if ((id->dma_ultra >> 10) & 1) { - printk(", UDMA(33)"); - } else if ((id->dma_ultra >> 9) & 1) { - printk(", UDMA(25)"); - } else if ((id->dma_ultra >> 8) & 1) { - printk(", UDMA(16)"); - } - } - } else { - printk(", (U)DMA"); /* Can be BIOS-enabled! */ - } + goto err_out; } else if (id->field_valid & 2) { if ((id->dma_mword >> 8) && (id->dma_1word >> 8)) - goto bug_dma_off; - printk(", DMA"); - } else if (id->field_valid & 1) { - goto bug_dma_off; + goto err_out; } - return; -bug_dma_off: - printk(", BUG DMA OFF"); - hwif->dma_off_quietly(drive); - return; + return 0; +err_out: + printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); + return 1; } -EXPORT_SYMBOL(ide_dma_verbose); - int ide_set_dma(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; int rc; + /* + * Force DMAing for the beginning of the check. + * Some chipsets appear to do interesting + * things, if not checked and cleared. + * PARANOIA!!! + */ + ide_dma_off_quietly(drive); + rc = ide_dma_check(drive); + if (rc) + return rc; - switch(rc) { - case -1: /* DMA needs to be disabled */ - hwif->dma_off_quietly(drive); - return -1; - case 0: /* DMA needs to be enabled */ - return hwif->ide_dma_on(drive); - case 1: /* DMA setting cannot be changed */ - break; - default: - BUG(); - break; - } + ide_dma_on(drive); + + return 0; +} + +void ide_check_dma_crc(ide_drive_t *drive) +{ + u8 mode; - return rc; + ide_dma_off_quietly(drive); + drive->crc_count = 0; + mode = drive->current_speed; + /* + * Don't try non Ultra-DMA modes without iCRC's. Force the + * device to PIO and make the user enable SWDMA/MWDMA modes. + */ + if (mode > XFER_UDMA_0 && mode <= XFER_UDMA_7) + mode--; + else + mode = XFER_PIO_4; + ide_set_xfer_rate(drive, mode); + if (drive->current_speed >= XFER_SW_DMA_0) + ide_dma_on(drive); } #ifdef CONFIG_BLK_DEV_IDEDMA_PCI @@ -904,10 +864,10 @@ EXPORT_SYMBOL(ide_dma_timeout); static void ide_release_dma_engine(ide_hwif_t *hwif) { if (hwif->dmatable_cpu) { - pci_free_consistent(hwif->pci_dev, - PRD_ENTRIES * PRD_BYTES, - hwif->dmatable_cpu, - hwif->dmatable_dma); + struct pci_dev *pdev = to_pci_dev(hwif->dev); + + pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES, + hwif->dmatable_cpu, hwif->dmatable_dma); hwif->dmatable_cpu = NULL; } } @@ -935,7 +895,9 @@ int ide_release_dma(ide_hwif_t *hwif) static int ide_allocate_dma_engine(ide_hwif_t *hwif) { - hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, + struct pci_dev *pdev = to_pci_dev(hwif->dev); + + hwif->dmatable_cpu = pci_alloc_consistent(pdev, PRD_ENTRIES * PRD_BYTES, &hwif->dmatable_dma); @@ -948,19 +910,19 @@ static int ide_allocate_dma_engine(ide_hwif_t *hwif) return 1; } -static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports) +static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base) { printk(KERN_INFO " %s: MMIO-DMA ", hwif->name); return 0; } -static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports) +static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base) { printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx", - hwif->name, base, base + ports - 1); + hwif->name, base, base + 7); - if (!request_region(base, ports, hwif->name)) { + if (!request_region(base, 8, hwif->name)) { printk(" -- Error, ports in use.\n"); return 1; } @@ -972,7 +934,7 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port if (!request_region(hwif->extra_base, hwif->cds->extra, hwif->cds->name)) { printk(" -- Error, extra ports in use.\n"); - release_region(base, ports); + release_region(base, 8); return 1; } hwif->extra_ports = hwif->cds->extra; @@ -982,17 +944,19 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port return 0; } -static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports) +static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base) { if (hwif->mmio) - return ide_mapped_mmio_dma(hwif, base,ports); + return ide_mapped_mmio_dma(hwif, base); - return ide_iomio_dma(hwif, base, ports); + return ide_iomio_dma(hwif, base); } -void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports) +void ide_setup_dma(ide_hwif_t *hwif, unsigned long base) { - if (ide_dma_iobase(hwif, base, num_ports)) + u8 dma_stat; + + if (ide_dma_iobase(hwif, base)) return; if (ide_allocate_dma_engine(hwif)) { @@ -1002,30 +966,19 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports) hwif->dma_base = base; - if (hwif->mate) - hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base; - else - hwif->dma_master = base; - - if (!(hwif->dma_command)) - hwif->dma_command = hwif->dma_base; - if (!(hwif->dma_vendor1)) - hwif->dma_vendor1 = (hwif->dma_base + 1); - if (!(hwif->dma_status)) - hwif->dma_status = (hwif->dma_base + 2); - if (!(hwif->dma_vendor3)) - hwif->dma_vendor3 = (hwif->dma_base + 3); - if (!(hwif->dma_prdtable)) - hwif->dma_prdtable = (hwif->dma_base + 4); - - if (!hwif->dma_off_quietly) - hwif->dma_off_quietly = &ide_dma_off_quietly; - if (!hwif->dma_host_off) - hwif->dma_host_off = &ide_dma_host_off; - if (!hwif->ide_dma_on) - hwif->ide_dma_on = &__ide_dma_on; - if (!hwif->dma_host_on) - hwif->dma_host_on = &ide_dma_host_on; + if (!hwif->dma_command) + hwif->dma_command = hwif->dma_base + 0; + if (!hwif->dma_vendor1) + hwif->dma_vendor1 = hwif->dma_base + 1; + if (!hwif->dma_status) + hwif->dma_status = hwif->dma_base + 2; + if (!hwif->dma_vendor3) + hwif->dma_vendor3 = hwif->dma_base + 3; + if (!hwif->dma_prdtable) + hwif->dma_prdtable = hwif->dma_base + 4; + + if (!hwif->dma_host_set) + hwif->dma_host_set = &ide_dma_host_set; if (!hwif->dma_setup) hwif->dma_setup = &ide_dma_setup; if (!hwif->dma_exec_cmd) @@ -1041,15 +994,10 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports) if (!hwif->dma_lost_irq) hwif->dma_lost_irq = &ide_dma_lost_irq; - if (hwif->chipset != ide_trm290) { - u8 dma_stat = hwif->INB(hwif->dma_status); - printk(", BIOS settings: %s:%s, %s:%s", - hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio", - hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio"); - } - printk("\n"); - - BUG_ON(!hwif->dma_master); + dma_stat = hwif->INB(hwif->dma_status); + printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n", + hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO", + hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO"); } EXPORT_SYMBOL_GPL(ide_setup_dma); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 04a357808f2..f8fe6ee128f 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1,15 +1,9 @@ /* - * linux/drivers/ide/ide-floppy.c Version 0.99 Feb 24 2002 - * - * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il> - * Copyright (C) 2000 - 2002 Paul Bristow <paul@paulbristow.net> - */ - -/* * IDE ATAPI floppy driver. * - * The driver currently doesn't have any fancy features, just the bare - * minimum read/write support. + * Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il> + * Copyright (C) 2000-2002 Paul Bristow <paul@paulbristow.net> + * Copyright (C) 2005 Bartlomiej Zolnierkiewicz * * This driver supports the following IDE floppy drives: * @@ -17,70 +11,11 @@ * Iomega Zip 100/250 * Iomega PC Card Clik!/PocketZip * - * Many thanks to Lode Leroy <Lode.Leroy@www.ibase.be>, who tested so many - * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive. - * - * Ver 0.1 Oct 17 96 Initial test version, mostly based on ide-tape.c. - * Ver 0.2 Oct 31 96 Minor changes. - * Ver 0.3 Dec 2 96 Fixed error recovery bug. - * Ver 0.4 Jan 26 97 Add support for the HDIO_GETGEO ioctl. - * Ver 0.5 Feb 21 97 Add partitions support. - * Use the minimum of the LBA and CHS capacities. - * Avoid hwgroup->rq == NULL on the last irq. - * Fix potential null dereferencing with DEBUG_LOG. - * Ver 0.8 Dec 7 97 Increase irq timeout from 10 to 50 seconds. - * Add media write-protect detection. - * Issue START command only if TEST UNIT READY fails. - * Add work-around for IOMEGA ZIP revision 21.D. - * Remove idefloppy_get_capabilities(). - * Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of - * bytes requested on each interrupt to be zero. - * Thanks to <shanos@es.co.nz> for pointing this out. - * Ver 0.9.sv Jan 6 01 Sam Varshavchik <mrsam@courier-mta.com> - * Implement low level formatting. Reimplemented - * IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp - * bit. My LS-120 drive barfs on - * IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me. - * Compromise by not reporting a failure to get this - * mode page. Implemented four IOCTLs in order to - * implement formatting. IOCTls begin with 0x4600, - * 0x46 is 'F' as in Format. - * Jan 9 01 Userland option to select format verify. - * Added PC_SUPPRESS_ERROR flag - some idefloppy drives - * do not implement IDEFLOPPY_CAPABILITIES_PAGE, and - * return a sense error. Suppress error reporting in - * this particular case in order to avoid spurious - * errors in syslog. The culprit is - * idefloppy_get_capability_page(), so move it to - * idefloppy_begin_format() so that it's not used - * unless absolutely necessary. - * If drive does not support format progress indication - * monitor the dsc bit in the status register. - * Also, O_NDELAY on open will allow the device to be - * opened without a disk available. This can be used to - * open an unformatted disk, or get the device capacity. - * Ver 0.91 Dec 11 99 Added IOMEGA Clik! drive support by - * <paul@paulbristow.net> - * Ver 0.92 Oct 22 00 Paul Bristow became official maintainer for this - * driver. Included Powerbook internal zip kludge. - * Ver 0.93 Oct 24 00 Fixed bugs for Clik! drive - * no disk on insert and disk change now works - * Ver 0.94 Oct 27 00 Tidied up to remove strstr(Clik) everywhere - * Ver 0.95 Nov 7 00 Brought across to kernel 2.4 - * Ver 0.96 Jan 7 01 Actually in line with release version of 2.4.0 - * including set_bit patch from Rusty Russell - * Ver 0.97 Jul 22 01 Merge 0.91-0.96 onto 0.9.sv for ac series - * Ver 0.97.sv Aug 3 01 Backported from 2.4.7-ac3 - * Ver 0.98 Oct 26 01 Split idefloppy_transfer_pc into two pieces to - * fix a lost interrupt problem. It appears the busy - * bit was being deasserted by my IOMEGA ATAPI ZIP 100 - * drive before the drive was actually ready. - * Ver 0.98a Oct 29 01 Expose delay value so we can play. - * Ver 0.99 Feb 24 02 Remove duplicate code, modify clik! detection code - * to support new PocketZip drives + * For a historical changelog see + * Documentation/ide/ChangeLog.ide-floppy.1996-2002 */ -#define IDEFLOPPY_VERSION "0.99.newide" +#define IDEFLOPPY_VERSION "1.00" #include <linux/module.h> #include <linux/types.h> @@ -102,179 +37,91 @@ #include <scsi/scsi_ioctl.h> #include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> +#include <linux/irq.h> +#include <linux/uaccess.h> +#include <linux/io.h> #include <asm/unaligned.h> -/* - * The following are used to debug the driver. - */ +/* define to see debug info */ #define IDEFLOPPY_DEBUG_LOG 0 -#define IDEFLOPPY_DEBUG_INFO 0 -#define IDEFLOPPY_DEBUG_BUGS 1 /* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */ -#define IDEFLOPPY_DEBUG( fmt, args... ) +#define IDEFLOPPY_DEBUG(fmt, args...) #if IDEFLOPPY_DEBUG_LOG -#define debug_log printk +#define debug_log(fmt, args...) \ + printk(KERN_INFO "ide-floppy: " fmt, ## args) #else -#define debug_log(fmt, args... ) do {} while(0) +#define debug_log(fmt, args...) do {} while (0) #endif -/* - * Some drives require a longer irq timeout. - */ +/* Some drives require a longer irq timeout. */ #define IDEFLOPPY_WAIT_CMD (5 * WAIT_CMD) /* - * After each failed packet command we issue a request sense command - * and retry the packet command IDEFLOPPY_MAX_PC_RETRIES times. + * After each failed packet command we issue a request sense command and retry + * the packet command IDEFLOPPY_MAX_PC_RETRIES times. */ #define IDEFLOPPY_MAX_PC_RETRIES 3 /* - * With each packet command, we allocate a buffer of - * IDEFLOPPY_PC_BUFFER_SIZE bytes. + * With each packet command, we allocate a buffer of IDEFLOPPY_PC_BUFFER_SIZE + * bytes. */ #define IDEFLOPPY_PC_BUFFER_SIZE 256 /* - * In various places in the driver, we need to allocate storage - * for packet commands and requests, which will remain valid while - * we leave the driver to wait for an interrupt or a timeout event. + * In various places in the driver, we need to allocate storage for packet + * commands and requests, which will remain valid while we leave the driver to + * wait for an interrupt or a timeout event. */ #define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES) -/* - * Our view of a packet command. - */ typedef struct idefloppy_packet_command_s { u8 c[12]; /* Actual packet bytes */ - int retries; /* On each retry, we increment retries */ + int retries; /* On each retry, we increment + retries */ int error; /* Error code */ int request_transfer; /* Bytes to transfer */ int actually_transferred; /* Bytes actually transferred */ int buffer_size; /* Size of our data buffer */ - int b_count; /* Missing/Available data on the current buffer */ + int b_count; /* Missing/Available data on + the current buffer */ struct request *rq; /* The corresponding request */ u8 *buffer; /* Data buffer */ - u8 *current_position; /* Pointer into the above buffer */ - void (*callback) (ide_drive_t *); /* Called when this packet command is completed */ + u8 *current_position; /* Pointer into above buffer */ + void (*callback) (ide_drive_t *); /* Called when this packet + command is completed */ u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */ - unsigned long flags; /* Status/Action bit flags: long for set_bit */ + unsigned long flags; /* Status/Action bit flags: long + for set_bit */ } idefloppy_pc_t; -/* - * Packet command flag bits. - */ -#define PC_ABORT 0 /* Set when an error is considered normal - We won't retry */ -#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */ -#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */ -#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */ -#define PC_WRITING 5 /* Data direction */ - -#define PC_SUPPRESS_ERROR 6 /* Suppress error reporting */ - -/* - * Removable Block Access Capabilities Page - */ -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned page_code :6; /* Page code - Should be 0x1b */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned ps :1; /* Should be 0 */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned ps :1; /* Should be 0 */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned page_code :6; /* Page code - Should be 0x1b */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 page_length; /* Page Length - Should be 0xa */ -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned reserved2 :6; - unsigned srfp :1; /* Supports reporting progress of format */ - unsigned sflp :1; /* System floppy type device */ - unsigned tlun :3; /* Total logical units supported by the device */ - unsigned reserved3 :3; - unsigned sml :1; /* Single / Multiple lun supported */ - unsigned ncd :1; /* Non cd optical device */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned sflp :1; /* System floppy type device */ - unsigned srfp :1; /* Supports reporting progress of format */ - unsigned reserved2 :6; - unsigned ncd :1; /* Non cd optical device */ - unsigned sml :1; /* Single / Multiple lun supported */ - unsigned reserved3 :3; - unsigned tlun :3; /* Total logical units supported by the device */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 reserved[8]; -} idefloppy_capabilities_page_t; - -/* - * Flexible disk page. - */ -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned page_code :6; /* Page code - Should be 0x5 */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned ps :1; /* The device is capable of saving the page */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned ps :1; /* The device is capable of saving the page */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned page_code :6; /* Page code - Should be 0x5 */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 page_length; /* Page Length - Should be 0x1e */ - u16 transfer_rate; /* In kilobits per second */ - u8 heads, sectors; /* Number of heads, Number of sectors per track */ - u16 sector_size; /* Byes per sector */ - u16 cyls; /* Number of cylinders */ - u8 reserved10[10]; - u8 motor_delay; /* Motor off delay */ - u8 reserved21[7]; - u16 rpm; /* Rotations per minute */ - u8 reserved30[2]; -} idefloppy_flexible_disk_page_t; - -/* - * Format capacity - */ -typedef struct { - u8 reserved[3]; - u8 length; /* Length of the following descriptors in bytes */ -} idefloppy_capacity_header_t; - -typedef struct { - u32 blocks; /* Number of blocks */ -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned dc :2; /* Descriptor Code */ - unsigned reserved :6; -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved :6; - unsigned dc :2; /* Descriptor Code */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 length_msb; /* Block Length (MSB)*/ - u16 length; /* Block Length */ -} idefloppy_capacity_descriptor_t; +/* Packet command flag bits. */ +enum { + /* 1 when we prefer to use DMA if possible */ + PC_FLAG_DMA_RECOMMENDED = (1 << 0), + /* 1 while DMA in progress */ + PC_FLAG_DMA_IN_PROGRESS = (1 << 1), + /* 1 when encountered problem during DMA */ + PC_FLAG_DMA_ERROR = (1 << 2), + /* Data direction */ + PC_FLAG_WRITING = (1 << 3), + /* Suppress error reporting */ + PC_FLAG_SUPPRESS_ERROR = (1 << 4), +}; +/* format capacities descriptor codes */ #define CAPACITY_INVALID 0x00 #define CAPACITY_UNFORMATTED 0x01 #define CAPACITY_CURRENT 0x02 #define CAPACITY_NO_CARTRIDGE 0x03 /* - * Most of our global data which we need to save even as we leave the - * driver due to an interrupt or a timer event is stored in a variable - * of type idefloppy_floppy_t, defined below. + * Most of our global data which we need to save even as we leave the driver + * due to an interrupt or a timer event is stored in a variable of type + * idefloppy_floppy_t, defined below. */ typedef struct ide_floppy_obj { ide_drive_t *drive; @@ -295,23 +142,19 @@ typedef struct ide_floppy_obj { /* We implement a circular array */ int rq_stack_index; - /* - * Last error information - */ + /* Last error information */ u8 sense_key, asc, ascq; /* delay this long before sending packet command */ u8 ticks; int progress_indication; - /* - * Device information - */ + /* Device information */ /* Current format */ int blocks, block_size, bs_factor; - /* Last format capacity */ - idefloppy_capacity_descriptor_t capacity; + /* Last format capacity descriptor */ + u8 cap_desc[8]; /* Copy of the flexible disk page */ - idefloppy_flexible_disk_page_t flexible_disk_page; + u8 flexible_disk_page[32]; /* Write protect */ int wp; /* Supports format progress report */ @@ -322,85 +165,40 @@ typedef struct ide_floppy_obj { #define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */ -/* - * Floppy flag bits values. - */ -#define IDEFLOPPY_DRQ_INTERRUPT 0 /* DRQ interrupt device */ -#define IDEFLOPPY_MEDIA_CHANGED 1 /* Media may have changed */ -#define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */ -#define IDEFLOPPY_FORMAT_IN_PROGRESS 3 /* Format in progress */ -#define IDEFLOPPY_CLIK_DRIVE 4 /* Avoid commands not supported in Clik drive */ -#define IDEFLOPPY_ZIP_DRIVE 5 /* Requires BH algorithm for packets */ - -/* - * ATAPI floppy drive packet commands - */ -#define IDEFLOPPY_FORMAT_UNIT_CMD 0x04 -#define IDEFLOPPY_INQUIRY_CMD 0x12 -#define IDEFLOPPY_MODE_SELECT_CMD 0x55 -#define IDEFLOPPY_MODE_SENSE_CMD 0x5a -#define IDEFLOPPY_READ10_CMD 0x28 -#define IDEFLOPPY_READ12_CMD 0xa8 -#define IDEFLOPPY_READ_CAPACITY_CMD 0x23 -#define IDEFLOPPY_REQUEST_SENSE_CMD 0x03 -#define IDEFLOPPY_PREVENT_REMOVAL_CMD 0x1e -#define IDEFLOPPY_SEEK_CMD 0x2b -#define IDEFLOPPY_START_STOP_CMD 0x1b -#define IDEFLOPPY_TEST_UNIT_READY_CMD 0x00 -#define IDEFLOPPY_VERIFY_CMD 0x2f -#define IDEFLOPPY_WRITE10_CMD 0x2a -#define IDEFLOPPY_WRITE12_CMD 0xaa -#define IDEFLOPPY_WRITE_VERIFY_CMD 0x2e +/* Floppy flag bits values. */ +enum { + /* DRQ interrupt device */ + IDEFLOPPY_FLAG_DRQ_INTERRUPT = (1 << 0), + /* Media may have changed */ + IDEFLOPPY_FLAG_MEDIA_CHANGED = (1 << 1), + /* Format in progress */ + IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS = (1 << 2), + /* Avoid commands not supported in Clik drive */ + IDEFLOPPY_FLAG_CLIK_DRIVE = (1 << 3), + /* Requires BH algorithm for packets */ + IDEFLOPPY_FLAG_ZIP_DRIVE = (1 << 4), +}; -/* - * Defines for the mode sense command - */ +/* Defines for the MODE SENSE command */ #define MODE_SENSE_CURRENT 0x00 #define MODE_SENSE_CHANGEABLE 0x01 -#define MODE_SENSE_DEFAULT 0x02 +#define MODE_SENSE_DEFAULT 0x02 #define MODE_SENSE_SAVED 0x03 -/* - * IOCTLs used in low-level formatting. - */ - +/* IOCTLs used in low-level formatting. */ #define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600 #define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601 #define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 #define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 -#if 0 -/* - * Special requests for our block device strategy routine. - */ -#define IDEFLOPPY_FIRST_RQ 90 - -/* - * IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue. - */ -#define IDEFLOPPY_PC_RQ 90 - -#define IDEFLOPPY_LAST_RQ 90 - -/* - * A macro which can be used to check if a given request command - * originated in the driver or in the buffer cache layer. - */ -#define IDEFLOPPY_RQ_CMD(cmd) ((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ)) - -#endif - -/* - * Error codes which are returned in rq->errors to the higher part - * of the driver. - */ +/* Error code returned in rq->errors to the higher part of the driver. */ #define IDEFLOPPY_ERROR_GENERAL 101 /* - * The following is used to format the general configuration word of - * the ATAPI IDENTIFY DEVICE command. + * The following is used to format the general configuration word of the + * ATAPI IDENTIFY DEVICE command. */ -struct idefloppy_id_gcw { +struct idefloppy_id_gcw { #if defined(__LITTLE_ENDIAN_BITFIELD) unsigned packet_size :2; /* Packet Size */ unsigned reserved234 :3; /* Reserved */ @@ -423,103 +221,12 @@ struct idefloppy_id_gcw { }; /* - * INQUIRY packet command - Data Format - */ -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned device_type :5; /* Peripheral Device Type */ - unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ - unsigned reserved1_6t0 :7; /* Reserved */ - unsigned rmb :1; /* Removable Medium Bit */ - unsigned ansi_version :3; /* ANSI Version */ - unsigned ecma_version :3; /* ECMA Version */ - unsigned iso_version :2; /* ISO Version */ - unsigned response_format :4; /* Response Data Format */ - unsigned reserved3_45 :2; /* Reserved */ - unsigned reserved3_6 :1; /* TrmIOP - Reserved */ - unsigned reserved3_7 :1; /* AENC - Reserved */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ - unsigned device_type :5; /* Peripheral Device Type */ - unsigned rmb :1; /* Removable Medium Bit */ - unsigned reserved1_6t0 :7; /* Reserved */ - unsigned iso_version :2; /* ISO Version */ - unsigned ecma_version :3; /* ECMA Version */ - unsigned ansi_version :3; /* ANSI Version */ - unsigned reserved3_7 :1; /* AENC - Reserved */ - unsigned reserved3_6 :1; /* TrmIOP - Reserved */ - unsigned reserved3_45 :2; /* Reserved */ - unsigned response_format :4; /* Response Data Format */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 additional_length; /* Additional Length (total_length-4) */ - u8 rsv5, rsv6, rsv7; /* Reserved */ - u8 vendor_id[8]; /* Vendor Identification */ - u8 product_id[16]; /* Product Identification */ - u8 revision_level[4]; /* Revision Level */ - u8 vendor_specific[20]; /* Vendor Specific - Optional */ - u8 reserved56t95[40]; /* Reserved - Optional */ - /* Additional information may be returned */ -} idefloppy_inquiry_result_t; - -/* - * REQUEST SENSE packet command result - Data Format. - */ -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned error_code :7; /* Current error (0x70) */ - unsigned valid :1; /* The information field conforms to SFF-8070i */ - u8 reserved1 :8; /* Reserved */ - unsigned sense_key :4; /* Sense Key */ - unsigned reserved2_4 :1; /* Reserved */ - unsigned ili :1; /* Incorrect Length Indicator */ - unsigned reserved2_67 :2; -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned valid :1; /* The information field conforms to SFF-8070i */ - unsigned error_code :7; /* Current error (0x70) */ - u8 reserved1 :8; /* Reserved */ - unsigned reserved2_67 :2; - unsigned ili :1; /* Incorrect Length Indicator */ - unsigned reserved2_4 :1; /* Reserved */ - unsigned sense_key :4; /* Sense Key */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u32 information __attribute__ ((packed)); - u8 asl; /* Additional sense length (n-7) */ - u32 command_specific; /* Additional command specific information */ - u8 asc; /* Additional Sense Code */ - u8 ascq; /* Additional Sense Code Qualifier */ - u8 replaceable_unit_code; /* Field Replaceable Unit Code */ - u8 sksv[3]; - u8 pad[2]; /* Padding to 20 bytes */ -} idefloppy_request_sense_result_t; - -/* - * Pages of the SELECT SENSE / MODE SENSE packet commands. + * Pages of the SELECT SENSE / MODE SENSE packet commands. + * See SFF-8070i spec. */ #define IDEFLOPPY_CAPABILITIES_PAGE 0x1b #define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05 -/* - * Mode Parameter Header for the MODE SENSE packet command - */ -typedef struct { - u16 mode_data_length; /* Length of the following data transfer */ - u8 medium_type; /* Medium Type */ -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned reserved3 :7; - unsigned wp :1; /* Write protect */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned wp :1; /* Write protect */ - unsigned reserved3 :7; -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 reserved[4]; -} idefloppy_mode_parameter_header_t; - static DEFINE_MUTEX(idefloppy_ref_mutex); #define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref) @@ -539,39 +246,35 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) return floppy; } -static void ide_floppy_release(struct kref *); +static void idefloppy_cleanup_obj(struct kref *); static void ide_floppy_put(struct ide_floppy_obj *floppy) { mutex_lock(&idefloppy_ref_mutex); - kref_put(&floppy->kref, ide_floppy_release); + kref_put(&floppy->kref, idefloppy_cleanup_obj); mutex_unlock(&idefloppy_ref_mutex); } /* - * Too bad. The drive wants to send us data which we are not ready to accept. - * Just throw it away. + * Too bad. The drive wants to send us data which we are not ready to accept. + * Just throw it away. */ -static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount) +static void idefloppy_discard_data(ide_drive_t *drive, unsigned int bcount) { while (bcount--) (void) HWIF(drive)->INB(IDE_DATA_REG); } -#if IDEFLOPPY_DEBUG_BUGS -static void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount) +static void idefloppy_write_zeros(ide_drive_t *drive, unsigned int bcount) { while (bcount--) HWIF(drive)->OUTB(0, IDE_DATA_REG); } -#endif /* IDEFLOPPY_DEBUG_BUGS */ /* - * idefloppy_do_end_request is used to finish servicing a request. - * - * For read/write requests, we will call ide_end_request to pass to the - * next buffer. + * Used to finish servicing a request. For read/write requests, we will call + * ide_end_request to pass to the next buffer. */ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs) { @@ -579,12 +282,12 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs) struct request *rq = HWGROUP(drive)->rq; int error; - debug_log(KERN_INFO "Reached idefloppy_end_request\n"); + debug_log("Reached %s\n", __func__); switch (uptodate) { - case 0: error = IDEFLOPPY_ERROR_GENERAL; break; - case 1: error = 0; break; - default: error = uptodate; + case 0: error = IDEFLOPPY_ERROR_GENERAL; break; + case 1: error = 0; break; + default: error = uptodate; } if (error) floppy->failed_pc = NULL; @@ -602,39 +305,8 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs) return 0; } -static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) -{ - struct request *rq = pc->rq; - struct bio_vec *bvec; - struct req_iterator iter; - unsigned long flags; - char *data; - int count, done = 0; - - rq_for_each_segment(bvec, rq, iter) { - if (!bcount) - break; - - count = min(bvec->bv_len, bcount); - - data = bvec_kmap_irq(bvec, &flags); - drive->hwif->atapi_input_bytes(drive, data, count); - bvec_kunmap_irq(data, &flags); - - bcount -= count; - pc->b_count += count; - done += count; - } - - idefloppy_do_end_request(drive, 1, done >> 9); - - if (bcount) { - printk(KERN_ERR "%s: leftover data in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount); - idefloppy_discard_data(drive, bcount); - } -} - -static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) +static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc, + unsigned int bcount, int direction) { struct request *rq = pc->rq; struct req_iterator iter; @@ -650,7 +322,10 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un count = min(bvec->bv_len, bcount); data = bvec_kmap_irq(bvec, &flags); - drive->hwif->atapi_output_bytes(drive, data, count); + if (direction) + drive->hwif->atapi_output_bytes(drive, data, count); + else + drive->hwif->atapi_input_bytes(drive, data, count); bvec_kunmap_irq(data, &flags); bcount -= count; @@ -660,15 +335,18 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un idefloppy_do_end_request(drive, 1, done >> 9); -#if IDEFLOPPY_DEBUG_BUGS if (bcount) { - printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount); - idefloppy_write_zeros(drive, bcount); + printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n", + drive->name, __func__, bcount); + if (direction) + idefloppy_write_zeros(drive, bcount); + else + idefloppy_discard_data(drive, bcount); + } -#endif } -static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc) +static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc) { struct request *rq = pc->rq; struct bio *bio = rq->bio; @@ -678,11 +356,12 @@ static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc) } /* - * idefloppy_queue_pc_head generates a new packet command request in front - * of the request queue, before the current request, so that it will be - * processed immediately, on the next pass through the driver. + * Generate a new packet command request in front of the request queue, before + * the current request so that it will be processed immediately, on the next + * pass through the driver. */ -static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq) +static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc, + struct request *rq) { struct ide_floppy_obj *floppy = drive->driver_data; @@ -693,16 +372,16 @@ static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struc (void) ide_do_drive_cmd(drive, rq, ide_preempt); } -static idefloppy_pc_t *idefloppy_next_pc_storage (ide_drive_t *drive) +static idefloppy_pc_t *idefloppy_next_pc_storage(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK) - floppy->pc_stack_index=0; + floppy->pc_stack_index = 0; return (&floppy->pc_stack[floppy->pc_stack_index++]); } -static struct request *idefloppy_next_rq_storage (ide_drive_t *drive) +static struct request *idefloppy_next_rq_storage(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; @@ -711,60 +390,53 @@ static struct request *idefloppy_next_rq_storage (ide_drive_t *drive) return (&floppy->rq_stack[floppy->rq_stack_index++]); } -/* - * idefloppy_analyze_error is called on each failed packet command retry - * to analyze the request sense. - */ -static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_result_t *result) +static void idefloppy_request_sense_callback(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; + u8 *buf = floppy->pc->buffer; - floppy->sense_key = result->sense_key; - floppy->asc = result->asc; - floppy->ascq = result->ascq; - floppy->progress_indication = result->sksv[0] & 0x80 ? - (u16)get_unaligned((u16 *)(result->sksv+1)):0x10000; - if (floppy->failed_pc) - debug_log(KERN_INFO "ide-floppy: pc = %x, sense key = %x, " - "asc = %x, ascq = %x\n", floppy->failed_pc->c[0], - result->sense_key, result->asc, result->ascq); - else - debug_log(KERN_INFO "ide-floppy: sense key = %x, asc = %x, " - "ascq = %x\n", result->sense_key, - result->asc, result->ascq); -} - -static void idefloppy_request_sense_callback (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; + debug_log("Reached %s\n", __func__); - debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); - if (!floppy->pc->error) { - idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); + floppy->sense_key = buf[2] & 0x0F; + floppy->asc = buf[12]; + floppy->ascq = buf[13]; + floppy->progress_indication = buf[15] & 0x80 ? + (u16)get_unaligned((u16 *)&buf[16]) : 0x10000; + + if (floppy->failed_pc) + debug_log("pc = %x, sense key = %x, asc = %x," + " ascq = %x\n", + floppy->failed_pc->c[0], + floppy->sense_key, + floppy->asc, + floppy->ascq); + else + debug_log("sense key = %x, asc = %x, ascq = %x\n", + floppy->sense_key, + floppy->asc, + floppy->ascq); + + idefloppy_do_end_request(drive, 1, 0); } else { - printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); + printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting" + " request!\n"); idefloppy_do_end_request(drive, 0, 0); } } -/* - * General packet command callback function. - */ -static void idefloppy_pc_callback (ide_drive_t *drive) +/* General packet command callback function. */ +static void idefloppy_pc_callback(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - - debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); + + debug_log("Reached %s\n", __func__); idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0); } -/* - * idefloppy_init_pc initializes a packet command. - */ -static void idefloppy_init_pc (idefloppy_pc_t *pc) +static void idefloppy_init_pc(idefloppy_pc_t *pc) { memset(pc->c, 0, 12); pc->retries = 0; @@ -775,76 +447,75 @@ static void idefloppy_init_pc (idefloppy_pc_t *pc) pc->callback = &idefloppy_pc_callback; } -static void idefloppy_create_request_sense_cmd (idefloppy_pc_t *pc) +static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc) { - idefloppy_init_pc(pc); - pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD; + idefloppy_init_pc(pc); + pc->c[0] = GPCMD_REQUEST_SENSE; pc->c[4] = 255; pc->request_transfer = 18; pc->callback = &idefloppy_request_sense_callback; } /* - * idefloppy_retry_pc is called when an error was detected during the - * last packet command. We queue a request sense packet command in - * the head of the request list. + * Called when an error was detected during the last packet command. We queue a + * request sense packet command in the head of the request list. */ -static void idefloppy_retry_pc (ide_drive_t *drive) +static void idefloppy_retry_pc(ide_drive_t *drive) { idefloppy_pc_t *pc; struct request *rq; - atapi_error_t error; - error.all = HWIF(drive)->INB(IDE_ERROR_REG); + (void)drive->hwif->INB(IDE_ERROR_REG); pc = idefloppy_next_pc_storage(drive); rq = idefloppy_next_rq_storage(drive); idefloppy_create_request_sense_cmd(pc); idefloppy_queue_pc_head(drive, pc, rq); } -/* - * idefloppy_pc_intr is the usual interrupt handler which will be called - * during a packet command. - */ +/* The usual interrupt handler called during a packet command. */ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - atapi_status_t status; - atapi_bcount_t bcount; - atapi_ireason_t ireason; + ide_hwif_t *hwif = drive->hwif; idefloppy_pc_t *pc = floppy->pc; struct request *rq = pc->rq; + xfer_func_t *xferfunc; unsigned int temp; - - debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n", - __FUNCTION__); - - if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { - if (HWIF(drive)->ide_dma_end(drive)) { - set_bit(PC_DMA_ERROR, &pc->flags); + int dma_error = 0; + u16 bcount; + u8 stat, ireason; + + debug_log("Reached %s interrupt handler\n", __func__); + + if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { + dma_error = hwif->ide_dma_end(drive); + if (dma_error) { + printk(KERN_ERR "%s: DMA %s error\n", drive->name, + rq_data_dir(rq) ? "write" : "read"); + pc->flags |= PC_FLAG_DMA_ERROR; } else { pc->actually_transferred = pc->request_transfer; idefloppy_update_buffers(drive, pc); } - debug_log(KERN_INFO "ide-floppy: DMA finished\n"); + debug_log("DMA finished\n"); } /* Clear the interrupt */ - status.all = HWIF(drive)->INB(IDE_STATUS_REG); + stat = drive->hwif->INB(IDE_STATUS_REG); - if (!status.b.drq) { /* No more interrupts */ - debug_log(KERN_INFO "Packet command completed, %d bytes " - "transferred\n", pc->actually_transferred); - clear_bit(PC_DMA_IN_PROGRESS, &pc->flags); + /* No more interrupts */ + if ((stat & DRQ_STAT) == 0) { + debug_log("Packet command completed, %d bytes transferred\n", + pc->actually_transferred); + pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; local_irq_enable_in_hardirq(); - if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { + if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { /* Error detected */ - debug_log(KERN_INFO "ide-floppy: %s: I/O error\n", - drive->name); + debug_log("%s: I/O error\n", drive->name); rq->errors++; - if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { + if (pc->c[0] == GPCMD_REQUEST_SENSE) { printk(KERN_ERR "ide-floppy: I/O error in " "request sense command\n"); return ide_do_reset(drive); @@ -862,7 +533,8 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) return ide_stopped; } - if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { + if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { + pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; printk(KERN_ERR "ide-floppy: The floppy wants to issue " "more interrupts in DMA mode\n"); ide_dma_off(drive); @@ -870,67 +542,60 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) } /* Get the number of bytes to transfer */ - bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG); - bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG); + bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) | + hwif->INB(IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); + ireason = hwif->INB(IDE_IREASON_REG); - if (ireason.b.cod) { - printk(KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n"); + if (ireason & CD) { + printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__); return ide_do_reset(drive); } - if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) { + if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { /* Hopefully, we will never get here */ printk(KERN_ERR "ide-floppy: We wanted to %s, ", - ireason.b.io ? "Write":"Read"); + (ireason & IO) ? "Write" : "Read"); printk(KERN_ERR "but the floppy wants us to %s !\n", - ireason.b.io ? "Read":"Write"); + (ireason & IO) ? "Read" : "Write"); return ide_do_reset(drive); } - if (!test_bit(PC_WRITING, &pc->flags)) { + if (!(pc->flags & PC_FLAG_WRITING)) { /* Reading - Check that we have enough space */ - temp = pc->actually_transferred + bcount.all; + temp = pc->actually_transferred + bcount; if (temp > pc->request_transfer) { if (temp > pc->buffer_size) { printk(KERN_ERR "ide-floppy: The floppy wants " "to send us more data than expected " "- discarding data\n"); - idefloppy_discard_data(drive,bcount.all); - BUG_ON(HWGROUP(drive)->handler != NULL); + idefloppy_discard_data(drive, bcount); + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); return ide_started; } - debug_log(KERN_NOTICE "ide-floppy: The floppy wants to " - "send us more data than expected - " - "allowing transfer\n"); + debug_log("The floppy wants to send us more data than" + " expected - allowing transfer\n"); } } - if (test_bit(PC_WRITING, &pc->flags)) { - if (pc->buffer != NULL) - /* Write the current buffer */ - HWIF(drive)->atapi_output_bytes(drive, - pc->current_position, - bcount.all); - else - idefloppy_output_buffers(drive, pc, bcount.all); - } else { - if (pc->buffer != NULL) - /* Read the current buffer */ - HWIF(drive)->atapi_input_bytes(drive, - pc->current_position, - bcount.all); - else - idefloppy_input_buffers(drive, pc, bcount.all); - } + if (pc->flags & PC_FLAG_WRITING) + xferfunc = hwif->atapi_output_bytes; + else + xferfunc = hwif->atapi_input_bytes; + + if (pc->buffer) + xferfunc(drive, pc->current_position, bcount); + else + ide_floppy_io_buffers(drive, pc, bcount, + !!(pc->flags & PC_FLAG_WRITING)); + /* Update the current position */ - pc->actually_transferred += bcount.all; - pc->current_position += bcount.all; + pc->actually_transferred += bcount; + pc->current_position += bcount; - BUG_ON(HWGROUP(drive)->handler != NULL); - ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ + /* And set the interrupt handler again */ + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); return ide_started; } @@ -939,24 +604,24 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) * It fails at high speeds on the Iomega ZIP drive, so there's a slower version * for that drive below. The algorithm is chosen based on drive type */ -static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive) +static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive) { ide_startstop_t startstop; idefloppy_floppy_t *floppy = drive->driver_data; - atapi_ireason_t ireason; + u8 ireason; if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { printk(KERN_ERR "ide-floppy: Strange, packet command " "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); - if (!ireason.b.cod || ireason.b.io) { + ireason = drive->hwif->INB(IDE_IREASON_REG); + if ((ireason & CD) == 0 || (ireason & IO)) { printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while " "issuing a packet command\n"); return ide_do_reset(drive); } - BUG_ON(HWGROUP(drive)->handler != NULL); + /* Set the interrupt routine */ ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Send the actual packet */ @@ -966,18 +631,16 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive) /* - * What we have here is a classic case of a top half / bottom half - * interrupt service routine. In interrupt mode, the device sends - * an interrupt to signal it's ready to receive a packet. However, - * we need to delay about 2-3 ticks before issuing the packet or we - * gets in trouble. + * What we have here is a classic case of a top half / bottom half interrupt + * service routine. In interrupt mode, the device sends an interrupt to signal + * that it is ready to receive a packet. However, we need to delay about 2-3 + * ticks before issuing the packet or we gets in trouble. * - * So, follow carefully. transfer_pc1 is called as an interrupt (or - * directly). In either case, when the device says it's ready for a - * packet, we schedule the packet transfer to occur about 2-3 ticks - * later in transfer_pc2. + * So, follow carefully. transfer_pc1 is called as an interrupt (or directly). + * In either case, when the device says it's ready for a packet, we schedule + * the packet transfer to occur about 2-3 ticks later in transfer_pc2. */ -static int idefloppy_transfer_pc2 (ide_drive_t *drive) +static int idefloppy_transfer_pc2(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; @@ -987,24 +650,24 @@ static int idefloppy_transfer_pc2 (ide_drive_t *drive) return IDEFLOPPY_WAIT_CMD; } -static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive) +static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; ide_startstop_t startstop; - atapi_ireason_t ireason; + u8 ireason; if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { printk(KERN_ERR "ide-floppy: Strange, packet command " "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); - if (!ireason.b.cod || ireason.b.io) { + ireason = drive->hwif->INB(IDE_IREASON_REG); + if ((ireason & CD) == 0 || (ireason & IO)) { printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) " "while issuing a packet command\n"); return ide_do_reset(drive); } - /* + /* * The following delay solves a problem with ATAPI Zip 100 drives * where the Busy flag was apparently being deasserted before the * unit was ready to receive data. This was happening on a @@ -1012,112 +675,82 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive) * 40 and 50msec work well. idefloppy_pc_intr will not be actually * used until after the packet is moved in about 50 msec. */ - BUG_ON(HWGROUP(drive)->handler != NULL); - ide_set_handler(drive, - &idefloppy_pc_intr, /* service routine for packet command */ - floppy->ticks, /* wait this long before "failing" */ - &idefloppy_transfer_pc2); /* fail == transfer_pc2 */ + + ide_set_handler(drive, &idefloppy_pc_intr, floppy->ticks, + &idefloppy_transfer_pc2); return ide_started; } -/** - * idefloppy_should_report_error() - * - * Supresses error messages resulting from Medium not present - */ -static inline int idefloppy_should_report_error(idefloppy_floppy_t *floppy) +static void ide_floppy_report_error(idefloppy_floppy_t *floppy, + idefloppy_pc_t *pc) { + /* supress error messages resulting from Medium not present */ if (floppy->sense_key == 0x02 && floppy->asc == 0x3a && floppy->ascq == 0x00) - return 0; - return 1; + return; + + printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, " + "asc = %2x, ascq = %2x\n", + floppy->drive->name, pc->c[0], floppy->sense_key, + floppy->asc, floppy->ascq); + } -/* - * Issue a packet command - */ -static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) +static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, + idefloppy_pc_t *pc) { idefloppy_floppy_t *floppy = drive->driver_data; ide_hwif_t *hwif = drive->hwif; - atapi_feature_t feature; - atapi_bcount_t bcount; ide_handler_t *pkt_xfer_routine; - -#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone - and have lived on another thread's stack; that stack may have become - unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */ -#if IDEFLOPPY_DEBUG_BUGS - if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD && - pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { - printk(KERN_ERR "ide-floppy: possible ide-floppy.c bug - " - "Two request sense in serial were issued\n"); - } -#endif /* IDEFLOPPY_DEBUG_BUGS */ -#endif + u16 bcount; + u8 dma; if (floppy->failed_pc == NULL && - pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD) + pc->c[0] != GPCMD_REQUEST_SENSE) floppy->failed_pc = pc; /* Set the current packet command */ floppy->pc = pc; - if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES || - test_bit(PC_ABORT, &pc->flags)) { - /* - * We will "abort" retrying a packet command in case - * a legitimate error code was received. - */ - if (!test_bit(PC_ABORT, &pc->flags)) { - if (!test_bit(PC_SUPPRESS_ERROR, &pc->flags)) { - if (idefloppy_should_report_error(floppy)) - printk(KERN_ERR "ide-floppy: %s: I/O error, " - "pc = %2x, key = %2x, " - "asc = %2x, ascq = %2x\n", - drive->name, pc->c[0], - floppy->sense_key, - floppy->asc, floppy->ascq); - } - /* Giving up */ - pc->error = IDEFLOPPY_ERROR_GENERAL; - } + if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { + if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) + ide_floppy_report_error(floppy, pc); + /* Giving up */ + pc->error = IDEFLOPPY_ERROR_GENERAL; + floppy->failed_pc = NULL; pc->callback(drive); return ide_stopped; } - debug_log(KERN_INFO "Retry number - %d\n",pc->retries); + debug_log("Retry number - %d\n", pc->retries); pc->retries++; /* We haven't transferred any data yet */ pc->actually_transferred = 0; pc->current_position = pc->buffer; - bcount.all = min(pc->request_transfer, 63 * 1024); + bcount = min(pc->request_transfer, 63 * 1024); - if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) + if (pc->flags & PC_FLAG_DMA_ERROR) { + pc->flags &= ~PC_FLAG_DMA_ERROR; ide_dma_off(drive); + } + dma = 0; - feature.all = 0; - - if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - feature.b.dma = !hwif->dma_setup(drive); + if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma) + dma = !hwif->dma_setup(drive); - if (IDE_CONTROL_REG) - HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); - /* Use PIO/DMA */ - HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG); - HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG); - HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG); - HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG); + ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK | + IDE_TFLAG_OUT_DEVICE, bcount, dma); - if (feature.b.dma) { /* Begin DMA, if necessary */ - set_bit(PC_DMA_IN_PROGRESS, &pc->flags); + if (dma) { + /* Begin DMA, if necessary */ + pc->flags |= PC_FLAG_DMA_IN_PROGRESS; hwif->dma_start(drive); } /* Can we transfer the packet when we get the interrupt or wait? */ - if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) { + if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE) { /* wait */ pkt_xfer_routine = &idefloppy_transfer_pc1; } else { @@ -1125,7 +758,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p pkt_xfer_routine = &idefloppy_transfer_pc; } - if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { + if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) { /* Issue the packet command */ ide_execute_command(drive, WIN_PACKETCMD, pkt_xfer_routine, @@ -1139,38 +772,37 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p } } -static void idefloppy_rw_callback (ide_drive_t *drive) +static void idefloppy_rw_callback(ide_drive_t *drive) { - debug_log(KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); + debug_log("Reached %s\n", __func__); idefloppy_do_end_request(drive, 1, 0); return; } -static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent) +static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent) { - debug_log(KERN_INFO "ide-floppy: creating prevent removal command, " - "prevent = %d\n", prevent); + debug_log("creating prevent removal command, prevent = %d\n", prevent); idefloppy_init_pc(pc); - pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD; + pc->c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; pc->c[4] = prevent; } -static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc) +static void idefloppy_create_read_capacity_cmd(idefloppy_pc_t *pc) { idefloppy_init_pc(pc); - pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD; + pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES; pc->c[7] = 255; pc->c[8] = 255; pc->request_transfer = 255; } -static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l, +static void idefloppy_create_format_unit_cmd(idefloppy_pc_t *pc, int b, int l, int flags) { idefloppy_init_pc(pc); - pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD; + pc->c[0] = GPCMD_FORMAT_UNIT; pc->c[1] = 0x17; memset(pc->buffer, 0, 12); @@ -1181,83 +813,79 @@ static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l, pc->buffer[1] ^= 0x20; /* ... turn off DCRT bit */ pc->buffer[3] = 8; - put_unaligned(htonl(b), (unsigned int *)(&pc->buffer[4])); - put_unaligned(htonl(l), (unsigned int *)(&pc->buffer[8])); - pc->buffer_size=12; - set_bit(PC_WRITING, &pc->flags); + put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buffer[4])); + put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buffer[8])); + pc->buffer_size = 12; + pc->flags |= PC_FLAG_WRITING; } -/* - * A mode sense command is used to "sense" floppy parameters. - */ -static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, u8 page_code, u8 type) +/* A mode sense command is used to "sense" floppy parameters. */ +static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code, + u8 type) { - u16 length = sizeof(idefloppy_mode_parameter_header_t); - + u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */ + idefloppy_init_pc(pc); - pc->c[0] = IDEFLOPPY_MODE_SENSE_CMD; + pc->c[0] = GPCMD_MODE_SENSE_10; pc->c[1] = 0; pc->c[2] = page_code + (type << 6); switch (page_code) { - case IDEFLOPPY_CAPABILITIES_PAGE: - length += 12; - break; - case IDEFLOPPY_FLEXIBLE_DISK_PAGE: - length += 32; - break; - default: - printk(KERN_ERR "ide-floppy: unsupported page code " + case IDEFLOPPY_CAPABILITIES_PAGE: + length += 12; + break; + case IDEFLOPPY_FLEXIBLE_DISK_PAGE: + length += 32; + break; + default: + printk(KERN_ERR "ide-floppy: unsupported page code " "in create_mode_sense_cmd\n"); } - put_unaligned(htons(length), (u16 *) &pc->c[7]); + put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]); pc->request_transfer = length; } -static void idefloppy_create_start_stop_cmd (idefloppy_pc_t *pc, int start) +static void idefloppy_create_start_stop_cmd(idefloppy_pc_t *pc, int start) { idefloppy_init_pc(pc); - pc->c[0] = IDEFLOPPY_START_STOP_CMD; + pc->c[0] = GPCMD_START_STOP_UNIT; pc->c[4] = start; } static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc) { idefloppy_init_pc(pc); - pc->c[0] = IDEFLOPPY_TEST_UNIT_READY_CMD; + pc->c[0] = GPCMD_TEST_UNIT_READY; } -static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq, unsigned long sector) +static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy, + idefloppy_pc_t *pc, struct request *rq, + unsigned long sector) { int block = sector / floppy->bs_factor; int blocks = rq->nr_sectors / floppy->bs_factor; int cmd = rq_data_dir(rq); - debug_log("create_rw1%d_cmd: block == %d, blocks == %d\n", - 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), + debug_log("create_rw10_cmd: block == %d, blocks == %d\n", block, blocks); idefloppy_init_pc(pc); - if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) { - pc->c[0] = cmd == READ ? IDEFLOPPY_READ12_CMD : IDEFLOPPY_WRITE12_CMD; - put_unaligned(htonl(blocks), (unsigned int *) &pc->c[6]); - } else { - pc->c[0] = cmd == READ ? IDEFLOPPY_READ10_CMD : IDEFLOPPY_WRITE10_CMD; - put_unaligned(htons(blocks), (unsigned short *) &pc->c[7]); - } - put_unaligned(htonl(block), (unsigned int *) &pc->c[2]); + pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10; + put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]); + put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]); + pc->callback = &idefloppy_rw_callback; pc->rq = rq; pc->b_count = cmd == READ ? 0 : rq->bio->bi_size; if (rq->cmd_flags & REQ_RW) - set_bit(PC_WRITING, &pc->flags); + pc->flags |= PC_FLAG_WRITING; pc->buffer = NULL; pc->request_transfer = pc->buffer_size = blocks * floppy->block_size; - set_bit(PC_DMA_RECOMMENDED, &pc->flags); + pc->flags |= PC_FLAG_DMA_RECOMMENDED; } -static void -idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq) +static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, + idefloppy_pc_t *pc, struct request *rq) { idefloppy_init_pc(pc); pc->callback = &idefloppy_rw_callback; @@ -1265,11 +893,10 @@ idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct req pc->rq = rq; pc->b_count = rq->data_len; if (rq->data_len && rq_data_dir(rq) == WRITE) - set_bit(PC_WRITING, &pc->flags); + pc->flags |= PC_FLAG_WRITING; pc->buffer = rq->data; if (rq->bio) - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - + pc->flags |= PC_FLAG_DMA_RECOMMENDED; /* * possibly problematic, doesn't look like ide-floppy correctly * handled scattered requests if dma fails... @@ -1277,30 +904,23 @@ idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct req pc->request_transfer = pc->buffer_size = rq->data_len; } -/* - * idefloppy_do_request is our request handling function. - */ -static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, sector_t block_s) +static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, + struct request *rq, sector_t block_s) { idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t *pc; unsigned long block = (unsigned long)block_s; - debug_log(KERN_INFO "dev: %s, flags: %lx, errors: %d\n", + debug_log("dev: %s, cmd_type: %x, errors: %d\n", rq->rq_disk ? rq->rq_disk->disk_name : "?", - rq->flags, rq->errors); - debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, " + rq->cmd_type, rq->errors); + debug_log("sector: %ld, nr_sectors: %ld, " "current_nr_sectors: %d\n", (long)rq->sector, rq->nr_sectors, rq->current_nr_sectors); if (rq->errors >= ERROR_MAX) { - if (floppy->failed_pc != NULL) { - if (idefloppy_should_report_error(floppy)) - printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x," - " key = %2x, asc = %2x, ascq = %2x\n", - drive->name, floppy->failed_pc->c[0], - floppy->sense_key, floppy->asc, floppy->ascq); - } + if (floppy->failed_pc) + ide_floppy_report_error(floppy, floppy->failed_pc); else printk(KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); @@ -1310,8 +930,8 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request if (blk_fs_request(rq)) { if (((long)rq->sector % floppy->bs_factor) || (rq->nr_sectors % floppy->bs_factor)) { - printk("%s: unsupported r/w request size\n", - drive->name); + printk(KERN_ERR "%s: unsupported r/w request size\n", + drive->name); idefloppy_do_end_request(drive, 0, 0); return ide_stopped; } @@ -1334,15 +954,15 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request } /* - * idefloppy_queue_pc_tail adds a special packet command request to the - * tail of the request queue, and waits for it to be serviced. + * Add a special packet command request to the tail of the request queue, + * and wait for it to be serviced. */ -static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc) +static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc) { struct ide_floppy_obj *floppy = drive->driver_data; struct request rq; - ide_init_drive_cmd (&rq); + ide_init_drive_cmd(&rq); rq.buffer = (char *) pc; rq.cmd_type = REQ_TYPE_SPECIAL; rq.rq_disk = floppy->disk; @@ -1351,88 +971,90 @@ static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc) } /* - * Look at the flexible disk page parameters. We will ignore the CHS - * capacity parameters and use the LBA parameters instead. + * Look at the flexible disk page parameters. We ignore the CHS capacity + * parameters and use the LBA parameters instead. */ -static int idefloppy_get_flexible_disk_page (ide_drive_t *drive) +static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; - idefloppy_mode_parameter_header_t *header; - idefloppy_flexible_disk_page_t *page; + u8 *page; int capacity, lba_capacity; + u16 transfer_rate, sector_size, cyls, rpm; + u8 heads, sectors; + + idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, + MODE_SENSE_CURRENT); - idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT); - if (idefloppy_queue_pc_tail(drive,&pc)) { - printk(KERN_ERR "ide-floppy: Can't get flexible disk " - "page parameters\n"); + if (idefloppy_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-floppy: Can't get flexible disk page" + " parameters\n"); return 1; } - header = (idefloppy_mode_parameter_header_t *) pc.buffer; - floppy->wp = header->wp; + floppy->wp = !!(pc.buffer[3] & 0x80); set_disk_ro(floppy->disk, floppy->wp); - page = (idefloppy_flexible_disk_page_t *) (header + 1); - - page->transfer_rate = ntohs(page->transfer_rate); - page->sector_size = ntohs(page->sector_size); - page->cyls = ntohs(page->cyls); - page->rpm = ntohs(page->rpm); - capacity = page->cyls * page->heads * page->sectors * page->sector_size; - if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t))) + page = &pc.buffer[8]; + + transfer_rate = be16_to_cpu(*(u16 *)&pc.buffer[8 + 2]); + sector_size = be16_to_cpu(*(u16 *)&pc.buffer[8 + 6]); + cyls = be16_to_cpu(*(u16 *)&pc.buffer[8 + 8]); + rpm = be16_to_cpu(*(u16 *)&pc.buffer[8 + 28]); + heads = pc.buffer[8 + 4]; + sectors = pc.buffer[8 + 5]; + + capacity = cyls * heads * sectors * sector_size; + + if (memcmp(page, &floppy->flexible_disk_page, 32)) printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, " "%d sector size, %d rpm\n", - drive->name, capacity / 1024, page->cyls, - page->heads, page->sectors, - page->transfer_rate / 8, page->sector_size, page->rpm); - - floppy->flexible_disk_page = *page; - drive->bios_cyl = page->cyls; - drive->bios_head = page->heads; - drive->bios_sect = page->sectors; + drive->name, capacity / 1024, cyls, heads, + sectors, transfer_rate / 8, sector_size, rpm); + + memcpy(&floppy->flexible_disk_page, page, 32); + drive->bios_cyl = cyls; + drive->bios_head = heads; + drive->bios_sect = sectors; lba_capacity = floppy->blocks * floppy->block_size; + if (capacity < lba_capacity) { printk(KERN_NOTICE "%s: The disk reports a capacity of %d " "bytes, but the drive only handles %d\n", drive->name, lba_capacity, capacity); - floppy->blocks = floppy->block_size ? capacity / floppy->block_size : 0; + floppy->blocks = floppy->block_size ? + capacity / floppy->block_size : 0; } return 0; } -static int idefloppy_get_capability_page(ide_drive_t *drive) +static int idefloppy_get_sfrp_bit(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; - idefloppy_mode_parameter_header_t *header; - idefloppy_capabilities_page_t *page; floppy->srfp = 0; idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE, MODE_SENSE_CURRENT); - set_bit(PC_SUPPRESS_ERROR, &pc.flags); - if (idefloppy_queue_pc_tail(drive,&pc)) { + pc.flags |= PC_FLAG_SUPPRESS_ERROR; + if (idefloppy_queue_pc_tail(drive, &pc)) return 1; - } - header = (idefloppy_mode_parameter_header_t *) pc.buffer; - page= (idefloppy_capabilities_page_t *)(header+1); - floppy->srfp = page->srfp; + floppy->srfp = pc.buffer[8 + 2] & 0x40; return (0); } /* - * Determine if a media is present in the floppy drive, and if so, - * its LBA capacity. + * Determine if a media is present in the floppy drive, and if so, its LBA + * capacity. */ -static int idefloppy_get_capacity (ide_drive_t *drive) +static int ide_floppy_get_capacity(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; - idefloppy_capacity_header_t *header; - idefloppy_capacity_descriptor_t *descriptor; - int i, descriptors, rc = 1, blocks, length; - + u8 *cap_desc; + u8 header_len, desc_cnt; + int i, rc = 1, blocks, length; + drive->bios_cyl = 0; drive->bios_head = drive->bios_sect = 0; floppy->blocks = 0; @@ -1444,44 +1066,55 @@ static int idefloppy_get_capacity (ide_drive_t *drive) printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return 1; } - header = (idefloppy_capacity_header_t *) pc.buffer; - descriptors = header->length / sizeof(idefloppy_capacity_descriptor_t); - descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); + header_len = pc.buffer[3]; + cap_desc = &pc.buffer[4]; + desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ + + for (i = 0; i < desc_cnt; i++) { + unsigned int desc_start = 4 + i*8; + + blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]); + length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]); - for (i = 0; i < descriptors; i++, descriptor++) { - blocks = descriptor->blocks = ntohl(descriptor->blocks); - length = descriptor->length = ntohs(descriptor->length); + debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n", + i, blocks * length / 1024, blocks, length); + + if (i) + continue; + /* + * the code below is valid only for the 1st descriptor, ie i=0 + */ - if (!i) - { - switch (descriptor->dc) { + switch (pc.buffer[desc_start + 4] & 0x03) { /* Clik! drive returns this instead of CAPACITY_CURRENT */ case CAPACITY_UNFORMATTED: - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) - /* + if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) + /* * If it is not a clik drive, break out * (maintains previous driver behaviour) */ break; case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */ - if (memcmp(descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) + if (memcmp(cap_desc, &floppy->cap_desc, 8)) printk(KERN_INFO "%s: %dkB, %d blocks, %d " "sector size\n", drive->name, blocks * length / 1024, blocks, length); - floppy->capacity = *descriptor; + memcpy(&floppy->cap_desc, cap_desc, 8); + if (!length || length % 512) { printk(KERN_NOTICE "%s: %d bytes block size " "not supported\n", drive->name, length); } else { - floppy->blocks = blocks; - floppy->block_size = length; - if ((floppy->bs_factor = length / 512) != 1) - printk(KERN_NOTICE "%s: warning: non " + floppy->blocks = blocks; + floppy->block_size = length; + floppy->bs_factor = length / 512; + if (floppy->bs_factor != 1) + printk(KERN_NOTICE "%s: warning: non " "512 bytes block size not " "fully supported\n", drive->name); - rc = 0; + rc = 0; } break; case CAPACITY_NO_CARTRIDGE: @@ -1496,54 +1129,42 @@ static int idefloppy_get_capacity (ide_drive_t *drive) "in drive\n", drive->name); break; } - } - if (!i) { - debug_log( "Descriptor 0 Code: %d\n", - descriptor->dc); - } - debug_log( "Descriptor %d: %dkB, %d blocks, %d " - "sector size\n", i, blocks * length / 1024, blocks, - length); + debug_log("Descriptor 0 Code: %d\n", + pc.buffer[desc_start + 4] & 0x03); } /* Clik! disk does not support get_flexible_disk_page */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { - (void) idefloppy_get_flexible_disk_page(drive); - } + if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) + (void) ide_floppy_get_flexible_disk_page(drive); set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor); return rc; } /* -** Obtain the list of formattable capacities. -** Very similar to idefloppy_get_capacity, except that we push the capacity -** descriptors to userland, instead of our own structures. -** -** Userland gives us the following structure: -** -** struct idefloppy_format_capacities { -** int nformats; -** struct { -** int nblocks; -** int blocksize; -** } formats[]; -** } ; -** -** userland initializes nformats to the number of allocated formats[] -** records. On exit we set nformats to the number of records we've -** actually initialized. -** -*/ - -static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg) + * Obtain the list of formattable capacities. + * Very similar to ide_floppy_get_capacity, except that we push the capacity + * descriptors to userland, instead of our own structures. + * + * Userland gives us the following structure: + * + * struct idefloppy_format_capacities { + * int nformats; + * struct { + * int nblocks; + * int blocksize; + * } formats[]; + * }; + * + * userland initializes nformats to the number of allocated formats[] records. + * On exit we set nformats to the number of records we've actually initialized. + */ + +static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) { - idefloppy_pc_t pc; - idefloppy_capacity_header_t *header; - idefloppy_capacity_descriptor_t *descriptor; - int i, descriptors, blocks, length; - int u_array_size; - int u_index; + idefloppy_pc_t pc; + u8 header_len, desc_cnt; + int i, blocks, length, u_array_size, u_index; int __user *argp; if (get_user(u_array_size, arg)) @@ -1555,30 +1176,27 @@ static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg) idefloppy_create_read_capacity_cmd(&pc); if (idefloppy_queue_pc_tail(drive, &pc)) { printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); - return (-EIO); - } - header = (idefloppy_capacity_header_t *) pc.buffer; - descriptors = header->length / - sizeof(idefloppy_capacity_descriptor_t); - descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); + return (-EIO); + } + header_len = pc.buffer[3]; + desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ u_index = 0; argp = arg + 1; /* - ** We always skip the first capacity descriptor. That's the - ** current capacity. We are interested in the remaining descriptors, - ** the formattable capacities. - */ + * We always skip the first capacity descriptor. That's the current + * capacity. We are interested in the remaining descriptors, the + * formattable capacities. + */ + for (i = 1; i < desc_cnt; i++) { + unsigned int desc_start = 4 + i*8; - for (i=0; i<descriptors; i++, descriptor++) { if (u_index >= u_array_size) break; /* User-supplied buffer too small */ - if (i == 0) - continue; /* Skip the first descriptor */ - blocks = ntohl(descriptor->blocks); - length = ntohs(descriptor->length); + blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]); + length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]); if (put_user(blocks, argp)) return(-EFAULT); @@ -1597,53 +1215,14 @@ static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg) } /* -** Send ATAPI_FORMAT_UNIT to the drive. -** -** Userland gives us the following structure: -** -** struct idefloppy_format_command { -** int nblocks; -** int blocksize; -** int flags; -** } ; -** -** flags is a bitmask, currently, the only defined flag is: -** -** 0x01 - verify media after format. -*/ - -static int idefloppy_begin_format(ide_drive_t *drive, int __user *arg) -{ - int blocks; - int length; - int flags; - idefloppy_pc_t pc; - - if (get_user(blocks, arg) || - get_user(length, arg+1) || - get_user(flags, arg+2)) { - return (-EFAULT); - } - - /* Get the SFRP bit */ - (void) idefloppy_get_capability_page(drive); - idefloppy_create_format_unit_cmd(&pc, blocks, length, flags); - if (idefloppy_queue_pc_tail(drive, &pc)) { - return (-EIO); - } - - return (0); -} - -/* -** Get ATAPI_FORMAT_UNIT progress indication. -** -** Userland gives a pointer to an int. The int is set to a progress -** indicator 0-65536, with 65536=100%. -** -** If the drive does not support format progress indication, we just check -** the dsc bit, and return either 0 or 65536. -*/ + * Get ATAPI_FORMAT_UNIT progress indication. + * + * Userland gives a pointer to an int. The int is set to a progress + * indicator 0-65536, with 65536=100%. + * + * If the drive does not support format progress indication, we just check + * the dsc bit, and return either 0 or 65536. + */ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg) { @@ -1653,26 +1232,24 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg) if (floppy->srfp) { idefloppy_create_request_sense_cmd(&pc); - if (idefloppy_queue_pc_tail(drive, &pc)) { + if (idefloppy_queue_pc_tail(drive, &pc)) return (-EIO); - } if (floppy->sense_key == 2 && floppy->asc == 4 && - floppy->ascq == 4) { + floppy->ascq == 4) progress_indication = floppy->progress_indication; - } - /* Else assume format_unit has finished, and we're - ** at 0x10000 */ + + /* Else assume format_unit has finished, and we're at 0x10000 */ } else { - atapi_status_t status; unsigned long flags; + u8 stat; local_irq_save(flags); - status.all = HWIF(drive)->INB(IDE_STATUS_REG); + stat = drive->hwif->INB(IDE_STATUS_REG); local_irq_restore(flags); - progress_indication = !status.b.dsc ? 0 : 0x10000; + progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000; } if (put_user(progress_indication, arg)) return (-EFAULT); @@ -1680,10 +1257,7 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg) return (0); } -/* - * Return the current floppy capacity. - */ -static sector_t idefloppy_capacity (ide_drive_t *drive) +static sector_t idefloppy_capacity(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; unsigned long capacity = floppy->blocks * floppy->bs_factor; @@ -1692,16 +1266,12 @@ static sector_t idefloppy_capacity (ide_drive_t *drive) } /* - * idefloppy_identify_device checks if we can support a drive, - * based on the ATAPI IDENTIFY command results. + * Check whether we can support a drive, based on the ATAPI IDENTIFY command + * results. */ -static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id) +static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id) { struct idefloppy_id_gcw gcw; -#if IDEFLOPPY_DEBUG_INFO - u16 mask,i; - char buffer[80]; -#endif /* IDEFLOPPY_DEBUG_INFO */ *((u16 *) &gcw) = id->config; @@ -1710,103 +1280,23 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id) if ((gcw.device_type == 5) && !strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) - gcw.device_type = 0; + gcw.device_type = 0; #endif -#if IDEFLOPPY_DEBUG_INFO - printk(KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n"); - switch (gcw.protocol) { - case 0: case 1: sprintf(buffer, "ATA");break; - case 2: sprintf(buffer, "ATAPI");break; - case 3: sprintf(buffer, "Reserved (Unknown to ide-floppy)");break; - } - printk(KERN_INFO "Protocol Type: %s\n", buffer); - switch (gcw.device_type) { - case 0: sprintf(buffer, "Direct-access Device");break; - case 1: sprintf(buffer, "Streaming Tape Device");break; - case 2: case 3: case 4: sprintf (buffer, "Reserved");break; - case 5: sprintf(buffer, "CD-ROM Device");break; - case 6: sprintf(buffer, "Reserved"); - case 7: sprintf(buffer, "Optical memory Device");break; - case 0x1f: sprintf(buffer, "Unknown or no Device type");break; - default: sprintf(buffer, "Reserved"); - } - printk(KERN_INFO "Device Type: %x - %s\n", gcw.device_type, buffer); - printk(KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No"); - switch (gcw.drq_type) { - case 0: sprintf(buffer, "Microprocessor DRQ");break; - case 1: sprintf(buffer, "Interrupt DRQ");break; - case 2: sprintf(buffer, "Accelerated DRQ");break; - case 3: sprintf(buffer, "Reserved");break; - } - printk(KERN_INFO "Command Packet DRQ Type: %s\n", buffer); - switch (gcw.packet_size) { - case 0: sprintf(buffer, "12 bytes");break; - case 1: sprintf(buffer, "16 bytes");break; - default: sprintf(buffer, "Reserved");break; - } - printk(KERN_INFO "Command Packet Size: %s\n", buffer); - printk(KERN_INFO "Model: %.40s\n",id->model); - printk(KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev); - printk(KERN_INFO "Serial Number: %.20s\n",id->serial_no); - printk(KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512); - printk(KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); - printk(KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); - printk(KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); - printk(KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); - printk(KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); - printk(KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO); - printk(KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA); - printk(KERN_INFO "Single Word DMA supported modes:\n"); - for (i=0,mask=1;i<8;i++,mask=mask << 1) { - if (id->dma_1word & mask) - printk(KERN_INFO " Mode %d%s\n", i, - (id->dma_1word & (mask << 8)) ? " (active)" : ""); - } - printk(KERN_INFO "Multi Word DMA supported modes:\n"); - for (i=0,mask=1;i<8;i++,mask=mask << 1) { - if (id->dma_mword & mask) - printk(KERN_INFO " Mode %d%s\n", i, - (id->dma_mword & (mask << 8)) ? " (active)" : ""); - } - if (id->field_valid & 0x0002) { - printk(KERN_INFO "Enhanced PIO Modes: %s\n", - id->eide_pio_modes & 1 ? "Mode 3":"None"); - if (id->eide_dma_min == 0) - sprintf(buffer, "Not supported"); - else - sprintf(buffer, "%d ns",id->eide_dma_min); - printk(KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer); - if (id->eide_dma_time == 0) - sprintf(buffer, "Not supported"); - else - sprintf(buffer, "%d ns",id->eide_dma_time); - printk(KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer); - if (id->eide_pio == 0) - sprintf(buffer, "Not supported"); - else - sprintf(buffer, "%d ns",id->eide_pio); - printk(KERN_INFO "Minimum PIO cycle without IORDY: %s\n", - buffer); - if (id->eide_pio_iordy == 0) - sprintf(buffer, "Not supported"); - else - sprintf(buffer, "%d ns",id->eide_pio_iordy); - printk(KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer); - } else - printk(KERN_INFO "According to the device, fields 64-70 are not valid.\n"); -#endif /* IDEFLOPPY_DEBUG_INFO */ - if (gcw.protocol != 2) - printk(KERN_ERR "ide-floppy: Protocol is not ATAPI\n"); + printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n", + gcw.protocol); else if (gcw.device_type != 0) - printk(KERN_ERR "ide-floppy: Device type is not set to floppy\n"); + printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set " + "to floppy\n", gcw.device_type); else if (!gcw.removable) printk(KERN_ERR "ide-floppy: The removable flag is not set\n"); else if (gcw.drq_type == 3) { - printk(KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type); + printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not " + "supported\n", gcw.drq_type); } else if (gcw.packet_size != 0) { - printk(KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n"); + printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 " + "bytes long\n", gcw.packet_size); } else return 1; return 0; @@ -1817,59 +1307,53 @@ static void idefloppy_add_settings(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; -/* - * drive setting name read/write data type min max mul_factor div_factor data pointer set function - */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, + &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, + &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, + &drive->bios_sect, NULL); + ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, + &floppy->ticks, NULL); } #else static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } #endif -/* - * Driver initialization. - */ -static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) +static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) { struct idefloppy_id_gcw gcw; *((u16 *) &gcw) = drive->id->config; floppy->pc = floppy->pc_stack; if (gcw.drq_type == 1) - set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); + floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT; /* - * We used to check revisions here. At this point however - * I'm giving up. Just assume they are all broken, its easier. + * We used to check revisions here. At this point however I'm giving up. + * Just assume they are all broken, its easier. * - * The actual reason for the workarounds was likely - * a driver bug after all rather than a firmware bug, - * and the workaround below used to hide it. It should - * be fixed as of version 1.9, but to be on the safe side - * we'll leave the limitation below for the 2.2.x tree. + * The actual reason for the workarounds was likely a driver bug after + * all rather than a firmware bug, and the workaround below used to hide + * it. It should be fixed as of version 1.9, but to be on the safe side + * we'll leave the limitation below for the 2.2.x tree. */ - if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) { - set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags); + floppy->flags |= IDEFLOPPY_FLAG_ZIP_DRIVE; /* This value will be visible in the /proc/ide/hdx/settings */ floppy->ticks = IDEFLOPPY_TICKS_DELAY; blk_queue_max_sectors(drive->queue, 64); } /* - * Guess what? The IOMEGA Clik! drive also needs the - * above fix. It makes nasty clicking noises without - * it, so please don't remove this. - */ + * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes + * nasty clicking noises without it, so please don't remove this. + */ if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) { blk_queue_max_sectors(drive->queue, 64); - set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags); + floppy->flags |= IDEFLOPPY_FLAG_CLIK_DRIVE; } - - (void) idefloppy_get_capacity(drive); + (void) ide_floppy_get_capacity(drive); idefloppy_add_settings(drive); } @@ -1885,7 +1369,7 @@ static void ide_floppy_remove(ide_drive_t *drive) ide_floppy_put(floppy); } -static void ide_floppy_release(struct kref *kref) +static void idefloppy_cleanup_obj(struct kref *kref) { struct ide_floppy_obj *floppy = to_ide_floppy(kref); ide_drive_t *drive = floppy->drive; @@ -1898,19 +1382,19 @@ static void ide_floppy_release(struct kref *kref) } #ifdef CONFIG_IDE_PROC_FS -static int proc_idefloppy_read_capacity - (char *page, char **start, off_t off, int count, int *eof, void *data) +static int proc_idefloppy_read_capacity(char *page, char **start, off_t off, + int count, int *eof, void *data) { ide_drive_t*drive = (ide_drive_t *)data; int len; - len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive)); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + len = sprintf(page, "%llu\n", (long long)idefloppy_capacity(drive)); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static ide_proc_entry_t idefloppy_proc[] = { - { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL }, - { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, + { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL }, + { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { NULL, 0, NULL, NULL } }; #endif /* CONFIG_IDE_PROC_FS */ @@ -1945,9 +1429,10 @@ static int idefloppy_open(struct inode *inode, struct file *filp) idefloppy_pc_t pc; int ret = 0; - debug_log(KERN_INFO "Reached idefloppy_open\n"); + debug_log("Reached %s\n", __func__); - if (!(floppy = ide_floppy_get(disk))) + floppy = ide_floppy_get(disk); + if (!floppy) return -ENXIO; drive = floppy->drive; @@ -1955,7 +1440,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp) floppy->openers++; if (floppy->openers == 1) { - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); + floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS; /* Just in case */ idefloppy_create_test_unit_ready_cmd(&pc); @@ -1964,13 +1449,13 @@ static int idefloppy_open(struct inode *inode, struct file *filp) (void) idefloppy_queue_pc_tail(drive, &pc); } - if (idefloppy_get_capacity (drive) + if (ide_floppy_get_capacity(drive) && (filp->f_flags & O_NDELAY) == 0 /* - ** Allow O_NDELAY to open a drive without a disk, or with - ** an unreadable disk, so that we can get the format - ** capacity of the drive or begin the format - Sam - */ + * Allow O_NDELAY to open a drive without a disk, or with an + * unreadable disk, so that we can get the format capacity + * of the drive or begin the format - Sam + */ ) { ret = -EIO; goto out_put_floppy; @@ -1980,14 +1465,14 @@ static int idefloppy_open(struct inode *inode, struct file *filp) ret = -EROFS; goto out_put_floppy; } - set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); + floppy->flags |= IDEFLOPPY_FLAG_MEDIA_CHANGED; /* IOMEGA Clik! drives do not support lock/unlock commands */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { + if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) { idefloppy_create_prevent_cmd(&pc, 1); (void) idefloppy_queue_pc_tail(drive, &pc); } check_disk_change(inode->i_bdev); - } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) { + } else if (floppy->flags & IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS) { ret = -EBUSY; goto out_put_floppy; } @@ -2005,17 +1490,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp) struct ide_floppy_obj *floppy = ide_floppy_g(disk); ide_drive_t *drive = floppy->drive; idefloppy_pc_t pc; - - debug_log(KERN_INFO "Reached idefloppy_release\n"); + + debug_log("Reached %s\n", __func__); if (floppy->openers == 1) { /* IOMEGA Clik! drives do not support lock/unlock commands */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { + if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) { idefloppy_create_prevent_cmd(&pc, 0); (void) idefloppy_queue_pc_tail(drive, &pc); } - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); + floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS; } floppy->openers--; @@ -2036,64 +1521,105 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } +static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, + unsigned long arg, unsigned int cmd) +{ + if (floppy->openers > 1) + return -EBUSY; + + /* The IOMEGA Clik! Drive doesn't support this command - + * no room for an eject mechanism */ + if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) { + int prevent = arg ? 1 : 0; + + if (cmd == CDROMEJECT) + prevent = 0; + + idefloppy_create_prevent_cmd(pc, prevent); + (void) idefloppy_queue_pc_tail(floppy->drive, pc); + } + + if (cmd == CDROMEJECT) { + idefloppy_create_start_stop_cmd(pc, 2); + (void) idefloppy_queue_pc_tail(floppy->drive, pc); + } + + return 0; +} + +static int ide_floppy_format_unit(idefloppy_floppy_t *floppy, + int __user *arg) +{ + int blocks, length, flags, err = 0; + idefloppy_pc_t pc; + + if (floppy->openers > 1) { + /* Don't format if someone is using the disk */ + floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS; + return -EBUSY; + } + + floppy->flags |= IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS; + + /* + * Send ATAPI_FORMAT_UNIT to the drive. + * + * Userland gives us the following structure: + * + * struct idefloppy_format_command { + * int nblocks; + * int blocksize; + * int flags; + * } ; + * + * flags is a bitmask, currently, the only defined flag is: + * + * 0x01 - verify media after format. + */ + if (get_user(blocks, arg) || + get_user(length, arg+1) || + get_user(flags, arg+2)) { + err = -EFAULT; + goto out; + } + + (void) idefloppy_get_sfrp_bit(floppy->drive); + idefloppy_create_format_unit_cmd(&pc, blocks, length, flags); + + if (idefloppy_queue_pc_tail(floppy->drive, &pc)) + err = -EIO; + +out: + if (err) + floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS; + return err; +} + + static int idefloppy_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); ide_drive_t *drive = floppy->drive; + idefloppy_pc_t pc; void __user *argp = (void __user *)arg; int err; - int prevent = (arg) ? 1 : 0; - idefloppy_pc_t pc; switch (cmd) { case CDROMEJECT: - prevent = 0; /* fall through */ case CDROM_LOCKDOOR: - if (floppy->openers > 1) - return -EBUSY; - - /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { - idefloppy_create_prevent_cmd(&pc, prevent); - (void) idefloppy_queue_pc_tail(drive, &pc); - } - if (cmd == CDROMEJECT) { - idefloppy_create_start_stop_cmd(&pc, 2); - (void) idefloppy_queue_pc_tail(drive, &pc); - } - return 0; + return ide_floppy_lockdoor(floppy, &pc, arg, cmd); case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: return 0; case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: - return idefloppy_get_format_capacities(drive, argp); + return ide_floppy_get_format_capacities(drive, argp); case IDEFLOPPY_IOCTL_FORMAT_START: - if (!(file->f_mode & 2)) return -EPERM; - if (floppy->openers > 1) { - /* Don't format if someone is using the disk */ - - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, - &floppy->flags); - return -EBUSY; - } - - set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); - - err = idefloppy_begin_format(drive, argp); - if (err) - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); - return err; - /* - ** Note, the bit will be cleared when the device is - ** closed. This is the cleanest way to handle the - ** situation where the drive does not support - ** format progress reporting. - */ + return ide_floppy_format_unit(floppy, (int __user *)arg); case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: return idefloppy_get_format_progress(drive, argp); } @@ -2118,13 +1644,16 @@ static int idefloppy_media_changed(struct gendisk *disk) { struct ide_floppy_obj *floppy = ide_floppy_g(disk); ide_drive_t *drive = floppy->drive; + int ret; /* do not scan partitions twice if this is a removable device */ if (drive->attach) { drive->attach = 0; return 0; } - return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); + ret = !!(floppy->flags & IDEFLOPPY_FLAG_MEDIA_CHANGED); + floppy->flags &= ~IDEFLOPPY_FLAG_MEDIA_CHANGED; + return ret; } static int idefloppy_revalidate_disk(struct gendisk *disk) @@ -2155,16 +1684,20 @@ static int ide_floppy_probe(ide_drive_t *drive) goto failed; if (drive->media != ide_floppy) goto failed; - if (!idefloppy_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name); + if (!idefloppy_identify_device(drive, drive->id)) { + printk(KERN_ERR "ide-floppy: %s: not supported by this version" + " of ide-floppy\n", drive->name); goto failed; } if (drive->scsi) { - printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name); + printk(KERN_INFO "ide-floppy: passing drive %s to ide-scsi" + " emulation.\n", drive->name); goto failed; } - if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { - printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); + floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL); + if (!floppy) { + printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy" + " structure\n", drive->name); goto failed; } @@ -2186,7 +1719,7 @@ static int ide_floppy_probe(ide_drive_t *drive) drive->driver_data = floppy; - idefloppy_setup (drive, floppy); + idefloppy_setup(drive, floppy); g->minors = 1 << PARTN_BITS; g->driverfs_dev = &drive->gendev; @@ -2202,9 +1735,7 @@ failed: return -ENODEV; } -MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); - -static void __exit idefloppy_exit (void) +static void __exit idefloppy_exit(void) { driver_unregister(&idefloppy_driver.gen_driver); } @@ -2219,3 +1750,5 @@ MODULE_ALIAS("ide:*m-floppy*"); module_init(idefloppy_init); module_exit(idefloppy_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); + diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 0f72b98d727..be469dbbe8f 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -14,10 +14,16 @@ static int __init ide_generic_init(void) { + u8 idx[MAX_HWIFS]; + int i; + if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) ide_get_lock(NULL, NULL); /* for atari only */ - (void)ideprobe_init(); + for (i = 0; i < MAX_HWIFS; i++) + idx[i] = ide_hwifs[i].present ? 0xff : i; + + ide_device_add_all(idx, NULL); if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) ide_release_lock(); /* for atari only */ diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index c89f0d3058e..4bddef0c0b9 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -58,15 +58,19 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, unsigned int nr_bytes, int dequeue) { int ret = 1; + int error = 0; + + if (uptodate <= 0) + error = uptodate ? uptodate : -EIO; /* * if failfast is set on a request, override number of sectors and * complete the whole request right now */ - if (blk_noretry_request(rq) && end_io_error(uptodate)) + if (blk_noretry_request(rq) && error) nr_bytes = rq->hard_nr_sectors << 9; - if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors) + if (!blk_fs_request(rq) && error && !rq->errors) rq->errors = -EIO; /* @@ -75,17 +79,12 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq, */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; - HWGROUP(drive)->hwif->ide_dma_on(drive); + ide_dma_on(drive); } - if (!end_that_request_chunk(rq, uptodate, nr_bytes)) { - add_disk_randomness(rq->rq_disk); - if (dequeue) { - if (!list_empty(&rq->queuelist)) - blkdev_dequeue_request(rq); + if (!__blk_end_request(rq, error, nr_bytes)) { + if (dequeue) HWGROUP(drive)->rq = NULL; - } - end_that_request_last(rq, uptodate); ret = 0; } @@ -189,18 +188,14 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * return ide_stopped; } if (ide_id_has_flush_cache_ext(drive->id)) - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; + args->tf.command = WIN_FLUSH_CACHE_EXT; else - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = &task_no_data_intr; - return do_rw_taskfile(drive, args); + args->tf.command = WIN_FLUSH_CACHE; + goto out_do_tf; case idedisk_pm_standby: /* Suspend step 2 (standby) */ - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = &task_no_data_intr; - return do_rw_taskfile(drive, args); + args->tf.command = WIN_STANDBYNOW1; + goto out_do_tf; case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ ide_set_max_pio(drive); @@ -214,10 +209,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * return ide_stopped; case idedisk_pm_idle: /* Resume step 2 (idle) */ - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = task_no_data_intr; - return do_rw_taskfile(drive, args); + args->tf.command = WIN_IDLEIMMEDIATE; + goto out_do_tf; case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */ /* @@ -225,9 +218,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * * we could be smarter and check for current xfer_speed * in struct drive etc... */ - if (drive->hwif->ide_dma_on == NULL) + if (drive->hwif->dma_host_set == NULL) break; - drive->hwif->dma_off_quietly(drive); /* * TODO: respect ->using_dma setting */ @@ -236,6 +228,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * } pm->pm_step = ide_pm_state_completed; return ide_stopped; + +out_do_tf: + args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + args->data_phase = TASKFILE_NO_DATA; + return do_rw_taskfile(drive, args); } /** @@ -292,12 +289,54 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) drive->blocked = 0; blk_start_queue(drive->queue); } - blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - end_that_request_last(rq, 1); + if (__blk_end_request(rq, 0, 0)) + BUG(); spin_unlock_irqrestore(&ide_lock, flags); } +void ide_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data = hwif->INW(IDE_DATA_REG); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG); + + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = hwif->INB(IDE_NSECTOR_REG); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = hwif->INB(IDE_SECTOR_REG); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = hwif->INB(IDE_LCYL_REG); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = hwif->INB(IDE_HCYL_REG); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = hwif->INB(IDE_SELECT_REG); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = hwif->INB(IDE_FEATURE_REG); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = hwif->INB(IDE_SECTOR_REG); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = hwif->INB(IDE_LCYL_REG); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = hwif->INB(IDE_HCYL_REG); + } +} + /** * ide_end_drive_cmd - end an explicit drive command * @drive: command @@ -314,7 +353,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) { - ide_hwif_t *hwif = HWIF(drive); unsigned long flags; struct request *rq; @@ -322,59 +360,18 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) rq = HWGROUP(drive)->rq; spin_unlock_irqrestore(&ide_lock, flags); - if (rq->cmd_type == REQ_TYPE_ATA_CMD) { - u8 *args = (u8 *) rq->buffer; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - args[0] = stat; - args[1] = err; - args[2] = hwif->INB(IDE_NSECTOR_REG); - } - } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { - u8 *args = (u8 *) rq->buffer; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - args[0] = stat; - args[1] = err; - args[2] = hwif->INB(IDE_NSECTOR_REG); - args[3] = hwif->INB(IDE_SECTOR_REG); - args[4] = hwif->INB(IDE_LCYL_REG); - args[5] = hwif->INB(IDE_HCYL_REG); - args[6] = hwif->INB(IDE_SELECT_REG); - } - } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { + if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { ide_task_t *args = (ide_task_t *) rq->special; if (rq->errors == 0) rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); if (args) { - if (args->tf_in_flags.b.data) { - u16 data = hwif->INW(IDE_DATA_REG); - args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; - args->hobRegister[IDE_DATA_OFFSET] = (data >> 8) & 0xFF; - } - args->tfRegister[IDE_ERROR_OFFSET] = err; - /* be sure we're looking at the low order bits */ - hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG); - args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); - args->tfRegister[IDE_STATUS_OFFSET] = stat; - - if (drive->addressing == 1) { - hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); - args->hobRegister[IDE_FEATURE_OFFSET] = hwif->INB(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); - } + struct ide_taskfile *tf = &args->tf; + + tf->error = err; + tf->status = stat; + + ide_tf_read(drive, args); } } else if (blk_pm_request(rq)) { struct request_pm_state *pm = rq->data; @@ -389,10 +386,10 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) } spin_lock_irqsave(&ide_lock, flags); - blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; rq->errors = err; - end_that_request_last(rq, !rq->errors); + if (__blk_end_request(rq, (rq->errors ? -EIO : 0), 0)) + BUG(); spin_unlock_irqrestore(&ide_lock, flags); } @@ -613,89 +610,26 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg) return __ide_abort(drive, rq); } -/** - * ide_cmd - issue a simple drive command - * @drive: drive the command is for - * @cmd: command byte - * @nsect: sector byte - * @handler: handler for the command completion - * - * Issue a simple drive command with interrupts. - * The drive must be selected beforehand. - */ - -static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, - ide_handler_t *handler) +static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) { - ide_hwif_t *hwif = HWIF(drive); - if (IDE_CONTROL_REG) - hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(drive,0); - hwif->OUTB(nsect,IDE_NSECTOR_REG); - ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL); + tf->nsect = drive->sect; + tf->lbal = drive->sect; + tf->lbam = drive->cyl; + tf->lbah = drive->cyl >> 8; + tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA; + tf->command = WIN_SPECIFY; } -/** - * drive_cmd_intr - drive command completion interrupt - * @drive: drive the completion interrupt occurred on - * - * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. - * We do any necessary data reading and then wait for the drive to - * go non busy. At that point we may read the error data and complete - * the request - */ - -static ide_startstop_t drive_cmd_intr (ide_drive_t *drive) +static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf) { - struct request *rq = HWGROUP(drive)->rq; - ide_hwif_t *hwif = HWIF(drive); - u8 *args = (u8 *) rq->buffer; - u8 stat = hwif->INB(IDE_STATUS_REG); - int retries = 10; - - local_irq_enable_in_hardirq(); - if ((stat & DRQ_STAT) && args && args[3]) { - u8 io_32bit = drive->io_32bit; - drive->io_32bit = 0; - hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); - drive->io_32bit = io_32bit; - while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) - udelay(100); - } - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "drive_cmd", stat); - /* calls ide_end_drive_cmd */ - ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); - return ide_stopped; + tf->nsect = drive->sect; + tf->command = WIN_RESTORE; } -static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task) +static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) { - task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; - task->tfRegister[IDE_SECTOR_OFFSET] = drive->sect; - task->tfRegister[IDE_LCYL_OFFSET] = drive->cyl; - task->tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; - task->tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; - task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; - - task->handler = &set_geometry_intr; -} - -static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task) -{ - task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; - task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; - - task->handler = &recal_intr; -} - -static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task) -{ - task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; - task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; - - task->handler = &set_multmode_intr; + tf->nsect = drive->mult_req; + tf->command = WIN_SETMULT; } static ide_startstop_t ide_disk_special(ide_drive_t *drive) @@ -704,19 +638,19 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); - args.command_type = IDE_DRIVE_TASK_NO_DATA; + args.data_phase = TASKFILE_NO_DATA; if (s->b.set_geometry) { s->b.set_geometry = 0; - ide_init_specify_cmd(drive, &args); + ide_tf_set_specify_cmd(drive, &args.tf); } else if (s->b.recalibrate) { s->b.recalibrate = 0; - ide_init_restore_cmd(drive, &args); + ide_tf_set_restore_cmd(drive, &args.tf); } else if (s->b.set_multmode) { s->b.set_multmode = 0; if (drive->mult_req > drive->id->max_multsect) drive->mult_req = drive->id->max_multsect; - ide_init_setmult_cmd(drive, &args); + ide_tf_set_setmult_cmd(drive, &args.tf); } else if (s->all) { int special = s->all; s->all = 0; @@ -724,6 +658,9 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) return ide_stopped; } + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE | + IDE_TFLAG_CUSTOM_HANDLER; + do_rw_taskfile(drive, &args); return ide_started; @@ -798,7 +735,7 @@ static ide_startstop_t do_special (ide_drive_t *drive) if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { if (keep_dma) - hwif->ide_dma_on(drive); + ide_dma_on(drive); } } @@ -858,13 +795,10 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = HWIF(drive); - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { - ide_task_t *args = rq->special; - - if (!args) - goto done; + ide_task_t *task = rq->special; - hwif->data_phase = args->data_phase; + if (task) { + hwif->data_phase = task->data_phase; switch (hwif->data_phase) { case TASKFILE_MULTI_OUT: @@ -877,61 +811,9 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, break; } - if (args->tf_out_flags.all != 0) - return flagged_taskfile(drive, args); - return do_rw_taskfile(drive, args); - } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { - u8 *args = rq->buffer; - u8 sel; - - if (!args) - goto done; -#ifdef DEBUG - printk("%s: DRIVE_TASK_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("fr=0x%02x ", args[1]); - printk("ns=0x%02x ", args[2]); - printk("sc=0x%02x ", args[3]); - printk("lcyl=0x%02x ", args[4]); - printk("hcyl=0x%02x ", args[5]); - printk("sel=0x%02x\n", args[6]); -#endif - hwif->OUTB(args[1], IDE_FEATURE_REG); - hwif->OUTB(args[3], IDE_SECTOR_REG); - hwif->OUTB(args[4], IDE_LCYL_REG); - hwif->OUTB(args[5], IDE_HCYL_REG); - sel = (args[6] & ~0x10); - if (drive->select.b.unit) - sel |= 0x10; - hwif->OUTB(sel, IDE_SELECT_REG); - ide_cmd(drive, args[0], args[2], &drive_cmd_intr); - return ide_started; - } else if (rq->cmd_type == REQ_TYPE_ATA_CMD) { - u8 *args = rq->buffer; - - if (!args) - goto done; -#ifdef DEBUG - printk("%s: DRIVE_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("sc=0x%02x ", args[1]); - printk("fr=0x%02x ", args[2]); - printk("xx=0x%02x\n", args[3]); -#endif - if (args[0] == WIN_SMART) { - hwif->OUTB(0x4f, IDE_LCYL_REG); - hwif->OUTB(0xc2, IDE_HCYL_REG); - hwif->OUTB(args[2],IDE_FEATURE_REG); - hwif->OUTB(args[1],IDE_SECTOR_REG); - ide_cmd(drive, args[0], args[3], &drive_cmd_intr); - return ide_started; - } - hwif->OUTB(args[2],IDE_FEATURE_REG); - ide_cmd(drive, args[0], args[1], &drive_cmd_intr); - return ide_started; - } - -done: + return do_rw_taskfile(drive, task); + } + /* * NULL is actually a valid way of waiting for * all current requests to be flushed from the queue. @@ -971,7 +853,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) if (rc) printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); SELECT_DRIVE(drive); - HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); + ide_set_irq(drive, 1); rc = ide_wait_not_busy(HWIF(drive), 100000); if (rc) printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); @@ -1003,6 +885,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) /* bail early if we've exceeded max_failures */ if (drive->max_failures && (drive->failures > drive->max_failures)) { + rq->cmd_flags |= REQ_FAILED; goto kill_rq; } @@ -1034,9 +917,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) if (drive->current_speed == 0xff) ide_config_drive_speed(drive, drive->desired_speed); - if (rq->cmd_type == REQ_TYPE_ATA_CMD || - rq->cmd_type == REQ_TYPE_ATA_TASK || - rq->cmd_type == REQ_TYPE_ATA_TASKFILE) + if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) return execute_drive_cmd(drive, rq); else if (blk_pm_request(rq)) { struct request_pm_state *pm = rq->data; @@ -1244,11 +1125,13 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) } again: hwif = HWIF(drive); - if (hwgroup->hwif->sharing_irq && - hwif != hwgroup->hwif && - hwif->io_ports[IDE_CONTROL_OFFSET]) { - /* set nIEN for previous hwif */ - SELECT_INTERRUPT(drive); + if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) { + /* + * set nIEN for previous hwif, drives in the + * quirk_list may not like intr setups/cleanups + */ + if (drive->quirk_list != 1) + ide_set_irq(drive, 0); } hwgroup->hwif = hwif; hwgroup->drive = drive; @@ -1361,7 +1244,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) */ drive->retry_pio++; drive->state = DMA_PIO_RETRY; - hwif->dma_off_quietly(drive); + ide_dma_off_quietly(drive); /* * un-busy drive etc (hwgroup->busy is cleared on return) and @@ -1454,12 +1337,8 @@ void ide_timer_expiry (unsigned long data) */ spin_unlock(&ide_lock); hwif = HWIF(drive); -#if DISABLE_IRQ_NOSYNC - disable_irq_nosync(hwif->irq); -#else /* disable_irq_nosync ?? */ disable_irq(hwif->irq); -#endif /* DISABLE_IRQ_NOSYNC */ /* local CPU only, * as if we were handling an interrupt */ local_irq_disable(); @@ -1608,7 +1487,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) * remove all the ifdef PCI crap */ #ifdef CONFIG_BLK_DEV_IDEPCI - if (hwif->pci_dev && !hwif->pci_dev->vendor) + if (hwif->chipset != ide_pci) #endif /* CONFIG_BLK_DEV_IDEPCI */ { /* @@ -1710,7 +1589,6 @@ irqreturn_t ide_intr (int irq, void *dev_id) void ide_init_drive_cmd (struct request *rq) { memset(rq, 0, sizeof(*rq)); - rq->cmd_type = REQ_TYPE_ATA_CMD; rq->ref_count = 1; } @@ -1785,3 +1663,19 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio } EXPORT_SYMBOL(ide_do_drive_cmd); + +void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma) +{ + ide_task_t task; + + memset(&task, 0, sizeof(task)); + task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | + IDE_TFLAG_OUT_FEATURE | tf_flags; + task.tf.feature = dma; /* Use PIO/DMA */ + task.tf.lbam = bcount & 0xff; + task.tf.lbah = (bcount >> 8) & 0xff; + + ide_tf_load(drive, &task); +} + +EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load); diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index dcda0f109df..a95178f5e1b 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/ide-iops.c Version 0.37 Mar 05, 2003 - * * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> * @@ -158,14 +156,6 @@ void default_hwif_mmiops (ide_hwif_t *hwif) EXPORT_SYMBOL(default_hwif_mmiops); -u32 ide_read_24 (ide_drive_t *drive) -{ - u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG); - u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG); - u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG); - return (hcyl<<16)|(lcyl<<8)|sect; -} - void SELECT_DRIVE (ide_drive_t *drive) { if (HWIF(drive)->selectproc) @@ -173,28 +163,12 @@ void SELECT_DRIVE (ide_drive_t *drive) HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG); } -EXPORT_SYMBOL(SELECT_DRIVE); - -void SELECT_INTERRUPT (ide_drive_t *drive) -{ - if (HWIF(drive)->intrproc) - HWIF(drive)->intrproc(drive); - else - HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG); -} - void SELECT_MASK (ide_drive_t *drive, int mask) { if (HWIF(drive)->maskproc) HWIF(drive)->maskproc(drive, mask); } -void QUIRK_LIST (ide_drive_t *drive) -{ - if (HWIF(drive)->quirkproc) - drive->quirk_list = HWIF(drive)->quirkproc(drive); -} - /* * Some localbus EIDE interfaces require a special access sequence * when using 32-bit I/O instructions to transfer data. We call this @@ -303,9 +277,6 @@ void default_hwif_transport(ide_hwif_t *hwif) hwif->atapi_output_bytes = atapi_output_bytes; } -/* - * Beginning of Taskfile OPCODE Library and feature sets. - */ void ide_fix_driveid (struct hd_driveid *id) { #ifndef __LITTLE_ENDIAN @@ -403,8 +374,12 @@ void ide_fix_driveid (struct hd_driveid *id) #endif } -/* FIXME: exported for use by the USB storage (isd200.c) code only */ -EXPORT_SYMBOL(ide_fix_driveid); +/* + * ide_fixstring() cleans up and (optionally) byte-swaps a text string, + * removing leading/trailing blanks and compressing internal blanks. + * It is primarily used to tidy up the model name/number fields as + * returned by the WIN_[P]IDENTIFY commands. + */ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) { @@ -448,7 +423,6 @@ int drive_is_ready (ide_drive_t *drive) udelay(1); #endif -#ifdef CONFIG_IDEPCI_SHARE_IRQ /* * We do a passive status test under shared PCI interrupts on * cards that truly share the ATA side interrupt, but may also share @@ -458,7 +432,6 @@ int drive_is_ready (ide_drive_t *drive) if (IDE_CONTROL_REG) stat = hwif->INB(IDE_ALTSTATUS_REG); else -#endif /* CONFIG_IDEPCI_SHARE_IRQ */ /* Note: this may clear a pending IRQ!! */ stat = hwif->INB(IDE_STATUS_REG); @@ -588,6 +561,9 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list); static const struct drive_list_entry ivb_list[] = { { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, + { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, + { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, + { "TSSTcorp CDDVDW SH-S202N" , "SB01" }, { NULL , NULL } }; @@ -608,12 +584,12 @@ u8 eighty_ninty_three (ide_drive_t *drive) printk(KERN_DEBUG "%s: skipping word 93 validity check\n", drive->name); + if (ide_dev_is_sata(id) && !ivb) + return 1; + if (hwif->cbl != ATA_CBL_PATA80 && !ivb) goto no_80w; - if (ide_dev_is_sata(id)) - return 1; - /* * FIXME: * - force bit13 (80c cable present) check also for !ivb devices @@ -636,66 +612,6 @@ no_80w: return 0; } -int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { - if (eighty_ninty_three(drive) == 0) { - printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " - "be set\n", drive->name); - return 1; - } - } - - return 0; -} - -/* - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ -int set_transfer (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) - return 1; - - return 0; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static u8 ide_auto_reduce_xfer (ide_drive_t *drive) -{ - if (!drive->crc_count) - return drive->current_speed; - drive->crc_count = 0; - - switch(drive->current_speed) { - case XFER_UDMA_7: return XFER_UDMA_6; - case XFER_UDMA_6: return XFER_UDMA_5; - case XFER_UDMA_5: return XFER_UDMA_4; - case XFER_UDMA_4: return XFER_UDMA_3; - case XFER_UDMA_3: return XFER_UDMA_2; - case XFER_UDMA_2: return XFER_UDMA_1; - case XFER_UDMA_1: return XFER_UDMA_0; - /* - * OOPS we do not goto non Ultra DMA modes - * without iCRC's available we force - * the system to PIO and make the user - * invoke the ATA-1 ATA-2 DMA modes. - */ - case XFER_UDMA_0: - default: return XFER_PIO_4; - } -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - int ide_driveid_update(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; @@ -708,8 +624,7 @@ int ide_driveid_update(ide_drive_t *drive) */ SELECT_MASK(drive, 1); - if (IDE_CONTROL_REG) - hwif->OUTB(drive->ctl,IDE_CONTROL_REG); + ide_set_irq(drive, 1); msleep(50); hwif->OUTB(WIN_IDENTIFY, IDE_COMMAND_REG); timeout = jiffies + WAIT_WORSTCASE; @@ -744,6 +659,9 @@ int ide_driveid_update(ide_drive_t *drive) drive->id->dma_1word = id->dma_1word; /* anything more ? */ kfree(id); + + if (drive->using_dma && ide_id_dma_bug(drive)) + ide_dma_off(drive); } return 1; @@ -752,17 +670,21 @@ int ide_driveid_update(ide_drive_t *drive) int ide_config_drive_speed(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = drive->hwif; - int error; + int error = 0; u8 stat; // while (HWGROUP(drive)->busy) // msleep(50); #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->ide_dma_on) /* check if host supports DMA */ - hwif->dma_host_off(drive); + if (hwif->dma_host_set) /* check if host supports DMA */ + hwif->dma_host_set(drive, 0); #endif + /* Skip setting PIO flow-control modes on pre-EIDE drives */ + if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08)) + goto skip; + /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, @@ -785,13 +707,12 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) SELECT_DRIVE(drive); SELECT_MASK(drive, 0); udelay(1); - if (IDE_CONTROL_REG) - hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); + ide_set_irq(drive, 0); hwif->OUTB(speed, IDE_NSECTOR_REG); hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG); hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG); - if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) - hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + if (drive->quirk_list == 2) + ide_set_irq(drive, 1); error = __ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT|ERR_STAT, @@ -810,11 +731,13 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; + skip: #ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0) - hwif->dma_host_on(drive); - else if (hwif->ide_dma_on) /* check if host supports DMA */ - hwif->dma_off_quietly(drive); + if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) && + drive->using_dma) + hwif->dma_host_set(drive, 1); + else if (hwif->dma_host_set) /* check if host supports DMA */ + ide_dma_off_quietly(drive); #endif switch(speed) { @@ -890,28 +813,24 @@ EXPORT_SYMBOL(ide_set_handler); * handler and IRQ setup do not race. All IDE command kick off * should go via this function or do equivalent locking. */ - -void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry) + +void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, + unsigned timeout, ide_expiry_t *expiry) { unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); - + spin_lock_irqsave(&ide_lock, flags); - BUG_ON(hwgroup->handler); - hwgroup->handler = handler; - hwgroup->expiry = expiry; - hwgroup->timer.expires = jiffies + timeout; - hwgroup->req_gen_timer = hwgroup->req_gen; - add_timer(&hwgroup->timer); + __ide_set_handler(drive, handler, timeout, expiry); hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG); - /* Drive takes 400nS to respond, we must avoid the IRQ being - serviced before that. - - FIXME: we could skip this delay with care on non shared - devices - */ + /* + * Drive takes 400nS to respond, we must avoid the IRQ being + * serviced before that. + * + * FIXME: we could skip this delay with care on non shared devices + */ ndelay(400); spin_unlock_irqrestore(&ide_lock, flags); } @@ -1019,19 +938,6 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) return ide_stopped; } -static void check_dma_crc(ide_drive_t *drive) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->crc_count) { - drive->hwif->dma_off_quietly(drive); - ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive)); - if (drive->current_speed >= XFER_SW_DMA_0) - (void) HWIF(drive)->ide_dma_on(drive); - } else - ide_dma_off(drive); -#endif -} - static void ide_disk_pre_reset(ide_drive_t *drive) { int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; @@ -1039,8 +945,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive) drive->special.all = 0; drive->special.b.set_geometry = legacy; drive->special.b.recalibrate = legacy; - if (OK_TO_RESET_CONTROLLER) - drive->mult_count = 0; + drive->mult_count = 0; if (!drive->keep_settings && !drive->using_dma) drive->mult_req = 0; if (drive->mult_req != drive->mult_count) @@ -1054,17 +959,20 @@ static void pre_reset(ide_drive_t *drive) else drive->post_reset = 1; + if (drive->using_dma) { + if (drive->crc_count) + ide_check_dma_crc(drive); + else + ide_dma_off(drive); + } + if (!drive->keep_settings) { - if (drive->using_dma) { - check_dma_crc(drive); - } else { + if (!drive->using_dma) { drive->unmask = 0; drive->io_32bit = 0; } return; } - if (drive->using_dma) - check_dma_crc(drive); if (HWIF(drive)->pre_reset != NULL) HWIF(drive)->pre_reset(drive); @@ -1125,7 +1033,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) for (unit = 0; unit < MAX_DRIVES; ++unit) pre_reset(&hwif->drives[unit]); -#if OK_TO_RESET_CONTROLLER if (!IDE_CONTROL_REG) { spin_unlock_irqrestore(&ide_lock, flags); return ide_stopped; @@ -1162,11 +1069,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) * state when the disks are reset this way. At least, the Winbond * 553 documentation says that */ - if (hwif->resetproc != NULL) { + if (hwif->resetproc) hwif->resetproc(drive); - } - -#endif /* OK_TO_RESET_CONTROLLER */ spin_unlock_irqrestore(&ide_lock, flags); return ide_started; @@ -1185,7 +1089,7 @@ EXPORT_SYMBOL(ide_do_reset); /* * ide_wait_not_busy() waits for the currently selected device on the hwif - * to report a non-busy status, see comments in probe_hwif(). + * to report a non-busy status, see comments in ide_probe_port(). */ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) { diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index af86433baed..b42940d8bf7 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -29,41 +29,44 @@ * Add common non I/O op stuff here. Make sure it has proper * kernel-doc function headers or your patch will be rejected */ - + +static const char *udma_str[] = + { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", + "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; +static const char *mwdma_str[] = + { "MWDMA0", "MWDMA1", "MWDMA2" }; +static const char *swdma_str[] = + { "SWDMA0", "SWDMA1", "SWDMA2" }; +static const char *pio_str[] = + { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; /** * ide_xfer_verbose - return IDE mode names - * @xfer_rate: rate to name + * @mode: transfer mode * * Returns a constant string giving the name of the mode * requested. */ -char *ide_xfer_verbose (u8 xfer_rate) +const char *ide_xfer_verbose(u8 mode) { - switch(xfer_rate) { - case XFER_UDMA_7: return("UDMA 7"); - case XFER_UDMA_6: return("UDMA 6"); - case XFER_UDMA_5: return("UDMA 5"); - case XFER_UDMA_4: return("UDMA 4"); - case XFER_UDMA_3: return("UDMA 3"); - case XFER_UDMA_2: return("UDMA 2"); - case XFER_UDMA_1: return("UDMA 1"); - case XFER_UDMA_0: return("UDMA 0"); - case XFER_MW_DMA_2: return("MW DMA 2"); - case XFER_MW_DMA_1: return("MW DMA 1"); - case XFER_MW_DMA_0: return("MW DMA 0"); - case XFER_SW_DMA_2: return("SW DMA 2"); - case XFER_SW_DMA_1: return("SW DMA 1"); - case XFER_SW_DMA_0: return("SW DMA 0"); - case XFER_PIO_4: return("PIO 4"); - case XFER_PIO_3: return("PIO 3"); - case XFER_PIO_2: return("PIO 2"); - case XFER_PIO_1: return("PIO 1"); - case XFER_PIO_0: return("PIO 0"); - case XFER_PIO_SLOW: return("PIO SLOW"); - default: return("XFER ERROR"); - } + const char *s; + u8 i = mode & 0xf; + + if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) + s = udma_str[i]; + else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2) + s = mwdma_str[i]; + else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) + s = swdma_str[i]; + else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5) + s = pio_str[i & 0x7]; + else if (mode == XFER_PIO_SLOW) + s = "PIO SLOW"; + else + s = "XFER ERROR"; + + return s; } EXPORT_SYMBOL(ide_xfer_verbose); @@ -355,8 +358,10 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) if (!PCI_DMA_BUS_IS_PHYS) { addr = BLK_BOUNCE_ANY; } else if (on && drive->media == ide_disk) { - if (HWIF(drive)->pci_dev) - addr = HWIF(drive)->pci_dev->dma_mask; + struct device *dev = drive->hwif->dev; + + if (dev && dev->dma_mask) + addr = *dev->dma_mask; } if (drive->queue) @@ -438,6 +443,12 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) * case could happen iff the transfer mode has already been set on * the device by ide-proc.c::set_xfer_rate()). */ + if (rate < XFER_PIO_0) { + if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE) + return ide_set_dma_mode(drive, rate); + else + return ide_config_drive_speed(drive, rate); + } return ide_set_dma_mode(drive, rate); } @@ -445,8 +456,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) static void ide_dump_opcode(ide_drive_t *drive) { struct request *rq; - u8 opcode = 0; - int found = 0; + ide_task_t *task = NULL; spin_lock(&ide_lock); rq = NULL; @@ -455,163 +465,129 @@ static void ide_dump_opcode(ide_drive_t *drive) spin_unlock(&ide_lock); if (!rq) return; - if (rq->cmd_type == REQ_TYPE_ATA_CMD || - rq->cmd_type == REQ_TYPE_ATA_TASK) { - char *args = rq->buffer; - if (args) { - opcode = args[0]; - found = 1; - } - } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { - ide_task_t *args = rq->special; - if (args) { - task_struct_t *tf = (task_struct_t *) args->tfRegister; - opcode = tf->command; - found = 1; - } - } + + if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) + task = rq->special; printk("ide: failed opcode was: "); - if (!found) - printk("unknown\n"); + if (task == NULL) + printk(KERN_CONT "unknown\n"); else - printk("0x%02x\n", opcode); + printk(KERN_CONT "0x%02x\n", task->tf.command); } -static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) +u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48) { - ide_hwif_t *hwif = HWIF(drive); - unsigned long flags; - u8 err = 0; + u32 high, low; - local_irq_save(flags); - printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); - if (stat & BUSY_STAT) - printk("Busy "); - else { - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("DeviceFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); + if (lba48) + high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) | + tf->hob_lbal; + else + high = tf->device & 0xf; + low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal; + + return ((u64)high << 24) | low; +} +EXPORT_SYMBOL_GPL(ide_get_lba_addr); + +static void ide_dump_sector(ide_drive_t *drive) +{ + ide_task_t task; + struct ide_taskfile *tf = &task.tf; + int lba48 = (drive->addressing == 1) ? 1 : 0; + + memset(&task, 0, sizeof(task)); + if (lba48) + task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA | + IDE_TFLAG_LBA48; + else + task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE; + + ide_tf_read(drive, &task); + + if (lba48 || (tf->device & ATA_LBA)) + printk(", LBAsect=%llu", + (unsigned long long)ide_get_lba_addr(tf, lba48)); + else + printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam, + tf->device & 0xf, tf->lbal); +} + +static void ide_dump_ata_error(ide_drive_t *drive, u8 err) +{ + printk("{ "); + if (err & ABRT_ERR) printk("DriveStatusError "); + if (err & ICRC_ERR) + printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); + if (err & ECC_ERR) printk("UncorrectableError "); + if (err & ID_ERR) printk("SectorIdNotFound "); + if (err & TRK0_ERR) printk("TrackZeroNotFound "); + if (err & MARK_ERR) printk("AddrMarkNotFound "); + printk("}"); + if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || + (err & (ECC_ERR|ID_ERR|MARK_ERR))) { + ide_dump_sector(drive); + if (HWGROUP(drive) && HWGROUP(drive)->rq) + printk(", sector=%llu", + (unsigned long long)HWGROUP(drive)->rq->sector); } + printk("\n"); +} + +static void ide_dump_atapi_error(ide_drive_t *drive, u8 err) +{ + printk("{ "); + if (err & ILI_ERR) printk("IllegalLengthIndication "); + if (err & EOM_ERR) printk("EndOfMedia "); + if (err & ABRT_ERR) printk("AbortedCommand "); + if (err & MCR_ERR) printk("MediaChangeRequested "); + if (err & LFS_ERR) printk("LastFailedSense=0x%02x ", + (err & LFS_ERR) >> 4); printk("}\n"); - if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = hwif->INB(IDE_ERROR_REG); - printk("%s: %s: error=0x%02x { ", drive->name, msg, err); - if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) - printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); - if (err & ECC_ERR) printk("UncorrectableError "); - if (err & ID_ERR) printk("SectorIdNotFound "); - if (err & TRK0_ERR) printk("TrackZeroNotFound "); - if (err & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || - (err & (ECC_ERR|ID_ERR|MARK_ERR))) { - if (drive->addressing == 1) { - __u64 sectors = 0; - u32 low = 0, high = 0; - low = ide_read_24(drive); - hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); - high = ide_read_24(drive); - sectors = ((__u64)high << 24) | low; - printk(", LBAsect=%llu, high=%d, low=%d", - (unsigned long long) sectors, - high, low); - } else { - u8 cur = hwif->INB(IDE_SELECT_REG); - if (cur & 0x40) { /* using LBA? */ - printk(", LBAsect=%ld", (unsigned long) - ((cur&0xf)<<24) - |(hwif->INB(IDE_HCYL_REG)<<16) - |(hwif->INB(IDE_LCYL_REG)<<8) - | hwif->INB(IDE_SECTOR_REG)); - } else { - printk(", CHS=%d/%d/%d", - (hwif->INB(IDE_HCYL_REG)<<8) + - hwif->INB(IDE_LCYL_REG), - cur & 0xf, - hwif->INB(IDE_SECTOR_REG)); - } - } - if (HWGROUP(drive) && HWGROUP(drive)->rq) - printk(", sector=%llu", - (unsigned long long)HWGROUP(drive)->rq->sector); - } - printk("\n"); - } - ide_dump_opcode(drive); - local_irq_restore(flags); - return err; } /** - * ide_dump_atapi_status - print human readable atapi status + * ide_dump_status - translate ATA/ATAPI error * @drive: drive that status applies to * @msg: text message to print * @stat: status byte to decode * * Error reporting, in human readable form (luxurious, but a memory hog). + * Combines the drive name, message and status byte to provide a + * user understandable explanation of the device error. */ -static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat) +u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) { unsigned long flags; + u8 err = 0; - atapi_status_t status; - atapi_error_t error; - - status.all = stat; - error.all = 0; local_irq_save(flags); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); - if (status.b.bsy) + if (stat & BUSY_STAT) printk("Busy "); else { - if (status.b.drdy) printk("DriveReady "); - if (status.b.df) printk("DeviceFault "); - if (status.b.dsc) printk("SeekComplete "); - if (status.b.drq) printk("DataRequest "); - if (status.b.corr) printk("CorrectedError "); - if (status.b.idx) printk("Index "); - if (status.b.check) printk("Error "); + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("DeviceFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); } printk("}\n"); - if (status.b.check && !status.b.bsy) { - error.all = HWIF(drive)->INB(IDE_ERROR_REG); - printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all); - if (error.b.ili) printk("IllegalLengthIndication "); - if (error.b.eom) printk("EndOfMedia "); - if (error.b.abrt) printk("AbortedCommand "); - if (error.b.mcr) printk("MediaChangeRequested "); - if (error.b.sense_key) printk("LastFailedSense=0x%02x ", - error.b.sense_key); - printk("}\n"); + if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { + err = drive->hwif->INB(IDE_ERROR_REG); + printk("%s: %s: error=0x%02x ", drive->name, msg, err); + if (drive->media == ide_disk) + ide_dump_ata_error(drive, err); + else + ide_dump_atapi_error(drive, err); } ide_dump_opcode(drive); local_irq_restore(flags); - return error.all; -} - -/** - * ide_dump_status - translate ATA/ATAPI error - * @drive: drive the error occured on - * @msg: information string - * @stat: status byte - * - * Error reporting, in human readable form (luxurious, but a memory hog). - * Combines the drive name, message and status byte to provide a - * user understandable explanation of the device error. - */ - -u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) -{ - if (drive->media == ide_disk) - return ide_dump_ata_status(drive, msg, stat); - return ide_dump_atapi_status(drive, msg, stat); + return err; } EXPORT_SYMBOL(ide_dump_status); diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index e245521af7b..b163b2e5221 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/ide-pnp.c - * * This file provides autodetection for ISA PnP IDE interfaces. * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface. * @@ -31,7 +29,6 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id { hw_regs_t hw; ide_hwif_t *hwif; - int index; if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0))) return -1; @@ -41,11 +38,19 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id pnp_port_start(dev, 1)); hw.irq = pnp_irq(dev, 0); - index = ide_register_hw(&hw, NULL, 1, &hwif); + hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif) { + u8 index = hwif->index; + u8 idx[4] = { index, 0xff, 0xff, 0xff }; + + ide_init_port_data(hwif, index); + ide_init_port_hw(hwif, &hw); - if (index != -1) { - printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index); + printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index); pnp_set_drvdata(dev,hwif); + + ide_device_add(idx, NULL); + return 0; } @@ -55,9 +60,10 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id static void idepnp_remove(struct pnp_dev * dev) { ide_hwif_t *hwif = pnp_get_drvdata(dev); - if (hwif) { - ide_unregister(hwif->index); - } else + + if (hwif) + ide_unregister(hwif->index, 0, 0); + else printk(KERN_ERR "idepnp: Unable to remove device, please report.\n"); } @@ -68,12 +74,15 @@ static struct pnp_driver idepnp_driver = { .remove = idepnp_remove, }; -void __init pnpide_init(void) +static int __init pnpide_init(void) { - pnp_register_driver(&idepnp_driver); + return pnp_register_driver(&idepnp_driver); } -void __exit pnpide_exit(void) +static void __exit pnpide_exit(void) { pnp_unregister_driver(&idepnp_driver); } + +module_init(pnpide_init); +module_exit(pnpide_exit); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 6a6f2e066b4..9c07bdb68d1 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1,7 +1,6 @@ /* - * linux/drivers/ide/ide-probe.c Version 1.11 Mar 05, 2003 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) + * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) + * Copyright (C) 2005, 2007 Bartlomiej Zolnierkiewicz */ /* @@ -13,22 +12,8 @@ * * This is the IDE probe module, as evolved from hd.c and ide.c. * - * Version 1.00 move drive probing code from ide.c to ide-probe.c - * Version 1.01 fix compilation problem for m68k - * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot - * by Andrea Arcangeli - * Version 1.03 fix for (hwif->chipset == ide_4drives) - * Version 1.04 fixed buggy treatments of known flash memory cards - * - * Version 1.05 fix for (hwif->chipset == ide_pdc4030) - * added ide6/7/8/9 - * allowed for secondary flash card to be detectable - * with new flag : drive->ata_flash : 1; - * Version 1.06 stream line request queue and prep for cascade project. - * Version 1.07 max_sect <= 255; slower disks would get behind and - * then fall over when they get to 256. Paul G. - * Version 1.10 Update set for new IDE. drive->id is now always - * valid after probe time even with noprobe + * -- increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot + * by Andrea Arcangeli */ #include <linux/module.h> @@ -109,10 +94,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) #ifdef CONFIG_IDEDISK_MULTI_MODE id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; id->multsect_valid = id->multsect ? 1 : 0; - drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; + drive->mult_req = id->multsect_valid ? id->max_multsect : 0; drive->special.b.set_multmode = drive->mult_req ? 1 : 0; #else /* original, pre IDE-NFG, per request of AC */ - drive->mult_req = INITIAL_MULT_COUNT; + drive->mult_req = 0; if (drive->mult_req > id->max_multsect) drive->mult_req = id->max_multsect; if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) @@ -143,6 +128,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) drive->id_read = 1; local_irq_enable(); +#ifdef DEBUG + printk(KERN_INFO "%s: dumping identify data\n", drive->name); + ide_dump_identify((u8 *)id); +#endif ide_fix_driveid(id); #if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) @@ -172,11 +161,12 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap); ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap); + /* we depend on this a lot! */ + id->model[sizeof(id->model)-1] = '\0'; + if (strstr(id->model, "E X A B Y T E N E S T")) goto err_misc; - /* we depend on this a lot! */ - id->model[sizeof(id->model)-1] = '\0'; printk("%s: %s, ", drive->name, id->model); drive->present = 1; drive->dead = 0; @@ -247,7 +237,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) drive->media = ide_disk; printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" ); - QUIRK_LIST(drive); + return; err_misc: @@ -363,22 +353,19 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) * the irq handler isn't expecting. */ if (IDE_CONTROL_REG) { - u8 ctl = drive->ctl | 2; if (!hwif->irq) { autoprobe = 1; cookie = probe_irq_on(); - /* enable device irq */ - ctl &= ~2; } - hwif->OUTB(ctl, IDE_CONTROL_REG); + ide_set_irq(drive, autoprobe); } retval = actual_try_to_identify(drive, cmd); if (autoprobe) { int irq; - /* mask device irq */ - hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); + + ide_set_irq(drive, 0); /* clear drive IRQ */ (void) hwif->INB(IDE_STATUS_REG); udelay(5); @@ -398,6 +385,20 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) return retval; } +static int ide_busy_sleep(ide_hwif_t *hwif) +{ + unsigned long timeout = jiffies + WAIT_WORSTCASE; + u8 stat; + + do { + msleep(50); + stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + if ((stat & BUSY_STAT) == 0) + return 0; + } while (time_before(jiffies, timeout)); + + return 1; +} /** * do_probe - probe an IDE device @@ -422,8 +423,9 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) static int do_probe (ide_drive_t *drive, u8 cmd) { - int rc; ide_hwif_t *hwif = HWIF(drive); + int rc; + u8 stat; if (drive->present) { /* avoid waiting for inappropriate probes */ @@ -460,31 +462,31 @@ static int do_probe (ide_drive_t *drive, u8 cmd) /* failed: try again */ rc = try_to_identify(drive,cmd); } - if (hwif->INB(IDE_STATUS_REG) == (BUSY_STAT|READY_STAT)) + + stat = hwif->INB(IDE_STATUS_REG); + + if (stat == (BUSY_STAT | READY_STAT)) return 4; if ((rc == 1 && cmd == WIN_PIDENTIFY) && ((drive->autotune == IDE_TUNE_DEFAULT) || (drive->autotune == IDE_TUNE_AUTO))) { - unsigned long timeout; - printk("%s: no response (status = 0x%02x), " - "resetting drive\n", drive->name, - hwif->INB(IDE_STATUS_REG)); + printk(KERN_ERR "%s: no response (status = 0x%02x), " + "resetting drive\n", drive->name, stat); msleep(50); hwif->OUTB(drive->select.all, IDE_SELECT_REG); msleep(50); hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); - timeout = jiffies; - while (((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && - time_before(jiffies, timeout + WAIT_WORSTCASE)) - msleep(50); + (void)ide_busy_sleep(hwif); rc = try_to_identify(drive, cmd); } + + /* ensure drive IRQ is clear */ + stat = hwif->INB(IDE_STATUS_REG); + if (rc == 1) - printk("%s: no response (status = 0x%02x)\n", - drive->name, hwif->INB(IDE_STATUS_REG)); - /* ensure drive irq is clear */ - (void) hwif->INB(IDE_STATUS_REG); + printk(KERN_ERR "%s: no response (status = 0x%02x)\n", + drive->name, stat); } else { /* not present or maybe ATAPI */ rc = 3; @@ -505,28 +507,26 @@ static int do_probe (ide_drive_t *drive, u8 cmd) static void enable_nest (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - unsigned long timeout; + u8 stat; printk("%s: enabling %s -- ", hwif->name, drive->id->model); SELECT_DRIVE(drive); msleep(50); hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (time_after(jiffies, timeout)) { - printk("failed (timeout)\n"); - return; - } - msleep(50); - } while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT); + + if (ide_busy_sleep(hwif)) { + printk(KERN_CONT "failed (timeout)\n"); + return; + } msleep(50); - if (!OK_STAT((hwif->INB(IDE_STATUS_REG)), 0, BAD_STAT)) { - printk("failed (status = 0x%02x)\n", hwif->INB(IDE_STATUS_REG)); - } else { - printk("success\n"); - } + stat = hwif->INB(IDE_STATUS_REG); + + if (!OK_STAT(stat, 0, BAD_STAT)) + printk(KERN_CONT "failed (status = 0x%02x)\n", stat); + else + printk(KERN_CONT "success\n"); /* if !(success||timed-out) */ if (do_probe(drive, WIN_IDENTIFY) >= 2) { @@ -620,7 +620,7 @@ static void hwif_release_dev (struct device *dev) complete(&hwif->gendev_rel_comp); } -static void hwif_register (ide_hwif_t *hwif) +static void ide_register_port(ide_hwif_t *hwif) { int ret; @@ -628,8 +628,8 @@ static void hwif_register (ide_hwif_t *hwif) strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE); hwif->gendev.driver_data = hwif; if (hwif->gendev.parent == NULL) { - if (hwif->pci_dev) - hwif->gendev.parent = &hwif->pci_dev->dev; + if (hwif->dev) + hwif->gendev.parent = hwif->dev; else /* Would like to do = &device_legacy */ hwif->gendev.parent = NULL; @@ -641,9 +641,35 @@ static void hwif_register (ide_hwif_t *hwif) __FUNCTION__, ret); } -static int wait_hwif_ready(ide_hwif_t *hwif) +/** + * ide_port_wait_ready - wait for port to become ready + * @hwif: IDE port + * + * This is needed on some PPCs and a bunch of BIOS-less embedded + * platforms. Typical cases are: + * + * - The firmware hard reset the disk before booting the kernel, + * the drive is still doing it's poweron-reset sequence, that + * can take up to 30 seconds. + * + * - The firmware does nothing (or no firmware), the device is + * still in POST state (same as above actually). + * + * - Some CD/DVD/Writer combo drives tend to drive the bus during + * their reset sequence even when they are non-selected slave + * devices, thus preventing discovery of the main HD. + * + * Doing this wait-for-non-busy should not harm any existing + * configuration and fix some issues like the above. + * + * BenH. + * + * Returns 0 on success, error code (< 0) otherwise. + */ + +static int ide_port_wait_ready(ide_hwif_t *hwif) { - int rc; + int unit, rc; printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name); @@ -660,38 +686,43 @@ static int wait_hwif_ready(ide_hwif_t *hwif) return rc; /* Now make sure both master & slave are ready */ - SELECT_DRIVE(&hwif->drives[0]); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - mdelay(2); - rc = ide_wait_not_busy(hwif, 35000); - if (rc) - return rc; - SELECT_DRIVE(&hwif->drives[1]); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - mdelay(2); - rc = ide_wait_not_busy(hwif, 35000); + for (unit = 0; unit < MAX_DRIVES; unit++) { + ide_drive_t *drive = &hwif->drives[unit]; + /* Ignore disks that we will not probe for later. */ + if (!drive->noprobe || drive->present) { + SELECT_DRIVE(drive); + ide_set_irq(drive, 1); + mdelay(2); + rc = ide_wait_not_busy(hwif, 35000); + if (rc) + goto out; + } else + printk(KERN_DEBUG "%s: ide_wait_not_busy() skipped\n", + drive->name); + } +out: /* Exit function with master reselected (let's be sane) */ - SELECT_DRIVE(&hwif->drives[0]); - + if (unit) + SELECT_DRIVE(&hwif->drives[0]); + return rc; } /** * ide_undecoded_slave - look for bad CF adapters - * @hwif: interface + * @drive1: drive * * Analyse the drives on the interface and attempt to decide if we * have the same drive viewed twice. This occurs with crap CF adapters * and PCMCIA sometimes. */ -void ide_undecoded_slave(ide_hwif_t *hwif) +void ide_undecoded_slave(ide_drive_t *drive1) { - ide_drive_t *drive0 = &hwif->drives[0]; - ide_drive_t *drive1 = &hwif->drives[1]; + ide_drive_t *drive0 = &drive1->hwif->drives[0]; - if (drive0->present == 0 || drive1->present == 0) + if ((drive1->dn & 1) == 0 || drive0->present == 0) return; /* If the models don't match they are not the same product */ @@ -714,36 +745,16 @@ void ide_undecoded_slave(ide_hwif_t *hwif) EXPORT_SYMBOL_GPL(ide_undecoded_slave); -/* - * This routine only knows how to look for drive units 0 and 1 - * on an interface, so any setting of MAX_DRIVES > 2 won't work here. - */ -static void probe_hwif(ide_hwif_t *hwif) +static int ide_probe_port(ide_hwif_t *hwif) { unsigned long flags; unsigned int irqd; - int unit; + int unit, rc = -ENODEV; - if (hwif->noprobe) - return; + BUG_ON(hwif->present); - if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) && - (ide_hwif_request_regions(hwif))) { - u16 msgout = 0; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present) { - drive->present = 0; - printk(KERN_ERR "%s: ERROR, PORTS ALREADY IN USE\n", - drive->name); - msgout = 1; - } - } - if (!msgout) - printk(KERN_ERR "%s: ports already in use, skipping probe\n", - hwif->name); - return; - } + if (hwif->noprobe) + return -EACCES; /* * We must always disable IRQ, as probe_for_drive will assert IRQ, but @@ -755,26 +766,7 @@ static void probe_hwif(ide_hwif_t *hwif) local_irq_set(flags); - /* This is needed on some PPCs and a bunch of BIOS-less embedded - * platforms. Typical cases are: - * - * - The firmware hard reset the disk before booting the kernel, - * the drive is still doing it's poweron-reset sequence, that - * can take up to 30 seconds - * - The firmware does nothing (or no firmware), the device is - * still in POST state (same as above actually). - * - Some CD/DVD/Writer combo drives tend to drive the bus during - * their reset sequence even when they are non-selected slave - * devices, thus preventing discovery of the main HD - * - * Doing this wait-for-busy should not harm any existing configuration - * (at least things won't be worse than what current code does, that - * is blindly go & talk to the drive) and fix some issues like the - * above. - * - * BenH. - */ - if (wait_hwif_ready(hwif) == -EBUSY) + if (ide_port_wait_ready(hwif) == -EBUSY) printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name); /* @@ -784,28 +776,15 @@ static void probe_hwif(ide_hwif_t *hwif) ide_drive_t *drive = &hwif->drives[unit]; drive->dn = (hwif->channel ? 2 : 0) + unit; (void) probe_for_drive(drive); - if (drive->present && !hwif->present) { - hwif->present = 1; - if (hwif->chipset != ide_4drives || - !hwif->mate || - !hwif->mate->present) { - hwif_register(hwif); - } - } + if (drive->present) + rc = 0; } if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { - unsigned long timeout = jiffies + WAIT_WORSTCASE; - u8 stat; - printk(KERN_WARNING "%s: reset\n", hwif->name); hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]); udelay(10); hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - do { - msleep(50); - stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); - } while ((stat & BUSY_STAT) && time_after(timeout, jiffies)); - + (void)ide_busy_sleep(hwif); } local_irq_restore(flags); /* @@ -815,13 +794,19 @@ static void probe_hwif(ide_hwif_t *hwif) if (irqd) enable_irq(irqd); - if (!hwif->present) { - ide_hwif_release_regions(hwif); - return; - } + return rc; +} + +static void ide_port_tune_devices(ide_hwif_t *hwif) +{ + int unit; + + for (unit = 0; unit < MAX_DRIVES; unit++) { + ide_drive_t *drive = &hwif->drives[unit]; - if (hwif->fixup) - hwif->fixup(hwif); + if (drive->present && hwif->quirkproc) + hwif->quirkproc(drive); + } for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; @@ -836,48 +821,21 @@ static void probe_hwif(ide_hwif_t *hwif) drive->nice1 = 1; - if (hwif->ide_dma_on) { - /* - * Force DMAing for the beginning of the check. - * Some chipsets appear to do interesting - * things, if not checked and cleared. - * PARANOIA!!! - */ - hwif->dma_off_quietly(drive); + if (hwif->dma_host_set) ide_set_dma(drive); - } } } for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - if (hwif->no_io_32bit) + if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) drive->no_io_32bit = 1; else drive->no_io_32bit = drive->id->dword_io ? 1 : 0; } } -static int hwif_init(ide_hwif_t *hwif); -static void hwif_register_devices(ide_hwif_t *hwif); - -static int probe_hwif_init(ide_hwif_t *hwif) -{ - probe_hwif(hwif); - - if (!hwif_init(hwif)) { - printk(KERN_INFO "%s: failed to initialize IDE interface\n", - hwif->name); - return -1; - } - - if (hwif->present) - hwif_register_devices(hwif); - - return 0; -} - #if MAX_HWIFS > 1 /* * save_match() is used to simplify logic in init_irq() below. @@ -930,13 +888,6 @@ static int ide_init_queue(ide_drive_t *drive) q->queuedata = drive; blk_queue_segment_boundary(q, 0xffff); - if (!hwif->rqsize) { - if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) || - (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA)) - hwif->rqsize = 256; - else - hwif->rqsize = 65536; - } if (hwif->rqsize < max_sectors) max_sectors = hwif->rqsize; blk_queue_max_sectors(q, max_sectors); @@ -967,6 +918,48 @@ static int ide_init_queue(ide_drive_t *drive) return 0; } +static void ide_add_drive_to_hwgroup(ide_drive_t *drive) +{ + ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; + + spin_lock_irq(&ide_lock); + if (!hwgroup->drive) { + /* first drive for hwgroup. */ + drive->next = drive; + hwgroup->drive = drive; + hwgroup->hwif = HWIF(hwgroup->drive); + } else { + drive->next = hwgroup->drive->next; + hwgroup->drive->next = drive; + } + spin_unlock_irq(&ide_lock); +} + +/* + * For any present drive: + * - allocate the block device queue + * - link drive into the hwgroup + */ +static void ide_port_setup_devices(ide_hwif_t *hwif) +{ + int i; + + for (i = 0; i < MAX_DRIVES; i++) { + ide_drive_t *drive = &hwif->drives[i]; + + if (!drive->present) + continue; + + if (ide_init_queue(drive)) { + printk(KERN_ERR "ide: failed to init %s\n", + drive->name); + continue; + } + + ide_add_drive_to_hwgroup(drive); + } +} + /* * This routine sets up the irq for an ide interface, and creates a new * hwgroup for the irq/hwif if none was previously assigned. @@ -974,11 +967,6 @@ static int ide_init_queue(ide_drive_t *drive) * Much of the code is for correctly detecting/handling irq sharing * and irq serialization situations. This is somewhat complex because * it handles static as well as dynamic (PCMCIA) IDE interfaces. - * - * The IRQF_DISABLED in sa_flags means ide_intr() is always entered with - * interrupts completely disabled. This can be bad for interrupt latency, - * but anything else has led to problems on some machines. We re-enable - * interrupts as much as we can safely do in most places. */ static int init_irq (ide_hwif_t *hwif) { @@ -1037,21 +1025,17 @@ static int init_irq (ide_hwif_t *hwif) spin_lock_irq(&ide_lock); hwif->next = hwgroup->hwif->next; hwgroup->hwif->next = hwif; + BUG_ON(hwif->next == hwif); spin_unlock_irq(&ide_lock); } else { - hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), - GFP_KERNEL | __GFP_ZERO, - hwif_to_node(hwif->drives[0].hwif)); - if (!hwgroup) - goto out_up; + hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO, + hwif_to_node(hwif)); + if (hwgroup == NULL) + goto out_up; hwif->hwgroup = hwgroup; + hwgroup->hwif = hwif->next = hwif; - hwgroup->hwif = hwif->next = hwif; - hwgroup->rq = NULL; - hwgroup->handler = NULL; - hwgroup->drive = NULL; - hwgroup->busy = 0; init_timer(&hwgroup->timer); hwgroup->timer.function = &ide_timer_expiry; hwgroup->timer.data = (unsigned long) hwgroup; @@ -1061,17 +1045,13 @@ static int init_irq (ide_hwif_t *hwif) * Allocate the irq, if not already obtained for another hwif */ if (!match || match->irq != hwif->irq) { - int sa = IRQF_DISABLED; + int sa = 0; #if defined(__mc68000__) || defined(CONFIG_APUS) sa = IRQF_SHARED; #endif /* __mc68000__ || CONFIG_APUS */ - if (IDE_CHIPSET_IS_PCI(hwif->chipset)) { + if (IDE_CHIPSET_IS_PCI(hwif->chipset)) sa = IRQF_SHARED; -#ifndef CONFIG_IDEPCI_SHARE_IRQ - sa |= IRQF_DISABLED; -#endif /* CONFIG_IDEPCI_SHARE_IRQ */ - } if (hwif->io_ports[IDE_CONTROL_OFFSET]) /* clear nIEN */ @@ -1081,30 +1061,12 @@ static int init_irq (ide_hwif_t *hwif) goto out_unlink; } - /* - * For any present drive: - * - allocate the block device queue - * - link drive into the hwgroup - */ - for (index = 0; index < MAX_DRIVES; ++index) { - ide_drive_t *drive = &hwif->drives[index]; - if (!drive->present) - continue; - if (ide_init_queue(drive)) { - printk(KERN_ERR "ide: failed to init %s\n",drive->name); - continue; - } - spin_lock_irq(&ide_lock); - if (!hwgroup->drive) { - /* first drive for hwgroup. */ - drive->next = drive; - hwgroup->drive = drive; - hwgroup->hwif = HWIF(hwgroup->drive); - } else { - drive->next = hwgroup->drive->next; - hwgroup->drive->next = drive; - } - spin_unlock_irq(&ide_lock); + if (!hwif->rqsize) { + if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) || + (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA)) + hwif->rqsize = 256; + else + hwif->rqsize = 65536; } #if !defined(__mc68000__) && !defined(CONFIG_APUS) @@ -1120,28 +1082,13 @@ static int init_irq (ide_hwif_t *hwif) printk(" (%sed with %s)", hwif->sharing_irq ? "shar" : "serializ", match->name); printk("\n"); + + ide_port_setup_devices(hwif); + mutex_unlock(&ide_cfg_mtx); return 0; out_unlink: - spin_lock_irq(&ide_lock); - if (hwif->next == hwif) { - BUG_ON(match); - BUG_ON(hwgroup->hwif != hwif); - kfree(hwgroup); - } else { - ide_hwif_t *g; - g = hwgroup->hwif; - while (g->next != hwif) - g = g->next; - g->next = hwif->next; - if (hwgroup->hwif == hwif) { - /* Impossible. */ - printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n"); - hwgroup->hwif = g; - } - BUG_ON(hwgroup->hwif == hwif); - } - spin_unlock_irq(&ide_lock); + ide_remove_port_from_hwgroup(hwif); out_up: mutex_unlock(&ide_cfg_mtx); return 1; @@ -1179,7 +1126,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data) { struct gendisk *p = data; *part &= (1 << PARTN_BITS) - 1; - return &p->kobj; + return &p->dev.kobj; } static int exact_lock(dev_t dev, void *data) @@ -1262,56 +1209,25 @@ static void drive_release_dev (struct device *dev) complete(&drive->gendev_rel_comp); } -/* - * init_gendisk() (as opposed to ide_geninit) is called for each major device, - * after probing for drives, to allocate partition tables and other data - * structures needed for the routines in genhd.c. ide_geninit() gets called - * somewhat later, during the partition check. - */ -static void init_gendisk (ide_hwif_t *hwif) -{ - unsigned int unit; - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t * drive = &hwif->drives[unit]; - ide_add_generic_settings(drive); - snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u", - hwif->index,unit); - drive->gendev.parent = &hwif->gendev; - drive->gendev.bus = &ide_bus_type; - drive->gendev.driver_data = drive; - drive->gendev.release = drive_release_dev; - } - blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS, - THIS_MODULE, ata_probe, ata_lock, hwif); -} - static int hwif_init(ide_hwif_t *hwif) { int old_irq; - /* Return success if no device is connected */ - if (!hwif->present) - return 1; - if (!hwif->irq) { if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { printk("%s: DISABLED, NO IRQ\n", hwif->name); - return (hwif->present = 0); + return 0; } } #ifdef CONFIG_BLK_DEV_HD if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) { printk("%s: CANNOT SHARE IRQ WITH OLD " "HARDDISK DRIVER (hd.c)\n", hwif->name); - return (hwif->present = 0); + return 0; } #endif /* CONFIG_BLK_DEV_HD */ - /* we set it back to 1 if all is ok below */ - hwif->present = 0; - if (register_blkdev(hwif->major, hwif->name)) return 0; @@ -1349,11 +1265,8 @@ static int hwif_init(ide_hwif_t *hwif) hwif->name, hwif->irq); done: - init_gendisk(hwif); - - ide_acpi_init(hwif); - - hwif->present = 1; /* success */ + blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS, + THIS_MODULE, ata_probe, ata_lock, hwif); return 1; out: @@ -1367,66 +1280,204 @@ static void hwif_register_devices(ide_hwif_t *hwif) for (i = 0; i < MAX_DRIVES; i++) { ide_drive_t *drive = &hwif->drives[i]; + struct device *dev = &drive->gendev; + int ret; - if (drive->present) { - int ret = device_register(&drive->gendev); + if (!drive->present) + continue; - if (ret < 0) - printk(KERN_WARNING "IDE: %s: " - "device_register error: %d\n", - __FUNCTION__, ret); - } + ide_add_generic_settings(drive); + + snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i); + dev->parent = &hwif->gendev; + dev->bus = &ide_bus_type; + dev->driver_data = drive; + dev->release = drive_release_dev; + + ret = device_register(dev); + if (ret < 0) + printk(KERN_WARNING "IDE: %s: device_register error: " + "%d\n", __func__, ret); } } -int ideprobe_init (void) +static void ide_port_init_devices(ide_hwif_t *hwif) { - unsigned int index; - int probe[MAX_HWIFS]; - - memset(probe, 0, MAX_HWIFS * sizeof(int)); - for (index = 0; index < MAX_HWIFS; ++index) - probe[index] = !ide_hwifs[index].present; - - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - probe_hwif(&ide_hwifs[index]); - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - hwif_init(&ide_hwifs[index]); - for (index = 0; index < MAX_HWIFS; ++index) { - if (probe[index]) { - ide_hwif_t *hwif = &ide_hwifs[index]; - if (!hwif->present) - continue; - if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) - hwif->chipset = ide_generic; - hwif_register_devices(hwif); - } + int i; + + for (i = 0; i < MAX_DRIVES; i++) { + ide_drive_t *drive = &hwif->drives[i]; + + if (hwif->host_flags & IDE_HFLAG_IO_32BIT) + drive->io_32bit = 1; + if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS) + drive->unmask = 1; + if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS) + drive->no_unmask = 1; + if ((hwif->host_flags & IDE_HFLAG_NO_AUTOTUNE) == 0) + drive->autotune = 1; } - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - ide_proc_register_port(&ide_hwifs[index]); - return 0; + + if (hwif->port_init_devs) + hwif->port_init_devs(hwif); } -EXPORT_SYMBOL_GPL(ideprobe_init); +static void ide_init_port(ide_hwif_t *hwif, unsigned int port, + const struct ide_port_info *d) +{ + if (d->chipset != ide_etrax100) + hwif->channel = port; + + if (d->chipset) + hwif->chipset = d->chipset; + + if (d->init_iops) + d->init_iops(hwif); + + if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) + ide_hwif_setup_dma(hwif, d); + + if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || + (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) + hwif->irq = port ? 15 : 14; + + hwif->host_flags = d->host_flags; + hwif->pio_mask = d->pio_mask; + + if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate) + hwif->mate->serialized = hwif->serialized = 1; + + hwif->swdma_mask = d->swdma_mask; + hwif->mwdma_mask = d->mwdma_mask; + hwif->ultra_mask = d->udma_mask; + + /* reset DMA masks only for SFF-style DMA controllers */ + if ((d->host_flags && IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0) + hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0; + + if (d->host_flags & IDE_HFLAG_RQSIZE_256) + hwif->rqsize = 256; + + /* call chipset specific routine for each enabled port */ + if (d->init_hwif) + d->init_hwif(hwif); + + if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) { + if (hwif->cbl != ATA_CBL_PATA40_SHORT) + hwif->cbl = hwif->cable_detect(hwif); + } +} -int ide_device_add(u8 idx[4]) +int ide_device_add_all(u8 *idx, const struct ide_port_info *d) { + ide_hwif_t *hwif, *mate = NULL; int i, rc = 0; - for (i = 0; i < 4; i++) { - if (idx[i] != 0xff) - rc |= probe_hwif_init(&ide_hwifs[idx[i]]); + for (i = 0; i < MAX_HWIFS; i++) { + if (d == NULL || idx[i] == 0xff) { + mate = NULL; + continue; + } + + hwif = &ide_hwifs[idx[i]]; + + if (d->chipset != ide_etrax100 && (i & 1) && mate) { + hwif->mate = mate; + mate->mate = hwif; + } + + mate = (i & 1) ? NULL : hwif; + + ide_init_port(hwif, i & 1, d); + ide_port_init_devices(hwif); + } + + for (i = 0; i < MAX_HWIFS; i++) { + if (idx[i] == 0xff) + continue; + + hwif = &ide_hwifs[idx[i]]; + + if ((hwif->chipset != ide_4drives || !hwif->mate || + !hwif->mate->present) && ide_hwif_request_regions(hwif)) { + printk(KERN_ERR "%s: ports already in use, " + "skipping probe\n", hwif->name); + continue; + } + + if (ide_probe_port(hwif) < 0) { + ide_hwif_release_regions(hwif); + continue; + } + + hwif->present = 1; + + if (hwif->chipset != ide_4drives || !hwif->mate || + !hwif->mate->present) + ide_register_port(hwif); + + ide_port_tune_devices(hwif); + } + + for (i = 0; i < MAX_HWIFS; i++) { + if (idx[i] == 0xff) + continue; + + hwif = &ide_hwifs[idx[i]]; + + if (!hwif->present) + continue; + + if (hwif_init(hwif) == 0) { + printk(KERN_INFO "%s: failed to initialize IDE " + "interface\n", hwif->name); + hwif->present = 0; + rc = -1; + continue; + } + + ide_acpi_init(hwif); + ide_acpi_port_init_devices(hwif); } - for (i = 0; i < 4; i++) { - if (idx[i] != 0xff) - ide_proc_register_port(&ide_hwifs[idx[i]]); + for (i = 0; i < MAX_HWIFS; i++) { + if (idx[i] == 0xff) + continue; + + hwif = &ide_hwifs[idx[i]]; + + if (hwif->present) { + if (hwif->chipset == ide_unknown || + hwif->chipset == ide_forced) + hwif->chipset = ide_generic; + hwif_register_devices(hwif); + } + } + + for (i = 0; i < MAX_HWIFS; i++) { + if (idx[i] == 0xff) + continue; + + hwif = &ide_hwifs[idx[i]]; + + if (hwif->present) { + ide_proc_register_port(hwif); + ide_proc_port_register_devices(hwif); + } } return rc; } +EXPORT_SYMBOL_GPL(ide_device_add_all); +int ide_device_add(u8 idx[4], const struct ide_port_info *d) +{ + u8 idx_all[MAX_HWIFS]; + int i; + + for (i = 0; i < MAX_HWIFS; i++) + idx_all[i] = (i < 4) ? idx[i] : 0xff; + + return ide_device_add_all(idx_all, d); +} EXPORT_SYMBOL_GPL(ide_device_add); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index a4007d30da5..975c0ff0f43 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/ide-proc.c Version 1.05 Mar 05, 2003 - * * Copyright (C) 1997-1998 Mark Lord * Copyright (C) 2003 Red Hat <alan@redhat.com> * @@ -346,14 +344,20 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va static int set_xfer_rate (ide_drive_t *drive, int arg) { + ide_task_t task; int err; if (arg < 0 || arg > 70) return -EINVAL; - err = ide_wait_cmd(drive, - WIN_SETFEATURES, (u8) arg, - SETFEATURES_XFER, 0, NULL); + memset(&task, 0, sizeof(task)); + task.tf.command = WIN_SETFEATURES; + task.tf.feature = SETFEATURES_XFER; + task.tf.nsect = (u8)arg; + task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT | + IDE_TFLAG_IN_NSECT; + + err = ide_no_data_taskfile(drive, &task); if (!err && arg) { ide_set_xfer_rate(drive, (u8) arg); @@ -735,7 +739,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) EXPORT_SYMBOL(ide_proc_unregister_driver); -static void create_proc_ide_drives(ide_hwif_t *hwif) +void ide_proc_port_register_devices(ide_hwif_t *hwif) { int d; struct proc_dir_entry *ent; @@ -789,9 +793,6 @@ static ide_proc_entry_t hwif_entries[] = { void ide_proc_register_port(ide_hwif_t *hwif) { - if (!hwif->present) - return; - if (!hwif->proc) { hwif->proc = proc_mkdir(hwif->name, proc_ide_root); @@ -800,8 +801,6 @@ void ide_proc_register_port(ide_hwif_t *hwif) ide_add_proc_entries(hwif->proc, hwif_entries, hwif); } - - create_proc_ide_drives(hwif); } #ifdef CONFIG_BLK_DEV_IDEPCI diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c new file mode 100644 index 00000000000..93d2e41be85 --- /dev/null +++ b/drivers/ide/ide-scan-pci.c @@ -0,0 +1,116 @@ +/* + * support for probing IDE PCI devices in the PCI bus order + * + * Copyright (c) 1998-2000 Andre Hedrick <andre@linux-ide.org> + * Copyright (c) 1995-1998 Mark Lord + * + * May be copied or modified under the terms of the GNU General Public License + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/ide.h> + +/* + * Module interfaces + */ + +static int pre_init = 1; /* Before first ordered IDE scan */ +static LIST_HEAD(ide_pci_drivers); + +/* + * __ide_pci_register_driver - attach IDE driver + * @driver: pci driver + * @module: owner module of the driver + * + * Registers a driver with the IDE layer. The IDE layer arranges that + * boot time setup is done in the expected device order and then + * hands the controllers off to the core PCI code to do the rest of + * the work. + * + * Returns are the same as for pci_register_driver + */ + +int __ide_pci_register_driver(struct pci_driver *driver, struct module *module, + const char *mod_name) +{ + if (!pre_init) + return __pci_register_driver(driver, module, mod_name); + driver->driver.owner = module; + list_add_tail(&driver->node, &ide_pci_drivers); + return 0; +} +EXPORT_SYMBOL_GPL(__ide_pci_register_driver); + +/** + * ide_scan_pcidev - find an IDE driver for a device + * @dev: PCI device to check + * + * Look for an IDE driver to handle the device we are considering. + * This is only used during boot up to get the ordering correct. After + * boot up the pci layer takes over the job. + */ + +static int __init ide_scan_pcidev(struct pci_dev *dev) +{ + struct list_head *l; + struct pci_driver *d; + + list_for_each(l, &ide_pci_drivers) { + d = list_entry(l, struct pci_driver, node); + if (d->id_table) { + const struct pci_device_id *id = + pci_match_id(d->id_table, dev); + + if (id != NULL && d->probe(dev, id) >= 0) { + dev->driver = d; + pci_dev_get(dev); + return 1; + } + } + } + return 0; +} + +/** + * ide_scan_pcibus - perform the initial IDE driver scan + * + * Perform the initial bus rather than driver ordered scan of the + * PCI drivers. After this all IDE pci handling becomes standard + * module ordering not traditionally ordered. + */ + +static int __init ide_scan_pcibus(void) +{ + struct pci_dev *dev = NULL; + struct pci_driver *d; + struct list_head *l, *n; + + pre_init = 0; + if (!ide_scan_direction) + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev))) + ide_scan_pcidev(dev); + else + while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, + dev))) + ide_scan_pcidev(dev); + + /* + * Hand the drivers over to the PCI layer now we + * are post init. + */ + + list_for_each_safe(l, n, &ide_pci_drivers) { + list_del(l); + d = list_entry(l, struct pci_driver, node); + if (__pci_register_driver(d, d->driver.owner, + d->driver.mod_name)) + printk(KERN_ERR "%s: failed to register %s driver\n", + __FUNCTION__, d->driver.mod_name); + } + + return 0; +} + +module_init(ide_scan_pcibus); diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 7b9181b5469..bf40d8c824a 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1,9 +1,8 @@ /* - * linux/drivers/ide/ide-tape.c Version 1.19 Nov, 2003 - * - * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il> + * IDE ATAPI streaming tape driver. * - * $Header$ + * Copyright (C) 1995-1999 Gadi Oxman <gadio@netvision.net.il> + * Copyright (C) 2003-2005 Bartlomiej Zolnierkiewicz * * This driver was constructed as a student project in the software laboratory * of the faculty of electrical engineering in the Technion - Israel's @@ -11,415 +10,9 @@ * * It is hereby placed under the terms of the GNU general public license. * (See linux/COPYING). - */ - -/* - * IDE ATAPI streaming tape driver. - * - * This driver is a part of the Linux ide driver and works in co-operation - * with linux/drivers/block/ide.c. - * - * The driver, in co-operation with ide.c, basically traverses the - * request-list for the block device interface. The character device - * interface, on the other hand, creates new requests, adds them - * to the request-list of the block device, and waits for their completion. - * - * Pipelined operation mode is now supported on both reads and writes. - * - * The block device major and minor numbers are determined from the - * tape's relative position in the ide interfaces, as explained in ide.c. - * - * The character device interface consists of the following devices: - * - * ht0 major 37, minor 0 first IDE tape, rewind on close. - * ht1 major 37, minor 1 second IDE tape, rewind on close. - * ... - * nht0 major 37, minor 128 first IDE tape, no rewind on close. - * nht1 major 37, minor 129 second IDE tape, no rewind on close. - * ... - * - * Run linux/scripts/MAKEDEV.ide to create the above entries. - * - * The general magnetic tape commands compatible interface, as defined by - * include/linux/mtio.h, is accessible through the character device. - * - * General ide driver configuration options, such as the interrupt-unmask - * flag, can be configured by issuing an ioctl to the block device interface, - * as any other ide device. - * - * Our own ide-tape ioctl's can be issued to either the block device or - * the character device interface. - * - * Maximal throughput with minimal bus load will usually be achieved in the - * following scenario: - * - * 1. ide-tape is operating in the pipelined operation mode. - * 2. No buffering is performed by the user backup program. - * - * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive. - * - * Ver 0.1 Nov 1 95 Pre-working code :-) - * Ver 0.2 Nov 23 95 A short backup (few megabytes) and restore procedure - * was successful ! (Using tar cvf ... on the block - * device interface). - * A longer backup resulted in major swapping, bad - * overall Linux performance and eventually failed as - * we received non serial read-ahead requests from the - * buffer cache. - * Ver 0.3 Nov 28 95 Long backups are now possible, thanks to the - * character device interface. Linux's responsiveness - * and performance doesn't seem to be much affected - * from the background backup procedure. - * Some general mtio.h magnetic tape operations are - * now supported by our character device. As a result, - * popular tape utilities are starting to work with - * ide tapes :-) - * The following configurations were tested: - * 1. An IDE ATAPI TAPE shares the same interface - * and irq with an IDE ATAPI CDROM. - * 2. An IDE ATAPI TAPE shares the same interface - * and irq with a normal IDE disk. - * Both configurations seemed to work just fine ! - * However, to be on the safe side, it is meanwhile - * recommended to give the IDE TAPE its own interface - * and irq. - * The one thing which needs to be done here is to - * add a "request postpone" feature to ide.c, - * so that we won't have to wait for the tape to finish - * performing a long media access (DSC) request (such - * as a rewind) before we can access the other device - * on the same interface. This effect doesn't disturb - * normal operation most of the time because read/write - * requests are relatively fast, and once we are - * performing one tape r/w request, a lot of requests - * from the other device can be queued and ide.c will - * service all of them after this single tape request. - * Ver 1.0 Dec 11 95 Integrated into Linux 1.3.46 development tree. - * On each read / write request, we now ask the drive - * if we can transfer a constant number of bytes - * (a parameter of the drive) only to its buffers, - * without causing actual media access. If we can't, - * we just wait until we can by polling the DSC bit. - * This ensures that while we are not transferring - * more bytes than the constant referred to above, the - * interrupt latency will not become too high and - * we won't cause an interrupt timeout, as happened - * occasionally in the previous version. - * While polling for DSC, the current request is - * postponed and ide.c is free to handle requests from - * the other device. This is handled transparently to - * ide.c. The hwgroup locking method which was used - * in the previous version was removed. - * Use of new general features which are provided by - * ide.c for use with atapi devices. - * (Programming done by Mark Lord) - * Few potential bug fixes (Again, suggested by Mark) - * Single character device data transfers are now - * not limited in size, as they were before. - * We are asking the tape about its recommended - * transfer unit and send a larger data transfer - * as several transfers of the above size. - * For best results, use an integral number of this - * basic unit (which is shown during driver - * initialization). I will soon add an ioctl to get - * this important parameter. - * Our data transfer buffer is allocated on startup, - * rather than before each data transfer. This should - * ensure that we will indeed have a data buffer. - * Ver 1.1 Dec 14 95 Fixed random problems which occurred when the tape - * shared an interface with another device. - * (poll_for_dsc was a complete mess). - * Removed some old (non-active) code which had - * to do with supporting buffer cache originated - * requests. - * The block device interface can now be opened, so - * that general ide driver features like the unmask - * interrupts flag can be selected with an ioctl. - * This is the only use of the block device interface. - * New fast pipelined operation mode (currently only on - * writes). When using the pipelined mode, the - * throughput can potentially reach the maximum - * tape supported throughput, regardless of the - * user backup program. On my tape drive, it sometimes - * boosted performance by a factor of 2. Pipelined - * mode is enabled by default, but since it has a few - * downfalls as well, you may want to disable it. - * A short explanation of the pipelined operation mode - * is available below. - * Ver 1.2 Jan 1 96 Eliminated pipelined mode race condition. - * Added pipeline read mode. As a result, restores - * are now as fast as backups. - * Optimized shared interface behavior. The new behavior - * typically results in better IDE bus efficiency and - * higher tape throughput. - * Pre-calculation of the expected read/write request - * service time, based on the tape's parameters. In - * the pipelined operation mode, this allows us to - * adjust our polling frequency to a much lower value, - * and thus to dramatically reduce our load on Linux, - * without any decrease in performance. - * Implemented additional mtio.h operations. - * The recommended user block size is returned by - * the MTIOCGET ioctl. - * Additional minor changes. - * Ver 1.3 Feb 9 96 Fixed pipelined read mode bug which prevented the - * use of some block sizes during a restore procedure. - * The character device interface will now present a - * continuous view of the media - any mix of block sizes - * during a backup/restore procedure is supported. The - * driver will buffer the requests internally and - * convert them to the tape's recommended transfer - * unit, making performance almost independent of the - * chosen user block size. - * Some improvements in error recovery. - * By cooperating with ide-dma.c, bus mastering DMA can - * now sometimes be used with IDE tape drives as well. - * Bus mastering DMA has the potential to dramatically - * reduce the CPU's overhead when accessing the device, - * and can be enabled by using hdparm -d1 on the tape's - * block device interface. For more info, read the - * comments in ide-dma.c. - * Ver 1.4 Mar 13 96 Fixed serialize support. - * Ver 1.5 Apr 12 96 Fixed shared interface operation, broken in 1.3.85. - * Fixed pipelined read mode inefficiency. - * Fixed nasty null dereferencing bug. - * Ver 1.6 Aug 16 96 Fixed FPU usage in the driver. - * Fixed end of media bug. - * Ver 1.7 Sep 10 96 Minor changes for the CONNER CTT8000-A model. - * Ver 1.8 Sep 26 96 Attempt to find a better balance between good - * interactive response and high system throughput. - * Ver 1.9 Nov 5 96 Automatically cross encountered filemarks rather - * than requiring an explicit FSF command. - * Abort pending requests at end of media. - * MTTELL was sometimes returning incorrect results. - * Return the real block size in the MTIOCGET ioctl. - * Some error recovery bug fixes. - * Ver 1.10 Nov 5 96 Major reorganization. - * Reduced CPU overhead a bit by eliminating internal - * bounce buffers. - * Added module support. - * Added multiple tape drives support. - * Added partition support. - * Rewrote DSC handling. - * Some portability fixes. - * Removed ide-tape.h. - * Additional minor changes. - * Ver 1.11 Dec 2 96 Bug fix in previous DSC timeout handling. - * Use ide_stall_queue() for DSC overlap. - * Use the maximum speed rather than the current speed - * to compute the request service time. - * Ver 1.12 Dec 7 97 Fix random memory overwriting and/or last block data - * corruption, which could occur if the total number - * of bytes written to the tape was not an integral - * number of tape blocks. - * Add support for INTERRUPT DRQ devices. - * Ver 1.13 Jan 2 98 Add "speed == 0" work-around for HP COLORADO 5GB - * Ver 1.14 Dec 30 98 Partial fixes for the Sony/AIWA tape drives. - * Replace cli()/sti() with hwgroup spinlocks. - * Ver 1.15 Mar 25 99 Fix SMP race condition by replacing hwgroup - * spinlock with private per-tape spinlock. - * Ver 1.16 Sep 1 99 Add OnStream tape support. - * Abort read pipeline on EOD. - * Wait for the tape to become ready in case it returns - * "in the process of becoming ready" on open(). - * Fix zero padding of the last written block in - * case the tape block size is larger than PAGE_SIZE. - * Decrease the default disconnection time to tn. - * Ver 1.16e Oct 3 99 Minor fixes. - * Ver 1.16e1 Oct 13 99 Patches by Arnold Niessen, - * niessen@iae.nl / arnold.niessen@philips.com - * GO-1) Undefined code in idetape_read_position - * according to Gadi's email - * AJN-1) Minor fix asc == 11 should be asc == 0x11 - * in idetape_issue_packet_command (did effect - * debugging output only) - * AJN-2) Added more debugging output, and - * added ide-tape: where missing. I would also - * like to add tape->name where possible - * AJN-3) Added different debug_level's - * via /proc/ide/hdc/settings - * "debug_level" determines amount of debugging output; - * can be changed using /proc/ide/hdx/settings - * 0 : almost no debugging output - * 1 : 0+output errors only - * 2 : 1+output all sensekey/asc - * 3 : 2+follow all chrdev related procedures - * 4 : 3+follow all procedures - * 5 : 4+include pc_stack rq_stack info - * 6 : 5+USE_COUNT updates - * AJN-4) Fixed timeout for retension in idetape_queue_pc_tail - * from 5 to 10 minutes - * AJN-5) Changed maximum number of blocks to skip when - * reading tapes with multiple consecutive write - * errors from 100 to 1000 in idetape_get_logical_blk - * Proposed changes to code: - * 1) output "logical_blk_num" via /proc - * 2) output "current_operation" via /proc - * 3) Either solve or document the fact that `mt rewind' is - * required after reading from /dev/nhtx to be - * able to rmmod the idetape module; - * Also, sometimes an application finishes but the - * device remains `busy' for some time. Same cause ? - * Proposed changes to release-notes: - * 4) write a simple `quickstart' section in the - * release notes; I volunteer if you don't want to - * 5) include a pointer to video4linux in the doc - * to stimulate video applications - * 6) release notes lines 331 and 362: explain what happens - * if the application data rate is higher than 1100 KB/s; - * similar approach to lower-than-500 kB/s ? - * 7) 6.6 Comparison; wouldn't it be better to allow different - * strategies for read and write ? - * Wouldn't it be better to control the tape buffer - * contents instead of the bandwidth ? - * 8) line 536: replace will by would (if I understand - * this section correctly, a hypothetical and unwanted situation - * is being described) - * Ver 1.16f Dec 15 99 Change place of the secondary OnStream header frames. - * Ver 1.17 Nov 2000 / Jan 2001 Marcel Mol, marcel@mesa.nl - * - Add idetape_onstream_mode_sense_tape_parameter_page - * function to get tape capacity in frames: tape->capacity. - * - Add support for DI-50 drives( or any DI- drive). - * - 'workaround' for read error/blank block around block 3000. - * - Implement Early warning for end of media for Onstream. - * - Cosmetic code changes for readability. - * - Idetape_position_tape should not use SKIP bit during - * Onstream read recovery. - * - Add capacity, logical_blk_num and first/last_frame_position - * to /proc/ide/hd?/settings. - * - Module use count was gone in the Linux 2.4 driver. - * Ver 1.17a Apr 2001 Willem Riede osst@riede.org - * - Get drive's actual block size from mode sense block descriptor - * - Limit size of pipeline - * Ver 1.17b Oct 2002 Alan Stern <stern@rowland.harvard.edu> - * Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used - * it in the code! - * Actually removed aborted stages in idetape_abort_pipeline - * instead of just changing the command code. - * Made the transfer byte count for Request Sense equal to the - * actual length of the data transfer. - * Changed handling of partial data transfers: they do not - * cause DMA errors. - * Moved initiation of DMA transfers to the correct place. - * Removed reference to unallocated memory. - * Made __idetape_discard_read_pipeline return the number of - * sectors skipped, not the number of stages. - * Replaced errant kfree() calls with __idetape_kfree_stage(). - * Fixed off-by-one error in testing the pipeline length. - * Fixed handling of filemarks in the read pipeline. - * Small code optimization for MTBSF and MTBSFM ioctls. - * Don't try to unlock the door during device close if is - * already unlocked! - * Cosmetic fixes to miscellaneous debugging output messages. - * Set the minimum /proc/ide/hd?/settings values for "pipeline", - * "pipeline_min", and "pipeline_max" to 1. - * - * Here are some words from the first releases of hd.c, which are quoted - * in ide.c and apply here as well: - * - * | Special care is recommended. Have Fun! - * - */ - -/* - * An overview of the pipelined operation mode. - * - * In the pipelined write mode, we will usually just add requests to our - * pipeline and return immediately, before we even start to service them. The - * user program will then have enough time to prepare the next request while - * we are still busy servicing previous requests. In the pipelined read mode, - * the situation is similar - we add read-ahead requests into the pipeline, - * before the user even requested them. - * - * The pipeline can be viewed as a "safety net" which will be activated when - * the system load is high and prevents the user backup program from keeping up - * with the current tape speed. At this point, the pipeline will get - * shorter and shorter but the tape will still be streaming at the same speed. - * Assuming we have enough pipeline stages, the system load will hopefully - * decrease before the pipeline is completely empty, and the backup program - * will be able to "catch up" and refill the pipeline again. - * - * When using the pipelined mode, it would be best to disable any type of - * buffering done by the user program, as ide-tape already provides all the - * benefits in the kernel, where it can be done in a more efficient way. - * As we will usually not block the user program on a request, the most - * efficient user code will then be a simple read-write-read-... cycle. - * Any additional logic will usually just slow down the backup process. - * - * Using the pipelined mode, I get a constant over 400 KBps throughput, - * which seems to be the maximum throughput supported by my tape. * - * However, there are some downfalls: - * - * 1. We use memory (for data buffers) in proportional to the number - * of pipeline stages (each stage is about 26 KB with my tape). - * 2. In the pipelined write mode, we cheat and postpone error codes - * to the user task. In read mode, the actual tape position - * will be a bit further than the last requested block. - * - * Concerning (1): - * - * 1. We allocate stages dynamically only when we need them. When - * we don't need them, we don't consume additional memory. In - * case we can't allocate stages, we just manage without them - * (at the expense of decreased throughput) so when Linux is - * tight in memory, we will not pose additional difficulties. - * - * 2. The maximum number of stages (which is, in fact, the maximum - * amount of memory) which we allocate is limited by the compile - * time parameter IDETAPE_MAX_PIPELINE_STAGES. - * - * 3. The maximum number of stages is a controlled parameter - We - * don't start from the user defined maximum number of stages - * but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we - * will not even allocate this amount of stages if the user - * program can't handle the speed). We then implement a feedback - * loop which checks if the pipeline is empty, and if it is, we - * increase the maximum number of stages as necessary until we - * reach the optimum value which just manages to keep the tape - * busy with minimum allocated memory or until we reach - * IDETAPE_MAX_PIPELINE_STAGES. - * - * Concerning (2): - * - * In pipelined write mode, ide-tape can not return accurate error codes - * to the user program since we usually just add the request to the - * pipeline without waiting for it to be serviced. In case an error - * occurs, I will report it on the next user request. - * - * In the pipelined read mode, subsequent read requests or forward - * filemark spacing will perform correctly, as we preserve all blocks - * and filemarks which we encountered during our excess read-ahead. - * - * For accurate tape positioning and error reporting, disabling - * pipelined mode might be the best option. - * - * You can enable/disable/tune the pipelined operation mode by adjusting - * the compile time parameters below. - */ - -/* - * Possible improvements. - * - * 1. Support for the ATAPI overlap protocol. - * - * In order to maximize bus throughput, we currently use the DSC - * overlap method which enables ide.c to service requests from the - * other device while the tape is busy executing a command. The - * DSC overlap method involves polling the tape's status register - * for the DSC bit, and servicing the other device while the tape - * isn't ready. - * - * In the current QIC development standard (December 1995), - * it is recommended that new tape drives will *in addition* - * implement the ATAPI overlap protocol, which is used for the - * same purpose - efficient use of the IDE bus, but is interrupt - * driven and thus has much less CPU overhead. - * - * ATAPI overlap is likely to be supported in most new ATAPI - * devices, including new ATAPI cdroms, and thus provides us - * a method by which we can achieve higher throughput when - * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. + * For a historical changelog see + * Documentation/ide/ChangeLog.ide-tape.1995-2002 */ #define IDETAPE_VERSION "1.19" @@ -443,49 +36,13 @@ #include <linux/completion.h> #include <linux/bitops.h> #include <linux/mutex.h> +#include <scsi/scsi.h> #include <asm/byteorder.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/unaligned.h> - -/* - * partition - */ -typedef struct os_partition_s { - __u8 partition_num; - __u8 par_desc_ver; - __u16 wrt_pass_cntr; - __u32 first_frame_addr; - __u32 last_frame_addr; - __u32 eod_frame_addr; -} os_partition_t; - -/* - * DAT entry - */ -typedef struct os_dat_entry_s { - __u32 blk_sz; - __u16 blk_cnt; - __u8 flags; - __u8 reserved; -} os_dat_entry_t; - -/* - * DAT - */ -#define OS_DAT_FLAGS_DATA (0xc) -#define OS_DAT_FLAGS_MARK (0x1) - -typedef struct os_dat_s { - __u8 dat_sz; - __u8 reserved1; - __u8 entry_cnt; - __u8 reserved3; - os_dat_entry_t dat_list[16]; -} os_dat_t; - #include <linux/mtio.h> /**************************** Tunable parameters *****************************/ @@ -513,10 +70,7 @@ typedef struct os_dat_s { /* * The following are used to debug the driver: * - * Setting IDETAPE_DEBUG_INFO to 1 will report device capabilities. * Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control. - * Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in - * some places. * * Setting them to 0 will restore normal operation mode: * @@ -528,9 +82,7 @@ typedef struct os_dat_s { * is verified to be stable enough. This will make it much more * esthetic. */ -#define IDETAPE_DEBUG_INFO 0 #define IDETAPE_DEBUG_LOG 0 -#define IDETAPE_DEBUG_BUGS 1 /* * After each failed packet command we issue a request sense command @@ -615,16 +167,6 @@ typedef struct os_dat_s { /*************************** End of tunable parameters ***********************/ /* - * Debugging/Performance analysis - * - * I/O trace support - */ -#define USE_IOTRACE 0 -#if USE_IOTRACE -#define IO_IDETAPE_FIFO 500 -#endif - -/* * Read/Write error simulation */ #define SIMULATE_ERRORS 0 @@ -682,65 +224,6 @@ typedef struct idetape_packet_command_s { #define PC_WRITING 5 /* - * Capabilities and Mechanical Status Page - */ -typedef struct { - unsigned page_code :6; /* Page code - Should be 0x2a */ - __u8 reserved0_6 :1; - __u8 ps :1; /* parameters saveable */ - __u8 page_length; /* Page Length - Should be 0x12 */ - __u8 reserved2, reserved3; - unsigned ro :1; /* Read Only Mode */ - unsigned reserved4_1234 :4; - unsigned sprev :1; /* Supports SPACE in the reverse direction */ - unsigned reserved4_67 :2; - unsigned reserved5_012 :3; - unsigned efmt :1; /* Supports ERASE command initiated formatting */ - unsigned reserved5_4 :1; - unsigned qfa :1; /* Supports the QFA two partition formats */ - unsigned reserved5_67 :2; - unsigned lock :1; /* Supports locking the volume */ - unsigned locked :1; /* The volume is locked */ - unsigned prevent :1; /* The device defaults in the prevent state after power up */ - unsigned eject :1; /* The device can eject the volume */ - __u8 disconnect :1; /* The device can break request > ctl */ - __u8 reserved6_5 :1; - unsigned ecc :1; /* Supports error correction */ - unsigned cmprs :1; /* Supports data compression */ - unsigned reserved7_0 :1; - unsigned blk512 :1; /* Supports 512 bytes block size */ - unsigned blk1024 :1; /* Supports 1024 bytes block size */ - unsigned reserved7_3_6 :4; - unsigned blk32768 :1; /* slowb - the device restricts the byte count for PIO */ - /* transfers for slow buffer memory ??? */ - /* Also 32768 block size in some cases */ - __u16 max_speed; /* Maximum speed supported in KBps */ - __u8 reserved10, reserved11; - __u16 ctl; /* Continuous Transfer Limit in blocks */ - __u16 speed; /* Current Speed, in KBps */ - __u16 buffer_size; /* Buffer Size, in 512 bytes */ - __u8 reserved18, reserved19; -} idetape_capabilities_page_t; - -/* - * Block Size Page - */ -typedef struct { - unsigned page_code :6; /* Page code - Should be 0x30 */ - unsigned reserved1_6 :1; - unsigned ps :1; - __u8 page_length; /* Page Length - Should be 2 */ - __u8 reserved2; - unsigned play32 :1; - unsigned play32_5 :1; - unsigned reserved2_23 :2; - unsigned record32 :1; - unsigned record32_5 :1; - unsigned reserved2_6 :1; - unsigned one :1; -} idetape_block_size_page_t; - -/* * A pipeline stage. */ typedef struct idetape_stage_s { @@ -750,32 +233,6 @@ typedef struct idetape_stage_s { } idetape_stage_t; /* - * REQUEST SENSE packet command result - Data Format. - */ -typedef struct { - unsigned error_code :7; /* Current of deferred errors */ - unsigned valid :1; /* The information field conforms to QIC-157C */ - __u8 reserved1 :8; /* Segment Number - Reserved */ - unsigned sense_key :4; /* Sense Key */ - unsigned reserved2_4 :1; /* Reserved */ - unsigned ili :1; /* Incorrect Length Indicator */ - unsigned eom :1; /* End Of Medium */ - unsigned filemark :1; /* Filemark */ - __u32 information __attribute__ ((packed)); - __u8 asl; /* Additional sense length (n-7) */ - __u32 command_specific; /* Additional command specific information */ - __u8 asc; /* Additional Sense Code */ - __u8 ascq; /* Additional Sense Code Qualifier */ - __u8 replaceable_unit_code; /* Field Replaceable Unit Code */ - unsigned sk_specific1 :7; /* Sense Key Specific */ - unsigned sksv :1; /* Sense Key Specific information is valid */ - __u8 sk_specific2; /* Sense Key Specific */ - __u8 sk_specific3; /* Sense Key Specific */ - __u8 pad[2]; /* Padding to 20 bytes */ -} idetape_request_sense_result_t; - - -/* * Most of our global data which we need to save even as we leave the * driver due to an interrupt or a timer event is stored in a variable * of type idetape_tape_t, defined below. @@ -865,8 +322,9 @@ typedef struct ide_tape_obj { /* Usually 512 or 1024 bytes */ unsigned short tape_block_size; int user_bs_factor; + /* Copy of the tape's Capabilities and Mechanical Page */ - idetape_capabilities_page_t capabilities; + u8 caps[20]; /* * Active data transfer request parameters. @@ -929,9 +387,6 @@ typedef struct ide_tape_obj { int avg_size; int avg_speed; - /* last sense information */ - idetape_request_sense_result_t sense; - char vendor_id[10]; char product_id[18]; char firmware_revision[6]; @@ -1063,27 +518,6 @@ static void ide_tape_put(struct ide_tape_obj *tape) #define IDETAPE_MEDIUM_PRESENT 9 /* - * Supported ATAPI tape drives packet commands - */ -#define IDETAPE_TEST_UNIT_READY_CMD 0x00 -#define IDETAPE_REWIND_CMD 0x01 -#define IDETAPE_REQUEST_SENSE_CMD 0x03 -#define IDETAPE_READ_CMD 0x08 -#define IDETAPE_WRITE_CMD 0x0a -#define IDETAPE_WRITE_FILEMARK_CMD 0x10 -#define IDETAPE_SPACE_CMD 0x11 -#define IDETAPE_INQUIRY_CMD 0x12 -#define IDETAPE_ERASE_CMD 0x19 -#define IDETAPE_MODE_SENSE_CMD 0x1a -#define IDETAPE_MODE_SELECT_CMD 0x15 -#define IDETAPE_LOAD_UNLOAD_CMD 0x1b -#define IDETAPE_PREVENT_CMD 0x1e -#define IDETAPE_LOCATE_CMD 0x2b -#define IDETAPE_READ_POSITION_CMD 0x34 -#define IDETAPE_READ_BUFFER_CMD 0x3c -#define IDETAPE_SET_SPEED_CMD 0xbb - -/* * Some defines for the READ BUFFER command */ #define IDETAPE_RETRIEVE_FAULTY_BLOCK 6 @@ -1140,31 +574,6 @@ struct idetape_id_gcw { }; /* - * INQUIRY packet command - Data Format (From Table 6-8 of QIC-157C) - */ -typedef struct { - unsigned device_type :5; /* Peripheral Device Type */ - unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ - unsigned reserved1_6t0 :7; /* Reserved */ - unsigned rmb :1; /* Removable Medium Bit */ - unsigned ansi_version :3; /* ANSI Version */ - unsigned ecma_version :3; /* ECMA Version */ - unsigned iso_version :2; /* ISO Version */ - unsigned response_format :4; /* Response Data Format */ - unsigned reserved3_45 :2; /* Reserved */ - unsigned reserved3_6 :1; /* TrmIOP - Reserved */ - unsigned reserved3_7 :1; /* AENC - Reserved */ - __u8 additional_length; /* Additional Length (total_length-4) */ - __u8 rsv5, rsv6, rsv7; /* Reserved */ - __u8 vendor_id[8]; /* Vendor Identification */ - __u8 product_id[16]; /* Product Identification */ - __u8 revision_level[4]; /* Revision Level */ - __u8 vendor_specific[20]; /* Vendor Specific - Optional */ - __u8 reserved56t95[40]; /* Reserved - Optional */ - /* Additional information may be returned */ -} idetape_inquiry_result_t; - -/* * READ POSITION packet command - Data Format (From Table 6-57) */ typedef struct { @@ -1182,100 +591,9 @@ typedef struct { u32 bytes_in_buffer; /* Bytes In Buffer (Optional) */ } idetape_read_position_result_t; -/* - * Follows structures which are related to the SELECT SENSE / MODE SENSE - * packet commands. Those packet commands are still not supported - * by ide-tape. - */ +/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */ #define IDETAPE_BLOCK_DESCRIPTOR 0 #define IDETAPE_CAPABILITIES_PAGE 0x2a -#define IDETAPE_PARAMTR_PAGE 0x2b /* Onstream DI-x0 only */ -#define IDETAPE_BLOCK_SIZE_PAGE 0x30 -#define IDETAPE_BUFFER_FILLING_PAGE 0x33 - -/* - * Mode Parameter Header for the MODE SENSE packet command - */ -typedef struct { - __u8 mode_data_length; /* Length of the following data transfer */ - __u8 medium_type; /* Medium Type */ - __u8 dsp; /* Device Specific Parameter */ - __u8 bdl; /* Block Descriptor Length */ -#if 0 - /* data transfer page */ - __u8 page_code :6; - __u8 reserved0_6 :1; - __u8 ps :1; /* parameters saveable */ - __u8 page_length; /* page Length == 0x02 */ - __u8 reserved2; - __u8 read32k :1; /* 32k blk size (data only) */ - __u8 read32k5 :1; /* 32.5k blk size (data&AUX) */ - __u8 reserved3_23 :2; - __u8 write32k :1; /* 32k blk size (data only) */ - __u8 write32k5 :1; /* 32.5k blk size (data&AUX) */ - __u8 reserved3_6 :1; - __u8 streaming :1; /* streaming mode enable */ -#endif -} idetape_mode_parameter_header_t; - -/* - * Mode Parameter Block Descriptor the MODE SENSE packet command - * - * Support for block descriptors is optional. - */ -typedef struct { - __u8 density_code; /* Medium density code */ - __u8 blocks[3]; /* Number of blocks */ - __u8 reserved4; /* Reserved */ - __u8 length[3]; /* Block Length */ -} idetape_parameter_block_descriptor_t; - -/* - * The Data Compression Page, as returned by the MODE SENSE packet command. - */ -typedef struct { - unsigned page_code :6; /* Page Code - Should be 0xf */ - unsigned reserved0 :1; /* Reserved */ - unsigned ps :1; - __u8 page_length; /* Page Length - Should be 14 */ - unsigned reserved2 :6; /* Reserved */ - unsigned dcc :1; /* Data Compression Capable */ - unsigned dce :1; /* Data Compression Enable */ - unsigned reserved3 :5; /* Reserved */ - unsigned red :2; /* Report Exception on Decompression */ - unsigned dde :1; /* Data Decompression Enable */ - __u32 ca; /* Compression Algorithm */ - __u32 da; /* Decompression Algorithm */ - __u8 reserved[4]; /* Reserved */ -} idetape_data_compression_page_t; - -/* - * The Medium Partition Page, as returned by the MODE SENSE packet command. - */ -typedef struct { - unsigned page_code :6; /* Page Code - Should be 0x11 */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned ps :1; - __u8 page_length; /* Page Length - Should be 6 */ - __u8 map; /* Maximum Additional Partitions - Should be 0 */ - __u8 apd; /* Additional Partitions Defined - Should be 0 */ - unsigned reserved4_012 :3; /* Reserved */ - unsigned psum :2; /* Should be 0 */ - unsigned idp :1; /* Should be 0 */ - unsigned sdp :1; /* Should be 0 */ - unsigned fdp :1; /* Fixed Data Partitions */ - __u8 mfr; /* Medium Format Recognition */ - __u8 reserved[2]; /* Reserved */ -} idetape_medium_partition_page_t; - -/* - * Run time configurable parameters. - */ -typedef struct { - int dsc_rw_frequency; - int dsc_media_access_frequency; - int nr_stages; -} idetape_config_t; /* * The variables below are used for the character device interface. @@ -1320,14 +638,12 @@ static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigne int count; while (bcount) { -#if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_input_buffers\n"); idetape_discard_data(drive, bcount); return; } -#endif /* IDETAPE_DEBUG_BUGS */ count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), bcount); HWIF(drive)->atapi_input_bytes(drive, bh->b_data + atomic_read(&bh->b_count), count); bcount -= count; @@ -1347,13 +663,11 @@ static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsign int count; while (bcount) { -#if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_output_buffers\n"); return; } -#endif /* IDETAPE_DEBUG_BUGS */ count = min((unsigned int)pc->b_count, (unsigned int)bcount); HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count); bcount -= count; @@ -1378,13 +692,11 @@ static void idetape_update_buffers (idetape_pc_t *pc) if (test_bit(PC_WRITING, &pc->flags)) return; while (bcount) { -#if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_update_buffers\n"); return; } -#endif /* IDETAPE_DEBUG_BUGS */ count = min((unsigned int)bh->b_size, (unsigned int)bcount); atomic_set(&bh->b_count, count); if (atomic_read(&bh->b_count) == bh->b_size) @@ -1457,36 +769,34 @@ static void idetape_init_pc (idetape_pc_t *pc) } /* - * idetape_analyze_error is called on each failed packet command retry - * to analyze the request sense. We currently do not utilize this - * information. + * called on each failed packet command retry to analyze the request sense. We + * currently do not utilize this information. */ -static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_result_t *result) +static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = tape->failed_pc; - tape->sense = *result; - tape->sense_key = result->sense_key; - tape->asc = result->asc; - tape->ascq = result->ascq; + tape->sense_key = sense[2] & 0xF; + tape->asc = sense[12]; + tape->ascq = sense[13]; #if IDETAPE_DEBUG_LOG /* - * Without debugging, we only log an error if we decided to - * give up retrying. + * Without debugging, we only log an error if we decided to give up + * retrying. */ if (tape->debug_level >= 1) printk(KERN_INFO "ide-tape: pc = %x, sense key = %x, " "asc = %x, ascq = %x\n", - pc->c[0], result->sense_key, - result->asc, result->ascq); + pc->c[0], tape->sense_key, + tape->asc, tape->ascq); #endif /* IDETAPE_DEBUG_LOG */ - /* - * Correct pc->actually_transferred by asking the tape. - */ + /* Correct pc->actually_transferred by asking the tape. */ if (test_bit(PC_DMA_ERROR, &pc->flags)) { - pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned(&result->information)); + pc->actually_transferred = pc->request_transfer - + tape->tape_block_size * + be32_to_cpu(get_unaligned((u32 *)&sense[3])); idetape_update_buffers(pc); } @@ -1495,29 +805,29 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res * with sense key=5, asc=0x22, ascq=0, let it slide. Some drives * (i.e. Seagate STT3401A Travan) don't support 0-length read/writes. */ - if ((pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) - && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) { /* length==0 */ - if (result->sense_key == 5) { + if ((pc->c[0] == READ_6 || pc->c[0] == WRITE_6) + /* length == 0 */ + && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) { + if (tape->sense_key == 5) { /* don't report an error, everything's ok */ pc->error = 0; /* don't retry read/write */ set_bit(PC_ABORT, &pc->flags); } } - if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) { + if (pc->c[0] == READ_6 && (sense[2] & 0x80)) { pc->error = IDETAPE_ERROR_FILEMARK; set_bit(PC_ABORT, &pc->flags); } - if (pc->c[0] == IDETAPE_WRITE_CMD) { - if (result->eom || - (result->sense_key == 0xd && result->asc == 0x0 && - result->ascq == 0x2)) { + if (pc->c[0] == WRITE_6) { + if ((sense[2] & 0x40) || (tape->sense_key == 0xd + && tape->asc == 0x0 && tape->ascq == 0x2)) { pc->error = IDETAPE_ERROR_EOD; set_bit(PC_ABORT, &pc->flags); } } - if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) { - if (result->sense_key == 8) { + if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) { + if (tape->sense_key == 8) { pc->error = IDETAPE_ERROR_EOD; set_bit(PC_ABORT, &pc->flags); } @@ -1527,10 +837,7 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res } } -/* - * idetape_active_next_stage will declare the next stage as "active". - */ -static void idetape_active_next_stage (ide_drive_t *drive) +static void idetape_activate_next_stage(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; idetape_stage_t *stage = tape->next_stage; @@ -1540,12 +847,10 @@ static void idetape_active_next_stage (ide_drive_t *drive) if (tape->debug_level >= 4) printk(KERN_INFO "ide-tape: Reached idetape_active_next_stage\n"); #endif /* IDETAPE_DEBUG_LOG */ -#if IDETAPE_DEBUG_BUGS if (stage == NULL) { printk(KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n"); return; } -#endif /* IDETAPE_DEBUG_BUGS */ rq->rq_disk = tape->disk; rq->buffer = NULL; @@ -1620,28 +925,24 @@ static void idetape_remove_stage_head (ide_drive_t *drive) if (tape->debug_level >= 4) printk(KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n"); #endif /* IDETAPE_DEBUG_LOG */ -#if IDETAPE_DEBUG_BUGS if (tape->first_stage == NULL) { printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n"); - return; + return; } if (tape->active_stage == tape->first_stage) { printk(KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n"); return; } -#endif /* IDETAPE_DEBUG_BUGS */ stage = tape->first_stage; tape->first_stage = stage->next; idetape_kfree_stage(tape, stage); tape->nr_stages--; if (tape->first_stage == NULL) { tape->last_stage = NULL; -#if IDETAPE_DEBUG_BUGS if (tape->next_stage != NULL) printk(KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n"); if (tape->nr_stages) printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 now\n"); -#endif /* IDETAPE_DEBUG_BUGS */ } } @@ -1700,6 +1001,11 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) if (error) tape->failed_pc = NULL; + if (!blk_special_request(rq)) { + ide_end_request(drive, uptodate, nr_sects); + return 0; + } + spin_lock_irqsave(&tape->spinlock, flags); /* The request was a pipelined data transfer request */ @@ -1722,7 +1028,7 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) } } if (tape->next_stage != NULL) { - idetape_active_next_stage(drive); + idetape_activate_next_stage(drive); /* * Insert the next request into the request queue. @@ -1754,7 +1060,7 @@ static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive) printk(KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n"); #endif /* IDETAPE_DEBUG_LOG */ if (!tape->pc->error) { - idetape_analyze_error(drive, (idetape_request_sense_result_t *) tape->pc->buffer); + idetape_analyze_error(drive, tape->pc->buffer); idetape_end_request(drive, 1, 0); } else { printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); @@ -1766,7 +1072,7 @@ static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive) static void idetape_create_request_sense_cmd (idetape_pc_t *pc) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_REQUEST_SENSE_CMD; + pc->c[0] = REQUEST_SENSE; pc->c[4] = 20; pc->request_transfer = 20; pc->callback = &idetape_request_sense_callback; @@ -1818,9 +1124,8 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive) idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc; struct request *rq; - atapi_error_t error; - error.all = HWIF(drive)->INB(IDE_ERROR_REG); + (void)drive->hwif->INB(IDE_ERROR_REG); pc = idetape_next_pc_storage(drive); rq = idetape_next_rq_storage(drive); idetape_create_request_sense_cmd(pc); @@ -1858,15 +1163,13 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; - atapi_status_t status; - atapi_bcount_t bcount; - atapi_ireason_t ireason; idetape_pc_t *pc = tape->pc; - unsigned int temp; #if SIMULATE_ERRORS static int error_sim_count = 0; #endif + u16 bcount; + u8 stat, ireason; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) @@ -1875,10 +1178,10 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) #endif /* IDETAPE_DEBUG_LOG */ /* Clear the interrupt */ - status.all = HWIF(drive)->INB(IDE_STATUS_REG); + stat = hwif->INB(IDE_STATUS_REG); if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { - if (HWIF(drive)->ide_dma_end(drive) || status.b.check) { + if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) { /* * A DMA error is sometimes expected. For example, * if the tape is crossing a filemark during a @@ -1912,7 +1215,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) } /* No more interrupts */ - if (!status.b.drq) { + if ((stat & DRQ_STAT) == 0) { #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred); @@ -1922,23 +1225,23 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) local_irq_enable(); #if SIMULATE_ERRORS - if ((pc->c[0] == IDETAPE_WRITE_CMD || - pc->c[0] == IDETAPE_READ_CMD) && + if ((pc->c[0] == WRITE_6 || pc->c[0] == READ_6) && (++error_sim_count % 100) == 0) { printk(KERN_INFO "ide-tape: %s: simulating error\n", tape->name); - status.b.check = 1; + stat |= ERR_STAT; } #endif - if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) - status.b.check = 0; - if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */ + if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE) + stat &= ~ERR_STAT; + if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) { + /* Error detected */ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 1) printk(KERN_INFO "ide-tape: %s: I/O error\n", tape->name); #endif /* IDETAPE_DEBUG_LOG */ - if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { + if (pc->c[0] == REQUEST_SENSE) { printk(KERN_ERR "ide-tape: I/O error in request sense command\n"); return ide_do_reset(drive); } @@ -1951,7 +1254,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) } pc->error = 0; if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) && - !status.b.dsc) { + (stat & SEEK_STAT) == 0) { /* Media access command */ tape->dsc_polling_start = jiffies; tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST; @@ -1973,30 +1276,30 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) return ide_do_reset(drive); } /* Get the number of bytes to transfer on this interrupt. */ - bcount.b.high = hwif->INB(IDE_BCOUNTH_REG); - bcount.b.low = hwif->INB(IDE_BCOUNTL_REG); + bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) | + hwif->INB(IDE_BCOUNTL_REG); - ireason.all = hwif->INB(IDE_IREASON_REG); + ireason = hwif->INB(IDE_IREASON_REG); - if (ireason.b.cod) { + if (ireason & CD) { printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); return ide_do_reset(drive); } - if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) { + if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ printk(KERN_ERR "ide-tape: We wanted to %s, ", - ireason.b.io ? "Write":"Read"); + (ireason & IO) ? "Write" : "Read"); printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n", - ireason.b.io ? "Read":"Write"); + (ireason & IO) ? "Read" : "Write"); return ide_do_reset(drive); } if (!test_bit(PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ - temp = pc->actually_transferred + bcount.all; + temp = pc->actually_transferred + bcount; if (temp > pc->request_transfer) { if (temp > pc->buffer_size) { printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); - idetape_discard_data(drive, bcount.all); + idetape_discard_data(drive, bcount); ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); return ide_started; } @@ -2008,23 +1311,26 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) } if (test_bit(PC_WRITING, &pc->flags)) { if (pc->bh != NULL) - idetape_output_buffers(drive, pc, bcount.all); + idetape_output_buffers(drive, pc, bcount); else /* Write the current buffer */ - HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all); + hwif->atapi_output_bytes(drive, pc->current_position, + bcount); } else { if (pc->bh != NULL) - idetape_input_buffers(drive, pc, bcount.all); + idetape_input_buffers(drive, pc, bcount); else /* Read the current buffer */ - HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all); + hwif->atapi_input_bytes(drive, pc->current_position, + bcount); } /* Update the current position */ - pc->actually_transferred += bcount.all; - pc->current_position += bcount.all; + pc->actually_transferred += bcount; + pc->current_position += bcount; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); + printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes " + "on that interrupt\n", pc->c[0], bcount); #endif /* And set the interrupt handler again */ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); @@ -2078,28 +1384,28 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = tape->pc; - atapi_ireason_t ireason; int retries = 100; ide_startstop_t startstop; + u8 ireason; if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all = hwif->INB(IDE_IREASON_REG); - while (retries-- && (!ireason.b.cod || ireason.b.io)) { + ireason = hwif->INB(IDE_IREASON_REG); + while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) { printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing " "a packet command, retrying\n"); udelay(100); - ireason.all = hwif->INB(IDE_IREASON_REG); + ireason = hwif->INB(IDE_IREASON_REG); if (retries == 0) { printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while " "issuing a packet command, ignoring\n"); - ireason.b.cod = 1; - ireason.b.io = 0; + ireason |= CD; + ireason &= ~IO; } } - if (!ireason.b.cod || ireason.b.io) { + if ((ireason & CD) == 0 || (ireason & IO)) { printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing " "a packet command\n"); return ide_do_reset(drive); @@ -2120,18 +1426,16 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape { ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; - atapi_bcount_t bcount; int dma_ok = 0; + u16 bcount; -#if IDETAPE_DEBUG_BUGS - if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && - pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { + if (tape->pc->c[0] == REQUEST_SENSE && + pc->c[0] == REQUEST_SENSE) { printk(KERN_ERR "ide-tape: possible ide-tape.c bug - " "Two request sense in serial were issued\n"); } -#endif /* IDETAPE_DEBUG_BUGS */ - if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD) + if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE) tape->failed_pc = pc; /* Set the current packet command */ tape->pc = pc; @@ -2144,7 +1448,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape * filemark, or end of the media, for example). */ if (!test_bit(PC_ABORT, &pc->flags)) { - if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && + if (!(pc->c[0] == TEST_UNIT_READY && tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) { printk(KERN_ERR "ide-tape: %s: I/O error, " @@ -2170,7 +1474,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape pc->actually_transferred = 0; pc->current_position = pc->buffer; /* Request to transfer the entire buffer at once */ - bcount.all = pc->request_transfer; + bcount = pc->request_transfer; if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { printk(KERN_WARNING "ide-tape: DMA disabled, " @@ -2180,17 +1484,14 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) dma_ok = !hwif->dma_setup(drive); - if (IDE_CONTROL_REG) - hwif->OUTB(drive->ctl, IDE_CONTROL_REG); - hwif->OUTB(dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */ - hwif->OUTB(bcount.b.high, IDE_BCOUNTH_REG); - hwif->OUTB(bcount.b.low, IDE_BCOUNTL_REG); - hwif->OUTB(drive->select.all, IDE_SELECT_REG); + ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK | + IDE_TFLAG_OUT_DEVICE, bcount, dma_ok); + if (dma_ok) /* Will begin DMA later */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); - hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); + ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc, + IDETAPE_WAIT_CMD, NULL); return ide_started; } else { hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); @@ -2220,7 +1521,7 @@ static ide_startstop_t idetape_pc_callback (ide_drive_t *drive) static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, u8 page_code) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_MODE_SENSE_CMD; + pc->c[0] = MODE_SENSE; if (page_code != IDETAPE_BLOCK_DESCRIPTOR) pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors */ pc->c[2] = page_code; @@ -2295,13 +1596,13 @@ static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = tape->pc; - atapi_status_t status; + u8 stat; - status.all = HWIF(drive)->INB(IDE_STATUS_REG); - if (status.b.dsc) { - if (status.b.check) { + stat = drive->hwif->INB(IDE_STATUS_REG); + if (stat & SEEK_STAT) { + if (stat & ERR_STAT) { /* Error detected */ - if (pc->c[0] != IDETAPE_TEST_UNIT_READY_CMD) + if (pc->c[0] != TEST_UNIT_READY) printk(KERN_ERR "ide-tape: %s: I/O error, ", tape->name); /* Retry operation */ @@ -2358,8 +1659,8 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive) static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_READ_CMD; - put_unaligned(htonl(length), (unsigned int *) &pc->c[1]); + pc->c[0] = READ_6; + put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; pc->callback = &idetape_rw_callback; pc->bh = bh; @@ -2376,7 +1677,7 @@ static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *p struct idetape_bh *p = bh; idetape_init_pc(pc); - pc->c[0] = IDETAPE_READ_BUFFER_CMD; + pc->c[0] = READ_BUFFER; pc->c[1] = IDETAPE_RETRIEVE_FAULTY_BLOCK; pc->c[7] = size >> 8; pc->c[8] = size & 0xff; @@ -2394,8 +1695,8 @@ static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *p static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_WRITE_CMD; - put_unaligned(htonl(length), (unsigned int *) &pc->c[1]); + pc->c[0] = WRITE_6; + put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; pc->callback = &idetape_rw_callback; set_bit(PC_WRITING, &pc->flags); @@ -2417,15 +1718,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = NULL; struct request *postponed_rq = tape->postponed_rq; - atapi_status_t status; + u8 stat; #if IDETAPE_DEBUG_LOG -#if 0 - if (tape->debug_level >= 5) - printk(KERN_INFO "ide-tape: %d, " - "dev: %s, cmd: %ld, errors: %d\n", - rq->rq_disk->disk_name, rq->cmd[0], rq->errors); -#endif if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: sector: %ld, " "nr_sectors: %ld, current_nr_sectors: %d\n", @@ -2446,10 +1741,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, * Retry a failed packet command */ if (tape->failed_pc != NULL && - tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { + tape->pc->c[0] == REQUEST_SENSE) { return idetape_issue_packet_command(drive, tape->failed_pc); } -#if IDETAPE_DEBUG_BUGS if (postponed_rq != NULL) if (rq != postponed_rq) { printk(KERN_ERR "ide-tape: ide-tape.c bug - " @@ -2457,7 +1751,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, idetape_end_request(drive, 0, 0); return ide_stopped; } -#endif /* IDETAPE_DEBUG_BUGS */ tape->postponed_rq = NULL; @@ -2465,7 +1758,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, * If the tape is still busy, postpone our request and service * the other device meanwhile. */ - status.all = HWIF(drive)->INB(IDE_STATUS_REG); + stat = drive->hwif->INB(IDE_STATUS_REG); if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2)) set_bit(IDETAPE_IGNORE_DSC, &tape->flags); @@ -2481,7 +1774,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); calculate_speeds(drive); if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) && - !status.b.dsc) { + (stat & SEEK_STAT) == 0) { if (postponed_rq == NULL) { tape->dsc_polling_start = jiffies; tape->dsc_polling_frequency = tape->best_dsc_rw_frequency; @@ -2502,9 +1795,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, } if (rq->cmd[0] & REQ_IDETAPE_READ) { tape->buffer_head++; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif tape->postpone_cnt = 0; pc = idetape_next_pc_storage(drive); idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special); @@ -2512,9 +1802,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, } if (rq->cmd[0] & REQ_IDETAPE_WRITE) { tape->buffer_head++; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif tape->postpone_cnt = 0; pc = idetape_next_pc_storage(drive); idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special); @@ -2650,13 +1937,11 @@ static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t * int ret = 0; while (n) { -#if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_copy_stage_from_user\n"); return 1; } -#endif /* IDETAPE_DEBUG_BUGS */ count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n); if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count)) ret = 1; @@ -2680,13 +1965,11 @@ static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, i int ret = 0; while (n) { -#if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_copy_stage_to_user\n"); return 1; } -#endif /* IDETAPE_DEBUG_BUGS */ count = min(tape->b_count, n); if (copy_to_user(buf, tape->b_data, count)) ret = 1; @@ -2766,12 +2049,10 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq) DECLARE_COMPLETION_ONSTACK(wait); idetape_tape_t *tape = drive->driver_data; -#if IDETAPE_DEBUG_BUGS if (rq == NULL || !blk_special_request(rq)) { printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n"); return; } -#endif /* IDETAPE_DEBUG_BUGS */ rq->end_io_data = &wait; rq->end_io = blk_end_sync_rq; spin_unlock_irq(&tape->spinlock); @@ -2831,7 +2112,7 @@ static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive) static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD; + pc->c[0] = WRITE_FILEMARKS; pc->c[4] = write_filemark; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; @@ -2840,7 +2121,7 @@ static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_TEST_UNIT_READY_CMD; + pc->c[0] = TEST_UNIT_READY; pc->callback = &idetape_pc_callback; } @@ -2878,7 +2159,7 @@ static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc) static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD; + pc->c[0] = START_STOP; pc->c[4] = cmd; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; @@ -2935,7 +2216,7 @@ static int idetape_flush_tape_buffers (ide_drive_t *drive) static void idetape_create_read_position_cmd (idetape_pc_t *pc) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_READ_POSITION_CMD; + pc->c[0] = READ_POSITION; pc->request_transfer = 20; pc->callback = &idetape_read_position_callback; } @@ -2961,9 +2242,9 @@ static int idetape_read_position (ide_drive_t *drive) static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_LOCATE_CMD; + pc->c[0] = POSITION_TO_ELEMENT; pc->c[1] = 2; - put_unaligned(htonl(block), (unsigned int *) &pc->c[3]); + put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]); pc->c[8] = partition; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; @@ -2973,11 +2254,12 @@ static int idetape_create_prevent_cmd (ide_drive_t *drive, idetape_pc_t *pc, int { idetape_tape_t *tape = drive->driver_data; - if (!tape->capabilities.lock) + /* device supports locking according to capabilities page */ + if (!(tape->caps[6] & 0x01)) return 0; idetape_init_pc(pc); - pc->c[0] = IDETAPE_PREVENT_CMD; + pc->c[0] = ALLOW_MEDIUM_REMOVAL; pc->c[4] = prevent; pc->callback = &idetape_pc_callback; return 1; @@ -3086,12 +2368,10 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, struct if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd); #endif /* IDETAPE_DEBUG_LOG */ -#if IDETAPE_DEBUG_BUGS if (idetape_pipeline_active(tape)) { printk(KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n"); return (0); } -#endif /* IDETAPE_DEBUG_BUGS */ idetape_init_rq(&rq, cmd); rq.rq_disk = tape->disk; @@ -3122,7 +2402,7 @@ static void idetape_insert_pipeline_into_queue (ide_drive_t *drive) return; if (!idetape_pipeline_active(tape)) { set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - idetape_active_next_stage(drive); + idetape_activate_next_stage(drive); (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end); } } @@ -3130,7 +2410,7 @@ static void idetape_insert_pipeline_into_queue (ide_drive_t *drive) static void idetape_create_inquiry_cmd (idetape_pc_t *pc) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_INQUIRY_CMD; + pc->c[0] = INQUIRY; pc->c[4] = pc->request_transfer = 254; pc->callback = &idetape_pc_callback; } @@ -3138,28 +2418,15 @@ static void idetape_create_inquiry_cmd (idetape_pc_t *pc) static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_REWIND_CMD; + pc->c[0] = REZERO_UNIT; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } -#if 0 -static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length) -{ - idetape_init_pc(pc); - set_bit(PC_WRITING, &pc->flags); - pc->c[0] = IDETAPE_MODE_SELECT_CMD; - pc->c[1] = 0x10; - put_unaligned(htons(length), (unsigned short *) &pc->c[3]); - pc->request_transfer = 255; - pc->callback = &idetape_pc_callback; -} -#endif - static void idetape_create_erase_cmd (idetape_pc_t *pc) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_ERASE_CMD; + pc->c[0] = ERASE; pc->c[1] = 1; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; @@ -3168,8 +2435,8 @@ static void idetape_create_erase_cmd (idetape_pc_t *pc) static void idetape_create_space_cmd (idetape_pc_t *pc,int count, u8 cmd) { idetape_init_pc(pc); - pc->c[0] = IDETAPE_SPACE_CMD; - put_unaligned(htonl(count), (unsigned int *) &pc->c[1]); + pc->c[0] = SPACE; + put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]); pc->c[1] = cmd; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; @@ -3241,9 +2508,6 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks) idetape_switch_buffers(tape, new_stage); idetape_add_stage_tail(drive, new_stage); tape->pipeline_head++; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif calculate_speeds(drive); /* @@ -3292,8 +2556,7 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive) idetape_tape_t *tape = drive->driver_data; int blocks, min; struct idetape_bh *bh; - -#if IDETAPE_DEBUG_BUGS + if (tape->chrdev_direction != idetape_direction_write) { printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n"); return; @@ -3302,7 +2565,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive) printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n"); tape->merge_stage_size = tape->stage_size; } -#endif /* IDETAPE_DEBUG_BUGS */ if (tape->merge_stage_size) { blocks = tape->merge_stage_size / tape->tape_block_size; if (tape->merge_stage_size % tape->tape_block_size) { @@ -3347,7 +2609,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive) * can be totally different on the next backup). */ tape->max_stages = tape->min_pipeline; -#if IDETAPE_DEBUG_BUGS if (tape->first_stage != NULL || tape->next_stage != NULL || tape->last_stage != NULL || @@ -3358,7 +2619,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive) tape->first_stage, tape->next_stage, tape->last_stage, tape->nr_stages); } -#endif /* IDETAPE_DEBUG_BUGS */ } static void idetape_restart_speed_control (ide_drive_t *drive) @@ -3381,7 +2641,7 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages) idetape_stage_t *new_stage; struct request rq; int bytes_read; - int blocks = tape->capabilities.ctl; + u16 blocks = *(u16 *)&tape->caps[12]; /* Initialize read operation */ if (tape->chrdev_direction != idetape_direction_read) { @@ -3389,12 +2649,10 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages) idetape_empty_write_pipeline(drive); idetape_flush_tape_buffers(drive); } -#if IDETAPE_DEBUG_BUGS if (tape->merge_stage || tape->merge_stage_size) { printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n"); tape->merge_stage_size = 0; } -#endif /* IDETAPE_DEBUG_BUGS */ if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL) return -ENOMEM; tape->chrdev_direction = idetape_direction_read; @@ -3493,17 +2751,12 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks) idetape_remove_stage_head(drive); spin_unlock_irqrestore(&tape->spinlock, flags); tape->pipeline_head++; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif calculate_speeds(drive); } -#if IDETAPE_DEBUG_BUGS if (bytes_read > blocks * tape->tape_block_size) { printk(KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n"); bytes_read = blocks * tape->tape_block_size; } -#endif /* IDETAPE_DEBUG_BUGS */ return (bytes_read); } @@ -3587,16 +2840,21 @@ static int idetape_rewind_tape (ide_drive_t *drive) static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned long arg) { idetape_tape_t *tape = drive->driver_data; - idetape_config_t config; void __user *argp = (void __user *)arg; + struct idetape_config { + int dsc_rw_frequency; + int dsc_media_access_frequency; + int nr_stages; + } config; + #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) printk(KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n"); #endif /* IDETAPE_DEBUG_LOG */ switch (cmd) { case 0x0340: - if (copy_from_user(&config, argp, sizeof (idetape_config_t))) + if (copy_from_user(&config, argp, sizeof(config))) return -EFAULT; tape->best_dsc_rw_frequency = config.dsc_rw_frequency; tape->max_stages = config.nr_stages; @@ -3604,7 +2862,7 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned l case 0x0350: config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency; config.nr_stages = tape->max_stages; - if (copy_to_user(argp, &config, sizeof (idetape_config_t))) + if (copy_to_user(argp, &config, sizeof(config))) return -EFAULT; break; default: @@ -3628,11 +2886,12 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c idetape_pc_t pc; unsigned long flags; int retval,count=0; + int sprev = !!(tape->caps[4] & 0x20); if (mt_count == 0) return 0; if (MTBSF == mt_op || MTBSFM == mt_op) { - if (!tape->capabilities.sprev) + if (!sprev) return -EIO; mt_count = - mt_count; } @@ -3686,7 +2945,7 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c return (idetape_queue_pc_tail(drive, &pc)); case MTFSFM: case MTBSFM: - if (!tape->capabilities.sprev) + if (!sprev) return (-EIO); retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count); if (retval) return (retval); @@ -3723,6 +2982,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, ide_drive_t *drive = tape->drive; ssize_t bytes_read,temp, actually_read = 0, rc; ssize_t ret = 0; + u16 ctl = *(u16 *)&tape->caps[12]; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) @@ -3748,7 +3008,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, count -= actually_read; } while (count >= tape->stage_size) { - bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl); + bytes_read = idetape_add_chrdev_read_request(drive, ctl); if (bytes_read <= 0) goto finish; if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read)) @@ -3758,7 +3018,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, actually_read += bytes_read; } if (count) { - bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl); + bytes_read = idetape_add_chrdev_read_request(drive, ctl); if (bytes_read <= 0) goto finish; temp = min((unsigned long)count, (unsigned long)bytes_read); @@ -3787,6 +3047,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, ide_drive_t *drive = tape->drive; ssize_t actually_written = 0; ssize_t ret = 0; + u16 ctl = *(u16 *)&tape->caps[12]; /* The drive is write protected. */ if (tape->write_prot) @@ -3802,13 +3063,11 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, if (tape->chrdev_direction != idetape_direction_write) { if (tape->chrdev_direction == idetape_direction_read) idetape_discard_read_pipeline(drive, 1); -#if IDETAPE_DEBUG_BUGS if (tape->merge_stage || tape->merge_stage_size) { printk(KERN_ERR "ide-tape: merge_stage_size " "should be 0 now\n"); tape->merge_stage_size = 0; } -#endif /* IDETAPE_DEBUG_BUGS */ if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL) return -ENOMEM; tape->chrdev_direction = idetape_direction_write; @@ -3836,12 +3095,10 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, if (tape->restart_speed_control_req) idetape_restart_speed_control(drive); if (tape->merge_stage_size) { -#if IDETAPE_DEBUG_BUGS if (tape->merge_stage_size >= tape->stage_size) { printk(KERN_ERR "ide-tape: bug: merge buffer too big\n"); tape->merge_stage_size = 0; } -#endif /* IDETAPE_DEBUG_BUGS */ actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count); if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written)) ret = -EFAULT; @@ -3852,7 +3109,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, if (tape->merge_stage_size == tape->stage_size) { ssize_t retval; tape->merge_stage_size = 0; - retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); + retval = idetape_add_chrdev_write_request(drive, ctl); if (retval <= 0) return (retval); } @@ -3863,7 +3120,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, ret = -EFAULT; buf += tape->stage_size; count -= tape->stage_size; - retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); + retval = idetape_add_chrdev_write_request(drive, ctl); actually_written += tape->stage_size; if (retval <= 0) return (retval); @@ -3891,69 +3148,20 @@ static int idetape_write_filemark (ide_drive_t *drive) } /* - * idetape_mtioctop is called from idetape_chrdev_ioctl when - * the general mtio MTIOCTOP ioctl is requested. - * - * We currently support the following mtio.h operations: - * - * MTFSF - Space over mt_count filemarks in the positive direction. - * The tape is positioned after the last spaced filemark. - * - * MTFSFM - Same as MTFSF, but the tape is positioned before the - * last filemark. - * - * MTBSF - Steps background over mt_count filemarks, tape is - * positioned before the last filemark. + * Called from idetape_chrdev_ioctl when the general mtio MTIOCTOP ioctl is + * requested. * - * MTBSFM - Like MTBSF, only tape is positioned after the last filemark. + * Note: MTBSF and MTBSFM are not supported when the tape doesn't support + * spacing over filemarks in the reverse direction. In this case, MTFSFM is also + * usually not supported (it is supported in the rare case in which we crossed + * the filemark during our read-ahead pipelined operation mode). * - * Note: + * The following commands are currently not supported: * - * MTBSF and MTBSFM are not supported when the tape doesn't - * support spacing over filemarks in the reverse direction. - * In this case, MTFSFM is also usually not supported (it is - * supported in the rare case in which we crossed the filemark - * during our read-ahead pipelined operation mode). - * - * MTWEOF - Writes mt_count filemarks. Tape is positioned after - * the last written filemark. - * - * MTREW - Rewinds tape. - * - * MTLOAD - Loads the tape. - * - * MTOFFL - Puts the tape drive "Offline": Rewinds the tape and - * MTUNLOAD prevents further access until the media is replaced. - * - * MTNOP - Flushes tape buffers. - * - * MTRETEN - Retension media. This typically consists of one end - * to end pass on the media. - * - * MTEOM - Moves to the end of recorded data. - * - * MTERASE - Erases tape. - * - * MTSETBLK - Sets the user block size to mt_count bytes. If - * mt_count is 0, we will attempt to autodetect - * the block size. - * - * MTSEEK - Positions the tape in a specific block number, where - * each block is assumed to contain which user_block_size - * bytes. - * - * MTSETPART - Switches to another tape partition. - * - * MTLOCK - Locks the tape door. - * - * MTUNLOCK - Unlocks the tape door. - * - * The following commands are currently not supported: - * - * MTFSS, MTBSS, MTWSM, MTSETDENSITY, - * MTSETDRVBUFFER, MT_ST_BOOLEANS, MT_ST_WRITE_THRESHOLD. + * MTFSS, MTBSS, MTWSM, MTSETDENSITY, MTSETDRVBUFFER, MT_ST_BOOLEANS, + * MT_ST_WRITE_THRESHOLD. */ -static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count) +static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t pc; @@ -4068,29 +3276,12 @@ static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count) } /* - * Our character device ioctls. - * - * General mtio.h magnetic io commands are supported here, and not in - * the corresponding block interface. - * - * The following ioctls are supported: - * - * MTIOCTOP - Refer to idetape_mtioctop for detailed description. - * - * MTIOCGET - The mt_dsreg field in the returned mtget structure - * will be set to (user block size in bytes << - * MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK. - * - * The mt_blkno is set to the current user block number. - * The other mtget fields are not supported. - * - * MTIOCPOS - The current tape "block position" is returned. We - * assume that each block contains user_block_size - * bytes. - * - * Our own ide-tape ioctls are supported on both interfaces. + * Our character device ioctls. General mtio.h magnetic io commands are + * supported here, and not in the corresponding block interface. Our own + * ide-tape ioctls are supported on both interfaces. */ -static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int idetape_chrdev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { struct ide_tape_obj *tape = ide_tape_f(file); ide_drive_t *drive = tape->drive; @@ -4144,7 +3335,30 @@ static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigne } } -static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive); +/* + * Do a mode sense page 0 with block descriptor and if it succeeds set the tape + * block size with the reported value. + */ +static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive) +{ + idetape_tape_t *tape = drive->driver_data; + idetape_pc_t pc; + + idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR); + if (idetape_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-tape: Can't get block descriptor\n"); + if (tape->tape_block_size == 0) { + printk(KERN_WARNING "ide-tape: Cannot deal with zero " + "block size, assuming 32k\n"); + tape->tape_block_size = 32768; + } + return; + } + tape->tape_block_size = (pc.buffer[4 + 5] << 16) + + (pc.buffer[4 + 6] << 8) + + pc.buffer[4 + 7]; + tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7; +} /* * Our character device open function. @@ -4198,7 +3412,7 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp) clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); /* Read block size and write protect status from drive. */ - idetape_get_blocksize_from_block_descriptor(drive); + ide_tape_get_bsize_from_bdesc(drive); /* Set write protect flag if device is opened as read-only. */ if ((filp->f_flags & O_ACCMODE) == O_RDONLY) @@ -4310,255 +3524,106 @@ static int idetape_identify_device (ide_drive_t *drive) { struct idetape_id_gcw gcw; struct hd_driveid *id = drive->id; -#if IDETAPE_DEBUG_INFO - unsigned short mask,i; -#endif /* IDETAPE_DEBUG_INFO */ if (drive->id_read == 0) return 1; *((unsigned short *) &gcw) = id->config; -#if IDETAPE_DEBUG_INFO - printk(KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n"); - printk(KERN_INFO "ide-tape: Protocol Type: "); - switch (gcw.protocol) { - case 0: case 1: printk("ATA\n");break; - case 2: printk("ATAPI\n");break; - case 3: printk("Reserved (Unknown to ide-tape)\n");break; - } - printk(KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type); - switch (gcw.device_type) { - case 0: printk("Direct-access Device\n");break; - case 1: printk("Streaming Tape Device\n");break; - case 2: case 3: case 4: printk("Reserved\n");break; - case 5: printk("CD-ROM Device\n");break; - case 6: printk("Reserved\n"); - case 7: printk("Optical memory Device\n");break; - case 0x1f: printk("Unknown or no Device type\n");break; - default: printk("Reserved\n"); - } - printk(KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n"); - printk(KERN_INFO "ide-tape: Command Packet DRQ Type: "); - switch (gcw.drq_type) { - case 0: printk("Microprocessor DRQ\n");break; - case 1: printk("Interrupt DRQ\n");break; - case 2: printk("Accelerated DRQ\n");break; - case 3: printk("Reserved\n");break; - } - printk(KERN_INFO "ide-tape: Command Packet Size: "); - switch (gcw.packet_size) { - case 0: printk("12 bytes\n");break; - case 1: printk("16 bytes\n");break; - default: printk("Reserved\n");break; - } - printk(KERN_INFO "ide-tape: Model: %.40s\n",id->model); - printk(KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev); - printk(KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no); - printk(KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512); - printk(KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); - printk(KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); - printk(KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); - printk(KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); - printk(KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); - printk(KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO); - printk(KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA); - printk(KERN_INFO "ide-tape: Single Word DMA supported modes: "); - for (i=0,mask=1;i<8;i++,mask=mask << 1) { - if (id->dma_1word & mask) - printk("%d ",i); - if (id->dma_1word & (mask << 8)) - printk("(active) "); - } - printk("\n"); - printk(KERN_INFO "ide-tape: Multi Word DMA supported modes: "); - for (i=0,mask=1;i<8;i++,mask=mask << 1) { - if (id->dma_mword & mask) - printk("%d ",i); - if (id->dma_mword & (mask << 8)) - printk("(active) "); - } - printk("\n"); - if (id->field_valid & 0x0002) { - printk(KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n", - id->eide_pio_modes & 1 ? "Mode 3":"None"); - printk(KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: "); - if (id->eide_dma_min == 0) - printk("Not supported\n"); - else - printk("%d ns\n",id->eide_dma_min); - - printk(KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: "); - if (id->eide_dma_time == 0) - printk("Not supported\n"); - else - printk("%d ns\n",id->eide_dma_time); - - printk(KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: "); - if (id->eide_pio == 0) - printk("Not supported\n"); - else - printk("%d ns\n",id->eide_pio); - - printk(KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: "); - if (id->eide_pio_iordy == 0) - printk("Not supported\n"); - else - printk("%d ns\n",id->eide_pio_iordy); - - } else - printk(KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n"); -#endif /* IDETAPE_DEBUG_INFO */ - /* Check that we can support this device */ - if (gcw.protocol !=2 ) - printk(KERN_ERR "ide-tape: Protocol is not ATAPI\n"); + if (gcw.protocol != 2) + printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n", + gcw.protocol); else if (gcw.device_type != 1) - printk(KERN_ERR "ide-tape: Device type is not set to tape\n"); + printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set " + "to tape\n", gcw.device_type); else if (!gcw.removable) printk(KERN_ERR "ide-tape: The removable flag is not set\n"); else if (gcw.packet_size != 0) { - printk(KERN_ERR "ide-tape: Packet size is not 12 bytes long\n"); - if (gcw.packet_size == 1) - printk(KERN_ERR "ide-tape: Sorry, padding to 16 bytes is still not supported\n"); + printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12 " + "bytes long\n", gcw.packet_size); } else return 1; return 0; } -/* - * Use INQUIRY to get the firmware revision - */ -static void idetape_get_inquiry_results (ide_drive_t *drive) +static void idetape_get_inquiry_results(ide_drive_t *drive) { char *r; idetape_tape_t *tape = drive->driver_data; idetape_pc_t pc; - idetape_inquiry_result_t *inquiry; - + idetape_create_inquiry_cmd(&pc); if (idetape_queue_pc_tail(drive, &pc)) { - printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name); + printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", + tape->name); return; } - inquiry = (idetape_inquiry_result_t *) pc.buffer; - memcpy(tape->vendor_id, inquiry->vendor_id, 8); - memcpy(tape->product_id, inquiry->product_id, 16); - memcpy(tape->firmware_revision, inquiry->revision_level, 4); + memcpy(tape->vendor_id, &pc.buffer[8], 8); + memcpy(tape->product_id, &pc.buffer[16], 16); + memcpy(tape->firmware_revision, &pc.buffer[32], 4); + ide_fixstring(tape->vendor_id, 10, 0); ide_fixstring(tape->product_id, 18, 0); ide_fixstring(tape->firmware_revision, 6, 0); r = tape->firmware_revision; if (*(r + 1) == '.') - tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0'; - printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision); + tape->firmware_revision_num = (*r - '0') * 100 + + (*(r + 2) - '0') * 10 + *(r + 3) - '0'; + printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", + drive->name, tape->name, tape->vendor_id, + tape->product_id, tape->firmware_revision); } /* - * idetape_get_mode_sense_results asks the tape about its various - * parameters. In particular, we will adjust our data transfer buffer - * size to the recommended value as returned by the tape. + * Ask the tape about its various parameters. In particular, we will adjust our + * data transfer buffer size to the recommended value as returned by the tape. */ static void idetape_get_mode_sense_results (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - idetape_capabilities_page_t *capabilities; - + u8 *caps; + u8 speed, max_speed; + idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE); if (idetape_queue_pc_tail(drive, &pc)) { - printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n"); + printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming" + " some default values\n"); tape->tape_block_size = 512; - tape->capabilities.ctl = 52; - tape->capabilities.speed = 450; - tape->capabilities.buffer_size = 6 * 52; + put_unaligned(52, (u16 *)&tape->caps[12]); + put_unaligned(540, (u16 *)&tape->caps[14]); + put_unaligned(6*52, (u16 *)&tape->caps[16]); return; } - header = (idetape_mode_parameter_header_t *) pc.buffer; - capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); + caps = pc.buffer + 4 + pc.buffer[3]; - capabilities->max_speed = ntohs(capabilities->max_speed); - capabilities->ctl = ntohs(capabilities->ctl); - capabilities->speed = ntohs(capabilities->speed); - capabilities->buffer_size = ntohs(capabilities->buffer_size); + /* convert to host order and save for later use */ + speed = be16_to_cpu(*(u16 *)&caps[14]); + max_speed = be16_to_cpu(*(u16 *)&caps[8]); - if (!capabilities->speed) { - printk(KERN_INFO "ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name); - capabilities->speed = 650; + put_unaligned(max_speed, (u16 *)&caps[8]); + put_unaligned(be16_to_cpu(*(u16 *)&caps[12]), (u16 *)&caps[12]); + put_unaligned(speed, (u16 *)&caps[14]); + put_unaligned(be16_to_cpu(*(u16 *)&caps[16]), (u16 *)&caps[16]); + + if (!speed) { + printk(KERN_INFO "ide-tape: %s: invalid tape speed " + "(assuming 650KB/sec)\n", drive->name); + put_unaligned(650, (u16 *)&caps[14]); } - if (!capabilities->max_speed) { - printk(KERN_INFO "ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name); - capabilities->max_speed = 650; + if (!max_speed) { + printk(KERN_INFO "ide-tape: %s: invalid max_speed " + "(assuming 650KB/sec)\n", drive->name); + put_unaligned(650, (u16 *)&caps[8]); } - tape->capabilities = *capabilities; /* Save us a copy */ - if (capabilities->blk512) + memcpy(&tape->caps, caps, 20); + if (caps[7] & 0x02) tape->tape_block_size = 512; - else if (capabilities->blk1024) + else if (caps[7] & 0x04) tape->tape_block_size = 1024; - -#if IDETAPE_DEBUG_INFO - printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n"); - printk(KERN_INFO "ide-tape: Mode Parameter Header:\n"); - printk(KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length); - printk(KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type); - printk(KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp); - printk(KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl); - - printk(KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n"); - printk(KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code); - printk(KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length); - printk(KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No"); - printk(KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No"); - printk(KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No"); - printk(KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed); - printk(KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl); - printk(KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed); - printk(KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512); -#endif /* IDETAPE_DEBUG_INFO */ -} - -/* - * ide_get_blocksize_from_block_descriptor does a mode sense page 0 with block descriptor - * and if it succeeds sets the tape block size with the reported value - */ -static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive) -{ - - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - idetape_parameter_block_descriptor_t *block_descrp; - - idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR); - if (idetape_queue_pc_tail(drive, &pc)) { - printk(KERN_ERR "ide-tape: Can't get block descriptor\n"); - if (tape->tape_block_size == 0) { - printk(KERN_WARNING "ide-tape: Cannot deal with zero block size, assume 32k\n"); - tape->tape_block_size = 32768; - } - return; - } - header = (idetape_mode_parameter_header_t *) pc.buffer; - block_descrp = (idetape_parameter_block_descriptor_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t)); - tape->tape_block_size =( block_descrp->length[0]<<16) + (block_descrp->length[1]<<8) + block_descrp->length[2]; - tape->drv_write_prot = (header->dsp & 0x80) >> 7; - -#if IDETAPE_DEBUG_INFO - printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); -#endif /* IDETAPE_DEBUG_INFO */ } #ifdef CONFIG_IDE_PROC_FS @@ -4569,13 +3634,15 @@ static void idetape_add_settings (ide_drive_t *drive) /* * drive setting name read/write data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); + ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, + 1, 2, (u16 *)&tape->caps[16], NULL); ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); - ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); + ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, + 1, 1, (u16 *)&tape->caps[14], NULL); ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); @@ -4607,22 +3674,15 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) struct idetape_id_gcw gcw; int stage_size; struct sysinfo si; + u16 *ctl = (u16 *)&tape->caps[12]; spin_lock_init(&tape->spinlock); drive->dsc_overlap = 1; -#ifdef CONFIG_BLK_DEV_IDEPCI - if (HWIF(drive)->pci_dev != NULL) { - /* - * These two ide-pci host adapters appear to need DSC overlap disabled. - * This probably needs further analysis. - */ - if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) || - (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) { - printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name); - drive->dsc_overlap = 0; - } + if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) { + printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", + tape->name); + drive->dsc_overlap = 0; } -#endif /* CONFIG_BLK_DEV_IDEPCI */ /* Seagate Travan drives do not support DSC overlap. */ if (strstr(drive->id->model, "Seagate STT3401")) drive->dsc_overlap = 0; @@ -4642,13 +3702,13 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) idetape_get_inquiry_results(drive); idetape_get_mode_sense_results(drive); - idetape_get_blocksize_from_block_descriptor(drive); + ide_tape_get_bsize_from_bdesc(drive); tape->user_bs_factor = 1; - tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; + tape->stage_size = *ctl * tape->tape_block_size; while (tape->stage_size > 0xffff) { printk(KERN_NOTICE "ide-tape: decreasing stage size\n"); - tape->capabilities.ctl /= 2; - tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; + *ctl /= 2; + tape->stage_size = *ctl * tape->tape_block_size; } stage_size = tape->stage_size; tape->pages_per_stage = stage_size / PAGE_SIZE; @@ -4657,11 +3717,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE; } - /* - * Select the "best" DSC read/write polling frequency - * and pipeline size. - */ - speed = max(tape->capabilities.speed, tape->capabilities.max_speed); + /* Select the "best" DSC read/write polling freq and pipeline size. */ + speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]); tape->max_stages = speed * 1000 * 10 / tape->stage_size; @@ -4678,7 +3735,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1; t1 = (tape->stage_size * HZ) / (speed * 1000); - tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125); + tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125); tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000); if (tape->max_stages) @@ -4693,8 +3750,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) tape->best_dsc_rw_frequency = max_t(unsigned long, min_t(unsigned long, t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN); printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, " "%dkB pipeline, %lums tDSC%s\n", - drive->name, tape->name, tape->capabilities.speed, - (tape->capabilities.buffer_size * 512) / tape->stage_size, + drive->name, tape->name, *(u16 *)&tape->caps[14], + (*(u16 *)&tape->caps[16] * 512) / tape->stage_size, tape->stage_size / 1024, tape->max_stages * tape->stage_size / 1024, tape->best_dsc_rw_frequency * 1000 / HZ, @@ -4724,10 +3781,8 @@ static void ide_tape_release(struct kref *kref) drive->dsc_overlap = 0; drive->driver_data = NULL; - class_device_destroy(idetape_sysfs_class, - MKDEV(IDETAPE_MAJOR, tape->minor)); - class_device_destroy(idetape_sysfs_class, - MKDEV(IDETAPE_MAJOR, tape->minor + 128)); + device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor)); + device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor + 128)); idetape_devs[tape->minor] = NULL; g->private_data = NULL; put_disk(g); @@ -4884,10 +3939,10 @@ static int ide_tape_probe(ide_drive_t *drive) idetape_setup(drive, tape, minor); - class_device_create(idetape_sysfs_class, NULL, - MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name); - class_device_create(idetape_sysfs_class, NULL, - MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name); + device_create(idetape_sysfs_class, &drive->gendev, + MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name); + device_create(idetape_sysfs_class, &drive->gendev, + MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name); g->fops = &idetape_block_ops; ide_register_region(g); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index d066546f283..4e1da1c78cb 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -1,11 +1,9 @@ /* - * linux/drivers/ide/ide-taskfile.c Version 0.38 March 05, 2003 - * - * Copyright (C) 2000-2002 Michael Cornwell <cornwell@acm.org> - * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2001-2002 Klaus Smolin + * Copyright (C) 2000-2002 Michael Cornwell <cornwell@acm.org> + * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> + * Copyright (C) 2001-2002 Klaus Smolin * IBM Storage Technology Division - * Copyright (C) 2003-2004 Bartlomiej Zolnierkiewicz + * Copyright (C) 2003-2004, 2007 Bartlomiej Zolnierkiewicz * * The big the bad and the ugly. */ @@ -35,93 +33,81 @@ #include <asm/uaccess.h> #include <asm/io.h> -static void ata_bswap_data (void *buffer, int wcount) -{ - u16 *p = buffer; - - while (wcount--) { - *p = *p << 8 | *p >> 8; p++; - *p = *p << 8 | *p >> 8; p++; - } -} - -static void taskfile_input_data(ide_drive_t *drive, void *buffer, u32 wcount) +void ide_tf_load(ide_drive_t *drive, ide_task_t *task) { - HWIF(drive)->ata_input_data(drive, buffer, wcount); - if (drive->bswap) - ata_bswap_data(buffer, wcount); -} + ide_hwif_t *hwif = drive->hwif; + struct ide_taskfile *tf = &task->tf; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + +#ifdef DEBUG + printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x " + "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n", + drive->name, tf->feature, tf->nsect, tf->lbal, + tf->lbam, tf->lbah, tf->device, tf->command); + printk("%s: hob: nsect 0x%02x lbal 0x%02x " + "lbam 0x%02x lbah 0x%02x\n", + drive->name, tf->hob_nsect, tf->hob_lbal, + tf->hob_lbam, tf->hob_lbah); +#endif -static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount) -{ - if (drive->bswap) { - ata_bswap_data(buffer, wcount); - HWIF(drive)->ata_output_data(drive, buffer, wcount); - ata_bswap_data(buffer, wcount); - } else { - HWIF(drive)->ata_output_data(drive, buffer, wcount); - } + ide_set_irq(drive, 1); + + if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0) + SELECT_MASK(drive, 0); + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) + hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG); + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + hwif->OUTB(tf->feature, IDE_FEATURE_REG); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + hwif->OUTB(tf->nsect, IDE_NSECTOR_REG); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + hwif->OUTB(tf->lbal, IDE_SECTOR_REG); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + hwif->OUTB(tf->lbam, IDE_LCYL_REG); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + hwif->OUTB(tf->lbah, IDE_HCYL_REG); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG); } int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) { ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; + args.tf.nsect = 0x01; if (drive->media == ide_disk) - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY; + args.tf.command = WIN_IDENTIFY; else - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY; - args.command_type = IDE_DRIVE_TASK_IN; - args.data_phase = TASKFILE_IN; - args.handler = &task_in_intr; - return ide_raw_taskfile(drive, &args, buf); + args.tf.command = WIN_PIDENTIFY; + args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + args.data_phase = TASKFILE_IN; + return ide_raw_taskfile(drive, &args, buf, 1); } -ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) +static int inline task_dma_ok(ide_task_t *task) { - ide_hwif_t *hwif = HWIF(drive); - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF; - - /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ - if (IDE_CONTROL_REG) { - /* clear nIEN */ - hwif->OUTB(drive->ctl, IDE_CONTROL_REG); - } - SELECT_MASK(drive, 0); - - if (drive->addressing == 1) { - hwif->OUTB(hobfile->feature, IDE_FEATURE_REG); - hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG); - hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG); - hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG); - hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG); - } - - hwif->OUTB(taskfile->feature, IDE_FEATURE_REG); - hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG); - hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG); - hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG); - hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG); - - hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); - - if (task->handler != NULL) { - if (task->prehandler != NULL) { - hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG); - ndelay(400); /* FIXME */ - return task->prehandler(drive, task->rq); - } - ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); - return ide_started; - } - - if (!drive->using_dma) - return ide_stopped; + if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED)) + return 1; - switch (taskfile->command) { + switch (task->tf.command) { case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA: case WIN_WRITEDMA_EXT: @@ -129,24 +115,79 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) case WIN_READDMA: case WIN_READDMA_EXT: case WIN_IDENTIFY_DMA: - if (!hwif->dma_setup(drive)) { - hwif->dma_exec_cmd(drive, taskfile->command); - hwif->dma_start(drive); - return ide_started; - } - break; - default: - if (task->handler == NULL) - return ide_stopped; + return 1; } - return ide_stopped; + return 0; } +static ide_startstop_t task_no_data_intr(ide_drive_t *); +static ide_startstop_t set_geometry_intr(ide_drive_t *); +static ide_startstop_t recal_intr(ide_drive_t *); +static ide_startstop_t set_multmode_intr(ide_drive_t *); +static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *); +static ide_startstop_t task_in_intr(ide_drive_t *); + +ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = HWIF(drive); + struct ide_taskfile *tf = &task->tf; + ide_handler_t *handler = NULL; + + if (task->data_phase == TASKFILE_MULTI_IN || + task->data_phase == TASKFILE_MULTI_OUT) { + if (!drive->mult_count) { + printk(KERN_ERR "%s: multimode not set!\n", + drive->name); + return ide_stopped; + } + } + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; + + if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) + ide_tf_load(drive, task); + + switch (task->data_phase) { + case TASKFILE_MULTI_OUT: + case TASKFILE_OUT: + hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG); + ndelay(400); /* FIXME */ + return pre_task_out_intr(drive, task->rq); + case TASKFILE_MULTI_IN: + case TASKFILE_IN: + handler = task_in_intr; + /* fall-through */ + case TASKFILE_NO_DATA: + if (handler == NULL) + handler = task_no_data_intr; + /* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */ + if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) { + switch (tf->command) { + case WIN_SPECIFY: handler = set_geometry_intr; break; + case WIN_RESTORE: handler = recal_intr; break; + case WIN_SETMULT: handler = set_multmode_intr; break; + } + } + ide_execute_command(drive, tf->command, handler, + WAIT_WORSTCASE, NULL); + return ide_started; + default: + if (task_dma_ok(task) == 0 || drive->using_dma == 0 || + hwif->dma_setup(drive)) + return ide_stopped; + hwif->dma_exec_cmd(drive, tf->command); + hwif->dma_start(drive); + return ide_started; + } +} +EXPORT_SYMBOL_GPL(do_rw_taskfile); + /* * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. */ -ide_startstop_t set_multmode_intr (ide_drive_t *drive) +static ide_startstop_t set_multmode_intr(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 stat; @@ -164,7 +205,7 @@ ide_startstop_t set_multmode_intr (ide_drive_t *drive) /* * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. */ -ide_startstop_t set_geometry_intr (ide_drive_t *drive) +static ide_startstop_t set_geometry_intr(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); int retries = 5; @@ -187,7 +228,7 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive) /* * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. */ -ide_startstop_t recal_intr (ide_drive_t *drive) +static ide_startstop_t recal_intr(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 stat; @@ -200,7 +241,7 @@ ide_startstop_t recal_intr (ide_drive_t *drive) /* * Handler for commands without a data phase */ -ide_startstop_t task_no_data_intr (ide_drive_t *drive) +static ide_startstop_t task_no_data_intr(ide_drive_t *drive) { ide_task_t *args = HWGROUP(drive)->rq->special; ide_hwif_t *hwif = HWIF(drive); @@ -217,8 +258,6 @@ ide_startstop_t task_no_data_intr (ide_drive_t *drive) return ide_stopped; } -EXPORT_SYMBOL(task_no_data_intr); - static u8 wait_drive_not_busy(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -227,8 +266,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) /* * Last sector was transfered, wait until drive is ready. - * This can take up to 10 usec, but we will wait max 1 ms - * (drive_cmd_intr() waits that long). + * This can take up to 10 usec, but we will wait max 1 ms. */ for (retries = 0; retries < 100; retries++) { if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) @@ -283,9 +321,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) /* do the actual data transfer */ if (write) - taskfile_output_data(drive, buf, SECTOR_WORDS); + hwif->ata_output_data(drive, buf, SECTOR_WORDS); else - taskfile_input_data(drive, buf, SECTOR_WORDS); + hwif->ata_input_data(drive, buf, SECTOR_WORDS); kunmap_atomic(buf, KM_BIO_SRC_IRQ); #ifdef CONFIG_HIGHMEM @@ -305,9 +343,18 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write) static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, unsigned int write) { + u8 saved_io_32bit = drive->io_32bit; + if (rq->bio) /* fs request */ rq->errors = 0; + if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { + ide_task_t *task = rq->special; + + if (task->tf_flags & IDE_TFLAG_IO_16BIT) + drive->io_32bit = 0; + } + touch_softlockup_watchdog(); switch (drive->hwif->data_phase) { @@ -319,6 +366,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, ide_pio_sector(drive, write); break; } + + drive->io_32bit = saved_io_32bit; } static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, @@ -356,40 +405,35 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, return ide_error(drive, s, stat); } -static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) +void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) { - HWIF(drive)->cursg = NULL; - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { - ide_task_t *task = rq->special; + u8 err = drive->hwif->INB(IDE_ERROR_REG); - if (task->tf_out_flags.all) { - u8 err = drive->hwif->INB(IDE_ERROR_REG); - ide_end_drive_cmd(drive, stat, err); - return; - } + ide_end_drive_cmd(drive, stat, err); + return; } if (rq->rq_disk) { ide_driver_t *drv; drv = *(ide_driver_t **)rq->rq_disk->private_data;; - drv->end_request(drive, 1, rq->hard_nr_sectors); + drv->end_request(drive, 1, rq->nr_sectors); } else - ide_end_request(drive, 1, rq->hard_nr_sectors); + ide_end_request(drive, 1, rq->nr_sectors); } /* * Handler for command with PIO data-in phase (Read/Read Multiple). */ -ide_startstop_t task_in_intr (ide_drive_t *drive) +static ide_startstop_t task_in_intr(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; struct request *rq = HWGROUP(drive)->rq; u8 stat = hwif->INB(IDE_STATUS_REG); /* new way for dealing with premature shared PCI interrupts */ - if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { + if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) { if (stat & (ERR_STAT | DRQ_STAT)) return task_error(drive, rq, __FUNCTION__, stat); /* No data yet, so wait for another IRQ. */ @@ -402,7 +446,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive) /* If it was the last datablock check status and finish transfer. */ if (!hwif->nleft) { stat = wait_drive_not_busy(drive); - if (!OK_STAT(stat, 0, BAD_R_STAT)) + if (!OK_STAT(stat, 0, BAD_STAT)) return task_error(drive, rq, __FUNCTION__, stat); task_end_request(drive, rq, stat); return ide_stopped; @@ -413,7 +457,6 @@ ide_startstop_t task_in_intr (ide_drive_t *drive) return ide_started; } -EXPORT_SYMBOL(task_in_intr); /* * Handler for command with PIO data-out phase (Write/Write Multiple). @@ -443,11 +486,11 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive) return ide_started; } -ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq) +static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; - if (ide_wait_stat(&startstop, drive, DATA_READY, + if (ide_wait_stat(&startstop, drive, DRQ_STAT, drive->bad_wstat, WAIT_DRQ)) { printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n", drive->name, @@ -464,13 +507,13 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq) return ide_started; } -EXPORT_SYMBOL(pre_task_out_intr); -static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf) +int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect) { struct request rq; memset(&rq, 0, sizeof(rq)); + rq.ref_count = 1; rq.cmd_type = REQ_TYPE_ATA_TASKFILE; rq.buffer = buf; @@ -480,50 +523,41 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long * if we would find a solution to transfer any size. * To support special commands like READ LONG. */ - if (args->command_type != IDE_DRIVE_TASK_NO_DATA) { - if (data_size == 0) - rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; - else - rq.nr_sectors = data_size / SECTOR_SIZE; - - if (!rq.nr_sectors) { - printk(KERN_ERR "%s: in/out command without data\n", - drive->name); - return -EFAULT; - } + rq.hard_nr_sectors = rq.nr_sectors = nsect; + rq.hard_cur_sectors = rq.current_nr_sectors = nsect; - rq.hard_nr_sectors = rq.nr_sectors; - rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors; + if (task->tf_flags & IDE_TFLAG_WRITE) + rq.cmd_flags |= REQ_RW; - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - rq.cmd_flags |= REQ_RW; - } + rq.special = task; + task->rq = &rq; - rq.special = args; - args->rq = &rq; return ide_do_drive_cmd(drive, &rq, ide_wait); } -int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf) +EXPORT_SYMBOL(ide_raw_taskfile); + +int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task) { - return ide_diag_taskfile(drive, args, 0, buf); -} + task->data_phase = TASKFILE_NO_DATA; -EXPORT_SYMBOL(ide_raw_taskfile); + return ide_raw_taskfile(drive, task, NULL, 0); +} +EXPORT_SYMBOL_GPL(ide_no_data_taskfile); +#ifdef CONFIG_IDE_TASK_IOCTL int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { ide_task_request_t *req_task; ide_task_t args; u8 *outbuf = NULL; u8 *inbuf = NULL; - task_ioreg_t *argsptr = args.tfRegister; - task_ioreg_t *hobsptr = args.hobRegister; + u8 *data_buf = NULL; int err = 0; int tasksize = sizeof(struct ide_task_request_s); unsigned int taskin = 0; unsigned int taskout = 0; - u8 io_32bit = drive->io_32bit; + u16 nsect = 0; char __user *buf = (char __user *)arg; // printk("IDE Taskfile ...\n"); @@ -570,24 +604,52 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) } memset(&args, 0, sizeof(ide_task_t)); - memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); - memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE); - args.tf_in_flags = req_task->in_flags; - args.tf_out_flags = req_task->out_flags; - args.data_phase = req_task->data_phase; - args.command_type = req_task->req_cmd; + memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2); + memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); + + args.data_phase = req_task->data_phase; + + args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE | + IDE_TFLAG_IN_TF; + if (drive->addressing == 1) + args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB); + + if (req_task->out_flags.all) { + args.tf_flags |= IDE_TFLAG_FLAGGED; + + if (req_task->out_flags.b.data) + args.tf_flags |= IDE_TFLAG_OUT_DATA; + + if (req_task->out_flags.b.nsector_hob) + args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT; + if (req_task->out_flags.b.sector_hob) + args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL; + if (req_task->out_flags.b.lcyl_hob) + args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM; + if (req_task->out_flags.b.hcyl_hob) + args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH; + + if (req_task->out_flags.b.error_feature) + args.tf_flags |= IDE_TFLAG_OUT_FEATURE; + if (req_task->out_flags.b.nsector) + args.tf_flags |= IDE_TFLAG_OUT_NSECT; + if (req_task->out_flags.b.sector) + args.tf_flags |= IDE_TFLAG_OUT_LBAL; + if (req_task->out_flags.b.lcyl) + args.tf_flags |= IDE_TFLAG_OUT_LBAM; + if (req_task->out_flags.b.hcyl) + args.tf_flags |= IDE_TFLAG_OUT_LBAH; + } else { + args.tf_flags |= IDE_TFLAG_OUT_TF; + if (args.tf_flags & IDE_TFLAG_LBA48) + args.tf_flags |= IDE_TFLAG_OUT_HOB; + } + + if (req_task->in_flags.b.data) + args.tf_flags |= IDE_TFLAG_IN_DATA; - drive->io_32bit = 0; switch(req_task->data_phase) { - case TASKFILE_OUT_DMAQ: - case TASKFILE_OUT_DMA: - err = ide_diag_taskfile(drive, &args, taskout, outbuf); - break; - case TASKFILE_IN_DMAQ: - case TASKFILE_IN_DMA: - err = ide_diag_taskfile(drive, &args, taskin, inbuf); - break; case TASKFILE_MULTI_OUT: if (!drive->mult_count) { /* (hs): give up if multcount is not set */ @@ -599,9 +661,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) } /* fall through */ case TASKFILE_OUT: - args.prehandler = &pre_task_out_intr; - args.handler = &task_out_intr; - err = ide_diag_taskfile(drive, &args, taskout, outbuf); + /* fall through */ + case TASKFILE_OUT_DMAQ: + case TASKFILE_OUT_DMA: + nsect = taskout / SECTOR_SIZE; + data_buf = outbuf; break; case TASKFILE_MULTI_IN: if (!drive->mult_count) { @@ -614,22 +678,46 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) } /* fall through */ case TASKFILE_IN: - args.handler = &task_in_intr; - err = ide_diag_taskfile(drive, &args, taskin, inbuf); + /* fall through */ + case TASKFILE_IN_DMAQ: + case TASKFILE_IN_DMA: + nsect = taskin / SECTOR_SIZE; + data_buf = inbuf; break; case TASKFILE_NO_DATA: - args.handler = &task_no_data_intr; - err = ide_diag_taskfile(drive, &args, 0, NULL); break; default: err = -EFAULT; goto abort; } - memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE); - memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE); - req_task->in_flags = args.tf_in_flags; - req_task->out_flags = args.tf_out_flags; + if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA) + nsect = 0; + else if (!nsect) { + nsect = (args.tf.hob_nsect << 8) | args.tf.nsect; + + if (!nsect) { + printk(KERN_ERR "%s: in/out command without data\n", + drive->name); + err = -EFAULT; + goto abort; + } + } + + if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE) + args.tf_flags |= IDE_TFLAG_WRITE; + + err = ide_raw_taskfile(drive, &args, data_buf, nsect); + + memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2); + memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE); + + if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) && + req_task->in_flags.all == 0) { + req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; + if (drive->addressing == 1) + req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); + } if (copy_to_user(buf, req_task, tasksize)) { err = -EFAULT; @@ -656,39 +744,25 @@ abort: // printk("IDE Taskfile ioctl ended. rc = %i\n", err); - drive->io_32bit = io_32bit; - return err; } - -int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf) -{ - struct request rq; - u8 buffer[4]; - - if (!buf) - buf = buffer; - memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors); - ide_init_drive_cmd(&rq); - rq.buffer = buf; - *buf++ = cmd; - *buf++ = nsect; - *buf++ = feature; - *buf++ = sectors; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} +#endif int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { - int err = 0; - u8 args[4], *argbuf = args; - u8 xfer_rate = 0; - int argsize = 4; + u8 *buf = NULL; + int bufsize = 0, err = 0; + u8 args[4], xfer_rate = 0; ide_task_t tfargs; + struct ide_taskfile *tf = &tfargs.tf; + struct hd_driveid *id = drive->id; if (NULL == (void *) arg) { struct request rq; + ide_init_drive_cmd(&rq); + rq.cmd_type = REQ_TYPE_ATA_TASKFILE; + return ide_do_drive_cmd(drive, &rq, ide_wait); } @@ -696,27 +770,46 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) return -EFAULT; memset(&tfargs, 0, sizeof(ide_task_t)); - tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; - tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; - tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; - tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; - tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; + tf->feature = args[2]; + if (args[0] == WIN_SMART) { + tf->nsect = args[3]; + tf->lbal = args[1]; + tf->lbam = 0x4f; + tf->lbah = 0xc2; + tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT; + } else { + tf->nsect = args[1]; + tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE | + IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT; + } + tf->command = args[0]; + tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA; if (args[3]) { - argsize = 4 + (SECTOR_WORDS * 4 * args[3]); - argbuf = kzalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) + tfargs.tf_flags |= IDE_TFLAG_IO_16BIT; + bufsize = SECTOR_WORDS * 4 * args[3]; + buf = kzalloc(bufsize, GFP_KERNEL); + if (buf == NULL) return -ENOMEM; } - if (set_transfer(drive, &tfargs)) { + + if (tf->command == WIN_SETFEATURES && + tf->feature == SETFEATURES_XFER && + tf->nsect >= XFER_SW_DMA_0 && + (id->dma_ultra || id->dma_mword || id->dma_1word)) { xfer_rate = args[1]; - if (ide_ata66_check(drive, &tfargs)) + if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) { + printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " + "be set\n", drive->name); goto abort; + } } - err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); + err = ide_raw_taskfile(drive, &tfargs, buf, args[3]); + + args[0] = tf->status; + args[1] = tf->error; + args[2] = tf->nsect; if (!err && xfer_rate) { /* active-retuning-calls future */ @@ -724,142 +817,38 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) ide_driveid_update(drive); } abort: - if (copy_to_user((void __user *)arg, argbuf, argsize)) + if (copy_to_user((void __user *)arg, &args, 4)) err = -EFAULT; - if (argsize > 4) - kfree(argbuf); + if (buf) { + if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) + err = -EFAULT; + kfree(buf); + } return err; } -static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf) -{ - struct request rq; - - ide_init_drive_cmd(&rq); - rq.cmd_type = REQ_TYPE_ATA_TASK; - rq.buffer = buf; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { void __user *p = (void __user *)arg; int err = 0; - u8 args[7], *argbuf = args; - int argsize = 7; + u8 args[7]; + ide_task_t task; if (copy_from_user(args, p, 7)) return -EFAULT; - err = ide_wait_cmd_task(drive, argbuf); - if (copy_to_user(p, argbuf, argsize)) - err = -EFAULT; - return err; -} -/* - * NOTICE: This is additions from IBM to provide a discrete interface, - * for selective taskregister access operations. Nice JOB Klaus!!! - * Glad to be able to work and co-develop this with you and IBM. - */ -ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = HWIF(drive); - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; + memset(&task, 0, sizeof(task)); + memcpy(&task.tf_array[7], &args[1], 6); + task.tf.command = args[0]; + task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - if (task->data_phase == TASKFILE_MULTI_IN || - task->data_phase == TASKFILE_MULTI_OUT) { - if (!drive->mult_count) { - printk(KERN_ERR "%s: multimode not set!\n", drive->name); - return ide_stopped; - } - } - - /* - * (ks) Check taskfile in flags. - * If set, then execute as it is defined. - * If not set, then define default settings. - * The default values are: - * read all taskfile registers (except data) - * read the hob registers (sector, nsector, lcyl, hcyl) - */ - if (task->tf_in_flags.all == 0) { - task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; - if (drive->addressing == 1) - task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); - } - - /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ - if (IDE_CONTROL_REG) - /* clear nIEN */ - hwif->OUTB(drive->ctl, IDE_CONTROL_REG); - SELECT_MASK(drive, 0); - - if (task->tf_out_flags.b.data) { - u16 data = taskfile->data + (hobfile->data << 8); - hwif->OUTW(data, IDE_DATA_REG); - } - - /* (ks) send hob registers first */ - if (task->tf_out_flags.b.nsector_hob) - hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG); - if (task->tf_out_flags.b.sector_hob) - hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl_hob) - hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl_hob) - hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG); - - /* (ks) Send now the standard registers */ - if (task->tf_out_flags.b.error_feature) - hwif->OUTB(taskfile->feature, IDE_FEATURE_REG); - /* refers to number of sectors to transfer */ - if (task->tf_out_flags.b.nsector) - hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to sector offset or start sector */ - if (task->tf_out_flags.b.sector) - hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl) - hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl) - hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG); - - /* - * (ks) In the flagged taskfile approch, we will use all specified - * registers and the register value will not be changed, except the - * select bit (master/slave) in the drive_head register. We must make - * sure that the desired drive is selected. - */ - hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG); - switch(task->data_phase) { + err = ide_no_data_taskfile(drive, &task); - case TASKFILE_OUT_DMAQ: - case TASKFILE_OUT_DMA: - case TASKFILE_IN_DMAQ: - case TASKFILE_IN_DMA: - if (!drive->using_dma) - break; + args[0] = task.tf.command; + memcpy(&args[1], &task.tf_array[7], 6); - if (!hwif->dma_setup(drive)) { - hwif->dma_exec_cmd(drive, taskfile->command); - hwif->dma_start(drive); - return ide_started; - } - break; - - default: - if (task->handler == NULL) - return ide_stopped; - - /* Issue the command */ - if (task->prehandler) { - hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG); - ndelay(400); /* FIXME */ - return task->prehandler(drive, task->rq); - } - ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); - return ide_started; - } + if (copy_to_user(p, args, 7)) + err = -EFAULT; - return ide_stopped; + return err; } diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h index daffbb9797e..adeda762652 100644 --- a/drivers/ide/ide-timing.h +++ b/drivers/ide/ide-timing.h @@ -2,8 +2,6 @@ #define _IDE_TIMING_H /* - * $Id: ide-timing.h,v 1.6 2001/12/23 22:47:56 vojtech Exp $ - * * Copyright (c) 1999-2001 Vojtech Pavlik */ diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 674a65c1a13..ac613600161 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1,7 +1,6 @@ /* - * linux/drivers/ide/ide.c Version 7.00beta2 Mar 05 2003 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) + * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) + * Copyrifht (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz */ /* @@ -46,7 +45,6 @@ */ #define REVISION "Revision: 7.00alpha2" -#define VERSION "Id: ide.c 7.00a2 20020906" #define _IDE_C /* Tell ide.h it's really us */ @@ -95,7 +93,7 @@ DEFINE_MUTEX(ide_cfg_mtx); __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); #ifdef CONFIG_IDEPCI_PCIBUS_ORDER -static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ +int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ #endif int noautodma = 0; @@ -116,7 +114,7 @@ EXPORT_SYMBOL(ide_hwifs); /* * Do not even *think* about calling this! */ -static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) +void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) { unsigned int unit; @@ -159,6 +157,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) init_completion(&drive->gendev_rel_comp); } } +EXPORT_SYMBOL_GPL(ide_init_port_data); static void init_hwif_default(ide_hwif_t *hwif, unsigned int index) { @@ -177,8 +176,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index) #endif } -extern void ide_arm_init(void); - /* * init_ide_data() sets reasonable default values into all fields * of all instances of the hwifs and drives, but only on the first call. @@ -210,16 +207,13 @@ static void __init init_ide_data (void) /* Initialise all interface structures */ for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; - init_hwif_data(hwif, index); + ide_init_port_data(hwif, index); init_hwif_default(hwif, index); #if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI) hwif->irq = ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]); #endif } -#ifdef CONFIG_IDE_ARM - ide_arm_init(); -#endif } /** @@ -246,22 +240,12 @@ static int ide_system_bus_speed(void) #define pci_default 0 #endif /* CONFIG_PCI */ - if (!system_bus_speed) { - if (idebus_parameter) { - /* user supplied value */ - system_bus_speed = idebus_parameter; - } else if (pci_dev_present(pci_default)) { - /* safe default value for PCI */ - system_bus_speed = 33; - } else { - /* safe default value for VESA and PCI */ - system_bus_speed = 50; - } - printk(KERN_INFO "ide: Assuming %dMHz system bus speed " - "for PIO modes%s\n", system_bus_speed, - idebus_parameter ? "" : "; override with idebus=xx"); - } - return system_bus_speed; + /* user supplied value */ + if (idebus_parameter) + return idebus_parameter; + + /* safe default value for PCI or VESA and PCI*/ + return pci_dev_present(pci_default) ? 33 : 50; } ide_hwif_t * ide_find_port(unsigned long base) @@ -409,13 +393,12 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->chipset = tmp_hwif->chipset; hwif->hold = tmp_hwif->hold; + hwif->dev = tmp_hwif->dev; + #ifdef CONFIG_BLK_DEV_IDEPCI - hwif->pci_dev = tmp_hwif->pci_dev; hwif->cds = tmp_hwif->cds; #endif - hwif->fixup = tmp_hwif->fixup; - hwif->set_pio_mode = tmp_hwif->set_pio_mode; hwif->set_dma_mode = tmp_hwif->set_dma_mode; hwif->mdma_filter = tmp_hwif->mdma_filter; @@ -424,7 +407,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->reset_poll = tmp_hwif->reset_poll; hwif->pre_reset = tmp_hwif->pre_reset; hwif->resetproc = tmp_hwif->resetproc; - hwif->intrproc = tmp_hwif->intrproc; hwif->maskproc = tmp_hwif->maskproc; hwif->quirkproc = tmp_hwif->quirkproc; hwif->busproc = tmp_hwif->busproc; @@ -434,16 +416,13 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->atapi_input_bytes = tmp_hwif->atapi_input_bytes; hwif->atapi_output_bytes = tmp_hwif->atapi_output_bytes; + hwif->dma_host_set = tmp_hwif->dma_host_set; hwif->dma_setup = tmp_hwif->dma_setup; hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd; hwif->dma_start = tmp_hwif->dma_start; hwif->ide_dma_end = tmp_hwif->ide_dma_end; - hwif->ide_dma_on = tmp_hwif->ide_dma_on; - hwif->dma_off_quietly = tmp_hwif->dma_off_quietly; hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq; hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq; - hwif->dma_host_on = tmp_hwif->dma_host_on; - hwif->dma_host_off = tmp_hwif->dma_host_off; hwif->dma_lost_irq = tmp_hwif->dma_lost_irq; hwif->dma_timeout = tmp_hwif->dma_timeout; @@ -468,7 +447,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) #endif hwif->dma_base = tmp_hwif->dma_base; - hwif->dma_master = tmp_hwif->dma_master; hwif->dma_command = tmp_hwif->dma_command; hwif->dma_vendor1 = tmp_hwif->dma_vendor1; hwif->dma_status = tmp_hwif->dma_status; @@ -483,9 +461,46 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->hwif_data = tmp_hwif->hwif_data; } +void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) +{ + ide_hwgroup_t *hwgroup = hwif->hwgroup; + + spin_lock_irq(&ide_lock); + /* + * Remove us from the hwgroup, and free + * the hwgroup if we were the only member + */ + if (hwif->next == hwif) { + BUG_ON(hwgroup->hwif != hwif); + kfree(hwgroup); + } else { + /* There is another interface in hwgroup. + * Unlink us, and set hwgroup->drive and ->hwif to + * something sane. + */ + ide_hwif_t *g = hwgroup->hwif; + + while (g->next != hwif) + g = g->next; + g->next = hwif->next; + if (hwgroup->hwif == hwif) { + /* Chose a random hwif for hwgroup->hwif. + * It's guaranteed that there are no drives + * left in the hwgroup. + */ + BUG_ON(hwgroup->drive != NULL); + hwgroup->hwif = g; + } + BUG_ON(hwgroup->hwif == hwif); + } + spin_unlock_irq(&ide_lock); +} + /** * ide_unregister - free an IDE interface * @index: index of interface (will change soon to a pointer) + * @init_default: init default hwif flag + * @restore: restore hwif flag * * Perform the final unregister of an IDE interface. At the moment * we don't refcount interfaces so this will also get split up. @@ -505,7 +520,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) * This is raving bonkers. */ -void ide_unregister(unsigned int index) +void ide_unregister(unsigned int index, int init_default, int restore) { ide_drive_t *drive; ide_hwif_t *hwif, *g; @@ -550,43 +565,8 @@ void ide_unregister(unsigned int index) if (irq_count == 1) free_irq(hwif->irq, hwgroup); - spin_lock_irq(&ide_lock); - /* - * Note that we only release the standard ports, - * and do not even try to handle any extra ports - * allocated for weird IDE interface chipsets. - */ - ide_hwif_release_regions(hwif); + ide_remove_port_from_hwgroup(hwif); - /* - * Remove us from the hwgroup, and free - * the hwgroup if we were the only member - */ - if (hwif->next == hwif) { - BUG_ON(hwgroup->hwif != hwif); - kfree(hwgroup); - } else { - /* There is another interface in hwgroup. - * Unlink us, and set hwgroup->drive and ->hwif to - * something sane. - */ - g = hwgroup->hwif; - while (g->next != hwif) - g = g->next; - g->next = hwif->next; - if (hwgroup->hwif == hwif) { - /* Chose a random hwif for hwgroup->hwif. - * It's guaranteed that there are no drives - * left in the hwgroup. - */ - BUG_ON(hwgroup->drive != NULL); - hwgroup->hwif = g; - } - BUG_ON(hwgroup->hwif == hwif); - } - - /* More messed up locking ... */ - spin_unlock_irq(&ide_lock); device_unregister(&hwif->gendev); wait_for_completion(&hwif->gendev_rel_comp); @@ -602,7 +582,6 @@ void ide_unregister(unsigned int index) (void) ide_release_dma(hwif); hwif->dma_base = 0; - hwif->dma_master = 0; hwif->dma_command = 0; hwif->dma_vendor1 = 0; hwif->dma_status = 0; @@ -613,14 +592,24 @@ void ide_unregister(unsigned int index) hwif->extra_ports = 0; } + /* + * Note that we only release the standard ports, + * and do not even try to handle any extra ports + * allocated for weird IDE interface chipsets. + */ + ide_hwif_release_regions(hwif); + /* copy original settings */ tmp_hwif = *hwif; /* restore hwif data to pristine status */ - init_hwif_data(hwif, index); - init_hwif_default(hwif, index); + ide_init_port_data(hwif, index); - ide_hwif_restore(hwif, &tmp_hwif); + if (init_default) + init_hwif_default(hwif, index); + + if (restore) + ide_hwif_restore(hwif, &tmp_hwif); abort: spin_unlock_irq(&ide_lock); @@ -683,70 +672,86 @@ void ide_setup_ports ( hw_regs_t *hw, */ } +void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) +{ + memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports)); + hwif->irq = hw->irq; + hwif->noprobe = 0; + hwif->chipset = hw->chipset; + hwif->gendev.parent = hw->dev; + hwif->ack_intr = hw->ack_intr; +} +EXPORT_SYMBOL_GPL(ide_init_port_hw); + +ide_hwif_t *ide_deprecated_find_port(unsigned long base) +{ + ide_hwif_t *hwif; + int i; + + for (i = 0; i < MAX_HWIFS; i++) { + hwif = &ide_hwifs[i]; + if (hwif->io_ports[IDE_DATA_OFFSET] == base) + goto found; + } + + for (i = 0; i < MAX_HWIFS; i++) { + hwif = &ide_hwifs[i]; + if (hwif->hold) + continue; + if (!hwif->present && hwif->mate == NULL) + goto found; + } + + hwif = NULL; +found: + return hwif; +} +EXPORT_SYMBOL_GPL(ide_deprecated_find_port); + /** * ide_register_hw - register IDE interface * @hw: hardware registers - * @fixup: fixup function - * @initializing: set while initializing built-in drivers + * @quirkproc: quirkproc function * @hwifp: pointer to returned hwif * * Register an IDE interface, specifying exactly the registers etc. - * Set init=1 iff calling before probes have taken place. * * Returns -1 on error. */ -int ide_register_hw(hw_regs_t *hw, void (*fixup)(ide_hwif_t *), - int initializing, ide_hwif_t **hwifp) +int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *), + ide_hwif_t **hwifp) { int index, retry = 1; ide_hwif_t *hwif; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; do { - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (hwif->io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET]) - goto found; - } - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (hwif->hold) - continue; - if ((!hwif->present && !hwif->mate && !initializing) || - (!hwif->io_ports[IDE_DATA_OFFSET] && initializing)) - goto found; - } + hwif = ide_deprecated_find_port(hw->io_ports[IDE_DATA_OFFSET]); + index = hwif->index; + if (hwif) + goto found; for (index = 0; index < MAX_HWIFS; index++) - ide_unregister(index); + ide_unregister(index, 1, 1); } while (retry--); return -1; found: if (hwif->present) - ide_unregister(index); - else if (!hwif->hold) { - init_hwif_data(hwif, index); - init_hwif_default(hwif, index); - } - if (hwif->present) - return -1; - memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports)); - hwif->irq = hw->irq; - hwif->noprobe = 0; - hwif->fixup = fixup; - hwif->chipset = hw->chipset; - hwif->gendev.parent = hw->dev; - hwif->ack_intr = hw->ack_intr; + ide_unregister(index, 0, 1); + else if (!hwif->hold) + ide_init_port_data(hwif, index); - if (initializing == 0) { - u8 idx[4] = { index, 0xff, 0xff, 0xff }; + ide_init_port_hw(hwif, hw); + hwif->quirkproc = quirkproc; - ide_device_add(idx); - } + idx[0] = index; + + ide_device_add(idx, NULL); if (hwifp) *hwifp = hwif; - return (initializing || hwif->present) ? index : -1; + return hwif->present ? index : -1; } EXPORT_SYMBOL(ide_register_hw); @@ -800,11 +805,13 @@ int set_io_32bit(ide_drive_t *drive, int arg) if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) return -EINVAL; + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + drive->io_32bit = arg; -#ifdef CONFIG_BLK_DEV_DTC2278 - if (HWIF(drive)->chipset == ide_dtc2278) - HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg; -#endif /* CONFIG_BLK_DEV_DTC2278 */ + + spin_unlock_irq(&ide_lock); + return 0; } @@ -833,7 +840,7 @@ int set_using_dma(ide_drive_t *drive, int arg) if (!drive->id || !(drive->id->capability & 1)) goto out; - if (hwif->ide_dma_on == NULL) + if (hwif->dma_host_set == NULL) goto out; err = -EBUSY; @@ -848,8 +855,7 @@ int set_using_dma(ide_drive_t *drive, int arg) err = 0; if (arg) { - hwif->dma_off_quietly(drive); - if (ide_set_dma(drive) || hwif->ide_dma_on(drive)) + if (ide_set_dma(drive)) err = -EIO; } else ide_dma_off(drive); @@ -882,7 +888,10 @@ int set_pio_mode(ide_drive_t *drive, int arg) if (drive->special.b.set_tune) return -EBUSY; + ide_init_drive_cmd(&rq); + rq.cmd_type = REQ_TYPE_ATA_TASKFILE; + drive->tune_req = (u8) arg; drive->special.b.set_tune = 1; (void) ide_do_drive_cmd(drive, &rq, ide_wait); @@ -914,7 +923,7 @@ static int set_unmaskirq(ide_drive_t *drive, int arg) int system_bus_clock (void) { - return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed )); + return system_bus_speed; } EXPORT_SYMBOL(system_bus_clock); @@ -1026,11 +1035,8 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device case HDIO_GET_NICE: return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP | - drive->nice0 << IDE_NICE_0 | - drive->nice1 << IDE_NICE_1 | - drive->nice2 << IDE_NICE_2, + drive->nice1 << IDE_NICE_1, (long __user *) arg); - #ifdef CONFIG_IDE_TASK_IOCTL case HDIO_DRIVE_TASKFILE: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) @@ -1064,14 +1070,14 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device ide_init_hwif_ports(&hw, (unsigned long) args[0], (unsigned long) args[1], NULL); hw.irq = args[2]; - if (ide_register_hw(&hw, NULL, 0, NULL) == -1) + if (ide_register_hw(&hw, NULL, NULL) == -1) return -EIO; return 0; } case HDIO_UNREGISTER_HWIF: if (!capable(CAP_SYS_RAWIO)) return -EACCES; /* (arg > MAX_HWIFS) checked in function */ - ide_unregister(arg); + ide_unregister(arg, 1, 1); return 0; case HDIO_SET_NICE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -1225,26 +1231,12 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m return 0; /* zero = nothing matched */ } -#ifdef CONFIG_BLK_DEV_ALI14XX extern int probe_ali14xx; -extern int ali14xx_init(void); -#endif -#ifdef CONFIG_BLK_DEV_UMC8672 extern int probe_umc8672; -extern int umc8672_init(void); -#endif -#ifdef CONFIG_BLK_DEV_DTC2278 extern int probe_dtc2278; -extern int dtc2278_init(void); -#endif -#ifdef CONFIG_BLK_DEV_HT6560B extern int probe_ht6560b; -extern int ht6560b_init(void); -#endif -#ifdef CONFIG_BLK_DEV_QD65XX extern int probe_qd65xx; -extern int qd65xx_init(void); -#endif +extern int cmd640_vlb; static int __initdata is_chipset_set[MAX_HWIFS]; @@ -1321,7 +1313,7 @@ static int __init ide_setup(char *s) if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = { "none", "noprobe", "nowerr", "cdrom", "nodma", - "autotune", "noautotune", "minus8", "swapdata", "bswap", + "autotune", "noautotune", "-8", "-9", "-10", "noflush", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; @@ -1357,10 +1349,6 @@ static int __init ide_setup(char *s) case -7: /* "noautotune" */ drive->autotune = IDE_TUNE_NOAUTO; goto obsolete_option; - case -9: /* "swapdata" */ - case -10: /* "bswap" */ - drive->bswap = 1; - goto done; case -11: /* noflush */ drive->noflush = 1; goto done; @@ -1460,11 +1448,8 @@ static int __init ide_setup(char *s) #endif #ifdef CONFIG_BLK_DEV_CMD640 case -14: /* "cmd640_vlb" */ - { - extern int cmd640_vlb; /* flag for cmd640.c */ cmd640_vlb = 1; goto done; - } #endif #ifdef CONFIG_BLK_DEV_HT6560B case -13: /* "ht6560b" */ @@ -1554,79 +1539,6 @@ done: return 1; } -extern void __init pnpide_init(void); -extern void __exit pnpide_exit(void); -extern void __init h8300_ide_init(void); - -/* - * probe_for_hwifs() finds/initializes "known" IDE interfaces - */ -static void __init probe_for_hwifs (void) -{ -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER - ide_scan_pcibus(ide_scan_direction); -#endif - -#ifdef CONFIG_ETRAX_IDE - { - extern void init_e100_ide(void); - init_e100_ide(); - } -#endif /* CONFIG_ETRAX_IDE */ -#ifdef CONFIG_BLK_DEV_CMD640 - { - extern void ide_probe_for_cmd640x(void); - ide_probe_for_cmd640x(); - } -#endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_IDE_PMAC - { - extern int pmac_ide_probe(void); - (void)pmac_ide_probe(); - } -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ -#ifdef CONFIG_BLK_DEV_GAYLE - { - extern void gayle_init(void); - gayle_init(); - } -#endif /* CONFIG_BLK_DEV_GAYLE */ -#ifdef CONFIG_BLK_DEV_FALCON_IDE - { - extern void falconide_init(void); - falconide_init(); - } -#endif /* CONFIG_BLK_DEV_FALCON_IDE */ -#ifdef CONFIG_BLK_DEV_MAC_IDE - { - extern void macide_init(void); - macide_init(); - } -#endif /* CONFIG_BLK_DEV_MAC_IDE */ -#ifdef CONFIG_BLK_DEV_Q40IDE - { - extern void q40ide_init(void); - q40ide_init(); - } -#endif /* CONFIG_BLK_DEV_Q40IDE */ -#ifdef CONFIG_BLK_DEV_BUDDHA - { - extern void buddha_init(void); - buddha_init(); - } -#endif /* CONFIG_BLK_DEV_BUDDHA */ -#ifdef CONFIG_BLK_DEV_IDEPNP - pnpide_init(); -#endif -#ifdef CONFIG_H8300 - h8300_ide_init(); -#endif -} - -/* - * Probe module - */ - EXPORT_SYMBOL(ide_lock); static int ide_bus_match(struct device *dev, struct device_driver *drv) @@ -1670,10 +1582,34 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "ide:m-%s\n", media_string(drive)); } +static ssize_t model_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->id->model); +} + +static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->id->fw_rev); +} + +static ssize_t serial_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->id->serial_no); +} + static struct device_attribute ide_dev_attrs[] = { __ATTR_RO(media), __ATTR_RO(drivename), __ATTR_RO(modalias), + __ATTR_RO(model), + __ATTR_RO(firmware), + __ATTR(serial, 0400, serial_show, NULL), __ATTR_NULL }; @@ -1739,6 +1675,10 @@ static int __init ide_init(void) printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); system_bus_speed = ide_system_bus_speed(); + printk(KERN_INFO "ide: Assuming %dMHz system bus speed " + "for PIO modes%s\n", system_bus_speed, + idebus_parameter ? "" : "; override with idebus=xx"); + ret = bus_register(&ide_bus_type); if (ret < 0) { printk(KERN_WARNING "IDE: bus_register error: %d\n", ret); @@ -1749,30 +1689,6 @@ static int __init ide_init(void) proc_ide_create(); -#ifdef CONFIG_BLK_DEV_ALI14XX - if (probe_ali14xx) - (void)ali14xx_init(); -#endif -#ifdef CONFIG_BLK_DEV_UMC8672 - if (probe_umc8672) - (void)umc8672_init(); -#endif -#ifdef CONFIG_BLK_DEV_DTC2278 - if (probe_dtc2278) - (void)dtc2278_init(); -#endif -#ifdef CONFIG_BLK_DEV_HT6560B - if (probe_ht6560b) - (void)ht6560b_init(); -#endif -#ifdef CONFIG_BLK_DEV_QD65XX - if (probe_qd65xx) - (void)qd65xx_init(); -#endif - - /* Probe for special PCI and other "known" interface chipsets. */ - probe_for_hwifs(); - return 0; } @@ -1806,11 +1722,7 @@ void __exit cleanup_module (void) int index; for (index = 0; index < MAX_HWIFS; ++index) - ide_unregister(index); - -#ifdef CONFIG_BLK_DEV_IDEPNP - pnpide_exit(); -#endif + ide_unregister(index, 0, 0); proc_ide_destroy(); diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile index 409822349f1..7043ec7d1e0 100644 --- a/drivers/ide/legacy/Makefile +++ b/drivers/ide/legacy/Makefile @@ -1,15 +1,24 @@ +# link order is important here + obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o +obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o -obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o -obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o +obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o +obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o +obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o +obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o +obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o -obj-$(CONFIG_BLK_DEV_PLATFORM) += ide_platform.o +ifeq ($(CONFIG_BLK_DEV_IDECS), m) + obj-m += ide-cs.o +endif -# Last of all -obj-$(CONFIG_BLK_DEV_HD) += hd.o +ifeq ($(CONFIG_BLK_DEV_PLATFORM), m) + obj-m += ide_platform.o +endif EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 10311ecc674..d4d1a6bea59 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/legacy/ali14xx.c Version 0.03 Feb 09, 1996 - * * Copyright (C) 1996 Linus Torvalds & author (see below) */ @@ -53,12 +51,13 @@ /* port addresses for auto-detection */ #define ALI_NUM_PORTS 4 -static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4}; +static const int ports[ALI_NUM_PORTS] __initdata = + { 0x074, 0x0f4, 0x034, 0x0e4 }; /* register initialization data */ typedef struct { u8 reg, data; } RegInitializer; -static RegInitializer initData[] __initdata = { +static const RegInitializer initData[] __initdata = { {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, @@ -177,7 +176,7 @@ static int __init findPort (void) * Initialize controller registers with default values. */ static int __init initRegisters (void) { - RegInitializer *p; + const RegInitializer *p; u8 t; unsigned long flags; @@ -192,9 +191,14 @@ static int __init initRegisters (void) { return t; } +static const struct ide_port_info ali14xx_port_info = { + .chipset = ide_ali14xx, + .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE, + .pio_mask = ATA_PIO4, +}; + static int __init ali14xx_probe(void) { - ide_hwif_t *hwif, *mate; static u8 idx[4] = { 0, 1, 0xff, 0xff }; printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n", @@ -206,21 +210,10 @@ static int __init ali14xx_probe(void) return 1; } - hwif = &ide_hwifs[0]; - mate = &ide_hwifs[1]; - - hwif->chipset = ide_ali14xx; - hwif->pio_mask = ATA_PIO4; - hwif->set_pio_mode = &ali14xx_set_pio_mode; - hwif->mate = mate; - - mate->chipset = ide_ali14xx; - mate->pio_mask = ATA_PIO4; - mate->set_pio_mode = &ali14xx_set_pio_mode; - mate->mate = hwif; - mate->channel = 1; + ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode; + ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode; - ide_device_add(idx); + ide_device_add(idx, &ali14xx_port_info); return 0; } @@ -230,8 +223,7 @@ int probe_ali14xx = 0; module_param_named(probe, probe_ali14xx, bool, 0); MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets"); -/* Can be called directly from ide.c. */ -int __init ali14xx_init(void) +static int __init ali14xx_init(void) { if (probe_ali14xx == 0) goto out; @@ -247,9 +239,7 @@ out: return -ENODEV; } -#ifdef MODULE module_init(ali14xx_init); -#endif MODULE_AUTHOR("see local file"); MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets"); diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c index 4a0be251a05..8bdb79da17e 100644 --- a/drivers/ide/legacy/buddha.c +++ b/drivers/ide/legacy/buddha.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver + * Amiga Buddha, Catweasel and X-Surf IDE Driver * * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others * @@ -112,6 +112,7 @@ typedef enum BuddhaType_Enum { BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF } BuddhaType; +static const char *buddha_board_name[] = { "Buddha", "Catweasel", "X-Surf" }; /* * Check and acknowledge the interrupt status @@ -143,11 +144,11 @@ static int xsurf_ack_intr(ide_hwif_t *hwif) * Probe for a Buddha or Catweasel IDE interface */ -void __init buddha_init(void) +static int __init buddha_init(void) { hw_regs_t hw; ide_hwif_t *hwif; - int i, index; + int i; struct zorro_dev *z = NULL; u_long buddha_board = 0; @@ -156,6 +157,8 @@ void __init buddha_init(void) while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { unsigned long board; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { buddha_num_hwifs = BUDDHA_NUM_HWIFS; type=BOARD_BUDDHA; @@ -195,7 +198,10 @@ fail_base2: /* X-Surf doesn't have this. IRQs are always on */ if (type != BOARD_XSURF) z_writeb(0, buddha_board+BUDDHA_IRQ_MR); - + + printk(KERN_INFO "ide: %s IDE controller\n", + buddha_board_name[type]); + for(i=0;i<buddha_num_hwifs;i++) { if(type != BOARD_XSURF) { ide_setup_ports(&hw, (buddha_board+buddha_bases[i]), @@ -213,23 +219,23 @@ fail_base2: IRQ_AMIGA_PORTS); } - index = ide_register_hw(&hw, NULL, 1, &hwif); - if (index != -1) { + hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif) { + u8 index = hwif->index; + + ide_init_port_data(hwif, index); + ide_init_port_hw(hwif, &hw); + hwif->mmio = 1; - printk("ide%d: ", index); - switch(type) { - case BOARD_BUDDHA: - printk("Buddha"); - break; - case BOARD_CATWEASEL: - printk("Catweasel"); - break; - case BOARD_XSURF: - printk("X-Surf"); - break; - } - printk(" IDE interface\n"); - } + + idx[i] = index; + } } + + ide_device_add(idx, NULL); } + + return 0; } + +module_init(buddha_init); diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index 24a845d45bd..73396f70f2b 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/legacy/dtc2278.c Version 0.02 Feb 10, 1996 - * * Copyright (C) 1996 Linus Torvalds & author (see below) */ @@ -86,14 +84,20 @@ static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio) /* Actually we do - there is a data sheet available for the Winbond but does anyone actually care */ } - - /* - * 32bit I/O has to be enabled for *both* drives at the same time. - */ - drive->io_32bit = 1; - HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1; } +static const struct ide_port_info dtc2278_port_info __initdata = { + .chipset = ide_dtc2278, + .host_flags = IDE_HFLAG_SERIALIZE | + IDE_HFLAG_NO_UNMASK_IRQS | + IDE_HFLAG_IO_32BIT | + /* disallow ->io_32bit changes */ + IDE_HFLAG_NO_IO_32BIT | + IDE_HFLAG_NO_DMA | + IDE_HFLAG_NO_AUTOTUNE, + .pio_mask = ATA_PIO4, +}; + static int __init dtc2278_probe(void) { unsigned long flags; @@ -124,23 +128,9 @@ static int __init dtc2278_probe(void) #endif local_irq_restore(flags); - hwif->serialized = 1; - hwif->chipset = ide_dtc2278; - hwif->pio_mask = ATA_PIO4; hwif->set_pio_mode = &dtc2278_set_pio_mode; - hwif->drives[0].no_unmask = 1; - hwif->drives[1].no_unmask = 1; - hwif->mate = mate; - - mate->serialized = 1; - mate->chipset = ide_dtc2278; - mate->pio_mask = ATA_PIO4; - mate->drives[0].no_unmask = 1; - mate->drives[1].no_unmask = 1; - mate->mate = hwif; - mate->channel = 1; - ide_device_add(idx); + ide_device_add(idx, &dtc2278_port_info); return 0; } @@ -150,8 +140,7 @@ int probe_dtc2278 = 0; module_param_named(probe, probe_dtc2278, bool, 0); MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); -/* Can be called directly from ide.c. */ -int __init dtc2278_init(void) +static int __init dtc2278_init(void) { if (probe_dtc2278 == 0) return -ENODEV; @@ -163,9 +152,7 @@ int __init dtc2278_init(void) return 0; } -#ifdef MODULE module_init(dtc2278_init); -#endif MODULE_AUTHOR("See Local File"); MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets"); diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c index 7d7936f1b90..85b69a82825 100644 --- a/drivers/ide/legacy/falconide.c +++ b/drivers/ide/legacy/falconide.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/legacy/falconide.c -- Atari Falcon IDE Driver + * Atari Falcon IDE Driver * * Created 12 Jul 1997 by Geert Uytterhoeven * @@ -62,19 +62,32 @@ EXPORT_SYMBOL(falconide_intr_lock); * Probe for a Falcon IDE interface */ -void __init falconide_init(void) +static int __init falconide_init(void) { if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) { hw_regs_t hw; - int index; + ide_hwif_t *hwif; + + printk(KERN_INFO "ide: Falcon IDE controller\n"); ide_setup_ports(&hw, ATA_HD_BASE, falconide_offsets, 0, 0, NULL, // falconide_iops, IRQ_MFP_IDE); - index = ide_register_hw(&hw, NULL, 1, NULL); - if (index != -1) - printk("ide%d: Falcon IDE interface\n", index); + hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif) { + u8 index = hwif->index; + u8 idx[4] = { index, 0xff, 0xff, 0xff }; + + ide_init_port_data(hwif, index); + ide_init_port_hw(hwif, &hw); + + ide_device_add(idx, NULL); + } } + + return 0; } + +module_init(falconide_init); diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c index 53331ee1e95..fc29ce75aff 100644 --- a/drivers/ide/legacy/gayle.c +++ b/drivers/ide/legacy/gayle.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver + * Amiga Gayle IDE Driver * * Created 9 Jul 1997 by Geert Uytterhoeven * @@ -110,12 +110,13 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif) * Probe for a Gayle IDE interface (and optionally for an IDE doubler) */ -void __init gayle_init(void) +static int __init gayle_init(void) { int a4000, i; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; if (!MACH_IS_AMIGA) - return; + return -ENODEV; if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) goto found; @@ -125,15 +126,21 @@ void __init gayle_init(void) NULL)) goto found; #endif - return; + return -ENODEV; found: + printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", + a4000 ? 4000 : 1200, +#ifdef CONFIG_BLK_DEV_IDEDOUBLER + ide_doubler ? ", IDE doubler" : +#endif + ""); + for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { unsigned long base, ctrlport, irqport; ide_ack_intr_t *ack_intr; hw_regs_t hw; ide_hwif_t *hwif; - int index; unsigned long phys_base, res_start, res_n; if (a4000) { @@ -165,21 +172,23 @@ found: // &gayle_iops, IRQ_AMIGA_PORTS); - index = ide_register_hw(&hw, NULL, 1, &hwif); - if (index != -1) { + hwif = ide_find_port(base); + if (hwif) { + u8 index = hwif->index; + + ide_init_port_data(hwif, index); + ide_init_port_hw(hwif, &hw); + hwif->mmio = 1; - switch (i) { - case 0: - printk("ide%d: Gayle IDE interface (A%d style)\n", index, - a4000 ? 4000 : 1200); - break; -#ifdef CONFIG_BLK_DEV_IDEDOUBLER - case 1: - printk("ide%d: IDE doubler\n", index); - break; -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - } + + idx[i] = index; } else release_mem_region(res_start, res_n); } + + ide_device_add(idx, NULL); + + return 0; } + +module_init(gayle_init); diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index a4245d13f11..02d12c74764 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/legacy/ht6560b.c Version 0.07 Feb 1, 2000 - * * Copyright (C) 1995-2000 Linus Torvalds & author (see below) */ @@ -302,17 +300,36 @@ static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio) #endif } +static void __init ht6560b_port_init_devs(ide_hwif_t *hwif) +{ + /* Setting default configurations for drives. */ + int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT; + + if (hwif->channel) + t |= (HT_SECONDARY_IF << 8); + + hwif->drives[0].drive_data = t; + hwif->drives[1].drive_data = t; +} + int probe_ht6560b = 0; module_param_named(probe, probe_ht6560b, bool, 0); MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); -/* Can be called directly from ide.c. */ -int __init ht6560b_init(void) +static const struct ide_port_info ht6560b_port_info __initdata = { + .chipset = ide_ht6560b, + .host_flags = IDE_HFLAG_SERIALIZE | /* is this needed? */ + IDE_HFLAG_NO_DMA | + IDE_HFLAG_NO_AUTOTUNE | + IDE_HFLAG_ABUSE_PREFETCH, + .pio_mask = ATA_PIO5, +}; + +static int __init ht6560b_init(void) { ide_hwif_t *hwif, *mate; static u8 idx[4] = { 0, 1, 0xff, 0xff }; - int t; if (probe_ht6560b == 0) return -ENODEV; @@ -331,36 +348,16 @@ int __init ht6560b_init(void) goto release_region; } - hwif->chipset = ide_ht6560b; hwif->selectproc = &ht6560b_selectproc; - hwif->host_flags = IDE_HFLAG_ABUSE_PREFETCH; - hwif->pio_mask = ATA_PIO5; hwif->set_pio_mode = &ht6560b_set_pio_mode; - hwif->serialized = 1; /* is this needed? */ - hwif->mate = mate; - mate->chipset = ide_ht6560b; mate->selectproc = &ht6560b_selectproc; - mate->host_flags = IDE_HFLAG_ABUSE_PREFETCH; - mate->pio_mask = ATA_PIO5; mate->set_pio_mode = &ht6560b_set_pio_mode; - mate->serialized = 1; /* is this needed? */ - mate->mate = hwif; - mate->channel = 1; - /* - * Setting default configurations for drives - */ - t = (HT_CONFIG_DEFAULT << 8); - t |= HT_TIMING_DEFAULT; - hwif->drives[0].drive_data = t; - hwif->drives[1].drive_data = t; - - t |= (HT_SECONDARY_IF << 8); - mate->drives[0].drive_data = t; - mate->drives[1].drive_data = t; + hwif->port_init_devs = ht6560b_port_init_devs; + mate->port_init_devs = ht6560b_port_init_devs; - ide_device_add(idx); + ide_device_add(idx, &ht6560b_port_info); return 0; @@ -369,9 +366,7 @@ release_region: return -ENODEV; } -#ifdef MODULE module_init(ht6560b_init); -#endif MODULE_AUTHOR("See Local File"); MODULE_DESCRIPTION("HT-6560B EIDE-controller support"); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 03715c05866..15ccf6944ae 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -2,8 +2,6 @@ A driver for PCMCIA IDE/ATA disk cards - ide-cs.c 1.3 2002/10/26 05:45:31 - The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of @@ -147,13 +145,36 @@ static void ide_detach(struct pcmcia_device *link) static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) { + ide_hwif_t *hwif; hw_regs_t hw; + int i; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + memset(&hw, 0, sizeof(hw)); - ide_init_hwif_ports(&hw, io, ctl, NULL); + ide_std_init_ports(&hw, io, ctl); hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; - return ide_register_hw(&hw, &ide_undecoded_slave, 0, NULL); + + hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif == NULL) + return -1; + + i = hwif->index; + + if (hwif->present) + ide_unregister(i, 0, 0); + else if (!hwif->hold) + ide_init_port_data(hwif, i); + + ide_init_port_hw(hwif, &hw); + hwif->quirkproc = &ide_undecoded_slave; + + idx[0] = i; + + ide_device_add(idx, NULL); + + return hwif->present ? i : -1; } /*====================================================================== @@ -339,7 +360,7 @@ void ide_release(struct pcmcia_device *link) if (info->ndev) { /* FIXME: if this fails we need to queue the cleanup somehow -- need to investigate the required PCMCIA magic */ - ide_unregister(info->hd); + ide_unregister(info->hd, 0, 0); } info->ndev = 0; diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c index 7bb79f53dac..26c82ce602d 100644 --- a/drivers/ide/legacy/ide_platform.c +++ b/drivers/ide/legacy/ide_platform.c @@ -21,56 +21,39 @@ #include <linux/platform_device.h> #include <linux/io.h> -static struct { - void __iomem *plat_ide_mapbase; - void __iomem *plat_ide_alt_mapbase; - ide_hwif_t *hwif; - int index; -} hwif_prop; - -static ide_hwif_t *__devinit plat_ide_locate_hwif(void __iomem *base, - void __iomem *ctrl, struct pata_platform_info *pdata, int irq, - int mmio) +static void __devinit plat_ide_setup_ports(hw_regs_t *hw, + void __iomem *base, + void __iomem *ctrl, + struct pata_platform_info *pdata, + int irq) { unsigned long port = (unsigned long)base; - ide_hwif_t *hwif = ide_find_port(port); int i; - if (hwif == NULL) - goto out; - - hwif->io_ports[IDE_DATA_OFFSET] = port; + hw->io_ports[IDE_DATA_OFFSET] = port; port += (1 << pdata->ioport_shift); for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++, port += (1 << pdata->ioport_shift)) - hwif->io_ports[i] = port; - - hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; + hw->io_ports[i] = port; - hwif->irq = irq; + hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; - hwif->chipset = ide_generic; + hw->irq = irq; - if (mmio) { - hwif->mmio = 1; - default_hwif_mmiops(hwif); - } - - hwif_prop.hwif = hwif; - hwif_prop.index = hwif->index; -out: - return hwif; + hw->chipset = ide_generic; } static int __devinit plat_ide_probe(struct platform_device *pdev) { struct resource *res_base, *res_alt, *res_irq; + void __iomem *base, *alt_base; ide_hwif_t *hwif; struct pata_platform_info *pdata; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; int ret = 0; int mmio = 0; + hw_regs_t hw; pdata = pdev->dev.platform_data; @@ -95,30 +78,37 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) } if (mmio) { - hwif_prop.plat_ide_mapbase = devm_ioremap(&pdev->dev, + base = devm_ioremap(&pdev->dev, res_base->start, res_base->end - res_base->start + 1); - hwif_prop.plat_ide_alt_mapbase = devm_ioremap(&pdev->dev, + alt_base = devm_ioremap(&pdev->dev, res_alt->start, res_alt->end - res_alt->start + 1); } else { - hwif_prop.plat_ide_mapbase = devm_ioport_map(&pdev->dev, + base = devm_ioport_map(&pdev->dev, res_base->start, res_base->end - res_base->start + 1); - hwif_prop.plat_ide_alt_mapbase = devm_ioport_map(&pdev->dev, + alt_base = devm_ioport_map(&pdev->dev, res_alt->start, res_alt->end - res_alt->start + 1); } - hwif = plat_ide_locate_hwif(hwif_prop.plat_ide_mapbase, - hwif_prop.plat_ide_alt_mapbase, pdata, res_irq->start, mmio); - + hwif = ide_find_port((unsigned long)base); if (!hwif) { ret = -ENODEV; goto out; } - hwif->gendev.parent = &pdev->dev; - hwif->noprobe = 0; + + memset(&hw, 0, sizeof(hw)); + plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start); + hw.dev = &pdev->dev; + + ide_init_port_hw(hwif, &hw); + + if (mmio) { + hwif->mmio = 1; + default_hwif_mmiops(hwif); + } idx[0] = hwif->index; - ide_device_add(idx); + ide_device_add(idx, NULL); platform_set_drvdata(pdev, hwif); @@ -132,14 +122,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev) { ide_hwif_t *hwif = pdev->dev.driver_data; - if (hwif != hwif_prop.hwif) { - dev_printk(KERN_DEBUG, &pdev->dev, "%s: hwif value error", - pdev->name); - } else { - ide_unregister(hwif_prop.index); - hwif_prop.index = 0; - hwif_prop.hwif = NULL; - } + ide_unregister(hwif->index, 0, 0); return 0; } diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index e87cd2f1643..06df8df857a 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/legacy/macide.c -- Macintosh IDE Driver + * Macintosh IDE Driver * * Copyright (C) 1998 by Michael Schmitz * @@ -77,15 +77,17 @@ int macide_ack_intr(ide_hwif_t* hwif) return 0; } +static const char *mac_ide_name[] = + { "Quadra", "Powerbook", "Powerbook Baboon" }; + /* * Probe for a Macintosh IDE interface */ -void macide_init(void) +static int __init macide_init(void) { hw_regs_t hw; ide_hwif_t *hwif; - int index = -1; switch (macintosh_config->ide_type) { case MAC_IDE_QUADRA: @@ -93,48 +95,40 @@ void macide_init(void) 0, 0, macide_ack_intr, // quadra_ide_iops, IRQ_NUBUS_F); - index = ide_register_hw(&hw, NULL, 1, &hwif); break; case MAC_IDE_PB: ide_setup_ports(&hw, IDE_BASE, macide_offsets, 0, 0, macide_ack_intr, // macide_pb_iops, IRQ_NUBUS_C); - index = ide_register_hw(&hw, NULL, 1, &hwif); break; case MAC_IDE_BABOON: ide_setup_ports(&hw, BABOON_BASE, macide_offsets, 0, 0, NULL, // macide_baboon_iops, IRQ_BABOON_1); - index = ide_register_hw(&hw, NULL, 1, &hwif); - if (index == -1) break; - if (macintosh_config->ident == MAC_MODEL_PB190) { - - /* Fix breakage in ide-disk.c: drive capacity */ - /* is not initialized for drives without a */ - /* hardware ID, and we can't get that without */ - /* probing the drive which freezes a 190. */ - - ide_drive_t *drive = &ide_hwifs[index].drives[0]; - drive->capacity64 = drive->cyl*drive->head*drive->sect; - - } break; - default: - return; + return -ENODEV; } - if (index != -1) { + printk(KERN_INFO "ide: Macintosh %s IDE controller\n", + mac_ide_name[macintosh_config->ide_type - 1]); + + hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif) { + u8 index = hwif->index; + u8 idx[4] = { index, 0xff, 0xff, 0xff }; + + ide_init_port_data(hwif, index); + ide_init_port_hw(hwif, &hw); + hwif->mmio = 1; - if (macintosh_config->ide_type == MAC_IDE_QUADRA) - printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index); - else if (macintosh_config->ide_type == MAC_IDE_PB) - printk(KERN_INFO "ide%d: Macintosh Powerbook IDE interface\n", index); - else if (macintosh_config->ide_type == MAC_IDE_BABOON) - printk(KERN_INFO "ide%d: Macintosh Powerbook Baboon IDE interface\n", index); - else - printk(KERN_INFO "ide%d: Unknown Macintosh IDE interface\n", index); + + ide_device_add(idx, NULL); } + + return 0; } + +module_init(macide_init); diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index a73db1bd482..2f0b34d892a 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/legacy/q40ide.c -- Q40 I/O port IDE Driver + * Q40 I/O port IDE Driver * * (c) Richard Zidlicky * @@ -111,15 +111,17 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ * Probe for Q40 IDE interfaces */ -void q40ide_init(void) +static int __init q40ide_init(void) { int i; ide_hwif_t *hwif; - int index; const char *name; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; if (!MACH_IS_Q40) - return ; + return -ENODEV; + + printk(KERN_INFO "ide: Q40 IDE controller\n"); for (i = 0; i < Q40IDE_NUM_HWIFS; i++) { hw_regs_t hw; @@ -141,10 +143,20 @@ void q40ide_init(void) 0, NULL, // m68kide_iops, q40ide_default_irq(pcide_bases[i])); - index = ide_register_hw(&hw, NULL, 1, &hwif); - // **FIXME** - if (index != -1) + + hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif) { + ide_init_port_data(hwif, hwif->index); + ide_init_port_hw(hwif, &hw); hwif->mmio = 1; + + idx[i] = hwif->index; + } } + + ide_device_add(idx, NULL); + + return 0; } +module_init(q40ide_init); diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 912e73853fa..bba29df5f21 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/legacy/qd65xx.c Version 0.07 Sep 30, 2001 - * * Copyright (C) 1996-2001 Linus Torvalds & author (see below) */ @@ -307,18 +305,33 @@ static int __init qd_testreg(int port) * called to setup an ata channel : adjusts attributes & links for tuning */ -static void __init qd_setup(ide_hwif_t *hwif, int base, int config, - unsigned int data0, unsigned int data1) +static void __init qd_setup(ide_hwif_t *hwif, int base, int config) { - hwif->chipset = ide_qd65xx; - hwif->channel = hwif->index; hwif->select_data = base; hwif->config_data = config; - hwif->drives[0].drive_data = data0; - hwif->drives[1].drive_data = data1; - hwif->drives[0].io_32bit = - hwif->drives[1].io_32bit = 1; - hwif->pio_mask = ATA_PIO4; +} + +static void __init qd6500_port_init_devs(ide_hwif_t *hwif) +{ + u8 base = hwif->select_data, config = QD_CONFIG(hwif); + + hwif->drives[0].drive_data = QD6500_DEF_DATA; + hwif->drives[1].drive_data = QD6500_DEF_DATA; +} + +static void __init qd6580_port_init_devs(ide_hwif_t *hwif) +{ + u16 t1, t2; + u8 base = hwif->select_data, config = QD_CONFIG(hwif); + + if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) { + t1 = QD6580_DEF_DATA; + t2 = QD6580_DEF_DATA2; + } else + t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA; + + hwif->drives[0].drive_data = t1; + hwif->drives[1].drive_data = t2; } /* @@ -358,6 +371,14 @@ static void __exit qd_unsetup(ide_hwif_t *hwif) } */ +static const struct ide_port_info qd65xx_port_info __initdata = { + .chipset = ide_qd65xx, + .host_flags = IDE_HFLAG_IO_32BIT | + IDE_HFLAG_NO_DMA | + IDE_HFLAG_NO_AUTOTUNE, + .pio_mask = ATA_PIO4, +}; + /* * qd_probe: * @@ -395,13 +416,14 @@ static int __init qd_probe(int base) return 1; } - qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA); + qd_setup(hwif, base, config); + hwif->port_init_devs = qd6500_port_init_devs; hwif->set_pio_mode = &qd6500_set_pio_mode; - idx[0] = unit; + idx[unit] = unit; - ide_device_add(idx); + ide_device_add(idx, &qd65xx_port_info); return 1; } @@ -428,14 +450,15 @@ static int __init qd_probe(int base) hwif = &ide_hwifs[unit]; printk(KERN_INFO "%s: qd6580: single IDE board\n", hwif->name); - qd_setup(hwif, base, config | (control << 8), - QD6580_DEF_DATA, QD6580_DEF_DATA2); + qd_setup(hwif, base, config | (control << 8)); + + hwif->port_init_devs = qd6580_port_init_devs; hwif->set_pio_mode = &qd6580_set_pio_mode; - idx[0] = unit; + idx[unit] = unit; - ide_device_add(idx); + ide_device_add(idx, &qd65xx_port_info); outb(QD_DEF_CONTR, QD_CONTROL_PORT); @@ -449,20 +472,20 @@ static int __init qd_probe(int base) printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", hwif->name, mate->name); - qd_setup(hwif, base, config | (control << 8), - QD6580_DEF_DATA, QD6580_DEF_DATA); + qd_setup(hwif, base, config | (control << 8)); + hwif->port_init_devs = qd6580_port_init_devs; hwif->set_pio_mode = &qd6580_set_pio_mode; - qd_setup(mate, base, config | (control << 8), - QD6580_DEF_DATA2, QD6580_DEF_DATA2); + qd_setup(mate, base, config | (control << 8)); + mate->port_init_devs = qd6580_port_init_devs; mate->set_pio_mode = &qd6580_set_pio_mode; idx[0] = 0; idx[1] = 1; - ide_device_add(idx); + ide_device_add(idx, &qd65xx_port_info); outb(QD_DEF_CONTR, QD_CONTROL_PORT); @@ -478,8 +501,7 @@ int probe_qd65xx = 0; module_param_named(probe, probe_qd65xx, bool, 0); MODULE_PARM_DESC(probe, "probe for QD65xx chipsets"); -/* Can be called directly from ide.c. */ -int __init qd65xx_init(void) +static int __init qd65xx_init(void) { if (probe_qd65xx == 0) return -ENODEV; @@ -492,9 +514,7 @@ int __init qd65xx_init(void) return 0; } -#ifdef MODULE module_init(qd65xx_init); -#endif MODULE_AUTHOR("Samuel Thibault"); MODULE_DESCRIPTION("support of qd65xx vlb ide chipset"); diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h index 633a42456ef..28dd50a15d5 100644 --- a/drivers/ide/legacy/qd65xx.h +++ b/drivers/ide/legacy/qd65xx.h @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/legacy/qd65xx.h - * * Copyright (c) 2000 Linus Torvalds & authors */ diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index 79577b91687..5696ba02600 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/legacy/umc8672.c Version 0.05 Jul 31, 1996 - * * Copyright (C) 1995-1996 Linus Torvalds & author (see below) */ @@ -122,9 +120,14 @@ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) spin_unlock_irqrestore(&ide_lock, flags); } +static const struct ide_port_info umc8672_port_info __initdata = { + .chipset = ide_umc8672, + .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE, + .pio_mask = ATA_PIO4, +}; + static int __init umc8672_probe(void) { - ide_hwif_t *hwif, *mate; unsigned long flags; static u8 idx[4] = { 0, 1, 0xff, 0xff }; @@ -145,21 +148,10 @@ static int __init umc8672_probe(void) umc_set_speeds (current_speeds); local_irq_restore(flags); - hwif = &ide_hwifs[0]; - mate = &ide_hwifs[1]; - - hwif->chipset = ide_umc8672; - hwif->pio_mask = ATA_PIO4; - hwif->set_pio_mode = &umc_set_pio_mode; - hwif->mate = mate; - - mate->chipset = ide_umc8672; - mate->pio_mask = ATA_PIO4; - mate->set_pio_mode = &umc_set_pio_mode; - mate->mate = hwif; - mate->channel = 1; + ide_hwifs[0].set_pio_mode = &umc_set_pio_mode; + ide_hwifs[1].set_pio_mode = &umc_set_pio_mode; - ide_device_add(idx); + ide_device_add(idx, &umc8672_port_info); return 0; } @@ -169,8 +161,7 @@ int probe_umc8672 = 0; module_param_named(probe, probe_umc8672, bool, 0); MODULE_PARM_DESC(probe, "probe for UMC8672 chipset"); -/* Can be called directly from ide.c. */ -int __init umc8672_init(void) +static int __init umc8672_init(void) { if (probe_umc8672 == 0) goto out; @@ -181,9 +172,7 @@ out: return -ENODEV;; } -#ifdef MODULE module_init(umc8672_init); -#endif MODULE_AUTHOR("Wolfram Podien"); MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset"); diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index a4ce3ba15d6..0f4bf5d7283 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/mips/au1xxx-ide.c version 01.30.00 Aug. 02 2005 - * * BRIEF MODULE DESCRIPTION * AMD Alchemy Au1xxx IDE interface routines over the Static Bus * @@ -50,7 +48,6 @@ #include <asm/mach-au1x00/au1xxx_ide.h> #define DRV_NAME "au1200-ide" -#define DRV_VERSION "1.0" #define DRV_AUTHOR "Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>" /* enable the burstmode in the dbdma */ @@ -198,8 +195,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed) break; #endif - default: - return; } au_writel(mem_sttime,MEM_STTIME2); @@ -211,24 +206,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed) */ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - -static int auide_build_sglist(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = drive->hwif; - _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; - struct scatterlist *sg = hwif->sg_table; - - ide_map_sg(drive, rq); - - if (rq_data_dir(rq) == READ) - hwif->sg_dma_direction = DMA_FROM_DEVICE; - else - hwif->sg_dma_direction = DMA_TO_DEVICE; - - return dma_map_sg(ahwif->dev, sg, hwif->sg_nents, - hwif->sg_dma_direction); -} - static int auide_build_dmatable(ide_drive_t *drive) { int i, iswrite, count = 0; @@ -243,8 +220,7 @@ static int auide_build_dmatable(ide_drive_t *drive) /* Save for interrupt context */ ahwif->drive = drive; - /* Build sglist */ - hwif->sg_nents = i = auide_build_sglist(drive, rq); + hwif->sg_nents = i = ide_build_sglist(drive, rq); if (!i) return 0; @@ -302,10 +278,7 @@ static int auide_build_dmatable(ide_drive_t *drive) return 1; use_pio_instead: - dma_unmap_sg(ahwif->dev, - hwif->sg_table, - hwif->sg_nents, - hwif->sg_dma_direction); + ide_destroy_dmatable(drive); return 0; /* revert to PIO for this request */ } @@ -313,11 +286,9 @@ static int auide_build_dmatable(ide_drive_t *drive) static int auide_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; if (hwif->sg_nents) { - dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents, - hwif->sg_dma_direction); + ide_destroy_dmatable(drive); hwif->sg_nents = 0; } @@ -397,26 +368,10 @@ static int auide_dma_test_irq(ide_drive_t *drive) return 0; } -static void auide_dma_host_on(ide_drive_t *drive) +static void auide_dma_host_set(ide_drive_t *drive, int on) { } -static int auide_dma_on(ide_drive_t *drive) -{ - drive->using_dma = 1; - - return 0; -} - -static void auide_dma_host_off(ide_drive_t *drive) -{ -} - -static void auide_dma_off_quietly(ide_drive_t *drive) -{ - drive->using_dma = 0; -} - static void auide_dma_lost_irq(ide_drive_t *drive) { printk(KERN_ERR "%s: IRQ lost\n", drive->name); @@ -522,7 +477,7 @@ static int auide_ddma_init(_auide_hwif *auide) { auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, NUM_DESCRIPTORS); - hwif->dmatable_cpu = dma_alloc_coherent(auide->dev, + hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev, PRD_ENTRIES * PRD_BYTES, /* 1 Page */ &hwif->dmatable_dma, GFP_KERNEL); @@ -593,6 +548,17 @@ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) *ata_regs = ahwif->regbase + (14 << AU1XXX_ATA_REG_OFFSET); } +static const struct ide_port_info au1xxx_port_info = { + .host_flags = IDE_HFLAG_POST_SET_MODE | + IDE_HFLAG_NO_DMA | /* no SFF-style DMA */ + IDE_HFLAG_NO_IO_32BIT | + IDE_HFLAG_UNMASK_IRQS, + .pio_mask = ATA_PIO4, +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + .mwdma_mask = ATA_MWDMA2, +#endif +}; + static int au_ide_probe(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -610,9 +576,6 @@ static int au_ide_probe(struct device *dev) #endif memset(&auide_hwif, 0, sizeof(_auide_hwif)); - auide_hwif.dev = 0; - - ahwif->dev = dev; ahwif->irq = platform_get_irq(pdev, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -643,28 +606,16 @@ static int au_ide_probe(struct device *dev) /* FIXME: This might possibly break PCMCIA IDE devices */ hwif = &ide_hwifs[pdev->id]; - hwif->irq = ahwif->irq; - hwif->chipset = ide_au1xxx; memset(&hw, 0, sizeof(hw)); auide_setup_ports(&hw, ahwif); - memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); + hw.irq = ahwif->irq; + hw.dev = dev; + hw.chipset = ide_au1xxx; - hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - hwif->mwdma_mask = 0x07; /* Multimode-2 DMA */ - hwif->swdma_mask = 0x00; -#else - hwif->mwdma_mask = 0x0; - hwif->swdma_mask = 0x0; -#endif - - hwif->pio_mask = ATA_PIO4; - hwif->host_flags = IDE_HFLAG_POST_SET_MODE; + ide_init_port_hw(hwif, &hw); - hwif->noprobe = 0; - hwif->drives[0].unmask = 1; - hwif->drives[1].unmask = 1; + hwif->dev = dev; /* hold should be on in all cases */ hwif->hold = 1; @@ -684,32 +635,21 @@ static int au_ide_probe(struct device *dev) hwif->set_dma_mode = &auide_set_dma_mode; #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - hwif->dma_off_quietly = &auide_dma_off_quietly; hwif->dma_timeout = &auide_dma_timeout; hwif->mdma_filter = &auide_mdma_filter; + hwif->dma_host_set = &auide_dma_host_set; hwif->dma_exec_cmd = &auide_dma_exec_cmd; hwif->dma_start = &auide_dma_start; hwif->ide_dma_end = &auide_dma_end; hwif->dma_setup = &auide_dma_setup; hwif->ide_dma_test_irq = &auide_dma_test_irq; - hwif->dma_host_off = &auide_dma_host_off; - hwif->dma_host_on = &auide_dma_host_on; hwif->dma_lost_irq = &auide_dma_lost_irq; - hwif->ide_dma_on = &auide_dma_on; -#else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ - hwif->channel = 0; - hwif->hold = 1; +#endif hwif->select_data = 0; /* no chipset-specific code */ hwif->config_data = 0; /* no chipset-specific code */ - hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */ - hwif->drives[1].autotune = 1; -#endif - hwif->drives[0].no_io_32bit = 1; - hwif->drives[1].no_io_32bit = 1; - auide_hwif.hwif = hwif; hwif->hwif_data = &auide_hwif; @@ -720,7 +660,7 @@ static int au_ide_probe(struct device *dev) idx[0] = hwif->index; - ide_device_add(idx); + ide_device_add(idx, &au1xxx_port_info); dev_set_drvdata(dev, hwif); @@ -737,7 +677,7 @@ static int au_ide_remove(struct device *dev) ide_hwif_t *hwif = dev_get_drvdata(dev); _auide_hwif *ahwif = &auide_hwif; - ide_unregister(hwif - ide_hwifs); + ide_unregister(hwif->index, 0, 0); iounmap((void *)ahwif->regbase); diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c index 521edd41b57..956259fc09b 100644 --- a/drivers/ide/mips/swarm.c +++ b/drivers/ide/mips/swarm.c @@ -117,6 +117,7 @@ static int __devinit swarm_ide_probe(struct device *dev) default_hwif_mmiops(hwif); /* Prevent resource map manipulation. */ hwif->mmio = 1; + hwif->chipset = ide_generic; hwif->noprobe = 0; for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) @@ -128,7 +129,7 @@ static int __devinit swarm_ide_probe(struct device *dev) idx[0] = hwif->index; - ide_device_add(idx); + ide_device_add(idx, NULL); dev_set_drvdata(dev, hwif); diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile index 95d1ea8f1f1..94803253e8a 100644 --- a/drivers/ide/pci/Makefile +++ b/drivers/ide/pci/Makefile @@ -36,4 +36,8 @@ obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o # Must appear at the end of the block obj-$(CONFIG_BLK_DEV_GENERIC) += generic.o +ifeq ($(CONFIG_BLK_DEV_CMD640), m) + obj-m += cmd640.o +endif + EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index 19ec421f7b9..cfb3265bc1a 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/aec62xx.c Version 0.27 Sep 16, 2007 - * * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com> * @@ -9,7 +7,6 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> @@ -90,7 +87,7 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr static void aec6210_set_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u16 d_conf = 0; u8 ultra = 0, ultra_conf = 0; u8 tmp0 = 0, tmp1 = 0, tmp2 = 0; @@ -116,7 +113,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed) static void aec6260_set_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 unit = (drive->select.b.unit & 0x01); u8 tmp1 = 0, tmp2 = 0; u8 ultra = 0, drive_conf = 0, ultra_conf = 0; @@ -168,29 +165,28 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch return dev->irq; } +static u8 __devinit atp86x_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01; + + pci_read_config_byte(dev, 0x49, &ata66); + + return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); hwif->set_pio_mode = &aec_set_pio_mode; if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) hwif->set_dma_mode = &aec6210_set_mode; - else + else { hwif->set_dma_mode = &aec6260_set_mode; - if (hwif->dma_base == 0) - return; - - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) - return; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) { - u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01; - - pci_read_config_byte(hwif->pci_dev, 0x49, &ata66); - - hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; + hwif->cable_detect = atp86x_cable_detect; } } @@ -202,6 +198,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_ATAPI_DMA | + IDE_HFLAG_NO_DSC | + IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -211,6 +209,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { .init_chipset = init_chipset_aec62xx, .init_hwif = init_hwif_aec62xx, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA | + IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -220,7 +219,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { .init_chipset = init_chipset_aec62xx, .init_hwif = init_hwif_aec62xx, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA, + .host_flags = IDE_HFLAG_NO_ATAPI_DMA | + IDE_HFLAG_ABUSE_SET_DMA_MODE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, @@ -228,7 +228,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { .name = "AEC6280", .init_chipset = init_chipset_aec62xx, .init_hwif = init_hwif_aec62xx, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAG_NO_ATAPI_DMA | + IDE_HFLAG_ABUSE_SET_DMA_MODE | + IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -237,7 +239,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { .init_chipset = init_chipset_aec62xx, .init_hwif = init_hwif_aec62xx, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAG_NO_ATAPI_DMA | + IDE_HFLAG_ABUSE_SET_DMA_MODE | + IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -260,6 +264,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi { struct ide_port_info d; u8 idx = id->driver_data; + int err; + + err = pci_enable_device(dev); + if (err) + return err; d = aec62xx_chipsets[idx]; @@ -272,7 +281,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi } } - return ide_setup_pci_device(dev, &d); + err = ide_setup_pci_device(dev, &d); + if (err) + pci_disable_device(dev); + + return err; } static const struct pci_device_id aec62xx_pci_tbl[] = { diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index a607dd31a64..b3b6f514ce2 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/alim15x3.c Version 0.29 Sep 16 2007 - * * Copyright (C) 1998-2000 Michel Aubry, Maintainer * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer @@ -33,7 +31,6 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> @@ -293,7 +290,7 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count) static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); int s_time, a_time, c_time; u8 s_clc, a_clc, r_clc; unsigned long flags; @@ -396,15 +393,12 @@ static u8 ali_udma_filter(ide_drive_t *drive) static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 speed1 = speed; u8 unit = (drive->select.b.unit & 0x01); u8 tmpbyte = 0x00; int m5229_udma = (hwif->channel) ? 0x57 : 0x56; - if (speed < XFER_PIO_0) - return; - if (speed == XFER_UDMA_6) speed1 = 0x47; @@ -603,6 +597,11 @@ static int ali_cable_override(struct pci_dev *pdev) pdev->subsystem_device == 0x10AF) return 1; + /* Mitac 8317 (Winbook-A) and relatives */ + if (pdev->subsystem_vendor == 0x1071 && + pdev->subsystem_device == 0x8317) + return 1; + /* Systems by DMI */ if (dmi_check_system(cable_dmi_table)) return 1; @@ -623,7 +622,7 @@ static int ali_cable_override(struct pci_dev *pdev) static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long flags; u8 cbl = ATA_CBL_PATA40, tmpbyte; @@ -666,13 +665,12 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->set_dma_mode = &ali_set_dma_mode; hwif->udma_filter = &ali_udma_filter; + hwif->cable_detect = ata66_ali15x3; + if (hwif->dma_base == 0) return; hwif->dma_setup = &ali15x3_dma_setup; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = ata66_ali15x3(hwif); } /** @@ -686,12 +684,13 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 ideic, inmir; s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; int irq = -1; - if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229) + if (dev->device == PCI_DEVICE_ID_AL_M5229) hwif->irq = hwif->channel ? 15 : 14; if (isa_dev) { @@ -743,7 +742,7 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) return; if (!hwif->channel) outb(inb(dmabase + 2) & 0x60, dmabase + 2); - ide_setup_dma(hwif, dmabase, 8); + ide_setup_dma(hwif, dmabase); } static const struct ide_port_info ali15x3_chipset __devinitdata = { @@ -773,7 +772,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev }; struct ide_port_info d = ali15x3_chipset; - u8 rev = dev->revision; + u8 rev = dev->revision, idx = id->driver_data; if (pci_dev_present(ati_rs100)) printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n"); @@ -796,6 +795,9 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev d.udma_mask = ATA_UDMA6; } + if (idx == 0) + d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX; + #if defined(CONFIG_SPARC64) d.init_hwif = init_hwif_common_ali15x3; #endif /* CONFIG_SPARC64 */ @@ -805,7 +807,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev static const struct pci_device_id alim15x3_pci_tbl[] = { { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 }, - { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 0 }, + { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl); diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 8d4125ec252..2ef890ce809 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -1,6 +1,4 @@ /* - * Version 2.24 - * * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04 * IDE driver for Linux. * @@ -19,90 +17,52 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/ide.h> -#include <asm/io.h> #include "ide-timing.h" -#define AMD_IDE_CONFIG (0x01 + amd_config->base) -#define AMD_CABLE_DETECT (0x02 + amd_config->base) -#define AMD_DRIVE_TIMING (0x08 + amd_config->base) -#define AMD_8BIT_TIMING (0x0e + amd_config->base) -#define AMD_ADDRESS_SETUP (0x0c + amd_config->base) -#define AMD_UDMA_TIMING (0x10 + amd_config->base) - -#define AMD_CHECK_SWDMA 0x08 -#define AMD_BAD_SWDMA 0x10 -#define AMD_BAD_FIFO 0x20 -#define AMD_CHECK_SERENADE 0x40 - -/* - * AMD SouthBridge chips. - */ - -static struct amd_ide_chip { - unsigned short id; - u8 base; - u8 udma_mask; - u8 flags; -} amd_ide_chips[] = { - { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, ATA_UDMA2, AMD_BAD_SWDMA }, - { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, ATA_UDMA4, AMD_CHECK_SWDMA }, - { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, ATA_UDMA5, AMD_BAD_FIFO }, - { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, ATA_UDMA5, }, - { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, ATA_UDMA6, AMD_CHECK_SERENADE }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, ATA_UDMA5, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, }, - { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, ATA_UDMA5, }, - { 0 } +enum { + AMD_IDE_CONFIG = 0x41, + AMD_CABLE_DETECT = 0x42, + AMD_DRIVE_TIMING = 0x48, + AMD_8BIT_TIMING = 0x4e, + AMD_ADDRESS_SETUP = 0x4c, + AMD_UDMA_TIMING = 0x50, }; -static struct amd_ide_chip *amd_config; -static const struct ide_port_info *amd_chipset; static unsigned int amd_80w; static unsigned int amd_clock; static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" }; static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 }; +static inline u8 amd_offset(struct pci_dev *dev) +{ + return (dev->vendor == PCI_VENDOR_ID_NVIDIA) ? 0x10 : 0; +} + /* * amd_set_speed() writes timing values to the chipset registers */ -static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing) +static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask, + struct ide_timing *timing) { - unsigned char t; + u8 t = 0, offset = amd_offset(dev); - pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t); + pci_read_config_byte(dev, AMD_ADDRESS_SETUP + offset, &t); t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); - pci_write_config_byte(dev, AMD_ADDRESS_SETUP, t); + pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t); - pci_write_config_byte(dev, AMD_8BIT_TIMING + (1 - (dn >> 1)), + pci_write_config_byte(dev, AMD_8BIT_TIMING + offset + (1 - (dn >> 1)), ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1)); - pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn), + pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn), ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1)); - switch (amd_config->udma_mask) { + switch (udma_mask) { case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break; case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break; @@ -110,7 +70,7 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi default: return; } - pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t); + pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t); } /* @@ -120,12 +80,15 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi static void amd_set_drive(ide_drive_t *drive, const u8 speed) { - ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1); + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + ide_drive_t *peer = hwif->drives + (~drive->dn & 1); struct ide_timing t, p; int T, UT; + u8 udma_mask = hwif->ultra_mask; T = 1000000000 / amd_clock; - UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2); + UT = (udma_mask == ATA_UDMA2) ? T : (T / 2); ide_timing_compute(drive, speed, &t, T, UT); @@ -137,7 +100,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed) if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1; if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15; - amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t); + amd_set_speed(dev, drive->dn, udma_mask, &t); } /* @@ -149,67 +112,68 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio) amd_set_drive(drive, XFER_PIO_0 + pio); } -/* - * The initialization callback. Here we determine the IDE chip type - * and initialize its drive independent registers. - */ +static void __devinit amd7409_cable_detect(struct pci_dev *dev, + const char *name) +{ + /* no host side cable detection */ + amd_80w = 0x03; +} -static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const char *name) +static void __devinit amd7411_cable_detect(struct pci_dev *dev, + const char *name) { - unsigned char t; - unsigned int u; int i; + u32 u = 0; + u8 t = 0, offset = amd_offset(dev); + + pci_read_config_byte(dev, AMD_CABLE_DETECT + offset, &t); + pci_read_config_dword(dev, AMD_UDMA_TIMING + offset, &u); + amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0); + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) { + printk(KERN_WARNING "%s: BIOS didn't set cable bits " + "correctly. Enabling workaround.\n", + name); + amd_80w |= (1 << (1 - (i >> 4))); + } +} /* - * Check for bad SWDMA. + * The initialization callback. Initialize drive independent registers. */ - if (amd_config->flags & AMD_CHECK_SWDMA) { - if (dev->revision <= 7) - amd_config->flags |= AMD_BAD_SWDMA; - } +static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, + const char *name) +{ + u8 t = 0, offset = amd_offset(dev); /* * Check 80-wire cable presence. */ - switch (amd_config->udma_mask) { - - case ATA_UDMA6: - case ATA_UDMA5: - pci_read_config_byte(dev, AMD_CABLE_DETECT, &t); - pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); - amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0); - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) { - printk(KERN_WARNING "%s: BIOS didn't set cable bits correctly. Enabling workaround.\n", - amd_chipset->name); - amd_80w |= (1 << (1 - (i >> 4))); - } - break; - - case ATA_UDMA4: - /* no host side cable detection */ - amd_80w = 0x03; - break; - } + if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->device == PCI_DEVICE_ID_AMD_COBRA_7401) + ; /* no UDMA > 2 */ + else if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->device == PCI_DEVICE_ID_AMD_VIPER_7409) + amd7409_cable_detect(dev, name); + else + amd7411_cable_detect(dev, name); /* * Take care of prefetch & postwrite. */ - pci_read_config_byte(dev, AMD_IDE_CONFIG, &t); - pci_write_config_byte(dev, AMD_IDE_CONFIG, - (amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0)); - -/* - * Take care of incorrectly wired Serenade mainboards. - */ - - if ((amd_config->flags & AMD_CHECK_SERENADE) && - dev->subsystem_vendor == PCI_VENDOR_ID_AMD && - dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE) - amd_config->udma_mask = ATA_UDMA5; + pci_read_config_byte(dev, AMD_IDE_CONFIG + offset, &t); + /* + * Check for broken FIFO support. + */ + if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411) + t &= 0x0f; + else + t |= 0xf0; + pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t); /* * Determine the system bus clock. @@ -225,53 +189,44 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch if (amd_clock < 20000 || amd_clock > 50000) { printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", - amd_chipset->name, amd_clock); + name, amd_clock); amd_clock = 33333; } -/* - * Print the boot message. - */ - - printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n", - amd_chipset->name, pci_name(dev), dev->revision, - amd_dma[fls(amd_config->udma_mask) - 1]); - return dev->irq; } +static u8 __devinit amd_cable_detect(ide_hwif_t *hwif) +{ + if ((amd_80w >> hwif->channel) & 1) + return ATA_CBL_PATA80; + else + return ATA_CBL_PATA40; +} + static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); + if (hwif->irq == 0) /* 0 is bogus but will do for now */ - hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel); + hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); hwif->set_pio_mode = &amd_set_pio_mode; hwif->set_dma_mode = &amd_set_drive; - if (!hwif->dma_base) - return; - - hwif->ultra_mask = amd_config->udma_mask; - if (amd_config->flags & AMD_BAD_SWDMA) - hwif->swdma_mask = 0x00; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) { - if ((amd_80w >> hwif->channel) & 1) - hwif->cbl = ATA_CBL_PATA80; - else - hwif->cbl = ATA_CBL_PATA40; - } + hwif->cable_detect = amd_cable_detect; } #define IDE_HFLAGS_AMD \ (IDE_HFLAG_PIO_NO_BLACKLIST | \ IDE_HFLAG_PIO_NO_DOWNGRADE | \ + IDE_HFLAG_ABUSE_SET_DMA_MODE | \ IDE_HFLAG_POST_SET_MODE | \ IDE_HFLAG_IO_32BIT | \ IDE_HFLAG_UNMASK_IRQS | \ IDE_HFLAG_BOOTABLE) -#define DECLARE_AMD_DEV(name_str) \ +#define DECLARE_AMD_DEV(name_str, swdma, udma) \ { \ .name = name_str, \ .init_chipset = init_chipset_amd74xx, \ @@ -279,11 +234,12 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \ .host_flags = IDE_HFLAGS_AMD, \ .pio_mask = ATA_PIO5, \ - .swdma_mask = ATA_SWDMA2, \ + .swdma_mask = swdma, \ .mwdma_mask = ATA_MWDMA2, \ + .udma_mask = udma, \ } -#define DECLARE_NV_DEV(name_str) \ +#define DECLARE_NV_DEV(name_str, udma) \ { \ .name = name_str, \ .init_chipset = init_chipset_amd74xx, \ @@ -293,45 +249,62 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) .pio_mask = ATA_PIO5, \ .swdma_mask = ATA_SWDMA2, \ .mwdma_mask = ATA_MWDMA2, \ + .udma_mask = udma, \ } static const struct ide_port_info amd74xx_chipsets[] __devinitdata = { - /* 0 */ DECLARE_AMD_DEV("AMD7401"), - /* 1 */ DECLARE_AMD_DEV("AMD7409"), - /* 2 */ DECLARE_AMD_DEV("AMD7411"), - /* 3 */ DECLARE_AMD_DEV("AMD7441"), - /* 4 */ DECLARE_AMD_DEV("AMD8111"), - - /* 5 */ DECLARE_NV_DEV("NFORCE"), - /* 6 */ DECLARE_NV_DEV("NFORCE2"), - /* 7 */ DECLARE_NV_DEV("NFORCE2-U400R"), - /* 8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA"), - /* 9 */ DECLARE_NV_DEV("NFORCE3-150"), - /* 10 */ DECLARE_NV_DEV("NFORCE3-250"), - /* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA"), - /* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"), - /* 13 */ DECLARE_NV_DEV("NFORCE-CK804"), - /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"), - /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"), - /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"), - /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"), - /* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"), - /* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"), - /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"), - /* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"), - /* 22 */ DECLARE_AMD_DEV("AMD5536"), + /* 0 */ DECLARE_AMD_DEV("AMD7401", 0x00, ATA_UDMA2), + /* 1 */ DECLARE_AMD_DEV("AMD7409", ATA_SWDMA2, ATA_UDMA4), + /* 2 */ DECLARE_AMD_DEV("AMD7411", ATA_SWDMA2, ATA_UDMA5), + /* 3 */ DECLARE_AMD_DEV("AMD7441", ATA_SWDMA2, ATA_UDMA5), + /* 4 */ DECLARE_AMD_DEV("AMD8111", ATA_SWDMA2, ATA_UDMA6), + + /* 5 */ DECLARE_NV_DEV("NFORCE", ATA_UDMA5), + /* 6 */ DECLARE_NV_DEV("NFORCE2", ATA_UDMA6), + /* 7 */ DECLARE_NV_DEV("NFORCE2-U400R", ATA_UDMA6), + /* 8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA", ATA_UDMA6), + /* 9 */ DECLARE_NV_DEV("NFORCE3-150", ATA_UDMA6), + /* 10 */ DECLARE_NV_DEV("NFORCE3-250", ATA_UDMA6), + /* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA", ATA_UDMA6), + /* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2", ATA_UDMA6), + /* 13 */ DECLARE_NV_DEV("NFORCE-CK804", ATA_UDMA6), + /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04", ATA_UDMA6), + /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51", ATA_UDMA6), + /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55", ATA_UDMA6), + /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61", ATA_UDMA6), + /* 18 */ DECLARE_NV_DEV("NFORCE-MCP65", ATA_UDMA6), + /* 19 */ DECLARE_NV_DEV("NFORCE-MCP67", ATA_UDMA6), + /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73", ATA_UDMA6), + /* 21 */ DECLARE_NV_DEV("NFORCE-MCP77", ATA_UDMA6), + + /* 22 */ DECLARE_AMD_DEV("AMD5536", ATA_SWDMA2, ATA_UDMA5), }; static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) { - amd_chipset = amd74xx_chipsets + id->driver_data; - amd_config = amd_ide_chips + id->driver_data; - if (dev->device != amd_config->id) { - printk(KERN_ERR "%s: assertion 0x%02x == 0x%02x failed !\n", - pci_name(dev), dev->device, amd_config->id); - return -ENODEV; + struct ide_port_info d; + u8 idx = id->driver_data; + + d = amd74xx_chipsets[idx]; + + /* + * Check for bad SWDMA and incorrectly wired Serenade mainboards. + */ + if (idx == 1) { + if (dev->revision <= 7) + d.swdma_mask = 0; + d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX; + } else if (idx == 4) { + if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD && + dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE) + d.udma_mask = ATA_UDMA5; } - return ide_setup_pci_device(dev, amd_chipset); + + printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n", + d.name, pci_name(dev), dev->revision, + amd_dma[fls(d.udma_mask) - 1]); + + return ide_setup_pci_device(dev, &d); } static const struct pci_device_id amd74xx_pci_tbl[] = { diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index ef8e0164ef7..7e037c880cb 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/atiixp.c Version 0.03 Aug 3 2007 - * * Copyright (C) 2003 ATI Inc. <hyu@ati.com> * Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz */ @@ -8,15 +6,11 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/ioport.h> #include <linux/pci.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/delay.h> #include <linux/init.h> -#include <asm/io.h> - #define ATIIXP_IDE_PIO_TIMING 0x40 #define ATIIXP_IDE_MDMA_TIMING 0x44 #define ATIIXP_IDE_PIO_CONTROL 0x48 @@ -43,47 +37,8 @@ static atiixp_ide_timing mdma_timing[] = { { 0x02, 0x00 }, }; -static int save_mdma_mode[4]; - static DEFINE_SPINLOCK(atiixp_lock); -static void atiixp_dma_host_on(ide_drive_t *drive) -{ - struct pci_dev *dev = drive->hwif->pci_dev; - unsigned long flags; - u16 tmp16; - - spin_lock_irqsave(&atiixp_lock, flags); - - pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); - if (save_mdma_mode[drive->dn]) - tmp16 &= ~(1 << drive->dn); - else - tmp16 |= (1 << drive->dn); - pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16); - - spin_unlock_irqrestore(&atiixp_lock, flags); - - ide_dma_host_on(drive); -} - -static void atiixp_dma_host_off(ide_drive_t *drive) -{ - struct pci_dev *dev = drive->hwif->pci_dev; - unsigned long flags; - u16 tmp16; - - spin_lock_irqsave(&atiixp_lock, flags); - - pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); - tmp16 &= ~(1 << drive->dn); - pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16); - - spin_unlock_irqrestore(&atiixp_lock, flags); - - ide_dma_host_off(drive); -} - /** * atiixp_set_pio_mode - set host controller for PIO mode * @drive: drive @@ -94,7 +49,7 @@ static void atiixp_dma_host_off(ide_drive_t *drive) static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio) { - struct pci_dev *dev = drive->hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); unsigned long flags; int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; u32 pio_timing_data; @@ -127,37 +82,54 @@ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio) static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed) { - struct pci_dev *dev = drive->hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); unsigned long flags; int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; u32 tmp32; u16 tmp16; - - if (speed < XFER_MW_DMA_0) - return; + u16 udma_ctl = 0; spin_lock_irqsave(&atiixp_lock, flags); - save_mdma_mode[drive->dn] = 0; + pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_ctl); + if (speed >= XFER_UDMA_0) { pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16); tmp16 &= ~(0x07 << (drive->dn * 4)); tmp16 |= ((speed & 0x07) << (drive->dn * 4)); pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16); - } else { - if ((speed >= XFER_MW_DMA_0) && (speed <= XFER_MW_DMA_2)) { - save_mdma_mode[drive->dn] = speed; - pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32); - tmp32 &= ~(0xff << timing_shift); - tmp32 |= (mdma_timing[speed & 0x03].recover_width << timing_shift) | - (mdma_timing[speed & 0x03].command_width << (timing_shift + 4)); - pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32); - } + + udma_ctl |= (1 << drive->dn); + } else if (speed >= XFER_MW_DMA_0) { + u8 i = speed & 0x03; + + pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32); + tmp32 &= ~(0xff << timing_shift); + tmp32 |= (mdma_timing[i].recover_width << timing_shift) | + (mdma_timing[i].command_width << (timing_shift + 4)); + pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32); + + udma_ctl &= ~(1 << drive->dn); } + pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, udma_ctl); + spin_unlock_irqrestore(&atiixp_lock, flags); } +static u8 __devinit atiixp_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *pdev = to_pci_dev(hwif->dev); + u8 udma_mode = 0, ch = hwif->channel; + + pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode); + + if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40) + return ATA_CBL_PATA80; + else + return ATA_CBL_PATA40; +} + /** * init_hwif_atiixp - fill in the hwif for the ATIIXP * @hwif: IDE interface @@ -168,25 +140,10 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed) static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) { - u8 udma_mode = 0; - u8 ch = hwif->channel; - struct pci_dev *pdev = hwif->pci_dev; - hwif->set_pio_mode = &atiixp_set_pio_mode; hwif->set_dma_mode = &atiixp_set_dma_mode; - if (!hwif->dma_base) - return; - - pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode); - - if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40) - hwif->cbl = ATA_CBL_PATA80; - else - hwif->cbl = ATA_CBL_PATA40; - - hwif->dma_host_on = &atiixp_dma_host_on; - hwif->dma_host_off = &atiixp_dma_host_off; + hwif->cable_detect = atiixp_cable_detect; } static const struct ide_port_info atiixp_pci_info[] __devinitdata = { diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 4aa48104e0c..bd24dad3cfc 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/cmd640.c Version 1.02 Sep 01, 1996 - * * Copyright (C) 1995-1996 Linus Torvalds & authors (see below) */ @@ -105,10 +103,6 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> @@ -705,10 +699,22 @@ static int pci_conf2(void) return 0; } +static const struct ide_port_info cmd640_port_info __initdata = { + .chipset = ide_cmd640, + .host_flags = IDE_HFLAG_SERIALIZE | + IDE_HFLAG_NO_DMA | + IDE_HFLAG_NO_AUTOTUNE | + IDE_HFLAG_ABUSE_PREFETCH | + IDE_HFLAG_ABUSE_FAST_DEVSEL, +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + .pio_mask = ATA_PIO5, +#endif +}; + /* - * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c + * Probe for a cmd640 chipset, and initialize it if found. */ -int __init ide_probe_for_cmd640x (void) +static int __init cmd640x_init(void) { #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED int second_port_toggled = 0; @@ -717,6 +723,7 @@ int __init ide_probe_for_cmd640x (void) const char *bus_type, *port2; unsigned int index; u8 b, cfr; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; if (cmd640_vlb && probe_for_cmd640_vlb()) { bus_type = "VLB"; @@ -761,14 +768,12 @@ int __init ide_probe_for_cmd640x (void) setup_device_ptrs (); printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n", cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr); - cmd_hwif0->chipset = ide_cmd640; #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif0->host_flags = IDE_HFLAG_ABUSE_PREFETCH | - IDE_HFLAG_ABUSE_FAST_DEVSEL; - cmd_hwif0->pio_mask = ATA_PIO5; cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode; #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + idx[0] = cmd_hwif0->index; + /* * Ensure compatibility by always using the slowest timings * for access to the drive's command register block, @@ -814,21 +819,14 @@ int __init ide_probe_for_cmd640x (void) * Initialize data for secondary cmd640 port, if enabled */ if (second_port_cmd640) { - cmd_hwif0->serialized = 1; - cmd_hwif1->serialized = 1; - cmd_hwif1->chipset = ide_cmd640; - cmd_hwif0->mate = cmd_hwif1; - cmd_hwif1->mate = cmd_hwif0; - cmd_hwif1->channel = 1; #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif1->host_flags = IDE_HFLAG_ABUSE_PREFETCH | - IDE_HFLAG_ABUSE_FAST_DEVSEL; - cmd_hwif1->pio_mask = ATA_PIO5; cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode; #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + + idx[1] = cmd_hwif1->index; } printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, - cmd_hwif0->serialized ? "" : "not ", port2); + second_port_cmd640 ? "" : "not ", port2); /* * Establish initial timings/prefetch for all drives. @@ -872,6 +870,13 @@ int __init ide_probe_for_cmd640x (void) #ifdef CMD640_DUMP_REGS cmd640_dump_regs(); #endif + + ide_device_add(idx, &cmd640_port_info); + return 1; } +module_param_named(probe_vlb, cmd640_vlb, bool, 0); +MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset"); + +module_init(cmd640x_init); diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index ea0143ef5fe..edabe6299ef 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007 - * * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. * Due to massive hardware bugs, UltraDMA is only supported * on the 646U2 and not on the 646U. @@ -15,15 +13,12 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> #include <asm/io.h> -#define DISPLAY_CMD64X_TIMINGS - #define CMD_DEBUG 0 #if CMD_DEBUG @@ -37,11 +32,6 @@ */ #define CFR 0x50 #define CFR_INTR_CH0 0x04 -#define CNTRL 0x51 -#define CNTRL_ENA_1ST 0x04 -#define CNTRL_ENA_2ND 0x08 -#define CNTRL_DIS_RA0 0x40 -#define CNTRL_DIS_RA1 0x80 #define CMDTIM 0x52 #define ARTTIM0 0x53 @@ -60,108 +50,13 @@ #define MRDMODE 0x71 #define MRDMODE_INTR_CH0 0x04 #define MRDMODE_INTR_CH1 0x08 -#define MRDMODE_BLK_CH0 0x10 -#define MRDMODE_BLK_CH1 0x20 -#define BMIDESR0 0x72 #define UDIDETCR0 0x73 #define DTPR0 0x74 #define BMIDECR1 0x78 #define BMIDECSR 0x79 -#define BMIDESR1 0x7A #define UDIDETCR1 0x7B #define DTPR1 0x7C -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static u8 cmd64x_proc = 0; - -#define CMD_MAX_DEVS 5 - -static struct pci_dev *cmd_devs[CMD_MAX_DEVS]; -static int n_cmd_devs; - -static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index) -{ - char *p = buf; - u8 reg72 = 0, reg73 = 0; /* primary */ - u8 reg7a = 0, reg7b = 0; /* secondary */ - u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0; /* extra */ - - p += sprintf(p, "\nController: %d\n", index); - p += sprintf(p, "PCI-%x Chipset.\n", dev->device); - - (void) pci_read_config_byte(dev, CFR, ®50); - (void) pci_read_config_byte(dev, CNTRL, ®51); - (void) pci_read_config_byte(dev, ARTTIM23, ®57); - (void) pci_read_config_byte(dev, MRDMODE, ®71); - (void) pci_read_config_byte(dev, BMIDESR0, ®72); - (void) pci_read_config_byte(dev, UDIDETCR0, ®73); - (void) pci_read_config_byte(dev, BMIDESR1, ®7a); - (void) pci_read_config_byte(dev, UDIDETCR1, ®7b); - - /* PCI0643/6 originally didn't have the primary channel enable bit */ - if ((dev->device == PCI_DEVICE_ID_CMD_643) || - (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 3)) - reg51 |= CNTRL_ENA_1ST; - - p += sprintf(p, "---------------- Primary Channel " - "---------------- Secondary Channel ------------\n"); - p += sprintf(p, " %s %s\n", - (reg51 & CNTRL_ENA_1ST) ? "enabled " : "disabled", - (reg51 & CNTRL_ENA_2ND) ? "enabled " : "disabled"); - p += sprintf(p, "---------------- drive0 --------- drive1 " - "-------- drive0 --------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s" - " %s %s\n", - (reg72 & 0x20) ? "yes" : "no ", (reg72 & 0x40) ? "yes" : "no ", - (reg7a & 0x20) ? "yes" : "no ", (reg7a & 0x40) ? "yes" : "no "); - p += sprintf(p, "UltraDMA mode: %s (%c) %s (%c)", - ( reg73 & 0x01) ? " on" : "off", - ((reg73 & 0x30) == 0x30) ? ((reg73 & 0x04) ? '3' : '0') : - ((reg73 & 0x30) == 0x20) ? ((reg73 & 0x04) ? '3' : '1') : - ((reg73 & 0x30) == 0x10) ? ((reg73 & 0x04) ? '4' : '2') : - ((reg73 & 0x30) == 0x00) ? ((reg73 & 0x04) ? '5' : '2') : '?', - ( reg73 & 0x02) ? " on" : "off", - ((reg73 & 0xC0) == 0xC0) ? ((reg73 & 0x08) ? '3' : '0') : - ((reg73 & 0xC0) == 0x80) ? ((reg73 & 0x08) ? '3' : '1') : - ((reg73 & 0xC0) == 0x40) ? ((reg73 & 0x08) ? '4' : '2') : - ((reg73 & 0xC0) == 0x00) ? ((reg73 & 0x08) ? '5' : '2') : '?'); - p += sprintf(p, " %s (%c) %s (%c)\n", - ( reg7b & 0x01) ? " on" : "off", - ((reg7b & 0x30) == 0x30) ? ((reg7b & 0x04) ? '3' : '0') : - ((reg7b & 0x30) == 0x20) ? ((reg7b & 0x04) ? '3' : '1') : - ((reg7b & 0x30) == 0x10) ? ((reg7b & 0x04) ? '4' : '2') : - ((reg7b & 0x30) == 0x00) ? ((reg7b & 0x04) ? '5' : '2') : '?', - ( reg7b & 0x02) ? " on" : "off", - ((reg7b & 0xC0) == 0xC0) ? ((reg7b & 0x08) ? '3' : '0') : - ((reg7b & 0xC0) == 0x80) ? ((reg7b & 0x08) ? '3' : '1') : - ((reg7b & 0xC0) == 0x40) ? ((reg7b & 0x08) ? '4' : '2') : - ((reg7b & 0xC0) == 0x00) ? ((reg7b & 0x08) ? '5' : '2') : '?'); - p += sprintf(p, "Interrupt: %s, %s %s, %s\n", - (reg71 & MRDMODE_BLK_CH0 ) ? "blocked" : "enabled", - (reg50 & CFR_INTR_CH0 ) ? "pending" : "clear ", - (reg71 & MRDMODE_BLK_CH1 ) ? "blocked" : "enabled", - (reg57 & ARTTIM23_INTR_CH1) ? "pending" : "clear "); - - return (char *)p; -} - -static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i; - - for (i = 0; i < n_cmd_devs; i++) { - struct pci_dev *dev = cmd_devs[i]; - p = print_cmd64x_get_info(p, dev, i); - } - return p-buffer; /* => must be less than 4k! */ -} - -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ - static u8 quantize_timing(int timing, int quant) { return (timing + quant - 1) / quant; @@ -173,7 +68,7 @@ static u8 quantize_timing(int timing, int quant) */ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time) { - struct pci_dev *dev = HWIF(drive)->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); int clock_time = 1000 / system_bus_clock(); u8 cycle_count, active_count, recovery_count, drwtim; static const u8 recovery_values[] = @@ -220,7 +115,7 @@ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned int cycle_time; u8 setup_count, arttim = 0; @@ -285,7 +180,7 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio) static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 unit = drive->dn & 0x01; u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0; @@ -322,8 +217,6 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) case XFER_MW_DMA_0: program_cycle_times(drive, 480, 215); break; - default: - return; } if (speed >= XFER_SW_DMA_0) @@ -333,13 +226,15 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) static int cmd648_ide_dma_end (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + unsigned long base = hwif->dma_base - (hwif->channel * 8); int err = __ide_dma_end(drive); u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; - u8 mrdmode = inb(hwif->dma_master + 0x01); + u8 mrdmode = inb(base + 1); /* clear the interrupt bit */ - outb(mrdmode | irq_mask, hwif->dma_master + 0x01); + outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask, + base + 1); return err; } @@ -347,7 +242,7 @@ static int cmd648_ide_dma_end (ide_drive_t *drive) static int cmd64x_ide_dma_end (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); int irq_reg = hwif->channel ? ARTTIM23 : CFR; u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; @@ -364,10 +259,11 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive) static int cmd648_ide_dma_test_irq (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + unsigned long base = hwif->dma_base - (hwif->channel * 8); u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; u8 dma_stat = inb(hwif->dma_status); - u8 mrdmode = inb(hwif->dma_master + 0x01); + u8 mrdmode = inb(base + 1); #ifdef DEBUG printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n", @@ -386,7 +282,7 @@ static int cmd648_ide_dma_test_irq (ide_drive_t *drive) static int cmd64x_ide_dma_test_irq (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); int irq_reg = hwif->channel ? ARTTIM23 : CFR; u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; @@ -471,22 +367,12 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha mrdmode &= ~0x30; (void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02)); -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) - - cmd_devs[n_cmd_devs++] = dev; - - if (!cmd64x_proc) { - cmd64x_proc = 1; - ide_pci_create_host_proc("cmd64x", cmd64x_get_info); - } -#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_IDE_PROC_FS */ - return 0; } static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01; switch (dev->device) { @@ -501,11 +387,13 @@ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif) static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); hwif->set_pio_mode = &cmd64x_set_pio_mode; hwif->set_dma_mode = &cmd64x_set_dma_mode; + hwif->cable_detect = ata66_cmd64x; + if (!hwif->dma_base) return; @@ -524,9 +412,6 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) if (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5) hwif->ultra_mask = 0x00; - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = ata66_cmd64x(hwif); - switch (dev->device) { case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_649: @@ -554,7 +439,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | + IDE_HFLAG_ABUSE_PREFETCH | + IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = 0x00, /* no udma */ @@ -563,6 +450,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, + .chipset = ide_cmd646, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, @@ -572,7 +460,6 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, - .chipset = ide_cmd646, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 0466462fd21..0be1a824102 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -35,22 +35,12 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> - -#include <linux/interrupt.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/ide.h> #include <linux/dma-mapping.h> -#include <asm/io.h> -#include <asm/irq.h> - struct pio_clocks { int address; @@ -69,9 +59,8 @@ static struct pio_clocks cs5520_pio_clocks[]={ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *pdev = hwif->pci_dev; + struct pci_dev *pdev = to_pci_dev(hwif->dev); int controller = drive->dn > 1 ? 1 : 0; - u8 reg; /* FIXME: if DMA = 1 do we need to set the DMA bit here ? */ @@ -91,11 +80,6 @@ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio) pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1), (cs5520_pio_clocks[pio].recovery << 4) | (cs5520_pio_clocks[pio].assert)); - - /* Set the DMA enable/disable flag */ - reg = inb(hwif->dma_base + 0x02 + 8*controller); - reg |= 1<<((drive->dn&1)+5); - outb(reg, hwif->dma_base + 0x02 + 8*controller); } static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed) @@ -109,13 +93,14 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed) * We wrap the DMA activate to set the vdma flag. This is needed * so that the IDE DMA layer issues PIO not DMA commands over the * DMA channel + * + * ATAPI is harder so disable it for now using IDE_HFLAG_NO_ATAPI_DMA */ - -static int cs5520_dma_on(ide_drive_t *drive) + +static void cs5520_dma_host_set(ide_drive_t *drive, int on) { - /* ATAPI is harder so leave it for now */ - drive->vdma = 1; - return 0; + drive->vdma = on; + ide_dma_host_set(drive, on); } static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) @@ -126,7 +111,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) if (hwif->dma_base == 0) return; - hwif->ide_dma_on = &cs5520_dma_on; + hwif->dma_host_set = &cs5520_dma_host_set; } #define DECLARE_CS_DEV(name_str) \ @@ -137,6 +122,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) IDE_HFLAG_CS5520 | \ IDE_HFLAG_VDMA | \ IDE_HFLAG_NO_ATAPI_DMA | \ + IDE_HFLAG_ABUSE_SET_DMA_MODE |\ IDE_HFLAG_BOOTABLE, \ .pio_mask = ATA_PIO4, \ } @@ -160,8 +146,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ide_setup_pci_noise(dev, d); /* We must not grab the entire device, it has 'ISA' space in its - BARS too and we will freak out other bits of the kernel */ - if (pci_enable_device_bars(dev, 1<<2)) { + * BARS too and we will freak out other bits of the kernel + * + * pci_enable_device_bars() is going away. I replaced it with + * IO only enable for now but I'll need confirmation this is + * allright for that device. If not, it will need some kind of + * quirk. --BenH. + */ + if (pci_enable_device_io(dev)) { printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name); return -ENODEV; } @@ -178,7 +170,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ide_pci_setup_ports(dev, d, 14, &idx[0]); - ide_device_add(idx); + ide_device_add(idx, d); return 0; } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index 599408952bd..941a1344820 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/cs5530.c Version 0.77 Sep 24 2007 - * * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2000 Mark Lord <mlord@pobox.com> * Copyright (C) 2007 Bartlomiej Zolnierkiewicz @@ -17,18 +15,12 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> -#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/ide.h> + #include <asm/io.h> -#include <asm/irq.h> /* * Here are the standard PIO mode 0-4 timings for each "format". @@ -116,9 +108,6 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) case XFER_MW_DMA_0: timings = 0x00077771; break; case XFER_MW_DMA_1: timings = 0x00012121; break; case XFER_MW_DMA_2: timings = 0x00002020; break; - default: - BUG(); - break; } basereg = CS5530_BASEREG(drive->hwif); reg = inl(basereg + 4); /* get drive0 config register */ diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c index 9094916e378..d7b5ea992e9 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/cs5535.c - * * Copyright (C) 2004-2005 Advanced Micro Devices, Inc. * Copyright (C) 2007 Bartlomiej Zolnierkiewicz * @@ -49,7 +47,7 @@ #define ATAC_BM0_PRD 0x04 #define CS5535_CABLE_DETECT 0x48 -/* Format I PIO settings. We seperate out cmd and data for safer timings */ +/* Format I PIO settings. We separate out cmd and data for safer timings */ static unsigned int cs5535_pio_cmd_timings[5] = { 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 }; @@ -157,8 +155,9 @@ static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio) cs5535_set_speed(drive, XFER_PIO_0 + pio); } -static u8 __devinit cs5535_cable_detect(struct pci_dev *dev) +static u8 __devinit cs5535_cable_detect(ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 bit; /* if a 80 wire cable was detected */ @@ -180,17 +179,14 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif) hwif->set_pio_mode = &cs5535_set_pio_mode; hwif->set_dma_mode = &cs5535_set_dma_mode; - if (hwif->dma_base == 0) - return; - - hwif->cbl = cs5535_cable_detect(hwif->pci_dev); + hwif->cable_detect = cs5535_cable_detect; } static const struct ide_port_info cs5535_chipset __devinitdata = { .name = "CS5535", .init_hwif = init_hwif_cs5535, .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_BOOTABLE, + IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index 1cd4e9cb052..724cbacf4e5 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/cy82c693.c Version 0.42 Oct 23, 2007 - * * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator * @@ -47,7 +45,6 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/ide.h> #include <linux/init.h> @@ -176,17 +173,12 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk) * set DMA mode a specific channel for CY82C693 */ -static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) +static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode) { - u8 index = 0, data = 0; + ide_hwif_t *hwif = drive->hwif; + u8 single = (mode & 0x10) >> 4, index = 0, data = 0; - if (mode>2) /* make sure we set a valid mode */ - mode = 2; - - if (mode > drive->id->tDMA) /* to be absolutly sure we have a valid mode */ - mode = drive->id->tDMA; - - index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1; + index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0; #if CY82C693_DEBUG_LOGS /* for debug let's show the previous values */ @@ -199,7 +191,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) (data&0x3), ((data>>2)&1)); #endif /* CY82C693_DEBUG_LOGS */ - data = (u8)mode|(u8)(single<<2); + data = (mode & 3) | (single << 2); outb(index, CY82_INDEX_PORT); outb(data, CY82_DATA_PORT); @@ -207,7 +199,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) #if CY82C693_DEBUG_INFO printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, - mode, single); + mode & 3, single); #endif /* CY82C693_DEBUG_INFO */ /* @@ -230,43 +222,10 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) #endif /* CY82C693_DEBUG_INFO */ } -/* - * used to set DMA mode for CY82C693 (single and multi modes) - */ -static int cy82c693_ide_dma_on (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "dma_on: %s\n", drive->name); -#endif /* CY82C693_DEBUG_INFO */ - - if (id != NULL) { - /* Enable DMA on any drive that has DMA - * (multi or single) enabled - */ - if (id->field_valid & 2) { /* regular DMA */ - int mmode, smode; - - mmode = id->dma_mword & (id->dma_mword >> 8); - smode = id->dma_1word & (id->dma_1word >> 8); - - if (mmode != 0) { - /* enable multi */ - cy82c693_dma_enable(drive, (mmode >> 1), 0); - } else if (smode != 0) { - /* enable single */ - cy82c693_dma_enable(drive, (smode >> 1), 1); - } - } - } - return __ide_dma_on(drive); -} - static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); pio_clocks_t pclk; unsigned int addrCtrl; @@ -429,18 +388,15 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif) { hwif->set_pio_mode = &cy82c693_set_pio_mode; - - if (hwif->dma_base == 0) - return; - - hwif->ide_dma_on = &cy82c693_ide_dma_on; + hwif->set_dma_mode = &cy82c693_set_dma_mode; } static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) { static ide_hwif_t *primary; + struct pci_dev *dev = to_pci_dev(hwif->dev); - if (PCI_FUNC(hwif->pci_dev->devfn) == 1) + if (PCI_FUNC(dev->devfn) == 1) primary = hwif; else { hwif->mate = primary; @@ -454,11 +410,11 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = { .init_iops = init_iops_cy82c693, .init_hwif = init_hwif_cy82c693, .chipset = ide_cy82c693, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_TRUST_BIOS_FOR_DMA | + .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO4, - .swdma_mask = ATA_SWDMA2_ONLY, - .mwdma_mask = ATA_MWDMA2_ONLY, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, }; static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id) diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c index 83829081640..3f9cd64c26a 100644 --- a/drivers/ide/pci/delkin_cb.c +++ b/drivers/ide/pci/delkin_cb.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/delkin_cb.c - * * Created 20 Oct 2004 by Mark Lord * * Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter @@ -18,15 +16,14 @@ * License. See the file COPYING in the main directory of this archive for * more details. */ -#include <linux/autoconf.h> + #include <linux/types.h> #include <linux/module.h> -#include <linux/mm.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> #include <linux/pci.h> + #include <asm/io.h> /* @@ -54,6 +51,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) ide_hwif_t *hwif = NULL; ide_drive_t *drive; int i, rc; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; rc = pci_enable_device(dev); if (rc) { @@ -80,20 +78,40 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) hw.irq = dev->irq; hw.chipset = ide_pci; /* this enables IRQ sharing */ - rc = ide_register_hw(&hw, &ide_undecoded_slave, 0, &hwif); - if (rc < 0) { - printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); - pci_disable_device(dev); - return -ENODEV; - } + hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); + if (hwif == NULL) + goto out_disable; + + i = hwif->index; + + if (hwif->present) + ide_unregister(i, 0, 0); + else if (!hwif->hold) + ide_init_port_data(hwif, i); + + ide_init_port_hw(hwif, &hw); + hwif->quirkproc = &ide_undecoded_slave; + + idx[0] = i; + + ide_device_add(idx, NULL); + + if (!hwif->present) + goto out_disable; + pci_set_drvdata(dev, hwif); - hwif->pci_dev = dev; + hwif->dev = &dev->dev; drive = &hwif->drives[0]; if (drive->present) { drive->io_32bit = 1; drive->unmask = 1; } return 0; + +out_disable: + printk(KERN_ERR "delkin_cb: no IDE devices found\n"); + pci_disable_device(dev); + return -ENODEV; } static void @@ -102,7 +120,8 @@ delkin_cb_remove (struct pci_dev *dev) ide_hwif_t *hwif = pci_get_drvdata(dev); if (hwif) - ide_unregister(hwif->index); + ide_unregister(hwif->index, 0, 0); + pci_disable_device(dev); } diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 06885697ed7..9262a9174b4 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/generic.c Version 0.11 December 30, 2002 - * * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Portions (C) Copyright 2002 Red Hat Inc <alan@redhat.com> * @@ -24,18 +22,11 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/pci.h> #include <linux/ide.h> #include <linux/init.h> -#include <asm/io.h> - static int ide_generic_all; /* Set to claim all devices */ /* @@ -104,7 +95,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = { { /* 14 */ .name = "Revolution", - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | + .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | + IDE_HFLAG_TRUST_BIOS_FOR_DMA | IDE_HFLAG_OFF_BOARD, .swdma_mask = ATA_SWDMA2, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index ae6307fae4f..9f01da46b01 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -1,7 +1,6 @@ /* - * linux/drivers/ide/pci/hpt34x.c Version 0.40 Sept 10, 2002 - * * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> + * * May be copied or modified under the terms of the GNU General Public License * * @@ -27,25 +26,18 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> #include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/ide.h> -#include <asm/io.h> -#include <asm/irq.h> - #define HPT343_DEBUG_DRIVE_INFO 0 static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed) { - struct pci_dev *dev = HWIF(drive)->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0; u8 hi_speed, lo_speed; @@ -129,14 +121,19 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif) hwif->set_dma_mode = &hpt34x_set_mode; } +#define IDE_HFLAGS_HPT34X \ + (IDE_HFLAG_NO_ATAPI_DMA | \ + IDE_HFLAG_NO_DSC | \ + IDE_HFLAG_ABUSE_SET_DMA_MODE | \ + IDE_HFLAG_NO_AUTODMA) + static const struct ide_port_info hpt34x_chipsets[] __devinitdata = { { /* 0 */ .name = "HPT343", .init_chipset = init_chipset_hpt34x, .init_hwif = init_hwif_hpt34x, .extra = 16, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | - IDE_HFLAG_NO_AUTODMA, + .host_flags = IDE_HFLAGS_HPT34X, .pio_mask = ATA_PIO5, }, { /* 1 */ @@ -144,9 +141,7 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = { .init_chipset = init_chipset_hpt34x, .init_hwif = init_hwif_hpt34x, .extra = 16, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | - IDE_HFLAG_NO_AUTODMA | - IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO5, #ifdef CONFIG_HPT34X_AUTODMA .swdma_mask = ATA_SWDMA2, diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 5682895d36d..d0f7bb8b8ad 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 1.21 Oct 23, 2007 - * * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc @@ -88,7 +86,7 @@ * - rename all the register related variables consistently * - move all the interrupt twiddling code from the speedproc handlers into * init_hwif_hpt366(), also grouping all the DMA related code together there - * - merge two HPT37x speedproc handlers, fix the PIO timing register mask and + * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and * separate the UltraDMA and MWDMA masks there to avoid changing PIO timings * when setting an UltraDMA mode * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select @@ -123,12 +121,8 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> #include <linux/blkdev.h> #include <linux/hdreg.h> - #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> @@ -136,7 +130,6 @@ #include <asm/uaccess.h> #include <asm/io.h> -#include <asm/irq.h> /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE @@ -310,6 +303,8 @@ static u32 twenty_five_base_hpt36x[] = { /* XFER_PIO_0 */ 0xc0d08585 }; +#if 0 +/* These are the timing tables from the HighPoint open source drivers... */ static u32 thirty_three_base_hpt37x[] = { /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */ /* XFER_UDMA_5 */ 0x12446231, @@ -369,6 +364,73 @@ static u32 sixty_six_base_hpt37x[] = { /* XFER_PIO_1 */ 0x0d029d26, /* XFER_PIO_0 */ 0x0d029d5e }; +#else +/* + * The following are the new timing tables with PIO mode data/taskfile transfer + * overclocking fixed... + */ + +/* This table is taken from the HPT370 data manual rev. 1.02 */ +static u32 thirty_three_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x16455031, /* 0x16655031 ?? */ + /* XFER_UDMA_5 */ 0x16455031, + /* XFER_UDMA_4 */ 0x16455031, + /* XFER_UDMA_3 */ 0x166d5031, + /* XFER_UDMA_2 */ 0x16495031, + /* XFER_UDMA_1 */ 0x164d5033, + /* XFER_UDMA_0 */ 0x16515097, + + /* XFER_MW_DMA_2 */ 0x26515031, + /* XFER_MW_DMA_1 */ 0x26515033, + /* XFER_MW_DMA_0 */ 0x26515097, + + /* XFER_PIO_4 */ 0x06515021, + /* XFER_PIO_3 */ 0x06515022, + /* XFER_PIO_2 */ 0x06515033, + /* XFER_PIO_1 */ 0x06915065, + /* XFER_PIO_0 */ 0x06d1508a +}; + +static u32 fifty_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x1a861842, + /* XFER_UDMA_5 */ 0x1a861842, + /* XFER_UDMA_4 */ 0x1aae1842, + /* XFER_UDMA_3 */ 0x1a8e1842, + /* XFER_UDMA_2 */ 0x1a0e1842, + /* XFER_UDMA_1 */ 0x1a161854, + /* XFER_UDMA_0 */ 0x1a1a18ea, + + /* XFER_MW_DMA_2 */ 0x2a821842, + /* XFER_MW_DMA_1 */ 0x2a821854, + /* XFER_MW_DMA_0 */ 0x2a8218ea, + + /* XFER_PIO_4 */ 0x0a821842, + /* XFER_PIO_3 */ 0x0a821843, + /* XFER_PIO_2 */ 0x0a821855, + /* XFER_PIO_1 */ 0x0ac218a8, + /* XFER_PIO_0 */ 0x0b02190c +}; + +static u32 sixty_six_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x1c86fe62, + /* XFER_UDMA_5 */ 0x1caefe62, /* 0x1c8afe62 */ + /* XFER_UDMA_4 */ 0x1c8afe62, + /* XFER_UDMA_3 */ 0x1c8efe62, + /* XFER_UDMA_2 */ 0x1c92fe62, + /* XFER_UDMA_1 */ 0x1c9afe62, + /* XFER_UDMA_0 */ 0x1c82fe62, + + /* XFER_MW_DMA_2 */ 0x2c82fe62, + /* XFER_MW_DMA_1 */ 0x2c82fe66, + /* XFER_MW_DMA_0 */ 0x2c82ff2e, + + /* XFER_PIO_4 */ 0x0c82fe62, + /* XFER_PIO_3 */ 0x0c82fe84, + /* XFER_PIO_2 */ 0x0c82fea6, + /* XFER_PIO_1 */ 0x0d02ff26, + /* XFER_PIO_0 */ 0x0d42ff7f +}; +#endif #define HPT366_DEBUG_DRIVE_INFO 0 #define HPT371_ALLOW_ATA133_6 1 @@ -389,6 +451,13 @@ enum ata_clock { NUM_ATA_CLOCKS }; +struct hpt_timings { + u32 pio_mask; + u32 dma_mask; + u32 ultra_mask; + u32 *clock_table[NUM_ATA_CLOCKS]; +}; + /* * Hold all the HighPoint chip information in one place. */ @@ -399,7 +468,8 @@ struct hpt_info { u8 udma_mask; /* Allowed UltraDMA modes mask. */ u8 dpll_clk; /* DPLL clock in MHz */ u8 pci_clk; /* PCI clock in MHz */ - u32 **settings; /* Chipset settings table */ + struct hpt_timings *timings; /* Chipset timing data */ + u8 clock; /* ATA clock selected */ }; /* Supported HighPoint chips */ @@ -417,20 +487,30 @@ enum { HPT371N }; -static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = { - twenty_five_base_hpt36x, - thirty_three_base_hpt36x, - forty_base_hpt36x, - NULL, - NULL +static struct hpt_timings hpt36x_timings = { + .pio_mask = 0xc1f8ffff, + .dma_mask = 0x303800ff, + .ultra_mask = 0x30070000, + .clock_table = { + [ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x, + [ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x, + [ATA_CLOCK_40MHZ] = forty_base_hpt36x, + [ATA_CLOCK_50MHZ] = NULL, + [ATA_CLOCK_66MHZ] = NULL + } }; -static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = { - NULL, - thirty_three_base_hpt37x, - NULL, - fifty_base_hpt37x, - sixty_six_base_hpt37x +static struct hpt_timings hpt37x_timings = { + .pio_mask = 0xcfc3ffff, + .dma_mask = 0x31c001ff, + .ultra_mask = 0x303c0000, + .clock_table = { + [ATA_CLOCK_25MHZ] = NULL, + [ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x, + [ATA_CLOCK_40MHZ] = NULL, + [ATA_CLOCK_50MHZ] = fifty_base_hpt37x, + [ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x + } }; static const struct hpt_info hpt36x __devinitdata = { @@ -438,7 +518,7 @@ static const struct hpt_info hpt36x __devinitdata = { .chip_type = HPT36x, .udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2, .dpll_clk = 0, /* no DPLL */ - .settings = hpt36x_settings + .timings = &hpt36x_timings }; static const struct hpt_info hpt370 __devinitdata = { @@ -446,7 +526,7 @@ static const struct hpt_info hpt370 __devinitdata = { .chip_type = HPT370, .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, .dpll_clk = 48, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt370a __devinitdata = { @@ -454,7 +534,7 @@ static const struct hpt_info hpt370a __devinitdata = { .chip_type = HPT370A, .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, .dpll_clk = 48, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt374 __devinitdata = { @@ -462,7 +542,7 @@ static const struct hpt_info hpt374 __devinitdata = { .chip_type = HPT374, .udma_mask = ATA_UDMA5, .dpll_clk = 48, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt372 __devinitdata = { @@ -470,7 +550,7 @@ static const struct hpt_info hpt372 __devinitdata = { .chip_type = HPT372, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 55, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt372a __devinitdata = { @@ -478,7 +558,7 @@ static const struct hpt_info hpt372a __devinitdata = { .chip_type = HPT372A, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 66, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt302 __devinitdata = { @@ -486,7 +566,7 @@ static const struct hpt_info hpt302 __devinitdata = { .chip_type = HPT302, .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 66, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt371 __devinitdata = { @@ -494,7 +574,7 @@ static const struct hpt_info hpt371 __devinitdata = { .chip_type = HPT371, .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 66, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt372n __devinitdata = { @@ -502,7 +582,7 @@ static const struct hpt_info hpt372n __devinitdata = { .chip_type = HPT372N, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 77, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt302n __devinitdata = { @@ -510,7 +590,7 @@ static const struct hpt_info hpt302n __devinitdata = { .chip_type = HPT302N, .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 77, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static const struct hpt_info hpt371n __devinitdata = { @@ -518,7 +598,7 @@ static const struct hpt_info hpt371n __devinitdata = { .chip_type = HPT371N, .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 77, - .settings = hpt37x_settings + .timings = &hpt37x_timings }; static int check_in_drive_list(ide_drive_t *drive, const char **list) @@ -539,7 +619,8 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list) static u8 hpt3xx_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct hpt_info *info = pci_get_drvdata(dev); u8 mask = hwif->ultra_mask; switch (info->chip_type) { @@ -578,7 +659,8 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) static u8 hpt3xx_mdma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct hpt_info *info = pci_get_drvdata(dev); switch (info->chip_type) { case HPT372 : @@ -606,100 +688,56 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info) for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) if (xfer_speeds[i] == speed) break; - /* - * NOTE: info->settings only points to the pointer - * to the list of the actual register values - */ - return (*info->settings)[i]; + + return info->timings->clock_table[info->clock][i]; } -static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed) +static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); struct hpt_info *info = pci_get_drvdata(dev); - u8 itr_addr = drive->dn ? 0x44 : 0x40; + struct hpt_timings *t = info->timings; + u8 itr_addr = 0x40 + (drive->dn * 4); u32 old_itr = 0; - u32 itr_mask, new_itr; - - itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : - (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); - - new_itr = get_speed_setting(speed, info); + u32 new_itr = get_speed_setting(speed, info); + u32 itr_mask = speed < XFER_MW_DMA_0 ? t->pio_mask : + (speed < XFER_UDMA_0 ? t->dma_mask : + t->ultra_mask); + pci_read_config_dword(dev, itr_addr, &old_itr); + new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask); /* * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) * to avoid problems handling I/O errors later */ - pci_read_config_dword(dev, itr_addr, &old_itr); - new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); new_itr &= ~0xc0000000; pci_write_config_dword(dev, itr_addr, new_itr); } -static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = pci_get_drvdata(dev); - u8 itr_addr = 0x40 + (drive->dn * 4); - u32 old_itr = 0; - u32 itr_mask, new_itr; - - itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : - (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); - - new_itr = get_speed_setting(speed, info); - - pci_read_config_dword(dev, itr_addr, &old_itr); - new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); - - if (speed < XFER_MW_DMA_0) - new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, itr_addr, new_itr); -} - -static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); - - if (info->chip_type >= HPT370) - hpt37x_set_mode(drive, speed); - else /* hpt368: hpt_minimum_revision(dev, 2) */ - hpt36x_set_mode(drive, speed); -} - static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio) { hpt3xx_set_mode(drive, XFER_PIO_0 + pio); } -static int hpt3xx_quirkproc(ide_drive_t *drive) +static void hpt3xx_quirkproc(ide_drive_t *drive) { struct hd_driveid *id = drive->id; const char **list = quirk_drives; while (*list) - if (strstr(id->model, *list++)) - return 1; - return 0; -} - -static void hpt3xx_intrproc(ide_drive_t *drive) -{ - if (drive->quirk_list) - return; + if (strstr(id->model, *list++)) { + drive->quirk_list = 1; + return; + } - /* drives in the quirk_list may not like intr setups/cleanups */ - outb(drive->ctl | 2, IDE_CONTROL_REG); + drive->quirk_list = 0; } static void hpt3xx_maskproc(ide_drive_t *drive, int mask) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); struct hpt_info *info = pci_get_drvdata(dev); if (drive->quirk_list) { @@ -731,7 +769,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask) */ static void hpt366_dma_lost_irq(ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u8 mcr1 = 0, mcr3 = 0, scr1 = 0; pci_read_config_byte(dev, 0x50, &mcr1); @@ -747,18 +785,20 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive) static void hpt370_clear_engine(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); - pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37); + pci_write_config_byte(dev, hwif->select_data, 0x37); udelay(10); } static void hpt370_irq_timeout(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); u16 bfifo = 0; u8 dma_cmd; - pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); + pci_read_config_word(dev, hwif->select_data + 2, &bfifo); printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff); /* get DMA command mode */ @@ -801,10 +841,11 @@ static void hpt370_dma_timeout(ide_drive_t *drive) static int hpt374_ide_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); u16 bfifo = 0; u8 dma_stat; - pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); + pci_read_config_word(dev, hwif->select_data + 2, &bfifo); if (bfifo & 0x1FF) { // printk("%s: %d bytes in FIFO\n", drive->name, bfifo); return 0; @@ -824,7 +865,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) static int hpt374_ide_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 mcr = 0, mcr_addr = hwif->select_data; u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01; @@ -845,32 +886,33 @@ static int hpt374_ide_dma_end(ide_drive_t *drive) static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) { - u8 scr2 = inb(hwif->dma_master + 0x7b); + unsigned long base = hwif->extra_base; + u8 scr2 = inb(base + 0x6b); if ((scr2 & 0x7f) == mode) return; /* Tristate the bus */ - outb(0x80, hwif->dma_master + 0x73); - outb(0x80, hwif->dma_master + 0x77); + outb(0x80, base + 0x63); + outb(0x80, base + 0x67); /* Switch clock and reset channels */ - outb(mode, hwif->dma_master + 0x7b); - outb(0xc0, hwif->dma_master + 0x79); + outb(mode, base + 0x6b); + outb(0xc0, base + 0x69); /* * Reset the state machines. * NOTE: avoid accidentally enabling the disabled channels. */ - outb(inb(hwif->dma_master + 0x70) | 0x32, hwif->dma_master + 0x70); - outb(inb(hwif->dma_master + 0x74) | 0x32, hwif->dma_master + 0x74); + outb(inb(base + 0x60) | 0x32, base + 0x60); + outb(inb(base + 0x64) | 0x32, base + 0x64); /* Complete reset */ - outb(0x00, hwif->dma_master + 0x79); + outb(0x00, base + 0x69); /* Reconnect channels to bus */ - outb(0x00, hwif->dma_master + 0x73); - outb(0x00, hwif->dma_master + 0x77); + outb(0x00, base + 0x63); + outb(0x00, base + 0x67); } /** @@ -898,7 +940,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) static int hpt3xx_busproc(ide_drive_t *drive, int state) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 mcr_addr = hwif->select_data + 2; u8 resetmask = hwif->channel ? 0x80 : 0x40; u8 bsr2 = 0; @@ -1141,7 +1183,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha * We also don't like using the DPLL because this causes glitches * on PRST-/SRST- when the state engine gets reset... */ - if (chip_type >= HPT374 || info->settings[clock] == NULL) { + if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) { u16 f_low, delta = pci_clk < 50 ? 2 : 4; int adjust; @@ -1157,7 +1199,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha clock = ATA_CLOCK_50MHZ; } - if (info->settings[clock] == NULL) { + if (info->timings->clock_table[clock] == NULL) { printk(KERN_ERR "%s: unknown bus timing!\n", name); kfree(info); return -EIO; @@ -1198,15 +1240,10 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha printk("%s: using %d MHz PCI clock\n", name, pci_clk); } - /* - * Advance the table pointer to a slot which points to the list - * of the register values settings matching the clock being used. - */ - info->settings += clock; - /* Store the clock frequencies. */ info->dpll_clk = dpll_clk; info->pci_clk = pci_clk; + info->clock = clock; /* Point to this chip's own instance of the hpt_info structure. */ pci_set_drvdata(dev, info); @@ -1237,12 +1274,55 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha return dev->irq; } +static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct hpt_info *info = pci_get_drvdata(dev); + u8 chip_type = info->chip_type; + u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02; + + /* + * The HPT37x uses the CBLID pins as outputs for MA15/MA16 + * address lines to access an external EEPROM. To read valid + * cable detect state the pins must be enabled as inputs. + */ + if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { + /* + * HPT374 PCI function 1 + * - set bit 15 of reg 0x52 to enable TCBLID as input + * - set bit 15 of reg 0x56 to enable FCBLID as input + */ + u8 mcr_addr = hwif->select_data + 2; + u16 mcr; + + pci_read_config_word(dev, mcr_addr, &mcr); + pci_write_config_word(dev, mcr_addr, (mcr | 0x8000)); + /* now read cable id register */ + pci_read_config_byte(dev, 0x5a, &scr1); + pci_write_config_word(dev, mcr_addr, mcr); + } else if (chip_type >= HPT370) { + /* + * HPT370/372 and 374 pcifn 0 + * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs + */ + u8 scr2 = 0; + + pci_read_config_byte(dev, 0x5b, &scr2); + pci_write_config_byte(dev, 0x5b, (scr2 & ~1)); + /* now read cable id register */ + pci_read_config_byte(dev, 0x5a, &scr1); + pci_write_config_byte(dev, 0x5b, scr2); + } else + pci_read_config_byte(dev, 0x5a, &scr1); + + return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); struct hpt_info *info = pci_get_drvdata(dev); int serialize = HPT_SERIALIZE_IO; - u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02; u8 chip_type = info->chip_type; u8 new_mcr, old_mcr = 0; @@ -1251,14 +1331,16 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->set_pio_mode = &hpt3xx_set_pio_mode; hwif->set_dma_mode = &hpt3xx_set_mode; + hwif->quirkproc = &hpt3xx_quirkproc; - hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; hwif->busproc = &hpt3xx_busproc; hwif->udma_filter = &hpt3xx_udma_filter; hwif->mdma_filter = &hpt3xx_mdma_filter; + hwif->cable_detect = hpt3xx_cable_detect; + /* * HPT3xxN chips have some complications: * @@ -1304,43 +1386,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) if (hwif->dma_base == 0) return; - /* - * The HPT37x uses the CBLID pins as outputs for MA15/MA16 - * address lines to access an external EEPROM. To read valid - * cable detect state the pins must be enabled as inputs. - */ - if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { - /* - * HPT374 PCI function 1 - * - set bit 15 of reg 0x52 to enable TCBLID as input - * - set bit 15 of reg 0x56 to enable FCBLID as input - */ - u8 mcr_addr = hwif->select_data + 2; - u16 mcr; - - pci_read_config_word (dev, mcr_addr, &mcr); - pci_write_config_word(dev, mcr_addr, (mcr | 0x8000)); - /* now read cable id register */ - pci_read_config_byte (dev, 0x5a, &scr1); - pci_write_config_word(dev, mcr_addr, mcr); - } else if (chip_type >= HPT370) { - /* - * HPT370/372 and 374 pcifn 0 - * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs - */ - u8 scr2 = 0; - - pci_read_config_byte (dev, 0x5b, &scr2); - pci_write_config_byte(dev, 0x5b, (scr2 & ~1)); - /* now read cable id register */ - pci_read_config_byte (dev, 0x5a, &scr1); - pci_write_config_byte(dev, 0x5b, scr2); - } else - pci_read_config_byte (dev, 0x5a, &scr1); - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; - if (chip_type >= HPT374) { hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_end = &hpt374_ide_dma_end; @@ -1354,7 +1399,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 masterdma = 0, slavedma = 0; u8 dma_new = 0, dma_old = 0; unsigned long flags; @@ -1374,7 +1419,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) local_irq_restore(flags); - ide_setup_dma(hwif, dmabase, 8); + ide_setup_dma(hwif, dmabase); } static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2) @@ -1425,6 +1470,11 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) return 0; } +#define IDE_HFLAGS_HPT3XX \ + (IDE_HFLAG_NO_ATAPI_DMA | \ + IDE_HFLAG_ABUSE_SET_DMA_MODE | \ + IDE_HFLAG_OFF_BOARD) + static const struct ide_port_info hpt366_chipsets[] __devinitdata = { { /* 0 */ .name = "HPT36x", @@ -1439,9 +1489,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { */ .enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}}, .extra = 240, - .host_flags = IDE_HFLAG_SINGLE | - IDE_HFLAG_NO_ATAPI_DMA | - IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 1 */ @@ -1451,7 +1499,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .extra = 240, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 2 */ @@ -1461,7 +1509,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .extra = 240, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 3 */ @@ -1471,7 +1519,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .extra = 240, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 4 */ @@ -1482,7 +1530,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .udma_mask = ATA_UDMA5, .extra = 240, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 5 */ @@ -1492,7 +1540,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .extra = 240, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, } diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index 90b52ed37bf..e3427eaab43 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -10,13 +10,10 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> -#include <asm/io.h> - /** * it8213_set_pio_mode - set host controller for PIO mode * @drive: drive @@ -28,7 +25,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); int is_slave = drive->dn & 1; int master_port = 0x40; int slave_port = 0x44; @@ -85,7 +82,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio) static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 maslave = 0x40; int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; @@ -101,24 +98,11 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_read_config_byte(dev, 0x54, ®54); pci_read_config_byte(dev, 0x55, ®55); - switch(speed) { - case XFER_UDMA_6: - case XFER_UDMA_4: - case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_5: - case XFER_UDMA_3: - case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_SW_DMA_2: - break; - default: - return; - } - if (speed >= XFER_UDMA_0) { + u8 udma = speed - XFER_UDMA_0; + + u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4); + if (!(reg48 & u_flag)) pci_write_config_byte(dev, 0x48, reg48 | u_flag); if (speed >= XFER_UDMA_5) { @@ -156,6 +140,16 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) } } +static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 reg42h = 0; + + pci_read_config_byte(dev, 0x42, ®42h); + + return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + /** * init_hwif_it8213 - set up hwif structs * @hwif: interface to set up @@ -165,18 +159,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) static void __devinit init_hwif_it8213(ide_hwif_t *hwif) { - u8 reg42h = 0; - hwif->set_dma_mode = &it8213_set_dma_mode; hwif->set_pio_mode = &it8213_set_pio_mode; - if (!hwif->dma_base) - return; - - pci_read_config_byte(hwif->pci_dev, 0x42, ®42h); - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; + hwif->cable_detect = it8213_cable_detect; } diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 5c997543531..1597f0cc1bf 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -1,7 +1,4 @@ - /* - * linux/drivers/ide/pci/it821x.c Version 0.16 Jul 3 2007 - * * Copyright (C) 2004 Red Hat <alan@redhat.com> * Copyright (C) 2007 Bartlomiej Zolnierkiewicz * @@ -66,13 +63,10 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> -#include <asm/io.h> - struct it821x_dev { unsigned int smart:1, /* Are we in smart raid mode */ @@ -113,7 +107,8 @@ static int it8212_noraid; static void it821x_program(ide_drive_t *drive, u16 timing) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); struct it821x_dev *itdev = ide_get_hwifdata(hwif); int channel = hwif->channel; u8 conf; @@ -123,7 +118,8 @@ static void it821x_program(ide_drive_t *drive, u16 timing) conf = timing >> 8; else conf = timing & 0xFF; - pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf); + + pci_write_config_byte(dev, 0x54 + 4 * channel, conf); } /** @@ -137,7 +133,8 @@ static void it821x_program(ide_drive_t *drive, u16 timing) static void it821x_program_udma(ide_drive_t *drive, u16 timing) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); struct it821x_dev *itdev = ide_get_hwifdata(hwif); int channel = hwif->channel; int unit = drive->select.b.unit; @@ -148,11 +145,12 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing) conf = timing >> 8; else conf = timing & 0xFF; - if(itdev->timing10 == 0) - pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf); + + if (itdev->timing10 == 0) + pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf); else { - pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf); - pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf); + pci_write_config_byte(dev, 0x56 + 4 * channel, conf); + pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf); } } @@ -167,6 +165,7 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing) static void it821x_clock_strategy(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); struct it821x_dev *itdev = ide_get_hwifdata(hwif); u8 unit = drive->select.b.unit; @@ -205,10 +204,11 @@ static void it821x_clock_strategy(ide_drive_t *drive) itdev->clock_mode = ATA_50; sel = 1; } - pci_read_config_byte(hwif->pci_dev, 0x50, &v); + + pci_read_config_byte(dev, 0x50, &v); v &= ~(1 << (1 + hwif->channel)); v |= sel << (1 + hwif->channel); - pci_write_config_byte(hwif->pci_dev, 0x50, v); + pci_write_config_byte(dev, 0x50, v); /* * Reprogram the UDMA/PIO of the pair drive for the switch @@ -282,7 +282,8 @@ static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio) static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif); int unit = drive->select.b.unit; int channel = hwif->channel; @@ -297,12 +298,12 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted) itdev->udma[unit] = UDMA_OFF; /* UDMA bits off - Revision 0x10 do them in pairs */ - pci_read_config_byte(hwif->pci_dev, 0x50, &conf); - if(itdev->timing10) + pci_read_config_byte(dev, 0x50, &conf); + if (itdev->timing10) conf |= channel ? 0x60: 0x18; else conf |= 1 << (3 + 2 * channel + unit); - pci_write_config_byte(hwif->pci_dev, 0x50, conf); + pci_write_config_byte(dev, 0x50, conf); it821x_clock_strategy(drive); /* FIXME: do we need to program this ? */ @@ -320,7 +321,8 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted) static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); struct it821x_dev *itdev = ide_get_hwifdata(hwif); int unit = drive->select.b.unit; int channel = hwif->channel; @@ -337,12 +339,12 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted) itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */ /* UDMA on. Again revision 0x10 must do the pair */ - pci_read_config_byte(hwif->pci_dev, 0x50, &conf); - if(itdev->timing10) + pci_read_config_byte(dev, 0x50, &conf); + if (itdev->timing10) conf &= channel ? 0x9F: 0xE7; else conf &= ~ (1 << (3 + 2 * channel + unit)); - pci_write_config_byte(hwif->pci_dev, 0x50, conf); + pci_write_config_byte(dev, 0x50, conf); it821x_clock_strategy(drive); it821x_program_udma(drive, itdev->udma[unit]); @@ -431,33 +433,29 @@ static u8 __devinit ata66_it821x(ide_hwif_t *hwif) } /** - * it821x_fixup - post init callback - * @hwif: interface + * it821x_quirkproc - post init callback + * @drive: drive * - * This callback is run after the drives have been probed but + * This callback is run after the drive has been probed but * before anything gets attached. It allows drivers to do any * final tuning that is needed, or fixups to work around bugs. */ -static void __devinit it821x_fixups(ide_hwif_t *hwif) +static void __devinit it821x_quirkproc(ide_drive_t *drive) { - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int i; + struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif); + struct hd_driveid *id = drive->id; + u16 *idbits = (u16 *)drive->id; - if(!itdev->smart) { + if (!itdev->smart) { /* * If we are in pass through mode then not much * needs to be done, but we do bother to clear the * IRQ mask as we may well be in PIO (eg rev 0x10) * for now and we know unmasking is safe on this chipset. */ - for (i = 0; i < 2; i++) { - ide_drive_t *drive = &hwif->drives[i]; - if(drive->present) - drive->unmask = 1; - } - return; - } + drive->unmask = 1; + } else { /* * Perform fixups on smart mode. We need to "lose" some * capabilities the firmware lacks but does not filter, and @@ -465,16 +463,6 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif) * in RAID mode. */ - for(i = 0; i < 2; i++) { - ide_drive_t *drive = &hwif->drives[i]; - struct hd_driveid *id; - u16 *idbits; - - if(!drive->present) - continue; - id = drive->id; - idbits = (u16 *)drive->id; - /* Check for RAID v native */ if(strstr(id->model, "Integrated Technology Express")) { /* In raid mode the ident block is slightly buggy @@ -534,9 +522,12 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif) static void __devinit init_hwif_it821x(ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL); u8 conf; + hwif->quirkproc = &it821x_quirkproc; + if (idev == NULL) { printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n"); return; @@ -544,7 +535,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) ide_set_hwifdata(hwif, idev); - pci_read_config_byte(hwif->pci_dev, 0x50, &conf); + pci_read_config_byte(dev, 0x50, &conf); if (conf & 1) { idev->smart = 1; hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; @@ -567,7 +558,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) * this is necessary. */ - pci_read_config_byte(hwif->pci_dev, 0x08, &conf); + pci_read_config_byte(dev, 0x08, &conf); if (conf == 0x10) { idev->timing10 = 1; hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; @@ -585,14 +576,13 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) } else hwif->host_flags |= IDE_HFLAG_NO_SET_MODE; + hwif->cable_detect = ata66_it821x; + if (hwif->dma_base == 0) return; hwif->ultra_mask = ATA_UDMA6; hwif->mwdma_mask = ATA_MWDMA2; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = ata66_it821x(hwif); } static void __devinit it8212_disable_raid(struct pci_dev *dev) @@ -633,7 +623,6 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha .name = name_str, \ .init_chipset = init_chipset_it821x, \ .init_hwif = init_hwif_it821x, \ - .fixup = it821x_fixups, \ .host_flags = IDE_HFLAG_BOOTABLE, \ .pio_mask = ATA_PIO4, \ } @@ -653,8 +642,7 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = { static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); - return 0; + return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); } static const struct pci_device_id it821x_pci_tbl[] = { diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index bdf64d99770..a56bcb4f22f 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -8,13 +8,10 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> -#include <asm/io.h> - typedef enum { PORT_PATA0 = 0, PORT_PATA1 = 1, @@ -30,7 +27,7 @@ typedef enum { static u8 __devinit ata66_jmicron(ide_hwif_t *hwif) { - struct pci_dev *pdev = hwif->pci_dev; + struct pci_dev *pdev = to_pci_dev(hwif->dev); u32 control; u32 control5; @@ -111,11 +108,7 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif) hwif->set_pio_mode = &jmicron_set_pio_mode; hwif->set_dma_mode = &jmicron_set_dma_mode; - if (hwif->dma_base == 0) - return; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = ata66_jmicron(hwif); + hwif->cable_detect = ata66_jmicron; } static const struct ide_port_info jmicron_chipset __devinitdata = { @@ -139,8 +132,7 @@ static const struct ide_port_info jmicron_chipset __devinitdata = { static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_setup_pci_device(dev, &jmicron_chipset); - return 0; + return ide_setup_pci_device(dev, &jmicron_chipset); } /* All JMB PATA controllers have and will continue to have the same diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index d4df4642dbb..bf0d3b2931f 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/ns87415.c Version 2.00 Sep. 10, 2002 - * * Copyright (C) 1997-1998 Mark Lord <mlord@pobox.com> * Copyright (C) 1998 Eddie C. Dost <ecd@skynet.be> * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> @@ -12,11 +10,7 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> #include <linux/interrupt.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/pci.h> #include <linux/delay.h> @@ -71,10 +65,9 @@ static u8 superio_ide_inb (unsigned long port) static void __devinit superio_ide_init_iops (struct hwif_s *hwif) { + struct pci_dev *pdev = to_pci_dev(hwif->dev); u32 base, dmabase; - u8 tmp; - struct pci_dev *pdev = hwif->pci_dev; - u8 port = hwif->channel; + u8 port = hwif->channel, tmp; base = pci_resource_start(pdev, port * 2) & ~3; dmabase = pci_resource_start(pdev, 4) & ~3; @@ -93,10 +86,11 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif) static void __devinit init_iops_ns87415(ide_hwif_t *hwif) { - if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) { + struct pci_dev *dev = to_pci_dev(hwif->dev); + + if (PCI_SLOT(dev->devfn) == 0xE) /* Built-in - assume it's under superio. */ superio_ide_init_iops(hwif); - } } #endif @@ -110,8 +104,8 @@ static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) { ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data; - struct pci_dev *dev = hwif->pci_dev; unsigned long flags; local_irq_save(flags); @@ -189,7 +183,7 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive) static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned int ctrl, using_inta; u8 progif; #ifdef __sparc_v9__ @@ -231,8 +225,8 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) #ifdef __sparc_v9__ /* - * XXX: Reset the device, if we don't it will not respond - * to SELECT_DRIVE() properly during first probe_hwif(). + * XXX: Reset the device, if we don't it will not respond to + * SELECT_DRIVE() properly during first ide_probe_port(). */ timeout = 10000; outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]); diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 8953d9c3926..46e8748f507 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/opti621.c Version 0.9 Sep 24, 2007 - * * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) */ @@ -89,11 +87,6 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/pci.h> #include <linux/hdreg.h> #include <linux/ide.h> @@ -322,14 +315,18 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) spin_unlock_irqrestore(&opti621_lock, flags); } +static void __devinit opti621_port_init_devs(ide_hwif_t *hwif) +{ + hwif->drives[0].drive_data = PIO_DONT_KNOW; + hwif->drives[1].drive_data = PIO_DONT_KNOW; +} + /* * init_hwif_opti621() is called once for each hwif found at boot. */ static void __devinit init_hwif_opti621 (ide_hwif_t *hwif) { - hwif->drives[0].drive_data = PIO_DONT_KNOW; - hwif->drives[1].drive_data = PIO_DONT_KNOW; - + hwif->port_init_devs = opti621_port_init_devs; hwif->set_pio_mode = &opti621_set_pio_mode; } diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 4234efeba60..1c8cb7797a4 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -19,18 +19,12 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> -#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/ide.h> #include <asm/io.h> -#include <asm/irq.h> #ifdef CONFIG_PPC_PMAC #include <asm/prom.h> @@ -146,9 +140,10 @@ static struct udma_timing { { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ }; -static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed) +static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 adj = (drive->dn & 1) ? 0x08 : 0x00; /* @@ -159,48 +154,21 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed) * As we set up the PLL to output 133 MHz for UltraDMA/133 capable * chips, we must override the default register settings... */ - if (max_dma_rate(hwif->pci_dev) == 4) { + if (max_dma_rate(dev) == 4) { u8 mode = speed & 0x07; - switch (speed) { - case XFER_UDMA_6: - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - set_indexed_reg(hwif, 0x10 + adj, - udma_timings[mode].reg10); - set_indexed_reg(hwif, 0x11 + adj, - udma_timings[mode].reg11); - set_indexed_reg(hwif, 0x12 + adj, - udma_timings[mode].reg12); - break; - - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - set_indexed_reg(hwif, 0x0e + adj, - mwdma_timings[mode].reg0e); - set_indexed_reg(hwif, 0x0f + adj, - mwdma_timings[mode].reg0f); - break; - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - set_indexed_reg(hwif, 0x0c + adj, - pio_timings[mode].reg0c); - set_indexed_reg(hwif, 0x0d + adj, - pio_timings[mode].reg0d); - set_indexed_reg(hwif, 0x13 + adj, - pio_timings[mode].reg13); - break; - default: - printk(KERN_ERR "pdc202xx_new: " - "Unknown speed %d ignored\n", speed); + if (speed >= XFER_UDMA_0) { + set_indexed_reg(hwif, 0x10 + adj, + udma_timings[mode].reg10); + set_indexed_reg(hwif, 0x11 + adj, + udma_timings[mode].reg11); + set_indexed_reg(hwif, 0x12 + adj, + udma_timings[mode].reg12); + } else { + set_indexed_reg(hwif, 0x0e + adj, + mwdma_timings[mode].reg0e); + set_indexed_reg(hwif, 0x0f + adj, + mwdma_timings[mode].reg0f); } } else if (speed == XFER_UDMA_2) { /* Set tHOLD bit to 0 if using UDMA mode 2 */ @@ -212,10 +180,18 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed) static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio) { - pdcnew_set_mode(drive, XFER_PIO_0 + pio); + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 adj = (drive->dn & 1) ? 0x08 : 0x00; + + if (max_dma_rate(dev) == 4) { + set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c); + set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d); + set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13); + } } -static u8 pdcnew_cable_detect(ide_hwif_t *hwif) +static u8 __devinit pdcnew_cable_detect(ide_hwif_t *hwif) { if (get_indexed_reg(hwif, 0x0b) & 0x04) return ATA_CBL_PATA40; @@ -223,14 +199,17 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif) return ATA_CBL_PATA80; } -static int pdcnew_quirkproc(ide_drive_t *drive) +static void pdcnew_quirkproc(ide_drive_t *drive) { const char **list, *model = drive->id->model; for (list = pdc_quirk_drives; *list != NULL; list++) - if (strstr(model, *list) != NULL) - return 2; - return 0; + if (strstr(model, *list) != NULL) { + drive->quirk_list = 2; + return; + } + + drive->quirk_list = 0; } static void pdcnew_reset(ide_drive_t *drive) @@ -466,24 +445,21 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) { hwif->set_pio_mode = &pdcnew_set_pio_mode; - hwif->set_dma_mode = &pdcnew_set_mode; + hwif->set_dma_mode = &pdcnew_set_dma_mode; hwif->quirkproc = &pdcnew_quirkproc; hwif->resetproc = &pdcnew_reset; - if (hwif->dma_base == 0) - return; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = pdcnew_cable_detect(hwif); + hwif->cable_detect = pdcnew_cable_detect; } static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) { struct pci_dev *dev2; - dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 2, + dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1, PCI_FUNC(dev->devfn))); + if (dev2 && dev2->vendor == dev->vendor && dev2->device == dev->device) { diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index e09742e2ba5..da432979038 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/pdc202xx_old.c Version 0.52 Aug 27, 2007 - * * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2006-2007 MontaVista Software, Inc. * Copyright (C) 2007 Bartlomiej Zolnierkiewicz @@ -34,18 +32,13 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> #include <linux/blkdev.h> #include <linux/hdreg.h> -#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/ide.h> #include <asm/io.h> -#include <asm/irq.h> #define PDC202XX_DEBUG_DRIVE_INFO 0 @@ -66,7 +59,7 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *); static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 drive_pci = 0x60 + (drive->dn << 2); u8 AP = 0, BP = 0, CP = 0; @@ -142,11 +135,12 @@ static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio) pdc202xx_set_mode(drive, XFER_PIO_0 + pio); } -static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) +static u8 __devinit pdc2026x_old_cable_detect(ide_hwif_t *hwif) { - u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10); - pci_read_config_word(hwif->pci_dev, 0x50, &CIS); + pci_read_config_word(dev, 0x50, &CIS); return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; } @@ -162,7 +156,7 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) */ static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif) { - unsigned long clock_reg = hwif->dma_master + 0x11; + unsigned long clock_reg = hwif->extra_base + 0x01; u8 clock = inb(clock_reg); outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg); @@ -170,20 +164,23 @@ static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif) static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) { - unsigned long clock_reg = hwif->dma_master + 0x11; + unsigned long clock_reg = hwif->extra_base + 0x01; u8 clock = inb(clock_reg); outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); } -static int pdc202xx_quirkproc (ide_drive_t *drive) +static void pdc202xx_quirkproc(ide_drive_t *drive) { const char **list, *model = drive->id->model; for (list = pdc_quirk_drives; *list != NULL; list++) - if (strstr(model, *list) != NULL) - return 2; - return 0; + if (strstr(model, *list) != NULL) { + drive->quirk_list = 2; + return; + } + + drive->quirk_list = 0; } static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) @@ -193,7 +190,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) if (drive->media != ide_disk || drive->addressing == 1) { struct request *rq = HWGROUP(drive)->rq; ide_hwif_t *hwif = HWIF(drive); - unsigned long high_16 = hwif->dma_master; + unsigned long high_16 = hwif->extra_base - 16; unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); u32 word_count = 0; u8 clock = inb(high_16 + 0x11); @@ -212,7 +209,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive) { if (drive->media != ide_disk || drive->addressing == 1) { ide_hwif_t *hwif = HWIF(drive); - unsigned long high_16 = hwif->dma_master; + unsigned long high_16 = hwif->extra_base - 16; unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); u8 clock = 0; @@ -228,7 +225,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive) static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - unsigned long high_16 = hwif->dma_master; + unsigned long high_16 = hwif->extra_base - 16; u8 dma_stat = inb(hwif->dma_status); u8 sc1d = inb(high_16 + 0x001d); @@ -271,7 +268,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive) static void pdc202xx_reset_host (ide_hwif_t *hwif) { - unsigned long high_16 = hwif->dma_master; + unsigned long high_16 = hwif->extra_base - 16; u8 udma_speed_flag = inb(high_16 | 0x001f); outb(udma_speed_flag | 0x10, high_16 | 0x001f); @@ -302,24 +299,26 @@ static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); + hwif->set_pio_mode = &pdc202xx_set_pio_mode; hwif->set_dma_mode = &pdc202xx_set_mode; hwif->quirkproc = &pdc202xx_quirkproc; - if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) { hwif->resetproc = &pdc202xx_reset; + hwif->cable_detect = pdc2026x_old_cable_detect; + } + if (hwif->dma_base == 0) return; hwif->dma_lost_irq = &pdc202xx_dma_lost_irq; hwif->dma_timeout = &pdc202xx_dma_timeout; - if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) { - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = pdc202xx_old_cable_detect(hwif); - + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) { hwif->dma_start = &pdc202xx_old_ide_dma_start; hwif->ide_dma_end = &pdc202xx_old_ide_dma_end; } @@ -331,7 +330,7 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; if (hwif->channel) { - ide_setup_dma(hwif, dmabase, 8); + ide_setup_dma(hwif, dmabase); return; } @@ -355,7 +354,7 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) } #endif /* CONFIG_PDC202XX_BURST */ - ide_setup_dma(hwif, dmabase, 8); + ide_setup_dma(hwif, dmabase); } static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, @@ -375,6 +374,11 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, } } +#define IDE_HFLAGS_PDC202XX \ + (IDE_HFLAG_ERROR_STOPS_FIFO | \ + IDE_HFLAG_ABUSE_SET_DMA_MODE | \ + IDE_HFLAG_OFF_BOARD) + #define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \ { \ .name = name_str, \ @@ -382,9 +386,7 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, .init_hwif = init_hwif_pdc202xx, \ .init_dma = init_dma_pdc202xx, \ .extra = 48, \ - .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO | \ - extra_flags | \ - IDE_HFLAG_OFF_BOARD, \ + .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \ .pio_mask = ATA_PIO4, \ .mwdma_mask = ATA_MWDMA2, \ .udma_mask = udma, \ @@ -397,8 +399,7 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { .init_hwif = init_hwif_pdc202xx, .init_dma = init_dma_pdc202xx, .extra = 16, - .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO | - IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAGS_PDC202XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 9329d4a810e..decef0f4767 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/piix.c Version 0.54 Sep 5, 2007 - * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat Inc <alan@redhat.com> @@ -8,53 +6,8 @@ * * May be copied or modified under the terms of the GNU General Public License * - * PIO mode setting function for Intel chipsets. - * For use instead of BIOS settings. - * - * 40-41 - * 42-43 - * - * 41 - * 43 - * - * | PIO 0 | c0 | 80 | 0 | - * | PIO 2 | SW2 | d0 | 90 | 4 | - * | PIO 3 | MW1 | e1 | a1 | 9 | - * | PIO 4 | MW2 | e3 | a3 | b | - * - * sitre = word40 & 0x4000; primary - * sitre = word42 & 0x4000; secondary - * - * 44 8421|8421 hdd|hdb - * - * 48 8421 hdd|hdc|hdb|hda udma enabled - * - * 0001 hda - * 0010 hdb - * 0100 hdc - * 1000 hdd - * - * 4a 84|21 hdb|hda - * 4b 84|21 hdd|hdc - * - * ata-33/82371AB - * ata-33/82371EB - * ata-33/82801AB ata-66/82801AA - * 00|00 udma 0 00|00 reserved - * 01|01 udma 1 01|01 udma 3 - * 10|10 udma 2 10|10 udma 4 - * 11|11 reserved 11|11 reserved + * Documentation: * - * 54 8421|8421 ata66 drive|ata66 enable - * - * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, ®40); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, ®42); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, ®44); - * pci_read_config_byte(HWIF(drive)->pci_dev, 0x48, ®48); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); - * pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, ®54); - * - * Documentation * Publically available from Intel web site. Errata documentation * is also publically available. As an aide to anyone hacking on this * driver the list of errata that are relevant is below.going back to @@ -94,11 +47,9 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/ioport.h> #include <linux/pci.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/delay.h> #include <linux/init.h> #include <asm/io.h> @@ -116,7 +67,7 @@ static int no_piix_dma; static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); int is_slave = drive->dn & 1; int master_port = hwif->channel ? 0x42 : 0x40; int slave_port = 0x44; @@ -185,7 +136,7 @@ static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio) static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 maslave = hwif->channel ? 0x42 : 0x40; int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; @@ -203,20 +154,11 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_read_config_byte(dev, 0x54, ®54); pci_read_config_byte(dev, 0x55, ®55); - switch(speed) { - case XFER_UDMA_4: - case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_5: - case XFER_UDMA_3: - case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_SW_DMA_2: break; - default: return; - } - if (speed >= XFER_UDMA_0) { + u8 udma = speed - XFER_UDMA_0; + + u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4); + if (!(reg48 & u_flag)) pci_write_config_byte(dev, 0x48, reg48 | u_flag); if (speed == XFER_UDMA_5) { @@ -302,9 +244,11 @@ struct ich_laptop { static const struct ich_laptop ich_laptop[] = { /* devid, subvendor, subdev */ + { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ + { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */ /* end marker */ { 0, } @@ -312,7 +256,7 @@ static const struct ich_laptop ich_laptop[] = { static u8 __devinit piix_cable_detect(ide_hwif_t *hwif) { - struct pci_dev *pdev = hwif->pci_dev; + struct pci_dev *pdev = to_pci_dev(hwif->dev); const struct ich_laptop *lap = &ich_laptop[0]; u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30; @@ -344,14 +288,11 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) hwif->set_pio_mode = &piix_set_pio_mode; hwif->set_dma_mode = &piix_set_dma_mode; + hwif->cable_detect = piix_cable_detect; + if (!hwif->dma_base) return; - if (hwif->ultra_mask & 0x78) { - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = piix_cable_detect(hwif); - } - if (no_piix_dma) hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0; } diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c index 6b10ae260fa..51676612f78 100644 --- a/drivers/ide/pci/rz1000.c +++ b/drivers/ide/pci/rz1000.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/rz1000.c Version 0.06 January 12, 2003 - * * Copyright (C) 1995-1998 Linus Torvalds & author (see below) */ @@ -18,22 +16,15 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/pci.h> #include <linux/ide.h> #include <linux/init.h> -#include <asm/io.h> - static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); u16 reg; - struct pci_dev *dev = hwif->pci_dev; if (!pci_read_config_word (dev, 0x40, ®) && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { @@ -42,8 +33,7 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif) } else { if (hwif->mate) hwif->mate->serialized = hwif->serialized = 1; - hwif->drives[0].no_unmask = 1; - hwif->drives[1].no_unmask = 1; + hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS; printk(KERN_INFO "%s: serialized, disabled unmasking " "(buggy RZ1000/RZ1001)\n", hwif->name); } diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 0a7b3202066..561aa47c772 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/sc1200.c Version 0.97 Aug 3 2007 - * * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> * Copyright (C) 2007 Bartlomiej Zolnierkiewicz * @@ -16,19 +14,13 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> -#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/ide.h> #include <linux/pm.h> + #include <asm/io.h> -#include <asm/irq.h> #define SC1200_REV_A 0x00 #define SC1200_REV_B1 0x01 @@ -87,7 +79,7 @@ static const unsigned int sc1200_pio_timings[4][5] = static void sc1200_tunepio(ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = drive->hwif; - struct pci_dev *pdev = hwif->pci_dev; + struct pci_dev *pdev = to_pci_dev(hwif->dev); unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0; pci_read_config_dword(pdev, basereg + 4, &format); @@ -130,73 +122,42 @@ out: static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode) { ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); int unit = drive->select.b.unit; unsigned int reg, timings; unsigned short pci_clock; unsigned int basereg = hwif->channel ? 0x50 : 0x40; + static const u32 udma_timing[3][3] = { + { 0x00921250, 0x00911140, 0x00911030 }, + { 0x00932470, 0x00922260, 0x00922140 }, + { 0x009436a1, 0x00933481, 0x00923261 }, + }; + + static const u32 mwdma_timing[3][3] = { + { 0x00077771, 0x00012121, 0x00002020 }, + { 0x000bbbb2, 0x00024241, 0x00013131 }, + { 0x000ffff3, 0x00035352, 0x00015151 }, + }; + pci_clock = sc1200_get_pci_clock(); /* * Note that each DMA mode has several timings associated with it. * The correct timing depends on the fast PCI clock freq. */ - timings = 0; - switch (mode) { - case XFER_UDMA_0: - switch (pci_clock) { - case PCI_CLK_33: timings = 0x00921250; break; - case PCI_CLK_48: timings = 0x00932470; break; - case PCI_CLK_66: timings = 0x009436a1; break; - } - break; - case XFER_UDMA_1: - switch (pci_clock) { - case PCI_CLK_33: timings = 0x00911140; break; - case PCI_CLK_48: timings = 0x00922260; break; - case PCI_CLK_66: timings = 0x00933481; break; - } - break; - case XFER_UDMA_2: - switch (pci_clock) { - case PCI_CLK_33: timings = 0x00911030; break; - case PCI_CLK_48: timings = 0x00922140; break; - case PCI_CLK_66: timings = 0x00923261; break; - } - break; - case XFER_MW_DMA_0: - switch (pci_clock) { - case PCI_CLK_33: timings = 0x00077771; break; - case PCI_CLK_48: timings = 0x000bbbb2; break; - case PCI_CLK_66: timings = 0x000ffff3; break; - } - break; - case XFER_MW_DMA_1: - switch (pci_clock) { - case PCI_CLK_33: timings = 0x00012121; break; - case PCI_CLK_48: timings = 0x00024241; break; - case PCI_CLK_66: timings = 0x00035352; break; - } - break; - case XFER_MW_DMA_2: - switch (pci_clock) { - case PCI_CLK_33: timings = 0x00002020; break; - case PCI_CLK_48: timings = 0x00013131; break; - case PCI_CLK_66: timings = 0x00015151; break; - } - break; - default: - BUG(); - break; - } + + if (mode >= XFER_UDMA_0) + timings = udma_timing[pci_clock][mode - XFER_UDMA_0]; + else + timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0]; if (unit == 0) { /* are we configuring drive0? */ - pci_read_config_dword(hwif->pci_dev, basereg+4, ®); + pci_read_config_dword(dev, basereg + 4, ®); timings |= reg & 0x80000000; /* preserve PIO format bit */ - pci_write_config_dword(hwif->pci_dev, basereg+4, timings); - } else { - pci_write_config_dword(hwif->pci_dev, basereg+12, timings); - } + pci_write_config_dword(dev, basereg + 4, timings); + } else + pci_write_config_dword(dev, basereg + 12, timings); } /* Replacement for the standard ide_dma_end action in @@ -251,9 +212,9 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) } if (mode != -1) { printk("SC1200: %s: changing (U)DMA mode\n", drive->name); - hwif->dma_off_quietly(drive); - if (ide_set_dma_mode(drive, mode) == 0) - hwif->dma_host_on(drive); + ide_dma_off_quietly(drive); + if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma) + hwif->dma_host_set(drive, 1); return; } @@ -261,66 +222,39 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) } #ifdef CONFIG_PM -static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) -{ - int h; - - for (h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; - if (prev) { - if (hwif == prev) - prev = NULL; // found previous, now look for next match - } else { - if (hwif && hwif->pci_dev == dev) - return hwif; // found next match - } - } - return NULL; // not found -} - -typedef struct sc1200_saved_state_s { - __u32 regs[4]; -} sc1200_saved_state_t; - +struct sc1200_saved_state { + u32 regs[8]; +}; static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) { - ide_hwif_t *hwif = NULL; - printk("SC1200: suspend(%u)\n", state.event); + /* + * we only save state when going from full power to less + */ if (state.event == PM_EVENT_ON) { - // we only save state when going from full power to less - - // - // Loop over all interfaces that are part of this PCI device: - // - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { - sc1200_saved_state_t *ss; - unsigned int basereg, r; - // - // allocate a permanent save area, if not already allocated - // - ss = (sc1200_saved_state_t *)hwif->config_data; - if (ss == NULL) { - ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL); - if (ss == NULL) - return -ENOMEM; - hwif->config_data = (unsigned long)ss; - } - ss = (sc1200_saved_state_t *)hwif->config_data; - // - // Save timing registers: this may be unnecessary if - // BIOS also does it - // - basereg = hwif->channel ? 0x50 : 0x40; - for (r = 0; r < 4; ++r) { - pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); - } + struct sc1200_saved_state *ss; + unsigned int r; + + /* + * allocate a permanent save area, if not already allocated + */ + ss = (struct sc1200_saved_state *)pci_get_drvdata(dev); + if (ss == NULL) { + ss = kmalloc(sizeof(*ss), GFP_KERNEL); + if (ss == NULL) + return -ENOMEM; + pci_set_drvdata(dev, ss); } - } - /* You don't need to iterate over disks -- sysfs should have done that for you already */ + /* + * save timing registers + * (this may be unnecessary if BIOS also does it) + */ + for (r = 0; r < 8; r++) + pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]); + } pci_disable_device(dev); pci_set_power_state(dev, pci_choose_state(dev, state)); @@ -329,30 +263,25 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) static int sc1200_resume (struct pci_dev *dev) { - ide_hwif_t *hwif = NULL; - int i; + struct sc1200_saved_state *ss; + unsigned int r; + int i; i = pci_enable_device(dev); if (i) return i; - // - // loop over all interfaces that are part of this pci device: - // - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { - unsigned int basereg, r; - sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data; - - // - // Restore timing registers: this may be unnecessary if BIOS also does it - // - basereg = hwif->channel ? 0x50 : 0x40; - if (ss != NULL) { - for (r = 0; r < 4; ++r) { - pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]); - } - } + ss = (struct sc1200_saved_state *)pci_get_drvdata(dev); + + /* + * restore timing registers + * (this may be unnecessary if BIOS also does it) + */ + if (ss) { + for (r = 0; r < 8; r++) + pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]); } + return 0; } #endif diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index ebb7132b9b8..238e3e181e8 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -254,19 +254,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed) offset = 0; /* 100MHz */ } - switch (speed) { - case XFER_UDMA_6: - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - idx = speed - XFER_UDMA_0; - break; - default: - return; - } + idx = speed - XFER_UDMA_0; jcactsel = JCACTSELtbl[offset][idx]; if (is_slave) { @@ -606,7 +594,7 @@ static int __devinit init_setup_scc(struct pci_dev *dev, static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); struct scc_ports *ports = pci_get_drvdata(dev); unsigned long dma_base = ports->dma; @@ -632,7 +620,7 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif) hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c; hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40; - hwif->irq = hwif->pci_dev->irq; + hwif->irq = dev->irq; hwif->dma_base = dma_base; hwif->config_data = ports->ctl; hwif->mmio = 1; @@ -648,13 +636,19 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif) static void __devinit init_iops_scc(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); + hwif->hwif_data = NULL; if (pci_get_drvdata(dev) == NULL) return; init_mmio_iops_scc(hwif); } +static u8 __devinit scc_cable_detect(ide_hwif_t *hwif) +{ + return ATA_CBL_PATA80; +} + /** * init_hwif_scc - set up hwif * @hwif: interface to set up @@ -689,8 +683,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif) else hwif->ultra_mask = ATA_UDMA5; /* 100MHz */ - /* we support 80c cable only. */ - hwif->cbl = ATA_CBL_PATA80; + hwif->cable_detect = scc_cable_detect; } #define DECLARE_SCC_DEV(name_str) \ @@ -738,14 +731,12 @@ static void __devexit scc_remove(struct pci_dev *dev) unsigned long dma_size = pci_resource_len(dev, 1); if (hwif->dmatable_cpu) { - pci_free_consistent(hwif->pci_dev, - PRD_ENTRIES * PRD_BYTES, - hwif->dmatable_cpu, - hwif->dmatable_dma); + pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES, + hwif->dmatable_cpu, hwif->dmatable_dma); hwif->dmatable_cpu = NULL; } - ide_unregister(hwif->index); + ide_unregister(hwif->index, 0, 0); hwif->chipset = ide_unknown; iounmap((void*)ports->dma); diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index a7280311357..c11880b0709 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/serverworks.c Version 0.22 Jun 27 2007 - * * Copyright (C) 1998-2000 Michel Aubry * Copyright (C) 1998-2000 Andrzej Krzysztofowicz * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> @@ -33,12 +31,10 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/ioport.h> #include <linux/pci.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> -#include <linux/delay.h> #include <asm/io.h> @@ -67,7 +63,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) static u8 svwks_udma_filter(ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u8 mask = 0; if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) @@ -130,7 +126,7 @@ static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio) static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 }; - struct pci_dev *dev = drive->hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]); @@ -153,7 +149,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) static const u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 }; ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 unit = (drive->select.b.unit & 0x01); u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0; @@ -164,25 +160,12 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) ultra_timing &= ~(0x0F << (4*unit)); ultra_enable &= ~(0x01 << drive->dn); - switch(speed) { - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; - break; - - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - dma_timing |= dma_modes[2]; - ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit)); - ultra_enable |= (0x01 << drive->dn); - default: - break; - } + if (speed >= XFER_UDMA_0) { + dma_timing |= dma_modes[2]; + ultra_timing |= (udma_modes[speed - XFER_UDMA_0] << (4 * unit)); + ultra_enable |= (0x01 << drive->dn); + } else if (speed >= XFER_MW_DMA_0) + dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing); pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing); @@ -300,7 +283,8 @@ static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif) */ static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); + if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && dev->vendor == PCI_VENDOR_ID_SERVERWORKS && (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE || @@ -318,7 +302,8 @@ static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif) */ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); + if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && dev->vendor == PCI_VENDOR_ID_SERVERWORKS && dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) @@ -329,7 +314,7 @@ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif) static u8 __devinit ata66_svwks(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); /* Server Works */ if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS) @@ -353,25 +338,27 @@ static u8 __devinit ata66_svwks(ide_hwif_t *hwif) static void __devinit init_hwif_svwks (ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); + hwif->set_pio_mode = &svwks_set_pio_mode; hwif->set_dma_mode = &svwks_set_dma_mode; hwif->udma_filter = &svwks_udma_filter; - if (!hwif->dma_base) - return; - - if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = ata66_svwks(hwif); - } + if (dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) + hwif->cable_detect = ata66_svwks; } +#define IDE_HFLAGS_SVWKS \ + (IDE_HFLAG_LEGACY_IRQS | \ + IDE_HFLAG_ABUSE_SET_DMA_MODE | \ + IDE_HFLAG_BOOTABLE) + static const struct ide_port_info serverworks_chipsets[] __devinitdata = { { /* 0 */ .name = "SvrWks OSB4", .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = 0x00, /* UDMA is problematic on OSB4 */ @@ -379,7 +366,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = "SvrWks CSB5", .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -387,7 +374,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = "SvrWks CSB6", .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -395,8 +382,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = "SvrWks CSB6", .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE | - IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -404,8 +390,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = "SvrWks HT1000", .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE | - IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -428,7 +413,9 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device d = serverworks_chipsets[idx]; - if (idx == 2 || idx == 3) { + if (idx == 1) + d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX; + else if (idx == 2 || idx == 3) { if ((PCI_FUNC(dev->devfn) & 1) == 0) { if (pci_resource_start(dev, 0) != 0x01f1) d.host_flags &= ~IDE_HFLAG_BOOTABLE; diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index de820aa58cd..054626497be 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -25,8 +25,6 @@ #include <linux/hdreg.h> #include <linux/init.h> #include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> #include <linux/scatterlist.h> @@ -159,6 +157,7 @@ sgiioc4_clearirq(ide_drive_t * drive) } if (intr_reg & 0x02) { + struct pci_dev *dev = to_pci_dev(hwif->dev); /* Error when transferring DMA data on PCI bus */ u32 pci_err_addr_low, pci_err_addr_high, pci_stat_cmd_reg; @@ -167,7 +166,7 @@ sgiioc4_clearirq(ide_drive_t * drive) readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]); pci_err_addr_high = readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4)); - pci_read_config_dword(hwif->pci_dev, PCI_COMMAND, + pci_read_config_dword(dev, PCI_COMMAND, &pci_stat_cmd_reg); printk(KERN_ERR "%s(%s) : PCI Bus Error when doing DMA:" @@ -178,8 +177,7 @@ sgiioc4_clearirq(ide_drive_t * drive) __FUNCTION__, drive->name, pci_err_addr_high, pci_err_addr_low); /* Clear the PCI Error indicator */ - pci_write_config_dword(hwif->pci_dev, PCI_COMMAND, - 0x00000146); + pci_write_config_dword(dev, PCI_COMMAND, 0x00000146); } /* Clear the Interrupt, Error bits on the IOC4 */ @@ -277,21 +275,6 @@ sgiioc4_ide_dma_end(ide_drive_t * drive) return dma_stat; } -static int -sgiioc4_ide_dma_on(ide_drive_t * drive) -{ - drive->using_dma = 1; - - return 0; -} - -static void sgiioc4_dma_off_quietly(ide_drive_t *drive) -{ - drive->using_dma = 0; - - drive->hwif->dma_host_off(drive); -} - static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed) { } @@ -303,13 +286,10 @@ sgiioc4_ide_dma_test_irq(ide_drive_t * drive) return sgiioc4_checkirq(HWIF(drive)); } -static void sgiioc4_dma_host_on(ide_drive_t * drive) +static void sgiioc4_dma_host_set(ide_drive_t *drive, int on) { -} - -static void sgiioc4_dma_host_off(ide_drive_t * drive) -{ - sgiioc4_clearirq(drive); + if (!on) + sgiioc4_clearirq(drive); } static void @@ -352,6 +332,7 @@ sgiioc4_INB(unsigned long port) static int __devinit ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) { + struct pci_dev *dev = to_pci_dev(hwif->dev); void __iomem *virt_dma_base; int num_ports = sizeof (ioc4_dma_regs_t); void *pad; @@ -377,7 +358,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) } hwif->dma_base = (unsigned long) virt_dma_base; - hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, + hwif->dmatable_cpu = pci_alloc_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, &hwif->dmatable_dma); @@ -386,7 +367,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) hwif->sg_max_nents = IOC4_PRD_ENTRIES; - pad = pci_alloc_consistent(hwif->pci_dev, IOC4_IDE_CACHELINE_SIZE, + pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE, (dma_addr_t *) &(hwif->dma_status)); if (pad) { @@ -394,8 +375,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) return 0; } - pci_free_consistent(hwif->pci_dev, - IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, + pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, hwif->dmatable_cpu, hwif->dmatable_dma); printk(KERN_INFO "%s() -- Error! Unable to allocate DMA Maps for drive %s\n", @@ -535,8 +515,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) } use_pio_instead: - pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents, - hwif->sg_dma_direction); + ide_destroy_dmatable(drive); return 0; /* revert to PIO for this request */ } @@ -574,7 +553,6 @@ static void __devinit ide_init_sgiioc4(ide_hwif_t * hwif) { hwif->mmio = 1; - hwif->pio_mask = 0x00; hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */ hwif->set_dma_mode = &sgiioc4_set_dma_mode; hwif->selectproc = NULL;/* Use the default routine to select drive */ @@ -582,7 +560,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->pre_reset = NULL; /* No HBA specific pre_set needed */ hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine, clear interrupts */ - hwif->intrproc = NULL; /* Enable or Disable interrupt from drive */ hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */ hwif->quirkproc = NULL; hwif->busproc = NULL; @@ -592,20 +569,22 @@ ide_init_sgiioc4(ide_hwif_t * hwif) if (hwif->dma_base == 0) return; - hwif->mwdma_mask = ATA_MWDMA2_ONLY; - + hwif->dma_host_set = &sgiioc4_dma_host_set; hwif->dma_setup = &sgiioc4_ide_dma_setup; hwif->dma_start = &sgiioc4_ide_dma_start; hwif->ide_dma_end = &sgiioc4_ide_dma_end; - hwif->ide_dma_on = &sgiioc4_ide_dma_on; - hwif->dma_off_quietly = &sgiioc4_dma_off_quietly; hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq; - hwif->dma_host_on = &sgiioc4_dma_host_on; - hwif->dma_host_off = &sgiioc4_dma_host_off; hwif->dma_lost_irq = &sgiioc4_dma_lost_irq; hwif->dma_timeout = &ide_dma_timeout; } +static const struct ide_port_info sgiioc4_port_info __devinitdata = { + .chipset = ide_pci, + .host_flags = IDE_HFLAG_NO_DMA | /* no SFF-style DMA */ + IDE_HFLAG_NO_AUTOTUNE, + .mwdma_mask = ATA_MWDMA2_ONLY, +}; + static int __devinit sgiioc4_ide_setup_pci_device(struct pci_dev *dev) { @@ -615,6 +594,8 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) ide_hwif_t *hwif; int h; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + hw_regs_t hw; + struct ide_port_info d = sgiioc4_port_info; /* * Find an empty HWIF; if none available, return -ENOMEM. @@ -654,21 +635,15 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) return -ENOMEM; } - if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) { - hw_regs_t hw; + /* Initialize the IO registers */ + memset(&hw, 0, sizeof(hw)); + sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); + hw.irq = dev->irq; + hw.chipset = ide_pci; + hw.dev = &dev->dev; + ide_init_port_hw(hwif, &hw); - /* Initialize the IO registers */ - memset(&hw, 0, sizeof(hw)); - sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); - memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; - } - - hwif->irq = dev->irq; - hwif->chipset = ide_pci; - hwif->pci_dev = dev; - hwif->channel = 0; /* Single Channel chip */ - hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */ + hwif->dev = &dev->dev; /* The IOC4 uses MMIO rather than Port IO. */ default_hwif_mmiops(hwif); @@ -676,15 +651,17 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) /* Initializing chipset IRQ Registers */ writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); - if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) + if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) { printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n", hwif->name, DRV_NAME); + d.mwdma_mask = 0; + } ide_init_sgiioc4(hwif); idx[0] = hwif->index; - if (ide_device_add(idx)) + if (ide_device_add(idx, &d)) return -EIO; return 0; diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 6d99441c605..ef5b39fa042 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/siimage.c Version 1.18 Oct 18 2007 - * * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> * Copyright (C) 2007 MontaVista Software, Inc. @@ -41,7 +39,6 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> @@ -79,7 +76,7 @@ static int pdev_is_sata(struct pci_dev *pdev) static inline int is_sata(ide_hwif_t *hwif) { - return pdev_is_sata(hwif->pci_dev); + return pdev_is_sata(to_pci_dev(hwif->dev)); } /** @@ -140,13 +137,14 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) static u8 sil_pata_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long base = (unsigned long) hwif->hwif_data; u8 mask = 0, scsc = 0; if (hwif->mmio) scsc = hwif->INB(base + 0x4A); else - pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); + pci_read_config_byte(dev, 0x8A, &scsc); if ((scsc & 0x30) == 0x10) /* 133 */ mask = ATA_UDMA6; @@ -219,19 +217,21 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) mode |= (unit ? 0x10 : 0x01); hwif->OUTB(mode, base + addr_mask); } else { - pci_write_config_word(hwif->pci_dev, addr, speedp); - pci_write_config_word(hwif->pci_dev, tfaddr, speedt); - pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); + struct pci_dev *dev = to_pci_dev(hwif->dev); + + pci_write_config_word(dev, addr, speedp); + pci_write_config_word(dev, tfaddr, speedt); + pci_read_config_word(dev, tfaddr - 2, &speedp); speedp &= ~0x200; /* Set IORDY for mode 3 or 4 */ if (pio > 2) speedp |= 0x200; - pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp); + pci_write_config_word(dev, tfaddr - 2, speedp); - pci_read_config_byte(hwif->pci_dev, addr_mask, &mode); + pci_read_config_byte(dev, addr_mask, &mode); mode &= ~(unit ? 0x30 : 0x03); mode |= (unit ? 0x10 : 0x01); - pci_write_config_byte(hwif->pci_dev, addr_mask, mode); + pci_write_config_byte(dev, addr_mask, mode); } } @@ -250,6 +250,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) u16 dma[] = { 0x2208, 0x10C2, 0x10C1 }; ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); u16 ultra = 0, multi = 0; u8 mode = 0, unit = drive->select.b.unit; unsigned long base = (unsigned long)hwif->hwif_data; @@ -266,10 +267,10 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) multi = hwif->INW(ma); ultra = hwif->INW(ua); } else { - pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); - pci_read_config_byte(hwif->pci_dev, addr_mask, &mode); - pci_read_config_word(hwif->pci_dev, ma, &multi); - pci_read_config_word(hwif->pci_dev, ua, &ultra); + pci_read_config_byte(dev, 0x8A, &scsc); + pci_read_config_byte(dev, addr_mask, &mode); + pci_read_config_word(dev, ma, &multi); + pci_read_config_word(dev, ua, &ultra); } mode &= ~((unit) ? 0x30 : 0x03); @@ -278,27 +279,14 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) scsc = is_sata(hwif) ? 1 : scsc; - switch(speed) { - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - multi = dma[speed - XFER_MW_DMA_0]; - mode |= ((unit) ? 0x20 : 0x02); - break; - case XFER_UDMA_6: - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - multi = dma[2]; - ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) : - (ultra5[speed - XFER_UDMA_0])); - mode |= ((unit) ? 0x30 : 0x03); - break; - default: - return; + if (speed >= XFER_UDMA_0) { + multi = dma[2]; + ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] : + ultra5[speed - XFER_UDMA_0]); + mode |= (unit ? 0x30 : 0x03); + } else { + multi = dma[speed - XFER_MW_DMA_0]; + mode |= (unit ? 0x20 : 0x02); } if (hwif->mmio) { @@ -306,9 +294,9 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) hwif->OUTW(multi, ma); hwif->OUTW(ultra, ua); } else { - pci_write_config_byte(hwif->pci_dev, addr_mask, mode); - pci_write_config_word(hwif->pci_dev, ma, multi); - pci_write_config_word(hwif->pci_dev, ua, ultra); + pci_write_config_byte(dev, addr_mask, mode); + pci_write_config_word(dev, ma, multi); + pci_write_config_word(dev, ua, ultra); } } @@ -316,6 +304,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) static int siimage_io_ide_dma_test_irq (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 dma_altstat = 0; unsigned long addr = siimage_selreg(hwif, 1); @@ -324,7 +313,7 @@ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive) return 1; /* return 1 if Device INTR asserted */ - pci_read_config_byte(hwif->pci_dev, addr, &dma_altstat); + pci_read_config_byte(dev, addr, &dma_altstat); if (dma_altstat & 8) return 0; //return 1; return 0; @@ -342,15 +331,18 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long addr = siimage_selreg(hwif, 0x1); + void __iomem *sata_error_addr + = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET]; - if (SATA_ERROR_REG) { + if (sata_error_addr) { unsigned long base = (unsigned long)hwif->hwif_data; - u32 ext_stat = readl((void __iomem *)(base + 0x10)); u8 watchdog = 0; + if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { - u32 sata_error = readl((void __iomem *)SATA_ERROR_REG); - writel(sata_error, (void __iomem *)SATA_ERROR_REG); + u32 sata_error = readl(sata_error_addr); + + writel(sata_error, sata_error_addr); watchdog = (sata_error & 0x00680000) ? 1 : 0; printk(KERN_WARNING "%s: sata_error = 0x%08x, " "watchdog = %d, %s\n", @@ -390,13 +382,14 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) static int sil_sata_busproc(ide_drive_t * drive, int state) { ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); u32 stat_config = 0; unsigned long addr = siimage_selreg(hwif, 0); if (hwif->mmio) stat_config = readl((void __iomem *)addr); else - pci_read_config_dword(hwif->pci_dev, addr, &stat_config); + pci_read_config_dword(dev, addr, &stat_config); switch (state) { case BUSSTATE_ON: @@ -428,13 +421,17 @@ static int sil_sata_busproc(ide_drive_t * drive, int state) static int sil_sata_reset_poll(ide_drive_t *drive) { - if (SATA_STATUS_REG) { - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = drive->hwif; + void __iomem *sata_status_addr + = (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET]; + + if (sata_status_addr) { + /* SATA Status is available only when in MMIO mode */ + u32 sata_stat = readl(sata_status_addr); - /* SATA_STATUS_REG is valid only when in MMIO mode */ - if ((readl((void __iomem *)SATA_STATUS_REG) & 0x03) != 0x03) { + if ((sata_stat & 0x03) != 0x03) { printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", - hwif->name, readl((void __iomem *)SATA_STATUS_REG)); + hwif->name, sata_stat); HWGROUP(drive)->polling = 0; return ide_started; } @@ -460,48 +457,6 @@ static void sil_sata_pre_reset(ide_drive_t *drive) } /** - * siimage_reset - reset a device on an siimage controller - * @drive: drive to reset - * - * Perform a controller level reset fo the device. For - * SATA we must also check the PHY. - */ - -static void siimage_reset (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u8 reset = 0; - unsigned long addr = siimage_selreg(hwif, 0); - - if (hwif->mmio) { - reset = hwif->INB(addr); - hwif->OUTB((reset|0x03), addr); - /* FIXME:posting */ - udelay(25); - hwif->OUTB(reset, addr); - (void) hwif->INB(addr); - } else { - pci_read_config_byte(hwif->pci_dev, addr, &reset); - pci_write_config_byte(hwif->pci_dev, addr, reset|0x03); - udelay(25); - pci_write_config_byte(hwif->pci_dev, addr, reset); - pci_read_config_byte(hwif->pci_dev, addr, &reset); - } - - if (SATA_STATUS_REG) { - /* SATA_STATUS_REG is valid only when in MMIO mode */ - u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG); - printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n", - hwif->name, sata_stat, __FUNCTION__); - if (!(sata_stat)) { - printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", - hwif->name, sata_stat); - drive->failures++; - } - } -} - -/** * proc_reports_siimage - add siimage controller to proc * @dev: PCI device * @clocking: SCSC value @@ -698,7 +653,7 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const ch static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); void *addr = pci_get_drvdata(dev); u8 ch = hwif->channel; hw_regs_t hw; @@ -768,9 +723,6 @@ static int is_dev_seagate_sata(ide_drive_t *drive) const char *s = &drive->id->model[0]; unsigned len; - if (!drive->present) - return 0; - len = strnlen(s, sizeof(drive->id->model)); if ((len > 4) && (!memcmp(s, "ST", 2))) { @@ -785,18 +737,20 @@ static int is_dev_seagate_sata(ide_drive_t *drive) } /** - * siimage_fixup - post probe fixups - * @hwif: interface to fix up + * sil_quirkproc - post probe fixups + * @drive: drive * * Called after drive probe we use this to decide whether the * Seagate fixup must be applied. This used to be in init_iops but * that can occur before we know what drives are present. */ -static void __devinit siimage_fixup(ide_hwif_t *hwif) +static void __devinit sil_quirkproc(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; + /* Try and raise the rqsize */ - if (!is_sata(hwif) || !is_dev_seagate_sata(&hwif->drives[0])) + if (!is_sata(hwif) || !is_dev_seagate_sata(drive)) hwif->rqsize = 128; } @@ -812,12 +766,14 @@ static void __devinit siimage_fixup(ide_hwif_t *hwif) static void __devinit init_iops_siimage(ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); + hwif->hwif_data = NULL; /* Pessimal until we finish probing */ hwif->rqsize = 15; - if (pci_get_drvdata(hwif->pci_dev) == NULL) + if (pci_get_drvdata(dev) == NULL) return; init_mmio_iops_siimage(hwif); @@ -833,11 +789,12 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif) static u8 __devinit ata66_siimage(ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long addr = siimage_selreg(hwif, 0); u8 ata66 = 0; - if (pci_get_drvdata(hwif->pci_dev) == NULL) - pci_read_config_byte(hwif->pci_dev, addr, &ata66); + if (pci_get_drvdata(dev) == NULL) + pci_read_config_byte(dev, addr, &ata66); else ata66 = hwif->INB(addr); @@ -857,9 +814,9 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) { u8 sata = is_sata(hwif); - hwif->resetproc = &siimage_reset; hwif->set_pio_mode = &sil_set_pio_mode; hwif->set_dma_mode = &sil_set_dma_mode; + hwif->quirkproc = &sil_quirkproc; if (sata) { static int first = 1; @@ -876,15 +833,14 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) } else hwif->udma_filter = &sil_pata_udma_filter; + hwif->cable_detect = ata66_siimage; + if (hwif->dma_base == 0) return; if (sata) hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = ata66_siimage(hwif); - if (hwif->mmio) { hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq; } else { @@ -898,7 +854,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) .init_chipset = init_chipset_siimage, \ .init_iops = init_iops_siimage, \ .init_hwif = init_hwif_siimage, \ - .fixup = siimage_fixup, \ .host_flags = IDE_HFLAG_BOOTABLE, \ .pio_mask = ATA_PIO4, \ .mwdma_mask = ATA_MWDMA2, \ diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 6b7bb53acef..512bb4c1fd5 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/sis5513.c Version 0.31 Aug 9, 2007 - * * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer * Copyright (C) 2003 Vojtech Pavlik <vojtech@suse.cz> @@ -49,20 +47,11 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> - -#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/ide.h> -#include <asm/irq.h> - #include "ide-timing.h" /* registers layout and init values are chipset family dependant */ @@ -197,7 +186,7 @@ static char* chipset_capability[] = { static u8 sis_ata133_get_base(ide_drive_t *drive) { - struct pci_dev *dev = drive->hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u32 reg54 = 0; pci_read_config_dword(dev, 0x54, ®54); @@ -207,7 +196,7 @@ static u8 sis_ata133_get_base(ide_drive_t *drive) static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode) { - struct pci_dev *dev = drive->hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u16 t1 = 0; u8 drive_pci = 0x40 + drive->dn * 2; @@ -230,7 +219,7 @@ static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode) static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode) { - struct pci_dev *dev = drive->hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u8 t1, drive_pci = 0x40 + drive->dn * 2; /* timing bits: 7:4 active 3:0 recovery */ @@ -253,7 +242,7 @@ static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode) static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode) { - struct pci_dev *dev = drive->hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u32 t1 = 0; u8 drive_pci = sis_ata133_get_base(drive), clk, idx; @@ -286,7 +275,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode) static void config_drive_art_rwp (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 reg4bh = 0; u8 rw_prefetch = 0; @@ -305,65 +294,61 @@ static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) sis_program_timings(drive, XFER_PIO_0 + pio); } +static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u32 regdw = 0; + u8 drive_pci = sis_ata133_get_base(drive), clk, idx; + + pci_read_config_dword(dev, drive_pci, ®dw); + + regdw |= 0x04; + regdw &= 0xfffff00f; + /* check if ATA133 enable */ + clk = (regdw & 0x08) ? ATA_133 : ATA_100; + idx = mode - XFER_UDMA_0; + regdw |= cycle_time_value[clk][idx] << 4; + regdw |= cvs_time_value[clk][idx] << 8; + + pci_write_config_dword(dev, drive_pci, regdw); +} + +static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family; + + pci_read_config_byte(dev, drive_pci + 1, ®); + + /* force the UDMA bit on if we want to use UDMA */ + reg |= 0x80; + /* clean reg cycle time bits */ + reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]); + /* set reg cycle time bits */ + reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i]; + + pci_write_config_byte(dev, drive_pci + 1, reg); +} + +static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode) +{ + if (chipset_family >= ATA_133) /* ATA_133 */ + sis_ata133_program_udma_timings(drive, mode); + else /* ATA_33/66/100a/100/133a */ + sis_ata33_program_udma_timings(drive, mode); +} + static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - /* Config chip for mode */ - switch(speed) { - case XFER_UDMA_6: - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - if (chipset_family >= ATA_133) { - u32 regdw = 0; - u8 drive_pci = sis_ata133_get_base(drive); - - pci_read_config_dword(dev, drive_pci, ®dw); - regdw |= 0x04; - regdw &= 0xfffff00f; - /* check if ATA133 enable */ - if (regdw & 0x08) { - regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4; - regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8; - } else { - regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4; - regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8; - } - pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); - } else { - u8 drive_pci = 0x40 + drive->dn * 2, reg = 0; - - pci_read_config_byte(dev, drive_pci+1, ®); - /* Force the UDMA bit on if we want to use UDMA */ - reg |= 0x80; - /* clean reg cycle time bits */ - reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family])) - << cycle_time_offset[chipset_family]); - /* set reg cycle time bits */ - reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0] - << cycle_time_offset[chipset_family]; - pci_write_config_byte(dev, drive_pci+1, reg); - } - break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - sis_program_timings(drive, speed); - break; - default: - BUG(); - break; - } + if (speed >= XFER_UDMA_0) + sis_program_udma_timings(drive, speed); + else + sis_program_timings(drive, speed); } static u8 sis5513_ata133_udma_filter(ide_drive_t *drive) { - struct pci_dev *dev = drive->hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u32 regdw = 0; u8 drive_pci = sis_ata133_get_base(drive); @@ -527,13 +512,14 @@ static const struct sis_laptop sis_laptop[] = { /* devid, subvendor, subdev */ { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ { 0x5513, 0x1734, 0x105f }, /* FSC Amilo A1630 */ + { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ /* end marker */ { 0, } }; static u8 __devinit ata66_sis5513(ide_hwif_t *hwif) { - struct pci_dev *pdev = hwif->pci_dev; + struct pci_dev *pdev = to_pci_dev(hwif->dev); const struct sis_laptop *lap = &sis_laptop[0]; u8 ata66 = 0; @@ -548,12 +534,12 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif) if (chipset_family >= ATA_133) { u16 regw = 0; u16 reg_addr = hwif->channel ? 0x52: 0x50; - pci_read_config_word(hwif->pci_dev, reg_addr, ®w); + pci_read_config_word(pdev, reg_addr, ®w); ata66 = (regw & 0x8000) ? 0 : 1; } else if (chipset_family >= ATA_66) { u8 reg48h = 0; u8 mask = hwif->channel ? 0x20 : 0x10; - pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); + pci_read_config_byte(pdev, 0x48, ®48h); ata66 = (reg48h & mask) ? 0 : 1; } @@ -570,13 +556,12 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) if (chipset_family >= ATA_133) hwif->udma_filter = sis5513_ata133_udma_filter; + hwif->cable_detect = ata66_sis5513; + if (hwif->dma_base == 0) return; hwif->ultra_mask = udma_rates[chipset_family]; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = ata66_sis5513(hwif); } static const struct ide_port_info sis5513_chipset __devinitdata = { diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 147d783f752..ee261ae15b6 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/sl82c105.c - * * SL82C105/Winbond 553 IDE driver * * Maintainer unknown. @@ -13,22 +11,17 @@ * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org * * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com> + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz */ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/pci.h> #include <linux/ide.h> #include <asm/io.h> -#include <asm/dma.h> #undef DEBUG @@ -77,7 +70,7 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio) */ static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio) { - struct pci_dev *dev = HWIF(drive)->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); int reg = 0x44 + drive->dn * 4; u16 drv_ctrl; @@ -90,14 +83,8 @@ static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio) drive->drive_data &= 0xffff0000; drive->drive_data |= drv_ctrl; - if (!drive->using_dma) { - /* - * If we are actually using MW DMA, then we can not - * reprogram the interface drive control register. - */ - pci_write_config_word(dev, reg, drv_ctrl); - pci_read_config_word (dev, reg, &drv_ctrl); - } + pci_write_config_word(dev, reg, drv_ctrl); + pci_read_config_word (dev, reg, &drv_ctrl); printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name, ide_xfer_verbose(pio + XFER_PIO_0), @@ -115,33 +102,14 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed) DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n", drive->name, ide_xfer_verbose(speed))); - switch (speed) { - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0]; + drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0]; - /* - * Store the DMA timings so that we can actually program - * them when DMA will be turned on... - */ - drive->drive_data &= 0x0000ffff; - drive->drive_data |= (unsigned long)drv_ctrl << 16; - - /* - * If we are already using DMA, we just reprogram - * the drive control register. - */ - if (drive->using_dma) { - struct pci_dev *dev = HWIF(drive)->pci_dev; - int reg = 0x44 + drive->dn * 4; - - pci_write_config_word(dev, reg, drv_ctrl); - } - break; - default: - return; - } + /* + * Store the DMA timings so that we can actually program + * them when DMA will be turned on... + */ + drive->drive_data &= 0x0000ffff; + drive->drive_data |= (unsigned long)drv_ctrl << 16; } /* @@ -171,7 +139,7 @@ static inline void sl82c105_reset_host(struct pci_dev *dev) static void sl82c105_dma_lost_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; u8 dma_cmd; @@ -208,7 +176,12 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive) static void sl82c105_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); + int reg = 0x44 + drive->dn * 4; + + DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name)); + + pci_write_config_word(dev, reg, drive->drive_data >> 16); sl82c105_reset_host(dev); ide_dma_start(drive); @@ -216,80 +189,43 @@ static void sl82c105_dma_start(ide_drive_t *drive) static void sl82c105_dma_timeout(ide_drive_t *drive) { + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name)); - sl82c105_reset_host(HWIF(drive)->pci_dev); + sl82c105_reset_host(dev); ide_dma_timeout(drive); } -static int sl82c105_ide_dma_on(ide_drive_t *drive) +static int sl82c105_dma_end(ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; - int rc, reg = 0x44 + drive->dn * 4; - - DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name)); - - rc = __ide_dma_on(drive); - if (rc == 0) { - pci_write_config_word(dev, reg, drive->drive_data >> 16); - - printk(KERN_INFO "%s: DMA enabled\n", drive->name); - } - return rc; -} - -static void sl82c105_dma_off_quietly(ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); int reg = 0x44 + drive->dn * 4; + int ret; - DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name)); + DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name)); - pci_write_config_word(dev, reg, drive->drive_data); + ret = __ide_dma_end(drive); - ide_dma_off_quietly(drive); -} + pci_write_config_word(dev, reg, drive->drive_data); -/* - * Ok, that is nasty, but we must make sure the DMA timings - * won't be used for a PIO access. The solution here is - * to make sure the 16 bits mode is diabled on the channel - * when DMA is enabled, thus causing the chip to use PIO0 - * timings for those operations. - */ -static void sl82c105_selectproc(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u32 val, old, mask; - - //DBG(("sl82c105_selectproc(drive:%s)\n", drive->name)); - - mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16; - old = val = (u32)pci_get_drvdata(dev); - if (drive->using_dma) - val &= ~mask; - else - val |= mask; - if (old != val) { - pci_write_config_dword(dev, 0x40, val); - pci_set_drvdata(dev, (void *)val); - } + return ret; } /* * ATA reset will clear the 16 bits mode in the control - * register, we need to update our cache + * register, we need to reprogram it */ static void sl82c105_resetproc(ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u32 val; DBG(("sl82c105_resetproc(drive:%s)\n", drive->name)); pci_read_config_dword(dev, 0x40, &val); - pci_set_drvdata(dev, (void *)val); + val |= (CTRL_P1F16 | CTRL_P0F16); + pci_write_config_dword(dev, 0x40, val); } /* @@ -342,7 +278,6 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c pci_read_config_dword(dev, 0x40, &val); val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; pci_write_config_dword(dev, 0x40, val); - pci_set_drvdata(dev, (void *)val); return dev->irq; } @@ -352,19 +287,19 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c */ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned int rev; DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); hwif->set_pio_mode = &sl82c105_set_pio_mode; hwif->set_dma_mode = &sl82c105_set_dma_mode; - hwif->selectproc = &sl82c105_selectproc; hwif->resetproc = &sl82c105_resetproc; if (!hwif->dma_base) return; - rev = sl82c105_bridge_revision(hwif->pci_dev); + rev = sl82c105_bridge_revision(dev); if (rev <= 5) { /* * Never ever EVER under any circumstances enable @@ -377,10 +312,9 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) hwif->mwdma_mask = ATA_MWDMA2; - hwif->ide_dma_on = &sl82c105_ide_dma_on; - hwif->dma_off_quietly = &sl82c105_dma_off_quietly; hwif->dma_lost_irq = &sl82c105_dma_lost_irq; hwif->dma_start = &sl82c105_dma_start; + hwif->ide_dma_end = &sl82c105_dma_end; hwif->dma_timeout = &sl82c105_dma_timeout; if (hwif->mate) diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index eb4445b229e..65f4c2ffaa5 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/pci/slc90e66.c Version 0.19 Sep 24, 2007 - * * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com> * @@ -12,21 +10,17 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/ioport.h> #include <linux/pci.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/delay.h> #include <linux/init.h> -#include <asm/io.h> - static DEFINE_SPINLOCK(slc90e66_lock); static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); int is_slave = drive->dn & 1; int master_port = hwif->channel ? 0x42 : 0x40; int slave_port = 0x44; @@ -79,7 +73,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 maslave = hwif->channel ? 0x42 : 0x40; int sitre = 0, a_speed = 7 << (drive->dn * 4); int u_speed = 0, u_flag = 1 << drive->dn; @@ -91,19 +85,9 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_read_config_word(dev, 0x48, ®48); pci_read_config_word(dev, 0x4a, ®4a); - switch(speed) { - case XFER_UDMA_4: u_speed = 4 << (drive->dn * 4); break; - case XFER_UDMA_3: u_speed = 3 << (drive->dn * 4); break; - case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_SW_DMA_2: break; - default: return; - } - if (speed >= XFER_UDMA_0) { + u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4); + if (!(reg48 & u_flag)) pci_write_config_word(dev, 0x48, reg48|u_flag); /* FIXME: (reg4a & a_speed) ? */ @@ -130,22 +114,23 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed) } } -static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) +static u8 __devinit slc90e66_cable_detect(ide_hwif_t *hwif) { - u8 reg47 = 0; - u8 mask = hwif->channel ? 0x01 : 0x02; /* bit0:Primary */ + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02; - hwif->set_pio_mode = &slc90e66_set_pio_mode; - hwif->set_dma_mode = &slc90e66_set_dma_mode; + pci_read_config_byte(dev, 0x47, ®47); - pci_read_config_byte(hwif->pci_dev, 0x47, ®47); + /* bit[0(1)]: 0:80, 1:40 */ + return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} - if (hwif->dma_base == 0) - return; +static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif) +{ + hwif->set_pio_mode = &slc90e66_set_pio_mode; + hwif->set_dma_mode = &slc90e66_set_dma_mode; - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - /* bit[0(1)]: 0:80, 1:40 */ - hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; + hwif->cable_detect = slc90e66_cable_detect; } static const struct ide_port_info slc90e66_chipset __devinitdata = { diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index a66ebd14664..2ef2ed2f2b3 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -1,6 +1,4 @@ /* - * drivers/ide/pci/tc86c001.c Version 1.01 Sep 5, 2007 - * * Copyright (C) 2002 Toshiba Corporation * Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com> * @@ -162,9 +160,23 @@ static int tc86c001_busproc(ide_drive_t *drive, int state) return 0; } +static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long sc_base = pci_resource_start(dev, 5); + u16 scr1 = inw(sc_base + 0x00); + + /* + * System Control 1 Register bit 13 (PDIAGN): + * 0=80-pin cable, 1=40-pin cable + */ + return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) { - unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5); + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long sc_base = pci_resource_start(dev, 5); u16 scr1 = inw(sc_base + 0x00); /* System Control 1 Register bit 15 (Soft Reset) set */ @@ -184,6 +196,8 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) hwif->busproc = &tc86c001_busproc; + hwif->cable_detect = tc86c001_cable_detect; + if (!hwif->dma_base) return; @@ -197,15 +211,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) hwif->rqsize = 0xffff; hwif->dma_start = &tc86c001_dma_start; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) { - /* - * System Control 1 Register bit 13 (PDIAGN): - * 0=80-pin cable, 1=40-pin cable - */ - scr1 = inw(sc_base + 0x00); - hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; - } } static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev, @@ -222,7 +227,8 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = { .name = "TC86C001", .init_chipset = init_chipset_tc86c001, .init_hwif = init_hwif_tc86c001, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD, + .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD | + IDE_HFLAG_ABUSE_SET_DMA_MODE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index a227c41d23a..a67d02a3f96 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -1,6 +1,4 @@ /* - * triflex.c - * * IDE Chipset driver for the Compaq TriFlex IDE controller. * * Known to work with the Compaq Workstation 5x00 series. @@ -30,11 +28,6 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/pci.h> #include <linux/ide.h> @@ -43,7 +36,7 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 channel_offset = hwif->channel ? 0x74 : 0x70; u16 timing = 0; u32 triflex_timings = 0; @@ -81,8 +74,6 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed) case XFER_PIO_0: timing = 0x0808; break; - default: - return; } triflex_timings &= ~(0xFFFF << (16 * unit)); diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index 5011ba22e36..de750f7a43e 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -1,7 +1,7 @@ /* - * linux/drivers/ide/pci/trm290.c Version 1.02 Mar. 18, 2000 - * * Copyright (c) 1997-1998 Mark Lord + * Copyright (c) 2007 MontaVista Software, Inc. <source@mvista.com> + * * May be copied or modified under the terms of the GNU General Public License * * June 22, 2004 - get rid of check_region @@ -131,14 +131,12 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/mm.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/blkdev.h> #include <linux/init.h> #include <linux/hdreg.h> #include <linux/pci.h> -#include <linux/delay.h> #include <linux/ide.h> #include <asm/io.h> @@ -177,15 +175,12 @@ static void trm290_selectproc (ide_drive_t *drive) trm290_prepare_drive(drive, drive->using_dma); } -static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) +static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command) { - BUG_ON(HWGROUP(drive)->handler != NULL); /* paranoia check */ - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - /* issue cmd to drive */ - outb(command, IDE_COMMAND_REG); + ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL); } -static int trm290_ide_dma_setup(ide_drive_t *drive) +static int trm290_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->hwgroup->rq; @@ -208,58 +203,73 @@ static int trm290_ide_dma_setup(ide_drive_t *drive) } /* select DMA xfer */ trm290_prepare_drive(drive, 1); - outl(hwif->dmatable_dma | rw, hwif->dma_command); + outl(hwif->dmatable_dma | rw, hwif->dma_base); drive->waiting_for_dma = 1; /* start DMA */ - outw((count * 2) - 1, hwif->dma_status); + outw(count * 2 - 1, hwif->dma_base + 2); return 0; } -static void trm290_ide_dma_start(ide_drive_t *drive) +static void trm290_dma_start(ide_drive_t *drive) { } static int trm290_ide_dma_end (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - u16 status = 0; + u16 status; drive->waiting_for_dma = 0; /* purge DMA mappings */ ide_destroy_dmatable(drive); - status = inw(hwif->dma_status); - return (status != 0x00ff); + status = inw(HWIF(drive)->dma_base + 2); + return status != 0x00ff; } static int trm290_ide_dma_test_irq (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - u16 status = 0; + u16 status; - status = inw(hwif->dma_status); - return (status == 0x00ff); + status = inw(HWIF(drive)->dma_base + 2); + return status == 0x00ff; +} + +static void trm290_dma_host_set(ide_drive_t *drive, int on) +{ } -/* - * Invoked from ide-dma.c at boot time. - */ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) { - unsigned int cfgbase = 0; + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned int cfg_base = pci_resource_start(dev, 4); unsigned long flags; u8 reg = 0; - struct pci_dev *dev = hwif->pci_dev; - - cfgbase = pci_resource_start(dev, 4); - if ((dev->class & 5) && cfgbase) { - hwif->config_data = cfgbase; - printk(KERN_INFO "TRM290: chip config base at 0x%04lx\n", - hwif->config_data); - } else { - hwif->config_data = 0x3df0; - printk(KERN_INFO "TRM290: using default config base at 0x%04lx\n", - hwif->config_data); + + if ((dev->class & 5) && cfg_base) + printk(KERN_INFO "TRM290: chip"); + else { + cfg_base = 0x3df0; + printk(KERN_INFO "TRM290: using default"); + } + printk(KERN_CONT " config base at 0x%04x\n", cfg_base); + hwif->config_data = cfg_base; + hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0); + + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx", + hwif->name, hwif->dma_base, hwif->dma_base + 3); + + if (!request_region(hwif->dma_base, 4, hwif->name)) { + printk(KERN_CONT " -- Error, ports in use.\n"); + return; + } + + hwif->dmatable_cpu = pci_alloc_consistent(dev, PRD_ENTRIES * PRD_BYTES, + &hwif->dmatable_dma); + if (!hwif->dmatable_cpu) { + printk(KERN_CONT " -- Error, unable to allocate DMA table.\n"); + release_region(hwif->dma_base, 4); + return; } + printk(KERN_CONT "\n"); local_irq_save(flags); /* put config reg into first byte of hwif->select_data */ @@ -274,20 +284,19 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) outb(reg, hwif->config_data + 3); local_irq_restore(flags); - if ((reg & 0x10)) + if (reg & 0x10) /* legacy mode */ hwif->irq = hwif->channel ? 15 : 14; else if (!hwif->irq && hwif->mate && hwif->mate->irq) /* sharing IRQ with mate */ hwif->irq = hwif->mate->irq; - ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); - - hwif->dma_setup = &trm290_ide_dma_setup; - hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd; - hwif->dma_start = &trm290_ide_dma_start; - hwif->ide_dma_end = &trm290_ide_dma_end; - hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; + hwif->dma_host_set = &trm290_dma_host_set; + hwif->dma_setup = &trm290_dma_setup; + hwif->dma_exec_cmd = &trm290_dma_exec_cmd; + hwif->dma_start = &trm290_dma_start; + hwif->ide_dma_end = &trm290_ide_dma_end; + hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; hwif->selectproc = &trm290_selectproc; #if 1 diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index a0d3c16b68e..f3f79f80581 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -1,7 +1,4 @@ /* - * - * Version 3.50 - * * VIA IDE driver for Linux. Supported southbridges: * * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, @@ -29,15 +26,11 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/ide.h> #include <linux/dmi.h> -#include <asm/io.h> - #ifdef CONFIG_PPC_CHRP #include <asm/processor.h> #endif @@ -121,8 +114,8 @@ struct via82cxxx_dev static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) { - struct pci_dev *dev = hwif->pci_dev; - struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct via82cxxx_dev *vdev = pci_get_drvdata(dev); u8 t; if (~vdev->via_config->flags & VIA_BAD_AST) { @@ -159,8 +152,10 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) static void via_set_drive(ide_drive_t *drive, const u8 speed) { - ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1); - struct via82cxxx_dev *vdev = pci_get_drvdata(drive->hwif->pci_dev); + ide_hwif_t *hwif = drive->hwif; + ide_drive_t *peer = hwif->drives + (~drive->dn & 1); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct via82cxxx_dev *vdev = pci_get_drvdata(dev); struct ide_timing t, p; unsigned int T, UT; @@ -408,7 +403,7 @@ static int via_cable_override(struct pci_dev *pdev) static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif) { - struct pci_dev *pdev = hwif->pci_dev; + struct pci_dev *pdev = to_pci_dev(hwif->dev); struct via82cxxx_dev *vdev = pci_get_drvdata(pdev); if (via_cable_override(pdev)) @@ -425,11 +420,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) hwif->set_pio_mode = &via_set_pio_mode; hwif->set_dma_mode = &via_set_drive; - if (!hwif->dma_base) - return; - - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = via82cxxx_cable_detect(hwif); + hwif->cable_detect = via82cxxx_cable_detect; } static const struct ide_port_info via82cxxx_chipset __devinitdata = { @@ -439,6 +430,7 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = { .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | IDE_HFLAG_PIO_NO_DOWNGRADE | + IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_POST_SET_MODE | IDE_HFLAG_IO_32BIT | IDE_HFLAG_BOOTABLE, diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile new file mode 100644 index 00000000000..65af5848b28 --- /dev/null +++ b/drivers/ide/ppc/Makefile @@ -0,0 +1,3 @@ + +obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o +obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += mpc8xx.o diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c index 5f0da35ab5a..06190b1c4ec 100644 --- a/drivers/ide/ppc/mpc8xx.c +++ b/drivers/ide/ppc/mpc8xx.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/ppc/ide-m8xx.c - * * Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de * Modified for direct IDE interface * by Thomas Lange, thomas@corelatus.com @@ -838,3 +836,21 @@ void m8xx_ide_init(void) ppc_ide_md.default_io_base = m8xx_ide_default_io_base; ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; } + +static int __init mpc8xx_ide_probe(void) +{ + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + +#ifdef IDE0_BASE_OFFSET + idx[0] = 0; +#ifdef IDE1_BASE_OFFSET + idx[1] = 1; +#endif +#endif + + ide_device_add(idx, NULL); + + return 0; +} + +module_init(mpc8xx_ide_probe); diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 816b5311dad..12ac3bfb4f9 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1,7 +1,6 @@ /* - * linux/drivers/ide/ppc/pmac.c - * * Support for IDE interfaces on PowerMacs. + * * These IDE interfaces are memory-mapped and have a DBDMA channel * for doing DMA. * @@ -413,7 +412,7 @@ kauai_lookup_timing(struct kauai_timing* table, int cycle_time) */ #define IDE_WAKEUP_DELAY (1*HZ) -static void pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif); +static int pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif); static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq); static void pmac_ide_selectproc(ide_drive_t *drive); static void pmac_ide_kauai_selectproc(ide_drive_t *drive); @@ -438,13 +437,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw, if (data_port == pmac_ide[ix].regbase) break; - if (ix >= MAX_HWIFS) { - /* Probably a PCI interface... */ - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i) - hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET; - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - return; - } + if (ix >= MAX_HWIFS) + return; /* not an IDE PMAC interface */ for (i = 0; i < 8; ++i) hw->io_ports[i] = data_port + i * 0x10; @@ -833,38 +827,20 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed) tl[0] = *timings; tl[1] = *timings2; - switch(speed) { #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - case XFER_UDMA_6: - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - if (pmif->kind == controller_kl_ata4) - ret = set_timings_udma_ata4(&tl[0], speed); - else if (pmif->kind == controller_un_ata6 - || pmif->kind == controller_k2_ata6) - ret = set_timings_udma_ata6(&tl[0], &tl[1], speed); - else if (pmif->kind == controller_sh_ata6) - ret = set_timings_udma_shasta(&tl[0], &tl[1], speed); - else - ret = 1; - break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed); - break; - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - return; + if (speed >= XFER_UDMA_0) { + if (pmif->kind == controller_kl_ata4) + ret = set_timings_udma_ata4(&tl[0], speed); + else if (pmif->kind == controller_un_ata6 + || pmif->kind == controller_k2_ata6) + ret = set_timings_udma_ata6(&tl[0], &tl[1], speed); + else if (pmif->kind == controller_sh_ata6) + ret = set_timings_udma_shasta(&tl[0], &tl[1], speed); + else + ret = -1; + } else + set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - default: - ret = 1; - } if (ret) return; @@ -1027,6 +1003,17 @@ pmac_ide_do_resume(ide_hwif_t *hwif) return 0; } +static const struct ide_port_info pmac_port_info = { + .chipset = ide_pmac, + .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | + IDE_HFLAG_PIO_NO_DOWNGRADE | + IDE_HFLAG_POST_SET_MODE | + IDE_HFLAG_NO_DMA | /* no SFF-style DMA */ + IDE_HFLAG_UNMASK_IRQS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, +}; + /* * Setup, register & probe an IDE channel driven by this driver, this is * called by one of the 2 probe functions (macio or PCI). Note that a channel @@ -1034,30 +1021,34 @@ pmac_ide_do_resume(ide_hwif_t *hwif) * (it is kept in 2.4). This introduce an interface numbering change on some * rare machines unfortunately, but it's better this way. */ -static int -pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) +static int __devinit +pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) { struct device_node *np = pmif->node; const int *bidp; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; - hw_regs_t hw; + struct ide_port_info d = pmac_port_info; pmif->cable_80 = 0; pmif->broken_dma = pmif->broken_dma_warn = 0; - if (of_device_is_compatible(np, "shasta-ata")) + if (of_device_is_compatible(np, "shasta-ata")) { pmif->kind = controller_sh_ata6; - else if (of_device_is_compatible(np, "kauai-ata")) + d.udma_mask = ATA_UDMA6; + } else if (of_device_is_compatible(np, "kauai-ata")) { pmif->kind = controller_un_ata6; - else if (of_device_is_compatible(np, "K2-UATA")) + d.udma_mask = ATA_UDMA5; + } else if (of_device_is_compatible(np, "K2-UATA")) { pmif->kind = controller_k2_ata6; - else if (of_device_is_compatible(np, "keylargo-ata")) { - if (strcmp(np->name, "ata-4") == 0) + d.udma_mask = ATA_UDMA5; + } else if (of_device_is_compatible(np, "keylargo-ata")) { + if (strcmp(np->name, "ata-4") == 0) { pmif->kind = controller_kl_ata4; - else + d.udma_mask = ATA_UDMA4; + } else pmif->kind = controller_kl_ata3; - } else if (of_device_is_compatible(np, "heathrow-ata")) + } else if (of_device_is_compatible(np, "heathrow-ata")) { pmif->kind = controller_heathrow; - else { + } else { pmif->kind = controller_ohare; pmif->broken_dma = 1; } @@ -1126,20 +1117,10 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) /* Tell common code _not_ to mess with resources */ hwif->mmio = 1; hwif->hwif_data = pmif; - memset(&hw, 0, sizeof(hw)); - pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, &hwif->irq); - memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); - hwif->chipset = ide_pmac; - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay; + ide_init_port_hw(hwif, hw); + hwif->noprobe = pmif->mediabay; hwif->hold = pmif->mediabay; hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40; - hwif->drives[0].unmask = 1; - hwif->drives[1].unmask = 1; - hwif->drives[0].autotune = IDE_TUNE_AUTO; - hwif->drives[1].autotune = IDE_TUNE_AUTO; - hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | - IDE_HFLAG_POST_SET_MODE; - hwif->pio_mask = ATA_PIO4; hwif->set_pio_mode = pmac_ide_set_pio_mode; if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6 @@ -1158,17 +1139,17 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->noprobe = 0; #endif /* CONFIG_PMAC_MEDIABAY */ - hwif->sg_max_nents = MAX_DCMDS; - #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + if (pmif->cable_80 == 0) + d.udma_mask &= ATA_UDMA2; /* has a DBDMA controller channel */ - if (pmif->dma_regs) - pmac_ide_setup_dma(pmif, hwif); -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + if (pmif->dma_regs == 0 || pmac_ide_setup_dma(pmif, hwif) < 0) +#endif + d.udma_mask = d.mwdma_mask = 0; idx[0] = hwif->index; - ide_device_add(idx); + ide_device_add(idx, &d); return 0; } @@ -1185,6 +1166,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) ide_hwif_t *hwif; pmac_ide_hwif_t *pmif; int i, rc; + hw_regs_t hw; i = 0; while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0 @@ -1226,8 +1208,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) base = ioremap(macio_resource_start(mdev, 0), 0x400); regbase = (unsigned long) base; - hwif->pci_dev = mdev->bus->pdev; - hwif->gendev.parent = &mdev->ofdev.dev; + hwif->dev = &mdev->bus->pdev->dev; pmif->mdev = mdev; pmif->node = mdev->ofdev.node; @@ -1245,17 +1226,22 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ dev_set_drvdata(&mdev->ofdev.dev, hwif); - rc = pmac_ide_setup_device(pmif, hwif); + memset(&hw, 0, sizeof(hw)); + pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL); + hw.irq = irq; + hw.dev = &mdev->ofdev.dev; + + rc = pmac_ide_setup_device(pmif, hwif, &hw); if (rc != 0) { /* The inteface is released to the common IDE layer */ dev_set_drvdata(&mdev->ofdev.dev, NULL); iounmap(base); - if (pmif->dma_regs) + if (pmif->dma_regs) { iounmap(pmif->dma_regs); + macio_release_resource(mdev, 1); + } memset(pmif, 0, sizeof(*pmif)); macio_release_resource(mdev, 0); - if (pmif->dma_regs) - macio_release_resource(mdev, 1); } return rc; @@ -1304,6 +1290,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) void __iomem *base; unsigned long rbase, rlen; int i, rc; + hw_regs_t hw; np = pci_device_to_OF_node(pdev); if (np == NULL) { @@ -1336,8 +1323,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) return -ENXIO; } - hwif->pci_dev = pdev; - hwif->gendev.parent = &pdev->dev; + hwif->dev = &pdev->dev; pmif->mdev = NULL; pmif->node = np; @@ -1354,7 +1340,12 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, hwif); - rc = pmac_ide_setup_device(pmif, hwif); + memset(&hw, 0, sizeof(hw)); + pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL); + hw.irq = pdev->irq; + hw.dev = &pdev->dev; + + rc = pmac_ide_setup_device(pmif, hwif, &hw); if (rc != 0) { /* The inteface is released to the common IDE layer */ pci_set_drvdata(pdev, NULL); @@ -1512,7 +1503,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) { if (pmif->broken_dma_warn == 0) { - printk(KERN_WARNING "%s: DMA on non aligned address," + printk(KERN_WARNING "%s: DMA on non aligned address, " "switching to PIO on Ohare chipset\n", drive->name); pmif->broken_dma_warn = 1; } @@ -1552,11 +1543,10 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) } printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); - use_pio_instead: - pci_unmap_sg(hwif->pci_dev, - hwif->sg_table, - hwif->sg_nents, - hwif->sg_dma_direction); + +use_pio_instead: + ide_destroy_dmatable(drive); + return 0; /* revert to PIO for this request */ } @@ -1565,12 +1555,9 @@ static void pmac_ide_destroy_dmatable (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = HWIF(drive)->pci_dev; - struct scatterlist *sg = hwif->sg_table; - int nents = hwif->sg_nents; - if (nents) { - pci_unmap_sg(dev, sg, nents, hwif->sg_dma_direction); + if (hwif->sg_nents) { + ide_destroy_dmatable(drive); hwif->sg_nents = 0; } } @@ -1720,11 +1707,7 @@ pmac_ide_dma_test_irq (ide_drive_t *drive) return 1; } -static void pmac_ide_dma_host_off(ide_drive_t *drive) -{ -} - -static void pmac_ide_dma_host_on(ide_drive_t *drive) +static void pmac_ide_dma_host_set(ide_drive_t *drive, int on) { } @@ -1747,64 +1730,44 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive) * Allocate the data structures needed for using DMA with an interface * and fill the proper list of functions pointers */ -static void __init -pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) +static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); + /* We won't need pci_dev if we switch to generic consistent * DMA routines ... */ - if (hwif->pci_dev == NULL) - return; + if (dev == NULL) + return -ENODEV; /* * Allocate space for the DBDMA commands. * The +2 is +1 for the stop command and +1 to allow for * aligning the start address to a multiple of 16 bytes. */ pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent( - hwif->pci_dev, + dev, (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), &hwif->dmatable_dma); if (pmif->dma_table_cpu == NULL) { printk(KERN_ERR "%s: unable to allocate DMA command list\n", hwif->name); - return; + return -ENOMEM; } - hwif->dma_off_quietly = &ide_dma_off_quietly; - hwif->ide_dma_on = &__ide_dma_on; + hwif->sg_max_nents = MAX_DCMDS; + + hwif->dma_host_set = &pmac_ide_dma_host_set; hwif->dma_setup = &pmac_ide_dma_setup; hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd; hwif->dma_start = &pmac_ide_dma_start; hwif->ide_dma_end = &pmac_ide_dma_end; hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq; - hwif->dma_host_off = &pmac_ide_dma_host_off; - hwif->dma_host_on = &pmac_ide_dma_host_on; hwif->dma_timeout = &ide_dma_timeout; hwif->dma_lost_irq = &pmac_ide_dma_lost_irq; - switch(pmif->kind) { - case controller_sh_ata6: - hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x00; - break; - case controller_un_ata6: - case controller_k2_ata6: - hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x00; - break; - case controller_kl_ata4: - hwif->ultra_mask = pmif->cable_80 ? 0x1f : 0x07; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x00; - break; - default: - hwif->ultra_mask = 0x00; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x00; - break; - } + return 0; } #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + +module_init(pmac_ide_probe); diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 02d14bf85ab..634e3f6a960 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -1,17 +1,11 @@ /* - * linux/drivers/ide/setup-pci.c Version 1.10 2002/08/19 + * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> + * Copyright (C) 1995-1998 Mark Lord + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz * - * Copyright (c) 1998-2000 Andre Hedrick <andre@linux-ide.org> - * - * Copyright (c) 1995-1998 Mark Lord * May be copied or modified under the terms of the GNU General Public License */ -/* - * This module provides support for automatic detection and - * configuration of all PCI IDE interfaces present in a system. - */ - #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -145,6 +139,16 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) } #ifdef CONFIG_BLK_DEV_IDEDMA_PCI +static void ide_pci_clear_simplex(unsigned long dma_base, const char *name) +{ + u8 dma_stat = inb(dma_base + 2); + + outb(dma_stat & 0x60, dma_base + 2); + dma_stat = inb(dma_base + 2); + if (dma_stat & 0x80) + printk(KERN_INFO "%s: simplex device: DMA forced\n", name); +} + /** * ide_get_or_set_dma_base - setup BMIBA * @d: IDE port info @@ -157,8 +161,9 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif) { - unsigned long dma_base = 0; - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long dma_base = 0; + u8 dma_stat = 0; if (hwif->mmio) return hwif->dma_base; @@ -170,57 +175,39 @@ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_ dma_base = pci_resource_start(dev, baridx); - if (dma_base == 0) + if (dma_base == 0) { printk(KERN_ERR "%s: DMA base is invalid\n", d->name); + return 0; + } } - if ((d->host_flags & IDE_HFLAG_CS5520) == 0 && dma_base) { - u8 simplex_stat = 0; - dma_base += hwif->channel ? 8 : 0; - - switch(dev->device) { - case PCI_DEVICE_ID_AL_M5219: - case PCI_DEVICE_ID_AL_M5229: - case PCI_DEVICE_ID_AMD_VIPER_7409: - case PCI_DEVICE_ID_CMD_643: - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - case PCI_DEVICE_ID_REVOLUTION: - simplex_stat = inb(dma_base + 2); - outb(simplex_stat & 0x60, dma_base + 2); - simplex_stat = inb(dma_base + 2); - if (simplex_stat & 0x80) { - printk(KERN_INFO "%s: simplex device: " - "DMA forced\n", - d->name); - } - break; - default: - /* - * If the device claims "simplex" DMA, - * this means only one of the two interfaces - * can be trusted with DMA at any point in time. - * So we should enable DMA only on one of the - * two interfaces. - */ - simplex_stat = hwif->INB(dma_base + 2); - if (simplex_stat & 0x80) { - /* simplex device? */ -/* - * At this point we haven't probed the drives so we can't make the - * appropriate decision. Really we should defer this problem - * until we tune the drive then try to grab DMA ownership if we want - * to be the DMA end. This has to be become dynamic to handle hot - * plug. - */ - if (hwif->mate && hwif->mate->dma_base) { - printk(KERN_INFO "%s: simplex device: " - "DMA disabled\n", - d->name); - dma_base = 0; - } - } - } + if (hwif->channel) + dma_base += 8; + + if (d->host_flags & IDE_HFLAG_CS5520) + goto out; + + if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) { + ide_pci_clear_simplex(dma_base, d->name); + goto out; } + + /* + * If the device claims "simplex" DMA, this means that only one of + * the two interfaces can be trusted with DMA at any point in time + * (so we should enable DMA only on one of the two interfaces). + * + * FIXME: At this point we haven't probed the drives so we can't make + * the appropriate decision. Really we should defer this problem until + * we tune the drive then try to grab DMA ownership if we want to be + * the DMA end. This has to be become dynamic to handle hot-plug. + */ + dma_stat = hwif->INB(dma_base + 2); + if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) { + printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name); + dma_base = 0; + } +out: return dma_base; } #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ @@ -241,7 +228,9 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); * @d: IDE port info * * Enable the IDE PCI device. We attempt to enable the device in full - * but if that fails then we only need BAR4 so we will enable that. + * but if that fails then we only need IO space. The PCI code should + * have setup the proper resources for us already for controllers in + * legacy mode. * * Returns zero on success or an error code */ @@ -251,7 +240,7 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) int ret; if (pci_enable_device(dev)) { - ret = pci_enable_device_bars(dev, 1 << 4); + ret = pci_enable_device_io(dev); if (ret < 0) { printk(KERN_WARNING "%s: (ide_setup_pci_device:) " "Could not enable device.\n", d->name); @@ -350,7 +339,8 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * * ide_hwif_configure - configure an IDE interface * @dev: PCI device holding interface * @d: IDE port info - * @mate: Paired interface if any + * @port: port number + * @irq: PCI IRQ * * Perform the initial set up for the hardware interface structure. This * is done per interface port rather than per PCI device. There may be @@ -359,11 +349,15 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * * Returns the new hardware interface structure, or NULL on a failure */ -static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *mate, int port, int irq) +static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, + const struct ide_port_info *d, + unsigned int port, int irq) { unsigned long ctl = 0, base = 0; ide_hwif_t *hwif; u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0; + u8 oldnoprobe = 0; + struct hw_regs_s hw; if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) { /* Possibly we should fail if these checks report true */ @@ -386,47 +380,41 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port } if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL) return NULL; /* no room in ide_hwifs[] */ - if (hwif->io_ports[IDE_DATA_OFFSET] != base || - hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) { - hw_regs_t hw; - - memset(&hw, 0, sizeof(hw)); -#ifndef CONFIG_IDE_ARCH_OBSOLETE_INIT - ide_std_init_ports(&hw, base, ctl | 2); -#else - ide_init_hwif_ports(&hw, base, ctl | 2, NULL); -#endif - memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; - } - hwif->chipset = d->chipset ? d->chipset : ide_pci; - hwif->pci_dev = dev; + + memset(&hw, 0, sizeof(hw)); + hw.irq = hwif->irq ? hwif->irq : irq; + hw.dev = &dev->dev; + hw.chipset = d->chipset ? d->chipset : ide_pci; + ide_std_init_ports(&hw, base, ctl | 2); + + if (hwif->io_ports[IDE_DATA_OFFSET] == base && + hwif->io_ports[IDE_CONTROL_OFFSET] == (ctl | 2)) + oldnoprobe = hwif->noprobe; + + ide_init_port_hw(hwif, &hw); + + hwif->noprobe = oldnoprobe; + + hwif->dev = &dev->dev; hwif->cds = d; - hwif->channel = port; - if (!hwif->irq) - hwif->irq = irq; - if (mate) { - hwif->mate = mate; - mate->mate = hwif; - } return hwif; } +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI /** * ide_hwif_setup_dma - configure DMA interface - * @dev: PCI device - * @d: IDE port info * @hwif: IDE interface + * @d: IDE port info * * Set up the DMA base for the interface. Enable the master bits as * necessary and attempt to bring the device DMA into a ready to use * state */ -static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *hwif) +void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) { -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI + struct pci_dev *dev = to_pci_dev(hwif->dev); u16 pcicmd; pci_read_config_word(dev, PCI_COMMAND, &pcicmd); @@ -451,15 +439,15 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info * if (d->init_dma) { d->init_dma(hwif, dma_base); } else { - ide_setup_dma(hwif, dma_base, 8); + ide_setup_dma(hwif, dma_base); } } else { printk(KERN_INFO "%s: %s Bus-Master DMA disabled " "(BIOS)\n", hwif->name, d->name); } } -#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/ } +#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ /** * ide_setup_pci_controller - set up IDE PCI @@ -521,7 +509,7 @@ out: void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx) { int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; - ide_hwif_t *hwif, *mate = NULL; + ide_hwif_t *hwif; u8 tmp; /* @@ -537,62 +525,11 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int continue; /* port not enabled */ } - if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL) + hwif = ide_hwif_configure(dev, d, port, pciirq); + if (hwif == NULL) continue; - /* setup proper ancestral information */ - hwif->gendev.parent = &dev->dev; - *(idx + port) = hwif->index; - - - if (d->init_iops) - d->init_iops(hwif); - - if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) - ide_hwif_setup_dma(dev, d, hwif); - - if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || - (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) - hwif->irq = port ? 15 : 14; - - hwif->fixup = d->fixup; - - hwif->host_flags = d->host_flags; - hwif->pio_mask = d->pio_mask; - - if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate) - hwif->mate->serialized = hwif->serialized = 1; - - if (d->host_flags & IDE_HFLAG_IO_32BIT) { - hwif->drives[0].io_32bit = 1; - hwif->drives[1].io_32bit = 1; - } - - if (d->host_flags & IDE_HFLAG_UNMASK_IRQS) { - hwif->drives[0].unmask = 1; - hwif->drives[1].unmask = 1; - } - - if (hwif->dma_base) { - hwif->swdma_mask = d->swdma_mask; - hwif->mwdma_mask = d->mwdma_mask; - hwif->ultra_mask = d->udma_mask; - } - - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (d->host_flags & IDE_HFLAG_RQSIZE_256) - hwif->rqsize = 256; - - if (d->init_hwif) - /* Call chipset-specific routine - * for each enabled hwif - */ - d->init_hwif(hwif); - - mate = hwif; } } @@ -674,7 +611,7 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) ret = do_ide_setup_pci_device(dev, d, &idx[0], 1); if (ret >= 0) - ide_device_add(idx); + ide_device_add(idx, d); return ret; } @@ -698,110 +635,9 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, goto out; } - ide_device_add(idx); + ide_device_add(idx, d); out: return ret; } EXPORT_SYMBOL_GPL(ide_setup_pci_devices); - -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER -/* - * Module interfaces - */ - -static int pre_init = 1; /* Before first ordered IDE scan */ -static LIST_HEAD(ide_pci_drivers); - -/* - * __ide_pci_register_driver - attach IDE driver - * @driver: pci driver - * @module: owner module of the driver - * - * Registers a driver with the IDE layer. The IDE layer arranges that - * boot time setup is done in the expected device order and then - * hands the controllers off to the core PCI code to do the rest of - * the work. - * - * Returns are the same as for pci_register_driver - */ - -int __ide_pci_register_driver(struct pci_driver *driver, struct module *module, - const char *mod_name) -{ - if(!pre_init) - return __pci_register_driver(driver, module, mod_name); - driver->driver.owner = module; - list_add_tail(&driver->node, &ide_pci_drivers); - return 0; -} - -EXPORT_SYMBOL_GPL(__ide_pci_register_driver); - -/** - * ide_scan_pcidev - find an IDE driver for a device - * @dev: PCI device to check - * - * Look for an IDE driver to handle the device we are considering. - * This is only used during boot up to get the ordering correct. After - * boot up the pci layer takes over the job. - */ - -static int __init ide_scan_pcidev(struct pci_dev *dev) -{ - struct list_head *l; - struct pci_driver *d; - - list_for_each(l, &ide_pci_drivers) { - d = list_entry(l, struct pci_driver, node); - if (d->id_table) { - const struct pci_device_id *id = pci_match_id(d->id_table, - dev); - if (id != NULL && d->probe(dev, id) >= 0) { - dev->driver = d; - pci_dev_get(dev); - return 1; - } - } - } - return 0; -} - -/** - * ide_scan_pcibus - perform the initial IDE driver scan - * @scan_direction: set for reverse order scanning - * - * Perform the initial bus rather than driver ordered scan of the - * PCI drivers. After this all IDE pci handling becomes standard - * module ordering not traditionally ordered. - */ - -void __init ide_scan_pcibus (int scan_direction) -{ - struct pci_dev *dev = NULL; - struct pci_driver *d; - struct list_head *l, *n; - - pre_init = 0; - if (!scan_direction) - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) - ide_scan_pcidev(dev); - else - while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) - != NULL) - ide_scan_pcidev(dev); - - /* - * Hand the drivers over to the PCI layer now we - * are post init. - */ - - list_for_each_safe(l, n, &ide_pci_drivers) { - list_del(l); - d = list_entry(l, struct pci_driver, node); - if (__pci_register_driver(d, d->driver.owner, d->driver.mod_name)) - printk(KERN_ERR "%s: failed to register driver for %s\n", - __FUNCTION__, d->driver.mod_name); - } -} -#endif |