# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.558 -> 1.559 # drivers/ide/probe.c 1.72 -> (deleted) # drivers/ide/main.c 1.28 -> (deleted) # drivers/ide/ide-disk.c 1.83 -> (deleted) # drivers/ide/quirks.c 1.2 -> (deleted) # drivers/ide/pcihost.h 1.6 -> (deleted) # drivers/scsi/ide-scsi.c 1.56 -> (deleted) # drivers/ide/it8172.c 1.14 -> (deleted) # drivers/ide/rz1000.c 1.9 -> (deleted) # drivers/ide/icside.c 1.24 -> (deleted) # drivers/ide/hpt34x.c 1.31 -> (deleted) # drivers/ide/macide.c 1.4 -> (deleted) # drivers/ide/ioctl.h 1.1 -> (deleted) # drivers/ide/hd.c 1.34 -> (deleted) # drivers/ide/hpt366.c 1.37 -> (deleted) # drivers/ide/opti621.c 1.13 -> (deleted) # drivers/ide/ide-tape.c 1.55 -> (deleted) # drivers/ide/pcidma.c 1.60 -> (deleted) # drivers/ide/trm290.c 1.25 -> (deleted) # include/linux/ide.h 1.98 -> (deleted) # drivers/ide/ht6560b.c 1.14 -> (deleted) # drivers/ide/gayle.c 1.4 -> (deleted) # drivers/ide/pdc4030.c 1.39 -> (deleted) # drivers/ide/ide-floppy.c 1.57 -> (deleted) # drivers/ide/cy82c693.c 1.19 -> (deleted) # drivers/ide/qd65xx.h 1.3 -> (deleted) # drivers/ide/rapide.c 1.5 -> (deleted) # drivers/ide/ioctl.c 1.16 -> (deleted) # drivers/ide/qd65xx.c 1.18 -> (deleted) # drivers/ide/sl82c105.c 1.20 -> (deleted) # drivers/ide/ataraid.h 1.3 -> (deleted) # drivers/ide/umc8672.c 1.10 -> (deleted) # drivers/ide/ide-cs.c 1.8 -> (deleted) # drivers/ide/ata-timing.c 1.6 -> (deleted) # drivers/ide/ns87415.c 1.20 -> (deleted) # drivers/ide/device.c 1.11 -> (deleted) # drivers/ide/aec62xx.c 1.25 -> (deleted) # drivers/ide/cmd64x.c 1.29 -> (deleted) # drivers/ide/sis5513.c 1.26 -> (deleted) # drivers/ide/buddha.c 1.7 -> (deleted) # drivers/ide/falconide.c 1.4 -> (deleted) # drivers/ide/cmd640.c 1.15 -> (deleted) # drivers/ide/ide-cd.c 1.72 -> (deleted) # drivers/ide/ataraid.c 1.12 -> (deleted) # drivers/ide/pdcraid.c 1.17 -> (deleted) # drivers/ide/ali14xx.c 1.14 -> (deleted) # drivers/ide/dtc2278.c 1.11 -> (deleted) # drivers/ide/ide-m8xx.c 1.6 -> (deleted) # drivers/ide/ide-taskfile.c 1.62 -> (deleted) # drivers/ide/q40ide.c 1.5 -> (deleted) # drivers/ide/serverworks.c 1.30 -> (deleted) # drivers/ide/amd74xx.c 1.25 -> (deleted) # drivers/ide/hptraid.h 1.2 -> (deleted) # drivers/ide/cs5530.c 1.23 -> (deleted) # drivers/ide/alim15x3.c 1.29 -> (deleted) # drivers/ide/Makefile 1.29 -> (deleted) # drivers/ide/timing.h 1.10 -> (deleted) # drivers/ide/ide-pmac.c 1.37 -> (deleted) # drivers/ide/pdcraid.h 1.1 -> (deleted) # drivers/ide/tcq.c 1.26 -> (deleted) # drivers/ide/ide-pci.c 1.46 -> (deleted) # drivers/ide/pdc4030.h 1.2 -> (deleted) # drivers/ide/atapi.c 1.3 -> (deleted) # drivers/ide/ide-pnp.c 1.8 -> (deleted) # drivers/ide/via82cxxx.c 1.29 -> (deleted) # drivers/ide/Config.in 1.36 -> (deleted) # drivers/ide/ide-cd.h 1.10 -> (deleted) # drivers/ide/piix.c 1.41 -> (deleted) # drivers/ide/pdc202xx.c 1.45 -> (deleted) # drivers/ide/ide.c 1.121 -> (deleted) # drivers/ide/hptraid.c 1.15 -> (deleted) # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/08/16 axboe@burns.home.kernel.dk 1.559 # Delete 2.5 IDE core # -------------------------------------------- # diff -Nru a/drivers/ide/Config.in b/drivers/ide/Config.in --- a/drivers/ide/Config.in Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,142 +0,0 @@ -# -# ATA/ATAPI block device driver configuration -# -dep_tristate 'Enhanced ATA/ATAPI device (disk,cdrom,...) support' CONFIG_BLK_DEV_IDE $CONFIG_IDE -if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then - dep_bool ' Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE $CONFIG_X86 - define_bool CONFIG_BLK_DEV_HD $CONFIG_BLK_DEV_HD_IDE - - dep_tristate ' ATA disk support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE - dep_bool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK - dep_bool ' Auto-Geometry Resizing support' CONFIG_IDEDISK_STROKE $CONFIG_BLK_DEV_IDEDISK - - dep_tristate ' ATAPI device support (CD-ROM, floppy)' CONFIG_ATAPI $CONFIG_BLK_DEV_IDE - dep_tristate ' CD-ROM support' CONFIG_BLK_DEV_IDECD $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE - dep_tristate ' Tape support' CONFIG_BLK_DEV_IDETAPE $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE - dep_tristate ' Floppy support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE - dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI - - dep_tristate ' PCMCIA/CardBus support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA - - comment 'ATA host controller support' - dep_bool ' RZ1000 bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86 - dep_bool ' CMD640 bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86 - dep_bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED $CONFIG_BLK_DEV_CMD640 - dep_bool ' ISA-PNP support' CONFIG_BLK_DEV_ISAPNP $CONFIG_ISAPNP - if [ "$CONFIG_PCI" != "n" ]; then - comment ' PCI host controller support' - dep_bool ' Boot off-board controllers first' CONFIG_BLK_DEV_OFFBOARD $CONFIG_PCI - dep_bool ' Sharing PCI ATA interrupts' CONFIG_IDEPCI_SHARE_IRQ $CONFIG_PCI - dep_bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_PCI - dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO - define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' Tagged command queueing (DANGEROUS)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL - dep_bool ' TCQ on by default' CONFIG_BLK_DEV_IDE_TCQ_DEFAULT $CONFIG_BLK_DEV_IDE_TCQ - if [ "$CONFIG_BLK_DEV_IDE_TCQ" != "n" ]; then - int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32 - fi - dep_bool ' Good-Bad DMA Model-Firmware (EXPERIMENTAL)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_EXPERIMENTAL - dep_bool ' Acard (Artop) chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' ATP865 burst mode' CONFIG_AEC6280_BURST $CONFIG_BLK_DEV_AEC62XX - dep_bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3 $CONFIG_EXPERIMENTAL - dep_bool ' AMD and nVidia chipset support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' CMD64X chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' HPT34X chipset support' CONFIG_BLK_DEV_HPT34X $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' HPT34X AUTODMA support (EXPERIMENTAL)' CONFIG_HPT34X_AUTODMA $CONFIG_BLK_DEV_HPT34X $CONFIG_EXPERIMENTAL - dep_bool ' HPT36X/37X chipset support' CONFIG_BLK_DEV_HPT366 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' Intel and Efar (SMsC) chipset support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI - if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then - dep_mbool ' IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO - fi - dep_bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_PCI $CONFIG_EXPERIMENTAL - dep_bool ' PROMISE PDC202{46|62|65|67|68|69|70} support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX - dep_bool ' Special FastTrak Feature' CONFIG_PDC202XX_FORCE $CONFIG_BLK_DEV_PDC202XX - dep_bool ' ServerWorks OSB4/CSB5 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 - dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 - dep_bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' VIA chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 $CONFIG_BLK_DEV_IDEDMA_PCI - fi - if [ "$CONFIG_ALL_PPC" = "y" ]; then - bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC - dep_bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC $CONFIG_BLK_DEV_IDE_PMAC - dep_bool ' Use DMA by default' CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO $CONFIG_BLK_DEV_IDEDMA_PMAC - if [ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" ]; then - define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PMAC - fi - fi - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - dep_bool ' ICS IDE interface support' CONFIG_BLK_DEV_IDE_ICSIDE $CONFIG_ARCH_ACORN - dep_bool ' ICS DMA support' CONFIG_BLK_DEV_IDEDMA_ICS $CONFIG_BLK_DEV_IDE_ICSIDE - dep_bool ' Use ICS DMA by default' CONFIG_IDEDMA_ICS_AUTO $CONFIG_BLK_DEV_IDEDMA_ICS - define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_ICS - dep_bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN - fi - if [ "$CONFIG_AMIGA" = "y" ]; then - dep_bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA - dep_mbool ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL - fi - if [ "$CONFIG_ZORRO" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_mbool ' Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)' CONFIG_BLK_DEV_BUDDHA $CONFIG_ZORRO $CONFIG_EXPERIMENTAL - fi - if [ "$CONFIG_ATARI" = "y" ]; then - dep_bool ' Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE $CONFIG_ATARI - fi - if [ "$CONFIG_MAC" = "y" ]; then - dep_bool ' Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE $CONFIG_MAC - fi - if [ "$CONFIG_Q40" = "y" ]; then - dep_bool ' Q40/Q60 IDE interface support' CONFIG_BLK_DEV_Q40IDE $CONFIG_Q40 - fi - if [ "$CONFIG_8xx" = "y" ]; then - dep_bool ' MPC8xx IDE support' CONFIG_BLK_DEV_MPC8xx_IDE $CONFIG_8xx - fi - - if [ "$CONFIG_BLK_DEV_MPC8xx_IDE" = "y" ]; then - choice 'Type of MPC8xx IDE interface' \ - "8xx_PCCARD CONFIG_IDE_8xx_PCCARD \ - 8xx_DIRECT CONFIG_IDE_8xx_DIRECT \ - EXT_DIRECT CONFIG_IDE_EXT_DIRECT" 8xx_PCCARD - fi - - # assume no ISA -> also no VLB - dep_bool ' ISA/VLB IDE chipset support' CONFIG_IDE_CHIPSETS $CONFIG_ISA - if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then - comment 'Note: most of these also require special kernel boot parameters' - bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX - bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278 - bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B - if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 - fi - dep_tristate ' QDI QD65xx support' CONFIG_BLK_DEV_QD65XX $CONFIG_BLK_DEV_IDE - bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672 - fi - if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" != "n" -o \ - "$CONFIG_BLK_DEV_IDEDMA_PMAC" != "n" -o \ - "$CONFIG_BLK_DEV_IDEDMA_ICS" != "n" ]; then - bool ' IGNORE word93 Validation BITS' CONFIG_IDEDMA_IVB - fi -else - bool 'Old disk only (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY - define_bool CONFIG_BLK_DEV_HD $CONFIG_BLK_DEV_HD_ONLY -fi - -if [ "$CONFIG_IDEDMA_PCI_AUTO" = "y" -o \ - "$CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO" = "y" -o \ - "$CONFIG_IDEDMA_ICS_AUTO" = "y" ]; then - define_bool CONFIG_IDEDMA_AUTO y -else - define_bool CONFIG_IDEDMA_AUTO n -fi - -dep_tristate 'Support for software RAID controllers (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL -dep_tristate ' Support Promise (Fasttrak(tm)) (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID -dep_tristate ' Highpoint 370 EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile --- a/drivers/ide/Makefile Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,74 +0,0 @@ -# -# Makefile for the kernel ata, atapi, and ide block device drivers. -# -# 12 September 2000, Bartlomiej Zolnierkiewicz -# Rewritten to use lists instead of if-statements. -# -# Note : at this point, these files are compiled on all systems. -# In the future, some of these should be built conditionally. -# - -export-objs := device.o ide-taskfile.o main.o ide.o probe.o quirks.o pcidma.o tcq.o \ - atapi.o ataraid.o - -obj-$(CONFIG_BLK_DEV_HD) += hd.o -obj-$(CONFIG_BLK_DEV_IDE) += ide-mod.o -obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o -obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o -obj-$(CONFIG_ATAPI) += atapi.o -obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o -obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o -obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o - -obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o -obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o - -ide-obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o -ide-obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o -ide-obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o -ide-obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o -ide-obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o -ide-obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o -ide-obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o -ide-obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o -ide-obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o -ide-obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o -ide-obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o -ide-obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o -ide-obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o -ide-obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o -ide-obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o -ide-obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o -ide-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o -ide-obj-$(CONFIG_BLK_DEV_IDEDMA) += quirks.o -ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI) += pcidma.o -ide-obj-$(CONFIG_BLK_DEV_IDE_TCQ) += tcq.o -ide-obj-$(CONFIG_PCI) += ide-pci.o -ide-obj-$(CONFIG_BLK_DEV_ISAPNP) += ide-pnp.o -ide-obj-$(CONFIG_BLK_DEV_IDE_PMAC) += ide-pmac.o -ide-obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o -ide-obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o -ide-obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o -ide-obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o -ide-obj-$(CONFIG_BLK_DEV_PDC202XX) += pdc202xx.o -ide-obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o -ide-obj-$(CONFIG_BLK_DEV_PIIX) += piix.o -ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o -ide-obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o -ide-obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o -ide-obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o -ide-obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o -ide-obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o -ide-obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o -ide-obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ide-m8xx.o - -# The virtualised raid layers MUST come after the ide itself or bad stuff -# will happen. -obj-$(CONFIG_BLK_DEV_ATARAID) += ataraid.o -obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o -obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o - -ide-mod-objs := device.o ide-taskfile.o main.o ide.o probe.o \ - ioctl.o ata-timing.o $(ide-obj-y) - -include $(TOPDIR)/Rules.make diff -Nru a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c --- a/drivers/ide/aec62xx.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,360 +0,0 @@ -/* - * - * aec62xx.c, v1.2 2002/05/24 - * - * Copyright (c) 2002 Vojtech Pavlik - * - * Based on the work of: - * Andre Hedrick - */ - -/* - * AEC 6210UF (ATP850UF), AEC6260 (ATP860) and AEC6280 (ATP865) IDE driver for Linux. - * - * UDMA66 and higher modes are autoenabled only in case the BIOS has detected a - * 80 wire cable. To ignore the BIOS data and assume the cable is present, use - * 'ide0=ata66' or 'ide1=ata66' on the kernel command line. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to , or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "timing.h" -#include "pcihost.h" - -#define AEC_DRIVE_TIMING 0x40 -#define AEC_UDMA_NEW 0x44 -#define AEC_MISC 0x49 -#define AEC_IDE_ENABLE 0x4a -#define AEC_UDMA_OLD 0x54 - -#define AEC_BM_STAT_PCH 0x02 -#define AEC_BM_STAT_SCH 0x0a - -#define AEC_PLLCLK_ATA133 0x10 -#define AEC_CABLEPINS_INPUT 0x10 - -static unsigned char aec_cyc2udma[9] = { 5, 5, 5, 4, 3, 2, 2, 1, 1 }; -static unsigned char aec_cyc2act[16] = - { 1, 1, 2, 3, 4, 5, 6, 0, 0, 7, 7, 7, 7, 7, 7, 7 }; -static unsigned char aec_cyc2rec[16] = - { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 12, 13, 14 }; - -/* - * aec_set_speed_old() writes timing values to - * the chipset registers for ATP850UF - */ - -static void aec_set_speed_old(struct pci_dev *dev, unsigned char dn, - struct ata_timing *timing) -{ - unsigned char t; - - pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1), - aec_cyc2act[FIT(timing->active, 0, 15)]); - pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1) + 1, - aec_cyc2rec[FIT(timing->recover, 0, 15)]); - - pci_read_config_byte(dev, AEC_UDMA_OLD, &t); - t &= ~(3 << (dn << 1)); - if (timing->udma) - t |= (5 - FIT(timing->udma, 2, 4)) << (dn << 1); - pci_write_config_byte(dev, AEC_UDMA_OLD, t); -} - -/* - * aec_set_speed_new() writes timing values to the chipset registers for all - * other Artop chips - */ - -static void aec_set_speed_new(struct pci_dev *dev, unsigned char dn, - struct ata_timing *timing) -{ - unsigned char t; - - pci_write_config_byte(dev, AEC_DRIVE_TIMING + dn, - (aec_cyc2act[FIT(timing->active, 0, 15)] << - 4) - | aec_cyc2rec[FIT(timing->recover, 0, 15)]); - - pci_read_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), &t); - t &= ~(0xf << ((dn & 1) << 2)); - if (timing->udma) { - if (timing->udma >= 2) - t |= aec_cyc2udma[FIT(timing->udma, 2, 8)] << - ((dn & 1) << 2); - if (timing->mode == XFER_UDMA_5) - t |= 6; - if (timing->mode == XFER_UDMA_6) - t |= 7; - } - pci_write_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), t); -} - -/* - * aec_set_drive() computes timing values configures the drive and - * the chipset to a desired transfer mode. It also can be called - * by upper layers. - */ - -static int aec_set_drive(struct ata_device *drive, unsigned char speed) -{ - struct ata_timing t; - int T, UT; - int aec_old; - - aec_old = - (drive->channel->pci_dev->device == - PCI_DEVICE_ID_ARTOP_ATP850UF); - - if (speed != XFER_PIO_SLOW && speed != drive->current_speed) - if (ide_config_drive_speed(drive, speed)) - printk(KERN_WARNING - "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", - drive->dn >> 1, drive->dn & 1); - - T = 1000000000 / system_bus_speed; - UT = T / (aec_old ? 1 : 2); - - ata_timing_compute(drive, speed, &t, T, UT); - ata_timing_merge_8bit(&t); - - if (aec_old) - aec_set_speed_old(drive->channel->pci_dev, drive->dn, &t); - else - aec_set_speed_new(drive->channel->pci_dev, drive->dn, &t); - - return 0; -} - -/* - * aec62xx_tune_drive() is a callback from upper layers for - * PIO-only tuning. - */ - -static void aec62xx_tune_drive(struct ata_device *drive, unsigned char pio) -{ - if (pio == 255) { - aec_set_drive(drive, - ata_timing_mode(drive, - XFER_PIO | XFER_EPIO)); - return; - } - - aec_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int __init aec62xx_modes_map(struct ata_channel *ch) -{ - u32 bmide = pci_resource_start(ch->pci_dev, 4); - int map; - - map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA | XFER_UDMA; - - if (ch->udma_four) - switch (ch->pci_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP865R: - case PCI_DEVICE_ID_ARTOP_ATP865: - /* Can't use these modes simultaneously, - based on which PLL clock was chosen. */ - map |= - inb(bmide + - AEC_BM_STAT_PCH) & AEC_PLLCLK_ATA133 ? - XFER_UDMA_133 : XFER_UDMA_100; - case PCI_DEVICE_ID_ARTOP_ATP860R: - case PCI_DEVICE_ID_ARTOP_ATP860: - map |= XFER_UDMA_66; - } - - return map; -} -#endif - -/* - * The initialization callback. Here we determine the IDE chip type - * and initialize its drive independent registers. - * We return the IRQ assigned to the chip. - */ - -static unsigned int __init aec62xx_init_chipset(struct pci_dev *dev) -{ - u32 bmide = pci_resource_start(dev, 4); - unsigned char t; - -/* - * Initialize if needed. - */ - - switch (dev->device) { - - case PCI_DEVICE_ID_ARTOP_ATP865R: - case PCI_DEVICE_ID_ARTOP_ATP865: - - /* Clear reset and test bits. */ - pci_read_config_byte(dev, AEC_MISC, &t); - pci_write_config_byte(dev, AEC_MISC, t & ~0x30); - - /* Enable chip interrupt output. */ - pci_read_config_byte(dev, AEC_IDE_ENABLE, &t); - pci_write_config_byte(dev, AEC_IDE_ENABLE, t & ~0x01); - -#ifdef CONFIG_AEC6280_BURST - /* Must be greater than 0x80 for burst mode. */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x90); - - /* Enable burst mode. */ - pci_read_config_byte(dev, AEC_IDE_ENABLE, &t); - pci_write_config_byte(dev, AEC_IDE_ENABLE, t | 0x80); -#endif - /* switch cable detection pins to input-only. */ - outb(inb(bmide + AEC_BM_STAT_SCH) | AEC_CABLEPINS_INPUT, - bmide + AEC_BM_STAT_SCH); - } - -/* - * Print the boot message. - */ - - pci_read_config_byte(dev, PCI_REVISION_ID, &t); - printk(KERN_INFO "AEC_IDE: %s (rev %02x) controller on pci%s\n", - dev->name, t, dev->slot_name); - - return dev->irq; -} - -static unsigned int __init aec62xx_ata66_check(struct ata_channel *ch) -{ - unsigned char t; - - if (ch->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) - return 0; - - pci_read_config_byte(ch->pci_dev, AEC_MISC, &t); - return ((t & (1 << ch->unit)) ? 0 : 1); -} - -static void __init aec62xx_init_channel(struct ata_channel *ch) -{ - int i; - - ch->tuneproc = aec62xx_tune_drive; - ch->speedproc = aec_set_drive; - - ch->io_32bit = 1; - ch->unmask = 1; - - ch->udma_four = aec62xx_ata66_check(ch); - - for (i = 0; i < 2; i++) { - ch->drives[i].autotune = 1; - ch->drives[i].dn = ch->unit * 2 + i; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (ch->dma_base) { - ch->highmem = 1; - ch->modes_map = aec62xx_modes_map(ch); - ch->udma_setup = udma_generic_setup; - } -#endif -} - -/* - * We allow the BM-DMA driver only work on enabled interfaces. - */ -static void __init aec62xx_init_dma(struct ata_channel *ch, - unsigned long dmabase) -{ - unsigned char t; - - pci_read_config_byte(ch->pci_dev, AEC_IDE_ENABLE, &t); - if (t & (1 << ((ch->unit << 1) + 2))) - ata_init_dma(ch, dmabase); -} - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_ARTOP, - .device = PCI_DEVICE_ID_ARTOP_ATP850UF, - .init_chipset = aec62xx_init_chipset, - .init_channel = aec62xx_init_channel, - .init_dma = aec62xx_init_dma, - .enablebits = {{0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04}}, - .bootable = OFF_BOARD, - .flags = ATA_F_SER | ATA_F_IRQ | ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_ARTOP, - .device = PCI_DEVICE_ID_ARTOP_ATP860, - .init_chipset = aec62xx_init_chipset, - .init_channel = aec62xx_init_channel, - .enablebits = {{0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04}}, - .bootable = NEVER_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_ARTOP, - .device = PCI_DEVICE_ID_ARTOP_ATP860R, - .init_chipset = aec62xx_init_chipset, - .init_channel = aec62xx_init_channel, - .enablebits = {{0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04}}, - .bootable = OFF_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_ARTOP, - .device = PCI_DEVICE_ID_ARTOP_ATP865, - .init_chipset = aec62xx_init_chipset, - .init_channel = aec62xx_init_channel, - .enablebits = {{0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04}}, - .bootable = NEVER_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_ARTOP, - .device = PCI_DEVICE_ID_ARTOP_ATP865R, - .init_chipset = aec62xx_init_chipset, - .init_channel = aec62xx_init_channel, - .enablebits = {{0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04}}, - .bootable = OFF_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA - } -}; - -int __init init_aec62xx(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); i++) - ata_register_chipset(chipsets + i); - - return 0; -} diff -Nru a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c --- a/drivers/ide/ali14xx.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,228 +0,0 @@ -/* - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -/* - * ALI M14xx chipset EIDE controller - * - * Works for ALI M1439/1443/1445/1487/1489 chipsets. - * - * Adapted from code developed by derekn@vw.ece.cmu.edu. -ml - * Derek's notes follow: - * - * I think the code should be pretty understandable, - * but I'll be happy to (try to) answer questions. - * - * The critical part is in the ali14xx_tune_drive function. The init_registers - * function doesn't seem to be necessary, but the DOS driver does it, so - * I threw it in. - * - * I've only tested this on my system, which only has one disk. I posted - * it to comp.sys.linux.hardware, so maybe some other people will try it - * out. - * - * Derek Noonburg (derekn@ece.cmu.edu) - * 95-sep-26 - * - * Update 96-jul-13: - * - * I've since upgraded to two disks and a CD-ROM, with no trouble, and - * I've also heard from several others who have used it successfully. - * This driver appears to work with both the 1443/1445 and the 1487/1489 - * chipsets. I've added support for PIO mode 4 for the 1487. This - * seems to work just fine on the 1443 also, although I'm not sure it's - * advertised as supporting mode 4. (I've been running a WDC AC21200 in - * mode 4 for a while now with no trouble.) -Derek - */ - -#include -#include -#include -#include -#include - -#include - -#include "timing.h" - -/* port addresses for auto-detection */ -#define ALI_NUM_PORTS 4 -static int ports[ALI_NUM_PORTS] __initdata = - { 0x074, 0x0f4, 0x034, 0x0e4 }; - -/* register initialization data */ -struct reg_initializer { - u8 reg, data; -}; - -static struct reg_initializer init_data[] __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}, - {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00}, - {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00}, - {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff}, - {0x35, 0x03}, {0x00, 0x00} -}; - -/* timing parameter registers for each drive */ -static struct { - u8 reg1, reg2, reg3, reg4; -} reg_tab[4] = { - { - 0x03, 0x26, 0x04, 0x27}, /* drive 0 */ - { - 0x05, 0x28, 0x06, 0x29}, /* drive 1 */ - { - 0x2b, 0x30, 0x2c, 0x31}, /* drive 2 */ - { - 0x2d, 0x32, 0x2e, 0x33}, /* drive 3 */ -}; - -static int base_port; /* base port address */ -static int reg_port; /* port for register number */ -static int data_port; /* port for register data */ -static u8 reg_on; /* output to base port to access registers */ -static u8 reg_off; /* output to base port to close registers */ - -/* - * Read a controller register. - */ -static inline u8 in_reg(u8 reg) -{ - outb_p(reg, reg_port); - return inb(data_port); -} - -/* - * Write a controller register. - */ -static inline void out_reg(u8 data, u8 reg) -{ - outb_p(reg, reg_port); - outb_p(data, data_port); -} - -/* - * Set PIO mode for the specified drive. - * This function computes timing parameters - * and sets controller registers accordingly. - * It assumes IRQ's are disabled or at least that no other process will - * attempt to access the IDE registers concurrently. - */ -static void ali14xx_tune_drive(struct ata_device *drive, u8 pio) -{ - int drive_num; - int time1, time2; - u8 param1, param2, param3, param4; - struct ata_timing *t; - - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); - else - pio = XFER_PIO_0 + min_t(u8, pio, 4); - - t = ata_timing_data(pio); - - /* calculate timing, according to PIO mode */ - time1 = t->cycle; - time2 = t->active; - param3 = param1 = (time2 * system_bus_speed + 999999) / 1000000; - param4 = param2 = - (time1 * system_bus_speed + 999999) / 1000000 - param1; - if (pio < XFER_PIO_3) { - param3 += 8; - param4 += 8; - } - printk(KERN_DEBUG - "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n", - drive->name, pio - XFER_PIO_0, time1, time2, param1, param2, - param3, param4); - - /* stuff timing parameters into controller registers */ - drive_num = (drive->channel->index << 1) + drive->select.b.unit; - outb_p(reg_on, base_port); - out_reg(param1, reg_tab[drive_num].reg1); - out_reg(param2, reg_tab[drive_num].reg2); - out_reg(param3, reg_tab[drive_num].reg3); - out_reg(param4, reg_tab[drive_num].reg4); - outb_p(reg_off, base_port); -} - -/* - * Auto-detect the IDE controller port. - */ -static int __init find_port(void) -{ - int i; - unsigned long flags; - - local_irq_save(flags); - for (i = 0; i < ALI_NUM_PORTS; i++) { - base_port = ports[i]; - reg_off = inb(base_port); - for (reg_on = 0x30; reg_on <= 0x33; reg_on++) { - outb_p(reg_on, base_port); - if (inb(base_port) == reg_on) { - u8 t; - reg_port = base_port + 4; - data_port = base_port + 8; - t = in_reg(0) & 0xf0; - outb_p(reg_off, base_port); - local_irq_restore(flags); - if (t != 0x50) - return 0; - return 1; /* success */ - } - } - outb_p(reg_off, base_port); - } - local_irq_restore(flags); - - return 0; -} - -/* - * Initialize controller registers with default values. - */ -static int __init init_registers(void) -{ - struct reg_initializer *p; - unsigned long flags; - u8 t; - - local_irq_save(flags); - outb_p(reg_on, base_port); - for (p = init_data; p->reg != 0; ++p) - out_reg(p->data, p->reg); - outb_p(0x01, reg_port); - t = inb(reg_port) & 0x01; - outb_p(reg_off, base_port); - local_irq_restore(flags); - - return t; -} - -void __init init_ali14xx(void) -{ - /* auto-detect IDE controller port */ - if (!find_port()) { - printk(KERN_ERR "ali14xx: not found\n"); - return; - } - - printk(KERN_DEBUG "ali14xx: base=%#03x, reg_on=%#02x\n", - base_port, reg_on); - ide_hwifs[0].chipset = ide_ali14xx; - ide_hwifs[1].chipset = ide_ali14xx; - ide_hwifs[0].tuneproc = &ali14xx_tune_drive; - ide_hwifs[1].tuneproc = &ali14xx_tune_drive; - ide_hwifs[0].unit = ATA_PRIMARY; - ide_hwifs[1].unit = ATA_SECONDARY; - - /* initialize controller registers */ - if (!init_registers()) { - printk(KERN_ERR "ali14xx: Chip initialization failed\n"); - return; - } -} diff -Nru a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c --- a/drivers/ide/alim15x3.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,404 +0,0 @@ -/* - * linux/drivers/ide/alim15x3.c Version 0.10 Jun. 9, 2000 - * - * Copyright (C) 1998-2000 Michel Aubry, Maintainer - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer - * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer - * - * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) - * May be copied or modified under the terms of the GNU General Public License - * - * (U)DMA capable version of ali 1533/1543(C), 1535(D) - * - ********************************************************************** - * 9/7/99 --Parts from the above author are included and need to be - * converted into standard interface, once I finish the thought. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "pcihost.h" - -static u8 m5229_revision; -static int chip_is_1543c_e; - -static struct pci_dev *isa_dev; - -static void ali15x3_tune_drive(struct ata_device *drive, u8 pio) -{ - struct ata_timing *t; - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - int s_time, a_time, c_time; - u8 s_clc, a_clc, r_clc; - unsigned long flags; - int port = hwif->unit ? 0x5c : 0x58; - int portFIFO = hwif->unit ? 0x55 : 0x54; - u8 cd_dma_fifo = 0; - - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); - else - pio = XFER_PIO_0 + min_t(u8, pio, 4); - - t = ata_timing_data(pio); - - /* FIXME: use generic ata-timing library --bkz */ - s_time = t->setup; - a_time = t->active; - if ((s_clc = (s_time * system_bus_speed + 999999) / 1000000) >= 8) - s_clc = 0; - if ((a_clc = (a_time * system_bus_speed + 999999) / 1000000) >= 8) - a_clc = 0; - c_time = t->cycle; - -#if 0 - if ((r_clc = ((c_time - s_time - a_time) * system_bus_speed + 999999) / 1000000) >= 16) - r_clc = 0; -#endif - - if (!(r_clc = (c_time * system_bus_speed + 999999) / 1000000 - a_clc - s_clc)) { - r_clc = 1; - } else { - if (r_clc >= 16) - r_clc = 0; - } - - local_irq_save(flags); - - /* - * PIO mode => ATA FIFO on, ATAPI FIFO off - */ - pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); - if (drive->type == ATA_DISK) { - if (hwif->index) { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); - } else { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); - } - } else { - if (hwif->index) { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); - } else { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); - } - } - - pci_write_config_byte(dev, port, s_clc); - pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); - - local_irq_restore(flags); -} - -static int ali15x3_tune_chipset(struct ata_device *drive, u8 speed) -{ - struct pci_dev *dev = drive->channel->pci_dev; - u8 unit = (drive->select.b.unit & 0x01); - u8 tmpbyte = 0x00; - int m5229_udma = drive->channel->unit ? 0x57 : 0x56; - - if (speed < XFER_UDMA_0) { - u8 ultra_enable = unit ? 0x7f : 0xf7; - /* - * clear "ultra enable" bit - */ - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= ultra_enable; - pci_write_config_byte(dev, m5229_udma, tmpbyte); - } - - if (speed < XFER_SW_DMA_0) - ali15x3_tune_drive(drive, speed); -#ifdef CONFIG_BLK_DEV_IDEDMA - /* FIXME: no support for MWDMA and SWDMA modes --bkz */ - else if (speed >= XFER_UDMA_0) { - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= (0x0f << ((1-unit) << 2)); - /* - * enable ultra dma and set timing - */ - tmpbyte |= ((0x08 | ((4-speed)&0x07)) << (unit << 2)); - pci_write_config_byte(dev, m5229_udma, tmpbyte); - if (speed >= XFER_UDMA_3) { - pci_read_config_byte(dev, 0x4b, &tmpbyte); - tmpbyte |= 1; - pci_write_config_byte(dev, 0x4b, tmpbyte); - } - } -#endif - - return ide_config_drive_speed(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int ali15x3_udma_setup(struct ata_device *drive, int map) -{ -#ifndef CONFIG_WDC_ALI15X3 - if ((m5229_revision < 0xC2) && chip_is_1543c_e && - strstr(drive->id->model, "WDC ")) - map &= ~XFER_UDMA_ALL; -#endif - return udma_generic_setup(drive, map); -} - -static int ali15x3_udma_init(struct ata_device *drive, struct request *rq) -{ - if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK)) - return ATA_OP_FINISHED; /* try PIO instead of DMA */ - - return udma_pci_init(drive, rq); -} - -static int __init ali15x3_modes_map(struct ata_channel *ch) -{ - int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA; - - if (m5229_revision <= 0x20) - return map; - - map |= XFER_UDMA; - - if (m5229_revision >= 0xC2) { - map |= XFER_UDMA_66; - if (m5229_revision >= 0xC4) - map |= XFER_UDMA_100; - } - - return map; -} -#endif - -static unsigned int __init ali15x3_init_chipset(struct pci_dev *dev) -{ - unsigned long fixdma_base = pci_resource_start(dev, 4); - - pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); - - isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); - - if (!fixdma_base) { - /* - * - */ - } else { - /* - * enable DMA capable bit, and "not" simplex only - */ - outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); - - if (inb(fixdma_base+2) & 0x80) - printk("%s: simplex device: DMA will fail!!\n", dev->name); - } - - return 0; -} - -/* - * This checks if the controller and the cable are capable - * of UDMA66 transfers. It doesn't check the drives. - * But see note 2 below! - */ -static unsigned int __init ali15x3_ata66_check(struct ata_channel *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - unsigned int ata66 = 0; - u8 cable_80_pin[2] = { 0, 0 }; - - unsigned long flags; - u8 tmpbyte; - - local_irq_save(flags); - - if (m5229_revision >= 0xC2) { - /* - * 1543C-B?, 1535, 1535D, 1553 - * Note 1: not all "motherboard" support this detection - * Note 2: if no udma 66 device, the detection may "error". - * but in this case, we will not set the device to - * ultra 66, the detection result is not important - */ - - /* - * enable "Cable Detection", m5229, 0x4b, bit3 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); - - /* - * set south-bridge's enable bit, m1533, 0x79 - */ - pci_read_config_byte(isa_dev, 0x79, &tmpbyte); - if (m5229_revision == 0xC2) { - /* - * 1543C-B0 (m1533, 0x79, bit 2) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); - } else if (m5229_revision >= 0xC3) { - /* - * 1553/1535 (m1533, 0x79, bit 1) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); - } - /* - * Ultra66 cable detection (from Host View) - * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin - */ - pci_read_config_byte(dev, 0x4a, &tmpbyte); - /* - * 0x4a, bit0 is 0 => primary channel - * has 80-pin (from host view) - */ - if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1; - /* - * 0x4a, bit1 is 0 => secondary channel - * has 80-pin (from host view) - */ - if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1; - /* - * Allow ata66 if cable of current channel has 80 pins - */ - ata66 = (hwif->unit)?cable_80_pin[1]:cable_80_pin[0]; - } else { - /* - * revision 0x20 (1543-E, 1543-F) - * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) - * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - /* - * clear bit 7 - */ - pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); - /* - * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 - */ - pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); - chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; - } - - /* - * CD_ROM DMA on (m5229, 0x53, bit0) - * Enable this bit even if we want to use PIO - * PIO FIFO off (m5229, 0x53, bit1) - * The hardware will use 0x54h and 0x55h to control PIO FIFO - */ - pci_read_config_byte(dev, 0x53, &tmpbyte); - tmpbyte = (tmpbyte & (~0x02)) | 0x01; - - pci_write_config_byte(dev, 0x53, tmpbyte); - - local_irq_restore(flags); - - return (ata66); -} - -static void __init ali15x3_init_channel(struct ata_channel *hwif) -{ -#ifndef CONFIG_SPARC64 - u8 ideic, inmir; - u8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, - 1, 11, 0, 12, 0, 14, 0, 15 }; - - hwif->irq = hwif->unit ? 15 : 14; - - if (isa_dev) { - /* - * read IDE interface control - */ - pci_read_config_byte(isa_dev, 0x58, &ideic); - - /* bit0, bit1 */ - ideic = ideic & 0x03; - - /* get IRQ for IDE Controller */ - if ((hwif->unit && ideic == 0x03) || (!hwif->unit && !ideic)) { - /* - * get SIRQ1 routing table - */ - pci_read_config_byte(isa_dev, 0x44, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } else if (hwif->unit && !(ideic & 0x01)) { - /* - * get SIRQ2 routing table - */ - pci_read_config_byte(isa_dev, 0x75, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } - } -#endif /* CONFIG_SPARC64 */ - - hwif->udma_four = ali15x3_ata66_check(hwif); - - hwif->tuneproc = &ali15x3_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->speedproc = ali15x3_tune_chipset; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if ((hwif->dma_base) && (m5229_revision >= 0x20)) { - /* - * M1543C or newer for DMAing - */ - hwif->modes_map = ali15x3_modes_map(hwif); - if (m5229_revision < 0xC2) - hwif->no_atapi_autodma = 1; - hwif->udma_setup = ali15x3_udma_setup; - hwif->udma_init = ali15x3_udma_init; - } -#endif -} - -static void __init ali15x3_init_dma(struct ata_channel *ch, unsigned long dmabase) -{ - if (dmabase && (m5229_revision < 0x20)) { - ch->autodma = 0; - return; - } - - ata_init_dma(ch, dmabase); -} - - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_AL, - .device = PCI_DEVICE_ID_AL_M5219, - /* FIXME: Perhaps we should use the same init routines - * as below here. */ - .enablebits = { {0x00,0x00,0x00}, {0x00,0x00,0x00} }, - .bootable = ON_BOARD, - .flags = ATA_F_SIMPLEX - }, - { - .vendor = PCI_VENDOR_ID_AL, - .device = PCI_DEVICE_ID_AL_M5229, - .init_chipset = ali15x3_init_chipset, - .init_channel = ali15x3_init_channel, - .init_dma = ali15x3_init_dma, - .enablebits = { {0x00,0x00,0x00}, {0x00,0x00,0x00} }, - .bootable = ON_BOARD - } -}; - -int __init init_ali15x3(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c --- a/drivers/ide/amd74xx.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,371 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * $Id: amd74xx.c,v 2.8 2002/03/14 11:52:20 vojtech Exp $ - * - * Copyright (c) 2000-2002 Vojtech Pavlik - * - * Based on the work of: - * Andre Hedrick - */ - -/* - * AMD 755/756/766/8111 IDE driver for Linux. - * - * UDMA66 and higher modes are autoenabled only in case the BIOS has detected a - * 80 wire cable. To ignore the BIOS data and assume the cable is present, use - * 'ide0=ata66' or 'ide1=ata66' on the kernel command line. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to , or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "pcihost.h" - -#define AMD_IDE_ENABLE (0x00 + amd_config->base) -#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_UDMA 0x07 -#define AMD_UDMA_33 0x01 -#define AMD_UDMA_66 0x02 -#define AMD_UDMA_100 0x03 -#define AMD_BAD_SWDMA 0x08 -#define AMD_BAD_FIFO 0x10 - -/* - * AMD SouthBridge chips. - */ - -static struct amd_ide_chip { - unsigned short id; - unsigned char rev; - unsigned int base; - unsigned char flags; -} amd_ide_chips[] = { - { PCI_DEVICE_ID_AMD_8111_IDE, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-8111 */ - { PCI_DEVICE_ID_AMD_OPUS_7441, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-768 Opus */ - { PCI_DEVICE_ID_AMD_VIPER_7411, 0x00, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO }, /* AMD-766 Viper */ - { PCI_DEVICE_ID_AMD_VIPER_7409, 0x07, 0x40, AMD_UDMA_66 }, /* AMD-756/c4+ Viper */ - { PCI_DEVICE_ID_AMD_VIPER_7409, 0x00, 0x40, AMD_UDMA_66 | AMD_BAD_SWDMA }, /* AMD-756 Viper */ - { PCI_DEVICE_ID_AMD_COBRA_7401, 0x00, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA }, /* AMD-755 Cobra */ - { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x00, 0x50, AMD_UDMA_100 }, /* nVidia nForce */ - { 0 } -}; - -static struct amd_ide_chip *amd_config; -static unsigned char amd_enabled; -static unsigned int amd_80w; - -static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3 }; -#if 0 -static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 1 }; -#endif -static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" }; - -/* - * amd_set_speed() writes timing values to the chipset registers - */ - -static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ata_timing *timing) -{ - unsigned char t; - - pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &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_8BIT_TIMING + (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), - ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1)); - - switch (amd_config->flags & AMD_UDMA) { - case AMD_UDMA_33: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; - case AMD_UDMA_66: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break; - case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break; - default: return; - } - - pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t); -} - -/* - * amd_set_drive() computes timing values configures the drive and - * the chipset to a desired transfer mode. It also can be called - * by upper layers. - */ - -static int amd_set_drive(struct ata_device *drive, unsigned char speed) -{ - struct ata_device *peer = drive->channel->drives + (~drive->dn & 1); - struct ata_timing t, p; - int T, UT; - - if (speed != XFER_PIO_SLOW && speed != drive->current_speed) - if (ide_config_drive_speed(drive, speed)) - printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", - drive->dn >> 1, drive->dn & 1); - - T = 1000000000 / system_bus_speed; - UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2); - - ata_timing_compute(drive, speed, &t, T, UT); - - if (peer->present) { - ata_timing_compute(peer, peer->current_speed, &p, T, UT); - ata_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); - } - - if (speed == XFER_UDMA_5 && system_bus_speed <= 33333) t.udma = 1; - - amd_set_speed(drive->channel->pci_dev, drive->dn, &t); - - return 0; -} - -/* - * amd74xx_tune_drive() is a callback from upper layers for - * PIO-only tuning. - */ - -static void amd74xx_tune_drive(struct ata_device *drive, u8 pio) -{ - if (!((amd_enabled >> drive->channel->unit) & 1)) - return; - - if (pio == 255) { - amd_set_drive(drive, ata_timing_mode(drive, XFER_PIO | XFER_EPIO)); - return; - } - - amd_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int __init amd_modes_map(struct ata_channel *ch) -{ - short w80 = ch->udma_four; - int map = XFER_EPIO | XFER_MWDMA | XFER_UDMA | - ((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) | - (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) | - (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0); - - return map; -} -#endif - -/* - * The initialization callback. Here we determine the IDE chip type - * and initialize its drive independent registers. - */ - -static unsigned int __init amd74xx_init_chipset(struct pci_dev *dev) -{ - unsigned char t; - unsigned int u; - int i; - -/* - * Find out what AMD IDE is this. - */ - - for (amd_config = amd_ide_chips; amd_config->id; amd_config++) { - pci_read_config_byte(dev, PCI_REVISION_ID, &t); - if (dev->device == amd_config->id && t >= amd_config->rev) - break; - } - - if (!amd_config->id) { - printk(KERN_WARNING "AMD_IDE: Unknown AMD IDE Chip, contact Vojtech Pavlik \n"); - return -ENODEV; - } - -/* - * Check 80-wire cable presence. - */ - - switch (amd_config->flags & AMD_UDMA) { - - case AMD_UDMA_100: - pci_read_config_byte(dev, AMD_CABLE_DETECT, &t); - amd_80w = ((u & 0x3) ? 1 : 0) | ((u & 0xc) ? 2 : 0); - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) { - printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits corectly. Enabling workaround.\n"); - amd_80w |= (1 << (1 - (i >> 4))); - } - break; - - case AMD_UDMA_66: - pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); - for (i = 24; i >= 0; i -= 8) - if ((u >> i) & 4) - amd_80w |= (1 << (1 - (i >> 4))); - break; - } - - pci_read_config_dword(dev, AMD_IDE_ENABLE, &u); - amd_enabled = ((u & 1) ? 2 : 0) | ((u & 2) ? 1 : 0); - -/* - * 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)); - -/* - * Print the boot message. - */ - - pci_read_config_byte(dev, PCI_REVISION_ID, &t); - printk(KERN_INFO "AMD_IDE: %s (rev %02x) %s controller on pci%s\n", - dev->name, t, amd_dma[amd_config->flags & AMD_UDMA], dev->slot_name); - - return 0; -} - -static unsigned int __init amd74xx_ata66_check(struct ata_channel *hwif) -{ - return ((amd_enabled & amd_80w) >> hwif->unit) & 1; -} - -static void __init amd74xx_init_channel(struct ata_channel *hwif) -{ - int i; - - hwif->udma_four = amd74xx_ata66_check(hwif); - - hwif->tuneproc = &amd74xx_tune_drive; - hwif->speedproc = &amd_set_drive; - - hwif->io_32bit = 1; - hwif->unmask = 1; - - for (i = 0; i < 2; i++) { - hwif->drives[i].autotune = 1; - hwif->drives[i].dn = hwif->unit * 2 + i; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->highmem = 1; - hwif->modes_map = amd_modes_map(hwif); - hwif->udma_setup = udma_generic_setup; - } -#endif -} - -/* - * We allow the BM-DMA driver only work on enabled interfaces. - */ -static void __init amd74xx_init_dma(struct ata_channel *ch, unsigned long dmabase) -{ - if ((amd_enabled >> ch->unit) & 1) - ata_init_dma(ch, dmabase); -} - - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_COBRA_7401, - .init_chipset = amd74xx_init_chipset, - .init_channel = amd74xx_init_channel, - .init_dma = amd74xx_init_dma, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_VIPER_7409, - .init_chipset = amd74xx_init_chipset, - .init_channel = amd74xx_init_channel, - .init_dma = amd74xx_init_dma, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, - .bootable = ON_BOARD, - .flags = ATA_F_SIMPLEX - }, - { - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_VIPER_7411, - .init_chipset = amd74xx_init_chipset, - .init_channel = amd74xx_init_channel, - .init_dma = amd74xx_init_dma, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_OPUS_7441, - .init_chipset = amd74xx_init_chipset, - .init_channel = amd74xx_init_channel, - .init_dma = amd74xx_init_dma, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_8111_IDE, - .init_chipset = amd74xx_init_chipset, - .init_channel = amd74xx_init_channel, - .init_dma = amd74xx_init_dma, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, - .init_chipset = amd74xx_init_chipset, - .init_channel = amd74xx_init_channel, - .init_dma = amd74xx_init_dma, - .enablebits = {{0x50,0x01,0x01}, {0x50,0x02,0x02}}, - .bootable = ON_BOARD - }, -}; - -int __init init_amd74xx(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/ide/ata-timing.c b/drivers/ide/ata-timing.c --- a/drivers/ide/ata-timing.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,299 +0,0 @@ -/* - * $Id: ata-timing.c,v 2.0 2002/03/12 15:48:43 vojtech Exp $ - * - * Copyright (c) 1999-2001 Vojtech Pavlik - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by e-mail - - * mail your message to , or by paper mail: Vojtech Pavlik, - * Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include -#include -#include - -#include "timing.h" - -/* - * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). These were taken - * from ATA/ATAPI-6 standard, rev 0a, except for PIO 5, which is a nonstandard - * extension and UDMA6, which is currently supported only by Maxtor drives. - */ - -struct ata_timing ata_timing[] = { - - { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 }, - { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 }, - { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 }, - { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 }, - - { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 }, - { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, - { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, - - { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, - - { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 }, - { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 }, - { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 }, - - { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 }, - { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, - { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, - - { XFER_PIO_5, 20, 50, 30, 100, 50, 30, 100, 0 }, - { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, - { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, - - { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 }, - { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 }, - { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 }, - - { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, - - { -1 } -}; - -/* - * Determine the best transfer mode appilcable to a particular drive. This has - * then to be matched agains in esp. other drives no the same channel or even - * the whole particular host chip. - */ -short ata_timing_mode(struct ata_device *drive, int map) -{ - struct hd_driveid *id = drive->id; - short best = 0; - - if (!id) - return XFER_PIO_SLOW; - - /* Want UDMA and UDMA bitmap valid */ - if ((map & XFER_UDMA) && (id->field_valid & 4)) { - if ((map & XFER_UDMA_133) == XFER_UDMA_133) - if ((best = (id->dma_ultra & 0x0040) ? XFER_UDMA_6 : 0)) return best; - - if ((map & XFER_UDMA_100) == XFER_UDMA_100) - if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best; - - if ((map & XFER_UDMA_66_4) == XFER_UDMA_66_4) - if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 : 0)) return best; - - if ((map & XFER_UDMA_66_3) == XFER_UDMA_66_3) - if ((best = (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best; - - if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 : - (id->dma_ultra & 0x0002) ? XFER_UDMA_1 : - (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : 0)) return best; - } - - /* Want MWDMA and drive has EIDE fields */ - if ((map & XFER_MWDMA) && (id->field_valid & 2)) { - if ((best = (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 : - (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 : - (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : 0)) - return best; - } - - /* Want SWDMA */ - if (map & XFER_SWDMA) { - - /* EIDE SWDMA */ - if (id->field_valid & 2) { - if ((best = (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 : - (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 : - (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0)) - return best; - } - - /* Pre-EIDE style SWDMA */ - if (id->capability & 1) { - if ((best = (id->tDMA == 2) ? XFER_SW_DMA_2 : - (id->tDMA == 1) ? XFER_SW_DMA_1 : - (id->tDMA == 0) ? XFER_SW_DMA_0 : 0)) - return best; - } - } - - /* EIDE PIO modes */ - if ((map & XFER_EPIO) && (id->field_valid & 2)) { - if ((best = (drive->id->eide_pio_modes & 4) ? XFER_PIO_5 : - (drive->id->eide_pio_modes & 2) ? XFER_PIO_4 : - (drive->id->eide_pio_modes & 1) ? XFER_PIO_3 : 0)) - return best; - } - - return (drive->id->tPIO == 2) ? XFER_PIO_2 : - (drive->id->tPIO == 1) ? XFER_PIO_1 : - (drive->id->tPIO == 0) ? XFER_PIO_0 : XFER_PIO_SLOW; -} - -/* - * Just get a pointer to the struct describing the timing values used commonly - * for a particular mode. - */ -struct ata_timing* ata_timing_data(short speed) -{ - struct ata_timing *t; - - for (t = ata_timing; t->mode != speed; t++) - if (t->mode < 0) - return NULL; - return t; -} - -/* - * This is just unit conversion. - */ -void ata_timing_quantize(struct ata_timing *t, struct ata_timing *q, - int T, int UT) -{ - q->setup = EZ(t->setup * 1000, T); - q->act8b = EZ(t->act8b * 1000, T); - q->rec8b = EZ(t->rec8b * 1000, T); - q->cyc8b = EZ(t->cyc8b * 1000, T); - q->active = EZ(t->active * 1000, T); - q->recover = EZ(t->recover * 1000, T); - q->cycle = EZ(t->cycle * 1000, T); - q->udma = EZ(t->udma * 1000, UT); -} - -/* - * Match against each other the timing setup for two devices on one channel. - * Becouse they share the electrical interface we can unsually only use the - * lowest common denominator between them. - */ -void ata_timing_merge(struct ata_timing *a, struct ata_timing *b, - struct ata_timing *m, unsigned int what) -{ - if (what & IDE_TIMING_SETUP) - m->setup = max(a->setup, b->setup); - if (what & IDE_TIMING_ACT8B) - m->act8b = max(a->act8b, b->act8b); - if (what & IDE_TIMING_REC8B) - m->rec8b = max(a->rec8b, b->rec8b); - if (what & IDE_TIMING_CYC8B) - m->cyc8b = max(a->cyc8b, b->cyc8b); - if (what & IDE_TIMING_ACTIVE) - m->active = max(a->active, b->active); - if (what & IDE_TIMING_RECOVER) - m->recover = max(a->recover, b->recover); - if (what & IDE_TIMING_CYCLE) - m->cycle = max(a->cycle, b->cycle); - if (what & IDE_TIMING_UDMA) - m->udma = max(a->udma, b->udma); -} - -/* - * Not all controllers can do separate timing for 8-bit command transfers - * and 16-bit data transfers. - */ - -void ata_timing_merge_8bit(struct ata_timing *t) -{ - t->active = max(t->active, t->act8b); - t->recover = max(t->recover, t->rec8b); - t->cycle = max(t->cycle, t->cyc8b); -} - -int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing *t, - int T, int UT) -{ - struct hd_driveid *id = drive->id; - struct ata_timing *s, p; - - /* Find the mode. - */ - - if (!(s = ata_timing_data(speed))) - return -EINVAL; - - memcpy(t, s, sizeof(struct ata_timing)); - - /* If the drive is an EIDE drive, it can tell us it needs extended - * PIO/MWDMA cycle timing. - */ - - /* EIDE drive */ - if (id && id->field_valid & 2) { - memset(&p, 0, sizeof(p)); - - switch (speed & XFER_MODE) { - case XFER_PIO: - if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = id->eide_pio; - else p.cycle = p.cyc8b = id->eide_pio_iordy; - break; - - case XFER_MWDMA: - p.cycle = id->eide_dma_min; - break; - } - - ata_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B); - } - - /* Convert the timing to bus clock counts. - */ - - ata_timing_quantize(t, t, T, UT); - - /* Even in DMA/UDMA modes we still use PIO access for IDENTIFY, - * S.M.A.R.T and some other commands. We have to ensure that the DMA - * cycle timing is slower/equal than the fastest PIO timing. - */ - - if ((speed & XFER_MODE) != XFER_PIO) { - ata_timing_compute(drive, ata_timing_mode(drive, XFER_PIO | XFER_EPIO), &p, T, UT); - ata_timing_merge(&p, t, t, IDE_TIMING_ALL); - } - - /* Lenghten active & recovery time so that cycle time is correct. - */ - - if (t->act8b + t->rec8b < t->cyc8b) { - t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2; - t->rec8b = t->cyc8b - t->act8b; - } - - if (t->active + t->recover < t->cycle) { - t->active += (t->cycle - (t->active + t->recover)) / 2; - t->recover = t->cycle - t->active; - } - - return 0; -} - -u8 ata_best_pio_mode(struct ata_device *drive) -{ - static u16 eide_pio_timing[6] = { 600, 383, 240, 180, 120, 90 }; - u16 pio_min; - u8 pio; - - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; - - /* downgrade mode if necessary */ - pio_min = (pio > 2) ? drive->id->eide_pio_iordy : drive->id->eide_pio; - - if (pio_min) - while (pio && pio_min > eide_pio_timing[pio]) - pio--; - - if (!pio && drive->id->tPIO) - return XFER_PIO_SLOW; - - /* don't allow XFER_PIO_5 for now */ - return XFER_PIO_0 + min_t(u8, pio, 4); -} diff -Nru a/drivers/ide/atapi.c b/drivers/ide/atapi.c --- a/drivers/ide/atapi.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,186 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* - * Code common among all the ATAPI device drivers. - * - * Ideally this should evolve in to a unified driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Initializes a packet command. Used by tape and floppy driver. - */ -void atapi_init_pc(struct atapi_packet_command *pc) -{ - memset(pc->c, 0, 12); - pc->retries = 0; - pc->flags = 0; - pc->request_transfer = 0; - pc->buffer = pc->pc_buffer; - pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE; - pc->b_data = NULL; - pc->bio = NULL; -} - -/* - * Too bad. The drive wants to send us data which we are not ready to accept. - * Just throw it away. - */ -void atapi_discard_data(struct ata_device *drive, unsigned int bcount) -{ - while (bcount--) - IN_BYTE(IDE_DATA_REG); -} - -void atapi_write_zeros(struct ata_device *drive, unsigned int bcount) -{ - while (bcount--) - OUT_BYTE(0, IDE_DATA_REG); -} - -/* - * The following routines are mainly used by the ATAPI drivers. - * - * These routines will round up any request for an odd number of bytes, so if - * an odd n is specified, be sure that there's at least one extra byte - * allocated for the buffer. - */ -void atapi_read(struct ata_device *drive, u8 *buf, unsigned int n) -{ - if (drive->channel->atapi_read) { - drive->channel->atapi_read(drive, buf, n); - return; - } - - ++n; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - insw_swapw(IDE_DATA_REG, buf, n / 2); - return; - } -#endif - ata_read(drive, buf, n / 4); - if ((n & 0x03) >= 2) - insw(IDE_DATA_REG, buf + (n & ~0x03), 1); -} - -void atapi_write(struct ata_device *drive, u8 *buf, unsigned int n) -{ - if (drive->channel->atapi_write) { - drive->channel->atapi_write(drive, buf, n); - return; - } - - ++n; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - outsw_swapw(IDE_DATA_REG, buf, n / 2); - return; - } -#endif - ata_write(drive, buf, n / 4); - if ((n & 0x03) >= 2) - outsw(IDE_DATA_REG, buf + (n & ~0x03), 1); -} - - -/* - * This function issues a special IDE device request onto the request queue. - * - * If action is ide_wait, then the rq is queued at the end of the request - * queue, and the function sleeps until it has been processed. This is for use - * when invoked from an ioctl handler. - * - * If action is ide_preempt, then the rq is queued at the head of the request - * queue, displacing the currently-being-processed request and this function - * returns immediately without waiting for the new rq to be completed. This is - * VERY DANGEROUS, and is intended for careful use by the ATAPI tape/cdrom - * driver code. - * - * If action is ide_end, then the rq is queued at the end of the request queue, - * and the function returns immediately without waiting for the new rq to be - * completed. This is again intended for careful use by the ATAPI tape/cdrom - * driver code. - */ -int ide_do_drive_cmd(struct ata_device *drive, struct request *rq, ide_action_t action) -{ - unsigned long flags; - struct ata_channel *ch = drive->channel; - unsigned int major = ch->major; - request_queue_t *q = &drive->queue; - struct list_head *queue_head = &q->queue_head; - DECLARE_COMPLETION(wait); - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (ch->chipset == ide_pdc4030 && rq->buffer) - return -ENOSYS; /* special drive cmds not supported */ -#endif - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - rq->rq_dev = mk_kdev(major, (drive->select.b.unit) << PARTN_BITS); - if (action == ide_wait) - rq->waiting = &wait; - - spin_lock_irqsave(ch->lock, flags); - - if (action == ide_preempt) - drive->rq = NULL; - else if (!blk_queue_empty(&drive->queue)) - queue_head = queue_head->prev; /* ide_end and ide_wait */ - - __elv_add_request(q, rq, queue_head); - - do_ide_request(q); - - spin_unlock_irqrestore(ch->lock, flags); - - if (action == ide_wait) { - wait_for_completion(&wait); /* wait for it to be serviced */ - return rq->errors ? -EIO : 0; /* return -EIO if errors */ - } - - return 0; -} - -EXPORT_SYMBOL(ide_do_drive_cmd); -EXPORT_SYMBOL(atapi_discard_data); -EXPORT_SYMBOL(atapi_write_zeros); -EXPORT_SYMBOL(atapi_init_pc); - -EXPORT_SYMBOL(atapi_read); -EXPORT_SYMBOL(atapi_write); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/ataraid.c b/drivers/ide/ataraid.c --- a/drivers/ide/ataraid.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,306 +0,0 @@ -/* - ataraid.c Copyright (C) 2001 Red Hat, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - (for example /usr/src/linux/COPYING); if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Authors: Arjan van de Ven - - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ataraid.h" - -static struct raid_device_operations *ataraid_ops[16]; - -static int ataraid_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -static int ataraid_open(struct inode *inode, struct file *filp); -static int ataraid_release(struct inode *inode, struct file *filp); -static void ataraid_split_request(request_queue_t * q, int rw, - struct buffer_head *bh); - - -static struct gendisk ataraid_gendisk[16]; -static struct hd_struct *ataraid_part; -static char *ataraid_names; -static int ataraid_readahead[256]; - -static struct block_device_operations ataraid_fops = { - .owner = THIS_MODULE, - .open = ataraid_open, - .release = ataraid_release, - .ioctl = ataraid_ioctl, -}; - - - -static DECLARE_MUTEX(ataraid_sem); - -/* Bitmap for the devices currently in use */ -static unsigned int ataraiduse; - - -/* stub fops functions */ - -static int ataraid_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int minor; - minor = minor(inode->i_rdev) >> SHIFT; - - if ((ataraid_ops[minor]) && (ataraid_ops[minor]->ioctl)) - return (ataraid_ops[minor]->ioctl) (inode, file, cmd, arg); - return -EINVAL; -} - -static int ataraid_open(struct inode *inode, struct file *filp) -{ - int minor; - minor = minor(inode->i_rdev) >> SHIFT; - - if ((ataraid_ops[minor]) && (ataraid_ops[minor]->open)) - return (ataraid_ops[minor]->open) (inode, filp); - return -EINVAL; -} - - -static int ataraid_release(struct inode *inode, struct file *filp) -{ - int minor; - minor = minor(inode->i_rdev) >> SHIFT; - - if ((ataraid_ops[minor]) && (ataraid_ops[minor]->release)) - return (ataraid_ops[minor]->release) (inode, filp); - return -EINVAL; -} - -static int ataraid_make_request(request_queue_t * q, int rw, - struct buffer_head *bh) -{ - int minor; - int retval; - minor = minor(bh->b_rdev) >> SHIFT; - - if ((ataraid_ops[minor]) && (ataraid_ops[minor]->make_request)) { - - retval = (ataraid_ops[minor]->make_request) (q, rw, bh); - if (retval == -1) { - ataraid_split_request(q, rw, bh); - return 0; - } else - return retval; - } - return -EINVAL; -} - -struct buffer_head *ataraid_get_bhead(void) -{ - void *ptr = NULL; - while (!ptr) { - ptr = kmalloc(sizeof(struct buffer_head), GFP_NOIO); - if (!ptr) - yield(); - } - return ptr; -} - -EXPORT_SYMBOL(ataraid_get_bhead); - -struct ataraid_bh_private *ataraid_get_private(void) -{ - void *ptr = NULL; - while (!ptr) { - ptr = kmalloc(sizeof(struct ataraid_bh_private), GFP_NOIO); - if (!ptr) - yield(); - } - return ptr; -} - -EXPORT_SYMBOL(ataraid_get_private); - -void ataraid_end_request(struct buffer_head *bh, int uptodate) -{ - struct ataraid_bh_private *private = bh->b_private; - - if (private == NULL) - BUG(); - - if (atomic_dec_and_test(&private->count)) { - private->parent->b_end_io(private->parent, uptodate); - private->parent = NULL; - kfree(private); - } - kfree(bh); -} - -EXPORT_SYMBOL(ataraid_end_request); - -static void ataraid_split_request(request_queue_t * q, int rw, - struct buffer_head *bh) -{ - struct buffer_head *bh1, *bh2; - struct ataraid_bh_private *private; - bh1 = ataraid_get_bhead(); - bh2 = ataraid_get_bhead(); - - /* If either of those ever fails we're doomed */ - if ((!bh1) || (!bh2)) - BUG(); - private = ataraid_get_private(); - if (private == NULL) - BUG(); - - memcpy(bh1, bh, sizeof(*bh)); - memcpy(bh2, bh, sizeof(*bh)); - - bh1->b_end_io = ataraid_end_request; - bh2->b_end_io = ataraid_end_request; - - bh2->b_rsector += bh->b_size >> 10; - bh1->b_size /= 2; - bh2->b_size /= 2; - private->parent = bh; - - bh1->b_private = private; - bh2->b_private = private; - atomic_set(&private->count, 2); - - bh2->b_data += bh->b_size / 2; - - generic_make_request(rw, bh1); - generic_make_request(rw, bh2); -} - - - - -/* device register / release functions */ - - -int ataraid_get_device(struct raid_device_operations *fops) -{ - int bit; - down(&ataraid_sem); - if (ataraiduse == ~0U) { - up(&ataraid_sem); - return -ENODEV; - } - bit = ffz(ataraiduse); - ataraiduse |= 1 << bit; - ataraid_ops[bit] = fops; - up(&ataraid_sem); - return bit; -} - -void ataraid_release_device(int device) -{ - down(&ataraid_sem); - - if ((ataraiduse & (1 << device)) == 0) - BUG(); /* device wasn't registered at all */ - - ataraiduse &= ~(1 << device); - ataraid_ops[device] = NULL; - up(&ataraid_sem); -} - -void ataraid_register_disk(int device, long size) -{ - struct gendisk *disk = ataraid_gendisk + device; - char *name = ataraid_names + 12 * device; - - sprintf(name, "ataraid/d%d", device); - disk->part = ataraid_part + 16 * device; - disk->major = ATAMAJOR; - disk->first_minor = 16 * device; - disk->major_name = name; - disk->minor_shift = 4; - disk->nr_real = 1; - disk->fops = &ataraid_fops; - - add_gendisk(disk); - register_disk(disk, - mk_kdev(disk->major, disk->first_minor), - 1 << disk->minor_shift, - disk->fops, size); -} - -void ataraid_unregister_disk(int device) -{ - del_gendisk(&ataraid_gendisk[device]); -} - -static __init int ataraid_init(void) -{ - int i; - for (i = 0; i < 256; i++) - ataraid_readahead[i] = 1023; - - /* setup the gendisk structure */ - ataraid_part = kmalloc(256 * sizeof(struct hd_struct), GFP_KERNEL); - ataraid_names = kmalloc(16 * 12, GFP_KERNEL); - if (!ataraid_part || !ataraid_names) { - kfree(ataraid_part); - kfree(ataraid_names); - printk(KERN_ERR - "ataraid: Couldn't allocate memory, aborting \n"); - return -1; - } - - memset(ataraid_part, 0, 256 * sizeof(struct hd_struct)); - - if (register_blkdev(ATAMAJOR, "ataraid", &ataraid_fops)) { - kfree(ataraid_part); - kfree(ataraid_names); - printk(KERN_ERR "ataraid: Could not get major %d \n", - ATAMAJOR); - return -1; - } - - blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR), - ataraid_make_request); - - return 0; -} - -static void __exit ataraid_exit(void) -{ - unregister_blkdev(ATAMAJOR, "ataraid"); - kfree(ataraid_part); - kfree(ataraid_names); -} - -module_init(ataraid_init); -module_exit(ataraid_exit); - -EXPORT_SYMBOL(ataraid_get_device); -EXPORT_SYMBOL(ataraid_release_device); -EXPORT_SYMBOL(ataraid_register_disk); -EXPORT_SYMBOL(ataraid_unregister_disk); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/ataraid.h b/drivers/ide/ataraid.h --- a/drivers/ide/ataraid.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,65 +0,0 @@ -/* - ataraid.h Copyright (C) 2001 Red Hat, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - (for example /usr/src/linux/COPYING); if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Authors: Arjan van de Ven - - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define ATAMAJOR 114 -#define SHIFT 4 -#define MINOR_MASK 15 -#define MAJOR_MASK 15 - - -/* raid_device_operations is a light struct block_device_operations with an - added method for make_request */ -struct raid_device_operations { - int (*open) (struct inode *, struct file *); - int (*release) (struct inode *, struct file *); - int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); - int (*make_request) (request_queue_t *q, int rw, struct buffer_head * bh); -}; - - -struct geom { - unsigned char heads; - unsigned int cylinders; - unsigned char sectors; -}; - -/* structure for the splitting of bufferheads */ - -struct ataraid_bh_private { - struct buffer_head *parent; - atomic_t count; -}; - -extern int ataraid_get_device(struct raid_device_operations *fops); -extern void ataraid_release_device(int device); -extern void ataraid_register_disk(int device,long size); -extern void ataraid_unregister_disk(int device); -extern struct buffer_head *ataraid_get_bhead(void); -extern struct ataraid_bh_private *ataraid_get_private(void); -extern void ataraid_end_request(struct buffer_head *bh, int uptodate); diff -Nru a/drivers/ide/buddha.c b/drivers/ide/buddha.c --- a/drivers/ide/buddha.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,225 +0,0 @@ -/* - * linux/drivers/ide/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver - * - * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others - * - * This driver was written based on the specifications in README.buddha and - * the X-Surf info from Inside_XSurf.txt available at - * http://www.jschoenfeld.com - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * TODO: - * - test it :-) - * - tune the timings using the speed-register - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - - /* - * The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2 - */ - -#define BUDDHA_NUM_HWIFS 2 -#define CATWEASEL_NUM_HWIFS 3 -#define XSURF_NUM_HWIFS 2 - - /* - * Bases of the IDE interfaces (relative to the board address) - */ - -#define BUDDHA_BASE1 0x800 -#define BUDDHA_BASE2 0xa00 -#define BUDDHA_BASE3 0xc00 - -#define XSURF_BASE1 0xb000 /* 2.5" Interface */ -#define XSURF_BASE2 0xd000 /* 3.5" Interface */ - -static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = { - BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 -}; - -static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = { - XSURF_BASE1, XSURF_BASE2 -}; - - - /* - * Offsets from one of the above bases - */ - -#define BUDDHA_DATA 0x00 -#define BUDDHA_ERROR 0x06 /* see err-bits */ -#define BUDDHA_NSECTOR 0x0a /* nr of sectors to read/write */ -#define BUDDHA_SECTOR 0x0e /* starting sector */ -#define BUDDHA_LCYL 0x12 /* starting cylinder */ -#define BUDDHA_HCYL 0x16 /* high byte of starting cyl */ -#define BUDDHA_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ -#define BUDDHA_STATUS 0x1e /* see status-bits */ -#define BUDDHA_CONTROL 0x11a -#define XSURF_CONTROL -1 /* X-Surf has no CS1* (Control/AltStat) */ - -static int buddha_offsets[IDE_NR_PORTS] __initdata = { - BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, - BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL, -1 -}; - -static int xsurf_offsets[IDE_NR_PORTS] __initdata = { - BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, - BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, XSURF_CONTROL, -1 -}; - - /* - * Other registers - */ - -#define BUDDHA_IRQ1 0xf00 /* MSB = 1, Harddisk is source of */ -#define BUDDHA_IRQ2 0xf40 /* interrupt */ -#define BUDDHA_IRQ3 0xf80 - -#define XSURF_IRQ1 0x7e -#define XSURF_IRQ2 0x7e - -static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = { - BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3 -}; - -static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = { - XSURF_IRQ1, XSURF_IRQ2 -}; - -#define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */ - - - /* - * Board information - */ - -typedef enum BuddhaType_Enum { - BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF -} BuddhaType; - - - /* - * Check and acknowledge the interrupt status - */ - -static int buddha_ack_intr(struct ata_channel *hwif) -{ - unsigned char ch; - - ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) - return 0; - return 1; -} - -static int xsurf_ack_intr(struct ata_channel *hwif) -{ - unsigned char ch; - - ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); - /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */ - z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) - return 0; - return 1; -} - - /* - * Probe for a Buddha or Catweasel IDE interface - */ - -void __init buddha_init(void) -{ - hw_regs_t hw; - int i, index; - - struct zorro_dev *z = NULL; - u_long buddha_board = 0; - BuddhaType type; - int buddha_num_hwifs; - - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - unsigned long board; - if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { - buddha_num_hwifs = BUDDHA_NUM_HWIFS; - type=BOARD_BUDDHA; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) { - buddha_num_hwifs = CATWEASEL_NUM_HWIFS; - type=BOARD_CATWEASEL; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) { - buddha_num_hwifs = XSURF_NUM_HWIFS; - type=BOARD_XSURF; - } else - continue; - - board = z->resource.start; - - if(type != BOARD_XSURF) { - if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE")) - continue; - } else { - if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE")) - continue; - if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE")) - goto fail_base2; - if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) { - release_mem_region(board+XSURF_BASE2, 0x1000); -fail_base2: - release_mem_region(board+XSURF_BASE1, 0x1000); - continue; - } - } - buddha_board = ZTWO_VADDR(board); - - /* write to BUDDHA_IRQ_MR to enable the board IRQ */ - /* X-Surf doesn't have this. IRQs are always on */ - if (type != BOARD_XSURF) - z_writeb(0, buddha_board+BUDDHA_IRQ_MR); - - for(i=0;i -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" - -/* - * This flag is set in ide.c by the parameter: ide0=cmd640_vlb - */ -int cmd640_vlb = 0; - -/* - * CMD640 specific registers definition. - */ - -#define VID 0x00 -#define DID 0x02 -#define PCMD 0x04 -#define PCMD_ENA 0x01 -#define PSTTS 0x06 -#define REVID 0x08 -#define PROGIF 0x09 -#define SUBCL 0x0a -#define BASCL 0x0b -#define BaseA0 0x10 -#define BaseA1 0x14 -#define BaseA2 0x18 -#define BaseA3 0x1c -#define INTLINE 0x3c -#define INPINE 0x3d - -#define CFR 0x50 -#define CFR_DEVREV 0x03 -#define CFR_IDE01INTR 0x04 -#define CFR_DEVID 0x18 -#define CFR_AT_VESA_078h 0x20 -#define CFR_DSA1 0x40 -#define CFR_DSA0 0x80 - -#define CNTRL 0x51 -#define CNTRL_DIS_RA0 0x40 -#define CNTRL_DIS_RA1 0x80 -#define CNTRL_ENA_2ND 0x08 - -#define CMDTIM 0x52 -#define ARTTIM0 0x53 -#define DRWTIM0 0x54 -#define ARTTIM1 0x55 -#define DRWTIM1 0x56 -#define ARTTIM23 0x57 -#define ARTTIM23_DIS_RA2 0x04 -#define ARTTIM23_DIS_RA3 0x08 -#define DRWTIM23 0x58 -#define BRST 0x59 - -/* - * Protects register file access from overlapping on primary and secondary - * channel, since those share hardware resources. - */ -static spinlock_t cmd640_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; - -/* - * Registers and masks for easy access by drive index: - */ -static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; -static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - -static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; -static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; - -/* - * Current cmd640 timing values for each drive. - * The defaults for each are the slowest possible timings. - */ -static u8 setup_counts[4] = {4, 4, 4, 4}; /* Address setup count (in clocks) */ -static u8 active_counts[4] = {16, 16, 16, 16}; /* Active count (encoded) */ -static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ - -#endif - -/* - * These are initialized to point at the devices we control - */ -static struct ata_channel *cmd_hwif0, *cmd_hwif1; -static struct ata_device *cmd_drives[4]; - -/* - * Interface to access cmd640x registers - */ -static unsigned int cmd640_key; -static void (*put_cmd640_reg)(unsigned short reg, u8 val); -static u8 (*get_cmd640_reg)(unsigned short reg); - -/* - * This is read from the CFR reg, and is used in several places. - */ -static unsigned int cmd640_chip_version; - -/* - * The CMD640x chip does not support DWORD config write cycles, but some - * of the BIOSes use them to implement the config services. - * Therefore, we must use direct IO instead. - */ - -/* PCI method 1 access */ - -static void put_cmd640_reg_pci1 (unsigned short reg, u8 val) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_lock, flags); - outb_p((reg & 0xfc) | cmd640_key, 0xcf8); - outb_p(val, (reg & 3) | 0xcfc); - spin_unlock_irqrestore(&pci_lock, flags); -} - -static u8 get_cmd640_reg_pci1 (unsigned short reg) -{ - u8 b; - unsigned long flags; - - spin_lock_irqsave(&pci_lock, flags); - outb_p((reg & 0xfc) | cmd640_key, 0xcf8); - b=inb_p((reg & 3) | 0xcfc); - spin_unlock_irqrestore(&pci_lock, flags); - return b; -} - -/* PCI method 2 access (from CMD datasheet) */ - -static void put_cmd640_reg_pci2 (unsigned short reg, u8 val) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_lock, flags); - outb_p(0x10, 0xcf8); - outb_p(val, cmd640_key + reg); - outb_p(0, 0xcf8); - spin_unlock_irqrestore(&pci_lock, flags); -} - -static u8 get_cmd640_reg_pci2 (unsigned short reg) -{ - u8 b; - unsigned long flags; - - spin_lock_irqsave(&pci_lock, flags); - outb_p(0x10, 0xcf8); - b = inb_p(cmd640_key + reg); - outb_p(0, 0xcf8); - spin_unlock_irqrestore(&pci_lock, flags); - return b; -} - -/* VLB access */ - -static void put_cmd640_reg_vlb (unsigned short reg, u8 val) -{ - unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - outb_p(reg, cmd640_key); - outb_p(val, cmd640_key + 4); - spin_unlock_irqrestore(&cmd640_lock, flags); -} - -static u8 get_cmd640_reg_vlb (unsigned short reg) -{ - u8 b; - unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - outb_p(reg, cmd640_key); - b = inb_p(cmd640_key + 4); - spin_unlock_irqrestore(&cmd640_lock, flags); - return b; -} - -static int __init match_pci_cmd640_device (void) -{ - const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; - unsigned int i; - for (i = 0; i < 4; i++) { - if (get_cmd640_reg(i) != ven_dev[i]) - return 0; - } -#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT - if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) { - printk("ide: cmd640 on PCI disabled by BIOS\n"); - return 0; - } -#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */ - return 1; /* success */ -} - -/* - * Probe for CMD640x -- pci method 1 - */ -static int __init probe_for_cmd640_pci1 (void) -{ - get_cmd640_reg = get_cmd640_reg_pci1; - put_cmd640_reg = put_cmd640_reg_pci1; - for (cmd640_key = 0x80000000; cmd640_key <= 0x8000f800; cmd640_key += 0x800) { - if (match_pci_cmd640_device()) - return 1; /* success */ - } - return 0; -} - -/* - * Probe for CMD640x -- pci method 2 - */ -static int __init probe_for_cmd640_pci2 (void) -{ - get_cmd640_reg = get_cmd640_reg_pci2; - put_cmd640_reg = put_cmd640_reg_pci2; - for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { - if (match_pci_cmd640_device()) - return 1; /* success */ - } - return 0; -} - -/* - * Probe for CMD640x -- vlb - */ -static int __init probe_for_cmd640_vlb (void) -{ - u8 b; - - get_cmd640_reg = get_cmd640_reg_vlb; - put_cmd640_reg = put_cmd640_reg_vlb; - cmd640_key = 0x178; - b = get_cmd640_reg(CFR); - if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { - cmd640_key = 0x78; - b = get_cmd640_reg(CFR); - if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h)) - return 0; - } - return 1; /* success */ -} - -/* - * Returns 1 if an IDE interface/drive exists at 0x170, - * Returns 0 otherwise. - */ -static int __init secondary_port_responding (void) -{ - unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - - outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ - udelay(100); - if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) { - outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ - udelay(100); - if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { - spin_unlock_irqrestore(&cmd640_lock, flags); - return 0; /* nothing responded */ - } - } - spin_unlock_irqrestore(&cmd640_lock, flags); - return 1; /* success */ -} - -#ifdef CMD640_DUMP_REGS -/* - * Dump out all cmd640 registers. May be called from ide.c - */ -void cmd640_dump_regs (void) -{ - unsigned int reg = cmd640_vlb ? 0x50 : 0x00; - - /* Dump current state of chip registers */ - printk("ide: cmd640 internal register dump:"); - for (; reg <= 0x59; reg++) { - if (!(reg & 0x0f)) - printk("\n%04x:", reg); - printk(" %02x", get_cmd640_reg(reg)); - } - printk("\n"); -} -#endif - -/* - * Check whether prefetch is on for a drive, - * and initialize the unmask flags for safe operation. - */ -static void __init check_prefetch (unsigned int index) -{ - struct ata_device *drive = cmd_drives[index]; - u8 b = get_cmd640_reg(prefetch_regs[index]); - - if (b & prefetch_masks[index]) { /* is prefetch off? */ - drive->channel->no_unmask = 0; - drive->channel->no_io_32bit = 1; - drive->channel->io_32bit = 0; - } else { -#if CMD640_PREFETCH_MASKS - drive->channel->no_unmask = 1; - drive->channel->unmask = 0; -#endif - drive->channel->no_io_32bit = 0; - } -} - -/* - * Figure out which devices we control - */ -static void __init setup_device_ptrs (void) -{ - unsigned int i; - - cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */ - cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ - for (i = 0; i < MAX_HWIFS; i++) { - struct ata_channel *hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) { - if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0) - cmd_hwif0 = hwif; - else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - cmd_hwif1 = hwif; - } - } - cmd_drives[0] = &cmd_hwif0->drives[0]; - cmd_drives[1] = &cmd_hwif0->drives[1]; - cmd_drives[2] = &cmd_hwif1->drives[0]; - cmd_drives[3] = &cmd_hwif1->drives[1]; -} - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - -/* - * Sets prefetch mode for a drive. - */ -static void set_prefetch_mode (unsigned int index, int mode) -{ - struct ata_device *drive = cmd_drives[index]; - int reg = prefetch_regs[index]; - u8 b; - unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - b = get_cmd640_reg(reg); - if (mode) { /* want prefetch on? */ -# if CMD640_PREFETCH_MASKS - drive->channel->no_unmask = 1; - drive->channel->unmask = 0; -# endif - drive->channel->no_io_32bit = 0; - b &= ~prefetch_masks[index]; /* enable prefetch */ - } else { - drive->channel->no_unmask = 0; - drive->channel->no_io_32bit = 1; - drive->channel->io_32bit = 0; - b |= prefetch_masks[index]; /* disable prefetch */ - } - put_cmd640_reg(reg, b); - spin_unlock_irqrestore(&cmd640_lock, flags); -} - -/* - * Dump out current drive clocks settings - */ -static void display_clocks (unsigned int index) -{ - u8 active_count, recovery_count; - - active_count = active_counts[index]; - if (active_count == 1) - ++active_count; - recovery_count = recovery_counts[index]; - if (active_count > 3 && recovery_count == 1) - ++recovery_count; - if (cmd640_chip_version > 1) - recovery_count += 1; /* cmd640b uses (count + 1)*/ - printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count); -} - -/* - * Pack active and recovery counts into single byte representation - * used by controller - */ -static inline u8 pack_nibbles (u8 upper, u8 lower) -{ - return ((upper & 0x0f) << 4) | (lower & 0x0f); -} - -/* - * This routine retrieves the initial drive timings from the chipset. - */ -static void __init retrieve_drive_counts (unsigned int index) -{ - u8 b; - - /* - * Get the internal setup timing, and convert to clock count - */ - b = get_cmd640_reg(arttim_regs[index]) & ~0x3f; - switch (b) { - case 0x00: b = 4; break; - case 0x80: b = 3; break; - case 0x40: b = 2; break; - default: b = 5; break; - } - setup_counts[index] = b; - - /* - * Get the active/recovery counts - */ - b = get_cmd640_reg(drwtim_regs[index]); - active_counts[index] = (b >> 4) ? (b >> 4) : 0x10; - recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10; -} - - -/* - * This routine writes the prepared setup/active/recovery counts - * for a drive into the cmd640 chipset registers to active them. - */ -static void program_drive_counts (unsigned int index) -{ - unsigned long flags; - u8 setup_count = setup_counts[index]; - u8 active_count = active_counts[index]; - u8 recovery_count = recovery_counts[index]; - - /* - * Set up address setup count and drive read/write timing registers. - * Primary interface has individual count/timing registers for - * each drive. Secondary interface has one common set of registers, - * so we merge the timings, using the slowest value for each timing. - */ - if (index > 1) { - unsigned int mate; - if (cmd_drives[mate = index ^ 1]->present) { - if (setup_count < setup_counts[mate]) - setup_count = setup_counts[mate]; - if (active_count < active_counts[mate]) - active_count = active_counts[mate]; - if (recovery_count < recovery_counts[mate]) - recovery_count = recovery_counts[mate]; - } - } - - /* - * Convert setup_count to internal chipset representation - */ - switch (setup_count) { - case 4: setup_count = 0x00; break; - case 3: setup_count = 0x80; break; - case 1: - case 2: setup_count = 0x40; break; - default: setup_count = 0xc0; /* case 5 */ - } - - /* - * Now that everything is ready, program the new timings - */ - spin_lock_irqsave(&cmd640_lock, flags); - /* - * Program the address_setup clocks into ARTTIM reg, - * and then the active/recovery counts into the DRWTIM reg - * (this converts counts of 16 into counts of zero -- okay). - */ - setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; - put_cmd640_reg(arttim_regs[index], setup_count); - put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); - spin_unlock_irqrestore(&cmd640_lock, flags); -} - -/* - * Set a specific pio_mode for a drive - */ -static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time, unsigned int active_time, unsigned int setup_time) -{ - int recovery_time, clock_time; - u8 setup_count, active_count; - u8 recovery_count, recovery_count2; - u8 cycle_count; - - recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000000 / system_bus_speed; - cycle_count = (cycle_time + clock_time - 1) / clock_time; - - setup_count = (setup_time + clock_time - 1) / clock_time; - - active_count = (active_time + clock_time - 1) / clock_time; - if (active_count < 2) - active_count = 2; /* minimum allowed by cmd640 */ - - recovery_count = (recovery_time + clock_time - 1) / clock_time; - recovery_count2 = cycle_count - (setup_count + active_count); - if (recovery_count2 > recovery_count) - recovery_count = recovery_count2; - if (recovery_count < 2) - recovery_count = 2; /* minimum allowed by cmd640 */ - if (recovery_count > 17) { - active_count += recovery_count - 17; - recovery_count = 17; - } - if (active_count > 16) - active_count = 16; /* maximum allowed by cmd640 */ - if (cmd640_chip_version > 1) - recovery_count -= 1; /* cmd640b uses (count + 1)*/ - if (recovery_count > 16) - recovery_count = 16; /* maximum allowed by cmd640 */ - - setup_counts[index] = setup_count; - active_counts[index] = active_count; - recovery_counts[index] = recovery_count; - - /* - * In a perfect world, we might set the drive pio mode here - * (using WIN_SETFEATURE) before continuing. - * - * But we do not, because: - * 1) this is the wrong place to do it (proper is do_special() in ide.c) - * 2) in practice this is rarely, if ever, necessary - */ - program_drive_counts (index); -} - -/* - * Drive PIO mode selection: - */ -static void cmd640_tune_drive(struct ata_device *drive, u8 mode_wanted) -{ - u8 b; - struct ata_timing *t; - unsigned int index = 0; - unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - - while (drive != cmd_drives[index]) { - if (++index > 3) { - printk(KERN_ERR "%s: bad news in cmd640_tune_drive\n", drive->name); - goto out_lock; - } - } - switch (mode_wanted) { - case 6: /* set fast-devsel off */ - case 7: /* set fast-devsel on */ - mode_wanted &= 1; - b = get_cmd640_reg(CNTRL) & ~0x27; - if (mode_wanted) - b |= 0x27; - put_cmd640_reg(CNTRL, b); - printk(KERN_INFO "%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, mode_wanted ? "en" : "dis"); - goto out_lock; - - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - mode_wanted &= 1; - set_prefetch_mode(index, mode_wanted); - printk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis"); - goto out_lock; - } - - if (mode_wanted == 255) - t = ata_timing_data(ata_timing_mode(drive, XFER_PIO | XFER_EPIO)); - else - t = ata_timing_data(XFER_PIO_0 + min_t(u8, mode_wanted, 4)); - - cmd640_set_mode(index, t->mode - XFER_PIO_0, t->cycle, t->active, t->setup); - - printk ("%s: selected cmd640 PIO mode%d (%dns)", - drive->name, t->mode, t->cycle); - - display_clocks(index); - -out_lock: - spin_unlock_irqrestore(&cmd640_lock, flags); - - return; -} - -#endif - -/** - * pci_conf1 - check for PCI type 1 configuration - * - * Issues a safe probe sequence for PCI configuration type 1 and - * returns non-zero if conf1 is supported. Takes the pci_config lock - */ - -static int pci_conf1(void) -{ - u32 tmp; - unsigned long flags; - - spin_lock_irqsave(&pci_lock, flags); - - OUT_BYTE(0x01, 0xCFB); - tmp = inl(0xCF8); - outl(0x80000000, 0xCF8); - if (inl(0xCF8) == 0x80000000) { - spin_unlock_irqrestore(&pci_lock, flags); - outl(tmp, 0xCF8); - return 1; - } - outl(tmp, 0xCF8); - spin_unlock_irqrestore(&pci_lock, flags); - return 0; -} - -/** - * pci_conf2 - check for PCI type 2 configuration - * - * Issues a safe probe sequence for PCI configuration type 2 and - * returns non-zero if conf2 is supported. Takes the pci_config lock. - */ - - -static int pci_conf2(void) -{ - unsigned long flags; - spin_lock_irqsave(&pci_lock, flags); - - OUT_BYTE(0x00, 0xCFB); - OUT_BYTE(0x00, 0xCF8); - OUT_BYTE(0x00, 0xCFA); - if (IN_BYTE(0xCF8) == 0x00 && IN_BYTE(0xCFA) == 0x00) { - spin_unlock_irqrestore(&pci_lock, flags); - return 1; - } - spin_unlock_irqrestore(&pci_lock, flags); - return 0; -} - -/* - * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c - */ - -int __init ide_probe_for_cmd640x(void) -{ -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - int second_port_toggled = 0; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - int second_port_cmd640 = 0; - const char *bus_type, *port2; - unsigned int index; - u8 b, cfr; - - if (cmd640_vlb && probe_for_cmd640_vlb()) { - bus_type = "VLB"; - } else { - cmd640_vlb = 0; - if (pci_conf1() && probe_for_cmd640_pci1()) - bus_type = "PCI (type1)"; - else if (pci_conf2() && probe_for_cmd640_pci2()) - bus_type = "PCI (type2)"; - else - return 0; - } - /* - * Undocumented magic (there is no 0x5b reg in specs) - */ - put_cmd640_reg(0x5b, 0xbd); - if (get_cmd640_reg(0x5b) != 0xbd) { - printk("ide: cmd640 init failed: wrong value in reg 0x5b\n"); - return 0; - } - put_cmd640_reg(0x5b, 0); - -#ifdef CMD640_DUMP_REGS - CMD640_DUMP_REGS; -#endif - - /* - * Documented magic begins here - */ - cfr = get_cmd640_reg(CFR); - cmd640_chip_version = cfr & CFR_DEVREV; - if (cmd640_chip_version == 0) { - printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version); - return 0; - } - - /* - * Initialize data for primary port - */ - 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->tuneproc = &cmd640_tune_drive; -#endif - - /* - * Ensure compatibility by always using the slowest timings - * for access to the drive's command register block, - * and reset the prefetch burstsize to default (512 bytes). - * - * Maybe we need a way to NOT do these on *some* systems? - */ - put_cmd640_reg(CMDTIM, 0); - put_cmd640_reg(BRST, 0x40); - - /* - * Try to enable the secondary interface, if not already enabled - */ - if (cmd_hwif1->noprobe) { - port2 = "not probed"; - } else { - b = get_cmd640_reg(CNTRL); - if (secondary_port_responding()) { - if ((b & CNTRL_ENA_2ND)) { - second_port_cmd640 = 1; - port2 = "okay"; - } else if (cmd640_vlb) { - second_port_cmd640 = 1; - port2 = "alive"; - } else - port2 = "not cmd640"; - } else { - put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ - if (secondary_port_responding()) { - second_port_cmd640 = 1; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - second_port_toggled = 1; -#endif - port2 = "enabled"; - } else { - put_cmd640_reg(CNTRL, b); /* restore original setting */ - port2 = "not responding"; - } - } - } - - /* - * 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_hwif1->unit = ATA_SECONDARY; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif1->tuneproc = &cmd640_tune_drive; -#endif - } - printk("%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, - cmd_hwif0->serialized ? "" : "not ", port2); - - /* - * Establish initial timings/prefetch for all drives. - * Do not unnecessarily disturb any prior BIOS setup of these. - */ - for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { - struct ata_device *drive = cmd_drives[index]; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - if (drive->autotune || ((index > 1) && second_port_toggled)) { - /* - * Reset timing to the slowest speed and turn off prefetch. - * This way, the drive identify code has a better chance. - */ - setup_counts [index] = 4; /* max possible */ - active_counts [index] = 16; /* max possible */ - recovery_counts [index] = 16; /* max possible */ - program_drive_counts (index); - set_prefetch_mode (index, 0); - printk("cmd640: drive%d timings/prefetch cleared\n", index); - } else { - /* - * Record timings/prefetch without changing them. - * This preserves any prior BIOS setup. - */ - retrieve_drive_counts (index); - check_prefetch (index); - printk("cmd640: drive%d timings/prefetch(%s) preserved", - index, drive->channel->no_io_32bit ? "off" : "on"); - display_clocks(index); - } -#else - /* - * Set the drive unmask flags to match the prefetch setting - */ - check_prefetch (index); - printk("cmd640: drive%d timings/prefetch(%s) preserved\n", - index, drive->channel->no_io_32bit ? "off" : "on"); -#endif - } - -#ifdef CMD640_DUMP_REGS - CMD640_DUMP_REGS; -#endif - return 1; -} - diff -Nru a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c --- a/drivers/ide/cmd64x.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,860 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 - * - * linux/drivers/ide/cmd64x.c Version 1.22 June 9, 2000 - * - * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. - * Note, this driver is not used at all on other systems because - * there the "BIOS" has done all of the following already. - * Due to massive hardware bugs, UDMA is not supported on the 646U. - * - * Copyright (C) 1998 Eddie C. Dost - * Copyright (C) 1998 David S. Miller - * Copyright (C) 1999-2002 Andre Hedrick - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "pcihost.h" - -#define CMD_DEBUG 0 - -#if CMD_DEBUG -#define cmdprintk(x...) printk(##x) -#else -#define cmdprintk(x...) -#endif - -/* - * CMD64x specific registers definition. - */ - -#define CFR 0x50 -#define CFR_INTR_CH0 0x02 -#define CNTRL 0x51 -#define CNTRL_DIS_RA0 0x40 -#define CNTRL_DIS_RA1 0x80 -#define CNTRL_ENA_2ND 0x08 - -#define CMDTIM 0x52 -#define ARTTIM0 0x53 -#define DRWTIM0 0x54 -#define ARTTIM1 0x55 -#define DRWTIM1 0x56 -#define ARTTIM23 0x57 -#define ARTTIM23_DIS_RA2 0x04 -#define ARTTIM23_DIS_RA3 0x08 -#define ARTTIM23_INTR_CH1 0x10 -#define ARTTIM2 0x57 -#define ARTTIM3 0x57 -#define DRWTIM23 0x58 -#define DRWTIM2 0x58 -#define BRST 0x59 -#define DRWTIM3 0x5b - -#define BMIDECR0 0x70 -#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 - -/* - * Registers and masks for easy access by drive index: - */ -#if 0 -static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; -static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; -#endif - -/* - * This routine writes the prepared setup/active/recovery counts - * for a drive into the cmd646 chipset registers to active them. - */ -static void program_drive_counts(struct ata_device *drive, int setup_count, int active_count, int recovery_count) -{ - unsigned long flags; - struct ata_device *drives = drive->channel->drives; - u8 temp_b; - static const u8 setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; - static const u8 recovery_counts[] = - {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; - static const u8 arttim_regs[2][2] = { - { ARTTIM0, ARTTIM1 }, - { ARTTIM23, ARTTIM23 } - }; - static const u8 drwtim_regs[2][2] = { - { DRWTIM0, DRWTIM1 }, - { DRWTIM2, DRWTIM3 } - }; - int channel = drive->channel->unit; - int slave = (drives != drive); /* Is this really the best way to determine this?? */ - - cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n", setup_count, - active_count, recovery_count, drive->present); - /* - * Set up address setup count registers. - * Primary interface has individual count/timing registers for - * each drive. Secondary interface has one common set of registers, - * for address setup so we merge these timings, using the slowest - * value. - */ - if (channel) { - drive->drive_data = setup_count; - setup_count = max(drives[0].drive_data, drives[1].drive_data); - cmdprintk("Secondary interface, setup_count = %d\n", setup_count); - } - - /* - * Convert values to internal chipset representation - */ - setup_count = (setup_count > 5) ? 0xc0 : (int) setup_counts[setup_count]; - active_count &= 0xf; /* Remember, max value is 16 */ - recovery_count = (int) recovery_counts[recovery_count]; - - cmdprintk("Final values = %d,%d,%d\n", setup_count, active_count, recovery_count); - - /* - * Now that everything is ready, program the new timings - */ - local_irq_save(flags); - /* - * Program the address_setup clocks into ARTTIM reg, - * and then the active/recovery counts into the DRWTIM reg - */ - (void) pci_read_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave], &temp_b); - (void) pci_write_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave], - ((u8) setup_count) | (temp_b & 0x3f)); - (void) pci_write_config_byte(drive->channel->pci_dev, drwtim_regs[channel][slave], - (u8) ((active_count << 4) | recovery_count)); - cmdprintk ("Write %x to %x\n", ((u8) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]); - cmdprintk ("Write %x to %x\n", (u8) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]); - local_irq_restore(flags); -} - -/* - * Attempts to set the interface PIO mode. Special cases are - * 8: prefetch off, 9: prefetch on, 255: auto-select best mode. - * Called with 255 at boot time. - */ -static void cmd64x_tuneproc(struct ata_device *drive, u8 pio) -{ - int T; - u8 speed, active, recover; - struct ata_timing *t; - - switch (pio) { - /* FIXME: b0rken --bkz */ - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - pio &= 1; - /*set_prefetch_mode(index, mode_wanted);*/ - cmdprintk("%s: %sabled cmd640 prefetch\n", drive->name, - pio ? "en" : "dis"); - return; - } - - if (pio == 255) - speed = ata_best_pio_mode(drive); - else - speed = XFER_PIO_0 + min_t(u8, pio, 4); - - t = ata_timing_data(speed); - - /* - * I copied all this complicated stuff from cmd640.c and made a few minor changes. - * For now I am just going to pray that it is correct. - */ - /* FIXME: verify it --bkz */ - - T = 1000000000 / system_bus_speed; - ata_timing_quantize(t, t, T, T); - - /* FIXME: maybe switch to ata_timing_compute() --bkz */ - recover = t->cycle - (t->setup + t->active); - active = t->active; - - if (recover > 16) { - active += recover - 16; - recover = 16; - } - if (active > 16) - active = 16; /* maximum allowed by CMD646 */ - - /* - * In a perfect world, we might set the drive pio mode here - * (using WIN_SETFEATURE) before continuing. - * - * But we do not, because: - * 1) this is the wrong place to do it (proper is do_special() in ide.c) - * 2) in practice this is rarely, if ever, necessary - */ - program_drive_counts(drive, t->setup, active, recover); - - cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns), clocks=%d/%d/%d\n", - drive->name, t.mode - XFER_PIO_0, pio, t->cycle, - t->setup, active, recover); - - ide_config_drive_speed(drive, speed); -} - -static int __init cmd6xx_modes_map(struct ata_channel *ch) -{ - struct pci_dev *dev = ch->pci_dev; - int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_680: - map |= XFER_UDMA_133; - case PCI_DEVICE_ID_CMD_649: - map |= XFER_UDMA_100; - case PCI_DEVICE_ID_CMD_648: - map |= XFER_UDMA_66; - case PCI_DEVICE_ID_CMD_643: - map |= XFER_UDMA; - break; - case PCI_DEVICE_ID_CMD_646: - { - u32 rev; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &rev); - rev &= 0xff; - /* - * UltraDMA only supported on PCI646U and PCI646U2, which - * correspond to revisions 0x03, 0x05 and 0x07 respectively. - * Actually, although the CMD tech support people won't - * tell me the details, the 0x03 revision cannot support - * UDMA correctly without hardware modifications, and even - * then it only works with Quantum disks due to some - * hold time assumptions in the 646U part which are fixed - * in the 646U2. - * - * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. - */ - switch(rev) { - case 0x07: - case 0x05: - map |= XFER_UDMA; - default: /* 0x03, 0x01 */ - break; - } - } - } - - return map; -} - -static u8 cmd680_taskfile_timing(struct ata_channel *ch) -{ - u8 addr_mask = (ch->unit) ? 0xB2 : 0xA2; - u16 timing; - - pci_read_config_word(ch->pci_dev, addr_mask, &timing); - - switch (timing) { - case 0x10c1: return 4; - case 0x10c3: return 3; - case 0x1281: return 2; - case 0x2283: return 1; - case 0x328a: - default: return 0; - } -} - -static void cmd680_tuneproc(struct ata_device *drive, u8 pio) -{ - struct ata_channel *ch = drive->channel; - struct pci_dev *dev = ch->pci_dev; - u8 unit = (drive->select.b.unit & 0x01); - u8 addr_mask = (ch->unit) ? 0x84 : 0x80; - u8 drive_pci, mode_pci, speed; - u8 channel_timings = cmd680_taskfile_timing(ch); - u16 speedt; - - pci_read_config_byte(dev, addr_mask, &mode_pci); - mode_pci &= ~(unit ? 0x30 : 0x03); - - if (pio == 255) - pio = ata_best_pio_mode(drive) - XFER_PIO_0; - - /* WARNING PIO timing mess is going to happen b/w devices, argh */ - if ((channel_timings != pio) && (pio > channel_timings)) - pio = channel_timings; - - switch (drive->dn) { - case 0: drive_pci = 0xA4; break; - case 1: drive_pci = 0xA6; break; - case 2: drive_pci = 0xB4; break; - case 3: drive_pci = 0xB6; break; - default: return; - } - - pci_read_config_word(dev, drive_pci, &speedt); - - /* cheat for now and use the docs */ -// switch(cmd680_taskfile_timing(hwif)) { - switch(pio) { - case 4: speedt = 0x10c1; break; - case 3: speedt = 0x10C3; break; - case 2: speedt = 0x1104; break; - case 1: speedt = 0x2283; break; - case 0: - default: speedt = 0x328A; break; - } - pci_write_config_word(dev, drive_pci, speedt); - - speed = XFER_PIO_0 + min_t(u8, pio, 4); - - ide_config_drive_speed(drive, speed); -} - -static int cmd64x_tune_chipset(struct ata_device *drive, u8 speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - - u8 unit = (drive->select.b.unit & 0x01); - u8 pciU = (hwif->unit) ? UDIDETCR1 : UDIDETCR0; - u8 pciD = (hwif->unit) ? BMIDESR1 : BMIDESR0; - u8 regU, regD, U = 0, D = 0; - - if ((drive->type != ATA_DISK) && (speed < XFER_SW_DMA_0)) - return 1; - - pci_read_config_byte(dev, pciD, ®D); - pci_read_config_byte(dev, pciU, ®U); - - /* unit 1 - 01000000b unit 0 - 00100000b */ - regD &= ~(unit ? 0x40 : 0x20); - - /* unit 1 - 11001010b unit 0 - 00110101b */ - regU &= ~(unit ? 0xCA : 0x35); - - pci_write_config_byte(dev, pciD, regD); - pci_write_config_byte(dev, pciU, regU); - - pci_read_config_byte(dev, pciD, ®D); - pci_read_config_byte(dev, pciU, ®U); - - switch(speed) { - /* FIXME: use tables --bkz */ - case XFER_UDMA_5: U = 0x05; break; - case XFER_UDMA_4: U = 0x15; break; - case XFER_UDMA_3: U = 0x25; break; - case XFER_UDMA_2: U = 0x11; break; - case XFER_UDMA_1: U = 0x21; break; - case XFER_UDMA_0: U = 0x31; break; - case XFER_MW_DMA_2: D = 0x10; break; - case XFER_MW_DMA_1: D = 0x20; break; - case XFER_MW_DMA_0: D = 0x30; break; - case XFER_SW_DMA_2: D = 0x10; break; - case XFER_SW_DMA_1: D = 0x20; break; - case XFER_SW_DMA_0: D = 0x30; break; -#else - switch(speed) { -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - cmd64x_tuneproc(drive, speed - XFER_PIO_0); - /* FIXME: error checking --bkz */ - return 0; - default: - return 1; - } - - cmd64x_tuneproc(drive, 255); -#ifdef CONFIG_BLK_DEV_IDEDMA - - if (unit) { - if (speed >= XFER_UDMA_0) - regU |= (((U & 0xf0) << 2) | ((U & 0x0f) << 1)); - else if (speed >= XFER_SW_DMA_0) - regD |= ((D & 0xf0) << 2); - } else { - regU |= U; - regD |= D; - } - - pci_write_config_byte(dev, pciU, regU); - - regD |= (unit ? 0x40 : 0x20); - pci_write_config_byte(dev, pciD, regD); -#endif - - return ide_config_drive_speed(drive, speed); -} - -static int cmd680_tune_chipset(struct ata_device *drive, u8 speed) -{ - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - u8 addr_mask = (hwif->unit) ? 0x84 : 0x80; - u8 unit = (drive->select.b.unit & 0x01); - u8 dma_pci, udma_pci; - u8 mode_pci, scsc, scsc_on = 0; - u16 ultra, multi; - - pci_read_config_byte(dev, addr_mask, &mode_pci); - pci_read_config_byte(dev, 0x8A, &scsc); - - switch (drive->dn) { - case 0: dma_pci = 0xA8; break; - case 1: dma_pci = 0xAA; break; - case 2: dma_pci = 0xB8; break; - case 3: dma_pci = 0xBA; break; - default: return 1; - } - udma_pci = dma_pci + 4; - - pci_read_config_byte(dev, addr_mask, &mode_pci); - mode_pci &= ~((unit) ? 0x30 : 0x03); - pci_read_config_word(dev, dma_pci, &multi); - pci_read_config_word(dev, udma_pci, &ultra); - - if ((speed == XFER_UDMA_6) && (scsc & 0x30) == 0x00) { - pci_write_config_byte(dev, 0x8A, scsc|0x01); - pci_read_config_byte(dev, 0x8A, &scsc); - } - - if (speed >= XFER_UDMA_0) { - ultra &= ~0x3F; - multi = 0x10C1; - scsc_on = ((scsc & 0x30) == 0x00) ? 1 : 0; - } - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_6: - if (scsc_on) - goto speed_break; - ultra |= 0x01; - break; -speed_break : - speed = XFER_UDMA_5; - case XFER_UDMA_5: - ultra |= (scsc_on ? 0x01 : 0x02); - break; - case XFER_UDMA_4: - ultra |= (scsc_on ? 0x02 : 0x03); - break; - case XFER_UDMA_3: - ultra |= (scsc_on ? 0x04 : 0x05); - break; - case XFER_UDMA_2: - ultra |= (scsc_on ? 0x05 : 0x07); - break; - case XFER_UDMA_1: - ultra |= (scsc_on ? 0x07 : 0x0B); - break; - case XFER_UDMA_0: - ultra |= (scsc_on ? 0x0C : 0x0F); - break; - case XFER_MW_DMA_2: - multi = 0x10C1; - break; - case XFER_MW_DMA_1: - multi = 0x10C2; - break; - case XFER_MW_DMA_0: - multi = 0x2208; - break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - cmd680_tuneproc(drive, speed - XFER_PIO_0); - /* FIXME: error checking --bkz */ - return 0; - default: - return 1; - } - - cmd680_tuneproc(drive, 255); - if (speed >= XFER_UDMA_0) - mode_pci |= ((unit) ? 0x30 : 0x03); - else if (speed >= XFER_MW_DMA_0) - mode_pci |= ((unit) ? 0x20 : 0x02); - else - mode_pci |= ((unit) ? 0x10 : 0x01); - - pci_write_config_byte(dev, addr_mask, mode_pci); - pci_write_config_word(dev, dma_pci, multi); - pci_write_config_word(dev, udma_pci, ultra); - - return ide_config_drive_speed(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int cmd64x_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - u8 dma_stat = 0; - unsigned long dma_base = ch->dma_base; - struct pci_dev *dev = ch->pci_dev; - u8 jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0; - - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - if (jack_slap) { - u8 dma_intr = 0; - u8 dma_mask = (ch->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; - u8 dma_reg = (ch->unit) ? ARTTIM2 : CFR; - (void) pci_read_config_byte(dev, dma_reg, &dma_intr); - /* - * DAMN BMIDE is not connected to PCI space! - * Have to manually jack-slap that bitch! - * To allow the PCI side to read incoming interrupts. - */ - (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); /* clear the INTR bit */ - } - udma_destroy_table(ch); /* purge DMA mappings */ - return (dma_stat & 7) != 4; /* verify good DMA status */ -} - -static int cmd64x_udma_irq_status(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - u8 dma_stat = 0; - u8 dma_alt_stat = 0; - unsigned long dma_base = ch->dma_base; - struct pci_dev *dev = ch->pci_dev; - u8 mask = (ch->unit) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; - - dma_stat = inb(dma_base+2); - (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat); -#ifdef DEBUG - printk("%s: dma_stat: 0x%02x dma_alt_stat: 0x%02x mask: 0x%02x\n", drive->name, dma_stat, dma_alt_stat, mask); -#endif - if (!(dma_alt_stat & mask)) { - return 0; - } - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ -} - -/* - * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old - * event order for DMA transfers. - */ -static int cmd646_1_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - u8 dma_stat; - - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - udma_destroy_table(ch); /* and free any DMA resources */ - return (dma_stat & 7) != 4; /* verify good DMA status */ -} - -#endif - -static int cmd680_busproc(struct ata_device * drive, int state) -{ -#if 0 - struct ata_channel *ch = drive->channel; - u8 addr_mask = (ch->unit) ? 0xB0 : 0xA0; - u32 stat_config = 0; - - pci_read_config_dword(ch->pci_dev, addr_mask, &stat_config); - - if (!ch) - return -EINVAL; - - switch (state) { - case BUSSTATE_ON: - ch->drives[0].failures = 0; - ch->drives[1].failures = 0; - break; - case BUSSTATE_OFF: - ch->drives[0].failures = ch->drives[0].max_failures + 1; - ch->drives[1].failures = ch->drives[1].max_failures + 1; - break; - case BUSSTATE_TRISTATE: - ch->drives[0].failures = ch->drives[0].max_failures + 1; - ch->drives[1].failures = ch->drives[1].max_failures + 1; - break; - default: - return 0; - } - ch->bus_state = state; -#endif - return 0; -} - -static void cmd680_reset(struct ata_device *drive) -{ -#if 0 - struct ata_channel *ch = drive->channel; - u8 addr_mask = (ch->unit) ? 0xB0 : 0xA0; - u8 reset = 0; - - pci_read_config_byte(ch->pci_dev, addr_mask, &reset); - pci_write_config_byte(ch->pci_dev, addr_mask, reset|0x03); -#endif -} - -static unsigned int cmd680_pci_init(struct pci_dev *dev) -{ - u8 tmpbyte = 0; - pci_write_config_byte(dev, 0x80, 0x00); - pci_write_config_byte(dev, 0x84, 0x00); - pci_read_config_byte(dev, 0x8A, &tmpbyte); - pci_write_config_byte(dev, 0x8A, tmpbyte|0x01); - pci_write_config_word(dev, 0xA2, 0x328A); - pci_write_config_dword(dev, 0xA4, 0x328A); - pci_write_config_dword(dev, 0xA8, 0x4392); - pci_write_config_dword(dev, 0xAC, 0x4009); - pci_write_config_word(dev, 0xB2, 0x328A); - pci_write_config_dword(dev, 0xB4, 0x328A); - pci_write_config_dword(dev, 0xB8, 0x4392); - pci_write_config_dword(dev, 0xBC, 0x4009); - - return 0; -} - -static unsigned int cmd64x_pci_init(struct pci_dev *dev) -{ - u8 mrdmode; - u32 class_rev; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - -#ifdef __i386__ - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", dev->name, dev->resource[PCI_ROM_RESOURCE].start); - } -#endif - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_643: - break; - case PCI_DEVICE_ID_CMD_646: - printk("%s: chipset revision 0x%02X, ", dev->name, class_rev); - switch(class_rev) { - case 0x07: - case 0x05: - printk("UltraDMA Capable"); - break; - case 0x03: - printk("MultiWord DMA Force Limited"); - break; - case 0x01: - default: - printk("MultiWord DMA Limited, IRQ workaround enabled"); - break; - } - printk("\n"); - break; - default: /* 648, 649 */ - break; - } - - /* Set a good latency timer and cache line size value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); -#ifdef __sparc_v9__ - (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); -#endif - - - /* Setup interrupts. */ - (void) pci_read_config_byte(dev, MRDMODE, &mrdmode); - mrdmode &= ~(0x30); - (void) pci_write_config_byte(dev, MRDMODE, mrdmode); - - /* Use MEMORY READ LINE for reads. - * NOTE: Although not mentioned in the PCI0646U specs, - * these bits are write only and won't be read - * back as set or not. The PCI0646U2 specs clarify - * this point. - */ - (void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02); - - /* Set reasonable active/recovery/address-setup values. */ - (void) pci_write_config_byte(dev, ARTTIM0, 0x40); - (void) pci_write_config_byte(dev, DRWTIM0, 0x3f); - (void) pci_write_config_byte(dev, ARTTIM1, 0x40); - (void) pci_write_config_byte(dev, DRWTIM1, 0x3f); -#ifdef __i386__ - (void) pci_write_config_byte(dev, ARTTIM23, 0x1c); -#else - (void) pci_write_config_byte(dev, ARTTIM23, 0x5c); -#endif - (void) pci_write_config_byte(dev, DRWTIM23, 0x3f); - (void) pci_write_config_byte(dev, DRWTIM3, 0x3f); -#ifdef CONFIG_PPC - (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); -#endif /* CONFIG_PPC */ - - return 0; -} - -static unsigned int __init cmd64x_init_chipset(struct pci_dev *dev) -{ - if (dev->device == PCI_DEVICE_ID_CMD_680) - return cmd680_pci_init (dev); - return cmd64x_pci_init (dev); -} - -static unsigned int cmd680_ata66(struct ata_channel *hwif) -{ - u8 ata66; - u8 addr_mask = (hwif->unit) ? 0xB0 : 0xA0; - - pci_read_config_byte(hwif->pci_dev, addr_mask, &ata66); - return (ata66 & 0x01) ? 1 : 0; -} - -static unsigned int cmd64x_ata66(struct ata_channel *hwif) -{ - u8 ata66; - u8 mask = (hwif->unit) ? 0x02 : 0x01; - - pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66); - return (ata66 & mask) ? 1 : 0; -} - -static void __init cmd64x_init_channel(struct ata_channel *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - u32 class_rev; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_680: - hwif->busproc = cmd680_busproc; - hwif->resetproc = cmd680_reset; - hwif->speedproc = cmd680_tune_chipset; - hwif->tuneproc = cmd680_tuneproc; - hwif->udma_four = cmd680_ata66(hwif); - break; - case PCI_DEVICE_ID_CMD_649: - case PCI_DEVICE_ID_CMD_648: - case PCI_DEVICE_ID_CMD_643: -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->udma_stop = cmd64x_udma_stop; - hwif->udma_irq_status = cmd64x_udma_irq_status; - } -#endif - hwif->tuneproc = cmd64x_tuneproc; - hwif->speedproc = cmd64x_tune_chipset; - hwif->udma_four = cmd64x_ata66(hwif); - break; - case PCI_DEVICE_ID_CMD_646: - hwif->chipset = ide_cmd646; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - if (class_rev == 0x01) { - hwif->udma_stop = cmd646_1_udma_stop; - } else { - hwif->udma_stop = cmd64x_udma_stop; - hwif->udma_irq_status = cmd64x_udma_irq_status; - } - } -#endif - hwif->tuneproc = cmd64x_tuneproc; - hwif->speedproc = cmd64x_tune_chipset; - hwif->udma_four = cmd64x_ata66(hwif); - break; - default: - break; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->highmem = 1; - hwif->modes_map = cmd6xx_modes_map(hwif); - hwif->no_atapi_autodma = 1; - hwif->udma_setup = udma_generic_setup; - } -#endif -} - - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_CMD, - .device = PCI_DEVICE_ID_CMD_643, - .init_chipset = cmd64x_init_chipset, - .init_channel = cmd64x_init_channel, - .bootable = ON_BOARD, - .flags = ATA_F_SIMPLEX, - }, - { - .vendor = PCI_VENDOR_ID_CMD, - .device = PCI_DEVICE_ID_CMD_646, - .init_chipset = cmd64x_init_chipset, - .init_channel = cmd64x_init_channel, - .enablebits = {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, - .bootable = ON_BOARD, - .flags = ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_CMD, - .device = PCI_DEVICE_ID_CMD_648, - .init_chipset = cmd64x_init_chipset, - .init_channel = cmd64x_init_channel, - .bootable = ON_BOARD, - .flags = ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_CMD, - .device = PCI_DEVICE_ID_CMD_649, - .init_chipset = cmd64x_init_chipset, - .init_channel = cmd64x_init_channel, - .bootable = ON_BOARD, - .flags = ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_CMD, - .device = PCI_DEVICE_ID_CMD_680, - .init_chipset = cmd64x_init_chipset, - .init_channel = cmd64x_init_channel, - .bootable = ON_BOARD, - .flags = ATA_F_DMA - }, -}; - -int __init init_cmd64x(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c --- a/drivers/ide/cs5530.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,333 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * linux/drivers/ide/cs5530.c Version 0.6 Mar. 18, 2000 - * - * Copyright (C) 2000 Andre Hedrick - * Ditto of GNU General Public License. - * - * Copyright (C) 2000 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - * - * Development of this chipset driver was funded - * by the nice folks at National Semiconductor. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "timing.h" -#include "pcihost.h" - -/* - * Set a new transfer mode at the drive - */ -int cs5530_set_xfer_mode(struct ata_device *drive, u8 mode) -{ - int error = 0; - - printk("%s: cs5530_set_xfer_mode(%02x)\n", drive->name, mode); - error = ide_config_drive_speed(drive, mode); - - return error; -} - -/* - * Here are the standard PIO mode 0-4 timings for each "format". - * Format-0 uses fast data reg timings, with slower command reg timings. - * Format-1 uses fast timings for all registers, but won't work with all drives. - */ -static unsigned int cs5530_pio_timings[2][5] = - {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, - {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}}; - -/* - * After chip reset, the PIO timings are set to 0x0000e132, which is not valid. - */ -#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) -#define CS5530_BASEREG(ch) (((ch)->dma_base & ~0xf) + ((ch)->unit ? 0x30 : 0x20)) - -/* - * Handle selection/setting of PIO modes for both the chipset and drive. - * - * The ide_init_cs5530() routine guarantees that all drives will have valid - * default PIO timings set up before we get here. - */ -static void cs5530_tuneproc(struct ata_device *drive, u8 pio) -{ - unsigned int format; - unsigned int basereg = CS5530_BASEREG(drive->channel); - - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); - else - pio = XFER_PIO_0 + min_t(u8, pio, 4); - - if (!cs5530_set_xfer_mode(drive, pio)) { - format = (inl(basereg+4) >> 31) & 1; - outl(cs5530_pio_timings[format][pio], basereg+(drive->select.b.unit<<3)); - } -} - -#ifdef CONFIG_BLK_DEV_IDEDMA - -/* - * Handle selection/setting of DMA/UDMA modes for both the chipset and drive. - */ -static int cs5530_config_dma(struct ata_device *drive) -{ - int udma_ok = 1; - int mode = 0; - struct ata_channel *ch = drive->channel; - int unit = drive->select.b.unit; - struct ata_device *mate = &ch->drives[unit^1]; - struct hd_driveid *id = drive->id; - unsigned int basereg, reg, timings; - - - /* - * Default to DMA-off in case we run into trouble here. - */ - udma_enable(drive, 0, 0); - outb(inb(ch->dma_base+2)&~(unit?0x40:0x20), ch->dma_base+2); /* clear DMA_capable bit */ - - /* - * The CS5530 specifies that two drives sharing a cable cannot - * mix UDMA/MDMA. It has to be one or the other, for the pair, - * though different timings can still be chosen for each drive. - * We could set the appropriate timing bits on the fly, - * but that might be a bit confusing. So, for now we statically - * handle this requirement by looking at our mate drive to see - * what it is capable of, before choosing a mode for our own drive. - */ - if (mate->present) { - struct hd_driveid *mateid = mate->id; - if (mateid && (mateid->capability & 1) && !udma_black_list(mate)) { - if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) - udma_ok = 1; - else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) - udma_ok = 0; - else - udma_ok = 1; - } - } - - /* - * Now see what the current drive is capable of, - * selecting UDMA only if the mate said it was ok. - */ - if (id && (id->capability & 1) && ch->autodma && !udma_black_list(drive)) { - if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { - if (id->dma_ultra & 4) - mode = XFER_UDMA_2; - else if (id->dma_ultra & 2) - mode = XFER_UDMA_1; - else if (id->dma_ultra & 1) - mode = XFER_UDMA_0; - } - if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { - if (id->dma_mword & 4) - mode = XFER_MW_DMA_2; - else if (id->dma_mword & 2) - mode = XFER_MW_DMA_1; - else if (id->dma_mword & 1) - mode = XFER_MW_DMA_0; - } - } - - /* - * Tell the drive to switch to the new mode; abort on failure. - */ - if (!mode || cs5530_set_xfer_mode(drive, mode)) - return 1; /* failure */ - - /* - * Now tune the chipset to match the drive: - */ - switch (mode) { - case XFER_UDMA_0: timings = 0x00921250; break; - case XFER_UDMA_1: timings = 0x00911140; break; - case XFER_UDMA_2: timings = 0x00911030; break; - 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: - printk("%s: cs5530_config_dma: huh? mode=%02x\n", drive->name, mode); - return 1; /* failure */ - } - basereg = CS5530_BASEREG(ch); - reg = inl(basereg+4); /* get drive0 config register */ - timings |= reg & 0x80000000; /* preserve PIO format bit */ - if (unit == 0) { /* are we configuring drive0? */ - outl(timings, basereg+4); /* write drive0 config register */ - } else { - if (timings & 0x00100000) - reg |= 0x00100000; /* enable UDMA timings for both drives */ - else - reg &= ~0x00100000; /* disable UDMA timings for both drives */ - outl(reg, basereg+4); /* write drive0 config register */ - outl(timings, basereg+12); /* write drive1 config register */ - } - outb(inb(ch->dma_base+2)|(unit?0x40:0x20), ch->dma_base+2); /* set DMA_capable bit */ - - /* - * Finally, turn DMA on in software, and exit. - */ - udma_enable(drive, 1, 1); /* success */ - - return 0; -} - -static int cs5530_udma_setup(struct ata_device *drive, int map) -{ - return cs5530_config_dma(drive); -} -#endif - -/* - * Initialize the cs5530 bridge for reliable IDE DMA operation. - */ -static unsigned int __init pci_init_cs5530(struct pci_dev *dev) -{ - struct pci_dev *master_0 = NULL; - struct pci_dev *cs5530_0 = NULL; - unsigned short pcicmd = 0; - unsigned long flags; - - pci_for_each_dev(dev) { - if (dev->vendor == PCI_VENDOR_ID_CYRIX) { - switch (dev->device) { - case PCI_DEVICE_ID_CYRIX_PCI_MASTER: - master_0 = dev; - break; - case PCI_DEVICE_ID_CYRIX_5530_LEGACY: - cs5530_0 = dev; - break; - } - } - } - - if (!master_0) { - printk("%s: unable to locate PCI MASTER function\n", dev->name); - return 0; - } - if (!cs5530_0) { - printk("%s: unable to locate CS5530 LEGACY function\n", dev->name); - return 0; - } - - /* - * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: - * --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530 - */ - - pci_set_master(cs5530_0); - pci_set_mwi(cs5530_0); - - /* - * Set PCI CacheLineSize to 16-bytes: - * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530 - */ - pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04); - - /* - * Disable trapping of UDMA register accesses (Win98 hack): - * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530 - */ - pci_write_config_word(cs5530_0, 0xd0, 0x5006); - - /* - * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus: - * The other settings are what is necessary to get the register - * into a sane state for IDE DMA operation. - */ - pci_write_config_byte(master_0, 0x40, 0x1e); - - /* - * Set max PCI burst size (16-bytes seems to work best): - * 16bytes: set bit-1 at 0x41 (reg value of 0x16) - * all others: clear bit-1 at 0x41, and do: - * 128bytes: OR 0x00 at 0x41 - * 256bytes: OR 0x04 at 0x41 - * 512bytes: OR 0x08 at 0x41 - * 1024bytes: OR 0x0c at 0x41 - */ - pci_write_config_byte(master_0, 0x41, 0x14); - - /* - * These settings are necessary to get the chip - * into a sane state for IDE DMA operation. - */ - pci_write_config_byte(master_0, 0x42, 0x00); - pci_write_config_byte(master_0, 0x43, 0xc1); - - return 0; -} - -/* - * This gets invoked once for each channel, and performs channel-specific - * pre-initialization before drive probing. - */ -static void __init ide_init_cs5530(struct ata_channel *ch) -{ - u32 basereg; - u32 d0_timings; - - ch->serialized = 1; - - /* We think a 64kB transfer is a 0 byte transfer, so set our - segment size to be one sector smaller than 64kB. */ - ch->max_segment_size = (1<<16) - 512; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (ch->dma_base) { - ch->highmem = 1; - ch->udma_setup = cs5530_udma_setup; - } -#endif - - ch->tuneproc = &cs5530_tuneproc; - basereg = CS5530_BASEREG(ch); - d0_timings = inl(basereg+0); - if (CS5530_BAD_PIO(d0_timings)) { /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); - if (!ch->drives[0].autotune) - ch->drives[0].autotune = 1; /* needs autotuning later */ - } - if (CS5530_BAD_PIO(inl(basereg+8))) { /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); - if (!ch->drives[1].autotune) - ch->drives[1].autotune = 1; /* needs autotuning later */ - } -} - - -/* module data table */ -static struct ata_pci_device chipset __initdata = { - .vendor = PCI_VENDOR_ID_CYRIX, - .device = PCI_DEVICE_ID_CYRIX_5530_IDE, - .init_chipset = pci_init_cs5530, - .init_channel = ide_init_cs5530, - .bootable = ON_BOARD, - .flags = ATA_F_DMA -}; - -int __init init_cs5530(void) -{ - ata_register_chipset(&chipset); - - return 0; -} diff -Nru a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c --- a/drivers/ide/cy82c693.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,443 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * linux/drivers/ide/cy82c693.c Version 0.34 Dec. 13, 1999 - * - * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer - * Copyright (C) 1998-2000 Andre Hedrick , Integrater - * - * CYPRESS CY82C693 chipset IDE controller - * - * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. - * Writting the driver was quite simple, since most of the job is - * done by the generic pci-ide support. - * The hard part was finding the CY82C693's datasheet on Cypress's - * web page :-(. But Altavista solved this problem :-). - * - * - * Notes: - * - I recently got a 16.8G IBM DTTA, so I was able to test it with - * a large and fast disk - the results look great, so I'd say the - * driver is working fine :-) - * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA - * - this is my first linux driver, so there's probably a lot of room - * for optimizations and bug fixing, so feel free to do it. - * - I had some problems with my IBM DHEA with PIO modes < 2 - * (lost interrupts) ????? - * FIXME: probably because we set wrong timings for 8bit --bkz - * - first tests with DMA look okay, they seem to work, but there is a - * problem with sound - the BusMaster IDE TimeOut should fixed this - * - * - * History: - * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 - * ASK@1999-01-23: v0.33 made a few minor code clean ups - * removed DMA clock speed setting by default - * added boot message - * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut - * added support to set DMA Controller Clock Speed - * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes on some drive - * ASK@1998-10-29: v0.3 added support to set DMA modes - * ASK@1998-10-28: v0.2 added support to set PIO modes - * ASK@1998-10-27: v0.1 first version - chipset detection - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "pcihost.h" - -/* the current version */ -#define CY82_VERSION "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)" - -/* - * The following are used to debug the driver. - */ -#define CY82C693_DEBUG_LOGS 0 -#define CY82C693_DEBUG_INFO 0 - -/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */ -#undef CY82C693_SETDMA_CLOCK - -/* - * note: the value for busmaster timeout is tricky and i got it by trial and error ! - * using a to low value will cause DMA timeouts and drop IDE performance - * using a to high value will cause audio playback to scatter - * if you know a better value or how to calc it, please let me know - */ -#define BUSMASTER_TIMEOUT 0x50 /* twice the value written in cy82c693ub datasheet */ -/* - * the value above was tested on my machine and it seems to work okay - */ - -/* here are the offset definitions for the registers */ -#define CY82_IDE_CMDREG 0x04 -#define CY82_IDE_ADDRSETUP 0x48 - -#define CYPRESS_TIMINGS 0x4C - -#define CY82_IDE_MASTER_IOR 0x4C -#define CY82_IDE_MASTER_IOW 0x4D -#define CY82_IDE_SLAVE_IOR 0x4E -#define CY82_IDE_SLAVE_IOW 0x4F -#define CY82_IDE_MASTER_8BIT 0x50 -#define CY82_IDE_SLAVE_8BIT 0x51 - -#define CY82_INDEX_PORT 0x22 -#define CY82_DATA_PORT 0x23 - -#define CY82_INDEX_CTRLREG1 0x01 -#define CY82_INDEX_CHANNEL0 0x30 -#define CY82_INDEX_CHANNEL1 0x31 -#define CY82_INDEX_TIMEOUT 0x32 - -/* the max PIO mode - from datasheet */ -#define CY82C693_MAX_PIO 4 - -/* the min and max PCI bus speed in MHz - from datasheet */ -#define CY82C963_MIN_BUS_SPEED 25 -#define CY82C963_MAX_BUS_SPEED 33 - -/* the struct for the PIO mode timings (in clocks) */ -typedef struct pio_clocks_s { - u8 address_time; /* Address setup */ - /* 0xF0=Active/data, 0x0F=Recovery */ - u8 time_16r; /* 16bit IOR */ - u8 time_16w; /* 16bit IOW */ - u8 time_8; /* 8bit */ -} pio_clocks_t; - -/* - * calc clocks using bus_speed - * returns (rounded up) time in bus clocks for time in ns - */ -static u8 calc_clk(int time, int bus_speed) -{ - int clocks; - - clocks = (time*bus_speed+999999)/1000000 -1; - - if (clocks < 0) - clocks = 0; - - if (clocks > 0x0F) - clocks = 0x0F; - - return (u8)clocks; -} - -/* - * compute the values for the clock registers for PIO - * mode and pci_clk [MHz] speed - * - * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used - * for mode 3 and 4 drives 8 and 16-bit timings are the same - * - */ -/* FIXME: use generic timings library --bkz */ -static void compute_clocks(u8 pio, pio_clocks_t *p_pclk) -{ - struct ata_timing *t; - int clk1, clk2; - - t = ata_timing_data(XFER_PIO_0 + pio); - - /* we don't check against CY82C693's min and max speed, - * so you can play with the idebus=xx parameter - * FIXME: warn about going out of specification --bkz - */ - - if (pio > CY82C693_MAX_PIO) - pio = CY82C693_MAX_PIO; - - /* address setup */ - p_pclk->address_time = calc_clk(t->setup, system_bus_speed); - - /* active */ - clk1 = calc_clk(t->active, system_bus_speed); - - /* FIXME: check why not t->cycle - t->active ? --bkz */ - /* recovery */ - clk2 = calc_clk(t->cycle - t->active - t->setup, system_bus_speed); - - clk1 = (clk1 << 4) | clk2; /* combine active and recovery clocks */ - - /* note: we use the same values for 16bit IOR and IOW - * those are all the same, since I don't have other - * timings than those from ata-timing.h - */ - p_pclk->time_16w = p_pclk->time_16r = clk1; - - /* FIXME: ugh... --bkz */ - /* what are good values for 8bit ?? */ - p_pclk->time_8 = clk1; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * set DMA mode a specific channel for CY82C693 - */ -static void cy82c693_dma_enable(struct ata_device *drive, int mode, int single) -{ - u8 index; - u8 data; - - 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 = (drive->channel->unit == 0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1; - -#if CY82C693_DEBUG_LOGS - /* for debug let's show the previous values */ - - OUT_BYTE(index, CY82_INDEX_PORT); - data = IN_BYTE(CY82_DATA_PORT); - - printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, drive->channel->unit, drive->select.b.unit, (data&0x3), ((data>>2)&1)); -#endif - - data = (u8) mode | (u8) (single << 2); - - OUT_BYTE(index, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, drive->channel->unit, drive->select.b.unit, mode, single); -#endif - - /* - * note: below we set the value for Bus Master IDE TimeOut Register - * I'm not absolutly sure what this does, but it solved my problem - * with IDE DMA and sound, so I now can play sound and work with - * my IDE driver at the same time :-) - * - * If you know the correct (best) value for this register please - * let me know - ASK - */ - - data = BUSMASTER_TIMEOUT; - OUT_BYTE(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", drive->name, data); -#endif -} - -/* - * used to set DMA mode for CY82C693 (single and multi modes) - */ -static int cy82c693_udma_setup(struct ata_device *drive, int map) -{ - /* - * Set dma mode for drive everything else is done by the defaul func. - */ - struct hd_driveid *id = drive->id; - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "dma_on: %s\n", drive->name); -#endif - - 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) - cy82c693_dma_enable(drive, (mmode >> 1), 0); /* enable multi */ - else if (smode != 0) - cy82c693_dma_enable(drive, (smode >> 1), 1); /* enable single */ - } - } - udma_enable(drive, 1, 1); - - return 0; -} -#endif - -/* - * tune ide drive - set PIO mode - */ -static void cy82c693_tune_drive(struct ata_device *drive, u8 pio) -{ - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - pio_clocks_t pclk; - unsigned int addrCtrl; - u8 ior, iow, bit8; - - /* FIXME: probaly broken --bkz */ - /* select primary or secondary channel */ - if (hwif->index > 0) { /* drive is on the secondary channel */ - dev = pci_find_slot(dev->bus->number, dev->devfn+1); - if (!dev) { - printk(KERN_ERR "%s: tune_drive: Cannot find secondary interface!\n", drive->name); - return; - } - } - - if (drive->select.b.unit == 0) { - ior = CY82_IDE_MASTER_IOR; - iow = CY82_IDE_MASTER_IOW; - bit8 = CY82_IDE_MASTER_8BIT; - } else { - ior = CY82_IDE_SLAVE_IOR; - iow = CY82_IDE_SLAVE_IOW; - bit8 = CY82_IDE_SLAVE_8BIT; - } - -#if CY82C693_DEBUG_LOGS - /* for debug let's show the register values */ - - /* - * get address setup control register - * mine master or slave data - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - - if (drive->select.b.unit == 0) - addrCtrl &= 0x0F; - else { - addrCtrl &= 0xF0; - addrCtrl >>= 4; - } - - /* now let's get the remaining registers */ - pci_read_config_byte(dev, ior, &pclk.time_16r); - pci_read_config_byte(dev, iow, &pclk.time_16w); - pci_read_config_byte(dev, bit8, &pclk.time_8); - - printk(KERN_INFO "%s (ch=%d, dev=%d): PIO timing is (addr=0x%X," - " ior=0x%X, iow=0x%X, 8bit=0x%X)\n", - drive->name, hwif->unit, drive->select.b.unit, - addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); -#endif /* CY82C693_DEBUG_LOGS */ - - /* first let's calc the pio modes */ - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Selected PIO mode %d\n", drive->name, pio); -#endif - - compute_clocks(pio, &pclk); /* let's calc the values for this PIO mode */ - - /* - * set address setup control register - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - if (drive->select.b.unit == 0) { - addrCtrl &= (~0x0F); - addrCtrl |= (unsigned int)pclk.address_time; - } else { - addrCtrl &= (~0xF0); - addrCtrl |= ((unsigned int)pclk.address_time<<4); - } - pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); - - /* now let's set the remaining registers */ - pci_write_config_byte(dev, ior, pclk.time_16r); - pci_write_config_byte(dev, iow, pclk.time_16w); - pci_write_config_byte(dev, bit8, pclk.time_8); - -#if CY82C693_DEBUG_INFO - printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to (addr=0x%X," - " ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, - hwif->unit, drive->select.b.unit, addrCtrl, - pclk.time_16r, pclk.time_16w, pclk.time_8); -#endif -} - -static unsigned int __init pci_init_cy82c693(struct pci_dev *dev) -{ -#ifdef CY82C693_SETDMA_CLOCK - u8 data; -#endif - - /* write info about this verion of the driver */ - printk (KERN_INFO CY82_VERSION "\n"); - -#ifdef CY82C693_SETDMA_CLOCK - /* okay let's set the DMA clock speed */ - - OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); - data = IN_BYTE(CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", dev->name, data); -#endif - - /* - * for some reason sometimes the DMA controller - * speed is set to ATCLK/2 ???? - we fix this here - * - * note: i don't know what causes this strange behaviour, - * but even changing the dma speed doesn't solve it :-( - * the ide performance is still only half the normal speed - * - * if anybody knows what goes wrong with my machine, please - * let me know - ASK - */ - - data |= 0x03; - - OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -# if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", dev->name, data); -# endif - -#endif - return 0; -} - -/* - * the init function - called for each ide channel once - */ -static void __init ide_init_cy82c693(struct ata_channel *hwif) -{ - hwif->chipset = ide_cy82c693; - hwif->tuneproc = cy82c693_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->highmem = 1; - hwif->udma_setup = cy82c693_udma_setup; - } -#endif -} - - -/* module data table */ -static struct ata_pci_device chipset __initdata = { - .vendor = PCI_VENDOR_ID_CONTAQ, - .device = PCI_DEVICE_ID_CONTAQ_82C693, - .init_chipset = pci_init_cy82c693, - .init_channel = ide_init_cy82c693, - .bootable = ON_BOARD, - .flags = ATA_F_DMA -}; - -int __init init_cy82c693(void) -{ - ata_register_chipset(&chipset); - - return 0; -} diff -Nru a/drivers/ide/device.c b/drivers/ide/device.c --- a/drivers/ide/device.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,263 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* - * Common low leved device access code. This is the lowest layer of hardware - * access. - * - * This is the place where register set access portability will be handled in - * the future. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Select a device for operation with possible busy waiting for the operation - * to complete. - */ -void ata_select(struct ata_device *drive, unsigned long delay) -{ - struct ata_channel *ch = drive->channel; - - if (!ch) - return; - - if (ch->selectproc) - ch->selectproc(drive); - OUT_BYTE(drive->select.all, ch->io_ports[IDE_SELECT_OFFSET]); - - /* The delays during probing for drives can be georgeous. Deal with - * it. - */ - if (delay) { - if (delay >= 1000) - mdelay(delay / 1000); - else - udelay(delay); - } -} - -EXPORT_SYMBOL(ata_select); - -/* - * Handle quirky routing of interrupts. - */ -void ata_mask(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - - if (!ch) - return; - - if (ch->maskproc) - ch->maskproc(drive); -} - -EXPORT_SYMBOL(ata_mask); - -/* - * Check the state of the status register. - */ -int ata_status(struct ata_device *drive, u8 good, u8 bad) -{ - struct ata_channel *ch = drive->channel; - - drive->status = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); - - return (drive->status & (good | bad)) == good; -} - -EXPORT_SYMBOL(ata_status); - -/* - * This is used to check for the drive status on the IRQ handling code path. - */ -int ata_status_irq(struct ata_device *drive) -{ - if (test_bit(IDE_DMA, drive->channel->active)) - return udma_irq_status(drive); - - /* Need to guarantee 400ns since last command was issued? - */ -#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 an - * interrupt with another pci card/device. - */ - - if (drive->channel->io_ports[IDE_CONTROL_OFFSET]) - drive->status = IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET]); - - else -#endif - ata_status(drive, 0, 0); /* Note: this may clear a pending IRQ! */ - - if (drive->status & BUSY_STAT) - return 0; /* drive busy: definitely not interrupting */ - else - return 1; /* drive ready: *might* be interrupting */ -} - -EXPORT_SYMBOL(ata_status_irq); - -/* - * Busy-wait for the drive status to be not "busy". Check then the status for - * all of the "good" bits and none of the "bad" bits, and if all is okay it - * returns 0. All other cases return 1 after invoking error handler -- caller - * should just return. - */ -int ata_status_poll(struct ata_device *drive, u8 good, u8 bad, - unsigned long timeout, struct request *rq) -{ - int i; - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) - return ATA_OP_FINISHED; - /* - * Spin until the drive is no longer busy. - * Spec allows drive 400ns to assert "BUSY" - */ - udelay(1); - if (!ata_status(drive, 0, BUSY_STAT)) { - unsigned long flags; - - local_save_flags(flags); - local_irq_enable(); - timeout += jiffies; - while (!ata_status(drive, 0, BUSY_STAT)) { - if (time_after(jiffies, timeout)) { - local_irq_restore(flags); - return ata_error(drive, rq, "status timeout"); - } - } - local_irq_restore(flags); - } - - /* - * Allow status to settle, then read it again. A few rare drives - * vastly violate the 400ns spec here, so we'll wait up to 10usec for a - * "good" status rather than expensively fail things immediately. This - * fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (ata_status(drive, good, bad)) - return ATA_OP_READY; - } - - return ata_error(drive, rq, "status error"); -} - -EXPORT_SYMBOL(ata_status_poll); - -/* - * Handle the nIEN - negated Interrupt ENable of the drive. - * This is controlling whatever the drive will acnowlenge commands - * with interrupts or not. - */ -int ata_irq_enable(struct ata_device *drive, int on) -{ - struct ata_channel *ch = drive->channel; - - if (!ch->io_ports[IDE_CONTROL_OFFSET]) - return 0; - - /* 0x08 is for legacy ATA-1 devices */ - if (on) - OUT_BYTE(0x08 | 0x00, ch->io_ports[IDE_CONTROL_OFFSET]); - else { - if (!ch->intrproc) - OUT_BYTE(0x08 | 0x02, ch->io_ports[IDE_CONTROL_OFFSET]); - else - ch->intrproc(drive); - } - - return 1; -} - -EXPORT_SYMBOL(ata_irq_enable); - -/* - * Perform a reset operation on the currently selected drive. - */ -void ata_reset(struct ata_channel *ch) -{ - unsigned long timeout = jiffies + WAIT_WORSTCASE; - u8 stat; - - if (!ch->io_ports[IDE_CONTROL_OFFSET]) - return; - - printk("%s: reset\n", ch->name); - /* 0x08 is for legacy ATA-1 devices */ - OUT_BYTE(0x08 | 0x04, ch->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - /* 0x08 is for legacy ATA-1 devices */ - OUT_BYTE(0x08 | 0x00, ch->io_ports[IDE_CONTROL_OFFSET]); - do { - mdelay(50); - stat = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); - } while ((stat & BUSY_STAT) && time_before(jiffies, timeout)); -} - -EXPORT_SYMBOL(ata_reset); - -/* - * Output a complete register file. - */ -void ata_out_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf) -{ - struct ata_channel *ch = drive->channel; - - OUT_BYTE(rf->feature, ch->io_ports[IDE_FEATURE_OFFSET]); - OUT_BYTE(rf->sector_count, ch->io_ports[IDE_NSECTOR_OFFSET]); - OUT_BYTE(rf->sector_number, ch->io_ports[IDE_SECTOR_OFFSET]); - OUT_BYTE(rf->low_cylinder, ch->io_ports[IDE_LCYL_OFFSET]); - OUT_BYTE(rf->high_cylinder, ch->io_ports[IDE_HCYL_OFFSET]); -} - -EXPORT_SYMBOL(ata_out_regfile); - -/* - * Input a complete register file. - */ -void ata_in_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf) -{ - struct ata_channel *ch = drive->channel; - - rf->sector_count = IN_BYTE(ch->io_ports[IDE_NSECTOR_OFFSET]); - rf->sector_number = IN_BYTE(ch->io_ports[IDE_SECTOR_OFFSET]); - rf->low_cylinder = IN_BYTE(ch->io_ports[IDE_LCYL_OFFSET]); - rf->high_cylinder = IN_BYTE(ch->io_ports[IDE_HCYL_OFFSET]); -} - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c --- a/drivers/ide/dtc2278.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,125 +0,0 @@ -/* - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" - -/* - * Changing this #undef to #define may solve start up problems in some systems. - */ -#undef ALWAYS_SET_DTC2278_PIO_MODE - -/* - * From: andy@cercle.cts.com (Dyan Wile) - * - * Below is a patch for DTC-2278 - alike software-programmable controllers - * The code enables the secondary IDE controller and the PIO4 (3?) timings on - * the primary (EIDE). You may probably have to enable the 32-bit support to - * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 - * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my - * filesystem corrupted with -u1, but under heavy disk load only :-) - * - * This card is now forced to use the "serialize" feature, - * and irq-unmasking is disallowed. If io_32bit is enabled, - * it must be done for BOTH drives on each interface. - * - * This code was written for the DTC2278E, but might work with any of these: - * - * DTC2278S has only a single IDE interface. - * DTC2278D has two IDE interfaces and is otherwise identical to the S version. - * DTC2278E also has serial ports and a printer port - * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford - * - * There may be a fourth controller type. The S and D versions use the - * Winbond chip, and I think the E version does also. - * - */ - -static void sub22 (char b, char c) -{ - int i; - - for(i = 0; i < 3; ++i) { - inb(0x3f6); - outb_p(b,0xb0); - inb(0x3f6); - outb_p(c,0xb4); - inb(0x3f6); - if(inb(0xb4) == c) { - outb_p(7,0xb0); - inb(0x3f6); - return; /* success */ - } - } -} - -/* Assumes IRQ's are disabled or at least that no other process will - attempt to access the IDE registers concurrently. */ -static void tune_dtc2278(struct ata_device *drive, u8 pio) -{ - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; - - if (pio >= 3) { - /* - * This enables PIO mode4 (3?) on the first interface - */ - sub22(1,0xc3); - sub22(0,0xa0); - } else { - /* we don't know how to set it back again.. */ - } - - /* - * 32bit I/O has to be enabled for *both* drives at the same time. - */ - drive->channel->io_32bit = 1; -} - -void __init init_dtc2278 (void) -{ - unsigned long flags; - - local_irq_save(flags); - /* - * This enables the second interface - */ - outb_p(4,0xb0); - inb(0x3f6); - outb_p(0x20,0xb4); - inb(0x3f6); -#ifdef ALWAYS_SET_DTC2278_PIO_MODE - /* - * This enables PIO mode4 (3?) on the first interface - * and may solve start-up problems for some people. - */ - sub22(1,0xc3); - sub22(0,0xa0); -#endif - local_irq_restore(flags); - - ide_hwifs[0].serialized = 1; - ide_hwifs[1].serialized = 1; - ide_hwifs[0].chipset = ide_dtc2278; - ide_hwifs[1].chipset = ide_dtc2278; - ide_hwifs[0].tuneproc = &tune_dtc2278; - /* FIXME: What about the following?! - ide_hwifs[1].tuneproc = &tune_dtc2278; - */ - ide_hwifs[0].no_unmask = 1; - ide_hwifs[1].no_unmask = 1; - ide_hwifs[0].unit = ATA_PRIMARY; - ide_hwifs[1].unit = ATA_SECONDARY; -} diff -Nru a/drivers/ide/falconide.c b/drivers/ide/falconide.c --- a/drivers/ide/falconide.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,68 +0,0 @@ -/* - * linux/drivers/ide/falconide.c -- Atari Falcon IDE Driver - * - * Created 12 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - - /* - * Base of the IDE interface - */ - -#define ATA_HD_BASE 0xfff00000 - - /* - * Offsets from the above base - */ - -#define ATA_HD_DATA 0x00 -#define ATA_HD_ERROR 0x05 /* see err-bits */ -#define ATA_HD_NSECTOR 0x09 /* nr of sectors to read/write */ -#define ATA_HD_SECTOR 0x0d /* starting sector */ -#define ATA_HD_LCYL 0x11 /* starting cylinder */ -#define ATA_HD_HCYL 0x15 /* high byte of starting cyl */ -#define ATA_HD_SELECT 0x19 /* 101dhhhh , d=drive, hhhh=head */ -#define ATA_HD_STATUS 0x1d /* see status-bits */ -#define ATA_HD_CONTROL 0x39 - -static int falconide_offsets[IDE_NR_PORTS] __initdata = { - ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL, - ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1 -}; - - - /* - * Probe for a Falcon IDE interface - */ - -void __init falconide_init(void) -{ - if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) { - hw_regs_t hw; - int index; - - ide_setup_ports(&hw, (ide_ioreg_t)ATA_HD_BASE, falconide_offsets, - 0, 0, NULL, IRQ_MFP_IDE); - index = ide_register_hw(&hw); - - if (index != -1) - printk("ide%d: Falcon IDE interface\n", index); - } -} diff -Nru a/drivers/ide/gayle.c b/drivers/ide/gayle.c --- a/drivers/ide/gayle.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,180 +0,0 @@ -/* - * linux/drivers/ide/gayle.c -- Amiga Gayle IDE Driver - * - * Created 9 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - - /* - * Bases of the IDE interfaces - */ - -#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ -#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 */ - - /* - * Offsets from one of the above bases - */ - -#define GAYLE_DATA 0x00 -#define GAYLE_ERROR 0x06 /* see err-bits */ -#define GAYLE_NSECTOR 0x0a /* nr of sectors to read/write */ -#define GAYLE_SECTOR 0x0e /* starting sector */ -#define GAYLE_LCYL 0x12 /* starting cylinder */ -#define GAYLE_HCYL 0x16 /* high byte of starting cyl */ -#define GAYLE_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ -#define GAYLE_STATUS 0x1e /* see status-bits */ -#define GAYLE_CONTROL 0x101a - -static int gayle_offsets[IDE_NR_PORTS] __initdata = { - GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL, - GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1 -}; - - - /* - * These are at different offsets from the base - */ - -#define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */ -#define GAYLE_IRQ_1200 0xda9000 /* interrupt */ - - - /* - * Offset of the secondary port for IDE doublers - * Note that GAYLE_CONTROL is NOT available then! - */ - -#define GAYLE_NEXT_PORT 0x1000 - -#ifndef CONFIG_BLK_DEV_IDEDOUBLER -#define GAYLE_NUM_HWIFS 1 -#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS -#define GAYLE_HAS_CONTROL_REG 1 -#define GAYLE_IDEREG_SIZE 0x2000 -#else /* CONFIG_BLK_DEV_IDEDOUBLER */ -#define GAYLE_NUM_HWIFS 2 -#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \ - GAYLE_NUM_HWIFS-1) -#define GAYLE_HAS_CONTROL_REG (!ide_doubler) -#define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000) -int ide_doubler = 0; /* support IDE doublers? */ -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - - - /* - * Check and acknowledge the interrupt status - */ - -static int gayle_ack_intr_a4000(struct ata_channel *hwif) -{ - unsigned char ch; - - ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & GAYLE_IRQ_IDE)) - return 0; - return 1; -} - -static int gayle_ack_intr_a1200(struct ata_channel *hwif) -{ - unsigned char ch; - - ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & GAYLE_IRQ_IDE)) - return 0; - (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]); - outb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]); - return 1; -} - -/* - * Probe for a Gayle IDE interface (and optionally for an IDE doubler) - */ - -void __init gayle_init(void) -{ - int a4000, i; - - if (!MACH_IS_AMIGA) - return; - - if (!(a4000 = AMIGAHW_PRESENT(A4000_IDE)) && !AMIGAHW_PRESENT(A1200_IDE)) - return; - - for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { - ide_ioreg_t base, ctrlport, irqport; - int (*ack_intr)(struct ata_channel *); - hw_regs_t hw; - int index; - unsigned long phys_base, res_start, res_n; - - if (a4000) { - phys_base = GAYLE_BASE_4000; - irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_4000); - ack_intr = gayle_ack_intr_a4000; - } else { - phys_base = GAYLE_BASE_1200; - irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200); - ack_intr = gayle_ack_intr_a1200; - } - phys_base += i*GAYLE_NEXT_PORT; - - res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); - res_n = GAYLE_IDEREG_SIZE; - - if (!request_mem_region(res_start, res_n, "IDE")) - continue; - - base = (ide_ioreg_t)ZTWO_VADDR(phys_base); - ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; - - ide_setup_ports(&hw, base, gayle_offsets, - ctrlport, irqport, ack_intr, IRQ_AMIGA_PORTS); - - index = ide_register_hw(&hw); - if (index != -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 */ - } - } else - release_mem_region(res_start, res_n); - -#if 1 /* TESTING */ - if (i == 1) { - volatile u_short *addr = (u_short *)base; - u_short data; - printk("+++ Probing for IDE doubler... "); - *addr = 0xffff; - data = *addr; - printk("probe returned 0x%02x (PLEASE REPORT THIS!!)\n", data); - } -#endif /* TESTING */ - } -} diff -Nru a/drivers/ide/hd.c b/drivers/ide/hd.c --- a/drivers/ide/hd.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,884 +0,0 @@ -/* - * Copyright (C) 1991, 1992 Linus Torvalds - * - * This is the low-level hd interrupt support. It traverses the - * request-list, using interrupts to jump between functions. As - * all the functions are called within interrupts, we may not - * sleep. Special care is recommended. - * - * modified by Drew Eckhardt to check nr of hd's from the CMOS. - * - * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug - * in the early extended-partition checks and added DM partitions - * - * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", - * and general streamlining by Mark Lord. - * - * Removed 99% of above. Use Mark's ide driver for those options. - * This is now a lightweight ST-506 driver. (Paul Gortmaker) - * - * Modified 1995 Russell King for ARM processor. - * - * Bugfix: max_sectors must be <= 255 or the wheels tend to come - * off in a hurry once you queue things up - Paul G. 02/2001 - */ - -/* Uncomment the following if you want verbose error reports. */ -/* #define VERBOSE_ERRORS */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* CMOS defines */ -#include -#include -#include - -#define REALLY_SLOW_IO -#include -#include -#include - -#define MAJOR_NR HD_MAJOR -#define DEVICE_NR(device) (minor(device)>>6) -#include - -/* ATA commands we use. - */ -#define WIN_SPECIFY 0x91 /* set drive geometry translation */ -#define WIN_RESTORE 0x10 -#define WIN_READ 0x20 /* 28-Bit */ -#define WIN_WRITE 0x30 /* 28-Bit */ - -#define HD_IRQ 14 /* the standard disk interrupt */ - -#ifdef __arm__ -#undef HD_IRQ -#endif -#include -#ifdef __arm__ -#define HD_IRQ IRQ_HARDDISK -#endif - -/* Hd controller regster ports */ - -#define HD_DATA 0x1f0 /* _CTL when writing */ -#define HD_ERROR 0x1f1 /* see err-bits */ -#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */ -#define HD_SECTOR 0x1f3 /* starting sector */ -#define HD_LCYL 0x1f4 /* starting cylinder */ -#define HD_HCYL 0x1f5 /* high byte of starting cyl */ -#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */ -#define HD_STATUS 0x1f7 /* see status-bits */ -#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */ -#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */ -#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ - -#define HD_CMD 0x3f6 /* used for resets */ -#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */ - -/* Bits of HD_STATUS */ -#define ERR_STAT 0x01 -#define INDEX_STAT 0x02 -#define ECC_STAT 0x04 /* Corrected error */ -#define DRQ_STAT 0x08 -#define SEEK_STAT 0x10 -#define SERVICE_STAT SEEK_STAT -#define WRERR_STAT 0x20 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits for HD_ERROR */ -#define MARK_ERR 0x01 /* Bad address mark */ -#define TRK0_ERR 0x02 /* couldn't find track 0 */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* media change request */ -#define ID_ERR 0x10 /* ID field not found */ -#define MC_ERR 0x20 /* media changed */ -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ -#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ - -static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED; - -#define TIMEOUT_VALUE (6*HZ) -#define HD_DELAY 0 - -#define MAX_ERRORS 16 /* Max read/write errors/sector */ -#define RESET_FREQ 8 /* Reset controller every 8th retry */ -#define RECAL_FREQ 4 /* Recalibrate every 4th retry */ -#define MAX_HD 2 - -#define STAT_OK (READY_STAT|SEEK_STAT) -#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK) - -static void recal_intr(void); -static void bad_rw_intr(void); - -static char recalibrate[MAX_HD]; -static char special_op[MAX_HD]; - -static int reset; -static int hd_error; - -#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) - -/* - * This struct defines the HD's and their types. - */ -struct hd_i_struct { - unsigned int head,sect,cyl,wpcom,lzone,ctl; -}; - -#ifdef HD_TYPE -static struct hd_i_struct hd_info[] = { HD_TYPE }; -static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct))); -#else -static struct hd_i_struct hd_info[MAX_HD]; -static int NR_HD; -#endif - -static struct hd_struct hd[MAX_HD<<6]; - -static struct timer_list device_timer; - -#define TIMEOUT_VALUE (6*HZ) - -#define SET_TIMER \ - do { \ - mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ - } while (0) - -static void (*do_hd)(void) = NULL; -#define SET_HANDLER(x) \ -if ((do_hd = (x)) != NULL) \ - SET_TIMER; \ -else \ - del_timer(&device_timer); - - -#if (HD_DELAY > 0) -unsigned long last_req; - -unsigned long read_timer(void) -{ - extern spinlock_t i8253_lock; - unsigned long t, flags; - int i; - - spin_lock_irqsave(&i8253_lock, flags); - t = jiffies * 11932; - outb_p(0, 0x43); - i = inb_p(0x40); - i |= inb(0x40) << 8; - spin_unlock_irqrestore(&i8253_lock, flags); - return(t - i); -} -#endif - -void __init hd_setup(char *str, int *ints) -{ - int hdind = 0; - - if (ints[0] != 3) - return; - if (hd_info[0].head != 0) - hdind=1; - hd_info[hdind].head = ints[2]; - hd_info[hdind].sect = ints[3]; - hd_info[hdind].cyl = ints[1]; - hd_info[hdind].wpcom = 0; - hd_info[hdind].lzone = ints[1]; - hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); - NR_HD = hdind+1; -} - -static void dump_status (const char *msg, unsigned int stat) -{ - char devc; - - devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?'; -#ifdef VERBOSE_ERRORS - printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff); - if (stat & BUSY_STAT) printk("Busy "); - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("WriteFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); - printk("}\n"); - if ((stat & ERR_STAT) == 0) { - hd_error = 0; - } else { - hd_error = inb(HD_ERROR); - printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff); - if (hd_error & BBD_ERR) printk("BadSector "); - if (hd_error & ECC_ERR) printk("UncorrectableError "); - if (hd_error & ID_ERR) printk("SectorIdNotFound "); - if (hd_error & ABRT_ERR) printk("DriveStatusError "); - if (hd_error & TRK0_ERR) printk("TrackZeroNotFound "); - if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { - printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), - inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); - if (!blk_queue_empty(QUEUE)) - printk(", sector=%ld", CURRENT->sector); - } - printk("\n"); - } -#else - printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff); - if ((stat & ERR_STAT) == 0) { - hd_error = 0; - } else { - hd_error = inb(HD_ERROR); - printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff); - } -#endif -} - -void check_status(void) -{ - int i = inb_p(HD_STATUS); - - if (!OK_STATUS(i)) { - dump_status("check_status", i); - bad_rw_intr(); - } -} - -static int controller_busy(void) -{ - int retries = 100000; - unsigned char status; - - do { - status = inb_p(HD_STATUS); - } while ((status & BUSY_STAT) && --retries); - return status; -} - -static int status_ok(void) -{ - unsigned char status = inb_p(HD_STATUS); - - if (status & BUSY_STAT) - return 1; /* Ancient, but does it make sense??? */ - if (status & WRERR_STAT) - return 0; - if (!(status & READY_STAT)) - return 0; - if (!(status & SEEK_STAT)) - return 0; - return 1; -} - -static int controller_ready(unsigned int drive, unsigned int head) -{ - int retry = 100; - - do { - if (controller_busy() & BUSY_STAT) - return 0; - outb_p(0xA0 | (drive<<4) | head, HD_CURRENT); - if (status_ok()) - return 1; - } while (--retry); - return 0; -} - -static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, - unsigned int head,unsigned int cyl,unsigned int cmd, - void (*intr_addr)(void)) -{ - unsigned short port; - -#if (HD_DELAY > 0) - while (read_timer() - last_req < HD_DELAY) - /* nothing */; -#endif - if (reset) - return; - if (!controller_ready(drive, head)) { - reset = 1; - return; - } - SET_HANDLER(intr_addr); - outb_p(hd_info[drive].ctl,HD_CMD); - port=HD_DATA; - outb_p(hd_info[drive].wpcom>>2,++port); - outb_p(nsect,++port); - outb_p(sect,++port); - outb_p(cyl,++port); - outb_p(cyl>>8,++port); - outb_p(0xA0|(drive<<4)|head,++port); - outb_p(cmd,++port); -} - -static void hd_request (void); - -static int drive_busy(void) -{ - unsigned int i; - unsigned char c; - - for (i = 0; i < 500000 ; i++) { - c = inb_p(HD_STATUS); - if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK) - return 0; - } - dump_status("reset timed out", c); - return 1; -} - -static void reset_controller(void) -{ - int i; - - outb_p(4,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - outb_p(hd_info[0].ctl & 0x0f,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - if (drive_busy()) - printk("hd: controller still busy\n"); - else if ((hd_error = inb(HD_ERROR)) != 1) - printk("hd: controller reset failed: %02x\n",hd_error); -} - -static void reset_hd(void) -{ - static int i; - -repeat: - if (reset) { - reset = 0; - i = -1; - reset_controller(); - } else { - check_status(); - if (reset) - goto repeat; - } - if (++i < NR_HD) { - special_op[i] = recalibrate[i] = 1; - hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1, - hd_info[i].cyl,WIN_SPECIFY,&reset_hd); - if (reset) - goto repeat; - } else - hd_request(); -} - -/* - * Ok, don't know what to do with the unexpected interrupts: on some machines - * doing a reset and a retry seems to result in an eternal loop. Right now I - * ignore it, and just set the timeout. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - */ -void unexpected_hd_interrupt(void) -{ - unsigned int stat = inb_p(HD_STATUS); - - if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { - dump_status ("unexpected interrupt", stat); - SET_TIMER; - } -} - -/* - * bad_rw_intr() now tries to be a bit smarter and does things - * according to the error returned by the controller. - * -Mika Liljeberg (liljeber@cs.Helsinki.FI) - */ -static void bad_rw_intr(void) -{ - int dev; - - if (blk_queue_empty(QUEUE)) - return; - dev = DEVICE_NR(CURRENT->rq_dev); - if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { - end_request(CURRENT, 0); - special_op[dev] = recalibrate[dev] = 1; - } else if (CURRENT->errors % RESET_FREQ == 0) - reset = 1; - else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0) - special_op[dev] = recalibrate[dev] = 1; - /* Otherwise just retry */ -} - -static inline int wait_DRQ(void) -{ - int retries = 100000, stat; - - while (--retries > 0) - if ((stat = inb_p(HD_STATUS)) & DRQ_STAT) - return 0; - dump_status("wait_DRQ", stat); - return -1; -} - -static void read_intr(void) -{ - int i, retries = 100000; - - do { - i = (unsigned) inb_p(HD_STATUS); - if (i & BUSY_STAT) - continue; - if (!OK_STATUS(i)) - break; - if (i & DRQ_STAT) - goto ok_to_read; - } while (--retries > 0); - dump_status("read_intr", i); - bad_rw_intr(); - hd_request(); - return; -ok_to_read: - insw(HD_DATA,CURRENT->buffer,256); - CURRENT->sector++; - CURRENT->buffer += 512; - CURRENT->errors = 0; - i = --CURRENT->nr_sectors; - --CURRENT->current_nr_sectors; -#ifdef DEBUG - printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n", - dev+'a', CURRENT->sector, CURRENT->nr_sectors, - (unsigned long) CURRENT->buffer+512)); -#endif - if (CURRENT->current_nr_sectors <= 0) - end_request(CURRENT, 1); - if (i > 0) { - SET_HANDLER(&read_intr); - return; - } - (void) inb_p(HD_STATUS); -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - if (!blk_queue_empty(QUEUE)) - hd_request(); - return; -} - -static void write_intr(void) -{ - int i; - int retries = 100000; - - do { - i = (unsigned) inb_p(HD_STATUS); - if (i & BUSY_STAT) - continue; - if (!OK_STATUS(i)) - break; - if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT)) - goto ok_to_write; - } while (--retries > 0); - dump_status("write_intr", i); - bad_rw_intr(); - hd_request(); - return; -ok_to_write: - CURRENT->sector++; - i = --CURRENT->nr_sectors; - --CURRENT->current_nr_sectors; - CURRENT->buffer += 512; - if (!i || (CURRENT->bio && !SUBSECTOR(i))) - end_request(CURRENT, 1); - if (i > 0) { - SET_HANDLER(&write_intr); - outsw(HD_DATA,CURRENT->buffer,256); - local_irq_enable(); - } else { -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - hd_request(); - } - return; -} - -static void recal_intr(void) -{ - check_status(); -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - hd_request(); -} - -/* - * This is another of the error-routines I don't know what to do with. The - * best idea seems to just set reset, and start all over again. - */ -static void hd_times_out(unsigned long dummy) -{ - unsigned int dev; - - do_hd = NULL; - - if (blk_queue_empty(QUEUE)) - return; - - disable_irq(HD_IRQ); - local_irq_enable(); - reset = 1; - dev = DEVICE_NR(CURRENT->rq_dev); - printk("hd%c: timeout\n", dev+'a'); - if (++CURRENT->errors >= MAX_ERRORS) { -#ifdef DEBUG - printk("hd%c: too many errors\n", dev+'a'); -#endif - end_request(CURRENT, 0); - } - local_irq_disable(); - hd_request(); - enable_irq(HD_IRQ); -} - -int do_special_op (unsigned int dev) -{ - if (recalibrate[dev]) { - recalibrate[dev] = 0; - hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr); - return reset; - } - if (hd_info[dev].head > 16) { - printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a'); - end_request(CURRENT, 0); - } - special_op[dev] = 0; - return 1; -} - -/* - * The driver enables interrupts as much as possible. In order to do this, - * (a) the device-interrupt is disabled before entering hd_request(), - * and (b) the timeout-interrupt is disabled before the sti(). - * - * Interrupts are still masked (by default) whenever we are exchanging - * data/cmds with a drive, because some drives seem to have very poor - * tolerance for latency during I/O. The IDE driver has support to unmask - * interrupts for non-broken hardware, so use that driver if required. - */ -static void hd_request(void) -{ - unsigned int dev, block, nsect, sec, track, head, cyl; - - if (do_hd) - return; -repeat: - del_timer(&device_timer); - local_irq_enable(); - - if (blk_queue_empty(QUEUE)) { - do_hd = NULL; - return; - } - - if (reset) { - local_irq_disable(); - reset_hd(); - return; - } - dev = minor(CURRENT->rq_dev); - block = CURRENT->sector; - nsect = CURRENT->nr_sectors; - if (dev >= (NR_HD<<6) || (dev & 0x3f) || - block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) { - if (dev >= (NR_HD<<6) || (dev & 0x3f)) - printk("hd: bad minor number: device=%s\n", - kdevname(CURRENT->rq_dev)); - else - printk("hd%c: bad access: block=%d, count=%d\n", - (minor(CURRENT->rq_dev)>>6)+'a', block, nsect); - end_request(CURRENT, 0); - goto repeat; - } - - dev >>= 6; - if (special_op[dev]) { - if (do_special_op(dev)) - goto repeat; - return; - } - sec = block % hd_info[dev].sect + 1; - track = block / hd_info[dev].sect; - head = track % hd_info[dev].head; - cyl = track / hd_info[dev].head; -#ifdef DEBUG - printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n", - dev+'a', (CURRENT->cmd == READ)?"read":"writ", - cyl, head, sec, nsect, (unsigned long) CURRENT->buffer); -#endif - if(CURRENT->flags & REQ_CMD) { - switch (rq_data_dir(CURRENT)) { - case READ: - hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr); - if (reset) - goto repeat; - break; - case WRITE: - hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr); - if (reset) - goto repeat; - if (wait_DRQ()) { - bad_rw_intr(); - goto repeat; - } - outsw(HD_DATA,CURRENT->buffer,256); - break; - default: - printk("unknown hd-command\n"); - end_request(CURRENT, 0); - break; - } - } -} - -static void do_hd_request (request_queue_t * q) -{ - disable_irq(HD_IRQ); - hd_request(); - enable_irq(HD_IRQ); -} - -static int hd_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - struct hd_geometry *loc = (struct hd_geometry *) arg; - int dev; - - if ((!inode) || kdev_none(inode->i_rdev)) - return -EINVAL; - dev = DEVICE_NR(inode->i_rdev); - if (dev >= NR_HD) - return -EINVAL; - switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry g; - if (!loc) return -EINVAL; - g.heads = hd_info[dev].head; - g.sectors = hd_info[dev].sect; - g.cylinders = hd_info[dev].cyl; - g.start = get_start_sect(inode->i_bdev); - return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; - } - - default: - return -EINVAL; - } -} - -static int hd_open(struct inode * inode, struct file * filp) -{ - int target = DEVICE_NR(inode->i_rdev); - if (target >= NR_HD) - return -ENODEV; - return 0; -} - -/* - * Releasing a block device means we sync() it, so that it can safely - * be forgotten about... - */ - -extern struct block_device_operations hd_fops; - -static struct gendisk hd_gendisk[2] = { -{ - .major = MAJOR_NR, - .first_minor = 0, - .major_name = "hda", - .minor_shift = 6, - .part = hd, - .fops = &hd_fops, -},{ - .major = MAJOR_NR, - .first_minor = 64, - .major_name = "hdb", - .minor_shift = 6, - .part = hd + 64, - .fops = &hd_fops, -} -}; - -static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - void (*handler)(void) = do_hd; - - do_hd = NULL; - del_timer(&device_timer); - if (!handler) - handler = unexpected_hd_interrupt; - handler(); - local_irq_enable(); -} - -static struct block_device_operations hd_fops = { - .open = hd_open, - .ioctl = hd_ioctl, -}; - -/* - * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags - * means we run the IRQ-handler with interrupts disabled: this is bad for - * interrupt latency, but anything else has led to problems on some - * machines. - * - * We enable interrupts in some of the routines after making sure it's - * safe. - */ -static void __init hd_geninit(void) -{ - int drive; - - blk_queue_hardsect_size(QUEUE, 512); - -#ifdef __i386__ - if (!NR_HD) { - extern struct drive_info drive_info; - unsigned char *BIOS = (unsigned char *) &drive_info; - unsigned long flags; - int cmos_disks; - - for (drive=0 ; drive<2 ; drive++) { - hd_info[drive].cyl = *(unsigned short *) BIOS; - hd_info[drive].head = *(2+BIOS); - hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); - hd_info[drive].ctl = *(8+BIOS); - hd_info[drive].lzone = *(unsigned short *) (12+BIOS); - hd_info[drive].sect = *(14+BIOS); -#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp - if (hd_info[drive].cyl && NR_HD == drive) - NR_HD++; -#endif - BIOS += 16; - } - - /* - We query CMOS about hard disks : it could be that - we have a SCSI/ESDI/etc controller that is BIOS - compatible with ST-506, and thus showing up in our - BIOS table, but not register compatible, and therefore - not present in CMOS. - - Furthermore, we will assume that our ST-506 drives - are the primary drives in the system, and - the ones reflected as drive 1 or 2. - - The first drive is stored in the high nibble of CMOS - byte 0x12, the second in the low nibble. This will be - either a 4 bit drive type or 0xf indicating use byte 0x19 - for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. - - Needless to say, a non-zero value means we have - an AT controller hard disk for that drive. - - Currently the rtc_lock is a bit academic since this - driver is non-modular, but someday... ? Paul G. - */ - - spin_lock_irqsave(&rtc_lock, flags); - cmos_disks = CMOS_READ(0x12); - spin_unlock_irqrestore(&rtc_lock, flags); - - if (cmos_disks & 0xf0) { - if (cmos_disks & 0x0f) - NR_HD = 2; - else - NR_HD = 1; - } - } -#endif /* __i386__ */ -#ifdef __arm__ - if (!NR_HD) { - /* We don't know anything about the drive. This means - * that you *MUST* specify the drive parameters to the - * kernel yourself. - */ - printk("hd: no drives specified - use hd=cyl,head,sectors" - " on kernel command line\n"); - } -#endif - - for (drive=0 ; drive < NR_HD ; drive++) { - hd[drive<<6].nr_sects = hd_info[drive].head * - hd_info[drive].sect * hd_info[drive].cyl; - printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a', - hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl, - hd_info[drive].head, hd_info[drive].sect); - } - if (!NR_HD) - return; - - if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) { - printk("hd: unable to get IRQ%d for the hard disk driver\n", - HD_IRQ); - NR_HD = 0; - return; - } - if (!request_region(HD_DATA, 8, "hd")) { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - NR_HD = 0; - free_irq(HD_IRQ, NULL); - return; - } - if (!request_region(HD_CMD, 1, "hd(cmd)")) { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); - NR_HD = 0; - free_irq(HD_IRQ, NULL); - release_region(HD_DATA, 8); - return; - } - - for(drive=0; drive < NR_HD; drive++) { - hd_gendisk[drive].nr_real = 1; - add_gendisk(hd_gendisk + drive); - register_disk(hd_gendisk + drive, - mk_kdev(MAJOR_NR,drive<<6), 1<<6, - &hd_fops, hd_info[drive].head * hd_info[drive].sect * - hd_info[drive].cyl); - } -} - -int __init hd_init(void) -{ - if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { - printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); - return -1; - } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock); - blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255); - init_timer(&device_timer); - device_timer.function = hd_times_out; - hd_geninit(); - return 0; -} - -static int parse_hd_setup (char *line) { - int ints[6]; - - (void) get_options(line, ARRAY_SIZE(ints), ints); - hd_setup(NULL, ints); - - return 1; -} -__setup("hd=", parse_hd_setup); - diff -Nru a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c --- a/drivers/ide/hpt34x.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,218 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * linux/drivers/ide/hpt34x.c Version 0.31 June. 9, 2000 - * - * Copyright (C) 1998-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - * ide-pci.c reference: - * - * Since there are two cards that report almost identically, - * the only discernable difference is the values reported in pcicmd. - * Booting-BIOS card or HPT363 :: pcicmd == 0x07 - * Non-bootable card or HPT343 :: pcicmd == 0x05 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "timing.h" -#include "pcihost.h" - -#define HPT343_DEBUG_DRIVE_INFO 0 - -static int hpt34x_tune_chipset(struct ata_device *drive, u8 speed) -{ - struct pci_dev *dev = drive->channel->pci_dev; - u8 udma = 0, pio = 0; - u32 reg1, reg2, tmp1, tmp2; - - if (speed >= XFER_UDMA_0) - udma = 0x01; - else if (speed >= XFER_SW_DMA_0) - udma = 0x10; - else - pio = speed & 7; - - pci_read_config_dword(dev, 0x44, ®1); - pci_read_config_dword(dev, 0x48, ®2); - tmp1 = (pio << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))); - tmp2 = (udma << drive->dn) | (reg2 & ~(0x11 << drive->dn)); - pci_write_config_dword(dev, 0x44, tmp1); - pci_write_config_dword(dev, 0x48, tmp2); - -#if HPT343_DEBUG_DRIVE_INFO - printk("%s: %02x drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \ - " (0x%02x 0x%02x) 0x%04x\n", - drive->name, speed, - drive->dn, reg1, tmp1, reg2, tmp2, - udma, pio, err); -#endif - - return ide_config_drive_speed(drive, speed); -} - -static void hpt34x_tune_drive(struct ata_device *drive, u8 pio) -{ - (void) hpt34x_tune_chipset(drive, XFER_PIO_0 + min_t(u8, pio, 4)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int hpt34x_udma_setup(struct ata_device *drive, int map) -{ -#ifdef CONFIG_HPT34X_AUTODMA - return udma_generic_setup(drive, map); -#else - return 0; -#endif -} - -static int hpt34x_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - u8 dma_stat; - - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - udma_destroy_table(ch); /* purge DMA mappings */ - - return (dma_stat & 7) != 4; /* verify good DMA status */ -} - -static int hpt34x_udma_init(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - unsigned int count; - u8 cmd; - - if (!(count = udma_new_table(drive, rq))) - return ATA_OP_FINISHED; /* try PIO instead of DMA */ - - if (rq_data_dir(rq) == READ) - cmd = 0x09; - else - cmd = 0x01; - - outl(ch->dmatable_dma, dma_base + 4); /* PRD table */ - outb(cmd, dma_base); /* specify r/w */ - outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ - - if (drive->type == ATA_DISK) { - ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - } - - return ATA_OP_CONTINUES; -} -#endif - -/* - * If the BIOS does not set the IO base addaress to XX00, 343 will fail. - */ -#define HPT34X_PCI_INIT_REG 0x80 - -static unsigned int __init pci_init_hpt34x(struct pci_dev *dev) -{ - int i = 0; - unsigned long hpt34xIoBase = pci_resource_start(dev, 4); - unsigned short cmd; - unsigned long flags; - - local_irq_save(flags); - - pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); - pci_read_config_word(dev, PCI_COMMAND, &cmd); - - if (cmd & PCI_COMMAND_MEMORY) { - if (pci_resource_start(dev, PCI_ROM_RESOURCE)) { - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->resource[PCI_ROM_RESOURCE].start); - } - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); - } else { - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); - } - - pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); - dev->resource[0].start = (hpt34xIoBase + 0x20); - dev->resource[1].start = (hpt34xIoBase + 0x34); - dev->resource[2].start = (hpt34xIoBase + 0x28); - dev->resource[3].start = (hpt34xIoBase + 0x3c); - for(i=0; i<4; i++) - dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; - /* - * Since 20-23 can be assigned and are R/W, we correct them. - */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start); - pci_write_config_word(dev, PCI_COMMAND, cmd); - - local_irq_restore(flags); - - return dev->irq; -} - -static void __init ide_init_hpt34x(struct ata_channel *hwif) -{ - hwif->tuneproc = hpt34x_tune_drive; - hwif->speedproc = hpt34x_tune_chipset; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - unsigned short pcicmd = 0; - - pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd); -#ifdef CONFIG_IDEDMA_AUTO - hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; -#endif - hwif->udma_stop = hpt34x_udma_stop; - hwif->udma_init = hpt34x_udma_init; - hwif->modes_map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA | XFER_UDMA; - hwif->no_atapi_autodma = 1; - hwif->udma_setup = hpt34x_udma_setup; - hwif->highmem = 1; - } else -#endif - { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -} - - -/* module data table */ -static struct ata_pci_device chipset __initdata = { - .vendor = PCI_VENDOR_ID_TTI, - .device = PCI_DEVICE_ID_TTI_HPT343, - .init_chipset = pci_init_hpt34x, - .init_channel = ide_init_hpt34x, - .bootable = NEVER_BOARD, - .extra = 16, - .flags = ATA_F_DMA -}; - -int __init init_hpt34x(void) -{ - ata_register_chipset(&chipset); - - return 0; -} diff -Nru a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c --- a/drivers/ide/hpt366.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1263 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * linux/drivers/ide/hpt366.c Version 0.22 20 Sep 2001 - * - * Copyright (C) 1999-2000 Andre Hedrick - * Portions Copyright (C) 2001 Sun Microsystems, Inc. - * May be copied or modified under the terms of the GNU General Public License - * - * Thanks to HighPoint Technologies for their assistance, and hardware. - * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his - * donation of an ABit BP6 mainboard, processor, and memory acellerated - * development and support. - * - * Note that final HPT370 support was done by force extraction of GPL. - * - * - add function for getting/setting power status of drive - * - the HPT370's state machine can get confused. reset it before each dma - * xfer to prevent that from happening. - * - reset state engine whenever we get an error. - * - check for busmaster state at end of dma. - * - use new highpoint timings. - * - detect bus speed using highpoint register. - * - use pll if we don't have a clock table. added a 66MHz table that's - * just 2x the 33MHz table. - * - removed turnaround. NOTE: we never want to switch between pll and - * pci clocks as the chip can glitch in those cases. the highpoint - * approved workaround slows everything down too much to be useful. in - * addition, we would have to serialize access to each chip. - * Adrian Sun - * - * add drive timings for 66MHz PCI bus, - * fix ATA Cable signal detection, fix incorrect /proc info - * add /proc display for per-drive PIO/DMA/UDMA mode and - * per-channel ATA-33/66 Cable detect. - * Duncan Laurie - * - * fixup /proc output for multiple controllers - * Tim Hockin - * - * On hpt366: - * Reset the hpt366 on error, reset on dma - * Fix disabling Fast Interrupt hpt366. - * Mike Waychison - * - * 02 May 2002 - HPT374 support (Andre Hedrick ) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "timing.h" -#include "pcihost.h" - - -/* various tuning parameters */ -#define HPT_RESET_STATE_ENGINE -/*#define HPT_DELAY_INTERRUPT*/ -/*#define HPT_SERIALIZE_IO*/ - -static const char *quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -static const char *bad_ata100_5[] = { - "IBM-DTLA-307075", - "IBM-DTLA-307060", - "IBM-DTLA-307045", - "IBM-DTLA-307030", - "IBM-DTLA-307020", - "IBM-DTLA-307015", - "IBM-DTLA-305040", - "IBM-DTLA-305030", - "IBM-DTLA-305020", - "IC35L010AVER07-0", - "IC35L020AVER07-0", - "IC35L030AVER07-0", - "IC35L040AVER07-0", - "IC35L060AVER07-0", - "WDC AC310200R", - NULL -}; - -static const char *bad_ata66_4[] = { - "IBM-DTLA-307075", - "IBM-DTLA-307060", - "IBM-DTLA-307045", - "IBM-DTLA-307030", - "IBM-DTLA-307020", - "IBM-DTLA-307015", - "IBM-DTLA-305040", - "IBM-DTLA-305030", - "IBM-DTLA-305020", - "IC35L010AVER07-0", - "IC35L020AVER07-0", - "IC35L030AVER07-0", - "IC35L040AVER07-0", - "IC35L060AVER07-0", - "WDC AC310200R", - NULL -}; - -static const char *bad_ata66_3[] = { - "WDC AC310200R", - NULL -}; - -static const char *bad_ata33[] = { - "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", - "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", - "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", - "Maxtor 90510D4", - "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", - "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", - "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", - NULL -}; - -struct chipset_bus_clock_list_entry { - u8 xfer_speed; - unsigned int chipset_settings; -}; - -/* key for bus clock timings for HPT370 - * bit - * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file - * register access. - * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file - * register access. - * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. - * during task file register access. - * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA - * xfer. - * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task - * register access. - * 28 UDMA enable - * 29 DMA enable - * 30 PIO_MST enable. if set, the chip is in bus master mode during - * PIO. - * 31 FIFO enable. - */ -static struct chipset_bus_clock_list_entry forty_base_hpt366[] = { - { XFER_UDMA_4, 0x900fd943 }, - { XFER_UDMA_3, 0x900ad943 }, - { XFER_UDMA_2, 0x900bd943 }, - { XFER_UDMA_1, 0x9008d943 }, - { XFER_UDMA_0, 0x9008d943 }, - - { XFER_MW_DMA_2, 0xa008d943 }, - { XFER_MW_DMA_1, 0xa010d955 }, - { XFER_MW_DMA_0, 0xa010d9fc }, - - { XFER_PIO_4, 0xc008d963 }, - { XFER_PIO_3, 0xc010d974 }, - { XFER_PIO_2, 0xc010d997 }, - { XFER_PIO_1, 0xc010d9c7 }, - { XFER_PIO_0, 0xc018d9d9 }, - { 0, 0x0120d9d9 } -}; - -static struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { - { XFER_UDMA_4, 0x90c9a731 }, - { XFER_UDMA_3, 0x90cfa731 }, - { XFER_UDMA_2, 0x90caa731 }, - { XFER_UDMA_1, 0x90cba731 }, - { XFER_UDMA_0, 0x90c8a731 }, - - { XFER_MW_DMA_2, 0xa0c8a731 }, - { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */ - { XFER_MW_DMA_0, 0xa0c8a797 }, - - { XFER_PIO_4, 0xc0c8a731 }, - { XFER_PIO_3, 0xc0c8a742 }, - { XFER_PIO_2, 0xc0d0a753 }, - { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */ - { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */ - { 0, 0x0120a7a7 } -}; - -static struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { - - { XFER_UDMA_4, 0x90c98521 }, - { XFER_UDMA_3, 0x90cf8521 }, - { XFER_UDMA_2, 0x90cf8521 }, - { XFER_UDMA_1, 0x90cb8521 }, - { XFER_UDMA_0, 0x90cb8521 }, - - { XFER_MW_DMA_2, 0xa0ca8521 }, - { XFER_MW_DMA_1, 0xa0ca8532 }, - { XFER_MW_DMA_0, 0xa0ca8575 }, - - { XFER_PIO_4, 0xc0ca8521 }, - { XFER_PIO_3, 0xc0ca8532 }, - { XFER_PIO_2, 0xc0ca8542 }, - { XFER_PIO_1, 0xc0d08572 }, - { XFER_PIO_0, 0xc0d08585 }, - { 0, 0x01208585 } -}; - -#if 1 -/* these are the current (4 sep 2001) timings from highpoint */ -static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { - { XFER_UDMA_5, 0x12446231 }, - { XFER_UDMA_4, 0x12446231 }, - { XFER_UDMA_3, 0x126c6231 }, - { XFER_UDMA_2, 0x12486231 }, - { XFER_UDMA_1, 0x124c6233 }, - { XFER_UDMA_0, 0x12506297 }, - - { XFER_MW_DMA_2, 0x22406c31 }, - { XFER_MW_DMA_1, 0x22406c33 }, - { XFER_MW_DMA_0, 0x22406c97 }, - - { XFER_PIO_4, 0x06414e31 }, - { XFER_PIO_3, 0x06414e42 }, - { XFER_PIO_2, 0x06414e53 }, - { XFER_PIO_1, 0x06814e93 }, - { XFER_PIO_0, 0x06814ea7 }, - { 0, 0x06814ea7 } -}; - -/* 2x 33MHz timings */ -static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { - { XFER_UDMA_5, 0x1488e673 }, - { XFER_UDMA_4, 0x1488e673 }, - { XFER_UDMA_3, 0x1498e673 }, - { XFER_UDMA_2, 0x1490e673 }, - { XFER_UDMA_1, 0x1498e677 }, - { XFER_UDMA_0, 0x14a0e73f }, - - { XFER_MW_DMA_2, 0x2480fa73 }, - { XFER_MW_DMA_1, 0x2480fa77 }, - { XFER_MW_DMA_0, 0x2480fb3f }, - - { XFER_PIO_4, 0x0c82be73 }, - { XFER_PIO_3, 0x0c82be95 }, - { XFER_PIO_2, 0x0c82beb7 }, - { XFER_PIO_1, 0x0d02bf37 }, - { XFER_PIO_0, 0x0d02bf5f }, - { 0, 0x0d02bf5f } -}; -#else -/* from highpoint documentation. these are old values */ -static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { - { XFER_UDMA_5, 0x16454e31 }, - { XFER_UDMA_4, 0x16454e31 }, - { XFER_UDMA_3, 0x166d4e31 }, - { XFER_UDMA_2, 0x16494e31 }, - { XFER_UDMA_1, 0x164d4e31 }, - { XFER_UDMA_0, 0x16514e31 }, - - { XFER_MW_DMA_2, 0x26514e21 }, - { XFER_MW_DMA_1, 0x26514e33 }, - { XFER_MW_DMA_0, 0x26514e97 }, - - { XFER_PIO_4, 0x06514e21 }, - { XFER_PIO_3, 0x06514e22 }, - { XFER_PIO_2, 0x06514e33 }, - { XFER_PIO_1, 0x06914e43 }, - { XFER_PIO_0, 0x06914e57 }, - { 0, 0x06514e57 } -}; - -static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { - { XFER_UDMA_5, 0x14846231 }, - { XFER_UDMA_4, 0x14886231 }, - { XFER_UDMA_3, 0x148c6231 }, - { XFER_UDMA_2, 0x148c6231 }, - { XFER_UDMA_1, 0x14906231 }, - { XFER_UDMA_0, 0x14986231 }, - - { XFER_MW_DMA_2, 0x26514e21 }, - { XFER_MW_DMA_1, 0x26514e33 }, - { XFER_MW_DMA_0, 0x26514e97 }, - - { XFER_PIO_4, 0x06514e21 }, - { XFER_PIO_3, 0x06514e22 }, - { XFER_PIO_2, 0x06514e33 }, - { XFER_PIO_1, 0x06914e43 }, - { XFER_PIO_0, 0x06914e57 }, - { 0, 0x06514e57 } -}; -#endif - -static struct chipset_bus_clock_list_entry fifty_base_hpt370[] = { - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x0ac1f48a } -}; - -static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { - { XFER_UDMA_6, 0x1c81dc62 }, - { XFER_UDMA_5, 0x1c6ddc62 }, - { XFER_UDMA_4, 0x1c8ddc62 }, - { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ - { XFER_UDMA_2, 0x1c91dc62 }, - { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ - { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ - - { XFER_MW_DMA_2, 0x2c829262 }, - { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ - { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ - - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d5e } -}; - -static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x0a81f443 } -}; - -static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { - { XFER_UDMA_6, 0x1c869c62 }, - { XFER_UDMA_5, 0x1cae9c62 }, - { XFER_UDMA_4, 0x1c8a9c62 }, - { XFER_UDMA_3, 0x1c8e9c62 }, - { XFER_UDMA_2, 0x1c929c62 }, - { XFER_UDMA_1, 0x1c9a9c62 }, - { XFER_UDMA_0, 0x1c829c62 }, - - { XFER_MW_DMA_2, 0x2c829c62 }, - { XFER_MW_DMA_1, 0x2c829c66 }, - { XFER_MW_DMA_0, 0x2c829d2e }, - - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d26 } -}; - -static struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { - { XFER_UDMA_6, 0x12808242 }, - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x06814e93 } -}; - -#if 0 -static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { - { XFER_UDMA_6, 0x12406231 }, /* checkme */ - { XFER_UDMA_5, 0x12446231 }, - 0x14846231 - { XFER_UDMA_4, 0x16814ea7 }, - 0x14886231 - { XFER_UDMA_3, 0x16814ea7 }, - 0x148c6231 - { XFER_UDMA_2, 0x16814ea7 }, - 0x148c6231 - { XFER_UDMA_1, 0x16814ea7 }, - 0x14906231 - { XFER_UDMA_0, 0x16814ea7 }, - 0x14986231 - { XFER_MW_DMA_2, 0x16814ea7 }, - 0x26514e21 - { XFER_MW_DMA_1, 0x16814ea7 }, - 0x26514e97 - { XFER_MW_DMA_0, 0x16814ea7 }, - 0x26514e97 - { XFER_PIO_4, 0x06814ea7 }, - 0x06514e21 - { XFER_PIO_3, 0x06814ea7 }, - 0x06514e22 - { XFER_PIO_2, 0x06814ea7 }, - 0x06514e33 - { XFER_PIO_1, 0x06814ea7 }, - 0x06914e43 - { XFER_PIO_0, 0x06814ea7 }, - 0x06914e57 - { 0, 0x06814ea7 } -}; -#endif - -#define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT374_ALLOW_ATA133_6 0 -#define HPT372_ALLOW_ATA133_6 1 -#define HPT370_ALLOW_ATA100_5 1 -#define HPT366_ALLOW_ATA66_4 1 -#define HPT366_ALLOW_ATA66_3 1 -#define HPT366_MAX_DEVS 8 - -#define F_LOW_PCI_33 0x23 -#define F_LOW_PCI_40 0x29 -#define F_LOW_PCI_50 0x2d -#define F_LOW_PCI_66 0x42 - -static int check_in_drive_lists(struct ata_device *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (quirk_drives == list) { - while (*list) { - if (strstr(id->model, *list++)) { - return 1; - } - } - } else { - while (*list) { - if (!strcmp(*list++,id->model)) { - return 1; - } - } - } - return 0; -} - -static unsigned int hpt_revision(struct pci_dev *dev) -{ - u32 class_rev; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - switch(dev->device) { - case PCI_DEVICE_ID_TTI_HPT374: - class_rev = PCI_DEVICE_ID_TTI_HPT374; break; - case PCI_DEVICE_ID_TTI_HPT372: - class_rev = PCI_DEVICE_ID_TTI_HPT372; break; - default: - break; - } - return class_rev; -} - -static int __init hpt3xx_modes_map(struct ata_channel *ch) -{ - u32 rev = hpt_revision(ch->pci_dev); - int map = XFER_EPIO | XFER_MWDMA | XFER_UDMA | XFER_UDMA_66; - - if (rev >= 8) { /* HPT374 */ - if (HPT374_ALLOW_ATA133_6) - map |= XFER_UDMA_133; - map |= XFER_UDMA_100; - } else if (rev >= 5) { /* HPT372 */ - if (HPT372_ALLOW_ATA133_6) - map |= XFER_UDMA_133; - map |= XFER_UDMA_100; - } else if (rev >= 3) { /* HPT370A / HPT370 */ - if (HPT370_ALLOW_ATA100_5) - map |= XFER_UDMA_100; - } /* HPT366 / HPT368 */ - - return map; -} - - -static unsigned int pci_bus_clock_list(u8 speed, struct chipset_bus_clock_list_entry * chipset_table) -{ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { - return chipset_table->chipset_settings; - } - return chipset_table->chipset_settings; -} - -static void hpt366_tune_chipset(struct ata_device *drive, u8 speed) -{ - struct pci_dev *dev = drive->channel->pci_dev; - u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; - u8 regfast = (drive->channel->unit) ? 0x55 : 0x51; - /* - * since the channel is always 0 it does not matter. - */ - - u32 reg1, reg2; - u8 drive_fast; - - /* - * Disable the "fast interrupt" prediction. - */ - pci_read_config_byte(dev, regfast, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, regfast, drive_fast & ~0x80); - - pci_read_config_dword(dev, regtime, ®1); - reg2 = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) dev->sysdata); - /* - * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later) - */ - if (speed >= XFER_MW_DMA_0) { - reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); - } else { - reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000); - } - reg2 &= ~0x80000000; - - pci_write_config_dword(dev, regtime, reg2); -} - -static void hpt370_tune_chipset(struct ata_device *drive, u8 speed) -{ - u8 regfast = (drive->channel->unit) ? 0x55 : 0x51; - u32 list_conf, drive_conf; - u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; - u8 drive_pci = 0x40 + (drive->dn * 4); - u8 new_fast, drive_fast; - struct pci_dev *dev = drive->channel->pci_dev; - - /* - * Disable the "fast interrupt" prediction. - * don't holdoff on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, regfast, &drive_fast); - new_fast = drive_fast; - if (new_fast & 0x02) - new_fast &= ~0x02; - -#ifdef HPT_DELAY_INTERRUPT - if (new_fast & 0x01) - new_fast &= ~0x01; -#else - if ((new_fast & 0x01) == 0) - new_fast |= 0x01; -#endif - if (new_fast != drive_fast) - pci_write_config_byte(drive->channel->pci_dev, regfast, new_fast); - - list_conf = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) - dev->sysdata); - - pci_read_config_dword(dev, drive_pci, &drive_conf); - list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); - - if (speed < XFER_MW_DMA_0) { - list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - } - - pci_write_config_dword(dev, drive_pci, list_conf); -} - -static void hpt372_tune_chipset(struct ata_device *drive, u8 speed) -{ - u8 regfast = (drive->channel->unit) ? 0x55 : 0x51; - u32 list_conf, drive_conf; - u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; - u8 drive_pci = 0x40 + (drive->dn * 4); - u8 drive_fast; - struct pci_dev *dev = drive->channel->pci_dev; - - /* - * Disable the "fast interrupt" prediction. - * don't holdoff on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, regfast, &drive_fast); - drive_fast &= ~0x07; - pci_write_config_byte(drive->channel->pci_dev, regfast, drive_fast); - - list_conf = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) - dev->sysdata); - pci_read_config_dword(dev, drive_pci, &drive_conf); - list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); - if (speed < XFER_MW_DMA_0) - list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, drive_pci, list_conf); -} - -static int hpt3xx_tune_chipset(struct ata_device *drive, u8 speed) -{ - u32 rev; - - if ((drive->type != ATA_DISK) && (speed < XFER_SW_DMA_0)) - return -1; - - rev = hpt_revision(drive->channel->pci_dev); - - if (rev >= 5) { - hpt372_tune_chipset(drive, speed); - } else if (rev >= 3) { - hpt370_tune_chipset(drive, speed); - } else { - hpt366_tune_chipset(drive, speed); - } - - return ide_config_drive_speed(drive, speed); -} - -/* FIXME: pio == 255 -> ata_best_pio_mode(drive) --bkz */ -static void hpt3xx_tune_drive(struct ata_device *drive, u8 pio) -{ - (void) hpt3xx_tune_chipset(drive, XFER_PIO_0 + min_t(u8, pio, 4)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int hpt3xx_udma_setup(struct ata_device *drive, int map) -{ - u32 rev; - - if (drive->type != ATA_DISK) - return 0; - - rev = hpt_revision(drive->channel->pci_dev); - - /* FIXME: badlists need futher investigation --bkz */ - - /* bad_ata100_5 is for HPT370/370A, - bad_ata66_4, bad_ata66_3 and bad_ata33 are for HPT366/368 */ - - if (rev < 5 && check_in_drive_lists(drive, bad_ata100_5)) - map &= ~XFER_UDMA_100; - - if (rev < 3) { - if (check_in_drive_lists(drive, bad_ata66_4)) - map &= ~XFER_UDMA_66_4; - - if (check_in_drive_lists(drive, bad_ata66_3)) - map &= ~XFER_UDMA_66_3; - - if (check_in_drive_lists(drive, bad_ata33)) - map &= ~XFER_UDMA_ALL; - } - - return udma_generic_setup(drive, map); -} - -static int hpt3xx_quirkproc(struct ata_device *drive) -{ - return ((int) check_in_drive_lists(drive, quirk_drives)); -} - -static void hpt3xx_intrproc(struct ata_device *drive) -{ - if (drive->quirk_list) { - /* drives in the quirk_list may not like intr setups/cleanups */ - } else { - OUT_BYTE(0x02, drive->channel->io_ports[IDE_CONTROL_OFFSET]); - } -} - -static void hpt3xx_maskproc(struct ata_device *drive) -{ - struct pci_dev *dev = drive->channel->pci_dev; - struct ata_channel *ch = drive->channel; - - if (drive->quirk_list) { - u32 rev = hpt_revision(dev); - if (rev >= 3) { - u8 reg5a; - pci_read_config_byte(dev, 0x5a, ®5a); - if ((reg5a & 0x10) >> 4) - pci_write_config_byte(dev, 0x5a, reg5a & ~0x10); - } else - enable_irq(drive->channel->irq); - } else { - if (ch->io_ports[IDE_CONTROL_OFFSET]) - OUT_BYTE(0x00, ch->io_ports[IDE_CONTROL_OFFSET]); - } -} - -static void hpt366_udma_irq_lost(struct ata_device *drive) -{ - struct pci_dev *dev = drive->channel->pci_dev; - u8 reg50h, reg52h, reg5ah; - - pci_read_config_byte(dev, 0x50, ®50h); - pci_read_config_byte(dev, 0x52, ®52h); - pci_read_config_byte(dev, 0x5a, ®5ah); - printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", - drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); - if (reg5ah & 0x10) - pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); -} - -static void do_udma_start(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - - u8 regstate = ch->unit ? 0x54 : 0x50; - pci_write_config_byte(ch->pci_dev, regstate, 0x37); - udelay(10); -} - -static void hpt370_udma_start(struct ata_device *drive, struct request *__rq) -{ - struct ata_channel *ch = drive->channel; - - do_udma_start(drive); - - /* Note that this is done *after* the cmd has been issued to the drive, - * as per the BM-IDE spec. The Promise Ultra33 doesn't work correctly - * when we do this part before issuing the drive cmd. - */ - - outb(inb(ch->dma_base) | 1, ch->dma_base); /* start DMA */ -} - -static void do_timeout_irq(struct ata_device *drive) -{ - u8 dma_stat; - u8 regstate = drive->channel->unit ? 0x54 : 0x50; - u8 reginfo = drive->channel->unit ? 0x56 : 0x52; - unsigned long dma_base = drive->channel->dma_base; - - pci_read_config_byte(drive->channel->pci_dev, reginfo, &dma_stat); - printk(KERN_INFO "%s: %d bytes in FIFO\n", drive->name, dma_stat); - pci_write_config_byte(drive->channel->pci_dev, regstate, 0x37); - udelay(10); - dma_stat = inb(dma_base); - outb(dma_stat & ~0x1, dma_base); /* stop dma */ - dma_stat = inb(dma_base + 2); - outb(dma_stat | 0x6, dma_base+2); /* clear errors */ - -} - -static void hpt370_udma_timeout(struct ata_device *drive) -{ - do_timeout_irq(drive); - do_udma_start(drive); -} - -static void hpt370_udma_irq_lost(struct ata_device *drive) -{ - do_timeout_irq(drive); - do_udma_start(drive); -} - -static int hpt370_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - u8 dma_stat; - - dma_stat = inb(dma_base + 2); - if (dma_stat & 0x01) { - udelay(20); /* wait a little */ - dma_stat = inb(dma_base + 2); - } - if ((dma_stat & 0x01) != 0) { - do_timeout_irq(drive); - do_udma_start(drive); - } - - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - udma_destroy_table(ch); /* purge DMA mappings */ - - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ -} - -static int hpt374_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - struct pci_dev *dev = drive->channel->pci_dev; - unsigned long dma_base = ch->dma_base; - u8 mscreg = ch->unit ? 0x54 : 0x50; - u8 dma_stat; - u8 bwsr_mask = ch->unit ? 0x02 : 0x01; - u8 bwsr_stat, msc_stat; - pci_read_config_byte(dev, 0x6a, &bwsr_stat); - pci_read_config_byte(dev, mscreg, &msc_stat); - if ((bwsr_stat & bwsr_mask) == bwsr_mask) - pci_write_config_byte(dev, mscreg, msc_stat|0x30); - - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - udma_destroy_table(ch); /* purge DMA mappings */ - - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ -} -#endif - -/* - * Since SUN Cobalt is attempting to do this operation, I should disclose - * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date - * HOTSWAP ATA Infrastructure. - */ -static void hpt3xx_reset(struct ata_device *drive) -{ -#if 0 - unsigned long high_16 = pci_resource_start(drive->channel->pci_dev, 4); - u8 reset = (drive->channel->unit) ? 0x80 : 0x40; - u8 reg59h; - - pci_read_config_byte(drive->channel->pci_dev, 0x59, ®59h); - pci_write_config_byte(drive->channel->pci_dev, 0x59, reg59h|reset); - pci_write_config_byte(drive->channel->pci_dev, 0x59, reg59h); -#endif -} - -#if 0 -static int hpt3xx_tristate(struct ata_device * drive, int state) -{ - struct ata_channel *ch = drive->channel; - struct pci_dev *dev = ch->pci_dev; - u8 reset = (ch->unit) ? 0x80 : 0x40; - u8 state_reg = (ch->unit) ? 0x57 : 0x53; - u8 reg59h, regXXh; - - if (!ch) - return -EINVAL; - -// ch->bus_state = state; - - pci_read_config_byte(dev, 0x59, ®59h); - pci_read_config_byte(dev, state_reg, ®XXh); - - if (state) { - // reset drives... - pci_write_config_byte(dev, state_reg, regXXh|0x80); - pci_write_config_byte(dev, 0x59, reg59h|reset); - } else { - pci_write_config_byte(dev, 0x59, reg59h & ~(reset)); - pci_write_config_byte(dev, state_reg, regXXh & ~(0x80)); - // reset drives... - } - return 0; -} -#endif - -/* - * set/get power state for a drive. - * turning the power off does the following things: - * 1) soft-reset the drive - * 2) tri-states the ide bus - * - * when we turn things back on, we need to re-initialize things. - */ -#define TRISTATE_BIT 0x8000 -static int hpt370_busproc(struct ata_device * drive, int state) -{ - struct ata_channel *ch = drive->channel; - u8 tristate, resetmask, bus_reg; - u16 tri_reg; - - if (!ch) - return -EINVAL; - - ch->bus_state = state; - - if (ch->unit) { - /* secondary channel */ - tristate = 0x56; - resetmask = 0x80; - } else { - /* primary channel */ - tristate = 0x52; - resetmask = 0x40; - } - - /* grab status */ - pci_read_config_word(ch->pci_dev, tristate, &tri_reg); - pci_read_config_byte(ch->pci_dev, 0x59, &bus_reg); - - /* set the state. we don't set it if we don't need to do so. - * make sure that the drive knows that it has failed if it's off */ - switch (state) { - case BUSSTATE_ON: - ch->drives[0].failures = 0; - ch->drives[1].failures = 0; - if ((bus_reg & resetmask) == 0) - return 0; - tri_reg &= ~TRISTATE_BIT; - bus_reg &= ~resetmask; - break; - case BUSSTATE_OFF: - ch->drives[0].failures = ch->drives[0].max_failures + 1; - ch->drives[1].failures = ch->drives[1].max_failures + 1; - if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask)) - return 0; - tri_reg &= ~TRISTATE_BIT; - bus_reg |= resetmask; - break; - case BUSSTATE_TRISTATE: - ch->drives[0].failures = ch->drives[0].max_failures + 1; - ch->drives[1].failures = ch->drives[1].max_failures + 1; - if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask)) - return 0; - tri_reg |= TRISTATE_BIT; - bus_reg |= resetmask; - break; - } - pci_write_config_byte(ch->pci_dev, 0x59, bus_reg); - pci_write_config_word(ch->pci_dev, tristate, tri_reg); - - return 0; -} - -static void __init hpt37x_init(struct pci_dev *dev) -{ - int adjust, i; - u16 freq; - u32 pll, rev = hpt_revision(dev); - u8 reg5bh; - - /* - * default to pci clock. make sure MA15/16 are set to output - * to prevent drives having problems with 40-pin cables. - */ - pci_write_config_byte(dev, 0x5b, 0x23); - - /* - * set up the PLL. we need to adjust it so that it's stable. - * freq = Tpll * 192 / Tpci - */ - pci_read_config_word(dev, 0x78, &freq); - freq &= 0x1FF; - if (freq < 0x9c) { - pll = F_LOW_PCI_33; - if (rev >= 7) { - dev->sysdata = (void *) thirty_three_base_hpt374; - } else if (rev >= 5) { - dev->sysdata = (void *) thirty_three_base_hpt372; - } else { - dev->sysdata = (void *) thirty_three_base_hpt370; - } - printk("HPT37X: using 33MHz PCI clock\n"); - } else if (freq < 0xb0) { - pll = F_LOW_PCI_40; - } else if (freq < 0xc8) { - pll = F_LOW_PCI_50; - if (rev >= 7) { - // dev->sysdata = (void *) fifty_base_hpt374; - BUG(); - } else if (rev >= 5) { - dev->sysdata = (void *) fifty_base_hpt372; - } else { - dev->sysdata = (void *) fifty_base_hpt370; - } - printk("HPT37X: using 50MHz PCI clock\n"); - } else { - pll = F_LOW_PCI_66; - if (rev >= 7) { - // dev->sysdata = (void *) sixty_six_base_hpt374; - BUG(); - } else if (rev >= 5) { - dev->sysdata = (void *) sixty_six_base_hpt372; - } else { - dev->sysdata = (void *) sixty_six_base_hpt370; - } - printk("HPT37X: using 66MHz PCI clock\n"); - } - - /* - * only try the pll if we don't have a table for the clock - * speed that we're running at. NOTE: the internal PLL will - * result in slow reads when using a 33MHz PCI clock. we also - * don't like to use the PLL because it will cause glitches - * on PRST/SRST when the HPT state engine gets reset. - */ - if (dev->sysdata) - goto init_hpt37X_done; - - /* - * adjust PLL based upon PCI clock, enable it, and wait for - * stabilization. - */ - adjust = 0; - freq = (pll < F_LOW_PCI_50) ? 2 : 4; - while (adjust++ < 6) { - pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 | - pll | 0x100); - - /* wait for clock stabilization */ - for (i = 0; i < 0x50000; i++) { - pci_read_config_byte(dev, 0x5b, ®5bh); - if (reg5bh & 0x80) { - /* spin looking for the clock to destabilize */ - for (i = 0; i < 0x1000; ++i) { - pci_read_config_byte(dev, 0x5b, - ®5bh); - if ((reg5bh & 0x80) == 0) - goto pll_recal; - } - pci_read_config_dword(dev, 0x5c, &pll); - pci_write_config_dword(dev, 0x5c, - pll & ~0x100); - pci_write_config_byte(dev, 0x5b, 0x21); - if (rev >= 7) { - // dev->sysdata = (void *) fifty_base_hpt374; - BUG(); - } else if (rev >= 5) { - dev->sysdata = (void *) fifty_base_hpt372; - } else { - dev->sysdata = (void *) fifty_base_hpt370; - } - printk("HPT37X: using 50MHz internal PLL\n"); - goto init_hpt37X_done; - } - } -pll_recal: - if (adjust & 1) - pll -= (adjust >> 1); - else - pll += (adjust >> 1); - } - -init_hpt37X_done: - /* reset state engine */ - pci_write_config_byte(dev, 0x50, 0x37); - pci_write_config_byte(dev, 0x54, 0x37); - udelay(100); -} - -static void __init hpt366_init(struct pci_dev *dev) -{ - u32 reg1; - u8 drive_fast; - - /* - * Disable the "fast interrupt" prediction. - */ - pci_read_config_byte(dev, 0x51, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); - pci_read_config_dword(dev, 0x40, ®1); - - /* detect bus speed by looking at control reg timing: */ - switch((reg1 >> 8) & 7) { - case 5: - dev->sysdata = (void *) forty_base_hpt366; - break; - case 9: - dev->sysdata = (void *) twenty_five_base_hpt366; - break; - case 7: - default: - dev->sysdata = (void *) thirty_three_base_hpt366; - break; - } -} - -static unsigned int __init hpt366_init_chipset(struct pci_dev *dev) -{ - u32 rev = hpt_revision(dev); - u8 test; - - if (dev->resource[PCI_ROM_RESOURCE].start) - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - - pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); - if (test != (L1_CACHE_BYTES / 4)) - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); - if (test != 0x78) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - - pci_read_config_byte(dev, PCI_MIN_GNT, &test); - if (test != 0x08) - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - - pci_read_config_byte(dev, PCI_MAX_LAT, &test); - if (test != 0x08) - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - - if (rev >= 3) - hpt37x_init(dev); - else - hpt366_init(dev); - - return dev->irq; -} - -static unsigned int __init hpt366_ata66_check(struct ata_channel *ch) -{ - u8 ata66; - u8 regmask = (ch->unit) ? 0x01 : 0x02; - - pci_read_config_byte(ch->pci_dev, 0x5a, &ata66); -#ifdef DEBUG - printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", - ata66, (ata66 & regmask) ? "33" : "66", - PCI_FUNC(ch->pci_dev->devfn)); -#endif - return ((ata66 & regmask) ? 0 : 1); -} - -static void __init hpt366_init_channel(struct ata_channel *ch) -{ - struct pci_dev *dev = ch->pci_dev; - u32 rev = hpt_revision(dev); - - ch->udma_four = hpt366_ata66_check(ch); - - ch->tuneproc = hpt3xx_tune_drive; - ch->speedproc = hpt3xx_tune_chipset; - ch->quirkproc = hpt3xx_quirkproc; - ch->intrproc = hpt3xx_intrproc; - ch->maskproc = hpt3xx_maskproc; - -#ifdef HPT_SERIALIZE_IO - /* serialize access to this device */ - if (ch->mate) - ch->serialized = ch->mate->serialized = 1; -#endif - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (ch->dma_base) { - if (rev >= 3) { - u8 reg5ah; - pci_read_config_byte(dev, 0x5a, ®5ah); - if (reg5ah & 0x10) /* interrupt force enable */ - pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); - /* - * set up ioctl for power status. - * note: power affects both - * drives on each channel - */ - ch->resetproc = hpt3xx_reset; - ch->busproc = hpt370_busproc; - - if (rev >= 5) { - ch->udma_stop = hpt374_udma_stop; - } else { /* rev >= 3 */ - ch->udma_start = hpt370_udma_start; - ch->udma_stop = hpt370_udma_stop; - ch->udma_timeout = hpt370_udma_timeout; - ch->udma_irq_lost = hpt370_udma_irq_lost; - } - } else { - ch->udma_irq_lost = hpt366_udma_irq_lost; -// ch->resetproc = hpt3xx_reset; -// ch->busproc = hpt3xx_tristate; - } - ch->modes_map = hpt3xx_modes_map(ch); - ch->udma_setup = hpt3xx_udma_setup; - ch->highmem = 1; - } else -#endif - { - ch->drives[0].autotune = 1; - ch->drives[1].autotune = 1; - } -} - -static void __init hpt366_init_dma(struct ata_channel *ch, unsigned long dmabase) -{ - u8 masterdma, slavedma; - u8 dma_old = inb(dmabase + 2); - u8 dma_new = dma_old; - u8 primary = ch->unit ? 0x4b : 0x43; - - pci_read_config_byte(ch->pci_dev, primary, &masterdma); - pci_read_config_byte(ch->pci_dev, primary + 4, &slavedma); - - if (masterdma & 0x30) - dma_new |= 0x20; - if (slavedma & 0x30) - dma_new |= 0x40; - if (dma_new != dma_old) - outb(dma_new, dmabase+2); - - ata_init_dma(ch, dmabase); -} - - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_TTI, - .device = PCI_DEVICE_ID_TTI_HPT366, - .init_chipset = hpt366_init_chipset, - .init_channel = hpt366_init_channel, - .init_dma = hpt366_init_dma, - .bootable = OFF_BOARD, - .extra = 240, - .flags = ATA_F_IRQ | ATA_F_HPTHACK | ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_TTI, - .device = PCI_DEVICE_ID_TTI_HPT372, - .init_chipset = hpt366_init_chipset, - .init_channel = hpt366_init_channel, - .init_dma = hpt366_init_dma, - .bootable = OFF_BOARD, - .extra = 0, - .flags = ATA_F_IRQ | ATA_F_HPTHACK | ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_TTI, - .device = PCI_DEVICE_ID_TTI_HPT374, - .init_chipset = hpt366_init_chipset, - .init_channel = hpt366_init_channel, - .init_dma = hpt366_init_dma, - .bootable = OFF_BOARD, - .extra = 0, - .flags = ATA_F_IRQ | ATA_F_HPTHACK | ATA_F_DMA - }, -}; - -int __init init_hpt366(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/ide/hptraid.c b/drivers/ide/hptraid.c --- a/drivers/ide/hptraid.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,382 +0,0 @@ -/* - hptraid.c Copyright (C) 2001 Red Hat, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - (for example /usr/src/linux/COPYING); if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Authors: Arjan van de Ven - - Based on work - Copyleft (C) 2001 by Wilfried Weissmann - Copyright (C) 1994-96 Marc ZYNGIER - Based on work done by Søren Schmidt for FreeBSD - - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ataraid.h" - -static int hptraid_open(struct inode *inode, struct file *filp); -static int hptraid_release(struct inode *inode, struct file *filp); -static int hptraid_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -static int hptraid_make_request(request_queue_t * q, int rw, - struct buffer_head *bh); - - - -struct hptdisk { - kdev_t device; - unsigned long sectors; - struct block_device *bdev; -}; - -struct hptraid { - unsigned int stride; - unsigned int disks; - unsigned long sectors; - struct geom geom; - - struct hptdisk disk[8]; - - unsigned long cutoff[8]; - unsigned int cutoff_disks[8]; -}; - -static struct raid_device_operations hptraid_ops = { - .open = hptraid_open, - .release = hptraid_release, - .ioctl = hptraid_ioctl, - .make_request = hptraid_make_request -}; - -static struct hptraid raid[16]; - -static int hptraid_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - unsigned int minor = minor(inode->i_rdev) >> SHIFT; - struct hd_geometry *geometry = (struct hd_geometry *) arg; - struct hd_geometry g; - - if (cmd != HDIO_GETGEO) - return -EINVAL; - - g.heads = 255; - g.sectors = 63; - g.cylinders = raid[minor].sectors / 63 / 255; - g.start = get_start_sect(inode->i_bdev); - return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0; -} - -static int hptraid_make_request(request_queue_t * q, int rw, - struct buffer_head *bh) -{ - unsigned long rsect; - unsigned long rsect_left, rsect_accum = 0; - unsigned long block; - unsigned int disk = 0, real_disk = 0; - int i; - int device; - struct hptraid *thisraid; - - rsect = bh->b_rsector; - - /* Ok. We need to modify this sector number to a new disk + new sector number. - * If there are disks of different sizes, this gets tricky. - * Example with 3 disks (1Gb, 4Gb and 5 GB): - * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. - * Then things get interesting. The next 2Gb (RAID view) are spread across disk 2 and 3 - * and the last 1Gb is disk 3 only. - * - * the way this is solved is like this: We have a list of "cutoff" points where everytime - * a disk falls out of the "higher" count, we mark the max sector. So once we pass a cutoff - * point, we have to divide by one less. - */ - - device = (bh->b_rdev >> SHIFT) & MAJOR_MASK; - thisraid = &raid[device]; - if (thisraid->stride == 0) - thisraid->stride = 1; - - /* Woops we need to split the request to avoid crossing a stride barrier */ - if ((rsect / thisraid->stride) != - ((rsect + (bh->b_size / 512) - 1) / thisraid->stride)) { - return -1; - } - - rsect_left = rsect; - - for (i = 0; i < 8; i++) { - if (thisraid->cutoff_disks[i] == 0) - break; - if (rsect > thisraid->cutoff[i]) { - /* we're in the wrong area so far */ - rsect_left -= thisraid->cutoff[i]; - rsect_accum += - thisraid->cutoff[i] / - thisraid->cutoff_disks[i]; - } else { - block = rsect_left / thisraid->stride; - disk = block % thisraid->cutoff_disks[i]; - block = - (block / thisraid->cutoff_disks[i]) * - thisraid->stride; - rsect = - rsect_accum + (rsect_left % thisraid->stride) + - block; - break; - } - } - - for (i = 0; i < 8; i++) { - if ((disk == 0) - && (thisraid->disk[i].sectors > rsect_accum)) { - real_disk = i; - break; - } - if ((disk > 0) - && (thisraid->disk[i].sectors >= rsect_accum)) { - disk--; - } - - } - disk = real_disk; - - /* All but the first disk have a 10 sector offset */ - if (i > 0) - rsect += 10; - - - /* - * The new BH_Lock semantics in ll_rw_blk.c guarantee that this - * is the only IO operation happening on this bh. - */ - - bh->b_rdev = thisraid->disk[disk].device; - bh->b_rsector = rsect; - - /* - * Let the main block layer submit the IO and resolve recursion: - */ - return 1; -} - - -#include "hptraid.h" - -static int __init read_disk_sb(struct block_device *bdev, - struct highpoint_raid_conf *buf) -{ - /* Superblock is at 9*512 bytes */ - Sector sect; - unsigned char *p = read_dev_sector(bdev, 9, §); - - if (p) { - memcpy(buf, p, 512); - put_dev_sector(§); - return 0; - } - printk(KERN_ERR "hptraid: Error reading superblock.\n"); - return -1; -} - -static unsigned long maxsectors(int major, int minor) -{ - unsigned long lba = 0; - kdev_t dev; - struct ata_device *ideinfo; - - dev = mk_kdev(major, minor); - ideinfo = get_info_ptr(dev); - if (ideinfo == NULL) - return 0; - - - /* first sector of the last cluster */ - if (ideinfo->head == 0) - return 0; - if (ideinfo->sect == 0) - return 0; - lba = (ideinfo->capacity); - - return lba; -} - -static struct highpoint_raid_conf __initdata prom; -static void __init probedisk(int major, int minor, int device) -{ - int i; - struct block_device *bdev = bdget(mk_kdev(major, minor)); - - if (!bdev) - return; - - if (blkdev_get(bdev, FMODE_READ | FMODE_WRITE, 0, BDEV_RAW) < 0) - return; - - if (maxsectors(major, minor) == 0) - goto out; - - if (read_disk_sb(bdev, &prom)) - goto out; - - if (prom.magic != 0x5a7816f0) - goto out; - if (prom.type) { - printk(KERN_INFO - "hptraid: only RAID0 is supported currently\n"); - goto out; - } - - i = prom.disk_number; - if (i < 0) - goto out; - if (i > 8) - goto out; - - if (bd_claim(bdev, &raid[device].disk[i]) < 0) - goto out; - raid[device].disk[i].bdev = bdev; - raid[device].disk[i].device = mk_kdev(major, minor); - raid[device].disk[i].sectors = maxsectors(major, minor); - raid[device].stride = (1 << prom.raid0_shift); - raid[device].disks = prom.raid_disks; - raid[device].sectors = prom.total_secs; - return; - out: - blkdev_put(bdev); -} - -static void __init fill_cutoff(int device) -{ - int i, j; - unsigned long smallest; - unsigned long bar; - int count; - - bar = 0; - for (i = 0; i < 8; i++) { - smallest = ~0; - for (j = 0; j < 8; j++) - if ((raid[device].disk[j].sectors < smallest) - && (raid[device].disk[j].sectors > bar)) - smallest = raid[device].disk[j].sectors; - count = 0; - for (j = 0; j < 8; j++) - if (raid[device].disk[j].sectors >= smallest) - count++; - - smallest = smallest * count; - bar = smallest; - raid[device].cutoff[i] = smallest; - raid[device].cutoff_disks[i] = count; - - } -} - - -static __init int hptraid_init_one(int device) -{ - int i, count; - - probedisk(IDE0_MAJOR, 0, device); - probedisk(IDE0_MAJOR, 64, device); - probedisk(IDE1_MAJOR, 0, device); - probedisk(IDE1_MAJOR, 64, device); - probedisk(IDE2_MAJOR, 0, device); - probedisk(IDE2_MAJOR, 64, device); - probedisk(IDE3_MAJOR, 0, device); - probedisk(IDE3_MAJOR, 64, device); - - fill_cutoff(device); - - count = 0; - printk(KERN_INFO - "Highpoint HPT370 Softwareraid driver for linux version 0.01\n"); - - for (i = 0; i < 8; i++) { - if (raid[device].disk[i].device != 0) { - printk(KERN_INFO "Drive %i is %li Mb \n", - i, raid[device].disk[i].sectors / 2048); - count++; - } - } - if (count) { - ataraid_register_disk(device, raid[device].sectors); - printk(KERN_INFO "Raid array consists of %i drives. \n", - count); - return 0; - } else { - printk(KERN_INFO "No raid array found\n"); - return -ENODEV; - } - -} - -static __init int hptraid_init(void) -{ - int retval, device; - - device = ataraid_get_device(&hptraid_ops); - if (device < 0) - return -ENODEV; - retval = hptraid_init_one(device); - if (retval) - ataraid_release_device(device); - return retval; -} - -static void __exit hptraid_exit(void) -{ - int i, device; - for (device = 0; device < 16; device++) { - for (i = 0; i < 8; i++) { - struct block_device *bdev = - raid[device].disk[i].bdev; - raid[device].disk[i].bdev = NULL; - if (bdev) { - bd_release(bdev); - blkdev_put(bdev, BDEV_RAW); - } - } - if (raid[device].sectors) { - ataraid_unregister_disk(device); - ataraid_release_device(device); - } - } -} - -static int hptraid_open(struct inode *inode, struct file *filp) -{ - MOD_INC_USE_COUNT; - return 0; -} -static int hptraid_release(struct inode *inode, struct file *filp) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -module_init(hptraid_init); -module_exit(hptraid_exit); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/hptraid.h b/drivers/ide/hptraid.h --- a/drivers/ide/hptraid.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,77 +0,0 @@ -/*- - * Copyright (c) 2000,2001 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -struct highpoint_raid_conf -{ - int8_t filler1[32]; - u_int32_t magic; -#define HPT_MAGIC_OK 0x5a7816f0 -#define HPT_MAGIC_BAD 0x5a7816fd - - u_int32_t magic_0; - u_int32_t magic_1; - u_int32_t order; -#define HPT_O_MIRROR 0x01 -#define HPT_O_STRIPE 0x02 -#define HPT_O_OK 0x04 - - u_int8_t raid_disks; - u_int8_t raid0_shift; - u_int8_t type; -#define HPT_T_RAID_0 0x00 -#define HPT_T_RAID_1 0x01 -#define HPT_T_RAID_01_RAID_0 0x02 -#define HPT_T_SPAN 0x03 -#define HPT_T_RAID_3 0x04 -#define HPT_T_RAID_5 0x05 -#define HPT_T_SINGLEDISK 0x06 -#define HPT_T_RAID_01_RAID_1 0x07 - - u_int8_t disk_number; - u_int32_t total_secs; - u_int32_t disk_mode; - u_int32_t boot_mode; - u_int8_t boot_disk; - u_int8_t boot_protect; - u_int8_t error_log_entries; - u_int8_t error_log_index; - struct - { - u_int32_t timestamp; - u_int8_t reason; -#define HPT_R_REMOVED 0xfe -#define HPT_R_BROKEN 0xff - - u_int8_t disk; - u_int8_t status; - u_int8_t sectors; - u_int32_t lba; - } errorlog[32]; - u_int8_t filler[60]; -}; diff -Nru a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c --- a/drivers/ide/ht6560b.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,328 +0,0 @@ -/* - * Copyright (C) 1995-2000 Linus Torvalds & author (see below) - * - * Version 0.01 Initial version hacked out of ide.c - * - * Version 0.02 Added support for PIO modes, auto-tune - * - * Version 0.03 Some cleanups - * - * Version 0.05 PIO mode cycle timings auto-tune using bus-speed - * - * Version 0.06 Prefetch mode now defaults no OFF. To set - * prefetch mode OFF/ON use "hdparm -p8/-p9". - * Unmask irq is disabled when prefetch mode - * is enabled. - * - * Version 0.07 Trying to fix CD-ROM detection problem. - * "Prefetch" mode bit OFF for ide disks and - * ON for anything else. - * - * - * HT-6560B EIDE-controller support - * To activate controller support use kernel parameter "ide0=ht6560b". - * Use hdparm utility to enable PIO mode support. - * - * Author: Mikko Ala-Fossi - * Jan Evert van Grootheest - * - * Try: http://www.maf.iki.fi/~maf/ht6560b/ - */ - -#define HT6560B_VERSION "v0.07" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" - -/* #define DEBUG */ /* remove comments for DEBUG messages */ - -/* - * The special i/o-port that HT-6560B uses to configuration: - * bit0 (0x01): "1" selects secondary interface - * bit2 (0x04): "1" enables FIFO function - * bit5 (0x20): "1" enables prefetched data read function (???) - * - * The special i/o-port that HT-6560A uses to configuration: - * bit0 (0x01): "1" selects secondary interface - * bit1 (0x02): "1" enables prefetched data read function - * bit2 (0x04): "0" enables multi-master system (?) - * bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?) - */ -#define HT_CONFIG_PORT 0x3e6 -#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8) -/* - * FIFO + PREFETCH (both a/b-model) - */ -#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */ -/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */ -#define HT_SECONDARY_IF 0x01 -#define HT_PREFETCH_MODE 0x20 - -/* - * ht6560b Timing values: - * - * I reviewed some assembler source listings of htide drivers and found - * out how they setup those cycle time interfacing values, as they at Holtek - * call them. IDESETUP.COM that is supplied with the drivers figures out - * optimal values and fetches those values to drivers. I found out that - * they use IDE_SELECT_REG to fetch timings to the ide board right after - * interface switching. After that it was quite easy to add code to - * ht6560b.c. - * - * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine - * for hda and hdc. But hdb needed higher values to work, so I guess - * that sometimes it is necessary to give higher value than IDESETUP - * gives. [see cmd640.c for an extreme example of this. -ml] - * - * Perhaps I should explain something about these timing values: - * The higher nibble of value is the Recovery Time (rt) and the lower nibble - * of the value is the Active Time (at). Minimum value 2 is the fastest and - * the maximum value 15 is the slowest. Default values should be 15 for both. - * So 0x24 means 2 for rt and 4 for at. Each of the drives should have - * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or - * similar. If value is too small there will be all sorts of failures. - * - * Timing byte consists of - * High nibble: Recovery Cycle Time (rt) - * The valid values range from 2 to 15. The default is 15. - * - * Low nibble: Active Cycle Time (at) - * The valid values range from 2 to 15. The default is 15. - * - * You can obtain optimized timing values by running Holtek IDESETUP.COM - * for DOS. DOS drivers get their timing values from command line, where - * the first value is the Recovery Time and the second value is the - * Active Time for each drive. Smaller value gives higher speed. - * In case of failures you should probably fall back to a higher value. - */ -#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff) -#define HT_TIMING_DEFAULT 0xff - -/* - * This routine handles interface switching for the peculiar hardware design - * on the F.G.I./Holtek HT-6560B VLB IDE interface. - * The HT-6560B can only enable one IDE port at a time, and requires a - * silly sequence (below) whenever we switch between primary and secondary. - */ - -/* - * This routine is invoked from ide.c to prepare for access to a given drive. - */ -static void ht6560b_selectproc(struct ata_device *drive) -{ - unsigned long flags; - static u8 current_select = 0; - static u8 current_timing = 0; - u8 select, timing; - - local_irq_save(flags); - - select = HT_CONFIG(drive); - timing = HT_TIMING(drive); - - if (select != current_select || timing != current_timing) { - current_select = select; - current_timing = timing; - if (drive->type != ATA_DISK || !drive->present) - select |= HT_PREFETCH_MODE; - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - outb(select, HT_CONFIG_PORT); - /* - * Set timing for this drive: - */ - outb(timing, IDE_SELECT_REG); - ata_status(drive, 0, 0); -#ifdef DEBUG - printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, select, timing); -#endif - } - local_irq_restore(flags); -} - -/* - * Autodetection and initialization of ht6560b - */ -static int __init try_to_init_ht6560b(void) -{ - u8 orig_value; - int i; - - /* Autodetect ht6560b */ - if ((orig_value=inb(HT_CONFIG_PORT)) == 0xff) - return 0; - - for (i=3;i>0;i--) { - outb(0x00, HT_CONFIG_PORT); - if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) { - outb(orig_value, HT_CONFIG_PORT); - return 0; - } - } - outb(0x00, HT_CONFIG_PORT); - if ((~inb(HT_CONFIG_PORT))& 0x3f) { - outb(orig_value, HT_CONFIG_PORT); - return 0; - } - /* - * Ht6560b autodetected - */ - outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); - outb(HT_TIMING_DEFAULT, 0x1f6); /* SELECT */ - (void) inb(0x1f7); /* STATUS */ - - printk("\nht6560b " HT6560B_VERSION - ": chipset detected and initialized" -#ifdef DEBUG - " with debug enabled" -#endif - ); - return 1; -} - -static u8 ht_pio2timings(struct ata_device *drive, u8 pio) -{ - int active_time, recovery_time; - int active_cycles, recovery_cycles; - struct ata_timing *t; - - if (pio) { - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); - else - pio = XFER_PIO_0 + min_t(u8, pio, 4); - - t = ata_timing_data(pio); - - /* - * Just like opti621.c we try to calculate the - * actual cycle time for recovery and activity - * according system bus speed. - */ - active_time = t->active; - recovery_time = t->cycle - active_time - t->setup; - /* - * Cycle times should be Vesa bus cycles - */ - active_cycles = (active_time * system_bus_speed + 999999) / 1000000; - recovery_cycles = (recovery_time * system_bus_speed + 999999) / 1000000; - /* - * Upper and lower limits - */ - if (active_cycles < 2) active_cycles = 2; - if (recovery_cycles < 2) recovery_cycles = 2; - if (active_cycles > 15) active_cycles = 15; - if (recovery_cycles > 15) recovery_cycles = 0; /* 0==16 */ - -#ifdef DEBUG - printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", - drive->name, pio - XFER_PIO_0, recovery_cycles, recovery_time, active_cycles, active_time); -#endif - - return (u8)((recovery_cycles << 4) | active_cycles); - } else { - -#ifdef DEBUG - printk("ht6560b: drive %s setting pio=0\n", drive->name); -#endif - - return HT_TIMING_DEFAULT; /* default setting */ - } -} - -/* - * Enable/Disable so called prefetch mode - */ -static void ht_set_prefetch(struct ata_device *drive, u8 state) -{ - int t = HT_PREFETCH_MODE << 8; - - /* - * Prefetch mode and unmask irq seems to conflict - */ - if (state) { - drive->drive_data |= t; /* enable prefetch mode */ - drive->channel->no_unmask = 1; - drive->channel->unmask = 0; - } else { - drive->drive_data &= ~t; /* disable prefetch mode */ - drive->channel->no_unmask = 0; - } - -#ifdef DEBUG - printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); -#endif -} - -/* Assumes IRQ's are disabled or at least that no other process will attempt to - * access the IDE registers concurrently. - */ -static void tune_ht6560b(struct ata_device *drive, u8 pio) -{ - u8 timing; - - switch (pio) { - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - ht_set_prefetch(drive, pio & 1); - return; - } - - timing = ht_pio2timings(drive, pio); - - drive->drive_data &= 0xff00; - drive->drive_data |= timing; - -#ifdef DEBUG - printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); -#endif -} - -void __init init_ht6560b (void) -{ - int t; - - if (check_region(HT_CONFIG_PORT,1)) { - printk(KERN_ERR "ht6560b: PORT %#x ALREADY IN USE\n", HT_CONFIG_PORT); - } else { - if (try_to_init_ht6560b()) { - request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name); - ide_hwifs[0].chipset = ide_ht6560b; - ide_hwifs[1].chipset = ide_ht6560b; - ide_hwifs[0].selectproc = &ht6560b_selectproc; - ide_hwifs[1].selectproc = &ht6560b_selectproc; - ide_hwifs[0].tuneproc = &tune_ht6560b; - ide_hwifs[1].tuneproc = &tune_ht6560b; - ide_hwifs[0].serialized = 1; /* is this needed? */ - ide_hwifs[1].serialized = 1; /* is this needed? */ - ide_hwifs[0].unit = ATA_PRIMARY; - ide_hwifs[1].unit = ATA_SECONDARY; - - /* - * Setting default configurations for drives - */ - t = (HT_CONFIG_DEFAULT << 8); - t |= HT_TIMING_DEFAULT; - ide_hwifs[0].drives[0].drive_data = t; - ide_hwifs[0].drives[1].drive_data = t; - t |= (HT_SECONDARY_IF << 8); - ide_hwifs[1].drives[0].drive_data = t; - ide_hwifs[1].drives[1].drive_data = t; - } else - printk(KERN_ERR "ht6560b: not found\n"); - } -} diff -Nru a/drivers/ide/icside.c b/drivers/ide/icside.c --- a/drivers/ide/icside.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,782 +0,0 @@ -/* - * linux/drivers/ide/icside.c - * - * Copyright (c) 1996-2002 Russell King. - * - * Changelog: - * 08-Jun-1996 RMK Created - * 12-Sep-1997 RMK Added interrupt enable/disable - * 17-Apr-1999 RMK Added support for V6 EASI - * 22-May-1999 RMK Added support for V6 DMA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Maximum number of interfaces per card - */ -#define MAX_IFS 2 - -#define ICS_IDENT_OFFSET 0x8a0 - -#define ICS_ARCIN_V5_INTRSTAT 0x000 -#define ICS_ARCIN_V5_INTROFFSET 0x001 -#define ICS_ARCIN_V5_IDEOFFSET 0xa00 -#define ICS_ARCIN_V5_IDEALTOFFSET 0xae0 -#define ICS_ARCIN_V5_IDESTEPPING 4 - -#define ICS_ARCIN_V6_IDEOFFSET_1 0x800 -#define ICS_ARCIN_V6_INTROFFSET_1 0x880 -#define ICS_ARCIN_V6_INTRSTAT_1 0x8a4 -#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0 -#define ICS_ARCIN_V6_IDEOFFSET_2 0xc00 -#define ICS_ARCIN_V6_INTROFFSET_2 0xc80 -#define ICS_ARCIN_V6_INTRSTAT_2 0xca4 -#define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0 -#define ICS_ARCIN_V6_IDESTEPPING 4 - -struct cardinfo { - unsigned int dataoffset; - unsigned int ctrloffset; - unsigned int stepping; -}; - -static struct cardinfo icside_cardinfo_v5 = { - ICS_ARCIN_V5_IDEOFFSET, - ICS_ARCIN_V5_IDEALTOFFSET, - ICS_ARCIN_V5_IDESTEPPING -}; - -static struct cardinfo icside_cardinfo_v6_1 = { - ICS_ARCIN_V6_IDEOFFSET_1, - ICS_ARCIN_V6_IDEALTOFFSET_1, - ICS_ARCIN_V6_IDESTEPPING -}; - -static struct cardinfo icside_cardinfo_v6_2 = { - ICS_ARCIN_V6_IDEOFFSET_2, - ICS_ARCIN_V6_IDEALTOFFSET_2, - ICS_ARCIN_V6_IDESTEPPING -}; - -struct icside_state { - unsigned int channel; - unsigned int enabled; - unsigned int irq_port; -}; - -static const card_ids icside_cids[] = { - { MANU_ICS, PROD_ICS_IDE }, - { MANU_ICS2, PROD_ICS2_IDE }, - { 0xffff, 0xffff } -}; - -typedef enum { - ics_if_unknown, - ics_if_arcin_v5, - ics_if_arcin_v6 -} iftype_t; - -/* ---------------- Version 5 PCB Support Functions --------------------- */ -/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) - * Purpose : enable interrupts from card - */ -static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) -{ - unsigned int memc_port = (unsigned int)ec->irq_data; - outb (0, memc_port + ICS_ARCIN_V5_INTROFFSET); -} - -/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) - * Purpose : disable interrupts from card - */ -static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) -{ - unsigned int memc_port = (unsigned int)ec->irq_data; - inb (memc_port + ICS_ARCIN_V5_INTROFFSET); -} - -static const expansioncard_ops_t icside_ops_arcin_v5 = { - icside_irqenable_arcin_v5, - icside_irqdisable_arcin_v5, - NULL, - NULL, - NULL, - NULL -}; - - -/* ---------------- Version 6 PCB Support Functions --------------------- */ -/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) - * Purpose : enable interrupts from card - */ -static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) -{ - struct icside_state *state = ec->irq_data; - unsigned int base = state->irq_port; - - state->enabled = 1; - - switch (state->channel) { - case 0: - outb(0, base + ICS_ARCIN_V6_INTROFFSET_1); - inb(base + ICS_ARCIN_V6_INTROFFSET_2); - break; - case 1: - outb(0, base + ICS_ARCIN_V6_INTROFFSET_2); - inb(base + ICS_ARCIN_V6_INTROFFSET_1); - break; - } -} - -/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) - * Purpose : disable interrupts from card - */ -static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) -{ - struct icside_state *state = ec->irq_data; - - state->enabled = 0; - - inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); -} - -/* Prototype: icside_irqprobe(struct expansion_card *ec) - * Purpose : detect an active interrupt from card - */ -static int icside_irqpending_arcin_v6(struct expansion_card *ec) -{ - struct icside_state *state = ec->irq_data; - - return inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || - inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; -} - -static const expansioncard_ops_t icside_ops_arcin_v6 = { - icside_irqenable_arcin_v6, - icside_irqdisable_arcin_v6, - icside_irqpending_arcin_v6, - NULL, - NULL, - NULL -}; - -/* Prototype: icside_identifyif (struct expansion_card *ec) - * Purpose : identify IDE interface type - * Notes : checks the description string - */ -static iftype_t __init icside_identifyif (struct expansion_card *ec) -{ - unsigned int addr; - iftype_t iftype; - int id = 0; - - iftype = ics_if_unknown; - - addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; - - id = inb (addr) & 1; - id |= (inb (addr + 1) & 1) << 1; - id |= (inb (addr + 2) & 1) << 2; - id |= (inb (addr + 3) & 1) << 3; - - switch (id) { - case 0: /* A3IN */ - printk("icside: A3IN unsupported\n"); - break; - - case 1: /* A3USER */ - printk("icside: A3USER unsupported\n"); - break; - - case 3: /* ARCIN V6 */ - printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v6; - break; - - case 15:/* ARCIN V5 (no id) */ - printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v5; - break; - - default:/* we don't know - complain very loudly */ - printk("icside: ***********************************\n"); - printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id); - printk("icside: ***********************************\n"); - printk("icside: please report this to linux@arm.linux.org.uk\n"); - printk("icside: defaulting to ARCIN V5\n"); - iftype = ics_if_arcin_v5; - break; - } - - return iftype; -} - -/* - * Handle routing of interrupts. This is called before - * we write the command to the drive. - */ -static void icside_maskproc(struct ata_device *drive) -{ - const int mask = 0; - struct ata_channel *ch = drive->channel; - struct icside_state *state = ch->hw.priv; - unsigned long flags; - - local_irq_save(flags); - - state->channel = ch->unit; - - if (state->enabled && !mask) { - switch (ch->unit) { - case 0: - outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); - break; - case 1: - outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - break; - } - } else { - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - } - - local_irq_restore(flags); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS -/* - * SG-DMA support. - * - * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers. - * There is only one DMA controller per card, which means that only - * one drive can be accessed at one time. NOTE! We do not enforce that - * here, but we rely on the main IDE driver spotting that both - * interfaces use the same IRQ, which should guarantee this. - */ -#define NR_ENTRIES 256 -#define TABLE_SIZE (NR_ENTRIES * 8) - -static int ide_build_sglist(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - struct scatterlist *sg = ch->sg_table; - int nents; - - if ((rq->flags & REQ_SPECIAL) && (drive->type == ATA_DISK)) { - struct ata_taskfile *args = rq->special; - - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - ch->sg_dma_direction = PCI_DMA_TODEVICE; - else - ch->sg_dma_direction = PCI_DMA_FROMDEVICE; - - memset(sg, 0, sizeof(*sg)); - sg->page = virt_to_page(rq->buffer); - sg->offset = ((unsigned long)rq->buffer) & ~PAGE_MASK; - sg->length = rq->nr_sectors * SECTOR_SIZE; - nents = 1; - } else { - nents = blk_rq_map_sg(&drive->queue, rq, sg); - - if (rq->q && nents > rq->nr_phys_segments) - printk("icside: received %d segments, build %d\n", - rq->nr_phys_segments, nents); - - if (rq_data_dir(rq) == READ) - ch->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - ch->sg_dma_direction = PCI_DMA_TODEVICE; - } - - return pci_map_sg(NULL, sg, nents, ch->sg_dma_direction); -} - -/* Teardown mappings after DMA has completed. */ -static void icside_destroy_dmatable(struct ata_device *drive) -{ - struct scatterlist *sg = drive->channel->sg_table; - int nents = drive->channel->sg_nents; - - pci_unmap_sg(NULL, sg, nents, drive->channel->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 - * calculate the cycle time based on the transfer mode, and the EIDE - * MW DMA specs that the drive provides in the IDENTIFY command. - * - * We have the following IOMD DMA modes to choose from: - * - * Type Active Recovery Cycle - * A 250 (250) 312 (550) 562 (800) - * B 187 250 437 - * C 125 (125) 125 (375) 250 (500) - * D 62 125 187 - * - * (figures in brackets are actual measured timings) - * - * However, we also need to take care of the read/write active and - * recovery timings: - * - * Read Write - * Mode Active -- Recovery -- Cycle IOMD type - * MW0 215 50 215 480 A - * MW1 80 50 50 150 C - * MW2 70 25 25 120 C - */ -static int -icside_config_if(struct ata_device *drive, int xfer_mode) -{ - int on = 0, cycle_time = 0, use_dma_info = 0; - - switch (xfer_mode) { - case XFER_MW_DMA_2: cycle_time = 250; use_dma_info = 1; break; - case XFER_MW_DMA_1: cycle_time = 250; use_dma_info = 1; break; - case XFER_MW_DMA_0: cycle_time = 480; break; - } - - /* - * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should - * take care to note the values in the ID... - */ - if (use_dma_info && drive->id->eide_dma_time > cycle_time) - cycle_time = drive->id->eide_dma_time; - - drive->drive_data = cycle_time; - - if (cycle_time && ide_config_drive_speed(drive, xfer_mode) == 0) - on = 1; - else - drive->drive_data = 480; - - printk("%s: %02x selected (peak %dMB/s)\n", drive->name, - xfer_mode, 2000 / drive->drive_data); - - drive->current_speed = xfer_mode; - - return on; -} - -static int icside_set_speed(struct ata_device *drive, u8 speed) -{ - return icside_config_if(drive, speed); -} - -static void icside_dma_enable(struct ata_device *drive, int on, int verbose) -{ - if (!on) { - if (verbose) - printk("%s: DMA disabled\n", drive->name); -#ifdef CONFIG_BLK_DEV_IDE_TCQ - udma_tcq_enable(drive, 0); -#endif - } - - /* - * We don't need any bouncing. Yes, this looks the - * wrong way around, but it is correct. - */ - blk_queue_bounce_limit(&drive->queue, BLK_BOUNCE_ANY); - drive->using_dma = on; - -#ifdef CONFIG_CLK_DEV_IDE_TCQ_DEFAULT - if (on) - udma_tcq_enable(drive, 1); -#endif -} - -static int icside_dma_check(struct ata_device *drive, int map) -{ - struct hd_driveid *id = drive->id; - struct ata_channel *ch = drive->channel; - int xfer_mode = XFER_PIO_2; - int on; - - if (!id || !(id->capability & 1) || !ch->autodma) - goto out; - - /* - * Enable DMA on any drive that has multiword DMA - */ - if (id->field_valid & 2) { - if (id->dma_mword & 4) { - xfer_mode = XFER_MW_DMA_2; - } else if (id->dma_mword & 2) { - xfer_mode = XFER_MW_DMA_1; - } else if (id->dma_mword & 1) { - xfer_mode = XFER_MW_DMA_0; - } - } - -out: - on = icside_config_if(drive, xfer_mode); - - icside_dma_enable(drive, on, 0); - - return 0; -} - -static int icside_dma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - - disable_dma(ch->hw.dma); - icside_destroy_dmatable(drive); - - return get_dma_residue(ch->hw.dma) != 0; -} - -static void icside_dma_start(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - - /* We can not enable DMA on both channels simultaneously. */ - BUG_ON(dma_channel_active(ch->hw.dma)); - enable_dma(ch->hw.dma); -} - -/* - * dma_intr() is the handler for disk read/write DMA interrupts - */ -static ide_startstop_t icside_dmaintr(struct ata_device *drive, struct request *rq) -{ - int dma_stat; - - dma_stat = icside_dma_stop(drive); - if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { - if (!dma_stat) { - __ide_end_request(drive, rq, 1, rq->nr_sectors); - return ATA_OP_FINISHED; - } - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", - drive->name, dma_stat); - } - return ata_error(drive, rq, __FUNCTION__); -} - -static int -icside_dma_common(struct ata_device *drive, struct request *rq, - unsigned int dma_mode) -{ - struct ata_channel *ch = drive->channel; - unsigned int count; - - /* - * We can not enable DMA on both channels. - */ - BUG_ON(dma_channel_active(ch->hw.dma)); - - count = ch->sg_nents = ide_build_sglist(drive, rq); - if (!count) - return 1; - - /* - * Route the DMA signals to to this channel. - */ - outb(ch->select_data, ch->config_data); - - /* - * Select the correct timing for this drive. - */ - set_dma_speed(ch->hw.dma, drive->drive_data); - - /* - * Tell the DMA engine about the SG table and - * data direction. - */ - set_dma_sg(ch->hw.dma, ch->sg_table, count); - set_dma_mode(ch->hw.dma, dma_mode); - - return 0; -} - -static int icside_dma_init(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - u8 int cmd; - - if (icside_dma_common(drive, rq, DMA_MODE_WRITE)) - return ATA_OP_FINISHED; - - if (drive->type != ATA_DISK) - return ATA_OP_CONTINUES; - - ata_set_handler(drive, icside_dmaintr, WAIT_CMD, NULL); - - if ((rq->flags & REQ_SPECIAL) && drive->addressing == 1) { - struct ata_taskfile *args = rq->special; - cmd = args->cmd; - } else if (drive->addressing) { - cmd = rq_data_dir(rq) == WRITE ? WIN_WRITEDMA_EXT : WIN_READDMA_EXT; - } else { - cmd = rq_data_dir(rq) == WRITE ? WIN_WRITEDMA : WIN_READDMA; - } - OUT_BYTE(cmd, IDE_COMMAND_REG); - - enable_dma(ch->hw.dma); - - return ATA_OP_CONTINUES; -} - -static int icside_irq_status(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - struct icside_state *state = ch->hw.priv; - - return inb(state->irq_port + - (ch->unit ? - ICS_ARCIN_V6_INTRSTAT_2 : - ICS_ARCIN_V6_INTRSTAT_1)) & 1; -} - -static void icside_dma_timeout(struct ata_device *drive) -{ - printk(KERN_ERR "ATA: %s: UDMA timeout occured:", drive->name); - ata_status(drive, 0, 0); - ata_dump(drive, NULL, "UDMA timeout"); -} - -static void icside_irq_lost(struct ata_device *drive) -{ - printk(KERN_ERR "ATA: %s: IRQ lost\n", drive->name); -} - -static int icside_setup_dma(struct ata_channel *ch) -{ - int autodma = 0; - -#ifdef CONFIG_IDEDMA_ICS_AUTO - autodma = 1; -#endif - - printk(" %s: SG-DMA", ch->name); - - ch->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES, - GFP_KERNEL); - if (!ch->sg_table) - goto failed; - - ch->dmatable_cpu = NULL; - ch->dmatable_dma = 0; - ch->speedproc = icside_set_speed; - ch->udma_setup = icside_dma_check; - ch->udma_enable = icside_dma_enable; - ch->udma_start = icside_dma_start; - ch->udma_stop = icside_dma_stop; - ch->udma_init = icside_dma_init; - ch->udma_irq_status = icside_irq_status; - ch->udma_timeout = icside_dma_timeout; - ch->udma_irq_lost = icside_irq_lost; - ch->autodma = autodma; - - printk(" capable%s\n", autodma ? ", auto-enable" : ""); - - return 1; - -failed: - printk(" disabled, unable to allocate DMA table\n"); - return 0; -} - -void ide_release_dma(struct ata_channel *ch) -{ - if (ch->sg_table) { - kfree(ch->sg_table); - ch->sg_table = NULL; - } -} -#endif - -static struct ata_channel *icside_find_hwif(unsigned long dataport) -{ - struct ata_channel *ch; - int index; - - for (index = 0; index < MAX_HWIFS; ++index) { - ch = &ide_hwifs[index]; - if (ch->io_ports[IDE_DATA_OFFSET] == (ide_ioreg_t)dataport) - goto found; - } - - for (index = 0; index < MAX_HWIFS; ++index) { - ch = &ide_hwifs[index]; - if (!ch->io_ports[IDE_DATA_OFFSET]) - goto found; - } - - return NULL; -found: - return ch; -} - -static struct ata_channel * -icside_setup(unsigned long base, struct cardinfo *info, int irq) -{ - unsigned long port = base + info->dataoffset; - struct ata_channel *ch; - - ch = icside_find_hwif(base); - if (ch) { - int i; - - memset(&ch->hw, 0, sizeof(hw_regs_t)); - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - ch->hw.io_ports[i] = (ide_ioreg_t)port; - ch->io_ports[i] = (ide_ioreg_t)port; - port += 1 << info->stepping; - } - ch->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; - ch->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; - ch->hw.irq = irq; - ch->irq = irq; - ch->hw.dma = NO_DMA; - ch->noprobe = 0; - ch->chipset = ide_acorn; - } - - return ch; -} - -static int __init icside_register_v5(struct expansion_card *ec) -{ - unsigned long slot_port; - struct ata_channel *ch; - - slot_port = ecard_address(ec, ECARD_MEMC, 0); - - ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); - ec->irqmask = 1; - ec->irq_data = (void *)slot_port; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; - - /* - * Be on the safe side - disable interrupts - */ - inb(slot_port + ICS_ARCIN_V5_INTROFFSET); - - ch = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); - - return ch ? 0 : -1; -} - -static int __init icside_register_v6(struct expansion_card *ec) -{ - unsigned long slot_port, port; - struct icside_state *state; - struct ata_channel *ch0, *ch1; - unsigned int sel = 0; - - slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); - port = ecard_address(ec, ECARD_EASI, ECARD_FAST); - - if (port == 0) - port = slot_port; - else - sel = 1 << 5; - - outb(sel, slot_port); - - /* - * Be on the safe side - disable interrupts - */ - inb(port + ICS_ARCIN_V6_INTROFFSET_1); - inb(port + ICS_ARCIN_V6_INTROFFSET_2); - - /* - * Find and register the interfaces. - */ - ch0 = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); - ch1 = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); - - if (!ch0 || !ch1) - return -ENODEV; - - state = kmalloc(sizeof(struct icside_state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - state->channel = 0; - state->enabled = 0; - state->irq_port = port; - - ec->irq_data = state; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; - - ch0->maskproc = icside_maskproc; - ch0->unit = 0; - ch0->hw.priv = state; - ch0->config_data = slot_port; - ch0->select_data = sel; - ch0->hw.dma = ec->dma; - - ch1->maskproc = icside_maskproc; - ch1->unit = 1; - ch1->hw.priv = state; - ch1->config_data = slot_port; - ch1->select_data = sel | 1; - ch1->hw.dma = ec->dma; - -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS - if (ec->dma != NO_DMA && !request_dma(ec->dma, ch0->name)) { - icside_setup_dma(ch0); - icside_setup_dma(ch1); - } -#endif - return 0; -} - -int __init icside_init(void) -{ - ecard_startfind (); - - do { - struct expansion_card *ec; - int result; - - ec = ecard_find(0, icside_cids); - if (ec == NULL) - break; - - ecard_claim(ec); - - switch (icside_identifyif(ec)) { - case ics_if_arcin_v5: - result = icside_register_v5(ec); - break; - - case ics_if_arcin_v6: - result = icside_register_v6(ec); - break; - - default: - result = -1; - break; - } - - if (result) - ecard_release(ec); - } while (1); - - return 0; -} diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2999 +0,0 @@ -/* - * Copyright (C) 1994, 1995, 1996 scott snyder - * Copyright (C) 1996-1998 Erik Andersen - * Copyright (C) 1998-2000 Jens Axboe - * - * 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. ;-) - * For those wishing to work on this driver, please be sure you download - * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI - * (SFF-8020i rev 2.6) standards. These documents can be obtained by - * anonymous ftp from: - * - * ftp://fission.dt.wdc.com/pub/standards/SFF_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 accomodated as much - * as possible via compile time or command-line options. Since I only have - * a few drives, you generally need to send me patches... - * - * ---------------------------------- - * 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 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 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 ). - * 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 Eissfeldt - * to remove redundant verify_area calls. - * 3.12 May 7, 1996 -- Rudimentary changer support. Based on patches - * from Gerhard Zuber . - * 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 .) - * 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers - * from Ben Galliart with - * special help from Jeff Lightfoot - * - * 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 - * -- 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 - * 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 Aleks 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 - * , a patch for 2.0.33 - * by Toni Giorgino , 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" - * - * 4.50 Oct 19, 1998 -- New maintainers! - * Jens Axboe - * Chris Zwilling - * - * 4.51 Dec 23, 1998 -- Jens Axboe - * - ide_cdrom_reset enabled since the ide subsystem - * handles resets fine now. - * - Transfer size fix for Samsung CD-ROMs, thanks to - * "Ville Hallik" . - * - other minor stuff. - * - * 4.52 Jan 19, 1999 -- Jens Axboe - * - 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 Eissfeldt supplied - * some fixes for CDI. - * - CD-ROM leaving door locked fix from Andries - * Brouwer - * - Erik Andersen 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 - * - *************************************************************************/ - -#define IDECD_VERSION "4.59" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include "ide-cd.h" - -/**************************************************************************** - * Generic packet command support and error handling routines. - */ - -/* Mark that we've seen a media change, and invalidate our internal - buffers. */ -static void cdrom_saw_media_change(struct ata_device *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; -} - -static void cdrom_analyze_sense_data(struct ata_device *drive, struct request *rq) -{ - int log = 0; - /* FIXME --mdcki */ - struct packet_command *pc = (struct packet_command *) rq->special; - struct packet_command *failed_command = pc->failed_command; - - /* Decode sense data from drive */ - struct request_sense *sense = (struct request_sense *) (pc->buffer - rq->cmd[4]); - unsigned char fail_cmd; - - if (sense == NULL || failed_command == NULL || failed_command->quiet) - return; - - fail_cmd = rq->cmd[0]; - - /* Check whatever this error should be logged: - */ - switch (sense->sense_key) { - case NO_SENSE: - case RECOVERED_ERROR: - break; - - case NOT_READY: - - /* Don't care about tray state messages for e.g. - * capacity commands or in-progress or becoming ready. - */ - if (sense->asc == 0x3a || sense->asc == 0x04) - break; - log = 1; - break; - - case UNIT_ATTENTION: - - /* Make good and sure we've seen this potential media - * change. Some drives (i.e. Creative) fail to present - * the correct sense key in the error register. - */ - cdrom_saw_media_change(drive); - break; - - default: - log = 1; - break; - } - - if (!log) - return; - - /* - * If a read toc is executed for a CD-R or CD-RW medium where the first - * toc has not been recorded yet, it will fail with 05/24/00 (which is - * a confusing error). - */ - - if (fail_cmd == GPCMD_READ_TOC_PMA_ATIP) - if (sense->sense_key == 0x05 && sense->asc == 0x24) - return; - -#if VERBOSE_IDE_CD_ERRORS - { - int i; - const char *s; - 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 < ARY_LEN(sense_key_texts)) - s = sense_key_texts[sense->sense_key]; - else - s = "bad 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 = ARY_LEN(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(" %s -- (asc=0x%02x, ascq=0x%02x)\n", - s, sense->asc, sense->ascq); - - { - - int lo=0, mid, hi= ARY_LEN (packet_command_texts); - s = NULL; - - while (hi > lo) { - mid = (lo + hi) / 2; - if (packet_command_texts[mid].packet_command == fail_cmd) { - s = packet_command_texts[mid].text; - break; - } - if (packet_command_texts[mid].packet_command > fail_cmd) - hi = mid; - else - lo = mid+1; - } - - printk (" The failed \"%s\" packet command was: \n \"", s); - for (i=0; i < CDROM_PACKET_SIZE; i++) - printk ("%02x ", rq->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(" Command is %02d%% complete\n", progress / 0xffff); - - } - - if (sense->sense_key == ILLEGAL_REQUEST && - (sense->sks[0] & 0x80) != 0) { - printk(" 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 - - /* 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("%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 -} - -static void cdrom_queue_request_sense(struct ata_device *drive, - struct completion *wait, - struct request_sense *sense, - struct packet_command *failed_command) -{ - struct cdrom_info *info = drive->driver_data; - struct packet_command *pc = &info->request_sense_pc; - struct request *rq; - - if (sense == NULL) - sense = &info->sense_data; - - memset(pc, 0, sizeof(*pc)); - pc->buffer = (void *) sense; - pc->buflen = 18; - pc->failed_command = failed_command; - - /* stuff the sense request in front of our current request */ - rq = &info->request_sense_request; - memset(rq, 0, sizeof(*rq)); - rq->cmd[0] = GPCMD_REQUEST_SENSE; - rq->cmd[4] = pc->buflen; - rq->flags = REQ_SENSE; - - /* FIXME --mdcki */ - rq->special = (char *) pc; - - rq->waiting = wait; - ide_do_drive_cmd(drive, rq, ide_preempt); -} - - -static void cdrom_end_request(struct ata_device *drive, struct request *rq, int uptodate) -{ - if ((rq->flags & REQ_SENSE) && uptodate) - cdrom_analyze_sense_data(drive, rq); - - if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors) - uptodate = 1; - - ata_end_request(drive, rq, uptodate, 0); -} - - -/* Returns 0 if the request should be continued. - Returns 1 if the request was ended. */ -static int cdrom_decode_status(ide_startstop_t *startstop, struct ata_device *drive, struct request *rq, - int good_stat, int *stat_ret) -{ - int err, sense_key; - struct packet_command *pc; - int ok; - - /* Check for errors. */ - ok = ata_status(drive, good_stat, BAD_R_STAT); - *stat_ret = drive->status; - if (ok) - return 0; - - /* Get the IDE error register. */ - err = GET_ERR(); - sense_key = err >> 4; - - if (rq == NULL) { - printk("%s: missing rq in %s\n", drive->name, __FUNCTION__); - *startstop = ATA_OP_FINISHED; - return 1; - } - - if (rq->flags & REQ_SENSE) { - /* We got an error trying to get sense info - from the drive (probably while trying - to recover from a former error). Just give up. */ - - /* FIXME --mdcki */ - pc = (struct packet_command *) rq->special; - pc->stat = 1; - cdrom_end_request(drive, rq, 1); - *startstop = ata_error(drive, rq, "request sense failure"); - - return 1; - } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) { - /* All other functions, except for READ. */ - struct completion *wait = NULL; - - /* FIXME --mdcki */ - pc = (struct packet_command *) rq->special; - - /* Check for tray open. */ - if (sense_key == NOT_READY) { - cdrom_saw_media_change (drive); - } else if (sense_key == UNIT_ATTENTION) { - /* Check for media change. */ - cdrom_saw_media_change (drive); - /*printk("%s: media changed\n",drive->name);*/ - return 0; - } else if (!pc->quiet) { - /* Otherwise, print an error. */ - ata_dump(drive, rq, "packet command error"); - } - - /* Set the error flag and complete the request. - Then, if we have a CHECK CONDITION status, queue a request - sense command. We must be careful, though: we don't want - the thread in cdrom_queue_packet_command to wake up until - the request sense has completed. We do this by transferring - the semaphore from the packet command request to the request - sense request. */ - - if (drive->status & ERR_STAT) { - wait = rq->waiting; - rq->waiting = NULL; - } - - pc->stat = 1; - cdrom_end_request(drive, rq, 1); - - /* FIXME: this is the only place where pc->sense get's used. - * Think hard about how to get rid of it... - */ - - if (drive->status & ERR_STAT) - cdrom_queue_request_sense(drive, wait, pc->sense, pc); - } else if (rq->flags & REQ_CMD) { - /* Handle errors from READ and WRITE requests. */ - - if (sense_key == NOT_READY) { - /* Tray open. */ - cdrom_saw_media_change (drive); - - /* Fail the request. */ - printk ("%s: tray open\n", drive->name); - cdrom_end_request(drive, rq, 0); - } else if (sense_key == UNIT_ATTENTION) { - /* Media change. */ - cdrom_saw_media_change (drive); - - /* Arrange to retry the request. - But be sure to give up if we've retried - too many times. */ - if (++rq->errors > ERROR_MAX) - cdrom_end_request(drive, rq, 0); - } else if (sense_key == ILLEGAL_REQUEST || - sense_key == DATA_PROTECT) { - /* No point in retrying after an illegal - request or data protect error.*/ - ata_dump(drive, rq, "command error"); - cdrom_end_request(drive, rq, 0); - } else if (sense_key == MEDIUM_ERROR) { - /* No point in re-trying a zillion times on a bad - * sector. The error is not correctable at all. - */ - ata_dump(drive, rq, "media error (bad sector)"); - cdrom_end_request(drive, rq, 0); - } else if ((err & ~ABRT_ERR) != 0) { - /* Go to the default handler - for other errors. */ - *startstop = ata_error(drive, rq, __FUNCTION__); - return 1; - } else if ((++rq->errors > ERROR_MAX)) { - /* We've racked up too many retries. Abort. */ - cdrom_end_request(drive, rq, 0); - } - - /* If we got a CHECK_CONDITION status, - queue a request sense command. */ - if (drive->status & ERR_STAT) - cdrom_queue_request_sense(drive, NULL, NULL, NULL); - } else - blk_dump_rq_flags(rq, "ide-cd bad flags"); - - /* Retry, or handle the next request. */ - *startstop = ATA_OP_FINISHED; - return 1; -} - -static ide_startstop_t cdrom_timer_expiry(struct ata_device *drive, struct request *rq, unsigned long *wait) -{ - /* - * Some commands are *slow* and normally take a long time to - * complete. Usually we can use the ATAPI "disconnect" to bypass - * this, but not all commands/drives support that. Let - * ide_timer_expiry keep polling us for these. - */ - switch (rq->cmd[0]) { - case GPCMD_BLANK: - case GPCMD_FORMAT_UNIT: - case GPCMD_RESERVE_RZONE_TRACK: - *wait = WAIT_CMD; - return ATA_OP_CONTINUES; - default: - *wait = 0; - break; - } - - return ATA_OP_FINISHED; -} - -/* Set up the device registers for transferring a packet command on DEV, - expecting to later transfer XFERLEN bytes. HANDLER is the routine - which actually transfers the command to the drive. If this is a - drq_interrupt device, this routine will arrange for HANDLER to be - called when the interrupt from the drive arrives. Otherwise, HANDLER - will be called immediately after the drive is prepared for the transfer. */ - -static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, - struct request *rq, - int xferlen, - ata_handler_t handler) -{ - struct cdrom_info *info = drive->driver_data; - int ret; - - /* Wait for the controller to be idle. */ - ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_READY, rq); - if (ret != ATA_OP_READY) - return ret; - - if (info->dma) { - if (info->cmd == READ || info->cmd == WRITE) - info->dma = udma_init(drive, rq); - else - printk("ide-cd: DMA set, but not allowed\n"); - } - - /* Set up the controller registers. */ - OUT_BYTE(info->dma, IDE_FEATURE_REG); - OUT_BYTE(0, IDE_NSECTOR_REG); - OUT_BYTE(0, IDE_SECTOR_REG); - - OUT_BYTE(xferlen & 0xff, IDE_LCYL_REG); - OUT_BYTE(xferlen >> 8 , IDE_HCYL_REG); - ata_irq_enable(drive, 1); - if (info->dma) - udma_start(drive, rq); - - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ata_set_handler(drive, handler, WAIT_CMD, cdrom_timer_expiry); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - ret = ATA_OP_CONTINUES; - } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - ret = handler(drive, rq); - } - - return ret; -} - -/* - * Send a packet command cmd to the drive. The device registers must have - * already been prepared by cdrom_start_packet_command. "handler" is the - * interrupt handler to call when the command completes or there's data ready. - */ -static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive, - struct request *rq, - unsigned char *cmd, unsigned long timeout, - ata_handler_t handler) -{ - ide_startstop_t startstop; - - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - /* Here we should have been called after receiving an interrupt - from the device. DRQ should how be set. */ - int stat_dum; - - /* Check for errors. */ - if (cdrom_decode_status(&startstop, drive, rq, DRQ_STAT, &stat_dum)) - return startstop; - } else { - /* Otherwise, we must wait for DRQ to get set. */ - startstop = ata_status_poll(drive, DRQ_STAT, BUSY_STAT, - WAIT_READY, rq); - if (startstop != ATA_OP_READY) - return startstop; - } - - /* Arm the interrupt handler and send the command to the device. */ - ata_set_handler(drive, handler, timeout, cdrom_timer_expiry); - atapi_write(drive, cmd, CDROM_PACKET_SIZE); - - return ATA_OP_CONTINUES; -} - -/**************************************************************************** - * Block read functions. - */ - -/* - * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector - * buffer. Once the first sector is added, any subsequent sectors are - * assumed to be continuous (until the buffer is cleared). For the first - * sector added, SECTOR is its sector number. (SECTOR is then ignored until - * the buffer is cleared.) - */ -static void cdrom_buffer_sectors(struct ata_device *drive, unsigned long sector, - int sectors_to_transfer) -{ - struct cdrom_info *info = drive->driver_data; - - /* Number of sectors to read into the buffer. */ - int sectors_to_buffer = MIN (sectors_to_transfer, - (SECTOR_BUFFER_SIZE >> SECTOR_BITS) - - info->nsectors_buffered); - - char *dest; - - /* If we couldn't get a buffer, don't try to buffer anything... */ - if (info->buffer == NULL) - sectors_to_buffer = 0; - - /* If this is the first sector in the buffer, remember its number. */ - if (info->nsectors_buffered == 0) - info->sector_buffered = sector; - - /* Read the data into the buffer. */ - dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE; - while (sectors_to_buffer > 0) { - atapi_read(drive, dest, SECTOR_SIZE); - --sectors_to_buffer; - --sectors_to_transfer; - ++info->nsectors_buffered; - dest += SECTOR_SIZE; - } - - /* Throw away any remaining data. */ - while (sectors_to_transfer > 0) { - char dum[SECTOR_SIZE]; - atapi_read(drive, dum, sizeof (dum)); - --sectors_to_transfer; - } -} - -/* - * Check the contents of the interrupt reason register from the cdrom - * and attempt to recover if there are problems. Returns 0 if everything's - * ok; nonzero if the request has been terminated. - */ -static inline -int cdrom_read_check_ireason(struct ata_device *drive, struct request *rq, int len, int ireason) -{ - ireason &= 3; - if (ireason == 2) return 0; - - if (ireason == 0) { - /* Whoops... The drive is expecting to receive data from us! */ - printk ("%s: cdrom_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) { - u8 dummy[4]; - - atapi_write(drive, dummy, sizeof(dummy)); - len -= sizeof(dummy); - } - } else if (ireason == 1) { - /* Some drives (ASUS) seem to tell us that status - * info is available. just get it and ignore. - */ - ata_status(drive, 0, 0); - return 0; - } else { - /* Drive wants a command packet, or invalid ireason... */ - printk ("%s: cdrom_read_intr: bad interrupt reason %d\n", - drive->name, ireason); - } - - cdrom_end_request(drive, rq, 0); - return -1; -} - -/* - * Interrupt routine. Called when a read request has completed. - */ -static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request *rq) -{ - int stat; - int ireason, len, sectors_to_transfer, nskip; - struct cdrom_info *info = drive->driver_data; - int dma = info->dma, dma_error = 0; - ide_startstop_t startstop; - - /* Check for errors. */ - if (dma) { - info->dma = 0; - if ((dma_error = udma_stop(drive))) - udma_enable(drive, 0, 1); - } - - if (cdrom_decode_status(&startstop, drive, rq, 0, &stat)) - return startstop; - - if (dma) { - if (!dma_error) { - ata_end_request(drive, rq, 1, rq->nr_sectors); - - return ATA_OP_FINISHED; - } else - return ata_error(drive, rq, "dma error"); - } - - /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE (IDE_NSECTOR_REG); - len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG); - - /* 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 ("%s: cdrom_read_intr: data underrun (%u blocks)\n", - drive->name, rq->current_nr_sectors); - cdrom_end_request(drive, rq, 0); - } else - cdrom_end_request(drive, rq, 1); - return ATA_OP_FINISHED; - } - - /* Check that the drive is expecting to do the same thing we are. */ - if (cdrom_read_check_ireason(drive, rq, len, ireason)) - return ATA_OP_FINISHED; - - /* 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 ("%s: cdrom_read_intr: Bad transfer size %d\n", - drive->name, len); - if (CDROM_CONFIG_FLAGS (drive)->limit_nframes) - printk (" This drive is not supported by this version of the driver\n"); - else { - printk (" Trying to limit transfer sizes\n"); - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - } - cdrom_end_request(drive, rq, 0); - return ATA_OP_FINISHED; - } - - /* 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((int)(rq->current_nr_sectors - bio_sectors(rq->bio)), sectors_to_transfer); - - while (nskip > 0) { - /* We need to throw away a sector. */ - char dum[SECTOR_SIZE]; - atapi_read(drive, dum, SECTOR_SIZE); - - --rq->current_nr_sectors; - --nskip; - --sectors_to_transfer; - } - - /* Now loop while we still have data to read from the drive. */ - while (sectors_to_transfer > 0) { - int this_transfer; - - /* 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, rq, 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 (sectors_to_transfer, - rq->current_nr_sectors); - - /* Read this_transfer sectors - into the current buffer. */ - while (this_transfer > 0) { - atapi_read(drive, rq->buffer, SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->nr_sectors; - --rq->current_nr_sectors; - ++rq->sector; - --this_transfer; - --sectors_to_transfer; - } - } - } - - /* Done moving data! Wait for another interrupt. */ - ata_set_handler(drive, cdrom_read_intr, WAIT_CMD, NULL); - - return ATA_OP_CONTINUES; -} - -/* - * Try to satisfy some of the current read request from our cached data. - * Returns nonzero if the request has been completed, zero otherwise. - */ -static int cdrom_read_from_buffer(struct ata_device *drive, struct request *rq) -{ - struct cdrom_info *info = drive->driver_data; - - /* Can't do anything if there's no buffer. */ - if (info->buffer == NULL) return 0; - - /* Loop while this request needs data and the next block is present - in our cache. */ - while (rq->nr_sectors > 0 && - rq->sector >= info->sector_buffered && - rq->sector < info->sector_buffered + info->nsectors_buffered) { - if (rq->current_nr_sectors == 0) - cdrom_end_request(drive, rq, 1); - - memcpy (rq->buffer, - info->buffer + - (rq->sector - info->sector_buffered) * SECTOR_SIZE, - SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->current_nr_sectors; - --rq->nr_sectors; - ++rq->sector; - } - - /* If we've satisfied the current request, - terminate it successfully. */ - if (rq->nr_sectors == 0) { - cdrom_end_request(drive, rq, 1); - return -1; - } - - /* Move on to the next buffer if needed. */ - if (rq->current_nr_sectors == 0) - cdrom_end_request(drive, rq, 1); - - /* If this condition does not hold, then the kluge i use to - represent the number of sectors to skip at the start of a transfer - will fail. I think that this will never happen, but let's be - paranoid and check. */ - if (rq->current_nr_sectors < bio_sectors(rq->bio) && - (rq->sector % SECTORS_PER_FRAME) != 0) { - printk ("%s: %s: buffer botch (%ld)\n", - drive->name, __FUNCTION__, rq->sector); - cdrom_end_request(drive, rq, 0); - return -1; - } - - return 0; -} - -/* - * Routine to send a read packet command to the drive. This is usually called - * directly from cdrom_start_read. 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(struct ata_device *drive, struct request *rq) -{ - int nsect, sector, nframes, frame, nskip; - - /* Number of sectors to transfer. */ - nsect = rq->nr_sectors; - - /* Starting sector. */ - sector = rq->sector; - - /* 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 = (sector % SECTORS_PER_FRAME); - if (nskip > 0) { - /* Sanity check... */ - if (rq->current_nr_sectors != bio_sectors(rq->bio) && - (rq->sector % CD_FRAMESIZE != 0)) { - printk ("%s: %s: buffer botch (%u)\n", - drive->name, __FUNCTION__, rq->current_nr_sectors); - cdrom_end_request(drive, rq, 0); - return ATA_OP_FINISHED; - } - sector -= nskip; - nsect += nskip; - rq->current_nr_sectors += nskip; - } - - /* Convert from sectors to cdrom blocks, rounding up the transfer - length if needed. */ - nframes = (nsect + SECTORS_PER_FRAME-1) / SECTORS_PER_FRAME; - frame = sector / SECTORS_PER_FRAME; - - /* Largest number of frames was can transfer at once is 64k-1. For - some drives we need to limit this even more. */ - nframes = MIN(nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ? - (65534 / CD_FRAMESIZE) : 65535); - - /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, rq, rq->cmd, WAIT_CMD, &cdrom_read_intr); -} - - -#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */ -#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */ -#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */ - -static ide_startstop_t cdrom_seek_intr(struct ata_device *drive, struct request *rq) -{ - struct cdrom_info *info = drive->driver_data; - int stat; - static int retry = 10; - ide_startstop_t startstop; - - if (cdrom_decode_status (&startstop, drive, rq, 0, &stat)) - return startstop; - CDROM_CONFIG_FLAGS(drive)->seeking = 1; - - if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) { - if (--retry == 0) { - /* - * this condition is far too common, to bother - * users about it - */ -#if 0 - printk("%s: disabled DSC seek overlap\n", drive->name); -#endif - drive->dsc_overlap = 0; - } - } - return ATA_OP_FINISHED; -} - -static ide_startstop_t cdrom_start_seek_continuation(struct ata_device *drive, struct request *rq) -{ - unsigned char cmd[CDROM_PACKET_SIZE]; - sector_t sector; - int frame, nskip; - - sector = rq->sector; - nskip = (sector % SECTORS_PER_FRAME); - if (nskip > 0) - sector -= nskip; - frame = sector / SECTORS_PER_FRAME; - - memset(rq->cmd, 0, sizeof(rq->cmd)); - cmd[0] = GPCMD_SEEK; - put_unaligned(cpu_to_be32(frame), (unsigned int *) &cmd[2]); - - return cdrom_transfer_packet_command(drive, rq, cmd, WAIT_CMD, &cdrom_seek_intr); -} - -static ide_startstop_t cdrom_start_seek(struct ata_device *drive, struct request *rq, sector_t block) -{ - struct cdrom_info *info = drive->driver_data; - - info->dma = 0; - info->cmd = 0; - info->start_seek = jiffies; - return cdrom_start_packet_command(drive, rq, 0, cdrom_start_seek_continuation); -} - -/* - * Fix up a possibly partially-processed request so that we can - * start it over entirely -- remember to call prep_rq_fn again since we - * may have changed the layout - */ -static void restore_request (struct request *rq) -{ - if (rq->buffer != bio_data(rq->bio)) { - sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE; - rq->buffer = bio_data(rq->bio); - rq->nr_sectors += n; - rq->sector -= n; - } - rq->hard_cur_sectors = rq->current_nr_sectors = bio_sectors(rq->bio); - rq->hard_nr_sectors = rq->nr_sectors; - rq->hard_sector = rq->sector; - rq->q->prep_rq_fn(rq->q, rq); -} - -/* - * Start a read request from the CD-ROM. - */ -static ide_startstop_t cdrom_start_read(struct ata_device *drive, struct request *rq, sector_t block) -{ - struct cdrom_info *info = drive->driver_data; - - restore_request(rq); - - /* Satisfy whatever we can of this request from our cached sector. */ - if (cdrom_read_from_buffer(drive, rq)) - return ATA_OP_FINISHED; - - blk_attempt_remerge(&drive->queue, rq); - - /* Clear the local sector buffer. */ - info->nsectors_buffered = 0; - - /* use dma, if possible. */ - if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) && - (rq->nr_sectors % SECTORS_PER_FRAME == 0)) - info->dma = 1; - else - info->dma = 0; - - info->cmd = READ; - /* Start sending the read request to the drive. */ - return cdrom_start_packet_command(drive, rq, 32768, cdrom_start_read_continuation); -} - -/**************************************************************************** - * Execute all other packet commands. - */ - -/* Interrupt routine for packet command completion. */ -static ide_startstop_t cdrom_pc_intr(struct ata_device *drive, struct request *rq) -{ - int ireason, len, stat, thislen; - - /* FIXME --mdcki */ - struct packet_command *pc = (struct packet_command *) rq->special; - ide_startstop_t startstop; - - /* Check for errors. */ - if (cdrom_decode_status (&startstop, drive, rq, 0, &stat)) - return startstop; - - /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE (IDE_NSECTOR_REG); - len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG); - - /* 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 && - pc->buflen > 0 && - pc->buflen <= 5) { - while (pc->buflen > 0) { - *pc->buffer++ = 0; - --pc->buflen; - } - } - - if (pc->buflen == 0) - cdrom_end_request(drive, rq, 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); - */ - pc->stat = 1; - cdrom_end_request(drive, rq, 1); - } - return ATA_OP_FINISHED; - } - - /* Figure out how much data to transfer. */ - thislen = pc->buflen; - if (thislen > len) thislen = len; - - /* The drive wants to be written to. */ - if ((ireason & 3) == 0) { - /* Transfer the data. */ - atapi_write(drive, pc->buffer, thislen); - - /* If we haven't moved enough data to satisfy the drive, - add some padding. */ - while (len > thislen) { - u8 dummy[4]; - - atapi_write(drive, dummy, sizeof(dummy)); - len -= sizeof(dummy); - } - - /* Keep count of how much data we've moved. */ - pc->buffer += thislen; - pc->buflen -= thislen; - } - - /* Same drill for reading. */ - else if ((ireason & 3) == 2) { - /* Transfer the data. */ - atapi_read(drive, pc->buffer, thislen); - - /* If we haven't moved enough data to satisfy the drive, - add some padding. */ - while (len > thislen) { - u8 dummy[4]; - - atapi_read(drive, dummy, sizeof(dummy)); - len -= sizeof(dummy); - } - - /* Keep count of how much data we've moved. */ - pc->buffer += thislen; - pc->buflen -= thislen; - } else { - printk ("%s: cdrom_pc_intr: The drive " - "appears confused (ireason = 0x%2x)\n", - drive->name, ireason); - pc->stat = 1; - } - - /* Now we wait for another interrupt. */ - ata_set_handler(drive, cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); - - return ATA_OP_CONTINUES; -} - -static ide_startstop_t cdrom_do_pc_continuation(struct ata_device *drive, struct request *rq) -{ - unsigned long timeout; - - /* FIXME --mdcki */ - struct packet_command *pc = (struct packet_command *) rq->special; - - if (pc->timeout) - timeout = pc->timeout; - else - timeout = WAIT_CMD; - - /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, rq, rq->cmd, timeout, &cdrom_pc_intr); -} - -static ide_startstop_t cdrom_do_packet_command(struct ata_device *drive, struct request *rq) -{ - int len; - - /* FIXME --mdcki */ - struct packet_command *pc = (struct packet_command *) rq->special; - struct cdrom_info *info = drive->driver_data; - - info->dma = 0; - info->cmd = 0; - pc->stat = 0; - len = pc->buflen; - - /* Start sending the command to the drive. */ - return cdrom_start_packet_command (drive, rq, len, cdrom_do_pc_continuation); -} - - -/* Sleep for TIME jiffies. - Not to be called from an interrupt handler. */ -static -void cdrom_sleep (int time) -{ - int sleep = time; - - do { - set_current_state(TASK_INTERRUPTIBLE); - sleep = schedule_timeout(sleep); - } while (sleep); -} - -static -int cdrom_queue_packet_command(struct ata_device *drive, unsigned char *cmd, - struct request_sense *sense, struct packet_command *pc) -{ - struct request rq; - int retries = 10; - - /* Start of retry loop. */ - do { - memset(&rq, 0, sizeof(rq)); - memcpy(rq.cmd, cmd, CDROM_PACKET_SIZE); - rq.flags = REQ_PC; - - /* FIXME --mdcki */ - rq.special = (void *) pc; - if (ide_do_drive_cmd(drive, &rq, ide_wait)) { - printk("%s: do_drive_cmd returned stat=%02x,err=%02x\n", - drive->name, rq.buffer[0], rq.buffer[1]); - - /* FIXME: we should probably abort/retry or something */ - if (sense) { - - /* Decode the error here at least for error - * reporting to upper layers.! - */ - - } - } - if (pc->stat != 0) { - /* The request failed. Retry if it was due to a unit - attention status - (usually means media was changed). */ - - if (sense && sense->sense_key == UNIT_ATTENTION) - cdrom_saw_media_change (drive); - else if (sense && sense->sense_key == NOT_READY && - sense->asc == 4 && sense->ascq != 4) { - /* The drive is in the process of loading - a disk. Retry, but wait a little to give - the drive time to complete the load. */ - cdrom_sleep(2 * HZ); - } else { - /* Otherwise, don't retry. */ - retries = 0; - } - --retries; - } - - /* End of retry loop. */ - } while (pc->stat != 0 && retries >= 0); - - /* Return an error if the command failed. */ - return pc->stat ? -EIO : 0; -} - -/* - * Write handling - */ -static inline int cdrom_write_check_ireason(struct ata_device *drive, struct request *rq, - int len, int ireason) -{ - /* 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 data from us. - */ - ireason &= 3; - - if (ireason == 2) { - /* Whoops... The drive wants to send data. */ - printk("%s: cdrom_write_intr: wrong transfer direction!\n", - drive->name); - - /* Throw some data at the drive so it doesn't hang - and quit this request. */ - while (len > 0) { - u8 dummy[4]; - atapi_write(drive, dummy, sizeof(dummy)); - len -= sizeof(dummy); - } - } else { - /* Drive wants a command packet, or invalid ireason... */ - printk("%s: cdrom_write_intr: bad interrupt reason %d\n", - drive->name, ireason); - } - - cdrom_end_request(drive, rq, 0); - return 1; -} - -static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request *rq) -{ - int stat, ireason, len, sectors_to_transfer, uptodate; - struct cdrom_info *info = drive->driver_data; - int dma_error = 0, dma = info->dma; - ide_startstop_t startstop; - - /* Check for errors. */ - if (dma) { - info->dma = 0; - if ((dma_error = udma_stop(drive))) { - printk("ide-cd: write dma error\n"); - udma_enable(drive, 0, 1); - } - } - - if (cdrom_decode_status(&startstop, drive, rq, 0, &stat)) { - printk("ide-cd: write_intr decode_status bad\n"); - return startstop; - } - - /* - * using dma, transfer is complete now - */ - if (dma) { - if (dma_error) - return ata_error(drive, rq, "dma error"); - - ata_end_request(drive, rq, 1, rq->nr_sectors); - - return ATA_OP_FINISHED; - } - - /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE(IDE_NSECTOR_REG); - len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG); - - /* 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("%s: write_intr: data underrun (%u blocks)\n", - drive->name, rq->current_nr_sectors); - uptodate = 0; - } - cdrom_end_request(drive, rq, uptodate); - return ATA_OP_FINISHED; - } - - /* Check that the drive is expecting to do the same thing we are. */ - if (ireason & 3) - if (cdrom_write_check_ireason(drive, rq, len, ireason)) - return ATA_OP_FINISHED; - - 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("ide-cd: write_intr: oops\n"); - break; - } - - /* - * Figure out how many sectors we can transfer - */ - this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors); - - while (this_transfer > 0) { - atapi_write(drive, rq->buffer, SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->nr_sectors; - --rq->current_nr_sectors; - ++rq->sector; - --this_transfer; - --sectors_to_transfer; - } - - /* - * current buffer complete, move on - */ - if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request(drive, rq, 1); - } - - /* re-arm handler */ - ata_set_handler(drive, cdrom_write_intr, 5 * WAIT_CMD, NULL); - - return ATA_OP_CONTINUES; -} - -static ide_startstop_t cdrom_start_write_cont(struct ata_device *drive, struct request *rq) -{ - return cdrom_transfer_packet_command(drive, rq, rq->cmd, 2 * WAIT_CMD, cdrom_write_intr); -} - -static ide_startstop_t cdrom_start_write(struct ata_device *drive, struct request *rq) -{ - struct cdrom_info *info = drive->driver_data; - - /* - * writes *must* be 2kB frame aligned - */ - if ((rq->nr_sectors & 3) || (rq->sector & 3)) { - cdrom_end_request(drive, rq, 0); - return ATA_OP_FINISHED; - } - - /* - * for dvd-ram and such media, it's a really big deal to get - * big writes all the time. so scour the queue and attempt to - * remerge requests, often the plugging will not have had time - * to do this properly - */ - blk_attempt_remerge(&drive->queue, rq); - - info->nsectors_buffered = 0; - - /* use dma, if possible. we don't need to check more, since we - * know that the transfer is always (at least!) 2KB aligned */ - info->dma = drive->using_dma ? 1 : 0; - info->cmd = WRITE; - - /* Start sending the read request to the drive. */ - return cdrom_start_packet_command(drive, rq, 32768, cdrom_start_write_cont); -} - -#define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t))) - -/**************************************************************************** - * cdrom driver request routine. - */ -static ide_startstop_t -ide_cdrom_do_request(struct ata_device *drive, struct request *rq, sector_t block) -{ - int ret; - struct cdrom_info *info = drive->driver_data; - - if (rq->flags & REQ_CMD) { - if (CDROM_CONFIG_FLAGS(drive)->seeking) { - if (ATA_OP_READY != ata_status_poll(drive, SEEK_STAT, 0, IDECD_SEEK_TIMEOUT, rq)) { - printk ("%s: DSC timeout\n", drive->name); - CDROM_CONFIG_FLAGS(drive)->seeking = 0; - } else - return ATA_OP_FINISHED; - } - if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) { - ret = cdrom_start_seek(drive, rq, block); - } else { - if (rq_data_dir(rq) == READ) - ret = cdrom_start_read(drive, rq, block); - else - ret = cdrom_start_write(drive, rq); - } - info->last_block = block; - return ret; - } else if (rq->flags & (REQ_PC | REQ_SENSE)) { - ret = cdrom_do_packet_command(drive, rq); - - return ret; - } else if (rq->flags & REQ_SPECIAL) { - /* - * FIXME: Kill REQ_SEPCIAL and replace it with commands queued - * at the request queue instead as suggested by Linus. - * - * right now this can only be a reset... - */ - - cdrom_end_request(drive, rq, 1); - - return ATA_OP_FINISHED; - } else if (rq->flags & REQ_BLOCK_PC) { - struct packet_command pc; - ide_startstop_t startstop; - - memset(&pc, 0, sizeof(pc)); - pc.quiet = 1; - pc.timeout = 60 * HZ; - - /* FIXME --mdcki */ - rq->special = (char *) &pc; - - startstop = cdrom_do_packet_command(drive, rq); - - if (pc.stat) - ++rq->errors; - - return startstop; - } - - blk_dump_rq_flags(rq, "ide-cd bad flags"); - - cdrom_end_request(drive, rq, 0); - - return ATA_OP_FINISHED; -} - - - -/**************************************************************************** - * Ioctl handling. - * - * Routines which queue packet commands take as a final argument a pointer - * to a request_sense struct. If execution of the command results - * in an error with a CHECK CONDITION status, this structure will be filled - * with the results of the subsequent request sense command. The pointer - * 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, u8 *m, u8 *s, u8 *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(u8 m, u8 s, u8 f) -{ - return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; -} - -static int cdrom_check_status(struct ata_device *drive, struct request_sense *sense) -{ - unsigned char cmd[CDROM_PACKET_SIZE]; - struct packet_command pc; - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - cmd[0] = GPCMD_TEST_UNIT_READY; - -#if !STANDARD_ATAPI - /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to - switch CDs instead of supporting the LOAD_UNLOAD opcode */ - - cmd[7] = cdi->sanyo_slot % 3; -#endif - - return cdrom_queue_packet_command(drive, cmd, sense, &pc); -} - - -/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ -static int -cdrom_lockdoor(struct ata_device *drive, int lockflag, struct request_sense *sense) -{ - struct packet_command pc; - int stat; - - /* If the drive cannot lock the door, just pretend. */ - if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) { - stat = 0; - } else { - unsigned char cmd[CDROM_PACKET_SIZE]; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; - cmd[4] = lockflag ? 1 : 0; - stat = cdrom_queue_packet_command(drive, cmd, sense, &pc); - } - - /* 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 ("%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(struct ata_device *drive, int ejectflag, - struct request_sense *sense) -{ - struct packet_command pc; - unsigned char cmd[CDROM_PACKET_SIZE]; - - if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag) - return -EDRIVE_CANT_DO_THIS; - - /* reload fails on some drives, if the tray is locked */ - if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) - return 0; - - memset(&pc, 0, sizeof (pc)); - pc.sense = sense; - - cmd[0] = GPCMD_START_STOP_UNIT; - cmd[4] = 0x02 + (ejectflag != 0); - return cdrom_queue_packet_command(drive, cmd, sense, &pc); -} - -static int cdrom_read_capacity(struct ata_device *drive, u32 *capacity, - struct request_sense *sense) -{ - struct { - __u32 lba; - __u32 blocklen; - } capbuf; - - int stat; - unsigned char cmd[CDROM_PACKET_SIZE]; - struct packet_command pc; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - cmd[0] = GPCMD_READ_CDVD_CAPACITY; - pc.buffer = (char *)&capbuf; - pc.buflen = sizeof(capbuf); - stat = cdrom_queue_packet_command(drive, cmd, sense, &pc); - if (stat == 0) - *capacity = 1 + be32_to_cpu(capbuf.lba); - - return stat; -} - -static int cdrom_read_tocentry(struct ata_device *drive, int trackno, int msf_flag, - int format, char *buf, int buflen, - struct request_sense *sense) -{ - unsigned char cmd[CDROM_PACKET_SIZE]; - struct packet_command pc; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - pc.buffer = buf; - pc.buflen = buflen; - pc.quiet = 1; - - cmd[0] = GPCMD_READ_TOC_PMA_ATIP; - if (msf_flag) - cmd[1] = 2; - cmd[6] = trackno; - cmd[7] = (buflen >> 8); - cmd[8] = (buflen & 0xff); - cmd[9] = (format << 6); - - return cdrom_queue_packet_command(drive, cmd, sense, &pc); -} - - -/* Try to read the entire TOC for the disk into our internal buffer. */ -static int cdrom_read_toc(struct ata_device *drive, struct request_sense *sense) -{ - int stat, ntracks, i; - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - struct atapi_toc *toc = info->toc; - struct { - struct atapi_toc_header hdr; - struct atapi_toc_entry ent; - } ms_tmp; - - if (toc == NULL) { - /* Try to allocate space. */ - toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc), - GFP_KERNEL); - info->toc = toc; - if (toc == NULL) { - printk ("%s: No cdrom TOC buffer!\n", drive->name); - return -ENOMEM; - } - } - - /* Check to see if the existing data is still valid. - If it is, just return. */ - cdrom_check_status(drive, sense); - - if (CDROM_STATE_FLAGS(drive)->toc_valid) - return 0; - - /* First read just the header, so we know how long the TOC is. */ - stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, - sizeof(struct atapi_toc_header), 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); - } -#endif /* not STANDARD_ATAPI */ - - ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; - if (ntracks <= 0) - return -EIO; - if (ntracks > MAX_TRACKS) - ntracks = MAX_TRACKS; - - /* Now read the whole schmeer. */ - stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0, - (char *)&toc->hdr, - sizeof(struct atapi_toc_header) + - (ntracks + 1) * - sizeof(struct atapi_toc_entry), sense); - - if (stat && toc->hdr.first_track > 1) { - /* Cds with CDI tracks only don't have any TOC entries, - despite of this the returned values are - first_track == last_track = number of CDI tracks + 1, - so that this case is indistinguishable from the same - layout plus an additional audio track. - If we get an error for the regular case, we assume - a CDI without additional audio tracks. In this case - the readable TOC is empty (CDI tracks are not included) - and only holds the Leadout entry. Heiko EiÃ^ßfeldt */ - ntracks = 0; - stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0, - (char *)&toc->hdr, - sizeof(struct atapi_toc_header) + - (ntracks + 1) * - sizeof(struct atapi_toc_entry), - sense); - if (stat) { - return stat; - } -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bin2bcd(CDROM_LEADOUT); - toc->hdr.last_track = bin2bcd(CDROM_LEADOUT); - } else -#endif /* not STANDARD_ATAPI */ - { - toc->hdr.first_track = CDROM_LEADOUT; - toc->hdr.last_track = CDROM_LEADOUT; - } - } - - if (stat) - return stat; - - 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); - } -#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); - 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); - } - - /* Read the multisession information. */ - if (toc->hdr.first_track != CDROM_LEADOUT) { - /* Read the multisession information. */ - stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, - sizeof(ms_tmp), sense); - if (stat) return stat; - } else { - ms_tmp.ent.addr.msf.minute = 0; - ms_tmp.ent.addr.msf.second = 2; - ms_tmp.ent.addr.msf.frame = 0; - ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT; - } - -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) - msf_from_bcd (&ms_tmp.ent.addr.msf); -#endif /* not STANDARD_ATAPI */ - - toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute, - ms_tmp.ent.addr.msf.second, - ms_tmp.ent.addr.msf.frame); - - toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); - - /* Now try to get the total cdrom capacity. */ - /* FIXME: This is making worng assumptions about register layout. */ - stat = cdrom_get_last_written(cdi, (unsigned long *) &toc->capacity); - if (stat) - stat = cdrom_read_capacity(drive, &toc->capacity, sense); - if (stat) - toc->capacity = 0x1fffff; - - drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; - - /* Remember that we've read this stuff. */ - CDROM_STATE_FLAGS (drive)->toc_valid = 1; - - return 0; -} - - -static int cdrom_read_subchannel(struct ata_device *drive, int format, char *buf, - int buflen, struct request_sense *sense) -{ - unsigned char cmd[CDROM_PACKET_SIZE]; - struct packet_command pc; - - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - pc.buffer = buf; - pc.buflen = buflen; - cmd[0] = GPCMD_READ_SUBCHANNEL; - cmd[1] = 2; /* MSF addressing */ - cmd[2] = 0x40; /* request subQ data */ - cmd[3] = format; - cmd[7] = (buflen >> 8); - cmd[8] = (buflen & 0xff); - - return cdrom_queue_packet_command(drive, cmd, sense, &pc); -} - -/* ATAPI cdrom drives are free to select the speed you request or any slower - rate :-( Requesting too fast a speed will _not_ produce an error. */ -static int cdrom_select_speed(struct ata_device *drive, int speed, - struct request_sense *sense) -{ - unsigned char cmd[CDROM_PACKET_SIZE]; - struct packet_command pc; - memset(&pc, 0, sizeof(pc)); - pc.sense = sense; - - if (speed == 0) - speed = 0xffff; /* set to max */ - else - speed *= 177; /* Nx to kbytes/s */ - - cmd[0] = GPCMD_SET_SPEED; - /* Read Drive speed in kbytes/second MSB */ - cmd[2] = (speed >> 8) & 0xff; - /* Read Drive speed in kbytes/second LSB */ - 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 */ - cmd[4] = (speed >> 8) & 0xff; - /* Write Drive speed in kbytes/second LSB */ - cmd[5] = speed & 0xff; - } - - return cdrom_queue_packet_command(drive, cmd, sense, &pc); -} - -static int cdrom_play_audio(struct ata_device *drive, int lba_start, int lba_end) -{ - struct request_sense sense; - unsigned char cmd[CDROM_PACKET_SIZE]; - struct packet_command pc; - - memset(&pc, 0, sizeof (pc)); - pc.sense = &sense; - - cmd[0] = GPCMD_PLAY_AUDIO_MSF; - lba_to_msf(lba_start, &cmd[3], &cmd[4], &cmd[5]); - lba_to_msf(lba_end-1, &cmd[6], &cmd[7], &cmd[8]); - - return cdrom_queue_packet_command(drive, cmd, &sense, &pc); -} - -static int cdrom_get_toc_entry(struct ata_device *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]; - - return 0; -} - -/* the generic packet interface to cdrom.c */ -static int ide_cdrom_packet(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc) -{ - struct packet_command pc; - struct ata_device *drive = (struct ata_device *) cdi->handle; - - if (cgc->timeout <= 0) - cgc->timeout = WAIT_CMD; - - /* here we queue the commands from the uniform CD-ROM - layer. the packet must be complete, as we do not - touch it at all. */ - memset(&pc, 0, sizeof(pc)); - pc.buffer = cgc->buffer; - pc.buflen = cgc->buflen; - pc.quiet = cgc->quiet; - pc.timeout = cgc->timeout; - pc.sense = cgc->sense; - cgc->stat = cdrom_queue_packet_command(drive, cgc->cmd, cgc->sense, &pc); - if (!cgc->stat) - cgc->buflen -= pc.buflen; - - return cgc->stat; -} - - -static -int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, unsigned long arg) -{ - struct cdrom_generic_command cgc; - char buffer[16]; - int stat; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); - - /* These will be moved into the Uniform layer shortly... */ - switch (cmd) { - case CDROMSETSPINDOWN: { - char spindown; - - if (copy_from_user(&spindown, (void *) arg, sizeof(char))) - return -EFAULT; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f); - - return cdrom_mode_select(cdi, &cgc); - } - - case CDROMGETSPINDOWN: { - char spindown; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - spindown = buffer[11] & 0x0f; - - if (copy_to_user((void *) arg, &spindown, sizeof (char))) - return -EFAULT; - - return 0; - } - - default: - return -EINVAL; - } - -} - -static -int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, void *arg) -{ - struct ata_device *drive = (struct ata_device *) 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 = (struct cdrom_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 = (struct cdrom_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 = (struct cdrom_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) -{ - struct ata_device *drive = (struct ata_device *) cdi->handle; - struct request_sense sense; - struct request req; - int ret; - - memset(&req, 0, sizeof(req)); - req.flags = REQ_SPECIAL; - 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) - cdrom_lockdoor(drive, 1, &sense); - - return ret; -} - - -static -int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position) -{ - struct ata_device *drive = (struct ata_device *) 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) -{ - struct ata_device *drive = (struct ata_device *) cdi->handle; - struct request_sense sense; - - return cdrom_lockdoor(drive, lock, &sense); -} - -static -int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) -{ - struct ata_device *drive = (struct ata_device *) cdi->handle; - struct request_sense sense; - int stat; - - if ((stat = cdrom_select_speed (drive, speed, &sense)) < 0) - return stat; - - cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed; - return 0; -} - -static -int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) -{ - struct ata_device *drive = (struct ata_device *) cdi->handle; - - if (slot_nr == CDSL_CURRENT) { - struct request_sense sense; - int stat = cdrom_check_status(drive, &sense); - if (stat == 0 || sense.sense_key == UNIT_ATTENTION) - return CDS_DISC_OK; - - 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; - } - return -EINVAL; -} - -static -int ide_cdrom_get_last_session (struct cdrom_device_info *cdi, - struct cdrom_multisession *ms_info) -{ - struct atapi_toc *toc; - struct ata_device *drive = (struct ata_device *) 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]; - struct ata_device *drive = (struct ata_device *) 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; -} - - - -/**************************************************************************** - * Other driver requests (open, close, check media change). - */ - -static -int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi, - int slot_nr) -{ - struct ata_device *drive = (struct ata_device *) cdi->handle; - int retval; - - if (slot_nr == CDSL_CURRENT) { - cdrom_check_status(drive, NULL); - retval = CDROM_STATE_FLAGS (drive)->media_changed; - CDROM_STATE_FLAGS (drive)->media_changed = 0; - return retval; - } else { - return -EINVAL; - } -} - - -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) -{ -} - - - -/**************************************************************************** - * Device initialization. - */ -static struct cdrom_device_ops ide_cdrom_dops = { - .open = ide_cdrom_open_real, - .release = ide_cdrom_release_real, - .drive_status = ide_cdrom_drive_status, - .media_changed = ide_cdrom_check_media_change_real, - .tray_move = ide_cdrom_tray_move, - .lock_door = ide_cdrom_lock_door, - .select_speed = ide_cdrom_select_speed, - .get_last_session = ide_cdrom_get_last_session, - .get_mcn = ide_cdrom_get_mcn, - .reset = ide_cdrom_reset, - .audio_ioctl = ide_cdrom_audio_ioctl, - .dev_ioctl = ide_cdrom_dev_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_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R | - CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM | - CDC_GENERIC_PACKET, - .generic_packet = ide_cdrom_packet, -}; - -static int ide_cdrom_register(struct ata_device *drive, int nslots) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *devinfo = &info->devinfo; - int minor = (drive->select.b.unit) << PARTN_BITS; - - devinfo->dev = mk_kdev(drive->channel->major, minor); - devinfo->ops = &ide_cdrom_dops; - devinfo->mask = 0; - devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed; - devinfo->capacity = nslots; - devinfo->handle = (void *) drive; - strcpy(devinfo->name, drive->name); - - /* set capability mask to match the probe. */ - if (!CDROM_CONFIG_FLAGS (drive)->cd_r) - devinfo->mask |= CDC_CD_R; - if (!CDROM_CONFIG_FLAGS (drive)->cd_rw) - devinfo->mask |= CDC_CD_RW; - if (!CDROM_CONFIG_FLAGS (drive)->dvd) - devinfo->mask |= CDC_DVD; - if (!CDROM_CONFIG_FLAGS (drive)->dvd_r) - devinfo->mask |= CDC_DVD_R; - if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram) - devinfo->mask |= CDC_DVD_RAM; - if (!CDROM_CONFIG_FLAGS (drive)->is_changer) - devinfo->mask |= CDC_SELECT_DISC; - if (!CDROM_CONFIG_FLAGS (drive)->audio_play) - devinfo->mask |= CDC_PLAY_AUDIO; - if (!CDROM_CONFIG_FLAGS (drive)->close_tray) - devinfo->mask |= CDC_CLOSE_TRAY; - - /* FIXME: I'm less that sure that this is the proper thing to do, since - * ware already adding the devices to devfs int ide.c upon device - * registration. - */ - - devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT, - drive->channel->major, minor, - S_IFBLK | S_IRUGO | S_IWUGO, - ide_fops, NULL); - - return register_cdrom(devinfo); -} - -static -int ide_cdrom_get_capabilities(struct ata_device *drive, struct atapi_capabilities_page *cap) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - struct cdrom_generic_command cgc; - int stat, attempts = 3, size = sizeof(*cap); - - /* - * ACER50 (and others?) require the full spec length mode sense - * page capabilities size, but older drives break. - */ - if (drive->id) { - if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || - !strcmp(drive->id->model, "WPI CDS-32X"))) - size -= sizeof(cap->pad); - } - - /* we have to cheat a little here. the packet will eventually - * be queued with ide_cdrom_packet(), which extracts the - * drive from cdi->handle. Since this device hasn't been - * registered with the Uniform layer yet, it can't do this. - * Same goes for cdi->ops. - */ - cdi->handle = (struct ata_device *) drive; - cdi->ops = &ide_cdrom_dops; - init_cdrom_command(&cgc, cap, 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) - break; - } while (--attempts); - return stat; -} - -static -int ide_cdrom_probe_capabilities(struct ata_device *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - struct atapi_capabilities_page cap; - int nslots = 1; - - if (CDROM_CONFIG_FLAGS (drive)->nec260) { - CDROM_CONFIG_FLAGS (drive)->no_eject = 0; - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; - return nslots; - } - - if (ide_cdrom_get_capabilities(drive, &cap)) - 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; - 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; - 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) - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; - -#if ! STANDARD_ATAPI - if (cdi->sanyo_slot > 0) { - CDROM_CONFIG_FLAGS (drive)->is_changer = 1; - nslots = 3; - } - - 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; - } - } - - /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ - if (drive->id && !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; - } - - /* don't print speed if the drive reported 0. - */ - printk("%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" : ""); - - 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" : ""); - - if (CDROM_CONFIG_FLAGS (drive)->is_changer) - printk (" changer w/%d slots", nslots); - else - printk (" drive"); - - printk (", %dkB Cache", be16_to_cpu(cap.buffer_size)); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma) - udma_print(drive); -#endif - printk("\n"); - - return nslots; -} - - -/* - * standard prep_rq_fn that builds 10 byte cmds - */ -static int ll_10byte_cmd_build(request_queue_t *q, struct request *rq) -{ - int hard_sect = queue_hardsect_size(q); - sector_t block = rq->hard_sector / (hard_sect >> 9); - unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9); - - if (!(rq->flags & REQ_CMD)) - return 0; - - if (rq->hard_nr_sectors != rq->nr_sectors) { - printk(KERN_ERR "ide-cd: hard_nr_sectors differs from nr_sectors! %lu %lu\n", - rq->nr_sectors, rq->hard_nr_sectors); - } - memset(rq->cmd, 0, sizeof(rq->cmd)); - - if (rq_data_dir(rq) == READ) - rq->cmd[0] = GPCMD_READ_10; - else - rq->cmd[0] = GPCMD_WRITE_10; - - /* - * fill in lba - */ - rq->cmd[2] = (block >> 24) & 0xff; - rq->cmd[3] = (block >> 16) & 0xff; - rq->cmd[4] = (block >> 8) & 0xff; - rq->cmd[5] = block & 0xff; - - /* - * and transfer length - */ - rq->cmd[7] = (blocks >> 8) & 0xff; - rq->cmd[8] = blocks & 0xff; - - return 0; -} - -static int ide_cdrom_setup(struct ata_device *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - int minor = drive->select.b.unit << PARTN_BITS; - int nslots; - - /* - * default to read-only always and fix latter at the bottom - */ - set_device_ro(mk_kdev(drive->channel->major, minor), 1); - blk_queue_hardsect_size(&drive->queue, CD_FRAMESIZE); - - blk_queue_prep_rq(&drive->queue, ll_10byte_cmd_build); - - drive->ready_stat = 0; - - CDROM_STATE_FLAGS (drive)->media_changed = 1; - CDROM_STATE_FLAGS (drive)->toc_valid = 0; - CDROM_STATE_FLAGS (drive)->door_locked = 0; - -#if NO_DOOR_LOCKING - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; -#else - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0; -#endif - - if (drive->id != NULL) - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = - ((drive->id->config & 0x0060) == 0x20); - else - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0; - - 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; - if (drive->id != NULL) { - /* 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 (drive->id != NULL) { - 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; - - nslots = ide_cdrom_probe_capabilities (drive); - - if (CDROM_CONFIG_FLAGS(drive)->dvd_ram) - set_device_ro(mk_kdev(drive->channel->major, minor), 0); - - if (ide_cdrom_register (drive, nslots)) { - printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); - info->devinfo.handle = NULL; - return 1; - } - - return 0; -} - -/* Forwarding functions to generic routines. */ -static int ide_cdrom_ioctl(struct ata_device *drive, - struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return cdrom_ioctl(inode, file, cmd, arg); -} - -static int ide_cdrom_open (struct inode *ip, struct file *fp, struct ata_device *drive) -{ - struct cdrom_info *info = drive->driver_data; - int rc = -ENOMEM; - - MOD_INC_USE_COUNT; - if (info->buffer == NULL) - info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL); - if ((info->buffer == NULL) || (rc = cdrom_open(ip, fp))) { - drive->usage--; - MOD_DEC_USE_COUNT; - } - return rc; -} - -static -void ide_cdrom_release (struct inode *inode, struct file *file, - struct ata_device *drive) -{ - cdrom_release (inode, file); - MOD_DEC_USE_COUNT; -} - -static -int ide_cdrom_check_media_change(struct ata_device *drive) -{ - return cdrom_media_changed(mk_kdev (drive->channel->major, - (drive->select.b.unit) << PARTN_BITS)); -} - -static -void ide_cdrom_revalidate(struct ata_device *drive) -{ - struct request_sense sense; - cdrom_read_toc(drive, &sense); -} - -static sector_t ide_cdrom_capacity(struct ata_device *drive) -{ - u32 capacity; - - if (cdrom_read_capacity(drive, &capacity, NULL)) - return 0; - - return capacity * SECTORS_PER_FRAME; -} - -static -int ide_cdrom_cleanup(struct ata_device *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *devinfo = &info->devinfo; - - if (ata_unregister_device(drive)) - return 1; - if (info->buffer != NULL) - kfree(info->buffer); - if (info->toc != NULL) - kfree(info->toc); - if (info->changer_info != NULL) - kfree(info->changer_info); - if (devinfo->handle == drive && unregister_cdrom (devinfo)) - printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree(info); - drive->driver_data = NULL; - return 0; -} - -static void ide_cdrom_attach(struct ata_device *drive); - -static struct ata_operations ide_cdrom_driver = { - .owner = THIS_MODULE, - .attach = ide_cdrom_attach, - .cleanup = ide_cdrom_cleanup, - .standby = NULL, - .do_request = ide_cdrom_do_request, - .end_request = NULL, - .ioctl = ide_cdrom_ioctl, - .open = ide_cdrom_open, - .release = ide_cdrom_release, - .check_media_change = ide_cdrom_check_media_change, - .revalidate = ide_cdrom_revalidate, - .capacity = ide_cdrom_capacity, -}; - -/* options */ -static char *ignore = NULL; - -static void ide_cdrom_attach(struct ata_device *drive) -{ - struct cdrom_info *info; - char *req; - struct ata_channel *channel; - struct gendisk *disk; - int unit; - - if (drive->type != ATA_ROM) - return; - - req = drive->driver_req; - if (req[0] != '\0' && strcmp(req, "ide-cdrom")) - return; - - /* skip drives that we were told to ignore */ - if (ignore && !strcmp(ignore, drive->name)) { - printk(KERN_INFO "%s: ignored\n", drive->name); - return; - } - info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL); - if (!info) { - printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name); - return; - } - if (ata_register_device(drive, &ide_cdrom_driver)) { - printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name); - kfree (info); - return; - } - - - memset(info, 0, sizeof (struct cdrom_info)); - drive->driver_data = info; - - if (ide_cdrom_setup (drive)) { - if (ide_cdrom_cleanup (drive)) - printk (KERN_ERR "%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name); - return; - } - - channel = drive->channel; - unit = drive - channel->drives; - disk = channel->gd[unit]; - disk->minor_shift = 0; - ide_cdrom_revalidate(drive); - register_disk(disk, mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, disk->fops, - ide_cdrom_capacity(drive)); -} - -MODULE_PARM(ignore, "s"); -MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); - -static void __exit ide_cdrom_exit(void) -{ - unregister_ata_driver(&ide_cdrom_driver); -} - -int ide_cdrom_init(void) -{ - return ata_driver_module(&ide_cdrom_driver); -} - -module_init(ide_cdrom_init); -module_exit(ide_cdrom_exit); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h --- a/drivers/ide/ide-cd.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,742 +0,0 @@ -/* - * linux/drivers/ide/ide_cd.h - * - * Copyright (C) 1996-98 Erik Andersen - * Copyright (C) 1998-2000 Jens Axboe - */ -#ifndef _IDE_CD_H -#define _IDE_CD_H - -#include -#include - -/* 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 - -/************************************************************************/ - -#define SECTOR_BITS 9 -#ifndef SECTOR_SIZE -# define SECTOR_SIZE (1 << SECTOR_BITS) -#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) - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -/* 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 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 reserved : 3; - u8 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; - u8 current_speed; /* Current speed of the drive */ -}; - -#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags)) - -struct packet_command { - char *buffer; - int buflen; - int stat; - int quiet; - int timeout; - struct request_sense *sense; - - /* This is currently used to pass failed commands through the request - * queue. Is this for asynchronos error reporting? - * - * Can we always be sure that this didn't valish from stack beneath us - * - we can't! - */ - - struct packet_command *failed_command; -}; - -/* Structure of a MSF cdrom address. */ -struct atapi_msf { - u8 __reserved; - u8 minute; - u8 second; - u8 frame; -} __attribute__((packed)); - -/* Space to hold the disk TOC. */ -#define MAX_TRACKS 99 -struct atapi_toc_header { - u16 toc_length; - u8 first_track; - u8 last_track; -} __attribute__((packed)); - -struct atapi_toc_entry { - u8 reserved1; -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 adr : 4; - __u8 control : 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 control : 4; - __u8 adr : 4; -#else -#error "Please fix " -#endif - u8 track; - u8 reserved2; - union { - unsigned lba; - struct atapi_msf msf; - } addr; -}; - -struct atapi_toc { - int last_session_lba; - int xa_flag; - u32 capacity; - struct atapi_toc_header hdr; - struct atapi_toc_entry ent[MAX_TRACKS+1]; /* 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 { - u8 acdsc_reserved; - u8 acdsc_audiostatus; - u16 acdsc_length; - u8 acdsc_format; - -#if defined(__BIG_ENDIAN_BITFIELD) - u8 acdsc_ctrl: 4; - u8 acdsc_adr: 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - u8 acdsc_adr: 4; - u8 acdsc_ctrl: 4; -#else -#error "Please fix " -#endif - u8 acdsc_trk; - u8 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 " -#endif - - u8 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 " -#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 " -#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 " -#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 " -#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 " -#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 " -#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 " -#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 " -#endif - - u8 curlba[3]; - u8 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 " -#endif - - u8 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 { - - /* Buffer for table of contents. NULL if we haven't allocated - a TOC buffer for this device yet. */ - - struct atapi_toc *toc; - - unsigned long sector_buffered; - unsigned long nsectors_buffered; - unsigned char *buffer; - - /* The result of the last successful request sense command - on this device. */ - struct request_sense sense_data; - - struct request request_sense_request; - struct packet_command request_sense_pc; - int dma; - int cmd; - 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; - - /* Per-device info needed by cdrom.c generic driver. */ - struct cdrom_device_info devinfo; -}; - -/**************************************************************************** - * Descriptions of ATAPI error codes. - */ - -#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0]))) - -/* This stuff should be in cdrom.h, since it is now generic... */ - -/* ATAPI sense keys (from table 140 of ATAPI 2.6) */ -#define NO_SENSE 0x00 -#define RECOVERED_ERROR 0x01 -#define NOT_READY 0x02 -#define MEDIUM_ERROR 0x03 -#define HARDWARE_ERROR 0x04 -#define ILLEGAL_REQUEST 0x05 -#define UNIT_ATTENTION 0x06 -#define DATA_PROTECT 0x07 -#define ABORTED_COMMAND 0x0b -#define MISCOMPARE 0x0e - -/* This stuff should be in cdrom.h, since it is now generic... */ -#if VERBOSE_IDE_CD_ERRORS - - /* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const struct { - unsigned short packet_command; - const char * const text; -} packet_command_texts[] = { - { GPCMD_TEST_UNIT_READY, "Test Unit Ready" }, - { GPCMD_REQUEST_SENSE, "Request Sense" }, - { GPCMD_FORMAT_UNIT, "Format Unit" }, - { GPCMD_INQUIRY, "Inquiry" }, - { GPCMD_START_STOP_UNIT, "Start/Stop Unit" }, - { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" }, - { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" }, - { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" }, - { GPCMD_READ_10, "Read 10" }, - { GPCMD_WRITE_10, "Write 10" }, - { GPCMD_SEEK, "Seek" }, - { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" }, - { GPCMD_VERIFY_10, "Verify 10" }, - { GPCMD_FLUSH_CACHE, "Flush Cache" }, - { GPCMD_READ_SUBCHANNEL, "Read Subchannel" }, - { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" }, - { GPCMD_READ_HEADER, "Read Header" }, - { GPCMD_PLAY_AUDIO_10, "Play Audio 10" }, - { GPCMD_GET_CONFIGURATION, "Get Configuration" }, - { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" }, - { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" }, - { GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" }, - { GPCMD_PAUSE_RESUME, "Pause/Resume" }, - { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" }, - { GPCMD_READ_DISC_INFO, "Read Disc Info" }, - { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" }, - { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" }, - { GPCMD_SEND_OPC, "Send OPC" }, - { GPCMD_MODE_SELECT_10, "Mode Select 10" }, - { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" }, - { GPCMD_MODE_SENSE_10, "Mode Sense 10" }, - { GPCMD_CLOSE_TRACK, "Close Track" }, - { GPCMD_BLANK, "Blank" }, - { GPCMD_SEND_EVENT, "Send Event" }, - { GPCMD_SEND_KEY, "Send Key" }, - { GPCMD_REPORT_KEY, "Report Key" }, - { GPCMD_LOAD_UNLOAD, "Load/Unload" }, - { GPCMD_SET_READ_AHEAD, "Set Read-ahead" }, - { GPCMD_READ_12, "Read 12" }, - { GPCMD_GET_PERFORMANCE, "Get Performance" }, - { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" }, - { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" }, - { GPCMD_SET_STREAMING, "Set Streaming" }, - { GPCMD_READ_CD_MSF, "Read CD MSF" }, - { GPCMD_SCAN, "Scan" }, - { GPCMD_SET_SPEED, "Set Speed" }, - { GPCMD_PLAY_CD, "Play CD" }, - { GPCMD_MECHANISM_STATUS, "Mechanism Status" }, - { GPCMD_READ_CD, "Read CD" }, -}; - - - -/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const char * const sense_key_texts[16] = { - "No sense data", - "Recovered error", - "Not ready", - "Medium error", - "Hardware error", - "Illegal request", - "Unit attention", - "Data protect", - "(reserved)", - "(reserved)", - "(reserved)", - "Aborted command", - "(reserved)", - "(reserved)", - "Miscompare", - "(reserved)", -}; - -/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -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 - - -#endif /* _IDE_CD_H */ diff -Nru a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c --- a/drivers/ide/ide-cs.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,525 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - A driver for PCMCIA IDE/ATA disk cards - - ide_cs.c 1.26 1999/11/16 02:10:49 - - 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 - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#define PCMCIA_DEBUG 100 -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static const char *version = "ide_cs.c 1.26 1999/11/16 02:10:49 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -/* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xdeb8; -static int irq_list[4] = { -1 }; - -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); - -MODULE_LICENSE("GPL"); - - -/*====================================================================*/ - -static const char ide_major[] = { - IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, -#ifdef IDE4_MAJOR - IDE4_MAJOR, IDE5_MAJOR -#endif -}; - -typedef struct ide_info_t { - dev_link_t link; - int ndev; - dev_node_t node; - int hd; -} ide_info_t; - -static void ide_config(dev_link_t * link); -static void ide_release(u_long arg); -static int ide_event(event_t event, int priority, - event_callback_args_t * args); - -static dev_info_t dev_info = "ide-cs"; - -static dev_link_t *ide_attach(void); -static void ide_detach(dev_link_t *); - -static dev_link_t *dev_list = NULL; - -/*====================================================================*/ - -static void cs_error(client_handle_t handle, int func, int ret) -{ - error_info_t err = { func, ret }; - - DEBUG(0, "cs_error\n"); - - CardServices(ReportError, handle, &err); -} - -/*====================================================================== - - ide_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - -======================================================================*/ - -static dev_link_t *ide_attach(void) -{ - ide_info_t *info; - dev_link_t *link; - client_reg_t client_reg; - int i, ret; - - DEBUG(0, "ide_attach\n"); - - /* Create new ide device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return NULL; - memset(info, 0, sizeof(*info)); - link = &info->link; - link->priv = info; - - link->release.function = &ide_release; - link->release.data = (u_long) link; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ide_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - ide_detach(link); - return NULL; - } - - return link; -} /* ide_attach */ - -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - -static void ide_detach(dev_link_t * link) -{ - dev_link_t **linkp; - int ret; - - DEBUG(0, "ide_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) - break; - if (*linkp == NULL) - return; - - del_timer(&link->release); - if (link->state & DEV_CONFIG) - ide_release((u_long) link); - - if (link->handle) { - ret = CardServices(DeregisterClient, link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - /* Unlink, free device structure */ - *linkp = link->next; - kfree(link->priv); - -} /* ide_detach */ - -/*====================================================================== - - ide_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - ide device available to the system. - -======================================================================*/ - -#define CS_CHECK(fn, args...) \ -while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed - -#define CFG_CHECK(fn, args...) \ -if (CardServices(fn, args) != 0) goto next_entry - -int idecs_register(int arg1, int arg2, int irq) -{ - hw_regs_t hw; - - DEBUG(0, "idecs_register\n"); - - ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, - NULL); - hw.irq = irq; - hw.chipset = ide_pci; /* this enables IRQ sharing w/ PCI irqs */ - - return ide_register_hw(&hw); -} - -void ide_config(dev_link_t * link) -{ - client_handle_t handle = link->handle; - ide_info_t *info = link->priv; - tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd = -1, io_base, ctl_base; - - DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, handle, &tuple); - CS_CHECK(GetTupleData, handle, &tuple); - CS_CHECK(ParseTuple, handle, &tuple, &parse); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - - /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, handle, &conf); - link->conf.Vcc = conf.Vcc; - - pass = io_base = ctl_base = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, handle, &tuple); - while (1) { - CFG_CHECK(GetTupleData, handle, &tuple); - CFG_CHECK(ParseTuple, handle, &tuple, &parse); - - /* Check for matching Vcc, unless we're desperate */ - if (!pass) { - if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (conf.Vcc != - cfg->vcc.param[CISTPL_POWER_VNOM] / - 10000) - goto next_entry; - } else if (dflt.vcc. - present & (1 << CISTPL_POWER_VNOM)) { - if (conf.Vcc != - dflt.vcc.param[CISTPL_POWER_VNOM] / - 10000) - goto next_entry; - } - } - - if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; - else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = - (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->conf.ConfigIndex = cfg->index; - link->io.BasePort1 = io->win[0].base; - link->io.IOAddrLines = - io->flags & CISTPL_IO_LINES_MASK; - if (!(io->flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = - IO_DATA_PATH_WIDTH_8; - if (io->nwin == 2) { - link->io.NumPorts1 = 8; - link->io.BasePort2 = io->win[1].base; - link->io.NumPorts2 = 1; - CFG_CHECK(RequestIO, link->handle, - &link->io); - io_base = link->io.BasePort1; - ctl_base = link->io.BasePort2; - } else if ((io->nwin == 1) - && (io->win[0].len >= 16)) { - link->io.NumPorts1 = io->win[0].len; - link->io.NumPorts2 = 0; - CFG_CHECK(RequestIO, link->handle, - &link->io); - io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1 + 0x0e; - } else - goto next_entry; - /* If we've got this far, we're done */ - break; - } - - next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) - dflt = *cfg; - if (pass) { - CS_CHECK(GetNextTuple, handle, &tuple); - } else if (CardServices(GetNextTuple, handle, &tuple) != 0) { - CS_CHECK(GetFirstTuple, handle, &tuple); - memset(&dflt, 0, sizeof(dflt)); - pass++; - } - } - - CS_CHECK(RequestIRQ, handle, &link->irq); - CS_CHECK(RequestConfiguration, handle, &link->conf); - - /* deal with brain dead IDE resource management */ - release_region(link->io.BasePort1, link->io.NumPorts1); - if (link->io.NumPorts2) - release_region(link->io.BasePort2, link->io.NumPorts2); - - /* retry registration in case device is still spinning up */ - for (i = 0; i < 10; i++) { - if (ctl_base) - outb(0x02, ctl_base); /* Set nIEN = disable device interrupts */ - hd = idecs_register(io_base, ctl_base, - link->irq.AssignedIRQ); - if (hd >= 0) - break; - if (link->io.NumPorts1 == 0x20) { - if (ctl_base) - outb(0x02, ctl_base + 0x10); - hd = idecs_register(io_base + 0x10, - ctl_base + 0x10, - link->irq.AssignedIRQ); - if (hd >= 0) { - io_base += 0x10; - ctl_base += 0x10; - break; - } - } - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 10); - } - - if (hd < 0) { - printk(KERN_NOTICE - "ide_cs: ide_register() at 0x%03x & 0x%03x" - ", irq %u failed\n", io_base, ctl_base, - link->irq.AssignedIRQ); - goto failed; - } - - MOD_INC_USE_COUNT; - info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); - info->node.major = ide_major[hd]; - info->node.minor = 0; - info->hd = hd; - link->dev = &info->node; - printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc / 10, - link->conf.Vcc % 10, link->conf.Vpp1 / 10, - link->conf.Vpp1 % 10); - - link->state &= ~DEV_CONFIG_PENDING; - return; - - cs_failed: - cs_error(link->handle, last_fn, last_ret); - failed: - ide_release((u_long) link); - -} /* ide_config */ - -/*====================================================================== - - After a card is removed, ide_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - -void ide_release(u_long arg) -{ - dev_link_t *link = (dev_link_t *) arg; - ide_info_t *info = link->priv; - - DEBUG(0, "ide_release(0x%p)\n", link); - - if (info->ndev) { - ide_unregister(&ide_hwifs[info->hd]); - MOD_DEC_USE_COUNT; - } - - request_region(link->io.BasePort1, link->io.NumPorts1, "ide-cs"); - if (link->io.NumPorts2) - request_region(link->io.BasePort2, link->io.NumPorts2, - "ide-cs"); - - info->ndev = 0; - link->dev = NULL; - - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; - -} /* ide_release */ - -/*====================================================================== - - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the ide drivers from - talking to the ports. - -======================================================================*/ - -int ide_event(event_t event, int priority, event_callback_args_t * args) -{ - dev_link_t *link = args->client_data; - - DEBUG(1, "ide_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) - mod_timer(&link->release, jiffies + HZ / 20); - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ide_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - CardServices(ReleaseConfiguration, link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link)) - CardServices(RequestConfiguration, link->handle, - &link->conf); - break; - } - return 0; -} /* ide_event */ - -/*====================================================================*/ - -static int __init init_ide_cs(void) -{ - servinfo_t serv; - DEBUG(0, "%s\n", version); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "ide_cs: Card Services release " - "does not match!\n"); - return -1; - } - register_pccard_driver(&dev_info, &ide_attach, &ide_detach); - - return 0; -} - -static void __exit exit_ide_cs(void) -{ - DEBUG(0, "ide_cs: unloading\n"); - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) - ide_detach(dev_list); -} - -module_init(init_ide_cs); -module_exit(exit_ide_cs); diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1510 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 1994-1998,2002 Linus Torvalds and authors: - * - * Mark Lord - * Gadi Oxman - * Andre Hedrick - * Jens Axboe - * Marcin Dalecki - * - * This is the ATA disk device driver, as evolved from hd.c and ide.c. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for invalidate_bdev() */ -#include -#include - -#include -#include -#include -#include - -#ifdef CONFIG_BLK_DEV_PDC4030 -# define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030) -#else -# define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ -#endif - -/* - * for now, taskfile requests are special :/ - */ -static inline char *ide_map_rq(struct request *rq, unsigned long *flags) -{ - if (rq->bio) - return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq); - else - return rq->buffer + ((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE; -} - -static inline void ide_unmap_rq(struct request *rq, char *to, - unsigned long *flags) -{ - if (rq->bio) - bio_kunmap_irq(to, flags); -} - -/* - * Perform a sanity check on the claimed "lba_capacity" - * value for this drive (from its reported identification information). - * - * Returns: 1 if lba_capacity looks sensible - * 0 otherwise - * - * It is called only once for each drive. - */ -static int lba_capacity_is_ok(struct hd_driveid *id) -{ - unsigned long lba_sects, chs_sects, head, tail; - - if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { - printk("48-bit Drive: %llu \n", - (unsigned long long) id->lba_capacity_2); - return 1; - } - - /* - * The ATA spec tells large drives to return - * C/H/S = 16383/16/63 independent of their size. - * Some drives can be jumpered to use 15 heads instead of 16. - * Some drives can be jumpered to use 4092 cyls instead of 16383. - */ - if ((id->cyls == 16383 - || (id->cyls == 4092 && id->cur_cyls == 16383)) && - id->sectors == 63 && - (id->heads == 15 || id->heads == 16) && - id->lba_capacity >= 16383*63*id->heads) - return 1; - - lba_sects = id->lba_capacity; - chs_sects = id->cyls * id->heads * id->sectors; - - /* perform a rough sanity check on lba_sects: within 10% is OK */ - if ((lba_sects - chs_sects) < chs_sects/10) - return 1; - - /* some drives have the word order reversed */ - head = ((lba_sects >> 16) & 0xffff); - tail = (lba_sects & 0xffff); - lba_sects = (head | (tail << 16)); - if ((lba_sects - chs_sects) < chs_sects/10) { - id->lba_capacity = lba_sects; - return 1; /* lba_capacity is (now) good */ - } - - return 0; /* lba_capacity value may be bad */ -} - -/* - * Handler for command with PIO data-in phase. - */ -static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq) -{ - int ret; - - if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { - if (drive->status & (ERR_STAT | DRQ_STAT)) - return ata_error(drive, rq, __FUNCTION__); - - /* no data yet, so wait for another interrupt */ - ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL); - - ret = ATA_OP_CONTINUES; - } else { - // printk("Read: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors); - { - unsigned long flags; - char *buf; - - buf = ide_map_rq(rq, &flags); - ata_read(drive, buf, SECTOR_WORDS); - ide_unmap_rq(rq, buf, &flags); - } - - /* First segment of the request is complete. note that this does not - * necessarily mean that the entire request is done!! this is only true - * if ata_end_request() returns 0. - */ - rq->errors = 0; - --rq->current_nr_sectors; - - if (rq->current_nr_sectors <= 0) { - if (!ata_end_request(drive, rq, 1, 0)) { - // printk("Request Ended stat: %02x\n", drive->status); - - return ATA_OP_FINISHED; - } - } - - /* still data left to transfer */ - ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL); - - ret = ATA_OP_CONTINUES; - } - - return ret; -} - -/* - * Handler for command with PIO data-out phase. - */ -static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *rq) -{ - int ret; - - if (!ata_status(drive, DRIVE_READY, drive->bad_wstat)) - return ata_error(drive, rq, __FUNCTION__); - - if (!rq->current_nr_sectors && !ata_end_request(drive, rq, 1, 0)) { - ret = ATA_OP_FINISHED; - } else { - if ((rq->nr_sectors == 1) != (drive->status & DRQ_STAT)) { - unsigned long flags; - char *buf; - -// printk("write: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors); - buf = ide_map_rq(rq, &flags); - ata_write(drive, buf, SECTOR_WORDS); - ide_unmap_rq(rq, buf, &flags); - - rq->errors = 0; - --rq->current_nr_sectors; - } - ata_set_handler(drive, task_out_intr, WAIT_CMD, NULL); - - ret = ATA_OP_CONTINUES; - } - - return ret; -} - -/* - * Handler for command with Read Multiple - */ -static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request *rq) -{ - int ret; - - if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { - if (drive->status & (ERR_STAT | DRQ_STAT)) - return ata_error(drive, rq, __FUNCTION__); - - /* no data yet, so wait for another interrupt */ - ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); - - ret = ATA_OP_CONTINUES; - } else { - unsigned int msect; - - /* (ks/hs): Fixed Multi-Sector transfer */ - msect = drive->mult_count; - - do { - unsigned int nsect; - - nsect = rq->current_nr_sectors; - if (nsect > msect) - nsect = msect; - -#if 0 - printk("Multiread: %p, nsect: %d , rq->current_nr_sectors: %d\n", - buf, nsect, rq->current_nr_sectors); -#endif - { - unsigned long flags; - char *buf; - - buf = ide_map_rq(rq, &flags); - ata_read(drive, buf, nsect * SECTOR_WORDS); - ide_unmap_rq(rq, buf, &flags); - } - - rq->errors = 0; - rq->current_nr_sectors -= nsect; - - /* FIXME: this seems buggy */ - if (rq->current_nr_sectors <= 0) { - if (!ata_end_request(drive, rq, 1, 0)) - return ATA_OP_FINISHED; - } - msect -= nsect; - } while (msect); - - /* more data left */ - ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); - - ret = ATA_OP_CONTINUES; - } - - return ret; -} - -static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq) -{ - int ok; - int ret; - - /* - * FIXME: the drive->status checks here seem to be messy. - * - * (ks/hs): Handle last IRQ on multi-sector transfer, - * occurs after all data was sent in this chunk - */ - - ok = ata_status(drive, DATA_READY, BAD_R_STAT); - - if (!ok || !rq->nr_sectors) { - if (drive->status & (ERR_STAT | DRQ_STAT)) - return ata_error(drive, rq, __FUNCTION__); - } - if (!rq->nr_sectors) { - ata_end_request(drive, rq, 1, rq->hard_nr_sectors); - rq->bio = NULL; - ret = ATA_OP_FINISHED; - } else if (!ok) { - /* not ready yet, so wait for next IRQ */ - ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); - - ret = ATA_OP_CONTINUES; - } else { - int mcount = drive->mult_count; - - /* prepare for next IRQ */ - ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); - - do { - char *buf; - int nsect = rq->current_nr_sectors; - unsigned long flags; - - if (nsect > mcount) - nsect = mcount; - mcount -= nsect; - - buf = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq); - rq->sector += nsect; - rq->nr_sectors -= nsect; - rq->current_nr_sectors -= nsect; - - /* Do we move to the next bio after this? */ - if (!rq->current_nr_sectors) { - /* remember to fix this up /jens */ - struct bio *bio = rq->bio->bi_next; - - /* end early if we ran out of requests */ - if (!bio) { - mcount = 0; - } else { - rq->bio = bio; - rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9; - } - } - rq->errors = 0; /* FIXME: why? --bzolnier */ - - /* - * Ok, we're all setup for the interrupt re-entering us on the - * last transfer. - */ - ata_write(drive, buf, nsect * SECTOR_WORDS); - bio_kunmap_irq(buf, &flags); - } while (mcount); - - ret = ATA_OP_CONTINUES; - } - - return ret; -} - -/* - * Issue a READ or WRITE command to a disk, using LBA if supported, or CHS - * otherwise, to address sectors. It also takes care of issuing special - * DRIVE_CMDs. - */ -static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct request *rq, sector_t block) -{ - struct ata_taskfile args; - struct ata_taskfile *ar; - struct hd_driveid *id = drive->id; - u8 cmd; - - /* Special drive commands don't need any kind of setup. - */ - if (rq->flags & REQ_SPECIAL) { - ar = rq->special; - cmd = ar->cmd; - } else { - unsigned int sectors; - - /* FIXME: this check doesn't make sense */ - if (!(rq->flags & REQ_CMD)) { - blk_dump_rq_flags(rq, "idedisk_do_request - bad command"); - ata_end_request(drive, rq, 0, 0); - - return ATA_OP_FINISHED; - } - - if (IS_PDC4030_DRIVE) { - extern ide_startstop_t promise_do_request(struct ata_device *, struct request *, sector_t); - - return promise_do_request(drive, rq, block); - } - - /* - * start a tagged operation - */ - if (drive->using_tcq) { - int st = blk_queue_start_tag(&drive->queue, rq); - - if (ata_pending_commands(drive) > drive->max_depth) - drive->max_depth = ata_pending_commands(drive); - if (ata_pending_commands(drive) > drive->max_last_depth) - drive->max_last_depth = ata_pending_commands(drive); - - if (st) { - BUG_ON(!ata_pending_commands(drive)); - - return ATA_OP_CONTINUES; - } - } - ar = &args; - - memset(&args, 0, sizeof(args)); - sectors = rq->nr_sectors; - /* Dispatch depending up on the drive access method. */ - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { - /* LBA 48 bit */ - /* - * 268435455 == 137439 MB or 28bit limit - * 320173056 == 163929 MB or 48bit addressing - * 1073741822 == 549756 MB or 48bit addressing fake drive - */ - if (sectors == 65536) - sectors = 0; - - if (blk_rq_tagged(rq)) { - args.taskfile.feature = sectors; - args.hobfile.feature = sectors >> 8; - args.taskfile.sector_count = rq->tag << 3; - } else { - args.taskfile.sector_count = sectors; - args.hobfile.sector_count = sectors >> 8; - } - - args.taskfile.sector_number = block; /* low lba */ - args.taskfile.low_cylinder = (block >>= 8); /* mid lba */ - args.taskfile.high_cylinder = (block >>= 8); /* hi lba */ - args.taskfile.device_head = drive->select.all; - - args.hobfile.sector_number = (block >>= 8); /* low lba */ - args.hobfile.low_cylinder = (block >>= 8); /* mid lba */ - args.hobfile.high_cylinder = (block >>= 8); /* hi lba */ - } else if (drive->select.b.lba) { - /* LBA 28 bit */ - if (sectors == 256) - sectors = 0; - - if (blk_rq_tagged(rq)) { - args.taskfile.feature = sectors; - args.taskfile.sector_count = rq->tag << 3; - } else - args.taskfile.sector_count = sectors; - - args.taskfile.sector_number = block; - args.taskfile.low_cylinder = (block >>= 8); - args.taskfile.high_cylinder = (block >>= 8); - args.taskfile.device_head = ((block >> 8) & 0x0f); - } else { - /* CHS */ - unsigned int track = (block / drive->sect); - unsigned int sect = (block % drive->sect) + 1; - unsigned int head = (track % drive->head); - unsigned int cyl = (track / drive->head); - - if (sectors == 256) - sectors = 0; - - if (blk_rq_tagged(rq)) { - args.taskfile.feature = sectors; - args.taskfile.sector_count = rq->tag << 3; - } else - args.taskfile.sector_count = sectors; - - args.taskfile.sector_number = sect; - args.taskfile.low_cylinder = cyl; - args.taskfile.high_cylinder = (cyl>>8); - args.taskfile.device_head = head; - } - args.taskfile.device_head |= drive->select.all; - - /* - * Decode with physical ATA command to use and setup associated data. - */ - - if (rq_data_dir(rq) == READ) { - args.command_type = IDE_DRIVE_TASK_IN; - if (drive->addressing) { - if (drive->using_tcq) { - cmd = WIN_READDMA_QUEUED_EXT; - } else if (drive->using_dma) { - cmd = WIN_READDMA_EXT; - } else if (drive->mult_count) { - args.XXX_handler = task_mulin_intr; - cmd = WIN_MULTREAD_EXT; - } else { - args.XXX_handler = task_in_intr; - cmd = WIN_READ_EXT; - } - } else { - if (drive->using_tcq) { - cmd = WIN_READDMA_QUEUED; - } else if (drive->using_dma) { - cmd = WIN_READDMA; - } else if (drive->mult_count) { - args.XXX_handler = task_mulin_intr; - cmd = WIN_MULTREAD; - } else { - args.XXX_handler = task_in_intr; - cmd = WIN_READ; - } - } - } else { - args.command_type = IDE_DRIVE_TASK_RAW_WRITE; - if (drive->addressing) { - if (drive->using_tcq) { - cmd = WIN_WRITEDMA_QUEUED_EXT; - } else if (drive->using_dma) { - cmd = WIN_WRITEDMA_EXT; - } else if (drive->mult_count) { - args.XXX_handler = task_mulout_intr; - cmd = WIN_MULTWRITE_EXT; - } else { - args.XXX_handler = task_out_intr; - cmd = WIN_WRITE_EXT; - } - } else { - if (drive->using_tcq) { - cmd = WIN_WRITEDMA_QUEUED; - } else if (drive->using_dma) { - cmd = WIN_WRITEDMA; - } else if (drive->mult_count) { - args.XXX_handler = task_mulout_intr; - cmd = WIN_MULTWRITE; - } else { - args.XXX_handler = task_out_intr; - cmd = WIN_WRITE; - } - } - } -#ifdef DEBUG - printk("%s: %sing: ", drive->name, - (rq_data_dir(rq)==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); - printk("sectors=%ld, ", rq->nr_sectors); - printk("buffer=%p\n", rq->buffer); -#endif - ar->cmd = cmd; - rq->special = ar; - } - - /* (ks/hs): Moved to start, do not use for multiple out commands. - * FIXME: why not?! */ - if (!(cmd == CFA_WRITE_MULTI_WO_ERASE || - cmd == WIN_MULTWRITE || - cmd == WIN_MULTWRITE_EXT)) { - ata_irq_enable(drive, 1); - ata_mask(drive); - } - - if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) - ata_out_regfile(drive, &ar->hobfile); - - ata_out_regfile(drive, &ar->taskfile); - - OUT_BYTE((ar->taskfile.device_head & (drive->addressing ? 0xE0 : 0xEF)) | drive->select.all, - IDE_SELECT_REG); - - /* FIXME: this is actually distingushing between PIO and DMA requests. - */ - if (ar->XXX_handler) { - if (ar->command_type == IDE_DRIVE_TASK_IN || - ar->command_type == IDE_DRIVE_TASK_NO_DATA) { - - ata_set_handler(drive, ar->XXX_handler, WAIT_CMD, NULL); - OUT_BYTE(cmd, IDE_COMMAND_REG); - - return ATA_OP_CONTINUES; - } - - /* FIXME: Warning check for race between handlers for writing - * first block of data. However since we are well inside the - * boundaries of the seek, we should be okay. - */ - if (ar->command_type == IDE_DRIVE_TASK_RAW_WRITE) { - ide_startstop_t ret; - - OUT_BYTE(cmd, IDE_COMMAND_REG); - - ret = ata_status_poll(drive, DATA_READY, drive->bad_wstat, - WAIT_DRQ, rq); - if (ret != ATA_OP_READY) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, drive->mult_count ? "MULTWRITE" : "WRITE"); - - return ret; - } - - /* FIXME: This doesn't make the slightest sense. - * (ks/hs): Fixed Multi Write - */ - if (!(cmd == CFA_WRITE_MULTI_WO_ERASE || - cmd == WIN_MULTWRITE || - cmd == WIN_MULTWRITE_EXT)) { - unsigned long flags; - char *buf = ide_map_rq(rq, &flags); - - ata_set_handler(drive, ar->XXX_handler, WAIT_CMD, NULL); - - /* For Write_sectors we need to stuff the first sector */ - /* FIXME: what if !rq->current_nr_sectors --bzolnier */ - ata_write(drive, buf, SECTOR_WORDS); - - rq->current_nr_sectors--; - ide_unmap_rq(rq, buf, &flags); - - return ATA_OP_CONTINUES; - } else { - int i; - - /* Polling wait until the drive is ready. - * - * Stuff the first sector(s) by calling the - * handler driectly therafter. - * - * FIXME: Replace hard-coded 100, what about - * error handling? - * - * FIXME: Whatabout the IRE clearing and not clearing case?! - */ - - for (i = 0; i < 100; ++i) { - if (ata_status_irq(drive)) - break; - } - if (!ata_status_irq(drive)) { - /* We are compleatly missing an error - * return path here. - * FIXME: We have only one? -alat - */ - printk(KERN_ERR "DISASTER WAITING TO HAPPEN! Try to Stop it!\n"); - return ata_error(drive, rq, __FUNCTION__); - } - - /* will set handler for us */ - return ar->XXX_handler(drive, rq); - } - } - } else { - /* - * FIXME: This is a gross hack, need to unify tcq dma proc and - * regular dma proc. It should now be easier. - * - * FIXME: Handle the alternateives by a command type. - */ - - /* FIXME: ATA_OP_CONTINUES? --bzolnier */ - /* Not started a request - BUG() ot ATA_OP_FINISHED to avoid lockup ? - alat*/ - if (!drive->using_dma) - return ATA_OP_CONTINUES; - - /* for dma commands we don't set the handler */ - if (cmd == WIN_WRITEDMA || - cmd == WIN_WRITEDMA_EXT || - cmd == WIN_READDMA || - cmd == WIN_READDMA_EXT) - return udma_init(drive, rq); -#ifdef CONFIG_BLK_DEV_IDE_TCQ - else if (cmd == WIN_WRITEDMA_QUEUED || - cmd == WIN_WRITEDMA_QUEUED_EXT || - cmd == WIN_READDMA_QUEUED || - cmd == WIN_READDMA_QUEUED_EXT) - return udma_tcq_init(drive, rq); -#endif - else { - printk(KERN_ERR "%s: unknown command %x\n", - __FUNCTION__, cmd); - - return ATA_OP_FINISHED; - } - } - - /* not reached */ - return ATA_OP_CONTINUES; -} - -static int idedisk_open(struct inode *inode, struct file *__fp, struct ata_device *drive) -{ - MOD_INC_USE_COUNT; - if (drive->removable && drive->usage == 1) { - check_disk_change(inode->i_bdev); - - /* - * Ignore the return code from door_lock, since the open() has - * already succeeded once, and the door_lock is irrelevant at this - * time. - */ - if (drive->doorlocking) { - struct ata_taskfile args; - - memset(&args, 0, sizeof(args)); - args.cmd = WIN_DOORLOCK; - if (ide_raw_taskfile(drive, &args, NULL)) - drive->doorlocking = 0; - } - } - - return 0; -} - -static int flush_cache(struct ata_device *drive) -{ - struct ata_taskfile args; - - memset(&args, 0, sizeof(args)); - - if (drive->id->cfs_enable_2 & 0x2400) - args.cmd = WIN_FLUSH_CACHE_EXT; - else - args.cmd = WIN_FLUSH_CACHE; - - return ide_raw_taskfile(drive, &args, NULL); -} - -static void idedisk_release(struct inode *inode, struct file *filp, struct ata_device *drive) -{ - if (drive->removable && !drive->usage) { - /* XXX I don't think this is up to the lowlevel drivers.. --hch */ - invalidate_bdev(inode->i_bdev, 0); - - if (drive->doorlocking) { - struct ata_taskfile args; - - memset(&args, 0, sizeof(args)); - args.cmd = WIN_DOORUNLOCK; - if (ide_raw_taskfile(drive, &args, NULL)) - drive->doorlocking = 0; - } - } - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (flush_cache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); - MOD_DEC_USE_COUNT; -} - -static int idedisk_check_media_change(struct ata_device *drive) -{ - /* if removable, always assume it was changed */ - return drive->removable; -} - -static sector_t idedisk_capacity(struct ata_device *drive) -{ - return drive->capacity; -} - -/* - * This is tightly woven into the driver->special can not touch. - * DON'T do it again until a total personality rewrite is committed. - */ -static int set_multcount(struct ata_device *drive, int arg) -{ - struct ata_taskfile args; - - /* Setting multi mode count on this channel type is not supported/not - * handled. - */ - if (IS_PDC4030_DRIVE) - return -EIO; - - /* Hugh, we still didn't detect the devices capabilities. - */ - if (!drive->id) - return -EIO; - - if (arg > drive->id->max_multsect) - arg = drive->id->max_multsect; - - memset(&args, 0, sizeof(args)); - args.taskfile.sector_count = arg; - args.cmd = WIN_SETMULT; - if (!ide_raw_taskfile(drive, &args, NULL)) { - /* all went well track this setting as valid */ - drive->mult_count = arg; - - return 0; - } else - drive->mult_count = 0; /* reset */ - - return -EIO; -} - -static int set_nowerr(struct ata_device *drive, int arg) -{ - drive->nowerr = arg; - drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; - - return 0; -} - -static int write_cache(struct ata_device *drive, int arg) -{ - struct ata_taskfile args; - - if (!(drive->id->cfs_enable_2 & 0x3000)) - return 1; - - memset(&args, 0, sizeof(args)); - args.taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - args.cmd = WIN_SETFEATURES; - ide_raw_taskfile(drive, &args, NULL); - - drive->wcache = arg; - - return 0; -} - -static int idedisk_standby(struct ata_device *drive) -{ - struct ata_taskfile args; - - memset(&args, 0, sizeof(args)); - args.cmd = WIN_STANDBYNOW1; - return ide_raw_taskfile(drive, &args, NULL); -} - -static int set_acoustic(struct ata_device *drive, int arg) -{ - struct ata_taskfile args; - - memset(&args, 0, sizeof(args)); - args.taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM; - args.taskfile.sector_count = arg; - args.cmd = WIN_SETFEATURES; - ide_raw_taskfile(drive, &args, NULL); - - drive->acoustic = arg; - - return 0; -} - -#ifdef CONFIG_BLK_DEV_IDE_TCQ -static int set_using_tcq(struct ata_device *drive, int arg) -{ - if (!drive->driver) - return -EPERM; - - if (!drive->channel->udma_setup) - return -EPERM; - - if (arg == drive->queue_depth && drive->using_tcq) - return 0; - - /* - * set depth, but check also id for max supported depth - */ - drive->queue_depth = arg ? arg : 1; - if (drive->id) { - if (drive->queue_depth > drive->id->queue_depth + 1) - drive->queue_depth = drive->id->queue_depth + 1; - } - - if (udma_tcq_enable(drive, arg)) - return -EIO; - - return 0; -} -#endif - -static int probe_lba_addressing(struct ata_device *drive, int arg) -{ - drive->addressing = 0; - - if (!(drive->id->cfs_enable_2 & 0x0400)) - return -EIO; - - drive->addressing = arg; - return 0; -} - -static int set_lba_addressing(struct ata_device *drive, int arg) -{ - return (probe_lba_addressing(drive, arg)); -} - -static int idedisk_suspend(struct device *dev, u32 state, u32 level) -{ - struct ata_device *drive = dev->driver_data; - - /* I hope that every freeze operations from the upper levels have - * already been done... - */ - - BUG_ON(in_interrupt()); - - if (level != SUSPEND_SAVE_STATE) - return 0; - - /* wait until all commands are finished */ - /* FIXME: waiting for spinlocks should be done instead. */ - while (drive->channel->handler) - yield(); - - /* set the drive to standby */ - printk(KERN_INFO "suspending: %s ", drive->name); - if (ata_ops(drive)) { - if (ata_ops(drive)->standby) - ata_ops(drive)->standby(drive); - } - drive->blocked = 1; - - return 0; -} - -static int idedisk_resume(struct device *dev, u32 level) -{ - struct ata_device *drive = dev->driver_data; - - if (level != RESUME_RESTORE_STATE) - return 0; - if (!drive->blocked) - panic("ide: Resume but not suspended?\n"); - - drive->blocked = 0; - return 0; -} - - -/* This is just a hook for the overall driver tree. - */ - -static struct device_driver disk_devdrv = { - .lock = RW_LOCK_UNLOCKED, - .suspend = idedisk_suspend, - .resume = idedisk_resume, -}; - -/* - * Queries for true maximum capacity of the drive. - * Returns maximum LBA address (> 0) of the drive, 0 if failed. - */ -static unsigned long native_max_address(struct ata_device *drive) -{ - struct ata_taskfile args; - unsigned long addr = 0; - - if (!(drive->id->command_set_1 & 0x0400) && - !(drive->id->cfs_enable_2 & 0x0100)) - return addr; - - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(args)); - args.taskfile.device_head = 0x40; - args.cmd = WIN_READ_NATIVE_MAX; - ide_raw_taskfile(drive, &args, NULL); - - /* if OK, compute maximum address value */ - if (!(drive->status & ERR_STAT)) { - addr = ((args.taskfile.device_head & 0x0f) << 24) - | (args.taskfile.high_cylinder << 16) - | (args.taskfile.low_cylinder << 8) - | args.taskfile.sector_number; - } - - addr++; /* since the return value is (maxlba - 1), we add 1 */ - - return addr; -} - -static u64 native_max_address_ext(struct ata_device *drive) -{ - struct ata_taskfile args; - u64 addr = 0; - - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(args)); - args.taskfile.device_head = 0x40; - args.cmd = WIN_READ_NATIVE_MAX_EXT; - ide_raw_taskfile(drive, &args, NULL); - - /* if OK, compute maximum address value */ - if (!(drive->status & ERR_STAT)) { - u32 high = (args.hobfile.high_cylinder << 16) | - (args.hobfile.low_cylinder << 8) | - args.hobfile.sector_number; - u32 low = (args.taskfile.high_cylinder << 16) | - (args.taskfile.low_cylinder << 8) | - args.taskfile.sector_number; - addr = ((u64)high << 24) | low; - } - - addr++; /* since the return value is (maxlba - 1), we add 1 */ - - return addr; -} - -#ifdef CONFIG_IDEDISK_STROKE -/* - * Sets maximum virtual LBA address of the drive. - * Returns new maximum virtual LBA address (> 0) or 0 on failure. - */ -static sector_t set_max_address(struct ata_device *drive, sector_t addr_req) -{ - struct ata_taskfile args; - sector_t addr_set = 0; - - addr_req--; - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(args)); - - args.taskfile.sector_number = (addr_req >> 0); - args.taskfile.low_cylinder = (addr_req >> 8); - args.taskfile.high_cylinder = (addr_req >> 16); - - args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40; - args.cmd = WIN_SET_MAX; - ide_raw_taskfile(drive, &args, NULL); - - /* if OK, read new maximum address value */ - if (!(drive->status & ERR_STAT)) { - addr_set = ((args.taskfile.device_head & 0x0f) << 24) - | (args.taskfile.high_cylinder << 16) - | (args.taskfile.low_cylinder << 8) - | args.taskfile.sector_number; - } - addr_set++; - return addr_set; -} - -static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req) -{ - struct ata_taskfile args; - u64 addr_set = 0; - - addr_req--; - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(args)); - - args.taskfile.sector_number = (addr_req >> 0); - args.taskfile.low_cylinder = (addr_req >>= 8); - args.taskfile.high_cylinder = (addr_req >>= 8); - args.taskfile.device_head = 0x40; - args.cmd = WIN_SET_MAX_EXT; - - args.hobfile.sector_number = (addr_req >>= 8); - args.hobfile.low_cylinder = (addr_req >>= 8); - args.hobfile.high_cylinder = (addr_req >>= 8); - args.hobfile.device_head = 0x40; - - ide_raw_taskfile(drive, &args, NULL); - - /* if OK, compute maximum address value */ - if (!(drive->status & ERR_STAT)) { - u32 high = (args.hobfile.high_cylinder << 16) | - (args.hobfile.low_cylinder << 8) | - args.hobfile.sector_number; - u32 low = (args.taskfile.high_cylinder << 16) | - (args.taskfile.low_cylinder << 8) | - args.taskfile.sector_number; - addr_set = ((u64)high << 24) | low; - } - return addr_set; -} - -#endif - -static void idedisk_setup(struct ata_device *drive) -{ - int i; - - struct hd_driveid *id = drive->id; - sector_t capacity; - sector_t set_max; - int drvid = -1; - struct ata_channel *ch = drive->channel; - - if (id == NULL) - return; - - /* - * CompactFlash cards and their brethern look just like hard drives - * to us, but they are removable and don't have a doorlock mechanism. - */ - if (drive->removable && !drive_is_flashcard(drive)) { - /* Removable disks (eg. SYQUEST); ignore 'WD' drives. - */ - if (!strncmp(id->model, "WD", 2)) - drive->doorlocking = 1; - } - - for (i = 0; i < MAX_DRIVES; ++i) { - if (drive != &ch->drives[i]) - continue; - drvid = i; - ch->gd[i]->de_arr[0] = drive->de; - if (drive->removable) - ch->gd[i]->flags[0] |= GENHD_FL_REMOVABLE; - break; - } - - /* Register us within the device tree. - */ - if (drvid != -1) { - sprintf(drive->dev.bus_id, "sd@%x,%x", ch->unit, drvid); - strcpy(drive->dev.name, "ATA-Disk"); - drive->dev.driver = &disk_devdrv; - drive->dev.parent = &ch->dev; - drive->dev.driver_data = drive; - device_register(&drive->dev); - } - - /* Extract geometry if we did not already have one for the drive */ - if (!drive->cyl || !drive->head || !drive->sect) { - drive->cyl = drive->bios_cyl = id->cyls; - drive->head = drive->bios_head = id->heads; - drive->sect = drive->bios_sect = id->sectors; - } - - /* Handle logical geometry translation by the drive. */ - if ((id->field_valid & 1) && id->cur_cyls && - id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { - drive->cyl = id->cur_cyls; - drive->head = id->cur_heads; - drive->sect = id->cur_sectors; - } - - /* Use physical geometry if what we have still makes no sense. */ - if (drive->head > 16 && id->heads && id->heads <= 16) { - drive->cyl = id->cyls; - drive->head = id->heads; - drive->sect = id->sectors; - } - - /* Calculate drive capacity, and select LBA if possible. - * drive->id != NULL is spected - * - * To compute capacity, this uses either of - * - * 1. CHS value set by user (whatever user sets will be trusted) - * 2. LBA value from target drive (require new ATA feature) - * 3. LBA value from system BIOS (new one is OK, old one may break) - * 4. CHS value from system BIOS (traditional style) - * - * in above order (i.e., if value of higher priority is available, - * reset will be ignored). - */ - capacity = drive->cyl * drive->head * drive->sect; - set_max = native_max_address(drive); - - drive->capacity = 0; - drive->select.b.lba = 0; - - if (id->cfs_enable_2 & 0x0400) { - u64 set_max_ext; - u64 capacity_2; - capacity_2 = capacity; - capacity_2 = id->lba_capacity_2; - - drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect); - drive->head = drive->bios_head = 255; - drive->sect = drive->bios_sect = 63; - - drive->select.b.lba = 1; - set_max_ext = native_max_address_ext(drive); - if (set_max_ext > capacity_2) { -#ifdef CONFIG_IDEDISK_STROKE - set_max_ext = native_max_address_ext(drive); - set_max_ext = set_max_address_ext(drive, set_max_ext); - if (set_max_ext) { - drive->capacity = capacity_2 = set_max_ext; - drive->cyl = (unsigned int) set_max_ext / (drive->head * drive->sect); - drive->select.b.lba = 1; - drive->id->lba_capacity_2 = capacity_2; - } -#else - printk("%s: setmax_ext LBA %llu, native %llu\n", - drive->name, - (long long) set_max_ext, - (long long) capacity_2); -#endif - } - drive->bios_cyl = drive->cyl; - drive->capacity = capacity_2; - } else { - - /* - * Determine capacity, and use LBA if the drive properly - * supports it. - */ - - if ((id->capability & 2) && lba_capacity_is_ok(id)) { - capacity = id->lba_capacity; - drive->cyl = capacity / (drive->head * drive->sect); - drive->select.b.lba = 1; - } - - if (set_max > capacity) { -#ifdef CONFIG_IDEDISK_STROKE - set_max = native_max_address(drive); - set_max = set_max_address(drive, set_max); - if (set_max) { - drive->capacity = capacity = set_max; - drive->cyl = set_max / (drive->head * drive->sect); - drive->select.b.lba = 1; - drive->id->lba_capacity = capacity; - } -#else - printk("%s: setmax LBA %lu, native %lu\n", - drive->name, set_max, capacity); -#endif - } - - drive->capacity = capacity; - - if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { - drive->capacity = id->lba_capacity_2; - drive->head = 255; - drive->sect = 63; - drive->cyl = (unsigned long)(drive->capacity) / (drive->head * drive->sect); - } - } - - /* - * If possible, give fdisk access to more of the drive, - * by correcting bios_cyls: - */ - capacity = idedisk_capacity(drive); - if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) && - (!drive->forced_geom) && drive->bios_sect && drive->bios_head) - drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head; - printk(KERN_INFO " %s: %ld sectors", drive->name, capacity); - -#if 0 - /* Right now we avoid this calculation, since it can result in the - * usage of not supported compiler internal functions on 32 bit hosts. - * However since the calculation appears to be an interesting piece of - * number theory let's preserve the formula here. - */ - - /* Give size in megabytes (MB), not mebibytes (MiB). - * We compute the exact rounded value, avoiding overflow. - */ - printk(" (%ld MB)", (capacity - capacity/625 + 974)/1950); -#endif - - /* Only print cache size when it was specified. - */ - 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); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma) - udma_print(drive); -#endif - printk("\n"); - - drive->mult_count = 0; -#if 0 - if (id->max_multsect) { - - /* FIXME: reenable this again after making it to use - * the same code path as the ioctl stuff. - */ - -#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; - if (drive->mult_req) - drive->special_cmd |= ATA_SPECIAL_MMODE; -#else - /* original, pre IDE-NFG, per request of AC */ - drive->mult_req = INITIAL_MULT_COUNT; - if (drive->mult_req > id->max_multsect) - drive->mult_req = id->max_multsect; - if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) - drive->special_cmd |= ATA_SPECIAL_MMODE; -#endif - } -#endif - - /* FIXME: Nowadays there are many chipsets out there which *require* 32 - * bit IO. Those will most propably not work properly with drives not - * supporting this. But right now we don't do anything about this. We - * dont' even *warn* the user! - */ - - drive->channel->no_io_32bit = id->dword_io ? 1 : 0; - - if (drive->id->cfs_enable_2 & 0x3000) - write_cache(drive, (id->cfs_enable_2 & 0x3000)); - - probe_lba_addressing(drive, 1); -} - -static int idedisk_cleanup(struct ata_device *drive) -{ - int ret; - - if (!drive) - return 0; - - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) { - if (flush_cache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); - } - ret = ata_unregister_device(drive); - - /* FIXME: This is killing the kernel with BUG 185 at asm/spinlocks.h - * horribly. Check whatever we did REGISTER the device properly - * in front? - */ -#if 0 - put_device(&drive->device); -#endif - - return ret; -} - -static int idedisk_ioctl(struct ata_device *drive, - struct inode *inode, struct file *__fp, - unsigned int cmd, unsigned long arg) -{ - struct hd_driveid *id = drive->id; - - switch (cmd) { - case HDIO_GET_ADDRESS: { - unsigned long val = drive->addressing; - - if (put_user(val, (unsigned long *) arg)) - return -EFAULT; - return 0; - } - - case HDIO_SET_ADDRESS: { - int val; - - if (arg < 0 || arg > 2) - return -EINVAL; - - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - - val = set_lba_addressing(drive, arg); - spin_unlock_irq(drive->channel->lock); - - return val; - } - - case HDIO_GET_MULTCOUNT: { - unsigned long val = drive->mult_count & 0xFF; - - if (put_user(val, (unsigned long *) arg)) - return -EFAULT; - return 0; - } - - case HDIO_SET_MULTCOUNT: { - int val; - - if (!id) - return -EBUSY; - - if (arg < 0 || arg > (id ? id->max_multsect : 0)) - return -EINVAL; - - val = set_multcount(drive, arg); - - return val; - } - - case HDIO_GET_NOWERR: { - unsigned long val = drive->nowerr; - - if (put_user(val, (unsigned long *) arg)) - return -EFAULT; - - return 0; - } - - case HDIO_SET_NOWERR: { - int val; - - if (arg < 0 || arg > 1) - return -EINVAL; - - val = set_nowerr(drive, arg); - - return val; - } - - case HDIO_GET_WCACHE: { - unsigned long val = drive->wcache; - - if (put_user(val, (unsigned long *) arg)) - return -EFAULT; - - return 0; - } - - case HDIO_SET_WCACHE: { - int val; - - if (arg < 0 || arg > 1) - return -EINVAL; - - val = write_cache(drive, arg); - - return val; - } - - case HDIO_GET_ACOUSTIC: { - unsigned long val = drive->acoustic; - - if (put_user(val, (u8 *) arg)) - return -EFAULT; - return 0; - } - - case HDIO_SET_ACOUSTIC: { - int val; - - if (arg < 0 || arg > 254) - return -EINVAL; - - val = set_acoustic(drive, arg); - - return val; - } - -#ifdef CONFIG_BLK_DEV_IDE_TCQ - case HDIO_GET_QDMA: { - /* Foolup hdparm 0 means off 1 on -alat */ - /* FIXME: hdparm have only -Q do we need something like: - * hdparm -q 1/0 - TCQ on/off - * hdparm -Q 1-MAX - TCQ queue_depth ? - */ - u8 val = ( drive->using_tcq ? drive->queue_depth : 0 ); - - if (put_user(val, (u8 *) arg)) - return -EFAULT; - - return 0; - } - - case HDIO_SET_QDMA: { - int val; - - if (arg < 0 || arg > IDE_MAX_TAG) - return -EINVAL; - - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - - val = set_using_tcq(drive, arg); - spin_unlock_irq(drive->channel->lock); - - return val; - } -#endif - default: - return -EINVAL; - } -} - -static void idedisk_attach(struct ata_device *drive); - -/* - * Subdriver functions. - */ -static struct ata_operations idedisk_driver = { - .owner = THIS_MODULE, - .attach = idedisk_attach, - .cleanup = idedisk_cleanup, - .standby = idedisk_standby, - .do_request = idedisk_do_request, - .end_request = NULL, - .ioctl = idedisk_ioctl, - .open = idedisk_open, - .release = idedisk_release, - .check_media_change = idedisk_check_media_change, - .revalidate = NULL, /* use default method */ - .capacity = idedisk_capacity, -}; - -static void idedisk_attach(struct ata_device *drive) -{ - char *req; - struct ata_channel *channel; - struct gendisk *disk; - int unit; - - if (drive->type != ATA_DISK) - return; - - req = drive->driver_req; - if (req[0] != '\0' && strcmp(req, "ide-disk")) - return; - - if (ata_register_device(drive, &idedisk_driver)) { - printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name); - return; - } - - idedisk_setup(drive); - if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { - printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); - idedisk_cleanup(drive); - return; - } - - channel = drive->channel; - unit = drive - channel->drives; - disk = channel->gd[unit]; - disk->minor_shift = PARTN_BITS; - register_disk(disk, mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, disk->fops, drive->capacity); -} - -static void __exit idedisk_exit(void) -{ - unregister_ata_driver(&idedisk_driver); -} - -int __init idedisk_init(void) -{ - return ata_driver_module(&idedisk_driver); -} - -module_init(idedisk_init); -module_exit(idedisk_exit); - -MODULE_DESCRIPTION("ATA DISK Driver"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1815 +0,0 @@ -/* - * Copyright (C) 1996 - 1999 Gadi Oxman - * Copyright (C) 2000 - 2002 Paul Bristow - */ - -/* - * IDE ATAPI floppy driver. - * - * The driver currently doesn't have any fancy features, just the bare - * minimum read/write support. - * - * This driver supports the following IDE floppy drives: - * - * LS-120/240 SuperDisk - * Iomega Zip 100/250 - * Iomega PC Card Clik!/PocketZip - * - * Many thanks to Lode Leroy , 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 for pointing this out. - * Ver 0.9.sv Jan 6 01 Sam Varshavchik - * 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 - * - * 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 - */ - -#define IDEFLOPPY_VERSION "0.99" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* - * The following are used to debug the driver. - */ -#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... ) - - -/* - * Some drives require a longer irq timeout. - */ -#define IDEFLOPPY_WAIT_CMD (5 * WAIT_CMD) - -/* - * After each failed packet command we issue a request sense command - * and retry the packet command IDEFLOPPY_MAX_PC_RETRIES times. - */ -#define IDEFLOPPY_MAX_PC_RETRIES 3 - -/* - * 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) - -/* - * 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; - -#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. - */ -typedef struct { - struct ata_device *drive; - - struct atapi_packet_command *pc; /* Current packet command */ - struct atapi_packet_command *failed_pc; /* Last failed packet command */ - struct atapi_packet_command pc_stack[IDEFLOPPY_PC_STACK]; /* Packet command stack */ - int pc_stack_index; /* Next free packet command storage space */ - struct request rq_stack[IDEFLOPPY_PC_STACK]; - int rq_stack_index; /* We implement a circular array */ - - /* - * Last error information - */ - u8 sense_key, asc, ascq; - u8 ticks; /* delay this long before sending packet command */ - int progress_indication; - - /* - * Device information - */ - int blocks, block_size, bs_factor; /* Current format */ - idefloppy_capacity_descriptor_t capacity; /* Last format capacity */ - idefloppy_flexible_disk_page_t flexible_disk_page; /* Copy of the flexible disk page */ - int wp; /* Write protect */ - int srfp; /* Supports format progress report */ - unsigned long flags; /* Status/Action flags */ -} idefloppy_floppy_t; - -#define IDEFLOPPY_TICKS_DELAY 3 /* default delay for ZIP 100 */ - -/* - * 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 - -/* - * Defines for the mode sense command - */ -#define MODE_SENSE_CURRENT 0x00 -#define MODE_SENSE_CHANGEABLE 0x01 -#define MODE_SENSE_DEFAULT 0x02 -#define MODE_SENSE_SAVED 0x03 - -/* - * IOCTLs used in low-level formatting. - */ - -#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600 -#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601 -#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 -#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 - -/* - * Error codes which are returned in rq->errors to the higher part - * of the driver. - */ -#define IDEFLOPPY_ERROR_GENERAL 101 - -/* - * Pages of the SELECT SENSE / MODE SENSE packet commands. - */ -#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; - -/* - * idefloppy_end_request is used to finish servicing a request. - * - * For read/write requests, we will call ata_end_request to pass to the - * next buffer. - */ -static int idefloppy_end_request(struct ata_device *drive, struct request *rq, int uptodate) -{ - unsigned long flags; - struct ata_channel *ch = drive->channel; - idefloppy_floppy_t *floppy = drive->driver_data; - int error; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_end_request\n"); -#endif - - switch (uptodate) { - case 0: error = IDEFLOPPY_ERROR_GENERAL; break; - case 1: error = 0; break; - default: error = uptodate; - } - if (error) - floppy->failed_pc = NULL; - /* Why does this happen? */ - if (!rq) - return 0; - - if (!(rq->flags & REQ_SPECIAL)) { - ata_end_request(drive, rq, uptodate, 0); - return 0; - } - - spin_lock_irqsave(ch->lock, flags); - - rq->errors = error; - blkdev_dequeue_request(rq); - drive->rq = NULL; - end_that_request_last(rq); - - spin_unlock_irqrestore(ch->lock, flags); - - return 0; -} - -static void idefloppy_input_buffers(struct ata_device *drive, struct request *rq, - struct atapi_packet_command *pc, unsigned int bcount) -{ - struct bio *bio = rq->bio; - int count; - - while (bcount) { - if (pc->b_count == bio->bi_size) { - rq->sector += rq->current_nr_sectors; - rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_end_request(drive, rq, 1); - if ((bio = rq->bio) != NULL) - pc->b_count = 0; - } - if (bio == NULL) { - printk (KERN_ERR "%s: bio == NULL in %s, bcount == %d\n", drive->name, __FUNCTION__, bcount); - atapi_discard_data(drive, bcount); - return; - } - count = min_t(unsigned int, bio->bi_size - pc->b_count, bcount); - atapi_read(drive, bio_data(bio) + pc->b_count, count); - bcount -= count; pc->b_count += count; - } -} - -static void idefloppy_output_buffers(struct ata_device *drive, struct request *rq, - struct atapi_packet_command *pc, unsigned int bcount) -{ - struct bio *bio = rq->bio; - int count; - - while (bcount) { - if (!pc->b_count) { - rq->sector += rq->current_nr_sectors; - rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_end_request(drive, rq, 1); - if ((bio = rq->bio) != NULL) { - pc->b_data = bio_data(bio); - pc->b_count = bio->bi_size; - } - } - if (bio == NULL) { - printk (KERN_ERR "%s: bio == NULL in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount); - atapi_write_zeros (drive, bcount); - return; - } - count = min_t(unsigned int, pc->b_count, bcount); - atapi_write(drive, pc->b_data, count); - bcount -= count; pc->b_data += count; pc->b_count -= count; - } -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static void idefloppy_update_buffers(struct ata_device *drive, struct request *rq) -{ - struct bio *bio = rq->bio; - - while ((bio = rq->bio) != NULL) - idefloppy_end_request(drive, rq, 1); -} -#endif - -/* - * 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. - */ -static void idefloppy_queue_pc_head(struct ata_device *drive, - struct atapi_packet_command *pc, struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->flags = REQ_SPECIAL; - /* FIXME: --mdcki */ - rq->buffer = (char *) pc; - (void) ide_do_drive_cmd (drive, rq, ide_preempt); -} - -static struct atapi_packet_command *idefloppy_next_pc_storage(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - if (floppy->pc_stack_index==IDEFLOPPY_PC_STACK) - floppy->pc_stack_index=0; - return (&floppy->pc_stack[floppy->pc_stack_index++]); -} - -static struct request *idefloppy_next_rq_storage(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - if (floppy->rq_stack_index==IDEFLOPPY_PC_STACK) - floppy->rq_stack_index=0; - 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(struct ata_device *drive, atapi_request_sense_result_t *result) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq; - floppy->progress_indication= result->sksv ? - (unsigned short)get_unaligned((u16 *)(result->sk_specific)):0x10000; -#if IDEFLOPPY_DEBUG_LOG - if (floppy->failed_pc) - printk (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 - printk (KERN_INFO "ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq); -#endif -} - -static void idefloppy_request_sense_callback(struct ata_device *drive, struct request *rq) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_request_sense_callback\n"); -#endif - if (!floppy->pc->error) { - idefloppy_analyze_error(drive,(atapi_request_sense_result_t *) floppy->pc->buffer); - idefloppy_end_request(drive, rq, 1); - } else { - printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); - idefloppy_end_request(drive, rq, 0); - } -} - -/* - * General packet command callback function. - */ -static void idefloppy_pc_callback(struct ata_device *drive, struct request *rq) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n"); -#endif - - idefloppy_end_request(drive, rq, floppy->pc->error ? 0:1); -} - -static void idefloppy_create_request_sense_cmd(struct atapi_packet_command *pc) -{ - atapi_init_pc(pc); - pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD; - 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. - */ -static void idefloppy_retry_pc(struct ata_device *drive) -{ - struct atapi_packet_command *pc; - struct request *rq; - atapi_error_reg_t error; - - error.all = IN_BYTE(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. - */ -static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct request *rq) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - atapi_status_reg_t status; - atapi_bcount_reg_t bcount; - atapi_ireason_reg_t ireason; - struct atapi_packet_command *pc = floppy->pc; - unsigned int temp; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n"); -#endif - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { - if (udma_stop(drive)) { - set_bit (PC_DMA_ERROR, &pc->flags); - } else { - pc->actually_transferred=pc->request_transfer; - idefloppy_update_buffers(drive, rq); - } -# if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: DMA finished\n"); -# endif - } -#endif - - ata_status(drive, 0, 0); - status.all = drive->status; /* Clear the interrupt */ - - if (!status.b.drq) { /* No more interrupts */ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); -#endif /* IDEFLOPPY_DEBUG_LOG */ - clear_bit(PC_DMA_IN_PROGRESS, &pc->flags); - - local_irq_enable(); - - if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name); -#endif - rq->errors++; - if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-floppy: I/O error in request sense command\n"); - return ATA_OP_FINISHED; - } - idefloppy_retry_pc (drive); /* Retry operation */ - return ATA_OP_FINISHED; /* queued, but not started */ - } - pc->error = 0; - if (floppy->failed_pc == pc) - floppy->failed_pc=NULL; - pc->callback(drive, rq); /* Command finished - Call the callback function */ - return ATA_OP_FINISHED; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { - printk (KERN_ERR "ide-floppy: The floppy wants to issue more interrupts in DMA mode\n"); - udma_enable(drive, 0, 1); - - return ATA_OP_FINISHED; - } -#endif - - bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ - bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all=IN_BYTE (IDE_IREASON_REG); - - if (ireason.b.cod) { - printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n"); - - return ATA_OP_FINISHED; - } - if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ - printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read"); - printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write"); - - return ATA_OP_FINISHED; - } - if (!test_bit(PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ - temp = pc->actually_transferred + bcount.all; - 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"); - - atapi_discard_data (drive,bcount.all); - ata_set_handler(drive, idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); - - return ATA_OP_CONTINUES; - } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n"); -#endif - } - } - if (test_bit (PC_WRITING, &pc->flags)) { - if (pc->buffer != NULL) - atapi_write(drive,pc->current_position,bcount.all); /* Write the current buffer */ - else - idefloppy_output_buffers(drive, rq, pc, bcount.all); - } else { - if (pc->buffer != NULL) - atapi_read(drive,pc->current_position,bcount.all); /* Read the current buffer */ - else - idefloppy_input_buffers (drive, rq, pc, bcount.all); - } - pc->actually_transferred+=bcount.all; /* Update the current position */ - pc->current_position+=bcount.all; - - ata_set_handler(drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ - - return ATA_OP_CONTINUES; -} - -/* - * This is the original routine that did the packet transfer. - * It fails at high speeds on the Iomega ZIP drive, so there's a slower version - * for that drive below. The algorithm is chosen based on drive type - */ -static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct request *rq) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - atapi_ireason_reg_t ireason; - int ret; - - ret = ata_status_poll(drive, DRQ_STAT, BUSY_STAT, WAIT_READY, rq); - if (ret != ATA_OP_READY) { - printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); - - return ret; - } - - ireason.all = IN_BYTE(IDE_IREASON_REG); - - if (!ireason.b.cod || ireason.b.io) { - printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); - ret = ATA_OP_FINISHED; - } else { - ata_set_handler(drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ - atapi_write(drive, floppy->pc->c, 12); /* Send the actual packet */ - ret = ATA_OP_CONTINUES; - } - - return ret; -} - - -/* - * 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. - * - * 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 ide_startstop_t idefloppy_transfer_pc2(struct ata_device *drive, struct request *__rq, unsigned long *wait) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - atapi_write(drive, floppy->pc->c, 12); /* Send the actual packet */ - *wait = IDEFLOPPY_WAIT_CMD; /* Timeout for the packet command */ - - return ATA_OP_CONTINUES; -} - -static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct request *rq) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - atapi_ireason_reg_t ireason; - int ret; - - ret = ata_status_poll(drive, DRQ_STAT, BUSY_STAT, WAIT_READY, rq); - if (ret != ATA_OP_READY) { - printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); - - return ret; - } - - ireason.all = IN_BYTE(IDE_IREASON_REG); - - if (!ireason.b.cod || ireason.b.io) { - printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); - ret = ATA_OP_FINISHED; - } else { - - /* - * The following delay solves a problem with ATAPI Zip 100 drives where - * the Busy flag was apparently being deasserted before the unit was - * ready to receive data. This was happening on a 1200 MHz Athlon - * system. 10/26/01 25msec is too short, 40 and 50msec work well. - * idefloppy_pc_intr will not be actually used until after the packet - * is moved in about 50 msec. - */ - ata_set_handler(drive, - idefloppy_pc_intr, /* service routine for packet command */ - floppy->ticks, /* wait this long before "failing" */ - idefloppy_transfer_pc2); /* fail == transfer_pc2 */ - ret = ATA_OP_CONTINUES; - } - - return ret; -} - -/* - * Issue a packet command - */ -static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct request *rq, - struct atapi_packet_command *pc) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - atapi_bcount_reg_t bcount; - int dma_ok = 0; - ata_handler_t *pkt_xfer_routine; - -#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 - - if (floppy->failed_pc == NULL && pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD) - floppy->failed_pc=pc; - floppy->pc=pc; /* Set the current packet command */ - - 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)) { - ; - 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); - } - pc->error = IDEFLOPPY_ERROR_GENERAL; /* Giving up */ - } - floppy->failed_pc = NULL; - pc->callback(drive, rq); - return ATA_OP_FINISHED; - } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Retry number - %d\n",pc->retries); -#endif - - pc->retries++; - pc->actually_transferred=0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; - bcount.all = min(pc->request_transfer, 63 * 1024); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) - udma_enable(drive, 0, 1); - - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok = udma_init(drive, rq); -#endif - - ata_irq_enable(drive, 1); - OUT_BYTE(dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE(bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE(bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE(drive->select.all,IDE_SELECT_REG); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit(PC_DMA_IN_PROGRESS, &pc->flags); - udma_start(drive, rq); - } -#endif - - /* Can we transfer the packet when we get the interrupt or wait? */ - if (test_bit (IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) { - pkt_xfer_routine = &idefloppy_transfer_pc1; /* wait */ - } else { - pkt_xfer_routine = &idefloppy_transfer_pc; /* immediate */ - } - - if (test_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - ata_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ - - return ATA_OP_CONTINUES; - } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); - return pkt_xfer_routine(drive, rq); - } -} - -static void idefloppy_rw_callback(struct ata_device *drive, struct request *rq) -{ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - idefloppy_end_request(drive, rq, 1); - return; -} - -static void idefloppy_create_prevent_cmd(struct atapi_packet_command *pc, int prevent) -{ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: creating prevent removal command, prevent = %d\n", prevent); -#endif - - atapi_init_pc (pc); - pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD; - pc->c[4] = prevent; - pc->callback = idefloppy_pc_callback; -} - -static void idefloppy_create_read_capacity_cmd(struct atapi_packet_command *pc) -{ - atapi_init_pc(pc); - pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD; - pc->c[7] = 255; - pc->c[8] = 255; - pc->request_transfer = 255; - pc->callback = idefloppy_pc_callback; -} - -static void idefloppy_create_format_unit_cmd(struct atapi_packet_command *pc, - int b, int l, int flags) -{ - atapi_init_pc (pc); - pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD; - pc->c[1] = 0x17; - - memset(pc->buffer, 0, 12); - pc->buffer[1] = 0xA2; - /* Default format list header, byte 1: FOV/DCRT/IMM bits set */ - - if (flags & 1) /* Verify bit on... */ - 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); - pc->callback = idefloppy_pc_callback; -} - -/* - * A mode sense command is used to "sense" floppy parameters. - */ -static void idefloppy_create_mode_sense_cmd(struct atapi_packet_command *pc, u8 page_code, u8 type) -{ - unsigned short length = sizeof(idefloppy_mode_parameter_header_t); - - atapi_init_pc(pc); - pc->c[0] = IDEFLOPPY_MODE_SENSE_CMD; - 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 in create_mode_sense_cmd\n"); - } - put_unaligned(htons(length), (unsigned short *) &pc->c[7]); - pc->request_transfer = length; - pc->callback = idefloppy_pc_callback; -} - -static void idefloppy_create_start_stop_cmd(struct atapi_packet_command *pc, int start) -{ - atapi_init_pc(pc); - pc->c[0] = IDEFLOPPY_START_STOP_CMD; - pc->c[4] = start; - pc->callback = idefloppy_pc_callback; -} - -static void idefloppy_create_test_unit_ready_cmd(struct atapi_packet_command *pc) -{ - atapi_init_pc(pc); - pc->c[0] = IDEFLOPPY_TEST_UNIT_READY_CMD; - pc->callback = idefloppy_pc_callback; -} - -static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy, - struct atapi_packet_command *pc, struct request *rq, sector_t sector) -{ - int block = sector / floppy->bs_factor; - int blocks = rq->nr_sectors / floppy->bs_factor; - int cmd = rq_data_dir(rq); - -#if IDEFLOPPY_DEBUG_LOG - printk ("create_rw1%d_cmd: block == %d, blocks == %d\n", - 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks); -#endif - - atapi_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->callback = idefloppy_rw_callback; - pc->b_data = rq->buffer; - pc->b_count = cmd == READ ? 0 : rq->bio->bi_size; - if (rq->flags & REQ_RW) - set_bit(PC_WRITING, &pc->flags); - pc->buffer = NULL; - pc->request_transfer = pc->buffer_size = blocks * floppy->block_size; - set_bit(PC_DMA_RECOMMENDED, &pc->flags); -} - -/* - * This is our request handling function. - */ -static ide_startstop_t idefloppy_do_request(struct ata_device *drive, struct request *rq, sector_t block) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct atapi_packet_command *pc; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "rq_status: %d, rq_dev: %u, flags: %lx, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->flags,rq->errors); - printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); -#endif - - if (rq->errors >= ERROR_MAX) { - if (floppy->failed_pc != NULL) - 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); - else - printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); - - idefloppy_end_request(drive, rq, 0); - - return ATA_OP_FINISHED; - } - if (rq->flags & REQ_CMD) { - if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) { - printk ("%s: unsupported r/w request size\n", drive->name); - - idefloppy_end_request(drive, rq, 0); - - return ATA_OP_FINISHED; - } - pc = idefloppy_next_pc_storage(drive); - idefloppy_create_rw_cmd (floppy, pc, rq, block); - } else if (rq->flags & REQ_SPECIAL) { - /* FIXME: --mdcki */ - pc = (struct atapi_packet_command *) rq->buffer; - } else { - blk_dump_rq_flags(rq, "ide-floppy: unsupported command in queue"); - - idefloppy_end_request(drive, rq, 0); - - return ATA_OP_FINISHED; - } - - return idefloppy_issue_pc(drive, rq, pc); -} - -/* - * idefloppy_queue_pc_tail adds a special packet command request to the - * tail of the request queue, and waits for it to be serviced. - */ -static int idefloppy_queue_pc_tail(struct ata_device *drive, struct atapi_packet_command *pc) -{ - struct request rq; - - memset(&rq, 0, sizeof(rq)); - /* FIXME: --mdcki */ - rq.buffer = (char *) pc; - rq.flags = REQ_SPECIAL; - - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - -/* - * Look at the flexible disk page parameters. We will ignore the CHS - * capacity parameters and use the LBA parameters instead. - */ -static int idefloppy_get_flexible_disk_page(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct atapi_packet_command pc; - idefloppy_mode_parameter_header_t *header; - idefloppy_flexible_disk_page_t *page; - int capacity, lba_capacity; - - 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"); - return 1; - } - header = (idefloppy_mode_parameter_header_t *) pc.buffer; - floppy->wp = header->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))) - 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; - 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; - } - return 0; -} - -static int idefloppy_get_capability_page(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct atapi_packet_command 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)) { - return 1; - } - - header = (idefloppy_mode_parameter_header_t *) pc.buffer; - page= (idefloppy_capabilities_page_t *)(header+1); - floppy->srfp=page->srfp; - return (0); -} - -/* - * Determine if a media is present in the floppy drive, and if so, - * its LBA capacity. - */ -static int idefloppy_get_capacity(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct atapi_packet_command pc; - idefloppy_capacity_header_t *header; - idefloppy_capacity_descriptor_t *descriptor; - int i, descriptors, rc = 1, blocks, length; - - drive->bios_cyl = 0; - drive->bios_head = drive->bios_sect = 0; - floppy->blocks = floppy->bs_factor = 0; - drive->part[0].nr_sects = 0; - - idefloppy_create_read_capacity_cmd (&pc); - if (idefloppy_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n"); - return 1; - } - header = (idefloppy_capacity_header_t *) pc.buffer; - descriptors = header->length / sizeof (idefloppy_capacity_descriptor_t); - descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); - - for (i = 0; i < descriptors; i++, descriptor++) { - blocks = descriptor->blocks = ntohl (descriptor->blocks); - length = descriptor->length = ntohs (descriptor->length); - - if (!i) - { - switch (descriptor->dc) { - case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) - break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */ - case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */ - if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) - printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length); - floppy->capacity = *descriptor; - 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 512 bytes block size not fully supported\n", drive->name); - rc = 0; - } - break; - case CAPACITY_NO_CARTRIDGE: - /* This is a KERN_ERR so it appears on screen for the user to see */ - printk (KERN_ERR "%s: No disk in drive\n", drive->name); - break; - case CAPACITY_INVALID: - printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name); - break; - } - } - if (!i) { - IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc); - } - IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); - } - - /* Clik! disk does not support get_flexible_disk_page */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) - { - (void) idefloppy_get_flexible_disk_page (drive); - } - - drive->part[0].nr_sects = 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(struct ata_device *drive, - struct inode *inode, - struct file *file, - int *arg) /* Cheater */ -{ - struct atapi_packet_command pc; - idefloppy_capacity_header_t *header; - idefloppy_capacity_descriptor_t *descriptor; - int i, descriptors, blocks, length; - int u_array_size; - int u_index; - int *argp; - - if (get_user(u_array_size, arg)) - return (-EFAULT); - - if (u_array_size <= 0) - return (-EINVAL); - - idefloppy_create_read_capacity_cmd(&pc); - if (idefloppy_queue_pc_tail(drive, &pc)) { - printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n"); - return (-EIO); - } - header = (idefloppy_capacity_header_t *) pc.buffer; - descriptors = header->length / - sizeof (idefloppy_capacity_descriptor_t); - descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); - - u_index=0; - argp=arg+1; - - /* - ** We always skip the first capacity descriptor. That's the - ** current capacity. We are interested in the remaining descriptors, - ** the formattable capacities. - */ - - for (i=0; i= 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); - - if (put_user(blocks, argp)) - return (-EFAULT); - ++argp; - - if (put_user(length, argp)) - return (-EFAULT); - ++argp; - - ++u_index; - } - - if (put_user(u_index, arg)) - return (-EFAULT); - return (0); -} - -/* -** 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(struct ata_device *drive, - struct inode *inode, - struct file *file, - int *arg) -{ - int blocks; - int length; - int flags; - struct atapi_packet_command pc; - - if (get_user(blocks, arg) - || get_user(length, arg+1) - || get_user(flags, arg+2)) - { - return (-EFAULT); - } - - (void) idefloppy_get_capability_page (drive); /* Get the SFRP bit */ - 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 progresss -** 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(struct ata_device *drive, - struct inode *inode, - struct file *file, - int *arg) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct atapi_packet_command pc; - int progress_indication=0x10000; - - if (floppy->srfp) - { - idefloppy_create_request_sense_cmd(&pc); - if (idefloppy_queue_pc_tail (drive, &pc)) - { - return (-EIO); - } - - if (floppy->sense_key == 2 && floppy->asc == 4 && - floppy->ascq == 4) - { - progress_indication=floppy->progress_indication; - } - /* Else assume format_unit has finished, and we're - * at 0x10000 - */ - } - else - { - atapi_status_reg_t status; - unsigned long flags; - - local_irq_save(flags); - ata_status(drive, 0, 0); - status.all = drive->status; - local_irq_restore(flags); - - progress_indication= !status.b.dsc ? 0:0x10000; - } - if (put_user(progress_indication, arg)) - return (-EFAULT); - - return (0); -} - -/* - * Our special ide-floppy ioctl's. - * - * Currently there aren't any ioctl's. - */ -static int idefloppy_ioctl(struct ata_device *drive, struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct atapi_packet_command pc; - idefloppy_floppy_t *floppy = drive->driver_data; - int prevent = (arg) ? 1 : 0; - - switch (cmd) { - case CDROMEJECT: - prevent = 0; - /* fall through */ - case CDROM_LOCKDOOR: - if (drive->usage > 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; - case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: - return (0); - case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: - return (idefloppy_get_format_capacities(drive, inode, file, - (int *)arg)); - case IDEFLOPPY_IOCTL_FORMAT_START: - - if (!(file->f_mode & 2)) - return (-EPERM); - - { - idefloppy_floppy_t *floppy = drive->driver_data; - - if (drive->usage > 1) - { - /* Don't format if someone is using the disk */ - - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, - &floppy->flags); - return -EBUSY; - } - else - { - int rc; - - set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, - &floppy->flags); - - rc=idefloppy_begin_format(drive, inode, - file, - (int *)arg); - - if (rc) - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, - &floppy->flags); - return (rc); - - /* - ** 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. - */ - } - } - case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: - return (idefloppy_get_format_progress(drive, inode, file, - (int *)arg)); - } - return -EIO; -} - -/* - * Our open/release functions - */ -static int idefloppy_open(struct inode *inode, struct file *filp, struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct atapi_packet_command pc; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_open\n"); -#endif - - MOD_INC_USE_COUNT; - if (drive->usage == 1) { - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); - /* Just in case */ - - idefloppy_create_test_unit_ready_cmd(&pc); - if (idefloppy_queue_pc_tail(drive, &pc)) { - idefloppy_create_start_stop_cmd (&pc, 1); - (void) idefloppy_queue_pc_tail (drive, &pc); - } - - if (idefloppy_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 - */ - ) { - drive->usage--; - MOD_DEC_USE_COUNT; - return -EIO; - } - - if (floppy->wp && (filp->f_mode & 2)) { - drive->usage--; - MOD_DEC_USE_COUNT; - return -EROFS; - } - set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); - /* IOMEGA Clik! drives do not support lock/unlock commands */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { - 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)) - { - drive->usage--; - MOD_DEC_USE_COUNT; - return -EBUSY; - } - return 0; -} - -static void idefloppy_release(struct inode *inode, struct file *filp, struct ata_device *drive) -{ - struct atapi_packet_command pc; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_release\n"); -#endif - - if (!drive->usage) { - idefloppy_floppy_t *floppy = drive->driver_data; - - /* IOMEGA Clik! drives do not support lock/unlock commands */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { - idefloppy_create_prevent_cmd (&pc, 0); - (void) idefloppy_queue_pc_tail (drive, &pc); - } - - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); - } - MOD_DEC_USE_COUNT; -} - -/* - * Check media change. Use a simple algorithm for now. - */ -static int idefloppy_check_media_change(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); -} - -/* - * Return the current floppy capacity to ide.c. - */ -static unsigned long idefloppy_capacity(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - unsigned long capacity = floppy->blocks * floppy->bs_factor; - - return capacity; -} - -/* - * idefloppy_identify_device checks if we can support a drive, - * based on the ATAPI IDENTIFY command results. - */ -static int idefloppy_identify_device(struct ata_device *drive,struct hd_driveid *id) -{ - struct atapi_id_gcw gcw; -#if IDEFLOPPY_DEBUG_INFO - unsigned short mask,i; - char buffer[80]; -#endif /* IDEFLOPPY_DEBUG_INFO */ - - *((unsigned short *) &gcw) = id->config; - -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if ((gcw.device_type == 5) && !strstr(id->model, "CD-ROM") - && strstr(id->model, "ZIP")) - 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"); - else if (gcw.device_type != 0) - printk (KERN_ERR "ide-floppy: Device type is not set to floppy\n"); - 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); - } else if (gcw.packet_size != 0) { - printk (KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n"); - } else - return 1; - return 0; -} - -/* - * Driver initialization. - */ -static void idefloppy_setup(struct ata_device *drive, idefloppy_floppy_t *floppy) -{ - struct atapi_id_gcw gcw; - int i; - - *((unsigned short *) &gcw) = drive->id->config; - drive->driver_data = floppy; - drive->ready_stat = 0; - memset (floppy, 0, sizeof (idefloppy_floppy_t)); - floppy->drive = drive; - floppy->pc = floppy->pc_stack; - if (gcw.drq_type == 1) - set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); - /* - * We used to check revisions here. At this point however - * I'm giving up. Just assume they are all broken, its easier. - * - * The actual reason for the workarounds was likely - * a driver bug after all rather than a firmware bug, - * and the workaround below used to hide it. It should - * be fixed as of version 1.9, but to be on the safe side - * we'll leave the limitation below for the 2.2.x tree. - */ - - if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0) - 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. - */ - if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) { - blk_queue_max_sectors(&drive->queue, 64); - set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags); - } - - (void) idefloppy_get_capacity (drive); - - for (i = 0; i < MAX_DRIVES; ++i) { - struct ata_channel *hwif = drive->channel; - - if (drive != &hwif->drives[i]) continue; - hwif->gd[i]->de_arr[0] = drive->de; - if (drive->removable) - hwif->gd[i]->flags[0] |= GENHD_FL_REMOVABLE; - break; - } -} - -static int idefloppy_cleanup(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - if (ata_unregister_device(drive)) - return 1; - drive->driver_data = NULL; - kfree(floppy); - return 0; -} - -static void idefloppy_attach(struct ata_device *drive); - -/* - * IDE subdriver functions, registered with ide.c - */ -static struct ata_operations idefloppy_driver = { - .owner = THIS_MODULE, - .attach = idefloppy_attach, - .cleanup = idefloppy_cleanup, - .standby = NULL, - .do_request = idefloppy_do_request, - .end_request = idefloppy_end_request, - .ioctl = idefloppy_ioctl, - .open = idefloppy_open, - .release = idefloppy_release, - .check_media_change = idefloppy_check_media_change, - .revalidate = NULL, /* use default method */ - .capacity = idefloppy_capacity, -}; - -static void idefloppy_attach(struct ata_device *drive) -{ - idefloppy_floppy_t *floppy; - char *req; - struct ata_channel *channel; - struct gendisk *disk; - int unit; - - if (drive->type != ATA_FLOPPY) - return; - - req = drive->driver_req; - if (req[0] != '\0' && strcmp(req, "ide-floppy")) - return; - - if (!idefloppy_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-floppy: %s: not supported by this version of driver\n", - drive->name); - return; - } - - if (drive->scsi) { - printk(KERN_INFO "ide-floppy: passing drive %s to ide-scsi emulation.\n", - drive->name); - return; - } - if (!(floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL))) { - printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", - drive->name); - return; - } - if (ata_register_device(drive, &idefloppy_driver)) { - printk(KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (floppy); - return; - } - - idefloppy_setup(drive, floppy); - - channel = drive->channel; - unit = drive - channel->drives; - disk = channel->gd[unit]; - disk->minor_shift = PARTN_BITS; - register_disk(disk, mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, disk->fops, - idefloppy_capacity(drive)); -} - -MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); - -static void __exit idefloppy_exit(void) -{ - unregister_ata_driver(&idefloppy_driver); -} - -int __init idefloppy_init(void) -{ - return ata_driver_module(&idefloppy_driver); -} - -module_init(idefloppy_init); -module_exit(idefloppy_exit); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/ide-m8xx.c b/drivers/ide/ide-m8xx.c --- a/drivers/ide/ide-m8xx.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,861 +0,0 @@ -/* - * linux/drivers/ide/ide-m8xx.c - * - * Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de - * Modified for direct IDE interface - * by Thomas Lange, thomas@corelatus.com - * Modified for direct IDE interface on 8xx without using the PCMCIA - * controller - * by Steven.Scholz@imc-berlin.de - * Moved out of arch/ppc/kernel/m8xx_setup.c, other minor cleanups - * by Mathew Locke - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "timing.h" - -static int identify (volatile unsigned char *p); -static void print_fixed (volatile unsigned char *p); -static void print_funcid (int func); -static int check_ide_device (unsigned long base); - -static int ide_interrupt_ack(struct ata_channel *); -static void m8xx_ide_tuneproc(struct ata_device *drive, u8 pio); - -typedef struct ide_ioport_desc { - unsigned long base_off; /* Offset to PCMCIA memory */ - ide_ioreg_t reg_off[IDE_NR_PORTS]; /* controller register offsets */ - int irq; /* IRQ */ -} ide_ioport_desc_t; - -ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = { -#ifdef IDE0_BASE_OFFSET - { IDE0_BASE_OFFSET, - { - IDE0_DATA_REG_OFFSET, - IDE0_ERROR_REG_OFFSET, - IDE0_NSECTOR_REG_OFFSET, - IDE0_SECTOR_REG_OFFSET, - IDE0_LCYL_REG_OFFSET, - IDE0_HCYL_REG_OFFSET, - IDE0_SELECT_REG_OFFSET, - IDE0_STATUS_REG_OFFSET, - IDE0_CONTROL_REG_OFFSET, - IDE0_IRQ_REG_OFFSET, - }, - IDE0_INTERRUPT, - }, -#ifdef IDE1_BASE_OFFSET - { IDE1_BASE_OFFSET, - { - IDE1_DATA_REG_OFFSET, - IDE1_ERROR_REG_OFFSET, - IDE1_NSECTOR_REG_OFFSET, - IDE1_SECTOR_REG_OFFSET, - IDE1_LCYL_REG_OFFSET, - IDE1_HCYL_REG_OFFSET, - IDE1_SELECT_REG_OFFSET, - IDE1_STATUS_REG_OFFSET, - IDE1_CONTROL_REG_OFFSET, - IDE1_IRQ_REG_OFFSET, - }, - IDE1_INTERRUPT, - }, -#endif /* IDE1_BASE_OFFSET */ -#endif /* IDE0_BASE_OFFSET */ -}; - -typedef struct ide_pio_timings_s { - int setup_time; /* Address setup (ns) minimum */ - int active_time; /* Active pulse (ns) minimum */ - int cycle_time; /* Cycle time (ns) minimum = (setup + active + recovery) */ -} ide_pio_timings_t; - -ide_pio_timings_t ide_pio_clocks[6]; -int hold_time[6] = {30, 20, 15, 10, 10, 10 }; /* PIO Mode 5 with IORDY (nonstandard) */ - -/* - * Warning: only 1 (ONE) PCMCIA slot supported here, - * which must be correctly initialized by the firmware (PPCBoot). - */ -static int _slot_ = -1; /* will be read from PCMCIA registers */ - -/* Make clock cycles and always round up */ -#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U ) - - - -/* - * IDE stuff. - */ -static int -m8xx_ide_default_irq(ide_ioreg_t base) -{ -#ifdef CONFIG_BLK_DEV_MPC8xx_IDE - if (base >= MAX_HWIFS) - return 0; - - printk("[%d] m8xx_ide_default_irq %d\n",__LINE__,ioport_dsc[base].irq); - - return (ioport_dsc[base].irq); -#else - return 9; -#endif -} - -static ide_ioreg_t -m8xx_ide_default_io_base(int index) -{ - return index; -} - -#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4)) -#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4)) - -/* - * The TQM850L hardware has two pins swapped! Grrrrgh! - */ -#ifdef CONFIG_TQM850L -#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXOE -#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXRESET -#else -#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXRESET -#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXOE -#endif - -#if defined(CONFIG_BLK_DEV_MPC8xx_IDE) && defined(CONFIG_IDE_8xx_PCCARD) -#define PCMCIA_SCHLVL IDE0_INTERRUPT /* Status Change Interrupt Level */ -static int pcmcia_schlvl = PCMCIA_SCHLVL; -#endif - -/* - * See include/linux/ide.h for definition of hw_regs_t (p, base) - */ - -/* - * m8xx_ide_init_hwif_ports for a direct IDE interface _using_ - */ -#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) -static void -m8xx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, - ide_ioreg_t ctrl_port, int *irq) -{ - ide_ioreg_t *p = hw->io_ports; - int i; - - typedef struct { - ulong br; - ulong or; - } pcmcia_win_t; - volatile pcmcia_win_t *win; - volatile pcmconf8xx_t *pcmp; - - uint *pgcrx; - u32 pcmcia_phy_base; - u32 pcmcia_phy_end; - static unsigned long pcmcia_base = 0; - unsigned long base; - - *p = 0; - if (irq) - *irq = 0; - - pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia)); - - if (!pcmcia_base) { - /* - * Read out PCMCIA registers. Since the reset values - * are undefined, we sure hope that they have been - * set up by firmware - */ - - /* Scan all registers for valid settings */ - pcmcia_phy_base = 0xFFFFFFFF; - pcmcia_phy_end = 0; - /* br0 is start of brX and orX regs */ - win = (pcmcia_win_t *) \ - (&(((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0)); - for (i = 0; i < 8; i++) { - if (win->or & 1) { /* This bank is marked as valid */ - if (win->br < pcmcia_phy_base) { - pcmcia_phy_base = win->br; - } - if ((win->br + PCMCIA_MEM_SIZE) > pcmcia_phy_end) { - pcmcia_phy_end = win->br + PCMCIA_MEM_SIZE; - } - /* Check which slot that has been defined */ - _slot_ = (win->or >> 2) & 1; - - } /* Valid bank */ - win++; - } /* for */ - - printk ("PCMCIA slot %c: phys mem %08x...%08x (size %08x)\n", - 'A' + _slot_, - pcmcia_phy_base, pcmcia_phy_end, - pcmcia_phy_end - pcmcia_phy_base); - - pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base, - pcmcia_phy_end-pcmcia_phy_base); - -#ifdef DEBUG - printk ("PCMCIA virt base: %08lx\n", pcmcia_base); -#endif - /* Compute clock cycles for PIO timings */ - for (i=0; i<6; ++i) { - bd_t *binfo = (bd_t *)__res; - struct ata_timing *t; - - t = ata_timing_data(i + XFER_PIO_0); - - hold_time[i] = - PCMCIA_MK_CLKS (hold_time[i], - binfo->bi_busfreq); - ide_pio_clocks[i].setup_time = - PCMCIA_MK_CLKS (t->setup, binfo->bi_busfreq); - ide_pio_clocks[i].active_time = - PCMCIA_MK_CLKS (t->active, binfo->bi_busfreq); - ide_pio_clocks[i].cycle_time = - PCMCIA_MK_CLKS (t->cycle, binfo->bi_busfreq); -#if 0 - printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n", - i, - ide_pio_clocks[i].setup_time, - ide_pio_clocks[i].active_time, - ide_pio_clocks[i].hold_time, - ide_pio_clocks[i].cycle_time, - t->setup, t->active, hold_time[i], t->cycle); -#endif - } - } - - if (data_port >= MAX_HWIFS) - return; - - if (_slot_ == -1) { - printk ("PCMCIA slot has not been defined! Using A as default\n"); - _slot_ = 0; - } - -#ifdef CONFIG_IDE_8xx_PCCARD - -#ifdef DEBUG - printk ("PIPR = 0x%08X slot %c ==> mask = 0x%X\n", - pcmp->pcmc_pipr, - 'A' + _slot_, - M8XX_PCMCIA_CD1(_slot_) | M8XX_PCMCIA_CD2(_slot_) ); -#endif /* DEBUG */ - - if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) { - printk ("No card in slot %c: PIPR=%08x\n", - 'A' + _slot_, (u32) pcmp->pcmc_pipr); - return; /* No card in slot */ - } - - check_ide_device (pcmcia_base); - -#endif /* CONFIG_IDE_8xx_PCCARD */ - - base = pcmcia_base + ioport_dsc[data_port].base_off; -#ifdef DEBUG - printk ("base: %08x + %08x = %08x\n", - pcmcia_base, ioport_dsc[data_port].base_off, base); -#endif - - for (i = 0; i < IDE_NR_PORTS; ++i) { -#ifdef DEBUG - printk ("port[%d]: %08x + %08x = %08x\n", - i, - base, - ioport_dsc[data_port].reg_off[i], - i, base + ioport_dsc[data_port].reg_off[i]); -#endif - *p++ = base + ioport_dsc[data_port].reg_off[i]; - } - - if (irq) { -#ifdef CONFIG_IDE_8xx_PCCARD - unsigned int reg; - - *irq = ioport_dsc[data_port].irq; - if (_slot_) - pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb; - else - pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcra; - - reg = *pgcrx; - reg |= mk_int_int_mask (pcmcia_schlvl) << 24; - reg |= mk_int_int_mask (pcmcia_schlvl) << 16; - *pgcrx = reg; -#else /* direct connected IDE drive, i.e. external IRQ, not the PCMCIA irq */ - *irq = ioport_dsc[data_port].irq; -#endif /* CONFIG_IDE_8xx_PCCARD */ - } - - /* register routine to tune PIO mode */ - ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc; - - hw->ack_intr = ide_interrupt_ack; - /* Enable Harddisk Interrupt, - * and make it edge sensitive - */ - /* (11-18) Set edge detect for irq, no wakeup from low power mode */ - ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |= - (0x80000000 >> ioport_dsc[data_port].irq); - -#ifdef CONFIG_IDE_8xx_PCCARD - /* Make sure we dont get garbage irq */ - ((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pscr = 0xFFFF; - - /* Enable falling edge irq */ - pcmp->pcmc_per = 0x100000 >> (16 * _slot_); -#endif /* CONFIG_IDE_8xx_PCCARD */ -} /* m8xx_ide_init_hwif_ports() using 8xx internal PCMCIA interface */ -#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */ - -/* - * m8xx_ide_init_hwif_ports for a direct IDE interface _not_ using - * MPC8xx's internal PCMCIA interface - */ -#if defined(CONFIG_IDE_EXT_DIRECT) -void m8xx_ide_init_hwif_ports (hw_regs_t *hw, - ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) -{ - ide_ioreg_t *p = hw->io_ports; - int i; - - u32 ide_phy_base; - u32 ide_phy_end; - static unsigned long ide_base = 0; - unsigned long base; - - *p = 0; - if (irq) - *irq = 0; - - if (!ide_base) { - - /* TODO: - * - add code to read ORx, BRx - */ - ide_phy_base = CFG_ATA_BASE_ADDR; - ide_phy_end = CFG_ATA_BASE_ADDR + 0x200; - - printk ("IDE phys mem : %08x...%08x (size %08x)\n", - ide_phy_base, ide_phy_end, - ide_phy_end - ide_phy_base); - - ide_base=(unsigned long)ioremap(ide_phy_base, - ide_phy_end-ide_phy_base); - -#ifdef DEBUG - printk ("IDE virt base: %08lx\n", ide_base); -#endif - } - - if (data_port >= MAX_HWIFS) - return; - - base = ide_base + ioport_dsc[data_port].base_off; -#ifdef DEBUG - printk ("base: %08x + %08x = %08x\n", - ide_base, ioport_dsc[data_port].base_off, base); -#endif - - for (i = 0; i < IDE_NR_PORTS; ++i) { -#ifdef DEBUG - printk ("port[%d]: %08x + %08x = %08x\n", - i, - base, - ioport_dsc[data_port].reg_off[i], - i, base + ioport_dsc[data_port].reg_off[i]); -#endif - *p++ = base + ioport_dsc[data_port].reg_off[i]; - } - - if (irq) { - /* direct connected IDE drive, i.e. external IRQ */ - *irq = ioport_dsc[data_port].irq; - } - - /* register routine to tune PIO mode */ - ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc; - - hw->ack_intr = ide_interrupt_ack; - /* Enable Harddisk Interrupt, - * and make it edge sensitive - */ - /* (11-18) Set edge detect for irq, no wakeup from low power mode */ - ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |= - (0x80000000 >> ioport_dsc[data_port].irq); -} /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */ - -#endif - - -/* -------------------------------------------------------------------- */ - - -/* PCMCIA Timing */ -#ifndef PCMCIA_SHT -#define PCMCIA_SHT(t) ((t & 0x0F)<<16) /* Strobe Hold Time */ -#define PCMCIA_SST(t) ((t & 0x0F)<<12) /* Strobe Setup Time */ -#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length */ -#endif - - -/* Calculate PIO timings */ -static void -m8xx_ide_tuneproc(struct ata_device *drive, u8 pio) -{ -#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) - volatile pcmconf8xx_t *pcmp; - ulong timing, mask, reg; -#endif - - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; - -#if 1 - printk("%s[%d] %s: best PIO mode: %d\n", - __FILE__,__LINE__,__FUNCTION__, pio); -#endif - -#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) - pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia)); - - mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF)); - - timing = PCMCIA_SHT(hold_time[pio] ) - | PCMCIA_SST(ide_pio_clocks[pio].setup_time ) - | PCMCIA_SL (ide_pio_clocks[pio].active_time) - ; - -#if 1 - printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing); -#endif - if ((reg = pcmp->pcmc_por0 & mask) != 0) - pcmp->pcmc_por0 = reg | timing; - - if ((reg = pcmp->pcmc_por1 & mask) != 0) - pcmp->pcmc_por1 = reg | timing; - - if ((reg = pcmp->pcmc_por2 & mask) != 0) - pcmp->pcmc_por2 = reg | timing; - - if ((reg = pcmp->pcmc_por3 & mask) != 0) - pcmp->pcmc_por3 = reg | timing; - - if ((reg = pcmp->pcmc_por4 & mask) != 0) - pcmp->pcmc_por4 = reg | timing; - - if ((reg = pcmp->pcmc_por5 & mask) != 0) - pcmp->pcmc_por5 = reg | timing; - - if ((reg = pcmp->pcmc_por6 & mask) != 0) - pcmp->pcmc_por6 = reg | timing; - - if ((reg = pcmp->pcmc_por7 & mask) != 0) - pcmp->pcmc_por7 = reg | timing; - -#elif defined(CONFIG_IDE_EXT_DIRECT) - - printk("%s[%d] %s: not implemented yet!\n", - __FILE__,__LINE__,__FUNCTION__); -#endif -} - -static int ide_interrupt_ack(struct ata_channel *ch) -{ -#ifdef CONFIG_IDE_8xx_PCCARD - u_int pscr, pipr; - -#if (PCMCIA_SOCKETS_NO == 2) - u_int _slot_; -#endif - - /* get interrupt sources */ - - pscr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr; - pipr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr; - - /* - * report only if both card detect signals are the same - * not too nice done, - * we depend on that CD2 is the bit to the left of CD1... - */ - - if(_slot_==-1){ - printk("PCMCIA slot has not been defined! Using A as default\n"); - _slot_=0; - } - - if(((pipr & M8XX_PCMCIA_CD2(_slot_)) >> 1) ^ - (pipr & M8XX_PCMCIA_CD1(_slot_)) ) { - printk ("card detect interrupt\n"); - } - /* clear the interrupt sources */ - ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr; - -#else - /* - * Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the - * MPC8xx's PCMCIA controller, so there is nothing to be done here - * for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT. - * The interrupt is handled somewhere else. -- Steven - */ -#endif - - return 0; -} - -/* - * CIS Tupel codes - */ -#define CISTPL_NULL 0x00 -#define CISTPL_DEVICE 0x01 -#define CISTPL_LONGLINK_CB 0x02 -#define CISTPL_INDIRECT 0x03 -#define CISTPL_CONFIG_CB 0x04 -#define CISTPL_CFTABLE_ENTRY_CB 0x05 -#define CISTPL_LONGLINK_MFC 0x06 -#define CISTPL_BAR 0x07 -#define CISTPL_PWR_MGMNT 0x08 -#define CISTPL_EXTDEVICE 0x09 -#define CISTPL_CHECKSUM 0x10 -#define CISTPL_LONGLINK_A 0x11 -#define CISTPL_LONGLINK_C 0x12 -#define CISTPL_LINKTARGET 0x13 -#define CISTPL_NO_LINK 0x14 -#define CISTPL_VERS_1 0x15 -#define CISTPL_ALTSTR 0x16 -#define CISTPL_DEVICE_A 0x17 -#define CISTPL_JEDEC_C 0x18 -#define CISTPL_JEDEC_A 0x19 -#define CISTPL_CONFIG 0x1a -#define CISTPL_CFTABLE_ENTRY 0x1b -#define CISTPL_DEVICE_OC 0x1c -#define CISTPL_DEVICE_OA 0x1d -#define CISTPL_DEVICE_GEO 0x1e -#define CISTPL_DEVICE_GEO_A 0x1f -#define CISTPL_MANFID 0x20 -#define CISTPL_FUNCID 0x21 -#define CISTPL_FUNCE 0x22 -#define CISTPL_SWIL 0x23 -#define CISTPL_END 0xff - -/* - * CIS Function ID codes - */ -#define CISTPL_FUNCID_MULTI 0x00 -#define CISTPL_FUNCID_MEMORY 0x01 -#define CISTPL_FUNCID_SERIAL 0x02 -#define CISTPL_FUNCID_PARALLEL 0x03 -#define CISTPL_FUNCID_FIXED 0x04 -#define CISTPL_FUNCID_VIDEO 0x05 -#define CISTPL_FUNCID_NETWORK 0x06 -#define CISTPL_FUNCID_AIMS 0x07 -#define CISTPL_FUNCID_SCSI 0x08 - -/* - * Fixed Disk FUNCE codes - */ -#define CISTPL_IDE_INTERFACE 0x01 - -#define CISTPL_FUNCE_IDE_IFACE 0x01 -#define CISTPL_FUNCE_IDE_MASTER 0x02 -#define CISTPL_FUNCE_IDE_SLAVE 0x03 - -/* First feature byte */ -#define CISTPL_IDE_SILICON 0x04 -#define CISTPL_IDE_UNIQUE 0x08 -#define CISTPL_IDE_DUAL 0x10 - -/* Second feature byte */ -#define CISTPL_IDE_HAS_SLEEP 0x01 -#define CISTPL_IDE_HAS_STANDBY 0x02 -#define CISTPL_IDE_HAS_IDLE 0x04 -#define CISTPL_IDE_LOW_POWER 0x08 -#define CISTPL_IDE_REG_INHIBIT 0x10 -#define CISTPL_IDE_HAS_INDEX 0x20 -#define CISTPL_IDE_IOIS16 0x40 - - -/* -------------------------------------------------------------------- */ - - -#define MAX_TUPEL_SZ 512 -#define MAX_FEATURES 4 - -static int check_ide_device (unsigned long base) -{ - volatile unsigned char *ident = NULL; - volatile unsigned char *feature_p[MAX_FEATURES]; - volatile unsigned char *p, *start; - int n_features = 0; - unsigned char func_id = ~0; - unsigned char code, len; - unsigned short config_base = 0; - int found = 0; - int i; - -#ifdef DEBUG - printk ("PCMCIA MEM: %08lX\n", base); -#endif - start = p = (volatile unsigned char *) base; - - while ((p - start) < MAX_TUPEL_SZ) { - - code = *p; p += 2; - - if (code == 0xFF) { /* End of chain */ - break; - } - - len = *p; p += 2; -#ifdef DEBUG_PCMCIA - { volatile unsigned char *q = p; - printk ("\nTuple code %02x length %d\n\tData:", - code, len); - - for (i = 0; i < len; ++i) { - printk (" %02x", *q); - q+= 2; - } - } -#endif - switch (code) { - case CISTPL_VERS_1: - ident = p + 4; - break; - case CISTPL_FUNCID: - func_id = *p; - break; - case CISTPL_FUNCE: - if (n_features < MAX_FEATURES) - feature_p[n_features++] = p; - break; - case CISTPL_CONFIG: - config_base = (*(p+6) << 8) + (*(p+4)); - default: - break; - } - p += 2 * len; - } - - found = identify (ident); - - if (func_id != ((unsigned char)~0)) { - print_funcid (func_id); - - if (func_id == CISTPL_FUNCID_FIXED) - found = 1; - else - return (1); /* no disk drive */ - } - - for (i=0; i id_str) { - if (*t == ' ') - *t = '\0'; - else - break; - } - printk ("Card ID: %s\n", id_str); - - for (card=known_cards; *card; ++card) { - if (strcmp(*card, id_str) == 0) { /* found! */ - return (1); - } - } - - return (0); /* don't know */ -} - -void m8xx_ide_init(void) -{ - ppc_ide_md.default_irq = m8xx_ide_default_irq; - ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; -} diff -Nru a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c --- a/drivers/ide/ide-pci.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,783 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * Copyright (C) 1998-2000 Andre Hedrick - * 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 ATA host chip chanells interfaces present in a system. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "pcihost.h" - -/* - * This is the list of registered PCI chipset driver data structures. - */ -static struct ata_pci_device *ata_pci_device_list; /* = NULL */ - -/* - * This function supplies the data necessary to detect the particular chipset. - * - * Please note that we don't copy data over. We are just linking it in to the - * list. - */ -void ata_register_chipset(struct ata_pci_device *d) -{ - struct ata_pci_device *tmp; - - if (!d) - return; - - d->next = NULL; - - if (!ata_pci_device_list) { - ata_pci_device_list = d; - - return; - } - - tmp = ata_pci_device_list; - while (tmp->next) { - tmp = tmp->next; - } - - tmp->next = d; -} - -/* - * Match a PCI IDE port against an entry in ide_hwifs[], - * based on io_base port if possible. - */ -static struct ata_channel __init *lookup_channel(unsigned long io_base, int bootable, const char *name) -{ - int h; - struct ata_channel *ch; - - /* - * Look for a channel with matching io_base default value. If chipset is - * "ide_unknown", then claim that channel slot. Otherwise, some other - * chipset has already claimed it.. :( - */ - for (h = 0; h < MAX_HWIFS; ++h) { - ch = &ide_hwifs[h]; - if (ch->io_ports[IDE_DATA_OFFSET] == io_base) { - if (ch->chipset == ide_generic) - return ch; /* a perfect match */ - if (ch->chipset == ide_unknown) - return ch; /* match */ - printk(KERN_INFO "%s: port 0x%04lx already claimed by %s\n", - name, io_base, ch->name); - return NULL; /* already claimed */ - } - } - - /* - * Okay, there is no ch matching our io_base, so we'll just claim an - * unassigned slot. - * - * Give preference to claiming other slots before claiming ide0/ide1, - * just in case there's another interface yet-to-be-scanned which uses - * ports 1f0/170 (the ide0/ide1 defaults). - * - * Unless there is a bootable card that does not use the standard ports - * 1f0/170 (the ide0/ide1 defaults). The (bootable) flag. - */ - - if (bootable == ON_BOARD) { - for (h = 0; h < MAX_HWIFS; ++h) { - ch = &ide_hwifs[h]; - if (ch->chipset == ide_unknown) - return ch; /* pick an unused entry */ - } - } else { - for (h = 2; h < MAX_HWIFS; ++h) { - ch = &ide_hwifs[h]; - if (ch->chipset == ide_unknown) - return ch; /* pick an unused entry */ - } - } - for (h = 0; h < 2; ++h) { - ch = &ide_hwifs[h]; - if (ch->chipset == ide_unknown) - return ch; /* pick an unused entry */ - } - printk(KERN_INFO "%s: too many ATA interfaces.\n", name); - - return NULL; -} - -static int __init setup_pci_baseregs(struct pci_dev *dev, const char *name) -{ - u8 reg; - u8 progif = 0; - - /* - * Place both IDE interfaces into PCI "native" mode: - */ - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { - if ((progif & 0xa) != 0xa) { - printk("%s: device not capable of full native PCI mode\n", name); - return 1; - } - printk("%s: placing both ports into native PCI mode\n", name); - pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { - printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif); - return 1; - } - } - /* - * Setup base registers for IDE command/control spaces for each interface: - */ - for (reg = 0; reg < 4; reg++) { - struct resource *res = dev->resource + reg; - if ((res->flags & IORESOURCE_IO) == 0) - continue; - if (!res->start) { - printk("%s: Missing I/O address #%d\n", name, reg); - return 1; - } - } - return 0; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * Setup DMA transfers on the channel. - */ -static void __init setup_channel_dma(struct pci_dev *dev, - struct ata_pci_device* d, - int autodma, - struct ata_channel *ch) -{ - unsigned long dma_base; - - if (d->flags & ATA_F_NOADMA) - autodma = 0; - - if (autodma) - ch->autodma = 1; - - if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80)))) - return; - - /* - * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: - */ - dma_base = pci_resource_start(dev, 4); - if (dma_base) { - /* PDC20246, PDC20262, HPT343, & HPT366 */ - if ((ch->unit == ATA_PRIMARY) && d->extra) { - request_region(dma_base + 16, d->extra, dev->name); - ch->dma_extra = d->extra; - } - - /* If we are on the second channel, the dma base address will - * be one entry away from the primary interface. - */ - if (ch->unit == ATA_SECONDARY) - dma_base += 8; - - if (d->flags & ATA_F_SIMPLEX) { - outb(inb(dma_base + 2) & 0x60, dma_base + 2); - if (inb(dma_base + 2) & 0x80) - printk(KERN_INFO "%s: simplex device: DMA forced\n", dev->name); - } else { - /* If the device claims "simplex" DMA, this means only - * one of the two interfaces can be trusted with DMA at - * any point in time. So we should enable DMA only on - * one of the two interfaces. - */ - if ((inb(dma_base + 2) & 0x80)) { - if ((!ch->drives[0].present && !ch->drives[1].present) || - ch->unit == ATA_SECONDARY) { - printk(KERN_INFO "%s: simplex device: DMA disabled\n", dev->name); - dma_base = 0; - } - } - } - } else { - printk(KERN_INFO "%s: %s Bus-Master DMA was disabled by BIOS\n", - ch->name, dev->name); - - return; - } - - /* The function below will check itself whatever there is something to - * be done or not. We don't have therefore to care whatever it was - * already enabled by the primary channel run. - */ - pci_set_master(dev); - if (d->init_dma) - d->init_dma(ch, dma_base); - else - ata_init_dma(ch, dma_base); -} -#endif - -/* - * Setup a particular port on an ATA host controller. - * - * This gets called once for the master and for the slave interface. - */ -static int __init setup_host_channel(struct pci_dev *dev, - struct ata_pci_device *d, - int port, - u8 class_rev, - int pciirq, - int autodma) -{ - unsigned long base = 0; - unsigned long ctl = 0; - ide_pci_enablebit_t *e = &(d->enablebits[port]); - struct ata_channel *ch; - - u8 tmp; - if (port == ATA_SECONDARY) { - - /* If this is a Promise FakeRaid controller, the 2nd controller - * will be marked as disabled while it is actually there and - * enabled by the bios for raid purposes. Skip the normal "is - * it enabled" test for those. - */ - if (d->flags & ATA_F_PHACK) - goto controller_ok; - } - - /* Test whatever the port is enabled. - */ - if (e->reg) { - if (pci_read_config_byte(dev, e->reg, &tmp)) - return 0; /* error! */ - if ((tmp & e->mask) != e->val) - return 0; - } - - /* Nothing to be done for the second port. - */ - if (port == ATA_SECONDARY) { - if ((d->flags & ATA_F_HPTHACK) && (class_rev < 0x03)) - return 0; - } -controller_ok: - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { - ctl = dev->resource[(2 * port) + 1].start; - base = dev->resource[2 * port].start; - if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || !(base & PCI_BASE_ADDRESS_IO_MASK)) { - printk(KERN_WARNING "%s: error: IO reported as MEM by BIOS!\n", dev->name); - /* try it with the default values */ - ctl = 0; - base = 0; - } - } - if (ctl && !base) { - printk(KERN_WARNING "%s: error: missing MEM base info from BIOS!\n", dev->name); - /* we will still try to get along with the default */ - } - if (base && !ctl) { - printk(KERN_WARNING "%s: error: missing IO base info from BIOS!\n", dev->name); - /* we will still try to get along with the default */ - } - - /* Fill in the default values: */ - if (!ctl) - ctl = port ? 0x374 : 0x3f4; - if (!base) - base = port ? 0x170 : 0x1f0; - - if ((ch = lookup_channel(base, d->bootable, dev->name)) == NULL) - return -ENOMEM; /* no room */ - - if (ch->io_ports[IDE_DATA_OFFSET] != base) { - ide_init_hwif_ports(&ch->hw, base, (ctl | 2), NULL); - memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports)); - ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET]; - } - - ch->chipset = ide_pci; - ch->pci_dev = dev; - ch->unit = port; - if (!ch->irq) - ch->irq = pciirq; - - /* Serialize the interfaces if requested by configuration information. - */ - if (d->flags & ATA_F_SER) - ch->serialized = 1; - - /* Cross wired IRQ lines on UMC chips and no DMA transfers.*/ - if (d->flags & ATA_F_FIXIRQ) { - ch->irq = port ? 15 : 14; - goto no_dma; - } - if (d->flags & ATA_F_NODMA) - goto no_dma; - - if (ch->udma_four) - printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name); - - -#ifdef CONFIG_BLK_DEV_IDEDMA - /* - * Setup DMA transfers on the channel. - */ - setup_channel_dma(dev, d, autodma, ch); -#endif -no_dma: - /* Call chipset-specific routine for each enabled channel. */ - if (d->init_channel) - d->init_channel(ch); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if ((d->flags & ATA_F_NOADMA) || noautodma) - ch->autodma = 0; -#endif - - return 0; -} - -/* - * Looks at the primary/secondary channels on a PCI IDE device and, if they are - * enabled, prepares the IDE driver for use with them. This generic code works - * for most PCI chipsets. - * - * One thing that is not standardized is the location of the primary/secondary - * interface "enable/disable" bits. For chipsets that we "know" about, this - * information is in the struct ata_pci_device struct; for all other chipsets, - * we just assume both interfaces are enabled. - */ -static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device *d) -{ - int autodma = 0; - int pciirq = 0; - unsigned short pcicmd = 0; - unsigned short tried_config = 0; - unsigned int class_rev; - -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - autodma = 1; -#endif - - if (pci_enable_device(dev)) { - printk(KERN_WARNING "%s: Could not enable PCI device.\n", dev->name); - return; - } - -check_if_enabled: - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { - printk(KERN_ERR "%s: error accessing PCI regs\n", dev->name); - return; - } - if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ - /* - * PnP BIOS was *supposed* to have set this device up for us, - * but we can do it ourselves, so long as the BIOS has assigned - * an IRQ (or possibly the device is using a "legacy header" - * for IRQs). Maybe the user deliberately *disabled* the - * device, but we'll eventually ignore it again if no drives - * respond. - */ - if (tried_config++ - || setup_pci_baseregs(dev, dev->name) - || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { - printk("%s: device disabled (BIOS)\n", dev->name); - return; - } - autodma = 0; /* default DMA off if we had to configure it here */ - goto check_if_enabled; - } - if (tried_config) - printk("%s: device enabled (Linux)\n", dev->name); - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - if (d->vendor == PCI_VENDOR_ID_TTI && PCI_DEVICE_ID_TTI_HPT343) { - /* see comments in hpt34x.c to see why... */ - d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; - } - - printk(KERN_INFO "ATA: chipset rev.: %d\n", class_rev); - - /* - * Can we trust the reported IRQ? - */ - pciirq = dev->irq; - - if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) { - /* By rights we want to ignore these, but the Promise Fastrak - people have some strange ideas about proprietary so we have - to act otherwise on those. The Supertrak however we need - to skip */ - if (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) { - printk(KERN_INFO "ATA: Found promise 20265 in RAID mode.\n"); - if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL && - dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) - { - printk(KERN_INFO "ATA: Skipping Promise PDC20265 attached to I2O RAID controller.\n"); - return; - } - } - /* Its attached to something else, just a random bridge. - Suspect a fastrak and fall through */ - } - if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { - printk(KERN_INFO "ATA: non-legacy mode: IRQ probe delayed\n"); - - /* - * This allows off board ide-pci cards to enable a BIOS, - * verify interrupt settings of split-mirror pci-config - * space, place chipset into init-mode, and/or preserve - * an interrupt if the card is not native ide support. - */ - if (d->init_chipset) - pciirq = d->init_chipset(dev); - else { - if (d->flags & ATA_F_IRQ) - pciirq = dev->irq; - else - pciirq = 0; - } - } else if (tried_config) { - printk(KERN_INFO "ATA: will probe IRQs later\n"); - pciirq = 0; - } else if (!pciirq) { - printk(KERN_INFO "ATA: invalid IRQ (%d): will probe later\n", pciirq); - pciirq = 0; - } else { - if (d->init_chipset) - d->init_chipset(dev); -#ifdef __sparc__ - printk(KERN_INFO "ATA: 100%% native mode on irq %s\n", __irq_itoa(pciirq)); -#else - printk(KERN_INFO "ATA: 100%% native mode on irq %d\n", pciirq); -#endif - } - - /* - * Set up IDE chanells. First the primary, then the secondary. - */ - setup_host_channel(dev, d, ATA_PRIMARY, class_rev, pciirq, autodma); - setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma); -} - -/* - * Fix crossover IRQ line setups between primary and secondary channel. Quite - * a common bug apparently. - */ -static void __init pdc20270_device_order_fixup (struct pci_dev *dev, struct ata_pci_device *d) -{ - struct pci_dev *dev2 = NULL; - struct pci_dev *findev; - struct ata_pci_device *d2; - - if (dev->bus->self && - dev->bus->self->vendor == PCI_VENDOR_ID_DEC && - dev->bus->self->device == PCI_DEVICE_ID_DEC_21150) { - if (PCI_SLOT(dev->devfn) & 2) { - return; - } - d->extra = 0; - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - (PCI_SLOT(findev->devfn) & 2)) { - u8 irq = 0; - u8 irq2 = 0; - dev2 = findev; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); - if (irq != irq2) { - dev2->irq = dev->irq; - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); - } - - } - } - } - printk(KERN_INFO "ATA: %s: controller, PCI slot %s\n", - dev->name, dev->slot_name); - setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk(KERN_INFO "ATA: %s: controller, PCI slot %s\n", - dev2->name, dev2->slot_name); - setup_pci_device(dev2, d2); -} - -static void __init hpt374_device_order_fixup (struct pci_dev *dev, struct ata_pci_device *d) -{ - struct pci_dev *dev2 = NULL; - struct pci_dev *findev; - struct ata_pci_device *d2; - - if (PCI_FUNC(dev->devfn) & 1) - return; - - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - dev2 = findev; - break; - } - } - - printk(KERN_INFO "ATA: %s: controller, PCI slot %s\n", - dev->name, dev->slot_name); - setup_pci_device(dev, d); - if (!dev2) { - return; - } else { - u8 irq = 0; - u8 irq2 = 0; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); - if (irq != irq2) { - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); - dev2->irq = dev->irq; - printk("%s: pci-config space interrupt fixed.\n", - dev2->name); - } - } - d2 = d; - printk(KERN_INFO "ATA: %s: controller, PCI slot %s\n", - dev2->name, dev2->slot_name); - setup_pci_device(dev2, d2); - -} - -static void __init hpt366_device_order_fixup (struct pci_dev *dev, struct ata_pci_device *d) -{ - struct pci_dev *dev2 = NULL, *findev; - struct ata_pci_device *d2; - unsigned char pin1 = 0, pin2 = 0; - unsigned int class_rev; - - if (PCI_FUNC(dev->devfn) & 1) - return; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - switch(class_rev) { - case 5: - case 4: - case 3: printk(KERN_INFO "ATA: %s: controller, PCI slot %s\n", - dev->name, dev->slot_name); - setup_pci_device(dev, d); - return; - default: break; - } - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - pci_for_each_dev(findev) { - if (findev->vendor == dev->vendor && - findev->device == dev->device && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - dev2 = findev; - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - if ((pin1 != pin2) && (dev->irq == dev2->irq)) { - d->bootable = ON_BOARD; - printk(KERN_INFO "ATAL: %s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2); - } - break; - } - } - printk(KERN_INFO "ATA: %s: controller, PCI slot %s\n", - dev->name, dev->slot_name); - setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk(KERN_INFO "ATA: %s: controller, PCI slot %s\n", - dev2->name, dev2->slot_name); - setup_pci_device(dev2, d2); -} - - - -/* - * This finds all PCI IDE controllers and calls appropriate initialization - * functions for them. - */ -static void __init scan_pcidev(struct pci_dev *dev) -{ - unsigned short vendor; - unsigned short device; - struct ata_pci_device *d; - - vendor = dev->vendor; - device = dev->device; - - - - /* Look up the chipset information. - * We expect only one match. - */ - for (d = ata_pci_device_list; d; d = d->next) { - if (d->vendor == vendor && d->device == device) - break; - } - - if (!d) { - /* Only check the device calls, if it wasn't listed, since - * there are in esp. some pdc202xx chips which "work around" - * beeing grabbed by generic drivers. - */ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { - printk(KERN_INFO "ATA: unknown interface: %s, PCI slot %s\n", - dev->name, dev->slot_name); - } - return; - } - - if (d->init_channel == ATA_PCI_IGNORE) - printk(KERN_INFO "ATA: %s: ignored by PCI bus scan\n", dev->name); - else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1)) - return; - else if ((d->vendor == PCI_VENDOR_ID_CONTAQ && d->device == PCI_DEVICE_ID_CONTAQ_82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* CY82C693 is more than only a IDE controller */ - else if ((d->vendor == PCI_VENDOR_ID_ITE && d->device == PCI_DEVICE_ID_ITE_IT8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* IT8172G is also more than only an IDE controller */ - else if ((d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) - return; /* UM8886A/BF pair */ - else if (d->flags & ATA_F_HPTHACK) { - if (d->device == PCI_DEVICE_ID_TTI_HPT366) - hpt366_device_order_fixup(dev, d); - if (d->device == PCI_DEVICE_ID_TTI_HPT374) - hpt374_device_order_fixup(dev, d); - } else if (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20268R) - pdc20270_device_order_fixup(dev, d); - else { - printk(KERN_INFO "ATA: %s, PCI slot %s\n", - dev->name, dev->slot_name); - setup_pci_device(dev, d); - } -} - -void __init ide_scan_pcibus(int scan_direction) -{ - struct pci_dev *dev; - - if (!scan_direction) { - pci_for_each_dev(dev) { - scan_pcidev(dev); - } - } else { - pci_for_each_dev_reverse(dev) { - scan_pcidev(dev); - } - } -} - -/* known chips without particular chipset driver module data table */ -/* Those are id's of chips we don't deal currently with, but which still need - * some generic quirk handling. - */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_PCTECH, - .device = PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_CMD, - .device = PCI_DEVICE_ID_CMD_640, - .init_channel = ATA_PCI_IGNORE, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_NS, - .device = PCI_DEVICE_ID_NS_87410, - .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_HINT, - .device = PCI_DEVICE_ID_HINT_VXPROII_IDE, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_HOLTEK, - .device = PCI_DEVICE_ID_HOLTEK_6565, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371MX, - .enablebits = {{0x6D,0x80,0x80}, {0x00,0x00,0x00}}, - .bootable = ON_BOARD, - .flags = ATA_F_NODMA - }, - { - .vendor = PCI_VENDOR_ID_UMC, - .device = PCI_DEVICE_ID_UMC_UM8673F, - .bootable = ON_BOARD, - .flags = ATA_F_FIXIRQ - }, - { - .vendor = PCI_VENDOR_ID_UMC, - .device = PCI_DEVICE_ID_UMC_UM8886A, - .bootable = ON_BOARD, - .flags = ATA_F_FIXIRQ - }, - { - .vendor = PCI_VENDOR_ID_UMC, - .device = PCI_DEVICE_ID_UMC_UM8886BF, - .bootable = ON_BOARD, - .flags = ATA_F_FIXIRQ - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C561, - .bootable = ON_BOARD, - .flags = ATA_F_NOADMA - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C586_1, - .bootable = ON_BOARD, - .flags = ATA_F_NOADMA - }, - { - .vendor = PCI_VENDOR_ID_TTI, - .device = PCI_DEVICE_ID_TTI_HPT366, - .bootable = OFF_BOARD, - .extra = 240, - .flags = ATA_F_IRQ | ATA_F_HPTHACK - } -}; - -int __init init_ata_pci_misc(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) { - ata_register_chipset(&chipsets[i]); - } - - return 0; -} diff -Nru a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c --- a/drivers/ide/ide-pmac.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1751 +0,0 @@ -/* - * Support for IDE interfaces on PowerMacs. - * These IDE interfaces are memory-mapped and have a DBDMA channel - * for doing DMA. - * - * Copyright (C) 1998-2001 Paul Mackerras & Ben. Herrenschmidt - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Some code taken from drivers/ide/ide-dma.c: - * - * Copyright (c) 1995-1998 Mark Lord - * - * TODO: - * - * - Find a way to duplicate less code with ide-dma and use the - * dma fileds in the hwif structure instead of our own - * - * - Fix check_disk_change() call - * - * - Make module-able (includes setting ppc_md. hooks from within - * this file and not from arch code, and handling module deps with - * mediabay (by having both modules do dynamic lookup of each other - * symbols or by storing hooks at arch level). - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PMAC_PBOOK -#include -#include -#endif -#include "timing.h" - -#undef IDE_PMAC_DEBUG - -#define DMA_WAIT_TIMEOUT 500 - -struct pmac_ide_hwif { - ide_ioreg_t regbase; - int irq; - int kind; - int aapl_bus_id; - struct device_node* node; - u32 timings[2]; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - /* Those fields are duplicating what is in hwif. We currently - * can't use the hwif ones because of some assumptions that are - * beeing done by the generic code about the kind of dma controller - * and format of the dma table. This will have to be fixed though. - */ - volatile struct dbdma_regs* dma_regs; - struct dbdma_cmd* dma_table_cpu; - dma_addr_t dma_table_dma; - struct scatterlist* sg_table; - int sg_nents; - int sg_dma_direction; -#endif - -} pmac_ide[MAX_HWIFS] __pmacdata; - -static int pmac_ide_count; - -enum { - controller_ohare, /* OHare based */ - controller_heathrow, /* Heathrow/Paddington */ - controller_kl_ata3, /* KeyLargo ATA-3 */ - controller_kl_ata4, /* KeyLargo ATA-4 */ - controller_kl_ata4_80 /* KeyLargo ATA-4 with 80 conductor cable */ -}; - -/* - * Extra registers, both 32-bit little-endian - */ -#define IDE_TIMING_CONFIG 0x200 -#define IDE_INTERRUPT 0x300 - -/* - * Timing configuration register definitions - */ - -/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ -#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) -#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) -#define IDE_SYSCLK_NS 30 /* 33Mhz cell */ -#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ - -/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on - * 40 connector cable and to 4 on 80 connector one. - * Clock unit is 15ns (66Mhz) - * - * 3 Values can be programmed: - * - Write data setup, which appears to match the cycle time. They - * also call it DIOW setup. - * - Ready to pause time (from spec) - * - Address setup. That one is weird. I don't see where exactly - * it fits in UDMA cycles, I got it's name from an obscure piece - * of commented out code in Darwin. They leave it to 0, we do as - * well, despite a comment that would lead to think it has a - * min value of 45ns. - * Apple also add 60ns to the write data setup (or cycle time ?) on - * reads. I can't explain that, I tried it and it broke everything - * here. - */ -#define TR_66_UDMA_MASK 0xfff00000 -#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ -#define TR_66_UDMA_ADDRSETUP_MASK 0xe0000000 /* Address setup */ -#define TR_66_UDMA_ADDRSETUP_SHIFT 29 -#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ -#define TR_66_UDMA_RDY2PAUS_SHIFT 25 -#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ -#define TR_66_UDMA_WRDATASETUP_SHIFT 21 -#define TR_66_MDMA_MASK 0x000ffc00 -#define TR_66_MDMA_RECOVERY_MASK 0x000f8000 -#define TR_66_MDMA_RECOVERY_SHIFT 15 -#define TR_66_MDMA_ACCESS_MASK 0x00007c00 -#define TR_66_MDMA_ACCESS_SHIFT 10 -#define TR_66_PIO_MASK 0x000003ff -#define TR_66_PIO_RECOVERY_MASK 0x000003e0 -#define TR_66_PIO_RECOVERY_SHIFT 5 -#define TR_66_PIO_ACCESS_MASK 0x0000001f -#define TR_66_PIO_ACCESS_SHIFT 0 - -/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo - * Can do pio & mdma modes, clock unit is 30ns (33Mhz) - * - * The access time and recovery time can be programmed. Some older - * Darwin code base limit OHare to 150ns cycle time. I decided to do - * the same here fore safety against broken old hardware ;) - * The HalfTick bit, when set, adds half a clock (15ns) to the access - * time and removes one from recovery. It's not supported on KeyLargo - * implementation afaik. The E bit appears to be set for PIO mode 0 and - * is used to reach long timings used in this mode. - */ -#define TR_33_MDMA_MASK 0x003ff800 -#define TR_33_MDMA_RECOVERY_MASK 0x001f0000 -#define TR_33_MDMA_RECOVERY_SHIFT 16 -#define TR_33_MDMA_ACCESS_MASK 0x0000f800 -#define TR_33_MDMA_ACCESS_SHIFT 11 -#define TR_33_MDMA_HALFTICK 0x00200000 -#define TR_33_PIO_MASK 0x000007ff -#define TR_33_PIO_E 0x00000400 -#define TR_33_PIO_RECOVERY_MASK 0x000003e0 -#define TR_33_PIO_RECOVERY_SHIFT 5 -#define TR_33_PIO_ACCESS_MASK 0x0000001f -#define TR_33_PIO_ACCESS_SHIFT 0 - -/* - * Interrupt register definitions - */ -#define IDE_INTR_DMA 0x80000000 -#define IDE_INTR_DEVICE 0x40000000 - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -# define BAD_DMA_DRIVE 0 -# define GOOD_DMA_DRIVE 1 - -/* Rounded Multiword DMA timings - * - * I gave up finding a generic formula for all controller - * types and instead, built tables based on timing values - * used by Apple in Darwin's implementation. - */ -struct mdma_timings_t { - int accessTime; - int recoveryTime; - int cycleTime; -}; - -struct mdma_timings_t mdma_timings_33[] __pmacdata = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 135, 135, 270 }, - { 120, 120, 240 }, - { 105, 105, 210 }, - { 90, 90, 180 }, - { 75, 75, 150 }, - { 75, 45, 120 }, - { 0, 0, 0 } -}; - -struct mdma_timings_t mdma_timings_33k[] __pmacdata = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 150, 150, 300 }, - { 120, 120, 240 }, - { 90, 120, 210 }, - { 90, 90, 180 }, - { 90, 60, 150 }, - { 90, 30, 120 }, - { 0, 0, 0 } -}; - -struct mdma_timings_t mdma_timings_66[] __pmacdata = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 135, 135, 270 }, - { 120, 120, 240 }, - { 105, 105, 210 }, - { 90, 90, 180 }, - { 90, 75, 165 }, - { 75, 45, 120 }, - { 0, 0, 0 } -}; - -/* Ultra DMA timings (rounded) */ -struct { - int addrSetup; /* ??? */ - int rdy2pause; - int wrDataSetup; -} udma_timings[] __pmacdata = -{ - { 0, 180, 120 }, /* Mode 0 */ - { 0, 150, 90 }, /* 1 */ - { 0, 120, 60 }, /* 2 */ - { 0, 90, 45 }, /* 3 */ - { 0, 90, 30 } /* 4 */ -}; - -/* allow up to 256 DBDMA commands per xfer */ -#define MAX_DCMDS 256 - -/* Wait 2s for disk to answer on IDE bus after - * enable operation. - * NOTE: There is at least one case I know of a disk that needs about 10sec - * before anwering on the bus. I beleive we could add a kernel command - * line arg to override this delay for such cases. - */ -#define IDE_WAKEUP_DELAY_MS 2000 - -static void pmac_ide_setup_dma(struct device_node *np, int ix); - -static void pmac_udma_enable(struct ata_device *drive, int on, int verbose); -static void pmac_udma_start(struct ata_device *drive, struct request *rq); -static int pmac_udma_stop(struct ata_device *drive); -static int pmac_udma_init(struct ata_device *drive, struct request *rq); -static int pmac_udma_irq_status(struct ata_device *drive); -static int pmac_udma_setup(struct ata_device *drive, int map); -static int pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, int wr); -static int pmac_ide_tune_chipset(struct ata_device *drive, u8 speed); -static void pmac_ide_tuneproc(struct ata_device *drive, u8 pio); -static void pmac_ide_selectproc(struct ata_device *drive); - -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - -#ifdef CONFIG_PMAC_PBOOK -static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when); -struct pmu_sleep_notifier idepmac_sleep_notifier = { - idepmac_notify_sleep, SLEEP_LEVEL_BLOCK, -}; -#endif /* CONFIG_PMAC_PBOOK */ - -static int __pmac -pmac_ide_find(struct ata_device *drive) -{ - struct ata_channel *hwif = drive->channel; - ide_ioreg_t base; - int i; - - for (i=0; iio_ports[0]) - return i; - } - return -1; -} - -/* - * N.B. this can't be an initfunc, because the media-bay task can - * call ide_[un]register at any time. - */ -void __pmac -pmac_ide_init_hwif_ports(hw_regs_t *hw, - ide_ioreg_t data_port, ide_ioreg_t ctrl_port, - int *irq) -{ - int i, ix; - - if (data_port == 0) - return; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - 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; - } - - for (i = 0; i < 8; ++i) - hw->io_ports[i] = data_port + i * 0x10; - hw->io_ports[8] = data_port + 0x160; - - if (irq != NULL) - *irq = pmac_ide[ix].irq; - - ide_hwifs[ix].tuneproc = pmac_ide_tuneproc; - ide_hwifs[ix].selectproc = pmac_ide_selectproc; - ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset; - if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table_cpu) { - ide_hwifs[ix].udma_enable = pmac_udma_enable; - ide_hwifs[ix].udma_start = pmac_udma_start; - ide_hwifs[ix].udma_stop = pmac_udma_stop; - ide_hwifs[ix].udma_init = pmac_udma_init; - ide_hwifs[ix].udma_irq_status = pmac_udma_irq_status; - ide_hwifs[ix].udma_setup = pmac_udma_setup; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO - if (!noautodma) - ide_hwifs[ix].autodma = 1; -#endif - ide_hwifs[ix].unmask = 1; - } -} - -/* Setup timings for the selected drive (master/slave). I still need to verify if this - * is enough, I beleive selectproc will be called whenever an IDE command is started, - * but... */ -static void __pmac -pmac_ide_selectproc(struct ata_device *drive) -{ - int i = pmac_ide_find(drive); - if (i < 0) - return; - - if (drive->select.b.unit & 0x01) - out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE), - pmac_ide[i].timings[1]); - else - out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE), - pmac_ide[i].timings[0]); - (void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE)); -} - - -/* Note: We don't use the generic routine here because for some - * yet unexplained reasons, it cause some media-bay CD-ROMs to - * lockup the bus. Strangely, this new version of the code is - * almost identical to the generic one and works, I've not yet - * managed to figure out what bit is causing the lockup in the - * generic code, possibly a timing issue... - * - * --BenH - */ -static int __pmac -wait_for_ready(struct ata_device *drive) -{ - /* Timeout bumped for some powerbooks */ - int timeout = 2000; - - while (--timeout) { - if(ata_status(drive, 0, BUSY_STAT)) { - if (drive->ready_stat == 0) - break; - else if((drive->status & drive->ready_stat) - || (drive->status & ERR_STAT)) - break; - } - mdelay(1); - } - if((drive->status & ERR_STAT) || timeout <= 0) { - if (drive->status & ERR_STAT) { - printk(KERN_ERR "ide_pmac: wait_for_ready, error status: %x\n", - drive->status); - } - return 1; - } - return 0; -} - -static int __pmac -pmac_ide_do_setfeature(struct ata_device *drive, u8 command) -{ - int result = 1; - unsigned long flags; - struct ata_channel *hwif = drive->channel; - - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ - udelay(1); - ata_select(drive, 0); - ata_mask(drive); - udelay(1); - ata_status(drive, 0, 0); /* Get rid of pending error state */ - if (wait_for_ready(drive)) { - printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n"); - goto out; - } - udelay(10); - ata_irq_enable(drive, 0); - OUT_BYTE(command, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - udelay(1); - local_save_flags(flags); - local_irq_enable(); - result = wait_for_ready(drive); - local_irq_restore(flags); - ata_irq_enable(drive, 1); - if (result) - printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n"); -out: - ata_mask(drive); - if (result == 0) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - switch(command) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; - } - } - enable_irq(hwif->irq); - - return result; -} - -/* Calculate PIO timings */ -static void __pmac -pmac_ide_tuneproc(struct ata_device *drive, u8 pio) -{ - struct ata_timing *t; - int i; - u32 *timings; - unsigned accessTicks, recTicks; - unsigned accessTime, recTime; - - i = pmac_ide_find(drive); - if (i < 0) - return; - - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); - else - pio = XFER_PIO_0 + min_t(u8, pio, 4); - - t = ata_timing_data(pio); - - accessTicks = SYSCLK_TICKS(t->active); - timings = &pmac_ide[i].timings[drive->select.b.unit & 0x01]; - - recTime = t->cycle - t->active - t->setup; - recTime = max(recTime, 150U); - accessTime = t->active; - accessTime = max(accessTime, 150U); - if (pmac_ide[i].kind == controller_kl_ata4 || - pmac_ide[i].kind == controller_kl_ata4_80) { - /* 66Mhz cell */ - accessTicks = SYSCLK_TICKS_66(accessTime); - accessTicks = min(accessTicks, 0x1fU); - recTicks = SYSCLK_TICKS_66(recTime); - recTicks = min(recTicks, 0x1fU); - *timings = ((*timings) & ~TR_66_PIO_MASK) | - (accessTicks << TR_66_PIO_ACCESS_SHIFT) | - (recTicks << TR_66_PIO_RECOVERY_SHIFT); - } else { - /* 33Mhz cell */ - int ebit = 0; - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = min(accessTicks, 0x1fU); - accessTicks = max(accessTicks, 4U); - recTicks = SYSCLK_TICKS(recTime); - recTicks = min(recTicks, 0x1fU); - recTicks = max(recTicks, 5U) - 4; - if (recTicks > 9) { - recTicks--; /* guess, but it's only for PIO0, so... */ - ebit = 1; - } - *timings = ((*timings) & ~TR_33_PIO_MASK) | - (accessTicks << TR_33_PIO_ACCESS_SHIFT) | - (recTicks << TR_33_PIO_RECOVERY_SHIFT); - if (ebit) - *timings |= TR_33_PIO_E; - } - -#ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n", - pio, *timings); -#endif - - if (drive->select.all == IN_BYTE(IDE_SELECT_REG)) - pmac_ide_selectproc(drive); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC -static int __pmac set_timings_udma(u32 *timings, u8 speed) -{ - unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; - - rdyToPauseTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].rdy2pause); - wrDataSetupTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].wrDataSetup); - addrTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].addrSetup); - - *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) | - (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | - (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) | - (addrTicks < cycleTime) - cycleTime = drive_cycle_time; - /* OHare limits according to some old Apple sources */ - if ((intf_type == controller_ohare) && (cycleTime < 150)) - cycleTime = 150; - /* Get the proper timing array for this controller */ - switch(intf_type) { - case controller_kl_ata4: - case controller_kl_ata4_80: - tm = mdma_timings_66; - break; - case controller_kl_ata3: - tm = mdma_timings_33k; - break; - default: - tm = mdma_timings_33; - break; - } - /* Lookup matching access & recovery times */ - i = -1; - for (;;) { - if (tm[i+1].cycleTime < cycleTime) - break; - i++; - } - if (i < 0) - return -1; - cycleTime = tm[i].cycleTime; - accessTime = tm[i].accessTime; - recTime = tm[i].recoveryTime; - -#ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "ide_pmac: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n", - cycleTime, accessTime, recTime); -#endif - if (intf_type == controller_kl_ata4 || intf_type == controller_kl_ata4_80) { - /* 66Mhz cell */ - accessTicks = SYSCLK_TICKS_66(accessTime); - accessTicks = min(accessTicks, 0x1fU); - accessTicks = max(accessTicks, 0x1U); - recTicks = SYSCLK_TICKS_66(recTime); - recTicks = min(recTicks, 0x1fU); - recTicks = max(recTicks, 0x3U); - /* Clear out mdma bits and disable udma */ - *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) | - (accessTicks << TR_66_MDMA_ACCESS_SHIFT) | - (recTicks << TR_66_MDMA_RECOVERY_SHIFT); - } else if (intf_type == controller_kl_ata3) { - /* 33Mhz cell on KeyLargo */ - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = max(accessTicks, 1U); - accessTicks = min(accessTicks, 0x1fU); - accessTime = accessTicks * IDE_SYSCLK_NS; - recTicks = SYSCLK_TICKS(recTime); - recTicks = max(recTicks, 1U); - recTicks = min(recTicks, 0x1fU); - *timings = ((*timings) & ~TR_33_MDMA_MASK) | - (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | - (recTicks << TR_33_MDMA_RECOVERY_SHIFT); - } else { - /* 33Mhz cell on others */ - int halfTick = 0; - int origAccessTime = accessTime; - int origRecTime = recTime; - - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = max(accessTicks, 1U); - accessTicks = min(accessTicks, 0x1fU); - accessTime = accessTicks * IDE_SYSCLK_NS; - recTicks = SYSCLK_TICKS(recTime); - recTicks = max(recTicks, 2U) - 1; - recTicks = min(recTicks, 0x1fU); - recTime = (recTicks + 1) * IDE_SYSCLK_NS; - if ((accessTicks > 1) && - ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && - ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) { - halfTick = 1; - accessTicks--; - } - *timings = ((*timings) & ~TR_33_MDMA_MASK) | - (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | - (recTicks << TR_33_MDMA_RECOVERY_SHIFT); - if (halfTick) - *timings |= TR_33_MDMA_HALFTICK; - } -# ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n", - speed & 0xf, *timings); -# endif - return 0; -} -#endif - -/* You may notice we don't use this function on normal operation, - * our, normal mdma function is supposed to be more precise - */ -static int __pmac -pmac_ide_tune_chipset (struct ata_device *drive, u8 speed) -{ - int intf = pmac_ide_find(drive); - int unit = (drive->select.b.unit & 0x01); - int ret = 0; - u32 *timings; - - if (intf < 0) - return 1; - - timings = &pmac_ide[intf].timings[unit]; - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - case XFER_UDMA_4: - case XFER_UDMA_3: - if (pmac_ide[intf].kind != controller_kl_ata4_80) - return 1; - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - if (pmac_ide[intf].kind != controller_kl_ata4 && - pmac_ide[intf].kind != controller_kl_ata4_80) - return 1; - ret = set_timings_udma(timings, speed); - break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - ret = set_timings_mdma(pmac_ide[intf].kind, timings, speed, 0); - break; - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - return 1; -#endif - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - pmac_ide_tuneproc(drive, speed & 0x07); - break; - default: - ret = 1; - } - if (ret) - return ret; - - ret = pmac_ide_do_setfeature(drive, speed); - if (ret) - return ret; - - pmac_ide_selectproc(drive); - drive->current_speed = speed; - - return 0; -} - -static void __pmac -sanitize_timings(int i) -{ - unsigned value; - - switch(pmac_ide[i].kind) { - case controller_kl_ata4: - case controller_kl_ata4_80: - value = 0x0008438c; - break; - case controller_kl_ata3: - value = 0x00084526; - break; - case controller_heathrow: - case controller_ohare: - default: - value = 0x00074526; - break; - } - pmac_ide[i].timings[0] = pmac_ide[i].timings[1] = value; -} - -ide_ioreg_t __pmac -pmac_ide_get_base(int index) -{ - return pmac_ide[index].regbase; -} - -int __pmac -pmac_ide_check_base(ide_ioreg_t base) -{ - int ix; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (base == pmac_ide[ix].regbase) - return ix; - return -1; -} - -int __pmac -pmac_ide_get_irq(ide_ioreg_t base) -{ - int ix; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (base == pmac_ide[ix].regbase) - return pmac_ide[ix].irq; - return 0; -} - -static int ide_majors[] __pmacdata = { 3, 22, 33, 34, 56, 57 }; - -kdev_t __init -pmac_find_ide_boot(char *bootdevice, int n) -{ - int i; - - /* - * Look through the list of IDE interfaces for this one. - */ - for (i = 0; i < pmac_ide_count; ++i) { - char *name; - if (!pmac_ide[i].node || !pmac_ide[i].node->full_name) - continue; - name = pmac_ide[i].node->full_name; - if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { - /* XXX should cope with the 2nd drive as well... */ - return mk_kdev(ide_majors[i], 0); - } - } - - return NODEV; -} - -void __init -pmac_ide_probe(void) -{ - struct device_node *np; - int i; - struct device_node *atas; - struct device_node *p, **pp, *removables, **rp; - unsigned long base; - int irq, big_delay; - struct ata_channel *hwif; - - if (_machine != _MACH_Pmac) - return; - pp = &atas; - rp = &removables; - p = find_devices("ATA"); - if (p == NULL) - p = find_devices("IDE"); - if (p == NULL) - p = find_type_devices("ide"); - if (p == NULL) - p = find_type_devices("ata"); - /* Move removable devices such as the media-bay CDROM - on the PB3400 to the end of the list. */ - for (; p != NULL; p = p->next) { - if (p->parent && p->parent->type - && strcasecmp(p->parent->type, "media-bay") == 0) { - *rp = p; - rp = &p->next; - } else { - *pp = p; - pp = &p->next; - } - } - *rp = NULL; - *pp = removables; - big_delay = 0; - - for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) { - struct device_node *tp; - struct pmac_ide_hwif *pmif; - int *bidp; - int in_bay = 0; - u8 pbus, pid; - struct pci_dev *pdev = NULL; - - /* - * If this node is not under a mac-io or dbdma node, - * leave it to the generic PCI driver. - */ - for (tp = np->parent; tp != 0; tp = tp->parent) - if (tp->type && (strcmp(tp->type, "mac-io") == 0 - || strcmp(tp->type, "dbdma") == 0)) - break; - if (tp == 0) - continue; - - if (np->n_addrs == 0) { - printk(KERN_WARNING "ide: no address for device %s\n", - np->full_name); - continue; - } - - /* We need to find the pci_dev of the mac-io holding the - * IDE interface - */ - if (pci_device_from_OF_node(tp, &pbus, &pid) == 0) - pdev = pci_find_slot(pbus, pid); - if (pdev == NULL) - printk(KERN_WARNING "ide: no PCI host for device %s, DMA disabled\n", - np->full_name); - - /* - * If this slot is taken (e.g. by ide-pci.c) try the next one. - */ - while (i < MAX_HWIFS - && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0) - ++i; - if (i >= MAX_HWIFS) - break; - pmif = &pmac_ide[i]; - - /* - * Some older OFs have bogus sizes, causing request_OF_resource - * to fail. We fix them up here - */ - if (np->addrs[0].size > 0x1000) - np->addrs[0].size = 0x1000; - if (np->n_addrs > 1 && np->addrs[1].size > 0x100) - np->addrs[1].size = 0x100; - - if (request_OF_resource(np, 0, " (mac-io IDE IO)") == NULL) { - printk(KERN_ERR "ide-pmac(%s): can't request IO resource !\n", np->name); - continue; - } - - base = (unsigned long) ioremap(np->addrs[0].address, 0x400) - _IO_BASE; - - /* XXX This is bogus. Should be fixed in the registry by checking - the kind of host interrupt controller, a bit like gatwick - fixes in irq.c - */ - if (np->n_intrs == 0) { - printk(KERN_WARNING "ide: no intrs for device %s, using 13\n", - np->full_name); - irq = 13; - } else { - irq = np->intrs[0].line; - } - pmif->regbase = base; - pmif->irq = irq; - pmif->node = np; - if (device_is_compatible(np, "keylargo-ata")) { - if (strcmp(np->name, "ata-4") == 0) - pmif->kind = controller_kl_ata4; - else - pmif->kind = controller_kl_ata3; - } else if (device_is_compatible(np, "heathrow-ata")) - pmif->kind = controller_heathrow; - else - pmif->kind = controller_ohare; - - bidp = (int *)get_property(np, "AAPL,bus-id", NULL); - pmif->aapl_bus_id = bidp ? *bidp : 0; - - if (pmif->kind == controller_kl_ata4) { - char* cable = get_property(np, "cable-type", NULL); - if (cable && !strncmp(cable, "80-", 3)) - pmif->kind = controller_kl_ata4_80; - } - - /* Make sure we have sane timings */ - sanitize_timings(i); - - if (np->parent && np->parent->name - && strcasecmp(np->parent->name, "media-bay") == 0) { -#ifdef CONFIG_PMAC_PBOOK - media_bay_set_ide_infos(np->parent,base,irq,i); -#endif - in_bay = 1; - if (!bidp) - pmif->aapl_bus_id = 1; - } else if (pmif->kind == controller_ohare) { - /* The code below is having trouble on some ohare machines - * (timing related ?). Until I can put my hand on one of these - * units, I keep the old way - */ - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); - } else { - /* This is necessary to enable IDE when net-booting */ - printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n", - pmif->aapl_bus_id); - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); - mdelay(10); - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0); - big_delay = 1; - } - - hwif = &ide_hwifs[i]; - pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->chipset = ide_pmac; - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay; - hwif->udma_four = (pmif->kind == controller_kl_ata4_80); - hwif->pci_dev = pdev; -#ifdef CONFIG_PMAC_PBOOK - if (in_bay && check_media_bay_by_base(base, MB_CD) == 0) - hwif->noprobe = 0; -#endif - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - if (pdev && np->n_addrs >= 2) { - /* has a DBDMA controller channel */ - pmac_ide_setup_dma(np, i); - } -#endif - - ++i; - } - pmac_ide_count = i; - if (big_delay) - mdelay(IDE_WAKEUP_DELAY_MS); - -#ifdef CONFIG_PMAC_PBOOK - pmu_register_sleep_notifier(&idepmac_sleep_notifier); -#endif -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -static void __init -pmac_ide_setup_dma(struct device_node *np, int ix) -{ - struct pmac_ide_hwif *pmif = &pmac_ide[ix]; - - if (request_OF_resource(np, 1, " (mac-io IDE DMA)") == NULL) { - printk(KERN_ERR "ide-pmac(%s): can't request DMA resource !\n", - np->name); - return; - } - - pmif->dma_regs = - (volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200); - - /* - * 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( - ide_hwifs[ix].pci_dev, - (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), - &pmif->dma_table_dma); - if (pmif->dma_table_cpu == NULL) { - printk(KERN_ERR "%s: unable to allocate DMA command list\n", - ide_hwifs[ix].name); - return; - } - - pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS, - GFP_KERNEL); - if (pmif->sg_table == NULL) { - pci_free_consistent( ide_hwifs[ix].pci_dev, - (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), - pmif->dma_table_cpu, pmif->dma_table_dma); - return; - } - ide_hwifs[ix].udma_enable = pmac_udma_enable; - ide_hwifs[ix].udma_start = pmac_udma_start; - ide_hwifs[ix].udma_stop = pmac_udma_stop; - ide_hwifs[ix].udma_init = pmac_udma_init; - ide_hwifs[ix].udma_irq_status = pmac_udma_irq_status; - ide_hwifs[ix].udma_setup = pmac_udma_setup; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO - if (!noautodma) - ide_hwifs[ix].autodma = 1; -#endif -} - -static int -pmac_ide_build_sglist (int ix, struct request *rq) -{ - struct ata_channel *hwif = &ide_hwifs[ix]; - struct pmac_ide_hwif *pmif = &pmac_ide[ix]; - request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue; - struct scatterlist *sg = pmif->sg_table; - int nents; - - nents = blk_rq_map_sg(q, rq, pmif->sg_table); - - if (rq->q && nents > rq->nr_phys_segments) - printk("ide-pmac: received %d phys segments, build %d\n", rq->nr_phys_segments, nents); - - if (rq_data_dir(rq) == READ) - pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - pmif->sg_dma_direction = PCI_DMA_TODEVICE; - - return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); -} - -static int -pmac_raw_build_sglist (int ix, struct request *rq) -{ - struct ata_channel *hwif = &ide_hwifs[ix]; - struct pmac_ide_hwif *pmif = &pmac_ide[ix]; - struct scatterlist *sg = pmif->sg_table; - int nents = 0; - struct ata_taskfile *args = rq->special; - unsigned char *virt_addr = rq->buffer; - int sector_count = rq->nr_sectors; - - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - pmif->sg_dma_direction = PCI_DMA_TODEVICE; - else - pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; - - if (sector_count > 128) { - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK; - sg[nents].length = 128 * SECTOR_SIZE; - nents++; - virt_addr = virt_addr + (128 * SECTOR_SIZE); - sector_count -= 128; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK; - sg[nents].length = sector_count * SECTOR_SIZE; - nents++; - - return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); -} - -/* - * pmac_ide_build_dmatable builds the DBDMA command list - * for a transfer and sets the DBDMA channel to point to it. - */ -static int -pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, int wr) -{ - struct dbdma_cmd *table; - int i, count = 0; - volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs; - struct scatterlist *sg; - - /* DMA table is already aligned */ - table = (struct dbdma_cmd *) pmac_ide[ix].dma_table_cpu; - - /* Make sure DMA controller is stopped (necessary ?) */ - out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); - while (in_le32(&dma->status) & RUN) - udelay(1); - - /* Build sglist */ - if (rq->flags & REQ_SPECIAL) { - pmac_ide[ix].sg_nents = i = pmac_raw_build_sglist(ix, rq); - } else { - pmac_ide[ix].sg_nents = i = pmac_ide_build_sglist(ix, rq); - } - if (!i) - return 0; - - /* Build DBDMA commands list */ - sg = pmac_ide[ix].sg_table; - while (i) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - while (cur_len) { - unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; - - if (++count >= MAX_DCMDS) { - printk(KERN_WARNING "%s: DMA table too small\n", - drive->name); - return 0; /* revert to PIO for this request */ - } - st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); - st_le16(&table->req_count, tc); - st_le32(&table->phy_addr, cur_addr); - table->cmd_dep = 0; - table->xfer_status = 0; - table->res_count = 0; - cur_addr += tc; - cur_len -= tc; - ++table; - } - sg++; - i--; - } - - /* convert the last command to an input/output last command */ - if (count) - st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); - else - printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); - - /* add the stop command to the end of the list */ - memset(table, 0, sizeof(struct dbdma_cmd)); - out_le16(&table->command, DBDMA_STOP); - - out_le32(&dma->cmdptr, pmac_ide[ix].dma_table_dma); - return 1; -} - -/* Teardown mappings after DMA has completed. */ -static void -pmac_ide_destroy_dmatable(struct ata_channel *ch, int ix) -{ - struct pci_dev *dev = ch->pci_dev; - struct scatterlist *sg = pmac_ide[ix].sg_table; - int nents = pmac_ide[ix].sg_nents; - - if (nents) { - pci_unmap_sg(dev, sg, nents, pmac_ide[ix].sg_dma_direction); - pmac_ide[ix].sg_nents = 0; - } -} - - -static __inline__ unsigned char -dma_bits_to_command(unsigned char bits) -{ - if(bits & 0x04) - return XFER_MW_DMA_2; - if(bits & 0x02) - return XFER_MW_DMA_1; - if(bits & 0x01) - return XFER_MW_DMA_0; - return 0; -} - -static __inline__ unsigned char -udma_bits_to_command(unsigned char bits, int high_speed) -{ - if (high_speed) { - if(bits & 0x10) - return XFER_UDMA_4; - if(bits & 0x08) - return XFER_UDMA_3; - } - if(bits & 0x04) - return XFER_UDMA_2; - if(bits & 0x02) - return XFER_UDMA_1; - if(bits & 0x01) - return XFER_UDMA_0; - return 0; -} - -/* Calculate MultiWord DMA timings */ -static int __pmac -pmac_ide_mdma_enable(struct ata_device *drive, int idx) -{ - u8 bits = drive->id->dma_mword & 0x07; - u8 feature = dma_bits_to_command(bits); - u32 *timings; - int drive_cycle_time; - struct hd_driveid *id = drive->id; - int ret; - - /* Set feature on drive */ - printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf); - ret = pmac_ide_do_setfeature(drive, feature); - if (ret) { - printk(KERN_WARNING "%s: Failed !\n", drive->name); - return 0; - } - - /* which drive is it ? */ - if (drive->select.b.unit & 0x01) - timings = &pmac_ide[idx].timings[1]; - else - timings = &pmac_ide[idx].timings[0]; - - /* Check if drive provide explicit cycle time */ - if ((id->field_valid & 2) && (id->eide_dma_time)) - drive_cycle_time = id->eide_dma_time; - else - drive_cycle_time = 0; - - /* Calculate controller timings */ - set_timings_mdma(pmac_ide[idx].kind, timings, feature, drive_cycle_time); - - drive->current_speed = feature; - return 1; -} - -/* Calculate Ultra DMA timings */ -static int __pmac -pmac_ide_udma_enable(struct ata_device *drive, int idx, int high_speed) -{ - u8 bits = drive->id->dma_ultra & 0x1f; - u8 feature = udma_bits_to_command(bits, high_speed); - u32 *timings; - int ret; - - /* Set feature on drive */ - printk(KERN_INFO "%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf); - ret = pmac_ide_do_setfeature(drive, feature); - if (ret) { - printk(KERN_WARNING "%s: Failed !\n", drive->name); - return 0; - } - - /* which drive is it ? */ - if (drive->select.b.unit & 0x01) - timings = &pmac_ide[idx].timings[1]; - else - timings = &pmac_ide[idx].timings[0]; - - set_timings_udma(timings, feature); - - drive->current_speed = feature; - return 1; -} - -static int __pmac -pmac_ide_check_dma(struct ata_device *drive) -{ - int ata4, udma, idx; - struct hd_driveid *id = drive->id; - int enable = 1; - - drive->using_dma = 0; - - idx = pmac_ide_find(drive); - if (idx < 0) - return 0; - - if (drive->type == ATA_FLOPPY) - enable = 0; - if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE)) - enable = 0; - if (check_drive_lists(drive, BAD_DMA_DRIVE)) - enable = 0; - - udma = 0; - ata4 = (pmac_ide[idx].kind == controller_kl_ata4 || - pmac_ide[idx].kind == controller_kl_ata4_80); - - if(enable) { - if (ata4 && (drive->type == ATA_DISK) && - (id->field_valid & 0x0004) && (id->dma_ultra & 0x1f)) { - /* UltraDMA modes. */ - drive->using_dma = pmac_ide_udma_enable(drive, idx, - pmac_ide[idx].kind == controller_kl_ata4_80); - } - if (!drive->using_dma && (id->dma_mword & 0x0007)) { - /* Normal MultiWord DMA modes. */ - drive->using_dma = pmac_ide_mdma_enable(drive, idx); - } - ata_irq_enable(drive, 1); - /* Apply settings to controller */ - pmac_ide_selectproc(drive); - } - return 0; -} - -static void ide_toggle_bounce(struct ata_device *drive, int on) -{ - dma64_addr_t addr = BLK_BOUNCE_HIGH; - - if (on && drive->type == ATA_DISK && drive->channel->highmem) { - if (!PCI_DMA_BUS_IS_PHYS) - addr = BLK_BOUNCE_ANY; - else - addr = drive->channel->pci_dev->dma_mask; - } - - blk_queue_bounce_limit(&drive->queue, addr); -} - -static void pmac_udma_enable(struct ata_device *drive, int on, int verbose) -{ - if (verbose) { - printk(KERN_INFO "%s: DMA disabled\n", drive->name); - } - - drive->using_dma = 0; - ide_toggle_bounce(drive, 0); -} - -static void pmac_udma_start(struct ata_device *drive, struct request *rq) -{ - int ix, ata4; - volatile struct dbdma_regs *dma; - - /* Can we stuff a pointer to our intf structure in config_data - * or select_data in hwif ? - */ - ix = pmac_ide_find(drive); - if (ix < 0) - return; - - dma = pmac_ide[ix].dma_regs; - ata4 = (pmac_ide[ix].kind == controller_kl_ata4 || - pmac_ide[ix].kind == controller_kl_ata4_80); - - out_le32(&dma->control, (RUN << 16) | RUN); - /* Make sure it gets to the controller right now */ - (void)in_le32(&dma->control); - - return; -} - -static int pmac_udma_stop(struct ata_device *drive) -{ - int ix, dstat, ata4; - volatile struct dbdma_regs *dma; - - /* Can we stuff a pointer to our intf structure in config_data - * or select_data in hwif ? - */ - ix = pmac_ide_find(drive); - if (ix < 0) - return 0; - dma = pmac_ide[ix].dma_regs; - ata4 = (pmac_ide[ix].kind == controller_kl_ata4 || - pmac_ide[ix].kind == controller_kl_ata4_80); - - dstat = in_le32(&dma->status); - out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16)); - pmac_ide_destroy_dmatable(drive->channel, ix); - /* verify good dma status */ - return (dstat & (RUN|DEAD|ACTIVE)) != RUN; -} - -static int pmac_udma_init(struct ata_device *drive, struct request *rq) -{ - int ix, ata4; - volatile struct dbdma_regs *dma; - u8 unit = (drive->select.b.unit & 0x01); - int reading; - - /* Can we stuff a pointer to our intf structure in config_data - * or select_data in hwif ? - */ - ix = pmac_ide_find(drive); - if (ix < 0) - return ATA_OP_FINISHED; - - if (rq_data_dir(rq) == READ) - reading = 1; - else - reading = 0; - - dma = pmac_ide[ix].dma_regs; - ata4 = (pmac_ide[ix].kind == controller_kl_ata4 || - pmac_ide[ix].kind == controller_kl_ata4_80); - - if (!pmac_ide_build_dmatable(drive, rq, ix, !reading)) - return ATA_OP_FINISHED; - /* Apple adds 60ns to wrDataSetup on reads */ - if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) { - out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE), - pmac_ide[ix].timings[unit] + - ((reading) ? 0x00800000UL : 0)); - (void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE)); - } - - if (drive->type != ATA_DISK) - return ATA_OP_CONTINUES; - - ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); - if ((rq->flags & REQ_SPECIAL) && - (drive->addressing == 1)) { - struct ata_taskfile *args = rq->special; - /* FIXME: this is never reached */ - OUT_BYTE(args->cmd, IDE_COMMAND_REG); - } else if (drive->addressing) { - OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - } else { - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - } - - udma_start(drive, rq); - - return ATA_OP_CONTINUES; -} - -/* - * FIXME: This should be attached to a channel as we can see now! - */ -static int pmac_udma_irq_status(struct ata_device *drive) -{ - int ix, ata4; - volatile struct dbdma_regs *dma; - - /* Can we stuff a pointer to our intf structure in config_data - * or select_data in hwif ? - */ - ix = pmac_ide_find(drive); - if (ix < 0) - return 0; - dma = pmac_ide[ix].dma_regs; - ata4 = (pmac_ide[ix].kind == controller_kl_ata4 || - pmac_ide[ix].kind == controller_kl_ata4_80); - - /* We have to things to deal with here: - * - * - The dbdma won't stop if the command was started but completed with - * an error without transfering all datas. This happens when bad blocks - * are met during a multi-block transfer. - * - * - The dbdma fifo hasn't yet finished flushing to to system memory - * when the disk interrupt occurs. - * - * FIXME: The following *trick* is broken: - * - * The trick here is to increment drive->waiting_for_dma, and return as - * if no interrupt occured. If the counter reach a certain timeout - * value, we then return 1. If we really got the interrupt, it will - * happen right away again. Apple's solution here may be more elegant. - * They issue a DMA channel interrupt (a separate irq line) via a DBDMA - * NOP command just before the STOP, and wait for both the disk and - * DBDMA interrupts to have completed. - */ - - /* If ACTIVE is cleared, the STOP command have passed and - * transfer is complete. - */ - if (!(in_le32(&dma->status) & ACTIVE)) - return 1; - - if (!test_bit(IDE_DMA, drive->channel->active)) - printk(KERN_WARNING "ide%d, ide_dma_test_irq \ - called while not waiting\n", ix); - - /* If dbdma didn't execute the STOP command yet, the - * active bit is still set */ - set_bit(IDE_DMA, drive->channel->active); -// if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { -// printk(KERN_WARNING "ide%d, timeout waiting \ -// for dbdma command stop\n", ix); -// return 1; -// } - udelay(1); - return 0; -} - -static int pmac_udma_setup(struct ata_device *drive, int map) -{ - /* Change this to better match ide-dma.c */ - pmac_ide_check_dma(drive); - ide_toggle_bounce(drive, drive->using_dma); - - return 0; -} -#endif - -static void idepmac_sleep_device(struct ata_device *drive, int i, unsigned base) -{ - int j; - - /* FIXME: We only handle the master IDE disk, we shoud - * try to fix CD-ROMs here - */ - switch (drive->type) { - case ATA_DISK: - /* Spin down the drive */ - outb(drive->select.all, base+0x60); - (void)inb(base+0x60); - udelay(100); - outb(0x0, base+0x30); - outb(0x0, base+0x20); - outb(0x0, base+0x40); - outb(0x0, base+0x50); - outb(0xe0, base+0x70); - outb(0x2, base+0x160); - for (j = 0; j < 10; j++) { - int status; - mdelay(100); - status = inb(base+0x70); - if (!(status & BUSY_STAT) && (status & DRQ_STAT)) - break; - } - break; - case ATA_ROM: - // todo - break; - case ATA_FLOPPY: - // todo - break; - } -} - -#ifdef CONFIG_PMAC_PBOOK -static void __pmac -idepmac_wake_device(struct ata_device *drive, int used_dma) -{ - /* We force the IDE subdriver to check for a media change - * This must be done first or we may lost the condition - * - * Problem: This can schedule. I moved the block device - * wakeup almost late by priority because of that. - */ - if (drive->driver != NULL && ata_ops(drive)->check_media_change) - ata_ops(drive)->check_media_change(drive); - - /* We kick the VFS too (see fix in ide.c revalidate) */ - __check_disk_change(MKDEV(drive->channel->major, (drive->select.b.unit) << PARTN_BITS)); - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - /* We re-enable DMA on the drive if it was active. */ - /* This doesn't work with the CD-ROM in the media-bay, probably - * because of a pending unit attention. The problem if that if I - * clear the error, the filesystem dies. - */ - if (used_dma && !ide_spin_wait_hwgroup(drive)) { - /* Lock HW group */ - set_bit(IDE_BUSY, drive->channel->active); - pmac_ide_check_dma(drive); - clear_bit(IDE_BUSY, drive->channel->active); - spin_unlock_irq(drive->channel->lock); - } -#endif -} - -static void __pmac -idepmac_sleep_interface(int i, unsigned base, int mediabay) -{ - struct device_node* np = pmac_ide[i].node; - - /* We clear the timings */ - pmac_ide[i].timings[0] = 0; - pmac_ide[i].timings[1] = 0; - - /* The media bay will handle itself just fine */ - if (mediabay) - return; - - /* Disable the bus */ - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 0); -} - -static void __pmac -idepmac_wake_interface(int i, unsigned long base, int mediabay) -{ - struct device_node* np = pmac_ide[i].node; - - if (!mediabay) { - /* Revive IDE disk and controller */ - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 1); - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 1); - mdelay(10); - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 0); - } -} - -static void -idepmac_sleep_drive(struct ata_device *drive, int idx, unsigned long base) -{ - /* Wait for HW group to complete operations */ - if (ide_spin_wait_hwgroup(drive)) - // What can we do here ? Wake drive we had already - // put to sleep and return an error ? - return; - else { - /* Lock HW group */ - set_bit(IDE_BUSY, drive->channel->active); - /* Stop the device */ - idepmac_sleep_device(drive, idx, base); - spin_unlock_irq(drive->channel->lock); - } -} - -static void -idepmac_wake_drive(struct ata_device *drive, unsigned long base) -{ - int j; - - /* Reset timings */ - pmac_ide_selectproc(drive); - mdelay(10); - - /* Wait up to 20 seconds for the drive to be ready */ - for (j = 0; j < 200; j++) { - int status; - mdelay(100); - outb(drive->select.all, base + 0x60); - if (inb(base + 0x60) != drive->select.all) - continue; - status = inb(base + 0x70); - if (!(status & BUSY_STAT)) - break; - } - - /* We resume processing on the lock group */ - spin_lock_irq(drive->channel->lock); - clear_bit(IDE_BUSY, drive->channel->active); - if (!list_empty(&drive->queue.queue_head)) - do_ide_request(&drive->queue); - spin_unlock_irq(drive->channel->lock); -} - -/* Note: We support only master drives for now. This will have to be - * improved if we want to handle sleep on the iMacDV where the CD-ROM - * is a slave - */ -static int __pmac -idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) -{ - int i, ret; - unsigned long base; - int big_delay; - - switch (when) { - case PBOOK_SLEEP_REQUEST: - break; - case PBOOK_SLEEP_REJECT: - break; - case PBOOK_SLEEP_NOW: - for (i = 0; i < pmac_ide_count; ++i) { - struct ata_channel *hwif; - int dn; - - if ((base = pmac_ide[i].regbase) == 0) - continue; - - hwif = &ide_hwifs[i]; - for (dn=0; dndrives[dn].present) - continue; - idepmac_sleep_drive(&hwif->drives[dn], i, base); - } - /* Disable irq during sleep */ - disable_irq(pmac_ide[i].irq); - - /* Check if this is a media bay with an IDE device or not - * a media bay. - */ - ret = check_media_bay_by_base(base, MB_CD); - if ((ret == 0) || (ret == -ENODEV)) - idepmac_sleep_interface(i, base, (ret == 0)); - } - break; - case PBOOK_WAKE: - big_delay = 0; - for (i = 0; i < pmac_ide_count; ++i) { - - if ((base = pmac_ide[i].regbase) == 0) - continue; - - /* Make sure we have sane timings */ - sanitize_timings(i); - - /* Check if this is a media bay with an IDE device or not - * a media bay - */ - ret = check_media_bay_by_base(base, MB_CD); - if ((ret == 0) || (ret == -ENODEV)) { - idepmac_wake_interface(i, base, (ret == 0)); - big_delay = 1; - } - - } - /* Let hardware get up to speed */ - if (big_delay) - mdelay(IDE_WAKEUP_DELAY_MS); - - for (i = 0; i < pmac_ide_count; ++i) { - struct ata_channel *hwif; - int used_dma, dn; - int irq_on = 0; - - if ((base = pmac_ide[i].regbase) == 0) - continue; - - hwif = &ide_hwifs[i]; - for (dn=0; dndrives[dn]; - if (!drive->present) - continue; - /* We don't have re-configured DMA yet */ - used_dma = drive->using_dma; - drive->using_dma = 0; - idepmac_wake_drive(drive, base); - if (!irq_on) { - enable_irq(pmac_ide[i].irq); - irq_on = 1; - } - idepmac_wake_device(drive, used_dma); - } - if (!irq_on) - enable_irq(pmac_ide[i].irq); - } - break; - } - return PBOOK_SLEEP_OK; -} -#endif /* CONFIG_PMAC_PBOOK */ diff -Nru a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c --- a/drivers/ide/ide-pnp.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,159 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * This file provides autodetection for ISA PnP IDE interfaces. - * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface. - * - * Copyright (C) 2000 Andrey Panin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example /usr/src/linux/COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -#include - -#ifndef PREPARE_FUNC -#define PREPARE_FUNC(dev) (dev->prepare) -#define ACTIVATE_FUNC(dev) (dev->activate) -#define DEACTIVATE_FUNC(dev) (dev->deactivate) -#endif - -#define DEV_IO(dev, index) (dev->resource[index].start) -#define DEV_IRQ(dev, index) (dev->irq_resource[index].start) - -#define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP") - -/* ISA PnP device table entry */ -struct pnp_dev_t { - unsigned short card_vendor, card_device, vendor, device; - int (*init_fn)(struct pci_dev *dev, int enable); -}; - -/* Generic initialisation function for ISA PnP IDE interface */ -static int __init pnpide_generic_init(struct pci_dev *dev, int enable) -{ - hw_regs_t hw; - int index; - int i; - - if (!enable) - return 0; - - if (!(DEV_IO(dev, 0) && DEV_IO(dev, 1) && DEV_IRQ(dev, 0))) - return 1; - - /* Initialize register access base values. */ - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i) - hw.io_ports[i] = DEV_IO(dev, 0) + i; - hw.io_ports[IDE_CONTROL_OFFSET] = DEV_IO(dev, 1); - - hw.irq = DEV_IRQ(dev, 0); - hw.dma = NO_DMA; - hw.ack_intr = NULL; - - index = ide_register_hw(&hw); - - if (index != -1) { - struct ata_channel *ch; - - ch = &ide_hwifs[index]; - ch->pci_dev = dev; - printk(KERN_INFO "ide%d: %s IDE interface\n", index, DEV_NAME(dev)); - - return 0; - } - - return 1; -} - -/* Add your devices here :)) */ -static struct pnp_dev_t pnp_devices[] __initdata = { - /* Generic ESDI/IDE/ATA compatible hard disk controller */ - { - ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600), - pnpide_generic_init - }, - { 0 } -}; - -#ifdef MODULE -#define NR_PNP_DEVICES 8 -struct pnp_dev_inst { - struct pci_dev *dev; - struct pnp_dev_t *dev_type; -}; -static struct pnp_dev_inst devices[NR_PNP_DEVICES]; -static int pnp_ide_dev_idx = 0; -#endif - -/* - * Probe for ISA PnP IDE interfaces. - */ -void __init pnpide_init(int enable) -{ - struct pci_dev *dev = NULL; - struct pnp_dev_t *dev_type; - - if (!isapnp_present()) - return; - -#ifdef MODULE - /* Module unload, deactivate all registered devices. */ - if (!enable) { - int i; - for (i = 0; i < pnp_ide_dev_idx; i++) { - devices[i].dev_type->init_fn(dev, 0); - - if (DEACTIVATE_FUNC(devices[i].dev)) - DEACTIVATE_FUNC(devices[i].dev)(devices[i].dev); - } - return; - } -#endif - for (dev_type = pnp_devices; dev_type->vendor; dev_type++) { - while ((dev = isapnp_find_dev(NULL, dev_type->vendor, - dev_type->device, dev))) { - - if (dev->active) - continue; - - if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) { - printk(KERN_ERR "ide: %s prepare failed\n", DEV_NAME(dev)); - continue; - } - - if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) { - printk(KERN_ERR "ide: %s activate failed\n", DEV_NAME(dev)); - continue; - } - - /* Call device initialization function */ - if (dev_type->init_fn(dev, 1)) { - if (DEACTIVATE_FUNC(dev)) - DEACTIVATE_FUNC(dev)(dev); - } else { -#ifdef MODULE - /* - * Register device in the array to - * deactivate it on a module unload. - */ - if (pnp_ide_dev_idx >= NR_PNP_DEVICES) - return; - devices[pnp_ide_dev_idx].dev = dev; - devices[pnp_ide_dev_idx].dev_type = dev_type; - pnp_ide_dev_idx++; -#endif - } - } - } -} diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,5651 +0,0 @@ -/* - * Copyright (C) 1995 - 1999 Gadi Oxman - * - * This driver was constructed as a student project in the software laboratory - * of the faculty of electrical engineering in the Technion - Israel's - * Institute Of Technology, with the guide of Avner Lottem and Dr. Ilana David. - * - * It is hereby placed under the terms of the GNU general public license. - * (See linux/COPYING). - * - * Contributors: - * - * Oct 1999 Arnold Niessen, , - * Nov 2000, Jan 2001 Marcel Mol, - * Apr 2001 Willem Riede, - */ - -/* - * FIXME: clean tape->spinlock locking --bzolnier - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -#define NO_LONGER_REQUIRED (1) - -/* - * OnStream support - */ -#define ONSTREAM_DEBUG (0) -#define OS_CONFIG_PARTITION (0xff) -#define OS_DATA_PARTITION (0) -#define OS_PARTITION_VERSION (1) -#define OS_EW 300 -#define OS_ADR_MINREV 2 - -#define OS_DATA_STARTFRAME1 20 -#define OS_DATA_ENDFRAME1 2980 - -/* - * 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; - -/* - * Frame types - */ -#define OS_FRAME_TYPE_FILL (0) -#define OS_FRAME_TYPE_EOD (1 << 0) -#define OS_FRAME_TYPE_MARKER (1 << 1) -#define OS_FRAME_TYPE_HEADER (1 << 3) -#define OS_FRAME_TYPE_DATA (1 << 7) - -/* - * AUX - */ -typedef struct os_aux_s { - __u32 format_id; /* hardware compability AUX is based on */ - char application_sig[4]; /* driver used to write this media */ - __u32 hdwr; /* reserved */ - __u32 update_frame_cntr; /* for configuration frame */ - __u8 frame_type; - __u8 frame_type_reserved; - __u8 reserved_18_19[2]; - os_partition_t partition; - __u8 reserved_36_43[8]; - __u32 frame_seq_num; - __u32 logical_blk_num_high; - __u32 logical_blk_num; - os_dat_t dat; - __u8 reserved188_191[4]; - __u32 filemark_cnt; - __u32 phys_fm; - __u32 last_mark_addr; - __u8 reserved204_223[20]; - - /* - * __u8 app_specific[32]; - * - * Linux specific fields: - */ - __u32 next_mark_addr; /* when known, points to next marker */ - __u8 linux_specific[28]; - - __u8 reserved_256_511[256]; -} os_aux_t; - -typedef struct os_header_s { - char ident_str[8]; - __u8 major_rev; - __u8 minor_rev; - __u8 reserved10_15[6]; - __u8 par_num; - __u8 reserved1_3[3]; - os_partition_t partition; -} os_header_t; - -/* - * OnStream Tape Parameters Page - */ -typedef struct { - unsigned page_code :6; /* Page code - Should be 0x2b */ - unsigned reserved1_6 :1; - unsigned ps :1; - __u8 reserved2; - __u8 density; /* kbpi */ - __u8 reserved3,reserved4; - __u16 segtrk; /* segment of per track */ - __u16 trks; /* tracks per tape */ - __u8 reserved5,reserved6,reserved7,reserved8,reserved9,reserved10; -} onstream_tape_paramtr_page_t; - -/* - * OnStream ADRL frame - */ -#define OS_FRAME_SIZE (32 * 1024 + 512) -#define OS_DATA_SIZE (32 * 1024) -#define OS_AUX_SIZE (512) - -/* - * internal error codes for onstream - */ -#define OS_PART_ERROR 2 -#define OS_WRITE_ERROR 1 - -#include - -/**************************** Tunable parameters *****************************/ - - -/* - * Pipelined mode parameters. - * - * We try to use the minimum number of stages which is enough to - * keep the tape constantly streaming. To accomplish that, we implement - * a feedback loop around the maximum number of stages: - * - * We start from MIN maximum stages (we will not even use MIN stages - * if we don't need them), increment it by RATE*(MAX-MIN) - * whenever we sense that the pipeline is empty, until we reach - * the optimum value or until we reach MAX. - * - * Setting the following parameter to 0 will disable the pipelined mode. - */ -#define IDETAPE_MIN_PIPELINE_STAGES 200 -#define IDETAPE_MAX_PIPELINE_STAGES 400 -#define IDETAPE_INCREASE_STAGES_RATE 20 - -/* - * 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: - * - * 1. Disable logging normal successful operations. - * 2. Disable self-sanity checks. - * 3. Errors will still be logged, of course. - * - * All the #if DEBUG code will be removed some day, when the driver - * is verified to be stable enough. This will make it much more - * esthetic. - */ -#define IDETAPE_DEBUG_INFO 1 -#define IDETAPE_DEBUG_LOG 1 -#define IDETAPE_DEBUG_LOG_VERBOSE 0 -#define IDETAPE_DEBUG_BUGS 1 - -/* - * After each failed packet command we issue a request sense command - * and retry the packet command IDETAPE_MAX_PC_RETRIES times. - * - * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries. - */ -#define IDETAPE_MAX_PC_RETRIES 3 - -/* - * In various places in the driver, we need to allocate storage - * for packet commands and requests, which will remain valid while - * we leave the driver to wait for an interrupt or a timeout event. - */ -#define IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES) - -/* - * Some tape drives require a long irq timeout - */ -#define IDETAPE_WAIT_CMD (60*HZ) - -/* - * The following parameter is used to select the point in the internal - * tape fifo in which we will start to refill the buffer. Decreasing - * the following parameter will improve the system's latency and - * interactive response, while using a high value might improve sytem - * throughput. - */ -#define IDETAPE_FIFO_THRESHOLD 2 - -/* - * DSC polling parameters. - * - * Polling for DSC (a single bit in the status register) is a very - * important function in ide-tape. There are two cases in which we - * poll for DSC: - * - * 1. Before a read/write packet command, to ensure that we - * can transfer data from/to the tape's data buffers, without - * causing an actual media access. In case the tape is not - * ready yet, we take out our request from the device - * request queue, so that ide.c will service requests from - * the other device on the same interface meanwhile. - * - * 2. After the successful initialization of a "media access - * packet command", which is a command which can take a long - * time to complete (it can be several seconds or even an hour). - * - * Again, we postpone our request in the middle to free the bus - * for the other device. The polling frequency here should be - * lower than the read/write frequency since those media access - * commands are slow. We start from a "fast" frequency - - * IDETAPE_DSC_MA_FAST (one second), and if we don't receive DSC - * after IDETAPE_DSC_MA_THRESHOLD (5 minutes), we switch it to a - * lower frequency - IDETAPE_DSC_MA_SLOW (1 minute). - * - * We also set a timeout for the timer, in case something goes wrong. - * The timeout should be longer then the maximum execution time of a - * tape operation. - */ - -/* - * DSC timings. - */ -#define IDETAPE_DSC_RW_MIN 5*HZ/100 /* 50 msec */ -#define IDETAPE_DSC_RW_MAX 40*HZ/100 /* 400 msec */ -#define IDETAPE_DSC_RW_TIMEOUT 2*60*HZ /* 2 minutes */ -#define IDETAPE_DSC_MA_FAST 2*HZ /* 2 seconds */ -#define IDETAPE_DSC_MA_THRESHOLD 5*60*HZ /* 5 minutes */ -#define IDETAPE_DSC_MA_SLOW 30*HZ /* 30 seconds */ -#define IDETAPE_DSC_MA_TIMEOUT 2*60*60*HZ /* 2 hours */ - -/*************************** End of tunable parameters ***********************/ - -/* - * Debugging/Performance analysis - * - * I/O trace support - */ -#define USE_IOTRACE 0 -#if USE_IOTRACE -#include -#define IO_IDETAPE_FIFO 500 -#endif - -/* - * Read/Write error simulation - */ -#define SIMULATE_ERRORS 0 - -/* - * For general magnetic tape device compatibility. - */ -typedef enum { - idetape_direction_none, - idetape_direction_read, - idetape_direction_write -} idetape_chrdev_direction_t; - -/* - * 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 { - struct request rq; /* The corresponding request */ - struct bio *bio; /* The data buffers */ - struct idetape_stage_s *next; /* Pointer to the next stage */ - os_aux_t *aux; /* OnStream aux ptr */ -} idetape_stage_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. - */ -typedef struct { - struct ata_device *drive; - devfs_handle_t de_r, de_n; - - /* - * Since a typical character device operation requires more - * than one packet command, we provide here enough memory - * for the maximum of interconnected packet commands. - * The packet commands are stored in the circular array pc_stack. - * pc_stack_index points to the last used entry, and warps around - * to the start when we get to the last array entry. - * - * pc points to the current processed packet command. - * - * failed_pc points to the last failed packet command, or contains - * NULL if we do not need to retry any packet command. This is - * required since an additional packet command is needed before the - * retry, to get detailed information on what went wrong. - */ - struct atapi_packet_command *pc; /* Current packet command */ - struct atapi_packet_command *failed_pc; /* Last failed packet command */ - struct atapi_packet_command pc_stack[IDETAPE_PC_STACK];/* Packet command stack */ - int pc_stack_index; /* Next free packet command storage space */ - struct request rq_stack[IDETAPE_PC_STACK]; - int rq_stack_index; /* We implement a circular array */ - - /* - * DSC polling variables. - * - * While polling for DSC we use postponed_rq to postpone the - * current request so that ide.c will be able to service - * pending requests on the other device. Note that at most - * we will have only one DSC (usually data transfer) request - * in the device request queue. Additional requests can be - * queued in our internal pipeline, but they will be visible - * to ide.c only one at a time. - */ - struct request *postponed_rq; - unsigned long dsc_polling_start; /* The time in which we started polling for DSC */ - struct timer_list dsc_timer; /* Timer used to poll for dsc */ - unsigned long best_dsc_rw_frequency; /* Read/Write dsc polling frequency */ - unsigned long dsc_polling_frequency; /* The current polling frequency */ - unsigned long dsc_timeout; /* Maximum waiting time */ - - /* - * Read position information - */ - u8 partition; - unsigned int first_frame_position; /* Current block */ - unsigned int last_frame_position; - unsigned int blocks_in_buffer; - - /* - * Last error information - */ - u8 sense_key, asc, ascq; - - /* - * Character device operation - */ - unsigned int minor; - char name[4]; /* device name */ - idetape_chrdev_direction_t chrdev_direction; /* Current character device data transfer direction */ - - /* - * Device information - */ - unsigned short tape_block_size; /* Usually 512 or 1024 bytes */ - int user_bs_factor; - idetape_capabilities_page_t capabilities; /* Copy of the tape's Capabilities and Mechanical Page */ - - /* - * Active data transfer request parameters. - * - * At most, there is only one ide-tape originated data transfer - * request in the device request queue. This allows ide.c to - * easily service requests from the other device when we - * postpone our active request. In the pipelined operation - * mode, we use our internal pipeline structure to hold - * more data requests. - * - * The data buffer size is chosen based on the tape's - * recommendation. - */ - struct request *active_data_request; /* Pointer to the request which is waiting in the device request queue */ - int stage_size; /* Data buffer size (chosen based on the tape's recommendation */ - idetape_stage_t *merge_stage; - int merge_stage_size; - struct bio *bio; - char *b_data; - int b_count; - - /* - * Pipeline parameters. - * - * To accomplish non-pipelined mode, we simply set the following - * variables to zero (or NULL, where appropriate). - */ - int nr_stages; /* Number of currently used stages */ - int nr_pending_stages; /* Number of pending stages */ - int max_stages, min_pipeline, max_pipeline; /* We will not allocate more than this number of stages */ - idetape_stage_t *first_stage; /* The first stage which will be removed from the pipeline */ - idetape_stage_t *active_stage; /* The currently active stage */ - idetape_stage_t *next_stage; /* Will be serviced after the currently active request */ - idetape_stage_t *last_stage; /* New requests will be added to the pipeline here */ - idetape_stage_t *cache_stage; /* Optional free stage which we can use */ - int pages_per_stage; - int excess_bh_size; /* Wasted space in each stage */ - - unsigned long flags; /* Status/Action flags: long for set_bit */ - spinlock_t spinlock; /* protects the ide-tape queue */ - - /* - * Measures average tape speed - */ - unsigned long avg_time; - int avg_size; - int avg_speed; - - atapi_request_sense_result_t sense; /* last sense information */ - - char vendor_id[10]; - char product_id[18]; - char firmware_revision[6]; - int firmware_revision_num; - - int door_locked; /* the door is currently locked */ - - /* - * OnStream flags - */ - int onstream; /* the tape is an OnStream tape */ - int raw; /* OnStream raw access (32.5KB block size) */ - int cur_frames; /* current number of frames in internal buffer */ - int max_frames; /* max number of frames in internal buffer */ - int logical_blk_num; /* logical block number */ - __u16 wrt_pass_cntr; /* write pass counter */ - __u32 update_frame_cntr; /* update frame counter */ - struct completion *waiting; - int onstream_write_error; /* write error recovery active */ - int header_ok; /* header frame verified ok */ - int linux_media; /* reading linux-specifc media */ - int linux_media_version; - char application_sig[5]; /* application signature */ - int filemark_cnt; - int first_mark_addr; - int last_mark_addr; - int eod_frame_addr; - unsigned long cmd_start_time; - unsigned long max_cmd_time; - unsigned capacity; - - /* - * Optimize the number of "buffer filling" - * mode sense commands. - */ - unsigned long last_buffer_fill; /* last time in which we issued fill cmd */ - int req_buffer_fill; /* buffer fill command requested */ - int writes_since_buffer_fill; - int reads_since_buffer_fill; - - /* - * Limit the number of times a request can - * be postponed, to avoid an infinite postpone - * deadlock. - */ - int postpone_cnt; /* request postpone count limit */ - - /* - * Measures number of frames: - * - * 1. written/read to/from the driver pipeline (pipeline_head). - * 2. written/read to/from the tape buffers (bio). - * 3. written/read by the tape to/from the media (tape_head). - */ - int pipeline_head; - int buffer_head; - int tape_head; - int last_tape_head; - - /* - * Speed control at the tape buffers input/output - */ - unsigned long insert_time; - int insert_size; - int insert_speed; - int max_insert_speed; - int measure_insert_time; - - /* - * Measure tape still time, in milliseconds - */ - unsigned long tape_still_time_begin; - int tape_still_time; - - /* - * Speed regulation negative feedback loop - */ - int speed_control; - int pipeline_head_speed, controlled_pipeline_head_speed, uncontrolled_pipeline_head_speed; - int controlled_last_pipeline_head, uncontrolled_last_pipeline_head; - unsigned long uncontrolled_pipeline_head_time, controlled_pipeline_head_time; - int controlled_previous_pipeline_head, uncontrolled_previous_pipeline_head; - unsigned long controlled_previous_head_time, uncontrolled_previous_head_time; - int restart_speed_control_req; - - /* - * 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 - */ - int debug_level; -} idetape_tape_t; - -/* - * Tape door status - */ -#define DOOR_UNLOCKED 0 -#define DOOR_LOCKED 1 -#define DOOR_EXPLICITLY_LOCKED 2 - -/* - * Tape flag bits values. - */ -#define IDETAPE_IGNORE_DSC 0 -#define IDETAPE_ADDRESS_VALID 1 /* 0 When the tape position is unknown */ -#define IDETAPE_BUSY 2 /* Device already opened */ -#define IDETAPE_PIPELINE_ERROR 3 /* Error detected in a pipeline stage */ -#define IDETAPE_DETECT_BS 4 /* Attempt to auto-detect the current user block size */ -#define IDETAPE_FILEMARK 5 /* Currently on a filemark */ -#define IDETAPE_DRQ_INTERRUPT 6 /* DRQ interrupt device */ -#define IDETAPE_READ_ERROR 7 -#define IDETAPE_PIPELINE_ACTIVE 8 /* pipeline active */ - -/* - * 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 - -/* - * Some defines for the SPACE command - */ -#define IDETAPE_SPACE_OVER_FILEMARK 1 -#define IDETAPE_SPACE_TO_EOD 3 - -/* - * Some defines for the LOAD UNLOAD command - */ -#define IDETAPE_LU_LOAD_MASK 1 -#define IDETAPE_LU_RETENSION_MASK 2 -#define IDETAPE_LU_EOT_MASK 4 - -/* - * Special requests for our block device strategy routine. - * - * In order to service a character device command, we add special - * requests to the tail of our block device request queue and wait - * for their completion. - * - */ -#define IDETAPE_FIRST_RQ 90 - -/* - * IDETAPE_PC_RQ is used to queue a packet command in the request queue. - */ -#define IDETAPE_PC_RQ1 90 -#define IDETAPE_PC_RQ2 91 - -/* - * IDETAPE_READ_RQ and IDETAPE_WRITE_RQ are used by our - * character device interface to request read/write operations from - * our block device interface. - */ -#define IDETAPE_READ_RQ 92 -#define IDETAPE_WRITE_RQ 93 -#define IDETAPE_ABORTED_WRITE_RQ 94 -#define IDETAPE_ABORTED_READ_RQ 95 -#define IDETAPE_READ_BUFFER_RQ 96 - -#define IDETAPE_LAST_RQ 96 - -/* - * A macro which can be used to check if a we support a given - * request command. - */ -#define IDETAPE_RQ_CMD(cmd) ((cmd >= IDETAPE_FIRST_RQ) && (cmd <= IDETAPE_LAST_RQ)) - -/* - * Error codes which are returned in rq->errors to the higher part - * of the driver. - */ -#define IDETAPE_ERROR_GENERAL 101 -#define IDETAPE_ERROR_FILEMARK 102 -#define IDETAPE_ERROR_EOD 103 - -/* - * idetape_chrdev_t provides the link between out character device - * interface and our block device interface and the corresponding - * ata_device structure. - */ -typedef struct { - struct ata_device *drive; -} idetape_chrdev_t; - -/* - * READ POSITION packet command - Data Format (From Table 6-57) - */ -typedef struct { - unsigned reserved0_10 :2; /* Reserved */ - unsigned bpu :1; /* Block Position Unknown */ - unsigned reserved0_543 :3; /* Reserved */ - unsigned eop :1; /* End Of Partition */ - unsigned bop :1; /* Beginning Of Partition */ - u8 partition; /* Partition Number */ - u8 reserved2, reserved3; /* Reserved */ - u32 first_block; /* First Block Location */ - u32 last_block; /* Last Block Location (Optional) */ - u8 reserved12; /* Reserved */ - u8 blocks_in_buffer[3]; /* Blocks In Buffer - (Optional) */ - 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. - */ -#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. - * Additional state variables are defined in our ata_device structure. - */ -static idetape_chrdev_t idetape_chrdevs[MAX_HWIFS * MAX_DRIVES]; -static int idetape_chrdev_present = 0; - -#if IDETAPE_DEBUG_LOG_VERBOSE - -/* - * DO NOT REMOVE, BUILDING A VERBOSE DEBUG SCHEME FOR ATAPI - */ - -char *idetape_sense_key_verbose(u8 idetape_sense_key) -{ - switch (idetape_sense_key) { - default: { - char buf[22]; - sprintf(buf, "IDETAPE_SENSE (0x%02x)", idetape_sense_key); - return(buf); - } - - } -} - -char *idetape_command_key_verbose(u8 idetape_command_key) -{ - switch (idetape_command_key) { - case IDETAPE_TEST_UNIT_READY_CMD: return("TEST_UNIT_READY_CMD"); - case IDETAPE_REWIND_CMD: return("REWIND_CMD"); - case IDETAPE_REQUEST_SENSE_CMD: return("REQUEST_SENSE_CMD"); - case IDETAPE_READ_CMD: return("READ_CMD"); - case IDETAPE_WRITE_CMD: return("WRITE_CMD"); - case IDETAPE_WRITE_FILEMARK_CMD: return("WRITE_FILEMARK_CMD"); - case IDETAPE_SPACE_CMD: return("SPACE_CMD"); - case IDETAPE_INQUIRY_CMD: return("INQUIRY_CMD"); - case IDETAPE_ERASE_CMD: return("ERASE_CMD"); - case IDETAPE_MODE_SENSE_CMD: return("MODE_SENSE_CMD"); - case IDETAPE_MODE_SELECT_CMD: return("MODE_SELECT_CMD"); - case IDETAPE_LOAD_UNLOAD_CMD: return("LOAD_UNLOAD_CMD"); - case IDETAPE_PREVENT_CMD: return("PREVENT_CMD"); - case IDETAPE_LOCATE_CMD: return("LOCATE_CMD"); - case IDETAPE_READ_POSITION_CMD: return("READ_POSITION_CMD"); - case IDETAPE_READ_BUFFER_CMD: return("READ_BUFFER_CMD"); - case IDETAPE_SET_SPEED_CMD: return("SET_SPEED_CMD"); - default: { - char buf[20]; - sprintf(buf, "CMD (0x%02x)", idetape_command_key); - return(buf); - } - } -} -#endif /* IDETAPE_DEBUG_LOG_VERBOSE */ - -/* - * Function declarations - * - */ -static void idetape_onstream_mode_sense_tape_parameter_page(struct ata_device *drive, int debug); -static int idetape_chrdev_release (struct inode *inode, struct file *filp); -static void idetape_write_release (struct inode *inode); - -static void idetape_input_buffers(struct ata_device *drive, - struct atapi_packet_command *pc, - unsigned int bcount) -{ - struct bio *bio = pc->bio; - int count; - - while (bcount) { -#if IDETAPE_DEBUG_BUGS - if (bio == NULL) { - printk (KERN_ERR "ide-tape: bio == NULL in idetape_input_buffers\n"); - atapi_discard_data(drive, bcount); - return; - } -#endif - count = min(bio->bi_size - pc->b_count, bcount); - atapi_read(drive, bio_data(bio) + pc->b_count, count); - bcount -= count; - pc->b_count += bio->bi_size; - if (pc->b_count == bio->bi_size) { - bio = bio->bi_next; - if (bio) - pc->b_count = 0; - } - } - pc->bio = bio; -} - -static void idetape_output_buffers(struct ata_device *drive, - struct atapi_packet_command *pc, - unsigned int bcount) -{ - struct bio *bio = pc->bio; - int count; - - while (bcount) { -#if IDETAPE_DEBUG_BUGS - if (bio == NULL) { - printk (KERN_ERR "ide-tape: bio == NULL in idetape_output_buffers\n"); - return; - } -#endif - count = min(pc->b_count, bcount); - atapi_write(drive, bio_data(bio), count); - bcount -= count; - pc->b_data += count; - pc->b_count -= count; - if (!pc->b_count) { - pc->bio = bio = bio->bi_next; - if (bio) { - pc->b_data = bio_data(bio); - pc->b_count = bio->bi_size; - } - } - } -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static void idetape_update_buffers(struct atapi_packet_command *pc) -{ - struct bio *bio = pc->bio; - int count; - unsigned int bcount = pc->actually_transferred; - - if (test_bit(PC_WRITING, &pc->flags)) - return; - while (bcount) { -# if IDETAPE_DEBUG_BUGS - if (bio == NULL) { - printk (KERN_ERR "ide-tape: bio == NULL in idetape_update_buffers\n"); - return; - } -# endif - count = min(bio->bi_size, bcount); - pc->b_count = count; - if (pc->b_count == bio->bi_size) - bio = bio->bi_next; - bcount -= count; - } - pc->bio = bio; -} -#endif - -/* - * idetape_next_pc_storage returns a pointer to a place in which we can - * safely store a packet command, even though we intend to leave the - * driver. A storage space for a maximum of IDETAPE_PC_STACK packet - * commands is allocated at initialization time. - */ -static struct atapi_packet_command *idetape_next_pc_storage(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: pc_stack_index=%d\n",tape->pc_stack_index); -#endif /* IDETAPE_DEBUG_LOG */ - if (tape->pc_stack_index==IDETAPE_PC_STACK) - tape->pc_stack_index=0; - return (&tape->pc_stack[tape->pc_stack_index++]); -} - -/* - * idetape_next_rq_storage is used along with idetape_next_pc_storage. - * Since we queue packet commands in the request queue, we need to - * allocate a request, along with the allocation of a packet command. - */ - -/************************************************************** - * * - * This should get fixed to use kmalloc(.., GFP_ATOMIC) * - * followed later on by kfree(). -ml * - * * - **************************************************************/ - -static struct request *idetape_next_rq_storage(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: rq_stack_index=%d\n",tape->rq_stack_index); -#endif - if (tape->rq_stack_index==IDETAPE_PC_STACK) - tape->rq_stack_index=0; - return (&tape->rq_stack[tape->rq_stack_index++]); -} - -/* - * idetape_analyze_error is called on each failed packet command retry - * to analyze the request sense. We currently do not utilize this - * information. - */ -static void idetape_analyze_error(struct ata_device *drive, atapi_request_sense_result_t *result) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command *pc = tape->failed_pc; - - tape->sense = *result; - tape->sense_key = result->sense_key; - tape->asc = result->asc; - tape->ascq = result->ascq; -#if IDETAPE_DEBUG_LOG - /* - * 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); -# if IDETAPE_DEBUG_LOG_VERBOSE - if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n", - idetape_command_key_verbose(pc->c[0]), - result->sense_key, - result->asc, - result->ascq); -# endif -#endif - - if (tape->onstream && result->sense_key == 2 && result->asc == 0x53 && result->ascq == 2) { - clear_bit(PC_DMA_ERROR, &pc->flags); - /* FIXME: we should use timeouts here */ - mdelay(HZ / 2 * 1000); - return; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - - /* - * 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)); - idetape_update_buffers(pc); - } -#endif - if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) { - 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)) { - 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) { - pc->error = IDETAPE_ERROR_EOD; - set_bit(PC_ABORT, &pc->flags); - } - if (!test_bit (PC_ABORT, &pc->flags) && (tape->onstream || pc->actually_transferred)) - pc->retries = IDETAPE_MAX_PC_RETRIES + 1; - } -} - -static void idetape_abort_pipeline(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage = tape->next_stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name); -#endif - while (stage) { - if (stage->rq.flags == IDETAPE_WRITE_RQ) - stage->rq.flags = IDETAPE_ABORTED_WRITE_RQ; - else if (stage->rq.flags == IDETAPE_READ_RQ) - stage->rq.flags = IDETAPE_ABORTED_READ_RQ; - stage = stage->next; - } -} - -/* - * idetape_active_next_stage will declare the next stage as "active". - */ -static void idetape_active_next_stage(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage = tape->next_stage; - struct request *rq = &stage->rq; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_active_next_stage\n"); -#endif -#if IDETAPE_DEBUG_BUGS - if (stage == NULL) { - printk (KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n"); - return; - } -#endif - - rq->buffer = NULL; - rq->bio = stage->bio; - tape->active_data_request = rq; - tape->active_stage = stage; - tape->next_stage = stage->next; -} - -/* - * idetape_increase_max_pipeline_stages is a part of the feedback - * loop which tries to find the optimum number of stages. In the - * feedback loop, we are starting from a minimum maximum number of - * stages, and if we sense that the pipeline is empty, we try to - * increase it, until we reach the user compile time memory limit. - */ -static void idetape_increase_max_pipeline_stages(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int increase = (tape->max_pipeline - tape->min_pipeline) / 10; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n"); -#endif - - tape->max_stages += increase; - tape->max_stages = max(tape->max_stages, tape->min_pipeline); - tape->max_stages = min(tape->max_stages, tape->max_pipeline); -} - -/* - * idetape_kfree_stage calls kfree to completely free a stage, along with - * its related buffers. - */ -static void __idetape_kfree_stage (idetape_stage_t *stage) -{ - struct bio *prev_bio, *bio = stage->bio; - int size; - - while (bio != NULL) { - if (bio_data(bio) != NULL) { - size = (int) bio->bi_size; - while (size > 0) { - free_page ((unsigned long) bio_data(bio)); - size -= PAGE_SIZE; - bio->bi_size += PAGE_SIZE; - } - } - prev_bio = bio; - bio = bio->bi_next; - kfree (prev_bio); - } - kfree (stage); -} - -static void idetape_kfree_stage (idetape_tape_t *tape, idetape_stage_t *stage) -{ - __idetape_kfree_stage (stage); -} - -/* - * idetape_remove_stage_head removes tape->first_stage from the pipeline. - * The caller should avoid race conditions. - */ -static void idetape_remove_stage_head(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n"); -#endif -#if IDETAPE_DEBUG_BUGS - if (tape->first_stage == NULL) { - printk (KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n"); - return; - } - if (tape->active_stage == tape->first_stage) { - printk (KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n"); - return; - } -#endif - 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_end_request is used to finish servicing a request, and to - * insert a pending pipeline request into the main device queue. - */ -static int idetape_end_request(struct ata_device *drive, struct request *rq, int uptodate) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags, flags2; - int error; - int remove_stage = 0; -#if ONSTREAM_DEBUG - idetape_stage_t *stage; - os_aux_t *aux; - unsigned char *p; -#endif - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_end_request\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - switch (uptodate) { - case 0: error = IDETAPE_ERROR_GENERAL; break; - case 1: error = 0; break; - default: error = uptodate; - } - rq->errors = error; - if (error) - tape->failed_pc = NULL; - - spin_lock_irqsave(&tape->spinlock, flags); - if (tape->active_data_request == rq) { /* The request was a pipelined data transfer request */ - tape->active_stage = NULL; - tape->active_data_request = NULL; - tape->nr_pending_stages--; - if (rq->flags == IDETAPE_WRITE_RQ) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) { - if (tape->onstream) { - stage = tape->first_stage; - aux = stage->aux; - p = bio_data(stage->bio); - if (ntohl(aux->logical_blk_num) < 11300 && ntohl(aux->logical_blk_num) > 11100) - printk(KERN_INFO "ide-tape: finished writing logical blk %u (data %x %x %x %x)\n", ntohl(aux->logical_blk_num), *p++, *p++, *p++, *p++); - } - } -#endif - if (tape->onstream && !tape->raw) { - if (tape->first_frame_position == OS_DATA_ENDFRAME1) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: %s: skipping over config parition..\n", tape->name); -#endif - tape->onstream_write_error = OS_PART_ERROR; - if (tape->waiting) - complete(tape->waiting); - } - } - remove_stage = 1; - if (error) { - set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - if (error == IDETAPE_ERROR_EOD) - idetape_abort_pipeline (drive); - if (tape->onstream && !tape->raw && error == IDETAPE_ERROR_GENERAL && tape->sense.sense_key == 3) { - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name); - tape->onstream_write_error = OS_WRITE_ERROR; - remove_stage = 0; - tape->nr_pending_stages++; - tape->next_stage = tape->first_stage; - rq->current_nr_sectors = rq->nr_sectors; - if (tape->waiting) - complete(tape->waiting); - } - } - } else if (rq->flags == IDETAPE_READ_RQ) { - if (error == IDETAPE_ERROR_EOD) { - set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - idetape_abort_pipeline(drive); - } - } - if (tape->next_stage != NULL && !tape->onstream_write_error) { - idetape_active_next_stage (drive); - - /* - * Insert the next request into the request queue. - */ - ide_do_drive_cmd(drive, tape->active_data_request, ide_end); - } else if (!error) { - if (!tape->onstream) - idetape_increase_max_pipeline_stages (drive); - } - } - - /* FIXME: replace tape->spinlock with channel->spinlock --bzolnier */ - spin_lock_irqsave(drive->channel->lock, flags2); - - blkdev_dequeue_request(rq); - drive->rq = NULL; - end_that_request_last(rq); - - spin_unlock_irqrestore(drive->channel->lock, flags2); - - if (remove_stage) - idetape_remove_stage_head(drive); - if (tape->active_data_request == NULL) - clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - spin_unlock_irqrestore(&tape->spinlock, flags); - - return 0; -} - -static void idetape_request_sense_callback(struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n"); -#endif - if (!tape->pc->error) { - idetape_analyze_error (drive, (atapi_request_sense_result_t *) tape->pc->buffer); - idetape_end_request(drive, rq, 1); - } else { - printk (KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); - idetape_end_request(drive, rq, 0); - } -} - -static void idetape_create_request_sense_cmd(struct atapi_packet_command *pc) -{ - atapi_init_pc(pc); - pc->c[0] = IDETAPE_REQUEST_SENSE_CMD; - pc->c[4] = 20; - pc->request_transfer = 18; - pc->callback = &idetape_request_sense_callback; -} - -/* - * idetape_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. - * - * idetape_queue_pc_head is called from the request handling part of - * the driver (the "bottom" part). Safe storage for the request should - * be allocated with idetape_next_pc_storage and idetape_next_rq_storage - * before calling idetape_queue_pc_head. - * - * Memory for those requests is pre-allocated at initialization time, and - * is limited to IDETAPE_PC_STACK requests. We assume that we have enough - * space for the maximum possible number of inter-dependent packet commands. - * - * The higher level of the driver - The ioctl handler and the character - * device handling functions should queue request to the lower level part - * and wait for their completion using idetape_queue_pc_tail or - * idetape_queue_rw_tail. - */ -static void idetape_queue_pc_head(struct ata_device *drive, struct atapi_packet_command *pc, struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->buffer = (char *) pc; - rq->flags = IDETAPE_PC_RQ1; - ide_do_drive_cmd(drive, rq, ide_preempt); -} - -/* - * idetape_retry_pc is called when an error was detected during the - * last packet command. We queue a request sense packet command in - * the head of the request list. - */ -static void idetape_retry_pc(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command *pc; - struct request *rq; - atapi_error_reg_t error; - - error.all = IN_BYTE (IDE_ERROR_REG); - pc = idetape_next_pc_storage (drive); - rq = idetape_next_rq_storage (drive); - idetape_create_request_sense_cmd (pc); - set_bit (IDETAPE_IGNORE_DSC, &tape->flags); - idetape_queue_pc_head (drive, pc, rq); -} - -/* - * idetape_postpone_request postpones the current request so that - * ide.c will be able to service requests from another device on - * the same interface while we are polling for DSC. - */ -static void idetape_postpone_request(struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: idetape_postpone_request\n"); -#endif - tape->postponed_rq = rq; - /* FIXME: we should use timeouts here */ - mdelay(tape->dsc_polling_frequency * 1000); -} - -/* - * idetape_pc_intr is the usual interrupt handler which will be called - * during a packet command. We will transfer some of the data (as - * requested by the drive) and will re-point interrupt handler to us. - * When data transfer is finished, we will act according to the - * algorithm described before idetape_issue_packet_command. - * - */ -static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - atapi_status_reg_t status; - atapi_bcount_reg_t bcount; - atapi_ireason_reg_t ireason; - struct atapi_packet_command *pc = tape->pc; - - unsigned int temp; - unsigned long cmd_time; -#if SIMULATE_ERRORS - static int error_sim_count = 0; -#endif - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_pc_intr interrupt handler\n"); -#endif - - ata_status(drive, 0, 0); - status.all = drive->status; /* Clear the interrupt */ - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - if (udma_stop(drive)) { - /* - * A DMA error is sometimes expected. For example, - * if the tape is crossing a filemark during a - * READ command, it will issue an irq and position - * itself before the filemark, so that only a partial - * data transfer will occur (which causes the DMA - * error). In that case, we will later ask the tape - * how much bytes of the original request were - * actually transferred (we can't receive that - * information from the DMA engine on most chipsets). - */ - set_bit (PC_DMA_ERROR, &pc->flags); - } else if (!status.b.check) { - pc->actually_transferred = pc->request_transfer; - idetape_update_buffers (pc); - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: DMA finished\n"); -#endif - } -#endif - - if (!status.b.drq) { /* No more interrupts */ - cmd_time = (jiffies - tape->cmd_start_time) * 1000 / HZ; - tape->max_cmd_time = max(cmd_time, tape->max_cmd_time); -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred); -#endif - clear_bit(PC_DMA_IN_PROGRESS, &pc->flags); - - local_irq_enable(); - -#if SIMULATE_ERRORS - if ((pc->c[0] == IDETAPE_WRITE_CMD || pc->c[0] == IDETAPE_READ_CMD) && (++error_sim_count % 100) == 0) { - printk(KERN_INFO "ide-tape: %s: simulating error\n", tape->name); - status.b.check = 1; - } -#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 IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name); -#endif - if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-tape: I/O error in request sense command\n"); - return ATA_OP_FINISHED; - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: [cmd %x]: check condition\n", pc->c[0]); -#endif - idetape_retry_pc(drive); /* Retry operation */ - return ATA_OP_FINISHED; - } - pc->error = 0; - if (!tape->onstream && test_bit (PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { /* Media access command */ - tape->dsc_polling_start = jiffies; - tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST; - tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT; - idetape_postpone_request(drive, rq); /* Allow ide.c to handle other requests */ - - return ATA_OP_FINISHED; - } - if (tape->failed_pc == pc) - tape->failed_pc = NULL; - pc->callback(drive, rq); /* Command finished - Call the callback function */ - return ATA_OP_FINISHED; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n"); - printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); - udma_enable(drive, 0, 1); - - return ATA_OP_FINISHED; - } -#endif - - bcount.b.high = IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ - bcount.b.low = IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all = IN_BYTE (IDE_IREASON_REG); - - if (ireason.b.cod) { - printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); - - return ATA_OP_FINISHED; - } - if (ireason.b.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"); - printk (KERN_ERR "ide-tape: but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write"); - - return ATA_OP_FINISHED; - } - if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ - temp = pc->actually_transferred + bcount.all; - 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"); - atapi_discard_data (drive, bcount.all); - ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); - - return ATA_OP_CONTINUES; - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n"); -#endif - } - } - if (test_bit (PC_WRITING, &pc->flags)) { - if (pc->bio != NULL) - idetape_output_buffers (drive, pc, bcount.all); - else - atapi_write(drive,pc->current_position,bcount.all); /* Write the current buffer */ - } else { - if (pc->bio != NULL) - idetape_input_buffers (drive, pc, bcount.all); - else - atapi_read(drive,pc->current_position,bcount.all); /* Read the current buffer */ - } - pc->actually_transferred += bcount.all; /* Update the current position */ - pc->current_position+=bcount.all; -#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); -#endif - ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ - - return ATA_OP_CONTINUES; -} - -/* - * Packet Command Interface - * - * The current Packet Command is available in tape->pc, and will not - * change until we finish handling it. Each packet command is associated - * with a callback function that will be called when the command is - * finished. - * - * The handling will be done in three stages: - * - * 1. idetape_issue_packet_command will send the packet command to the - * drive, and will set the interrupt handler to idetape_pc_intr. - * - * 2. On each interrupt, idetape_pc_intr will be called. This step - * will be repeated until the device signals us that no more - * interrupts will be issued. - * - * 3. ATAPI Tape media access commands have immediate status with a - * delayed process. In case of a successful initiation of a - * media access packet command, the DSC bit will be set when the - * actual execution of the command is finished. - * Since the tape drive will not issue an interrupt, we have to - * poll for this event. In this case, we define the request as - * "low priority request" by setting rq_status to - * IDETAPE_RQ_POSTPONED, set a timer to poll for DSC and exit - * the driver. - * - * ide.c will then give higher priority to requests which - * originate from the other device, until will change rq_status - * to RQ_ACTIVE. - * - * 4. When the packet command is finished, it will be checked for errors. - * - * 5. In case an error was found, we queue a request sense packet command - * in front of the request queue and retry the operation up to - * IDETAPE_MAX_PC_RETRIES times. - * - * 6. In case no error was found, or we decided to give up and not - * to retry again, the callback function will be called and then - * we will handle the next request. - * - */ -static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command *pc = tape->pc; - atapi_ireason_reg_t ireason; - int retries = 100; - int ret; - - ret = ata_status_poll(drive, DRQ_STAT, BUSY_STAT, WAIT_READY, rq); - if (ret != ATA_OP_READY) { - printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); - - return ret; - } - - ireason.all = IN_BYTE (IDE_IREASON_REG); - - while (retries-- && (!ireason.b.cod || ireason.b.io)) { - printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n"); - udelay(100); - ireason.all = IN_BYTE(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; - } - } - - if (!ireason.b.cod || ireason.b.io) { - printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n"); - ret = ATA_OP_FINISHED; - } else { - tape->cmd_start_time = jiffies; - ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ - atapi_write(drive,pc->c,12); /* Send the actual packet */ - ret = ATA_OP_CONTINUES; - } - - return ret; -} - -static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, - struct request *rq, struct atapi_packet_command *pc) -{ - idetape_tape_t *tape = drive->driver_data; - atapi_bcount_reg_t bcount; - int dma_ok = 0; - -#if IDETAPE_DEBUG_BUGS - if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - 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) - tape->failed_pc = pc; - tape->pc = pc; /* Set the current packet command */ - - if (pc->retries > IDETAPE_MAX_PC_RETRIES || test_bit(PC_ABORT, &pc->flags)) { - /* - * We will "abort" retrying a packet command in case - * a legitimate error code was received (crossing a - * filemark, or DMA error in the end of media, for - * example). - */ - if (!test_bit (PC_ABORT, &pc->flags)) { - if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && tape->sense_key == 2 && - tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) { - printk (KERN_ERR "ide-tape: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", - tape->name, pc->c[0], tape->sense_key, tape->asc, tape->ascq); - if (tape->onstream && pc->c[0] == IDETAPE_READ_CMD && tape->sense_key == 3 && tape->asc == 0x11) /* AJN-1: 11 should be 0x11 */ - printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name); - } - pc->error = IDETAPE_ERROR_GENERAL; /* Giving up */ - } - tape->failed_pc = NULL; - pc->callback(drive, rq); - return ATA_OP_FINISHED; - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Retry number - %d\n", pc->retries); -#endif - - pc->retries++; - pc->actually_transferred = 0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; - bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */ - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); - udma_enable(drive, 0, 1); - } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok = udma_init(drive, rq); -#endif - - ata_irq_enable(drive, 1); - OUT_BYTE (dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high, IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low, IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all, IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit(PC_DMA_IN_PROGRESS, &pc->flags); - udma_start(drive, rq); - } -#endif - if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - ata_set_handler(drive, idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - - return ATA_OP_CONTINUES; - } else { - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - return idetape_transfer_pc(drive, rq); - } -} - -/* - * General packet command callback function. - */ -static void idetape_pc_callback(struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_pc_callback\n"); -#endif - - idetape_end_request(drive, rq, tape->pc->error ? 0 : 1); -} - -/* - * A mode sense command is used to "sense" tape parameters. - */ -static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, u8 page_code) -{ - atapi_init_pc(pc); - pc->c[0] = IDETAPE_MODE_SENSE_CMD; - if (page_code != IDETAPE_BLOCK_DESCRIPTOR) - pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors */ - pc->c[2] = page_code; - pc->c[3] = 255; /* Don't limit the returned information */ - pc->c[4] = 255; /* (We will just discard data in that case) */ - if (page_code == IDETAPE_BLOCK_DESCRIPTOR) - pc->request_transfer = 12; - else if (page_code == IDETAPE_CAPABILITIES_PAGE) - pc->request_transfer = 24; - else - pc->request_transfer = 50; - pc->callback = idetape_pc_callback; -} - -static void idetape_onstream_buffer_fill_callback (struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - - tape->max_frames = tape->pc->buffer[4 + 2]; - tape->cur_frames = tape->pc->buffer[4 + 3]; - if (tape->chrdev_direction == idetape_direction_write) - tape->tape_head = tape->buffer_head - tape->cur_frames; - else - tape->tape_head = tape->buffer_head + tape->cur_frames; - if (tape->tape_head != tape->last_tape_head) { - tape->last_tape_head = tape->tape_head; - tape->tape_still_time_begin = jiffies; - if (tape->tape_still_time > 200) - tape->measure_insert_time = 1; - } - tape->tape_still_time = (jiffies - tape->tape_still_time_begin) * 1000 / HZ; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", tape->cur_frames, tape->max_frames); -#endif - idetape_end_request(drive, rq, tape->pc->error ? 0 : 1); -} - -static void idetape_queue_onstream_buffer_fill(struct ata_device *drive) -{ - struct atapi_packet_command *pc; - struct request *rq; - - pc = idetape_next_pc_storage (drive); - rq = idetape_next_rq_storage (drive); - idetape_create_mode_sense_cmd (pc, IDETAPE_BUFFER_FILLING_PAGE); - pc->callback = idetape_onstream_buffer_fill_callback; - idetape_queue_pc_head (drive, pc, rq); -} - -static void calculate_speeds(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int full = 125, empty = 75; - - if (jiffies > tape->controlled_pipeline_head_time + 120 * HZ) { - tape->controlled_previous_pipeline_head = tape->controlled_last_pipeline_head; - tape->controlled_previous_head_time = tape->controlled_pipeline_head_time; - tape->controlled_last_pipeline_head = tape->pipeline_head; - tape->controlled_pipeline_head_time = jiffies; - } - if (jiffies > tape->controlled_pipeline_head_time + 60 * HZ) - tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_last_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_pipeline_head_time); - else if (jiffies > tape->controlled_previous_head_time) - tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_previous_head_time); - - if (tape->nr_pending_stages < tape->max_stages /*- 1 */) { /* -1 for read mode error recovery */ - if (jiffies > tape->uncontrolled_previous_head_time + 10 * HZ) { - tape->uncontrolled_pipeline_head_time = jiffies; - tape->uncontrolled_pipeline_head_speed = (tape->pipeline_head - tape->uncontrolled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->uncontrolled_previous_head_time); - } - } else { - tape->uncontrolled_previous_head_time = jiffies; - tape->uncontrolled_previous_pipeline_head = tape->pipeline_head; - if (jiffies > tape->uncontrolled_pipeline_head_time + 30 * HZ) { - tape->uncontrolled_pipeline_head_time = jiffies; - } - } - tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed, tape->controlled_pipeline_head_speed); - if (tape->speed_control == 0) { - tape->max_insert_speed = 5000; - } else if (tape->speed_control == 1) { - if (tape->nr_pending_stages >= tape->max_stages / 2) - tape->max_insert_speed = tape->pipeline_head_speed + - (1100 - tape->pipeline_head_speed) * 2 * (tape->nr_pending_stages - tape->max_stages / 2) / tape->max_stages; - else - tape->max_insert_speed = 500 + - (tape->pipeline_head_speed - 500) * 2 * tape->nr_pending_stages / tape->max_stages; - if (tape->nr_pending_stages >= tape->max_stages * 99 / 100) - tape->max_insert_speed = 5000; - } else if (tape->speed_control == 2) { - tape->max_insert_speed = tape->pipeline_head_speed * empty / 100 + - (tape->pipeline_head_speed * full / 100 - tape->pipeline_head_speed * empty / 100) * tape->nr_pending_stages / tape->max_stages; - } else - tape->max_insert_speed = tape->speed_control; - tape->max_insert_speed = max(tape->max_insert_speed, 500); -} - -static void idetape_media_access_finished(struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command *pc = tape->pc; - atapi_status_reg_t status; - - if (tape->onstream) - printk(KERN_INFO "ide-tape: bug: onstream, media_access_finished\n"); - ata_status(drive, 0, 0); - status.all = drive->status; - if (status.b.dsc) { - if (status.b.check) { /* Error detected */ - printk (KERN_ERR "ide-tape: %s: I/O error, ",tape->name); - idetape_retry_pc(drive); /* Retry operation */ - return; - } - pc->error = 0; - if (tape->failed_pc == pc) - tape->failed_pc = NULL; - } else { - pc->error = IDETAPE_ERROR_GENERAL; - tape->failed_pc = NULL; - } - pc->callback(drive, rq); -} - -static void idetape_rw_callback(struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - int blocks = tape->pc->actually_transferred / tape->tape_block_size; - - tape->avg_size += blocks * tape->tape_block_size; - tape->insert_size += blocks * tape->tape_block_size; - if (tape->insert_size > 1024 * 1024) - tape->measure_insert_time = 1; - if (tape->measure_insert_time) { - tape->measure_insert_time = 0; - tape->insert_time = jiffies; - tape->insert_size = 0; - } - if (jiffies > tape->insert_time) - tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - if (jiffies - tape->avg_time >= HZ) { - tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024; - tape->avg_size = 0; - tape->avg_time = jiffies; - } - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_rw_callback\n"); -#endif - - tape->first_frame_position += blocks; - rq->current_nr_sectors -= blocks; - - if (!tape->pc->error) - idetape_end_request(drive, rq, 1); - else - idetape_end_request(drive, rq, tape->pc->error); -} - -static void idetape_create_read_cmd(idetape_tape_t *tape, - struct atapi_packet_command *pc, - unsigned int length, struct bio *bio) -{ - struct bio *p = bio; - struct bio_vec *bv = bio_iovec(p); - atapi_init_pc(pc); - pc->c[0] = IDETAPE_READ_CMD; - put_unaligned (htonl (length), (unsigned int *) &pc->c[1]); - pc->c[1] = 1; - pc->callback = idetape_rw_callback; - pc->bio = bio; - bv->bv_len = 0; - pc->buffer = NULL; - if (tape->onstream) { - while (p) { - bv->bv_len = 0; - p = p->bi_next; - } - } - if (!tape->onstream) { - pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; - if (pc->request_transfer == tape->stage_size) - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else { - if (length) { - pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else - pc->request_transfer = 0; - } -} - -static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, - struct atapi_packet_command *pc, - unsigned int length, struct bio *bio) -{ - int size = 32768; - - struct bio *p = bio; - atapi_init_pc(pc); - pc->c[0] = IDETAPE_READ_BUFFER_CMD; - pc->c[1] = IDETAPE_RETRIEVE_FAULTY_BLOCK; - pc->c[7] = size >> 8; - pc->c[8] = size & 0xff; - pc->callback = idetape_pc_callback; - pc->bio = bio; - atomic_set(&bio->bi_cnt, 0); - pc->buffer = NULL; - while (p) { - p->bi_size = 0; - p = p->bi_next; - } - pc->request_transfer = pc->buffer_size = size; -} - -static void idetape_create_write_cmd(idetape_tape_t *tape, - struct atapi_packet_command *pc, - unsigned int length, struct bio *bio) -{ - struct bio *p = bio; - struct bio_vec *bv= bio_iovec(p); - atapi_init_pc(pc); - pc->c[0] = IDETAPE_WRITE_CMD; - put_unaligned (htonl (length), (unsigned int *) &pc->c[1]); - pc->c[1] = 1; - pc->callback = idetape_rw_callback; - set_bit (PC_WRITING, &pc->flags); - if (tape->onstream) { - while (p) { - bv->bv_len = p->bi_size; - p = p->bi_next; - } - } - pc->bio = bio; - pc->b_data = bio_data(bio); - pc->b_count = bio->bi_size; - pc->buffer = NULL; - if (!tape->onstream) { - pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; - if (pc->request_transfer == tape->stage_size) - set_bit (PC_DMA_RECOMMENDED, &pc->flags); - } else { - if (length) { - pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit (PC_DMA_RECOMMENDED, &pc->flags); - } else - pc->request_transfer = 0; - } -} - -/* - * This is our request handling function. - */ -static ide_startstop_t idetape_do_request(struct ata_device *drive, struct request *rq, sector_t block) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command *pc; - struct request *postponed_rq = tape->postponed_rq; - atapi_status_reg_t status; - -#if IDETAPE_DEBUG_LOG -/* if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: rq_status: %d, rq_dev: %u, cmd: %ld, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->flags,rq->errors); */ - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); -#endif - - if (!IDETAPE_RQ_CMD (rq->flags)) { - /* - * We do not support buffer cache originated requests. - */ - printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%ld)\n", drive->name, rq->flags); - ata_end_request(drive, rq, 0, 0); /* Let the common code handle it */ - return ATA_OP_FINISHED; - } - - /* - * Retry a failed packet command - */ - if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - - return idetape_issue_packet_command(drive, rq, tape->failed_pc); - } -#if IDETAPE_DEBUG_BUGS - if (postponed_rq != NULL) - if (rq != postponed_rq) { - printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n"); - - idetape_end_request(drive, rq, 0); - - return ATA_OP_FINISHED; - } -#endif - - tape->postponed_rq = NULL; - - /* - * If the tape is still busy, postpone our request and service - * the other device meanwhile. - */ - ata_status(drive, 0, 0); - status.all = drive->status; - - /* - * The OnStream tape drive doesn't support DSC. Assume - * that DSC is always set. - */ - if (tape->onstream) - status.b.dsc = 1; - if (!drive->dsc_overlap && rq->flags != IDETAPE_PC_RQ2) - set_bit(IDETAPE_IGNORE_DSC, &tape->flags); - - /* - * For the OnStream tape, check the current status of the tape - * internal buffer using data gathered from the buffer fill - * mode page, and postpone our request, effectively "disconnecting" - * from the IDE bus, in case the buffer is full (writing) or - * empty (reading), and there is a danger that our request will - * hold the IDE bus during actual media access. - */ - if (tape->tape_still_time > 100 && tape->tape_still_time < 200) - tape->measure_insert_time = 1; - if (tape->req_buffer_fill && (rq->flags == IDETAPE_WRITE_RQ || rq->flags == IDETAPE_READ_RQ)) { - tape->req_buffer_fill = 0; - tape->writes_since_buffer_fill = 0; - tape->reads_since_buffer_fill = 0; - tape->last_buffer_fill = jiffies; - idetape_queue_onstream_buffer_fill(drive); - if (jiffies > tape->insert_time) - tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - return ATA_OP_FINISHED; - } - if (jiffies > tape->insert_time) - tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - calculate_speeds(drive); - if (tape->onstream && tape->max_frames && - ((rq->flags == IDETAPE_WRITE_RQ && - ( tape->cur_frames == tape->max_frames || - ( tape->speed_control && tape->cur_frames > 5 && - (tape->insert_speed > tape->max_insert_speed || - (0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */) ) ) ) ) || - (rq->flags == IDETAPE_READ_RQ && - ( tape->cur_frames == 0 || - ( tape->speed_control && (tape->cur_frames < tape->max_frames - 5) && - tape->insert_speed > tape->max_insert_speed ) ) && rq->nr_sectors) ) ) { -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: postponing request, cmd %ld, cur %d, max %d\n", - rq->flags, tape->cur_frames, tape->max_frames); -#endif - if (tape->postpone_cnt++ < 500) { - status.b.dsc = 0; - tape->req_buffer_fill = 1; - } -#if ONSTREAM_DEBUG - else if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n", tape->name, tape->postpone_cnt); -#endif - } - if (!test_and_clear_bit (IDETAPE_IGNORE_DSC, &tape->flags) && !status.b.dsc) { - if (postponed_rq == NULL) { - tape->dsc_polling_start = jiffies; - tape->dsc_polling_frequency = tape->best_dsc_rw_frequency; - tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT; - } else if ((signed long) (jiffies - tape->dsc_timeout) > 0) { - printk (KERN_ERR "ide-tape: %s: DSC timeout\n", tape->name); - - if (rq->flags == IDETAPE_PC_RQ2) - idetape_media_access_finished(drive, rq); - - return ATA_OP_FINISHED; - } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD) - tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW; - idetape_postpone_request(drive, rq); - - return ATA_OP_FINISHED; - } - switch (rq->flags) { - case IDETAPE_READ_RQ: - 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; - tape->reads_since_buffer_fill++; - if (tape->onstream) { - if (tape->cur_frames - tape->reads_since_buffer_fill <= 0) - tape->req_buffer_fill = 1; - if (jiffies > tape->last_buffer_fill + 5 * HZ / 100) - tape->req_buffer_fill = 1; - } - pc = idetape_next_pc_storage(drive); - idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, rq->bio); - break; - case IDETAPE_WRITE_RQ: - 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; - tape->writes_since_buffer_fill++; - if (tape->onstream) { - if (tape->cur_frames + tape->writes_since_buffer_fill >= tape->max_frames) - tape->req_buffer_fill = 1; - if (jiffies > tape->last_buffer_fill + 5 * HZ / 100) - tape->req_buffer_fill = 1; - calculate_speeds(drive); - } - pc = idetape_next_pc_storage (drive); - idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, rq->bio); - break; - case IDETAPE_READ_BUFFER_RQ: - tape->postpone_cnt = 0; - pc = idetape_next_pc_storage (drive); - idetape_create_read_buffer_cmd(tape, pc, rq->current_nr_sectors, rq->bio); - break; - case IDETAPE_ABORTED_WRITE_RQ: - rq->flags = IDETAPE_WRITE_RQ; - idetape_end_request(drive, rq, IDETAPE_ERROR_EOD); - return ATA_OP_FINISHED; - case IDETAPE_ABORTED_READ_RQ: -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: detected aborted read rq\n", tape->name); -#endif - rq->flags = IDETAPE_READ_RQ; - idetape_end_request(drive, rq, IDETAPE_ERROR_EOD); - return ATA_OP_FINISHED; - case IDETAPE_PC_RQ1: - /* FIXME: --mdcki */ - pc = (struct atapi_packet_command *) rq->buffer; - rq->flags = IDETAPE_PC_RQ2; - break; - case IDETAPE_PC_RQ2: - idetape_media_access_finished(drive, rq); - - return ATA_OP_FINISHED; - default: - printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n"); - - idetape_end_request(drive, rq, 0); - - return ATA_OP_FINISHED; - } - - return idetape_issue_packet_command(drive, rq, pc); -} - -/* - * Pipeline related functions - */ -static inline int idetape_pipeline_active (idetape_tape_t *tape) -{ - int rc1, rc2; - - rc1 = test_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - rc2 = (tape->active_data_request != NULL); - return rc1; -} - -/* - * idetape_kmalloc_stage uses __get_free_page to allocate a pipeline - * stage, along with all the necessary small buffers which together make - * a buffer of size tape->stage_size (or a bit more). We attempt to - * combine sequential pages as much as possible. - * - * Returns a pointer to the new allocated stage, or NULL if we - * can't (or don't want to) allocate a stage. - * - * Pipeline stages are optional and are used to increase performance. - * If we can't allocate them, we'll manage without them. - */ -static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, int clear) -{ - idetape_stage_t *stage; - struct bio *prev_bio, *bio; - int pages = tape->pages_per_stage; - char *b_data = NULL; - struct bio_vec *bv; - - if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL) - return NULL; - stage->next = NULL; - - bio = stage->bio = bio_alloc(GFP_KERNEL,1); - bv = bio_iovec(bio); - bv->bv_len = 0; - if (bio == NULL) - goto abort; - bio->bi_next = NULL; - if ((bio->bi_io_vec[0].bv_page = alloc_page(GFP_KERNEL)) == NULL) - goto abort; - if (clear) - memset(bio_data(bio), 0, PAGE_SIZE); - bio->bi_size = PAGE_SIZE; - if(bv->bv_len == full) - bv->bv_len = bio->bi_size; -#if 0 - - /* FIXME: What what this supposed to achieve? */ - - set_bit (BH_Lock, &bio->bi_flags); -#endif - while (--pages) { - if ((bio->bi_io_vec[pages].bv_page = alloc_page(GFP_KERNEL)) == NULL) - goto abort; - if (clear) - memset(bio_data(bio), 0, PAGE_SIZE); - if (bio->bi_size == bv->bv_len + PAGE_SIZE) { - bio->bi_size += PAGE_SIZE; - bv->bv_len += PAGE_SIZE; - bv->bv_offset -= PAGE_SIZE; - if (full) - bio->bi_size += PAGE_SIZE; - continue; - } - if (b_data == bio_data(bio) + bio->bi_size) { - bio->bi_size += PAGE_SIZE; - if (full) - bio->bi_size += PAGE_SIZE; - continue; - } - prev_bio = bio; - if ((bio = bio_alloc(GFP_KERNEL,1)) == NULL) { - free_page ((unsigned long) bio_data(bio)); - goto abort; - } - bio->bi_next = NULL; - //bio->bi_io_vec[0].bv_offset = b_data; - bio->bi_size = PAGE_SIZE; - atomic_set(&bio->bi_cnt, full ? bio->bi_size : 0); -#if 0 - /* FIXME: What what this supposed to achieve? */ - - set_bit (BH_Lock, &bio->bi_flags); -#endif - prev_bio->bi_next = bio; - } - bio->bi_size -= tape->excess_bh_size; - if (full) - atomic_sub(tape->excess_bh_size, &bio->bi_cnt); - if (tape->onstream) - stage->aux = (os_aux_t *) (bio_data(bio) + bio->bi_size - OS_AUX_SIZE); - return stage; -abort: - __idetape_kfree_stage (stage); - return NULL; -} - -static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape) -{ - idetape_stage_t *cache_stage = tape->cache_stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_kmalloc_stage\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - if (tape->nr_stages >= tape->max_stages) - return NULL; - if (cache_stage != NULL) { - tape->cache_stage = NULL; - return cache_stage; - } - return __idetape_kmalloc_stage (tape, 0, 0); -} - -static void idetape_copy_stage_from_user(idetape_tape_t *tape, idetape_stage_t *stage, - const char *buf, unsigned int n) -{ - struct bio *bio = tape->bio; - int count; - - while (n) { -#if IDETAPE_DEBUG_BUGS - if (bio == NULL) { - printk (KERN_ERR "ide-tape: bio == NULL in idetape_copy_stage_from_user\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - count = min(bio->bi_size - tape->b_count, n); - copy_from_user (bio_data(bio) + tape->b_count, buf, count); - n -= count; - bio->bi_size += count; - buf += count; - if (tape->b_count == bio->bi_size) { - bio = bio->bi_next; - if (bio) - tape->b_count = 0; - } - } - tape->bio = bio; -} - -static void idetape_copy_stage_to_user (idetape_tape_t *tape, char *buf, idetape_stage_t *stage, int n) -{ - struct bio *bio = tape->bio; - int count; - - while (n) { -#if IDETAPE_DEBUG_BUGS - if (bio == NULL) { - printk (KERN_ERR "ide-tape: bio == NULL in idetape_copy_stage_to_user\n"); - return; - } -#endif - count = min(tape->b_count, n); - copy_to_user (buf, tape->b_data, count); - n -= count; - tape->b_data += count; - tape->b_count -= count; - buf += count; - if (!tape->b_count) { - tape->bio = bio = bio->bi_next; - if (bio) { - tape->b_data = bio_data(bio); - tape->b_count = bio->bi_size; - } - } - } -} - -static void idetape_init_merge_stage (idetape_tape_t *tape) -{ - struct bio *bio = tape->merge_stage->bio; - - tape->bio = bio; - if (tape->chrdev_direction == idetape_direction_write) - atomic_set(&bio->bi_cnt, 0); - else { - tape->b_data = bio_data(bio); - tape->b_count = atomic_read(&bio->bi_cnt); - } -} - -static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage) -{ - struct bio *tmp; - os_aux_t *tmp_aux; - - tmp = stage->bio; tmp_aux = stage->aux; - stage->bio = tape->merge_stage->bio; stage->aux = tape->merge_stage->aux; - tape->merge_stage->bio = tmp; tape->merge_stage->aux = tmp_aux; - idetape_init_merge_stage (tape); -} - -/* - * idetape_add_stage_tail adds a new stage at the end of the pipeline. - */ -static void idetape_add_stage_tail(struct ata_device *drive, idetape_stage_t *stage) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_add_stage_tail\n"); -#endif - spin_lock_irqsave(&tape->spinlock, flags); - stage->next=NULL; - if (tape->last_stage != NULL) - tape->last_stage->next=stage; - else - tape->first_stage = tape->next_stage=stage; - tape->last_stage = stage; - if (tape->next_stage == NULL) - tape->next_stage = tape->last_stage; - tape->nr_stages++; - tape->nr_pending_stages++; - spin_unlock_irqrestore(&tape->spinlock, flags); -} - -/* - * Initialize the OnStream AUX - */ -static void idetape_init_stage(struct ata_device *drive, idetape_stage_t *stage, int frame_type, int logical_blk_num) -{ - idetape_tape_t *tape = drive->driver_data; - os_aux_t *aux = stage->aux; - os_partition_t *par = &aux->partition; - os_dat_t *dat = &aux->dat; - - if (!tape->onstream || tape->raw) - return; - memset(aux, 0, sizeof(*aux)); - aux->format_id = htonl(0); - memcpy(aux->application_sig, "LIN3", 4); - aux->hdwr = htonl(0); - aux->frame_type = frame_type; - - if (frame_type == OS_FRAME_TYPE_HEADER) { - aux->update_frame_cntr = htonl(tape->update_frame_cntr); - par->partition_num = OS_CONFIG_PARTITION; - par->par_desc_ver = OS_PARTITION_VERSION; - par->wrt_pass_cntr = htons(0xffff); - par->first_frame_addr = htonl(0); - par->last_frame_addr = htonl(0xbb7); /* 2999 */ - aux->frame_seq_num = htonl(0); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(0); - aux->next_mark_addr = htonl(tape->first_mark_addr); - } else { - aux->update_frame_cntr = htonl(0); - par->partition_num = OS_DATA_PARTITION; - par->par_desc_ver = OS_PARTITION_VERSION; - par->wrt_pass_cntr = htons(tape->wrt_pass_cntr); - par->first_frame_addr = htonl(OS_DATA_STARTFRAME1); - par->last_frame_addr = htonl(tape->capacity); - aux->frame_seq_num = htonl(logical_blk_num); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(logical_blk_num); - dat->dat_sz = 8; - dat->reserved1 = 0; - dat->entry_cnt = 1; - dat->reserved3 = 0; - if (frame_type == OS_FRAME_TYPE_DATA) - dat->dat_list[0].blk_sz = htonl(32 * 1024); - else - dat->dat_list[0].blk_sz = 0; - dat->dat_list[0].blk_cnt = htons(1); - if (frame_type == OS_FRAME_TYPE_MARKER) - dat->dat_list[0].flags = OS_DAT_FLAGS_MARK; - else - dat->dat_list[0].flags = OS_DAT_FLAGS_DATA; - dat->dat_list[0].reserved = 0; - } - aux->filemark_cnt = ntohl(tape->filemark_cnt); /* shouldn't this be htonl ?? */ - aux->phys_fm = ntohl(0xffffffff); /* shouldn't this be htonl ?? */ - aux->last_mark_addr = ntohl(tape->last_mark_addr); /* shouldn't this be htonl ?? */ -} - -/* - * idetape_wait_for_request installs a completion in a pending request - * and sleeps until it is serviced. - * - * The caller should ensure that the request will not be serviced - * before we install the completion (usually by disabling interrupts). - */ -static void idetape_wait_for_request(struct ata_device *drive, struct request *rq) -{ - DECLARE_COMPLETION(wait); - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_BUGS - if (rq == NULL || !IDETAPE_RQ_CMD (rq->flags)) { - printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - rq->waiting = &wait; - tape->waiting = &wait; - spin_unlock(&tape->spinlock); - wait_for_completion(&wait); - rq->waiting = NULL; - tape->waiting = NULL; - spin_lock_irq(&tape->spinlock); -} - -static void idetape_read_position_callback(struct ata_device *drive, struct request *rq) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_read_position_result_t *result; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n"); -#endif - - if (!tape->pc->error) { - result = (idetape_read_position_result_t *) tape->pc->buffer; -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: BOP - %s\n",result->bop ? "Yes":"No"); - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: EOP - %s\n",result->eop ? "Yes":"No"); -#endif - if (result->bpu) { - printk (KERN_INFO "ide-tape: Block location is unknown to the tape\n"); - clear_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request(drive, rq, 0); - } else { -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Block Location - %u\n", ntohl (result->first_block)); -#endif - tape->partition = result->partition; - tape->first_frame_position = ntohl (result->first_block); - tape->last_frame_position = ntohl (result->last_block); - tape->blocks_in_buffer = result->blocks_in_buffer[2]; - set_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request(drive, rq, 1); - } - } else { - idetape_end_request(drive, rq, 0); - } -} - -/* - * idetape_create_write_filemark_cmd will: - * - * 1. Write a filemark if write_filemark=1. - * 2. Flush the device buffers without writing a filemark - * if write_filemark=0. - * - */ -static void idetape_create_write_filemark_cmd(struct ata_device *drive, - struct atapi_packet_command *pc,int write_filemark) -{ - idetape_tape_t *tape = drive->driver_data; - - atapi_init_pc(pc); - pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD; - if (tape->onstream) - pc->c[1] = 1; /* Immed bit */ - pc->c[4] = write_filemark; /* not used for OnStream ?? */ - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = idetape_pc_callback; -} - -static void idetape_create_test_unit_ready_cmd(struct atapi_packet_command *pc) -{ - atapi_init_pc(pc); - pc->c[0] = IDETAPE_TEST_UNIT_READY_CMD; - pc->callback = idetape_pc_callback; -} - -/* - * idetape_queue_pc_tail is based on the following functions: - * - * ide_do_drive_cmd from ide.c - * cdrom_queue_request and cdrom_queue_packet_command from ide-cd.c - * - * We add a special packet command request to the tail of the request queue, - * and wait for it to be serviced. - * - * This is not to be called from within the request handling part - * of the driver ! We allocate here data in the stack, and it is valid - * until the request is finished. This is not the case for the bottom - * part of the driver, where we are always leaving the functions to wait - * for an interrupt or a timer event. - * - * From the bottom part of the driver, we should allocate safe memory - * using idetape_next_pc_storage and idetape_next_rq_storage, and add - * the request to the request list without waiting for it to be serviced ! - * In that case, we usually use idetape_queue_pc_head. - */ -static int __idetape_queue_pc_tail(struct ata_device *drive, struct atapi_packet_command *pc) -{ - struct request rq; - - memset(&rq, 0, sizeof(rq)); - /* FIXME: --mdcki */ - rq.buffer = (char *) pc; - rq.flags = IDETAPE_PC_RQ1; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - -static void idetape_create_load_unload_cmd(struct ata_device *drive, - struct atapi_packet_command *pc, int cmd) -{ - idetape_tape_t *tape = drive->driver_data; - - atapi_init_pc(pc); - pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD; - pc->c[4] = cmd; - if (tape->onstream) { - pc->c[1] = 1; - if (cmd == !IDETAPE_LU_LOAD_MASK) - pc->c[4] = 4; - } - set_bit (PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = idetape_pc_callback; -} - -static int idetape_wait_ready(struct ata_device *drive, unsigned long long timeout) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command pc; - - /* - * Wait for the tape to become ready - */ - timeout += jiffies; - while (jiffies < timeout) { - idetape_create_test_unit_ready_cmd(&pc); - if (!__idetape_queue_pc_tail(drive, &pc)) - return 0; - if (tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2) { - idetape_create_load_unload_cmd (drive, &pc, IDETAPE_LU_LOAD_MASK); - __idetape_queue_pc_tail(drive, &pc); - idetape_create_test_unit_ready_cmd(&pc); - if (!__idetape_queue_pc_tail(drive, &pc)) - return 0; - } - if (!(tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) - break; - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ / 10); - } - return -EIO; -} - -static int idetape_queue_pc_tail(struct ata_device *drive, struct atapi_packet_command *pc) -{ - idetape_tape_t *tape = drive->driver_data; - int rc; - - rc = __idetape_queue_pc_tail(drive, pc); - if (rc) - return rc; - if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags)) - rc = idetape_wait_ready(drive, 60 * 10 * HZ); /* AJN-4: Changed from 5 to 10 minutes; - because retension takes approx. 8:20 with Onstream 30GB tape */ - return rc; -} - -static int idetape_flush_tape_buffers(struct ata_device *drive) -{ - struct atapi_packet_command pc; - int rc; - - idetape_create_write_filemark_cmd(drive, &pc, 0); - if ((rc = idetape_queue_pc_tail (drive, &pc))) - return rc; - idetape_wait_ready(drive, 60 * 5 * HZ); - return 0; -} - -static void idetape_create_read_position_cmd(struct atapi_packet_command *pc) -{ - atapi_init_pc(pc); - pc->c[0] = IDETAPE_READ_POSITION_CMD; - pc->request_transfer = 20; - pc->callback = idetape_read_position_callback; -} - -static int idetape_read_position(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command pc; - int position; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_read_position\n"); -#endif - -#ifdef NO_LONGER_REQUIRED - idetape_flush_tape_buffers(drive); -#endif - idetape_create_read_position_cmd(&pc); - if (idetape_queue_pc_tail (drive, &pc)) - return -1; - position = tape->first_frame_position; -#ifdef NO_LONGER_REQUIRED - if (tape->onstream) { - if ((position != tape->last_frame_position - tape->blocks_in_buffer) && - (position != tape->last_frame_position + tape->blocks_in_buffer)) { - if (tape->blocks_in_buffer == 0) { - printk("ide-tape: %s: correcting read position %d, %d, %d\n", tape->name, position, tape->last_frame_position, tape->blocks_in_buffer); - position = tape->last_frame_position; - tape->first_frame_position = position; - } - } - } -#endif - return position; -} - -static void idetape_create_locate_cmd(struct ata_device *drive, - struct atapi_packet_command *pc, - unsigned int block, u8 partition, int skip) -{ - idetape_tape_t *tape = drive->driver_data; - - atapi_init_pc(pc); - pc->c[0] = IDETAPE_LOCATE_CMD; - if (tape->onstream) - pc->c[1] = 1; /* Immediate bit */ - else - pc->c[1] = 2; - put_unaligned (htonl (block), (unsigned int *) &pc->c[3]); - pc->c[8] = partition; - if (tape->onstream) - /* - * Set SKIP bit. - * In case of write error this will write buffered - * data in the drive to this new position! - */ - pc->c[9] = skip << 7; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = idetape_pc_callback; -} - -static int idetape_create_prevent_cmd(struct ata_device *drive, - struct atapi_packet_command *pc, int prevent) -{ - idetape_tape_t *tape = drive->driver_data; - - if (!tape->capabilities.lock) - return 0; - - atapi_init_pc(pc); - pc->c[0] = IDETAPE_PREVENT_CMD; - pc->c[4] = prevent; - pc->callback = idetape_pc_callback; - - return 1; -} - -static int __idetape_discard_read_pipeline(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - int cnt; - - if (tape->chrdev_direction != idetape_direction_read) - return 0; - tape->merge_stage_size = 0; - if (tape->merge_stage != NULL) { - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - tape->chrdev_direction = idetape_direction_none; - - if (tape->first_stage == NULL) - return 0; - - spin_lock_irqsave(&tape->spinlock, flags); - tape->next_stage = NULL; - if (idetape_pipeline_active (tape)) - idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&tape->spinlock, flags); - - cnt = tape->nr_stages - tape->nr_pending_stages; - while (tape->first_stage != NULL) - idetape_remove_stage_head (drive); - tape->nr_pending_stages = 0; - tape->max_stages = tape->min_pipeline; - return cnt; -} - -/* - * idetape_position_tape positions the tape to the requested block - * using the LOCATE packet command. A READ POSITION command is then - * issued to check where we are positioned. - * - * Like all higher level operations, we queue the commands at the tail - * of the request queue and wait for their completion. - * - */ -static int idetape_position_tape(struct ata_device *drive, unsigned int block, u8 partition, int skip) -{ - idetape_tape_t *tape = drive->driver_data; - int retval; - struct atapi_packet_command pc; - - if (tape->chrdev_direction == idetape_direction_read) - __idetape_discard_read_pipeline(drive); - idetape_wait_ready(drive, 60 * 5 * HZ); - idetape_create_locate_cmd (drive, &pc, block, partition, skip); - retval = idetape_queue_pc_tail (drive, &pc); - if (retval) - return (retval); - - idetape_create_read_position_cmd (&pc); - return (idetape_queue_pc_tail (drive, &pc)); -} - -static void idetape_discard_read_pipeline(struct ata_device *drive, int restore_position) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt; - int seek, position; - - cnt = __idetape_discard_read_pipeline(drive); - if (restore_position) { - position = idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", position, cnt); -#endif - seek = position > cnt ? position - cnt : 0; - if (idetape_position_tape(drive, seek, 0, 0)) { - printk(KERN_INFO "ide-tape: %s: position_tape failed in discard_pipeline()\n", tape->name); - return; - } - } -} - -static void idetape_update_stats(struct ata_device *drive) -{ - struct atapi_packet_command pc; - - idetape_create_mode_sense_cmd (&pc, IDETAPE_BUFFER_FILLING_PAGE); - pc.callback = idetape_onstream_buffer_fill_callback; - (void) idetape_queue_pc_tail(drive, &pc); -} - -/* - * idetape_queue_rw_tail generates a read/write request for the block - * device interface and wait for it to be serviced. - */ -static int idetape_queue_rw_tail(struct ata_device *drive, int cmd, int blocks, struct bio *bio) -{ - idetape_tape_t *tape = drive->driver_data; - struct request rq; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd); -#endif -#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 - - memset(&rq, 0, sizeof(rq)); - rq.flags = cmd; - rq.bio = bio; - rq.sector = tape->first_frame_position; - rq.nr_sectors = rq.current_nr_sectors = blocks; - if (tape->onstream) - tape->postpone_cnt = 600; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); - - if (cmd != IDETAPE_READ_RQ && cmd != IDETAPE_WRITE_RQ) - return 0; - - if (tape->merge_stage) - idetape_init_merge_stage (tape); - if (rq.errors == IDETAPE_ERROR_GENERAL) - return -EIO; - return (tape->tape_block_size * (blocks-rq.current_nr_sectors)); -} - -/* - * Read back the drive's internal buffer contents, as a part - * of the write error recovery mechanism for old OnStream - * firmware revisions. - */ -static void idetape_onstream_read_back_buffer(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int frames, i, logical_blk_num; - idetape_stage_t *stage, *first = NULL, *last = NULL; - os_aux_t *aux; - struct request *rq; - unsigned char *p; - unsigned long flags; - - idetape_update_stats(drive); - frames = tape->cur_frames; - logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num) - frames; - printk(KERN_INFO "ide-tape: %s: reading back %d frames from the drive's internal buffer\n", tape->name, frames); - for (i = 0; i < frames; i++) { - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (!first) - first = stage; - aux = stage->aux; - p = bio_data(stage->bio); - idetape_queue_rw_tail(drive, IDETAPE_READ_BUFFER_RQ, tape->capabilities.ctl, stage->bio); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++); -#endif - rq = &stage->rq; - memset(rq, 0, sizeof(*rq)); - rq->flags = IDETAPE_WRITE_RQ; - rq->sector = tape->first_frame_position; - rq->nr_sectors = rq->current_nr_sectors = tape->capabilities.ctl; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_DATA, logical_blk_num++); - stage->next = NULL; - if (last) - last->next = stage; - last = stage; - } - if (frames) { - spin_lock_irqsave(&tape->spinlock, flags); - last->next = tape->first_stage; - tape->next_stage = tape->first_stage = first; - tape->nr_stages += frames; - tape->nr_pending_stages += frames; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - idetape_update_stats(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", tape->name, tape->cur_frames); -#endif -} - -/* - * Error recovery algorithm for the OnStream tape. - */ -static void idetape_onstream_write_error_recovery(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned int block; - - if (tape->onstream_write_error == OS_WRITE_ERROR) { - printk(KERN_ERR "ide-tape: %s: onstream_write_error_recovery: detected physical bad block at %u, logical %u first frame %u last_frame %u bufblocks %u stages %u skipping %u frames\n", - tape->name, ntohl(tape->sense.information), tape->logical_blk_num, - tape->first_frame_position, tape->last_frame_position, - tape->blocks_in_buffer, tape->nr_stages, - (ntohl(tape->sense.command_specific) >> 16) & 0xff ); - block = ntohl(tape->sense.information) + ((ntohl(tape->sense.command_specific) >> 16) & 0xff); - idetape_update_stats(drive); - printk(KERN_ERR "ide-tape: %s: relocating %d buffered logical blocks to physical block %u\n", tape->name, tape->cur_frames, block); -#if 0 /* isn't once enough ??? MM */ - idetape_update_stats(drive); -#endif - if (tape->firmware_revision_num >= 106) - idetape_position_tape(drive, block, 0, 1); - else { - idetape_onstream_read_back_buffer(drive); - idetape_position_tape(drive, block, 0, 0); - } -#if 0 /* already done in idetape_position_tape MM */ - idetape_read_position(drive); -#endif -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_ERR "ide-tape: %s: positioning complete, cur_frames %d, pos %d, tape pos %d\n", tape->name, tape->cur_frames, tape->first_frame_position, tape->last_frame_position); -#endif - } else if (tape->onstream_write_error == OS_PART_ERROR) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: skipping over config partition\n", tape->name); -#endif - idetape_flush_tape_buffers(drive); - block = idetape_read_position(drive); - if (block != OS_DATA_ENDFRAME1) - printk(KERN_ERR "ide-tape: warning, current position %d, expected %d\n", block, OS_DATA_ENDFRAME1); - idetape_position_tape(drive, 0xbb8, 0, 0); /* 3000 */ - } - tape->onstream_write_error = 0; -} - -/* - * idetape_insert_pipeline_into_queue is used to start servicing the - * pipeline stages, starting from tape->next_stage. - */ -static void idetape_insert_pipeline_into_queue(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (tape->next_stage == NULL) - return; - if (!idetape_pipeline_active (tape)) { - if (tape->onstream_write_error) - idetape_onstream_write_error_recovery(drive); - set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - idetape_active_next_stage (drive); - (void) ide_do_drive_cmd (drive, tape->active_data_request, ide_end); - } -} - -static void idetape_create_inquiry_cmd(struct atapi_packet_command *pc) -{ - atapi_init_pc(pc); - pc->c[0] = IDETAPE_INQUIRY_CMD; - pc->c[4] = pc->request_transfer = 254; - pc->callback = idetape_pc_callback; -} - -static void idetape_create_rewind_cmd(struct ata_device *drive, - struct atapi_packet_command *pc) -{ - idetape_tape_t *tape = drive->driver_data; - - atapi_init_pc(pc); - pc->c[0] = IDETAPE_REWIND_CMD; - if (tape->onstream) - pc->c[1] = 1; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = idetape_pc_callback; -} - -static void idetape_create_mode_select_cmd(struct atapi_packet_command *pc, int length) -{ - atapi_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; -} - -static void idetape_create_erase_cmd(struct atapi_packet_command *pc) -{ - atapi_init_pc(pc); - pc->c[0] = IDETAPE_ERASE_CMD; - pc->c[1] = 1; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = idetape_pc_callback; -} - -static void idetape_create_space_cmd(struct atapi_packet_command *pc, int count, u8 cmd) -{ - atapi_init_pc(pc); - pc->c[0] = IDETAPE_SPACE_CMD; - put_unaligned (htonl (count), (unsigned int *) &pc->c[1]); - pc->c[1] = cmd; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; -} - -/* - * Verify that we have the correct tape frame - */ -static int idetape_verify_stage(struct ata_device *drive, idetape_stage_t *stage, int logical_blk_num, int quiet) -{ - idetape_tape_t *tape = drive->driver_data; - os_aux_t *aux = stage->aux; - os_partition_t *par = &aux->partition; - struct request *rq = &stage->rq; - struct bio *bio; - - if (!tape->onstream) - return 1; - if (tape->raw) { - if (rq->errors) { - bio = stage->bio; - while (bio) { - memset(bio_data(bio), 0, bio->bi_size); - bio = bio->bi_next; - } - strcpy(bio_data(stage->bio), "READ ERROR ON FRAME"); - } - return 1; - } - if (rq->errors == IDETAPE_ERROR_GENERAL) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, read error\n", tape->name, tape->first_frame_position); - return 0; - } - if (rq->errors == IDETAPE_ERROR_EOD) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, eod\n", tape->name, tape->first_frame_position); - return 0; - } - if (ntohl(aux->format_id) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, format_id %u\n", tape->name, tape->first_frame_position, ntohl(aux->format_id)); - return 0; - } - if (memcmp(aux->application_sig, tape->application_sig, 4) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, incorrect application signature\n", tape->name, tape->first_frame_position); - return 0; - } - if (aux->frame_type != OS_FRAME_TYPE_DATA && - aux->frame_type != OS_FRAME_TYPE_EOD && - aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, frame type %x\n", tape->name, tape->first_frame_position, aux->frame_type); - return 0; - } - if (par->partition_num != OS_DATA_PARTITION) { - if (!tape->linux_media || tape->linux_media_version != 2) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition num %d\n", tape->name, tape->first_frame_position, par->partition_num); - return 0; - } - } - if (par->par_desc_ver != OS_PARTITION_VERSION) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition version %d\n", tape->name, tape->first_frame_position, par->par_desc_ver); - return 0; - } - if (ntohs(par->wrt_pass_cntr) != tape->wrt_pass_cntr) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", tape->name, tape->first_frame_position, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num)); - return 0; - } - if (aux->frame_seq_num != aux->logical_blk_num) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, seq != logical\n", tape->name, tape->first_frame_position); - return 0; - } - if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) { - if (!quiet) - printk(KERN_INFO "ide-tape: %s: skipping frame %d, logical_blk_num %u (expected %d)\n", tape->name, tape->first_frame_position, ntohl(aux->logical_blk_num), logical_blk_num); - return 0; - } - if (aux->frame_type == OS_FRAME_TYPE_MARKER) { - rq->errors = IDETAPE_ERROR_FILEMARK; - rq->current_nr_sectors = rq->nr_sectors; - } - return 1; -} - -static void idetape_wait_first_stage(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - - if (tape->first_stage == NULL) - return; - spin_lock_irqsave(&tape->spinlock, flags); - if (tape->active_stage == tape->first_stage) - idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&tape->spinlock, flags); -} - -/* - * idetape_add_chrdev_write_request tries to add a character device - * originated write request to our pipeline. In case we don't succeed, - * we revert to non-pipelined operation mode for this request. - * - * 1. Try to allocate a new pipeline stage. - * 2. If we can't, wait for more and more requests to be serviced - * and try again each time. - * 3. If we still can't allocate a stage, fallback to - * non-pipelined operation mode for this request. - */ -static int idetape_add_chrdev_write_request(struct ata_device *drive, int blocks) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *new_stage; - unsigned long flags; - struct request *rq; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n"); -#endif - - /* - * Attempt to allocate a new stage. - * Pay special attention to possible race conditions. - */ - while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) { - spin_lock_irqsave(&tape->spinlock, flags); - if (idetape_pipeline_active (tape)) { - idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&tape->spinlock, flags); - } else { - spin_unlock_irqrestore(&tape->spinlock, flags); - idetape_insert_pipeline_into_queue (drive); - if (idetape_pipeline_active (tape)) - continue; - /* - * Linux is short on memory. Fallback to - * non-pipelined operation mode for this request. - */ - return idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bio); - } - } - rq = &new_stage->rq; - memset(rq, 0, sizeof(*rq)); - rq->flags = IDETAPE_WRITE_RQ; - rq->sector = tape->first_frame_position; /* Doesn't actually matter - We always assume sequential access */ - rq->nr_sectors = rq->current_nr_sectors = blocks; - - idetape_switch_buffers (tape, new_stage); - idetape_init_stage(drive, new_stage, OS_FRAME_TYPE_DATA, tape->logical_blk_num); - tape->logical_blk_num++; - 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); - - /* - * Estimate whether the tape has stopped writing by checking - * if our write pipeline is currently empty. If we are not - * writing anymore, wait for the pipeline to be full enough - * (90%) before starting to service requests, so that we will - * be able to keep up with the higher speeds of the tape. - * - * For the OnStream drive, we can query the number of pending - * frames in the drive's internal buffer. As long as the tape - * is still writing, it is better to write frames immediately - * rather than gather them in the pipeline. This will give the - * tape's firmware the ability to sense the current incoming - * data rate more accurately, and since the OnStream tape - * supports variable speeds, it can try to adjust itself to the - * incoming data rate. - */ - if (!idetape_pipeline_active(tape)) { - if (tape->nr_stages >= tape->max_stages * 9 / 10 || - tape->nr_stages >= tape->max_stages - tape->uncontrolled_pipeline_head_speed * 3 * 1024 / tape->tape_block_size) { - tape->measure_insert_time = 1; - tape->insert_time = jiffies; - tape->insert_size = 0; - tape->insert_speed = 0; - idetape_insert_pipeline_into_queue (drive); - } else if (tape->onstream) { - idetape_update_stats(drive); - if (tape->cur_frames > 5) - idetape_insert_pipeline_into_queue (drive); - } - } - if (test_and_clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags)) /* Return a deferred error */ - return -EIO; - return blocks; -} - -/* - * idetape_wait_for_pipeline will wait until all pending pipeline - * requests are serviced. Typically called on device close. - */ -static void idetape_wait_for_pipeline(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - - while (tape->next_stage || idetape_pipeline_active(tape)) { - idetape_insert_pipeline_into_queue (drive); - spin_lock_irqsave(&tape->spinlock, flags); - if (idetape_pipeline_active(tape)) - idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&tape->spinlock, flags); - } -} - -static void idetape_empty_write_pipeline(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int blocks, min; - struct bio *bio; - -#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; - } - if (tape->merge_stage_size > tape->stage_size) { - printk (KERN_ERR "ide-tape: bug: merge_buffer too big\n"); - tape->merge_stage_size = tape->stage_size; - } -#endif - if (tape->merge_stage_size) { - blocks = tape->merge_stage_size / tape->tape_block_size; - if (tape->merge_stage_size % tape->tape_block_size) { - unsigned int i; - - blocks++; - i = tape->tape_block_size - tape->merge_stage_size % tape->tape_block_size; - bio = tape->bio->bi_next; - while (bio) { - atomic_set(&bio->bi_cnt, 0); - bio = bio->bi_next; - } - bio = tape->bio; - while (i) { - if (bio == NULL) { - printk(KERN_INFO "ide-tape: bug, bio NULL\n"); - break; - } - min = min(i, bio->bi_size - atomic_read(&bio->bi_cnt)); - memset(bio_data(bio) + bio->bi_size, 0, min); - atomic_add(min, &bio->bi_cnt); - i -= min; - bio = bio->bi_next; - } - } - (void) idetape_add_chrdev_write_request (drive, blocks); - tape->merge_stage_size = 0; - } - idetape_wait_for_pipeline (drive); - if (tape->merge_stage != NULL) { - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - tape->chrdev_direction = idetape_direction_none; - - /* - * On the next backup, perform the feedback loop again. - * (I don't want to keep sense information between backups, - * as some systems are constantly on, and the system load - * 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 || tape->nr_stages != 0) { - printk (KERN_ERR "ide-tape: ide-tape pipeline bug, " - "first_stage %p, next_stage %p, last_stage %p, nr_stages %d\n", - tape->first_stage, tape->next_stage, tape->last_stage, tape->nr_stages); - } -#endif /* IDETAPE_DEBUG_BUGS */ -} - -static void idetape_restart_speed_control(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - tape->restart_speed_control_req = 0; - tape->pipeline_head = 0; - tape->buffer_head = tape->tape_head = tape->cur_frames; - tape->controlled_last_pipeline_head = tape->uncontrolled_last_pipeline_head = 0; - tape->controlled_previous_pipeline_head = tape->uncontrolled_previous_pipeline_head = 0; - tape->pipeline_head_speed = tape->controlled_pipeline_head_speed = 5000; - tape->uncontrolled_pipeline_head_speed = 0; - tape->controlled_pipeline_head_time = tape->uncontrolled_pipeline_head_time = jiffies; - tape->controlled_previous_head_time = tape->uncontrolled_previous_head_time = jiffies; -} - -static int idetape_initiate_read(struct ata_device *drive, int max_stages) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *new_stage; - struct request rq; - int bytes_read; - int blocks = tape->capabilities.ctl; - - if (tape->chrdev_direction != idetape_direction_read) { /* Initialize read operation */ - if (tape->chrdev_direction == idetape_direction_write) { - 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; - tape->logical_blk_num = 0; - - /* - * Issue a read 0 command to ensure that DSC handshake - * is switched from completion mode to buffer available - * mode. - */ - bytes_read = idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bio); - if (bytes_read < 0) { - kfree (tape->merge_stage); - tape->merge_stage = NULL; - tape->chrdev_direction = idetape_direction_none; - return bytes_read; - } - } - if (tape->restart_speed_control_req) - idetape_restart_speed_control(drive); - - memset(&rq, 0, sizeof(rq)); - rq.flags = IDETAPE_READ_RQ; - rq.sector = tape->first_frame_position; - rq.nr_sectors = rq.current_nr_sectors = blocks; - if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages <= max_stages) { - new_stage = idetape_kmalloc_stage (tape); - while (new_stage != NULL) { - new_stage->rq = rq; - idetape_add_stage_tail (drive, new_stage); - if (tape->nr_stages >= max_stages) - break; - new_stage = idetape_kmalloc_stage (tape); - } - } - if (!idetape_pipeline_active(tape)) { - if (tape->nr_pending_stages >= 3 * max_stages / 4) { - tape->measure_insert_time = 1; - tape->insert_time = jiffies; - tape->insert_size = 0; - tape->insert_speed = 0; - idetape_insert_pipeline_into_queue (drive); - } else if (tape->onstream) { - idetape_update_stats(drive); - if (tape->cur_frames < tape->max_frames - 5) - idetape_insert_pipeline_into_queue (drive); - } - } - return 0; -} - -static int idetape_get_logical_blk(struct ata_device *drive, int logical_blk_num, int max_stages, int quiet) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - int cnt = 0, x, position; - - /* - * Search and wait for the next logical tape block - */ - while (1) { - if (cnt++ > 1000) { /* AJN: was 100 */ - printk(KERN_INFO "ide-tape: %s: couldn't find logical block %d, aborting\n", tape->name, logical_blk_num); - return 0; - } - idetape_initiate_read(drive, max_stages); - if (tape->first_stage == NULL) { - if (tape->onstream) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: first_stage == NULL, pipeline error %ld\n", tape->name, (long)test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)); -#endif - clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); - position = idetape_read_position(drive); - printk(KERN_INFO "ide-tape: %s: blank block detected at %d\n", tape->name, position); - if (position >= 3000 && position < 3080) - position += 32; /* Why is this check and number ??? MM */ - if (position >= OS_DATA_ENDFRAME1 && position < 3000) - position = 3000; - else - /* - * compensate for write errors that generally skip 80 frames, - * expect around 20 read errors in a row... - */ - position += 60; - if (position >= OS_DATA_ENDFRAME1 && position < 3000) - position = 3000; - printk(KERN_INFO "ide-tape: %s: positioning tape to block %d\n", tape->name, position); - if (position == 3000) /* seems to be needed to correctly position at block 3000 MM */ - idetape_position_tape(drive, 0, 0, 0); - idetape_position_tape(drive, position, 0, 0); - cnt += 40; - continue; - } else - return 0; - } - idetape_wait_first_stage(drive); - if (idetape_verify_stage(drive, tape->first_stage, logical_blk_num, quiet)) - break; - if (tape->first_stage->rq.errors == IDETAPE_ERROR_EOD) - cnt--; - if (idetape_verify_stage(drive, tape->first_stage, -1, quiet)) { - x = ntohl(tape->first_stage->aux->logical_blk_num); - if (x > logical_blk_num) { - printk(KERN_ERR "ide-tape: %s: couldn't find logical block %d, aborting (block %d found)\n", tape->name, logical_blk_num, x); - return 0; - } - } - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - if (tape->onstream) - tape->logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num); - return 1; -} - -/* - * idetape_add_chrdev_read_request is called from idetape_chrdev_read - * to service a character device read request and add read-ahead - * requests to our pipeline. - */ -static int idetape_add_chrdev_read_request(struct ata_device *drive,int blocks) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - struct request *rq_ptr; - int bytes_read; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_read_request, %d blocks\n", blocks); -#endif /* IDETAPE_DEBUG_LOG */ - - /* - * Wait for the next logical block to be available at the head - * of the pipeline - */ - if (!idetape_get_logical_blk(drive, tape->logical_blk_num, tape->max_stages, 0)) { - if (tape->onstream) { - set_bit(IDETAPE_READ_ERROR, &tape->flags); - return 0; - } - if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)) - return 0; - return idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bio); - } - rq_ptr = &tape->first_stage->rq; - bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors); - rq_ptr->nr_sectors = rq_ptr->current_nr_sectors = 0; - - - if (tape->onstream && !tape->raw && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: EOD reached\n", tape->name); -#endif - return 0; - } - if (rq_ptr->errors == IDETAPE_ERROR_EOD) - return 0; - if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) { - idetape_switch_buffers (tape, tape->first_stage); - set_bit (IDETAPE_FILEMARK, &tape->flags); -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif - calculate_speeds(drive); - } else { - idetape_switch_buffers (tape, tape->first_stage); - if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read); -#endif - } - clear_bit (IDETAPE_FILEMARK, &tape->flags); - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - tape->logical_blk_num++; - 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 - return (bytes_read); -} - -static void idetape_pad_zeros(struct ata_device *drive, int bcount) -{ - idetape_tape_t *tape = drive->driver_data; - struct bio *bio; - int blocks; - - while (bcount) { - unsigned int count; - - bio = tape->merge_stage->bio; - count = min(tape->stage_size, bcount); - bcount -= count; - blocks = count / tape->tape_block_size; - while (count) { - atomic_set(&bio->bi_cnt, min(count, bio->bi_size)); - memset (bio_data(bio), 0, bio->bi_size); - count -= atomic_read(&bio->bi_cnt); - bio = bio->bi_next; - } - idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bio); - } -} - -static int idetape_pipeline_size(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - struct request *rq; - int size = 0; - - idetape_wait_for_pipeline (drive); - stage = tape->first_stage; - while (stage != NULL) { - rq = &stage->rq; - size += tape->tape_block_size * (rq->nr_sectors-rq->current_nr_sectors); - if (rq->errors == IDETAPE_ERROR_FILEMARK) - size += tape->tape_block_size; - stage = stage->next; - } - size += tape->merge_stage_size; - return size; -} - -/* - * Rewinds the tape to the Beginning Of the current Partition (BOP). - * - * We currently support only one partition. - */ -static int idetape_rewind_tape(struct ata_device *drive) -{ - int retval; - struct atapi_packet_command pc; - idetape_tape_t *tape = drive->driver_data; -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Reached idetape_rewind_tape\n"); -#endif - - idetape_create_rewind_cmd (drive, &pc); - retval = idetape_queue_pc_tail (drive, &pc); - if (retval) - return retval; - - idetape_create_read_position_cmd (&pc); - retval = idetape_queue_pc_tail (drive, &pc); - if (retval) - return retval; - tape->logical_blk_num = 0; - return 0; -} - -/* - * Our special ide-tape ioctl's. - * - * Currently there aren't any ioctl's. - * mtio.h compatible commands should be issued to the character device - * interface. - */ -static int idetape_blkdev_ioctl(struct ata_device *drive, struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_config_t config; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n"); -#endif - switch (cmd) { - case 0x0340: - if (copy_from_user ((char *) &config, (char *) arg, sizeof (idetape_config_t))) - return -EFAULT; - tape->best_dsc_rw_frequency = config.dsc_rw_frequency; - tape->max_stages = config.nr_stages; - break; - case 0x0350: - config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency; - config.nr_stages = tape->max_stages; - if (copy_to_user ((char *) arg, (char *) &config, sizeof (idetape_config_t))) - return -EFAULT; - break; - default: - return -EIO; - } - return 0; -} - -/* - * The block device interface should not be used for data transfers. - * However, we still allow opening it so that we can issue general - * ide driver configuration ioctl's, such as the interrupt unmask feature. - */ -static int idetape_blkdev_open(struct inode *inode, struct file *filp, struct ata_device *drive) -{ - MOD_INC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_blkdev_open\n"); -#endif - return 0; -} - -static void idetape_blkdev_release(struct inode *inode, struct file *filp, struct ata_device *drive) -{ - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_blkdev_release\n"); -#endif -} - -/* - * Character device interface functions - */ -static struct ata_device *get_drive_ptr (kdev_t i_rdev) -{ - unsigned int i = minor(i_rdev) & ~0xc0; - - if (i >= MAX_HWIFS * MAX_DRIVES) - return NULL; - return (idetape_chrdevs[i].drive); -} - -static int idetape_onstream_space_over_filemarks_backward(struct ata_device *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0; - int last_mark_addr; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_bwd\n", tape->name); - return -EIO; - } - while (cnt != mt_count) { - last_mark_addr = ntohl(tape->first_stage->aux->last_mark_addr); - if (last_mark_addr == -1) - return -EIO; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: positioning to last mark at %d\n", last_mark_addr); -#endif - idetape_position_tape(drive, last_mark_addr, 0, 0); - cnt++; - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, last_mark_addr); - return -EIO; - } - } - if (mt_op == MTBSFM) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - -/* - * ADRL 1.1 compatible "slow" space filemarks fwd version - * - * Just scans for the filemark sequentially. - */ -static int idetape_onstream_space_over_filemarks_forward_slow(struct ata_device *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); - return -EIO; - } - while (1) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) - cnt++; - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); -#endif - return -EIO; - } - if (cnt == mt_count) - break; - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - if (mt_op == MTFSF) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - - -/* - * Fast linux specific version of OnStream FSF - */ -static int idetape_onstream_space_over_filemarks_forward_fast(struct ata_device *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0, next_mark_addr; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); - return -EIO; - } - - /* - * Find nearest (usually previous) marker - */ - while (1) { - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) - break; - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); -#endif - return -EIO; - } - if (ntohl(tape->first_stage->aux->filemark_cnt) == 0) { - if (tape->first_mark_addr == -1) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); - return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); - } - idetape_position_tape(drive, tape->first_mark_addr, 0, 0); - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd_fast\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find filemark at %d\n", tape->name, tape->first_mark_addr); - return -EIO; - } - } else { - if (idetape_onstream_space_over_filemarks_backward(drive, MTBSF, 1) < 0) - return -EIO; - mt_count++; - } - } - cnt++; - while (cnt != mt_count) { - next_mark_addr = ntohl(tape->first_stage->aux->next_mark_addr); - if (!next_mark_addr || next_mark_addr > tape->eod_frame_addr) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); - return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count - cnt); -#if ONSTREAM_DEBUG - } else if (tape->debug_level >= 2) { - printk(KERN_INFO "ide-tape: positioning to next mark at %d\n", next_mark_addr); -#endif - } - idetape_position_tape(drive, next_mark_addr, 0, 0); - cnt++; - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, next_mark_addr); - return -EIO; - } - } - if (mt_op == MTFSF) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - -/* - * idetape_space_over_filemarks is now a bit more complicated than just - * passing the command to the tape since we may have crossed some - * filemarks during our pipelined read-ahead mode. - * - * As a minor side effect, the pipeline enables us to support MTFSFM when - * the filemark is in our internal pipeline even if the tape doesn't - * support spacing over filemarks in the reverse direction. - */ -static int idetape_space_over_filemarks(struct ata_device *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command pc; - unsigned long flags; - int retval,count=0; - int speed_control; - - if (tape->onstream) { - if (tape->raw) - return -EIO; - speed_control = tape->speed_control; - tape->speed_control = 0; - if (mt_op == MTFSF || mt_op == MTFSFM) { - if (tape->linux_media) - retval = idetape_onstream_space_over_filemarks_forward_fast(drive, mt_op, mt_count); - else - retval = idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); - } else - retval = idetape_onstream_space_over_filemarks_backward(drive, mt_op, mt_count); - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - return retval; - } - - if (tape->chrdev_direction == idetape_direction_read) { - /* - * We have a read-ahead buffer. Scan it for crossed - * filemarks. - */ - tape->merge_stage_size = 0; - clear_bit (IDETAPE_FILEMARK, &tape->flags); - while (tape->first_stage != NULL) { - idetape_wait_first_stage(drive); - if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) - count++; - if (count == mt_count) { - switch (mt_op) { - case MTFSF: - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - case MTFSFM: - return (0); - default: - break; - } - } - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - idetape_discard_read_pipeline (drive, 1); - } - - /* - * The filemark was not found in our internal pipeline. - * Now we can issue the space command. - */ - switch (mt_op) { - case MTFSF: - idetape_create_space_cmd (&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive, &pc)); - case MTFSFM: - if (!tape->capabilities.sprev) - return (-EIO); - retval = idetape_space_over_filemarks (drive, MTFSF, mt_count-count); - if (retval) return (retval); - return (idetape_space_over_filemarks (drive, MTBSF, 1)); - case MTBSF: - if (!tape->capabilities.sprev) - return (-EIO); - idetape_create_space_cmd (&pc,-(mt_count+count),IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive, &pc)); - case MTBSFM: - if (!tape->capabilities.sprev) - return (-EIO); - retval = idetape_space_over_filemarks (drive, MTBSF, mt_count+count); - if (retval) return (retval); - return (idetape_space_over_filemarks (drive, MTFSF, 1)); - default: - printk (KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); - return (-EIO); - } -} - - -/* - * Our character device read / write functions. - * - * The tape is optimized to maximize throughput when it is transferring - * an integral number of the "continuous transfer limit", which is - * a parameter of the specific tape (26 KB on my particular tape). - * (32 kB for Onstream) - * - * As of version 1.3 of the driver, the character device provides an - * abstract continuous view of the media - any mix of block sizes (even 1 - * byte) on the same backup/restore procedure is supported. The driver - * will internally convert the requests to the recommended transfer unit, - * so that an unmatch between the user's block size to the recommended - * size will only result in a (slightly) increased driver overhead, but - * will no longer hit performance. - * This is not applicable to Onstream. - */ -static ssize_t idetape_chrdev_read (struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - struct inode *inode = file->f_dentry->d_inode; - struct ata_device *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape = drive->driver_data; - ssize_t bytes_read,temp, actually_read = 0, rc; - - if (ppos != &file->f_pos) { - /* "A request was outside the capabilities of the device." */ - return -ENXIO; - } - if (tape->onstream && (count != tape->tape_block_size)) { - printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count); - return -EINVAL; - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count); -#endif /* IDETAPE_DEBUG_LOG */ - - if (tape->chrdev_direction != idetape_direction_read) { - if (test_bit (IDETAPE_DETECT_BS, &tape->flags)) - if (count > tape->tape_block_size && (count % tape->tape_block_size) == 0) - tape->user_bs_factor = count / tape->tape_block_size; - } - if ((rc = idetape_initiate_read(drive, tape->max_stages)) < 0) - return rc; - if (count == 0) - return (0); - if (tape->merge_stage_size) { - actually_read = min(tape->merge_stage_size, count); - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, actually_read); - buf += actually_read; - tape->merge_stage_size -= actually_read; - count -= actually_read; - } - while (count >= tape->stage_size) { - bytes_read = idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); - if (bytes_read <= 0) - goto finish; - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, bytes_read); - buf += bytes_read; - count -= bytes_read; - actually_read += bytes_read; - } - if (count) { - bytes_read=idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); - if (bytes_read <= 0) - goto finish; - temp = min(count, bytes_read); - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, temp); - actually_read += temp; - tape->merge_stage_size = bytes_read-temp; - } -finish: - if (!actually_read && test_bit (IDETAPE_FILEMARK, &tape->flags)) { -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: spacing over filemark\n", tape->name); -#endif - idetape_space_over_filemarks (drive, MTFSF, 1); - return 0; - } - if (tape->onstream && !actually_read && test_and_clear_bit(IDETAPE_READ_ERROR, &tape->flags)) { - printk(KERN_ERR "ide-tape: %s: unrecovered read error on logical block number %d, skipping\n", - tape->name, tape->logical_blk_num); - tape->logical_blk_num++; - return -EIO; - } - return actually_read; -} - -static void idetape_update_last_marker(struct ata_device *drive, int last_mark_addr, int next_mark_addr) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_aux_t *aux; - int position; - - if (!tape->onstream || tape->raw) - return; - if (last_mark_addr == -1) - return; - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (stage == NULL) - return; - idetape_flush_tape_buffers(drive); - position = idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) %d, lblk %d\n", position, tape->logical_blk_num); - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) tape block %d\n", tape->last_frame_position); -#endif - idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bio)) { - printk(KERN_INFO "ide-tape: %s: couldn't read last marker\n", tape->name); - __idetape_kfree_stage (stage); - idetape_position_tape(drive, position, 0, 0); - return; - } - aux = stage->aux; - if (aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at addr %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage (stage); - idetape_position_tape(drive, position, 0, 0); - return; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: writing back marker\n"); -#endif - aux->next_mark_addr = htonl(next_mark_addr); - idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bio)) { - printk(KERN_INFO "ide-tape: %s: couldn't write back marker frame at %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage (stage); - idetape_position_tape(drive, position, 0, 0); - return; - } - __idetape_kfree_stage (stage); - idetape_flush_tape_buffers (drive); - idetape_position_tape(drive, position, 0, 0); - return; -} - -static void idetape_write_filler(struct ata_device *drive, int block, int cnt) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - int rc; - - if (!tape->onstream || tape->raw) - return; - stage = __idetape_kmalloc_stage(tape, 1, 1); - if (stage == NULL) - return; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_FILL, 0); - idetape_wait_ready(drive, 60 * 5 * HZ); - rc = idetape_position_tape(drive, block, 0, 0); -#if ONSTREAM_DEBUG - printk(KERN_INFO "write_filler: positioning failed it returned %d\n", rc); -#endif - if (rc != 0) - return; /* don't write fillers if we cannot position the tape. */ - - strcpy(bio_data(stage->bio), "Filler"); - while (cnt--) { - if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bio)) { - printk(KERN_INFO "ide-tape: %s: write_filler: couldn't write header frame\n", tape->name); - __idetape_kfree_stage (stage); - return; - } - } - __idetape_kfree_stage (stage); -} - -static void __idetape_write_header(struct ata_device *drive, int block, int cnt) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_header_t header; - - stage = __idetape_kmalloc_stage(tape, 1, 1); - if (stage == NULL) - return; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_HEADER, tape->logical_blk_num); - idetape_wait_ready(drive, 60 * 5 * HZ); - idetape_position_tape(drive, block, 0, 0); - memset(&header, 0, sizeof(header)); - strcpy(header.ident_str, "ADR_SEQ"); - header.major_rev = 1; - header.minor_rev = OS_ADR_MINREV; - header.par_num = 1; - header.partition.partition_num = OS_DATA_PARTITION; - header.partition.par_desc_ver = OS_PARTITION_VERSION; - header.partition.first_frame_addr = htonl(OS_DATA_STARTFRAME1); - header.partition.last_frame_addr = htonl(tape->capacity); - header.partition.wrt_pass_cntr = htons(tape->wrt_pass_cntr); - header.partition.eod_frame_addr = htonl(tape->eod_frame_addr); - memcpy(bio_data(stage->bio), &header, sizeof(header)); - while (cnt--) { - if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bio)) { - printk(KERN_INFO "ide-tape: %s: couldn't write header frame\n", tape->name); - __idetape_kfree_stage (stage); - return; - } - } - __idetape_kfree_stage (stage); - idetape_flush_tape_buffers (drive); -} - -static void idetape_write_header(struct ata_device *drive, int locate_eod) -{ - idetape_tape_t *tape = drive->driver_data; - -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: writing tape header\n", tape->name); -#endif - if (!tape->onstream || tape->raw) - return; - tape->update_frame_cntr++; - __idetape_write_header(drive, 5, 5); - __idetape_write_header(drive, 0xbae, 5); /* 2990 */ - if (locate_eod) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: locating back to eod frame addr %d\n", tape->name, tape->eod_frame_addr); -#endif - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - } -} - -static ssize_t idetape_chrdev_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct inode *inode = file->f_dentry->d_inode; - struct ata_device *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape = drive->driver_data; - ssize_t retval, actually_written = 0; - int position; - - if (ppos != &file->f_pos) { - /* "A request was outside the capabilities of the device." */ - return -ENXIO; - } - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_write, count %Zd\n", count); -#endif - - if (tape->onstream) { - if (count != tape->tape_block_size) { - printk(KERN_ERR "ide-tape: %s: chrdev_write: use %d bytes as block size (%Zd used)\n", - tape->name, tape->tape_block_size, count); - return -EINVAL; - } - /* - * Check if we reach the end of the tape. Just assume the whole pipeline - * is filled with write requests! - */ - if (tape->first_frame_position + tape->nr_stages >= tape->capacity - OS_EW) { -#if ONSTREAM_DEBUG - printk(KERN_INFO, "chrdev_write: Write truncated at EOM early warning"); -#endif - if (tape->chrdev_direction == idetape_direction_write) - idetape_write_release(inode); - return -ENOSPC; - } - } - - if (tape->chrdev_direction != idetape_direction_write) { /* Initialize write operation */ - 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 - if ((tape->merge_stage = __idetape_kmalloc_stage (tape, 0, 0)) == NULL) - return -ENOMEM; - tape->chrdev_direction = idetape_direction_write; - idetape_init_merge_stage (tape); - - if (tape->onstream) { - position = idetape_read_position(drive); - if (position <= OS_DATA_STARTFRAME1) { - tape->logical_blk_num = 0; - tape->wrt_pass_cntr++; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to %d\n", tape->name, OS_DATA_STARTFRAME1); - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: allocating new write pass counter %d\n", tape->name, tape->wrt_pass_cntr); -#endif - tape->filemark_cnt = 0; - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->first_mark_addr = tape->last_mark_addr = -1; - idetape_write_header(drive, 1); - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr); -#endif - position = idetape_read_position(drive); - if (position != tape->eod_frame_addr) - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: first_frame_position %d\n", tape->name, tape->first_frame_position); -#endif - } - - /* - * Issue a write 0 command to ensure that DSC handshake - * is switched from completion mode to buffer available - * mode. - */ - retval = idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bio); - if (retval < 0) { - kfree (tape->merge_stage); - tape->merge_stage = NULL; - tape->chrdev_direction = idetape_direction_none; - return retval; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: first_frame_position %d\n", tape->first_frame_position); -#endif - } - if (count == 0) - return (0); - 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(tape->stage_size - tape->merge_stage_size, count); - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, actually_written); - buf += actually_written; - tape->merge_stage_size += actually_written; - count -= actually_written; - - if (tape->merge_stage_size == tape->stage_size) { - tape->merge_stage_size = 0; - retval = idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); - if (retval <= 0) - return (retval); - } - } - while (count >= tape->stage_size) { - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, tape->stage_size); - buf += tape->stage_size; - count -= tape->stage_size; - retval = idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); - actually_written += tape->stage_size; - if (retval <= 0) - return (retval); - } - if (count) { - actually_written+=count; - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, count); - tape->merge_stage_size += count; - } - return (actually_written); -} - -static int idetape_write_filemark(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int last_mark_addr; - struct atapi_packet_command pc; - - if (!tape->onstream) { - idetape_create_write_filemark_cmd(drive, &pc, 1); /* Write a filemark */ - if (idetape_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-tape: Couldn't write a filemark\n"); - return -EIO; - } - } else if (!tape->raw) { - last_mark_addr = idetape_read_position(drive); - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); - if (tape->merge_stage != NULL) { - idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_MARKER, tape->logical_blk_num); - idetape_pad_zeros (drive, tape->stage_size); - tape->logical_blk_num++; - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - if (tape->filemark_cnt) - idetape_update_last_marker(drive, tape->last_mark_addr, last_mark_addr); - tape->last_mark_addr = last_mark_addr; - if (tape->filemark_cnt++ == 0) - tape->first_mark_addr = last_mark_addr; - } - return 0; -} - -static void idetape_write_eod(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (!tape->onstream || tape->raw) - return; - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); - if (tape->merge_stage != NULL) { - tape->eod_frame_addr = idetape_read_position(drive); - idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_EOD, tape->logical_blk_num); - idetape_pad_zeros (drive, tape->stage_size); - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - return; -} - -int idetape_seek_logical_blk(struct ata_device *drive, int logical_blk_num) -{ - idetape_tape_t *tape = drive->driver_data; - int estimated_address = logical_blk_num + 20; - int retries = 0; - int speed_control; - - speed_control = tape->speed_control; - tape->speed_control = 0; - if (logical_blk_num < 0) - logical_blk_num = 0; - if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1)) - goto ok; - while (++retries < 10) { - idetape_discard_read_pipeline(drive, 0); - idetape_position_tape(drive, estimated_address, 0, 0); - if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1)) - goto ok; - if (!idetape_get_logical_blk(drive, -1, 10, 1)) - goto error; - if (tape->logical_blk_num < logical_blk_num) - estimated_address += logical_blk_num - tape->logical_blk_num; - else - break; - } -error: - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - printk(KERN_INFO "ide-tape: %s: couldn't seek to logical block %d (at %d), %d retries\n", tape->name, logical_blk_num, tape->logical_blk_num, retries); - return -EIO; -ok: - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - return 0; -} - -/* - * 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. - * - * MTBSFM - Like MTBSF, only tape is positioned after the last filemark. - * - * Note: - * - * MTBSF and MTBSFM are not supported when the tape doesn't - * supports 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. - */ -static int idetape_mtioctop(struct ata_device *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command pc; - int i,retval; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",mt_op,mt_count); -#endif /* IDETAPE_DEBUG_LOG */ - /* - * Commands which need our pipelined read-ahead stages. - */ - switch (mt_op) { - case MTFSF: - case MTFSFM: - case MTBSF: - case MTBSFM: - if (!mt_count) - return (0); - return (idetape_space_over_filemarks (drive,mt_op,mt_count)); - default: - break; - } - switch (mt_op) { - case MTWEOF: - idetape_discard_read_pipeline (drive, 1); - for (i = 0; i < mt_count; i++) { - retval = idetape_write_filemark(drive); - if (retval) return retval; - } - return (0); - case MTREW: - idetape_discard_read_pipeline (drive, 0); - if (idetape_rewind_tape(drive)) - return -EIO; - if (tape->onstream && !tape->raw) - return idetape_position_tape(drive, OS_DATA_STARTFRAME1, 0, 0); - return 0; - case MTLOAD: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc, IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive, &pc)); - case MTUNLOAD: - case MTOFFL: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc,!IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive, &pc)); - case MTNOP: - idetape_discard_read_pipeline (drive, 0); - return (idetape_flush_tape_buffers (drive)); - case MTRETEN: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive, &pc)); - case MTEOM: - if (tape->onstream) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr); -#endif - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_EOD) - return -EIO; - return 0; - } - idetape_create_space_cmd (&pc, 0, IDETAPE_SPACE_TO_EOD); - return (idetape_queue_pc_tail (drive, &pc)); - case MTERASE: - if (tape->onstream) { - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->logical_blk_num = 0; - tape->first_mark_addr = tape->last_mark_addr = -1; - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - idetape_write_eod(drive); - idetape_flush_tape_buffers (drive); - idetape_write_header(drive, 0); - /* - * write filler frames to the unused frames... - * REMOVE WHEN going to LIN4 application type... - */ - idetape_write_filler(drive, OS_DATA_STARTFRAME1 - 10, 10); - idetape_write_filler(drive, OS_DATA_ENDFRAME1, 10); - idetape_flush_tape_buffers (drive); - (void) idetape_rewind_tape (drive); - return 0; - } - (void) idetape_rewind_tape (drive); - idetape_create_erase_cmd (&pc); - return (idetape_queue_pc_tail (drive, &pc)); - case MTSETBLK: - if (tape->onstream) { - if (mt_count != tape->tape_block_size) { - printk(KERN_INFO "ide-tape: %s: MTSETBLK %d -- only %d bytes block size supported\n", tape->name, mt_count, tape->tape_block_size); - return -EINVAL; - } - return 0; - } - if (mt_count) { - if (mt_count < tape->tape_block_size || mt_count % tape->tape_block_size) - return -EIO; - tape->user_bs_factor = mt_count / tape->tape_block_size; - clear_bit (IDETAPE_DETECT_BS, &tape->flags); - } else - set_bit (IDETAPE_DETECT_BS, &tape->flags); - return 0; - case MTSEEK: - if (!tape->onstream || tape->raw) { - idetape_discard_read_pipeline (drive, 0); - return idetape_position_tape (drive, mt_count * tape->user_bs_factor, tape->partition, 0); - } - return idetape_seek_logical_blk(drive, mt_count); - case MTSETPART: - idetape_discard_read_pipeline (drive, 0); - if (tape->onstream) - return -EIO; - return (idetape_position_tape (drive, 0, mt_count, 0)); - case MTFSR: - case MTBSR: - if (tape->onstream) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - if (mt_op == MTFSR) - return idetape_seek_logical_blk(drive, tape->logical_blk_num + mt_count); - else { - idetape_discard_read_pipeline (drive, 0); - return idetape_seek_logical_blk(drive, tape->logical_blk_num - mt_count); - } - } - case MTLOCK: - if (!idetape_create_prevent_cmd(drive, &pc, 1)) - return 0; - retval = idetape_queue_pc_tail (drive, &pc); - if (retval) return retval; - tape->door_locked = DOOR_EXPLICITLY_LOCKED; - return 0; - case MTUNLOCK: - if (!idetape_create_prevent_cmd(drive, &pc, 0)) - return 0; - retval = idetape_queue_pc_tail (drive, &pc); - if (retval) return retval; - tape->door_locked = DOOR_UNLOCKED; - return 0; - default: - printk (KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); - return (-EIO); - } -} - -/* - * 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. - */ -static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct ata_device *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape = drive->driver_data; - struct mtop mtop; - struct mtget mtget; - struct mtpos mtpos; - int block_offset = 0, position = tape->first_frame_position; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_ioctl, cmd=%u\n",cmd); -#endif /* IDETAPE_DEBUG_LOG */ - - tape->restart_speed_control_req = 1; - if (tape->chrdev_direction == idetape_direction_write) { - idetape_empty_write_pipeline (drive); - idetape_flush_tape_buffers (drive); - } - if (cmd == MTIOCGET || cmd == MTIOCPOS) { - block_offset = idetape_pipeline_size (drive) / (tape->tape_block_size * tape->user_bs_factor); - if ((position = idetape_read_position(drive)) < 0) - return -EIO; - } - switch (cmd) { - case MTIOCTOP: - if (copy_from_user ((char *) &mtop, (char *) arg, sizeof (struct mtop))) - return -EFAULT; - return (idetape_mtioctop (drive,mtop.mt_op,mtop.mt_count)); - case MTIOCGET: - memset (&mtget, 0, sizeof (struct mtget)); - mtget.mt_type = MT_ISSCSI2; - if (!tape->onstream || tape->raw) - mtget.mt_blkno = position / tape->user_bs_factor - block_offset; - else { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - mtget.mt_blkno = -1; - else - mtget.mt_blkno = tape->logical_blk_num; - } - mtget.mt_dsreg = ((tape->tape_block_size * tape->user_bs_factor) << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK; - if (tape->onstream) { - mtget.mt_gstat |= GMT_ONLINE(0xffffffff); - if (tape->first_stage && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) - mtget.mt_gstat |= GMT_EOD(0xffffffff); - if (position <= OS_DATA_STARTFRAME1) - mtget.mt_gstat |= GMT_BOT(0xffffffff); - } - if (copy_to_user ((char *) arg,(char *) &mtget, sizeof (struct mtget))) - return -EFAULT; - return 0; - case MTIOCPOS: - if (tape->onstream && !tape->raw) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - mtpos.mt_blkno = tape->logical_blk_num; - } else - mtpos.mt_blkno = position / tape->user_bs_factor - block_offset; - if (copy_to_user ((char *) arg,(char *) &mtpos, sizeof (struct mtpos))) - return -EFAULT; - return 0; - default: - if (tape->chrdev_direction == idetape_direction_read) - idetape_discard_read_pipeline (drive, 1); - return (idetape_blkdev_ioctl (drive,inode,file,cmd,arg)); - } -} - -static int __idetape_analyze_headers(struct ata_device *drive, int block) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_header_t *header; - os_aux_t *aux; - - if (!tape->onstream || tape->raw) { - tape->header_ok = tape->linux_media = 1; - return 1; - } - tape->header_ok = tape->linux_media = 0; - tape->update_frame_cntr = 0; - tape->wrt_pass_cntr = 0; - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->first_mark_addr = tape->last_mark_addr = -1; - stage = __idetape_kmalloc_stage (tape, 0, 0); - if (stage == NULL) - return 0; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name); -#endif - idetape_position_tape(drive, block, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bio)) { - printk(KERN_INFO "ide-tape: %s: couldn't read header frame\n", tape->name); - __idetape_kfree_stage (stage); - return 0; - } - header = (os_header_t *) bio_data(stage->bio); - aux = stage->aux; - if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0) { - printk(KERN_INFO "ide-tape: %s: invalid header identification string\n", tape->name); - __idetape_kfree_stage (stage); - return 0; - } - if (header->major_rev != 1 || (header->minor_rev > OS_ADR_MINREV)) - printk(KERN_INFO "ide-tape: warning: revision %d.%d detected (up to 1.%d supported)\n", header->major_rev, header->minor_rev, OS_ADR_MINREV); - if (header->par_num != 1) - printk(KERN_INFO "ide-tape: warning: %d partitions defined, only one supported\n", header->par_num); - tape->wrt_pass_cntr = ntohs(header->partition.wrt_pass_cntr); - tape->eod_frame_addr = ntohl(header->partition.eod_frame_addr); - tape->filemark_cnt = ntohl(aux->filemark_cnt); - tape->first_mark_addr = ntohl(aux->next_mark_addr); - tape->last_mark_addr = ntohl(aux->last_mark_addr); - tape->update_frame_cntr = ntohl(aux->update_frame_cntr); - memcpy(tape->application_sig, aux->application_sig, 4); - tape->application_sig[4] = 0; - if (memcmp(tape->application_sig, "LIN", 3) == 0) { - tape->linux_media = 1; - tape->linux_media_version = tape->application_sig[3] - '0'; - if (tape->linux_media_version != 3) - printk(KERN_INFO "ide-tape: %s: Linux media version %d detected (current 3)\n", - tape->name, tape->linux_media_version); - } else { - printk(KERN_INFO "ide-tape: %s: non Linux media detected (%s)\n", tape->name, tape->application_sig); - tape->linux_media = 0; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: detected write pass counter %d, eod frame addr %d\n", tape->name, tape->wrt_pass_cntr, tape->eod_frame_addr); -#endif - __idetape_kfree_stage (stage); - return 1; -} - -static int idetape_analyze_headers(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int position, block; - - if (!tape->onstream || tape->raw) { - tape->header_ok = tape->linux_media = 1; - return 1; - } - tape->header_ok = tape->linux_media = 0; - position = idetape_read_position(drive); - for (block = 5; block < 10; block++) - if (__idetape_analyze_headers(drive, block)) - goto ok; - for (block = 0xbae; block < 0xbb3; block++) /* 2990 - 2994 */ - if (__idetape_analyze_headers(drive, block)) - goto ok; - printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", tape->name); - return 0; -ok: - if (position < OS_DATA_STARTFRAME1) - position = OS_DATA_STARTFRAME1; - idetape_position_tape(drive, position, 0, 0); - tape->header_ok = 1; - return 1; -} - -/* - * Our character device open function. - */ -static int idetape_chrdev_open (struct inode *inode, struct file *filp) -{ - struct ata_device *drive; - idetape_tape_t *tape; - struct atapi_packet_command pc; - unsigned int minor=minor(inode->i_rdev); - -#if IDETAPE_DEBUG_LOG - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_open\n"); -#endif - - if ((drive = get_drive_ptr (inode->i_rdev)) == NULL) - return -ENXIO; - tape = drive->driver_data; - - if (test_and_set_bit (IDETAPE_BUSY, &tape->flags)) - return -EBUSY; - MOD_INC_USE_COUNT; - if (!tape->onstream) { - idetape_read_position(drive); - if (!test_bit (IDETAPE_ADDRESS_VALID, &tape->flags)) - (void) idetape_rewind_tape (drive); - } else { - if (minor & 64) { - tape->tape_block_size = tape->stage_size = 32768 + 512; - tape->raw = 1; - } else { - tape->tape_block_size = tape->stage_size = 32768; - tape->raw = 0; - } - idetape_onstream_mode_sense_tape_parameter_page(drive, tape->debug_level); - } - if (idetape_wait_ready(drive, 60 * HZ)) { - clear_bit(IDETAPE_BUSY, &tape->flags); - printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - idetape_read_position(drive); - MOD_DEC_USE_COUNT; - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - - if (tape->chrdev_direction == idetape_direction_none) { - MOD_INC_USE_COUNT; - if (idetape_create_prevent_cmd(drive, &pc, 1)) { - if (!idetape_queue_pc_tail (drive, &pc)) { - if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) - tape->door_locked = DOOR_LOCKED; - } - } - idetape_analyze_headers(drive); - } - tape->max_frames = tape->cur_frames = tape->req_buffer_fill = 0; - idetape_restart_speed_control(drive); - tape->restart_speed_control_req = 0; - return 0; -} - -static void idetape_write_release (struct inode *inode) -{ - struct ata_device *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape = drive->driver_data; - unsigned int minor=minor(inode->i_rdev); - - idetape_empty_write_pipeline (drive); - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); - if (tape->merge_stage != NULL) { - idetape_pad_zeros (drive, tape->tape_block_size * (tape->user_bs_factor - 1)); - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - idetape_write_filemark(drive); - idetape_write_eod(drive); - idetape_flush_tape_buffers (drive); - idetape_write_header(drive, minor >= 128); - idetape_flush_tape_buffers (drive); - - return; -} - -/* - * Our character device release function. - */ -static int idetape_chrdev_release (struct inode *inode, struct file *filp) -{ - struct ata_device *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape; - struct atapi_packet_command pc; - unsigned int minor=minor(inode->i_rdev); - - tape = drive->driver_data; -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_release\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - if (tape->chrdev_direction == idetape_direction_write) { - idetape_write_release(inode); - } - if (tape->chrdev_direction == idetape_direction_read) { - if (minor < 128) - idetape_discard_read_pipeline (drive, 1); - else - idetape_wait_for_pipeline (drive); - } - if (tape->cache_stage != NULL) { - __idetape_kfree_stage (tape->cache_stage); - tape->cache_stage = NULL; - } - if (minor < 128) - (void) idetape_rewind_tape (drive); - if (tape->chrdev_direction == idetape_direction_none) { - if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) { - if (idetape_create_prevent_cmd(drive, &pc, 0)) - if (!idetape_queue_pc_tail (drive, &pc)) - tape->door_locked = DOOR_UNLOCKED; - } - MOD_DEC_USE_COUNT; - } - clear_bit (IDETAPE_BUSY, &tape->flags); - return 0; -} - -/* - * idetape_identify_device is called to check the contents of the - * ATAPI IDENTIFY command results. We return: - * - * 1 If the tape can be supported by us, based on the information - * we have so far. - * - * 0 If this tape driver is not currently supported by us. - */ -static int idetape_identify_device(struct ata_device *drive,struct hd_driveid *id) -{ - struct atapi_id_gcw gcw; -#if IDETAPE_DEBUG_INFO - unsigned short mask,i; -#endif /* IDETAPE_DEBUG_INFO */ - - if (!id) - return 0; - - *((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 (KERN_INFO "ATA\n");break; - case 2: printk (KERN_INFO "ATAPI\n");break; - case 3: printk (KERN_INFO "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 (KERN_INFO "Direct-access Device\n");break; - case 1: printk (KERN_INFO "Streaming Tape Device\n");break; - case 2: case 3: case 4: printk (KERN_INFO "Reserved\n");break; - case 5: printk (KERN_INFO "CD-ROM Device\n");break; - case 6: printk (KERN_INFO "Reserved\n"); - case 7: printk (KERN_INFO "Optical memory Device\n");break; - case 0x1f: printk (KERN_INFO "Unknown or no Device type\n");break; - default: printk (KERN_INFO "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 (KERN_INFO "Microprocessor DRQ\n");break; - case 1: printk (KERN_INFO "Interrupt DRQ\n");break; - case 2: printk (KERN_INFO "Accelerated DRQ\n");break; - case 3: printk (KERN_INFO "Reserved\n");break; - } - printk (KERN_INFO "ide-tape: Command Packet Size: "); - switch (gcw.packet_size) { - case 0: printk (KERN_INFO "12 bytes\n");break; - case 1: printk (KERN_INFO "16 bytes\n");break; - default: printk (KERN_INFO "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 (KERN_INFO "%d ",i); - if (id->dma_1word & (mask << 8)) - printk (KERN_INFO "(active) "); - } - printk (KERN_INFO "\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 (KERN_INFO "%d ",i); - if (id->dma_mword & (mask << 8)) - printk (KERN_INFO "(active) "); - } - printk (KERN_INFO "\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 (KERN_INFO "Not supported\n"); - else - printk (KERN_INFO "%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 (KERN_INFO "Not supported\n"); - else - printk (KERN_INFO "%d ns\n",id->eide_dma_time); - - printk (KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: "); - if (id->eide_pio == 0) - printk (KERN_INFO "Not supported\n"); - else - printk (KERN_INFO "%d ns\n",id->eide_pio); - - printk (KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: "); - if (id->eide_pio_iordy == 0) - printk (KERN_INFO "Not supported\n"); - else - printk (KERN_INFO "%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"); - else if (gcw.device_type != 1) - printk (KERN_ERR "ide-tape: Device type is not set to tape\n"); - 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"); - } else - return 1; - return 0; -} - -/* - * Notify vendor ID to the OnStream tape drive - */ -static void idetape_onstream_set_vendor(struct ata_device *drive, char *vendor) -{ - struct atapi_packet_command pc; - idetape_mode_parameter_header_t *header; - - idetape_create_mode_select_cmd(&pc, sizeof(*header) + 8); - pc.buffer[0] = 3 + 8; /* Mode Data Length */ - pc.buffer[1] = 0; /* Medium Type - ignoring */ - pc.buffer[2] = 0; /* Reserved */ - pc.buffer[3] = 0; /* Block Descriptor Length */ - pc.buffer[4 + 0] = 0x36 | (1 << 7); - pc.buffer[4 + 1] = 6; - pc.buffer[4 + 2] = vendor[0]; - pc.buffer[4 + 3] = vendor[1]; - pc.buffer[4 + 4] = vendor[2]; - pc.buffer[4 + 5] = vendor[3]; - pc.buffer[4 + 6] = 0; - pc.buffer[4 + 7] = 0; - if (idetape_queue_pc_tail (drive, &pc)) - printk (KERN_ERR "ide-tape: Couldn't set vendor name to %s\n", vendor); - -} - -/* - * Various unused OnStream commands - */ -#if ONSTREAM_DEBUG -static void idetape_onstream_set_retries(struct ata_device *drive, int retries) -{ - struct atapi_packet_command pc; - - idetape_create_mode_select_cmd(&pc, sizeof(idetape_mode_parameter_header_t) + 4); - pc.buffer[0] = 3 + 4; - pc.buffer[1] = 0; /* Medium Type - ignoring */ - pc.buffer[2] = 0; /* Reserved */ - pc.buffer[3] = 0; /* Block Descriptor Length */ - pc.buffer[4 + 0] = 0x2f | (1 << 7); - pc.buffer[4 + 1] = 2; - pc.buffer[4 + 2] = 4; - pc.buffer[4 + 3] = retries; - if (idetape_queue_pc_tail (drive, &pc)) - printk (KERN_ERR "ide-tape: Couldn't set retries to %d\n", retries); -} -#endif - -/* - * Configure 32.5KB block size. - */ -static void idetape_onstream_configure_block_size(struct ata_device *drive) -{ - struct atapi_packet_command pc; - idetape_mode_parameter_header_t *header; - idetape_block_size_page_t *bs; - - /* - * Get the current block size from the block size mode page - */ - idetape_create_mode_sense_cmd (&pc, IDETAPE_BLOCK_SIZE_PAGE); - if (idetape_queue_pc_tail (drive, &pc)) - printk (KERN_ERR "ide-tape: can't get tape block size mode page\n"); - header = (idetape_mode_parameter_header_t *) pc.buffer; - bs = (idetape_block_size_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - -#if IDETAPE_DEBUG_INFO - printk(KERN_INFO "ide-tape: 32KB play back: %s\n", bs->play32 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32.5KB play back: %s\n", bs->play32_5 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32KB record: %s\n", bs->record32 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32.5KB record: %s\n", bs->record32_5 ? "Yes" : "No"); -#endif /* IDETAPE_DEBUG_INFO */ - - /* - * Configure default auto columns mode, 32.5KB block size - */ - bs->one = 1; - bs->play32 = 0; - bs->play32_5 = 1; - bs->record32 = 0; - bs->record32_5 = 1; - idetape_create_mode_select_cmd(&pc, sizeof(*header) + sizeof(*bs)); - if (idetape_queue_pc_tail (drive, &pc)) - printk (KERN_ERR "ide-tape: Couldn't set tape block size mode page\n"); - -#if ONSTREAM_DEBUG - /* - * In debug mode, we want to see as many errors as possible - * to test the error recovery mechanism. - */ - idetape_onstream_set_retries(drive, 0); -#endif -} - -/* - * Use INQUIRY to get the firmware revision - */ -static void idetape_get_inquiry_results(struct ata_device *drive) -{ - char *r; - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command pc; - atapi_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); - return; - } - inquiry = (atapi_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); - 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'; - else if (tape->onstream) - tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 1) - '0') * 10 + *(r + 2) - '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); -} - -/* - * Configure the OnStream ATAPI tape drive for default operation - */ -static void idetape_configure_onstream(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (tape->firmware_revision_num < 105) { - printk(KERN_INFO "ide-tape: %s: Old OnStream firmware revision detected (%s)\n", tape->name, tape->firmware_revision); - printk(KERN_INFO "ide-tape: %s: An upgrade to version 1.05 or above is recommended\n", tape->name); - } - - /* - * Configure 32.5KB (data+aux) block size. - */ - idetape_onstream_configure_block_size(drive); - - /* - * Set vendor name to 'LIN3' for "Linux support version 3". - */ - idetape_onstream_set_vendor(drive, "LIN3"); -} - -/* - * idetape_get_mode_sense_parameters asks the tape about its various - * parameters. This may work for other drives to??? - */ -static void idetape_onstream_mode_sense_tape_parameter_page(struct ata_device *drive, int debug) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command pc; - idetape_mode_parameter_header_t *header; - onstream_tape_paramtr_page_t *prm; - - idetape_create_mode_sense_cmd (&pc, IDETAPE_PARAMTR_PAGE); - if (idetape_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-tape: Can't get tape parameters page - probably no tape inserted in onstream drive\n"); - return; - } - header = (idetape_mode_parameter_header_t *) pc.buffer; - prm = (onstream_tape_paramtr_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - - tape->capacity = ntohs(prm->segtrk) * ntohs(prm->trks); - if (debug) { - printk (KERN_INFO "ide-tape: %s <-> %s: Tape length %dMB (%d frames/track, %d tracks = %d blocks, density: %dKbpi)\n", - drive->name, tape->name, tape->capacity/32, ntohs(prm->segtrk), ntohs(prm->trks), tape->capacity, prm->density); - } - - return; -} - -/* - * 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. - */ -static void idetape_get_mode_sense_results(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command pc; - idetape_mode_parameter_header_t *header; - idetape_capabilities_page_t *capabilities; - - 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"); - tape->tape_block_size = 512; tape->capabilities.ctl = 52; - tape->capabilities.speed = 450; tape->capabilities.buffer_size = 6 * 52; - return; - } - header = (idetape_mode_parameter_header_t *) pc.buffer; - capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - - capabilities->max_speed = ntohs (capabilities->max_speed); - capabilities->ctl = ntohs (capabilities->ctl); - capabilities->speed = ntohs (capabilities->speed); - capabilities->buffer_size = ntohs (capabilities->buffer_size); - - if (!capabilities->speed) { - printk(KERN_INFO "ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name); - capabilities->speed = 650; - } - if (!capabilities->max_speed) { - printk(KERN_INFO "ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name); - capabilities->max_speed = 650; - } - - tape->capabilities = *capabilities; /* Save us a copy */ - if (capabilities->blk512) - tape->tape_block_size = 512; - else if (capabilities->blk1024) - tape->tape_block_size = 1024; - else if (tape->onstream && capabilities->blk32768) - tape->tape_block_size = 32768; - -#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(struct ata_device *drive) -{ - - idetape_tape_t *tape = drive->driver_data; - struct atapi_packet_command 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]; -#if IDETAPE_DEBUG_INFO - printk (KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); -#endif -} - -/* - * ide_setup is called to: - * - * 1. Initialize our various state variables. - * 2. Ask the tape for its capabilities. - * 3. Allocate a buffer which will be used for data - * transfer. The buffer size is chosen based on - * the recommendation which we received in step (2). - * - * Note that at this point ide.c already assigned us an irq, so that - * we can queue requests here and wait for their completion. - */ -static void idetape_setup(struct ata_device *drive, idetape_tape_t *tape, int minor) -{ - unsigned long t1, tmid, tn; - unsigned long t; - int speed; - struct atapi_id_gcw gcw; - int stage_size; - struct sysinfo si; - - memset (tape, 0, sizeof (idetape_tape_t)); - spin_lock_init(&tape->spinlock); - drive->driver_data = tape; - drive->ready_stat = 0; /* An ATAPI device ignores DRDY */ - if (strstr(drive->id->model, "OnStream DI-")) - tape->onstream = 1; - drive->dsc_overlap = 1; -#ifdef CONFIG_PCI - if (!tape->onstream && drive->channel->pci_dev != NULL) { - /* - * These two ide-pci host adapters appear to need DSC overlap disabled. - * This probably needs further analysis. - */ - if ((drive->channel->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) || - (drive->channel->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) { - printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name); - drive->dsc_overlap = 0; - } - } -#endif - tape->drive = drive; - tape->minor = minor; - tape->name[0] = 'h'; tape->name[1] = 't'; tape->name[2] = '0' + minor; - tape->chrdev_direction = idetape_direction_none; - tape->pc = tape->pc_stack; - tape->max_insert_speed = 10000; - tape->speed_control = 1; - *((unsigned short *) &gcw) = drive->id->config; - if (gcw.drq_type == 1) - set_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags); - - tape->min_pipeline = tape->max_pipeline = tape->max_stages = 10; - - idetape_get_inquiry_results(drive); - idetape_get_mode_sense_results(drive); - idetape_get_blocksize_from_block_descriptor(drive); - if (tape->onstream) { - idetape_onstream_mode_sense_tape_parameter_page(drive, 1); - idetape_configure_onstream(drive); - } - tape->user_bs_factor = 1; - tape->stage_size = tape->capabilities.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; - } - stage_size = tape->stage_size; - if (tape->onstream) - stage_size = 32768 + 512; - tape->pages_per_stage = stage_size / PAGE_SIZE; - if (stage_size % PAGE_SIZE) { - tape->pages_per_stage++; - 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); - - tape->max_stages = speed * 1000 * 10 / tape->stage_size; - - /* - * Limit memory use for pipeline to 10% of physical memory - */ - si_meminfo(&si); - if ( tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10) - tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size); - tape->min_pipeline = tape->max_stages; - tape->max_pipeline = tape->max_stages * 2; - - t1 = (tape->stage_size * HZ) / (speed * 1000); - tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125); - tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000); - - if (tape->max_stages) - t = tn; - else - t = t1; - - /* - * Ensure that the number we got makes sense; limit - * it within IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX. - */ - tape->best_dsc_rw_frequency = max(min(t, (unsigned long) IDETAPE_DSC_RW_MAX), - (unsigned long) 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, - tape->stage_size / 1024, tape->max_stages * tape->stage_size / 1024, - tape->best_dsc_rw_frequency * 1000 / HZ, drive->using_dma ? ", DMA":""); -} - -static int idetape_cleanup(struct ata_device *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int minor = tape->minor; - unsigned long flags; - - spin_lock_irqsave (&tape->spinlock, flags); /* overkill? */ - if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) { - spin_unlock_irqrestore(&tape->spinlock, flags); - return 1; - } - idetape_chrdevs[minor].drive = NULL; - spin_unlock_irqrestore(&tape->spinlock, flags); - - MOD_DEC_USE_COUNT; - - ata_unregister_device(drive); - drive->driver_data = NULL; - devfs_unregister (tape->de_r); - devfs_unregister (tape->de_n); - kfree (tape); - for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) - if (idetape_chrdevs[minor].drive != NULL) - return 0; - unregister_chrdev (IDETAPE_MAJOR, "ht"); - idetape_chrdev_present = 0; - return 0; -} - -static void idetape_attach(struct ata_device *); - -static struct ata_operations idetape_driver = { - .owner = THIS_MODULE, - .attach = idetape_attach, - .cleanup = idetape_cleanup, - .standby = NULL, - .do_request = idetape_do_request, - .end_request = idetape_end_request, - .ioctl = idetape_blkdev_ioctl, - .open = idetape_blkdev_open, - .release = idetape_blkdev_release, -}; - - - -/* - * Our character device supporting functions, passed to register_chrdev. - */ -static struct file_operations idetape_fops = { - .owner = THIS_MODULE, - .read = idetape_chrdev_read, - .write = idetape_chrdev_write, - .ioctl = idetape_chrdev_ioctl, - .open = idetape_chrdev_open, - .release = idetape_chrdev_release, -}; - -static void idetape_attach(struct ata_device *drive) -{ - idetape_tape_t *tape; - int minor, supported = 0; - char *req; - struct ata_channel *channel; - int unit; - - if (drive->type != ATA_TAPE) - return; - - req = drive->driver_req; - if (req[0] != '\0' && strcmp(req, "ide-tape")) - return; - - if (!idetape_chrdev_present) - for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ ) - idetape_chrdevs[minor].drive = NULL; - - if (!idetape_chrdev_present && - register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) { - printk(KERN_ERR "ide-tape: Failed to register character device interface\n"); - return; - } - - if (!idetape_identify_device (drive, drive->id)) { - printk(KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name); - return; - } - if (drive->scsi) { - if (strstr(drive->id->model, "OnStream DI-")) { - printk(KERN_INFO "ide-tape: ide-scsi emulation is not supported for %s.\n", drive->id->model); - } else { - printk(KERN_INFO "ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name); - return; - } - } - tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL); - if (!tape) { - printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); - return; - } - if (ata_register_device(drive, &idetape_driver)) { - printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (tape); - return; - } - for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++); - idetape_setup (drive, tape, minor); - idetape_chrdevs[minor].drive = drive; - tape->de_r = - devfs_register (drive->de, "mt", DEVFS_FL_DEFAULT, - drive->channel->major, minor, - S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL); - tape->de_n = - devfs_register (drive->de, "mtn", DEVFS_FL_DEFAULT, - drive->channel->major, minor + 128, - S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL); - devfs_register_tape (tape->de_r); - supported++; - - if (!idetape_chrdev_present && !supported) { - unregister_chrdev (IDETAPE_MAJOR, "ht"); - } else - idetape_chrdev_present = 1; -} - -MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver"); -MODULE_LICENSE("GPL"); - -static void __exit idetape_exit(void) -{ - unregister_ata_driver(&idetape_driver); -} - -int __init idetape_init(void) -{ - return ata_driver_module(&idetape_driver); -} - -module_init(idetape_init); -module_exit(idetape_exit); diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,233 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * Copyright (C) 2000 Michael Cornwell - * Copyright (C) 2000 Andre Hedrick - * - * May be copied or modified under the terms of the GNU General Public License - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * Data transfer functions for polled IO. - */ -static void ata_read_32(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - insl(IDE_DATA_REG, buffer, wcount); -} - -static void ata_write_32(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - outsl(IDE_DATA_REG, buffer, wcount); -} - -#if SUPPORT_SLOW_DATA_PORTS -static void ata_read_slow(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - unsigned short *ptr = (unsigned short *) buffer; - - while (wcount--) { - *ptr++ = inw_p(IDE_DATA_REG); - *ptr++ = inw_p(IDE_DATA_REG); - } -} - -static void ata_write_slow(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - unsigned short *ptr = (unsigned short *) buffer; - - while (wcount--) { - outw_p(*ptr++, IDE_DATA_REG); - outw_p(*ptr++, IDE_DATA_REG); - } -} -#endif - -static void ata_read_16(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - insw(IDE_DATA_REG, buffer, wcount<<1); -} - -static void ata_write_16(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - outsw(IDE_DATA_REG, buffer, wcount<<1); -} - -/* - * This is used for most PIO data transfers *from* the device. - */ -void ata_read(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - int io_32bit; - - /* - * First check if this controller has defined a special function - * for handling polled ide transfers. - */ - if (drive->channel->ata_read) { - drive->channel->ata_read(drive, buffer, wcount); - return; - } - - io_32bit = drive->channel->io_32bit; - - if (io_32bit) { - ata_read_32(drive, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->channel->slow) - ata_read_slow(drive, buffer, wcount); - else -#endif - ata_read_16(drive, buffer, wcount); - } -} - -/* - * This is used for most PIO data transfers *to* the device interface. - */ -void ata_write(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - int io_32bit; - - if (drive->channel->ata_write) { - drive->channel->ata_write(drive, buffer, wcount); - return; - } - - io_32bit = drive->channel->io_32bit; - - if (io_32bit) { - ata_write_32(drive, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->channel->slow) - ata_write_slow(drive, buffer, wcount); - else -#endif - ata_write_16(drive, buffer, wcount); - } -} - -/* - * Invoked on completion of a special REQ_SPECIAL command. - */ -static ide_startstop_t special_intr(struct ata_device *drive, struct request *rq) { - unsigned long flags; - struct ata_channel *ch =drive->channel; - struct ata_taskfile *ar = rq->special; - ide_startstop_t ret = ATA_OP_FINISHED; - - local_irq_enable(); - - if (rq->buffer && ar->taskfile.sector_number) { - if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) { - int retries = 10; - - ata_read(drive, rq->buffer, ar->taskfile.sector_number * SECTOR_WORDS); - - while (!ata_status(drive, 0, BUSY_STAT) && retries--) - udelay(100); - } - } - - if (!ata_status(drive, READY_STAT, BAD_STAT)) { - /* Keep quiet for NOP because it is expected to fail. */ - if (ar->cmd != WIN_NOP) - ret = ata_error(drive, rq, __FUNCTION__); - rq->errors = 1; - } - - ar->taskfile.feature = IN_BYTE(IDE_ERROR_REG); - ata_in_regfile(drive, &ar->taskfile); - ar->taskfile.device_head = IN_BYTE(IDE_SELECT_REG); - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - /* The following command goes to the hob file! */ - OUT_BYTE(0x80, drive->channel->io_ports[IDE_CONTROL_OFFSET]); - ar->hobfile.feature = IN_BYTE(IDE_FEATURE_REG); - ata_in_regfile(drive, &ar->hobfile); - } - - spin_lock_irqsave(ch->lock, flags); - - blkdev_dequeue_request(rq); - drive->rq = NULL; - end_that_request_last(rq); - - spin_unlock_irqrestore(ch->lock, flags); - - return ret; -} - -int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar, char *buf) -{ - struct request *rq; - unsigned long flags; - struct ata_channel *ch = drive->channel; - request_queue_t *q = &drive->queue; - struct list_head *queue_head = &q->queue_head; - DECLARE_COMPLETION(wait); - struct request req; - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (ch->chipset == ide_pdc4030 && buf) - return -ENOSYS; /* special drive cmds not supported */ -#endif - - memset(&req, 0, sizeof(req)); - rq = &req; - - rq->flags = REQ_SPECIAL; - rq->buffer = buf; - rq->special = ar; - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - rq->waiting = &wait; - - ar->XXX_handler = special_intr; - ar->command_type = IDE_DRIVE_TASK_NO_DATA; - - spin_lock_irqsave(ch->lock, flags); - - if (!blk_queue_empty(&drive->queue)) - queue_head = queue_head->prev; - __elv_add_request(q, rq, queue_head); - - q->request_fn(q); - spin_unlock_irqrestore(ch->lock, flags); - - wait_for_completion(&wait); /* wait for it to be serviced */ - - return rq->errors ? -EIO : 0; /* return -EIO if errors */ -} - -EXPORT_SYMBOL(ata_read); -EXPORT_SYMBOL(ata_write); -EXPORT_SYMBOL(ide_raw_taskfile); diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1125 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 1994-1998,2002 Linus Torvalds and authors: - * - * Mark Lord - * Gadi Oxman - * Andre Hedrick - * Jens Axboe - * Marcin Dalecki - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This is the basic common code of the ATA interface drivers. - * - * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs (usually 14 - * & 15). There can be up to two drives per interface, as per the ATA-7 spec. - * - * Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64 - * Secondary: ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64 - * Tertiary: ide2, port 0x???; major=33; hde is minor=0; hdf is minor=64 - * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64 - * ... - * - * Contributors: - * - * Drew Eckhardt - * Branko Lankester - * Mika Liljeberg - * Delman Lee - * Scott Snyder - * - * Some additional driver compile-time options are in - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef MODULE -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "timing.h" -#include "pcihost.h" -#include "ioctl.h" - -/* - * CompactFlash cards and their relatives pretend to be removable hard disks, except: - * (1) they never have a slave unit, and - * (2) they don't have a door lock mechanisms. - * This test catches them, and is invoked elsewhere when setting appropriate config bits. - * - * FIXME FIXME: Yes this is for certain applicable for all of them as time has shown. - * - * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) devices, - * so in linux 2.3.x we should change this to just treat all PCMCIA drives this way, - * and get rid of the model-name tests below (too big of an interface change for 2.2.x). - * At that time, we might also consider parameterizing the timeouts and retries, - * since these are MUCH faster than mechanical drives. -M.Lord - */ -int drive_is_flashcard(struct ata_device *drive) -{ - struct hd_driveid *id = drive->id; - int i; - - char *flashcards[] = { - "KODAK ATA_FLASH", - "Hitachi CV", - "SunDisk SDCFB", - "HAGIWARA HPC", - "LEXAR ATA_FLASH", - "ATA_FLASH" /* Simple Tech */ - }; - - if (drive->removable && id != NULL) { - if (id->config == 0x848a) - return 1; /* CompactFlash */ - for (i = 0; i < ARRAY_SIZE(flashcards); i++) - if (!strncmp(id->model, flashcards[i], - strlen(flashcards[i]))) - return 1; - } - return 0; -} - -int ata_end_request(struct ata_device *drive, struct request *rq, int uptodate, unsigned int nr_secs) -{ - unsigned long flags; - struct ata_channel *ch = drive->channel; - int ret = 1; - - spin_lock_irqsave(ch->lock, flags); - - BUG_ON(!(rq->flags & REQ_STARTED)); - - /* FIXME: Make this "small" hack to eliminate locking from - * ata_end_request to grab the first segment number of sectors go away. - */ - if (!nr_secs) - nr_secs = rq->hard_cur_sectors; - - /* - * Decide whether to reenable DMA -- 3 is a random magic for now, - * if we DMA timeout more than 3 times, just stay in PIO. - */ - if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { - drive->state = 0; - udma_enable(drive, 1, 1); - } - - if (!end_that_request_first(rq, uptodate, nr_secs)) { - add_blkdev_randomness(ch->major); - if (!blk_rq_tagged(rq)) - blkdev_dequeue_request(rq); - else - blk_queue_end_tag(&drive->queue, rq); - drive->rq = NULL; - end_that_request_last(rq); - ret = 0; - } - - spin_unlock_irqrestore(ch->lock, flags); - - return ret; -} - -/* - * This should get invoked any time we exit the driver to - * wait for an interrupt response from a drive. handler() points - * at the appropriate code to handle the next interrupt, and a - * timer is started to prevent us from waiting forever in case - * something goes wrong (see the ide_timer_expiry() handler later on). - */ -void ata_set_handler(struct ata_device *drive, ata_handler_t handler, - unsigned long timeout, ata_expiry_t expiry) -{ - unsigned long flags; - struct ata_channel *ch = drive->channel; - - spin_lock_irqsave(ch->lock, flags); - - /* FIXME: change it later to BUG_ON(ch->handler) --bzolnier */ - if (ch->handler) - printk("%s: %s: handler not null; old=%p, new=%p, from %p\n", - drive->name, __FUNCTION__, ch->handler, handler, __builtin_return_address(0)); - - ch->handler = handler; - - ch->expiry = expiry; - ch->timer.expires = jiffies + timeout; - - add_timer(&ch->timer); - - spin_unlock_irqrestore(ch->lock, flags); -} - -static void check_crc_errors(struct ata_device *drive) -{ - if (!drive->using_dma) - return; - - /* check the DMA crc count */ - if (drive->crc_count) { - udma_enable(drive, 0, 0); - if (drive->channel->speedproc) { - u8 mode = drive->current_speed; - drive->crc_count = 0; - - if (mode > XFER_UDMA_0) - mode--; - else - - /* - * We do not do non Ultra DMA modes. Without iCRC's - * available, we force the system to PIO and make the - * user select the ATA-1 ATA-2 DMA modes himself. - */ - - mode = XFER_PIO_4; - - drive->channel->speedproc(drive, mode); - } - if (drive->current_speed >= XFER_UDMA_0) - udma_enable(drive, 1, 1); - } else - udma_enable(drive, 0, 1); -} - -/* - * The capacity of a drive according to its current geometry/LBA settings in - * sectors. - */ -sector_t ata_capacity(struct ata_device *drive) -{ - if (!drive->present || !drive->driver) - return 0; - - if (ata_ops(drive) && ata_ops(drive)->capacity) - return ata_ops(drive)->capacity(drive); - - return ~0UL; -} - -static inline u32 read_24(struct ata_device *drive) -{ - return (IN_BYTE(IDE_HCYL_REG) << 16) | - (IN_BYTE(IDE_LCYL_REG) << 8) | - IN_BYTE(IDE_SECTOR_REG); -} - -#if FANCY_STATUS_DUMPS -struct ata_bit_messages { - u8 mask; - u8 match; - const char *msg; -}; - -static struct ata_bit_messages ata_status_msgs[] = { - { BUSY_STAT, BUSY_STAT, "busy" }, - { READY_STAT, READY_STAT, "drive ready" }, - { WRERR_STAT, WRERR_STAT, "device fault" }, - { SEEK_STAT, SEEK_STAT, "seek complete" }, - { DRQ_STAT, DRQ_STAT, "data request" }, - { ECC_STAT, ECC_STAT, "corrected error" }, - { INDEX_STAT, INDEX_STAT, "index" }, - { ERR_STAT, ERR_STAT, "error" } -}; - -static struct ata_bit_messages ata_error_msgs[] = { - { ICRC_ERR|ABRT_ERR, ABRT_ERR, "drive status error" }, - { ICRC_ERR|ABRT_ERR, ICRC_ERR, "bad sector" }, - { ICRC_ERR|ABRT_ERR, ICRC_ERR|ABRT_ERR, "invalid checksum" }, - { ECC_ERR, ECC_ERR, "uncorrectable error" }, - { ID_ERR, ID_ERR, "sector id not found" }, - { TRK0_ERR, TRK0_ERR, "track zero not found" }, - { MARK_ERR, MARK_ERR, "addr mark not found" } -}; - -static void dump_bits(struct ata_bit_messages *msgs, int nr, u8 bits) -{ - int i; - int first = 1; - - printk(" [ "); - - for (i = 0; i < nr; i++, msgs++) - if ((bits & msgs->mask) == msgs->match) { - if (!first) - printk(","); - printk("%s", msgs->msg); - first = 0; - } - - printk("] "); -} -#else -# define dump_bits(msgs,nr,bits) do { } while (0) -#endif - -/* - * Error reporting, in human readable form (luxurious, but a memory hog). - */ -u8 ata_dump(struct ata_device *drive, struct request * rq, const char *msg) -{ - unsigned long flags; - u8 err = 0; - - /* FIXME: --bzolnier */ - local_save_flags(flags); - local_irq_enable(); - - printk("%s: %s: status=0x%02x", drive->name, msg, drive->status); - dump_bits(ata_status_msgs, ARRAY_SIZE(ata_status_msgs), drive->status); - printk("\n"); - - if ((drive->status & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = GET_ERR(); - printk("%s: %s: error=0x%02x", drive->name, msg, err); -#if FANCY_STATUS_DUMPS - if (drive->type == ATA_DISK) { - dump_bits(ata_error_msgs, ARRAY_SIZE(ata_error_msgs), err); - - if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - __u64 sectors = 0; - u32 low = 0, high = 0; - low = read_24(drive); - OUT_BYTE(0x80, drive->channel->io_ports[IDE_CONTROL_OFFSET]); - high = read_24(drive); - - sectors = ((__u64)high << 24) | low; - printk(", LBAsect=%lld, high=%d, low=%d", (long long) sectors, high, low); - } else { - u8 cur = IN_BYTE(IDE_SELECT_REG); - if (cur & 0x40) { /* using LBA? */ - printk(", LBAsect=%ld", (unsigned long) - ((cur&0xf)<<24) - |(IN_BYTE(IDE_HCYL_REG)<<16) - |(IN_BYTE(IDE_LCYL_REG)<<8) - | IN_BYTE(IDE_SECTOR_REG)); - } else { - printk(", CHS=%d/%d/%d", - (IN_BYTE(IDE_HCYL_REG)<<8) + - IN_BYTE(IDE_LCYL_REG), - cur & 0xf, - IN_BYTE(IDE_SECTOR_REG)); - } - } - if (rq) - printk(", sector=%ld", rq->sector); - } - } -#endif - printk("\n"); - } - local_irq_restore (flags); - - return err; -} - -/* - * Take action based on the error returned by the drive. - * - * FIXME: Separate the error handling code out and call it only in cases where - * we really wan't to try to recover from the error and not just reporting. - */ -ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const char *msg) -{ - u8 err; - u8 stat = drive->status; - - err = ata_dump(drive, rq, msg); - - /* Only try to recover from block I/O operations. - */ - if (!rq || !(rq->flags & REQ_CMD)) { - rq->errors = 1; - - return ATA_OP_FINISHED; - } - - /* other bits are useless when BUSY */ - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) - rq->errors |= ERROR_RESET; - else if (drive->type == ATA_DISK) { - /* The error bit has different meaning on cdrom and tape. - */ - if (stat & ERR_STAT) { - if (err == ABRT_ERR) { - if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) - return ATA_OP_FINISHED; /* some newer drives don't support WIN_SPECIFY */ - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) - drive->crc_count++; /* UDMA crc error -- just retry the operation */ - else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ - rq->errors = ERROR_MAX; - } - - /* As an alternative to resetting the drive, we try to clear - * the condition by reading a sector's worth of data from the - * drive. Of course, this can not help if the drive is - * *waiting* for data from *us*. - */ - - if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ) { - int i; - - for (i = (drive->mult_count ? drive->mult_count : 1); i > 0; --i) { - u32 buffer[SECTOR_WORDS]; - - ata_read(drive, buffer, SECTOR_WORDS); - } - } - } - - /* Force an abort if not even the status data is available. This will - * clear all pending IRQs on the drive as well. - */ - if (!ata_status(drive, 0, BUSY_STAT | DRQ_STAT)) - OUT_BYTE(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG); - - /* Bail out immediately. */ - if (rq->errors >= ERROR_MAX) { - printk(KERN_ERR "%s: max number of retries exceeded!\n", drive->name); - if (ata_ops(drive) && ata_ops(drive)->end_request) - ata_ops(drive)->end_request(drive, rq, 0); - else - ata_end_request(drive, rq, 0, 0); - - return ATA_OP_FINISHED; - } - - ++rq->errors; - printk(KERN_INFO "%s: request error, nr. %d\n", drive->name, rq->errors); - - /* - * Attempt to recover a confused drive by resetting it. Unfortunately, - * resetting a disk drive actually resets all devices on the same - * interface, so it can really be thought of as resetting the interface - * rather than resetting the drive. - * - * ATAPI devices have their own reset mechanism which allows them to be - * individually reset without clobbering other devices on the same - * interface. - * - * The IDE interface does not generate an interrupt to let us know when - * the reset operation has finished, so we must poll for this. This - * may take a very long time to complete. - * - * Maybe we can check if we are in IRQ context and schedule the CPU - * during this time. But for certain we should block all data transfers - * on the channel in question during those operations. - */ - - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - unsigned int unit; - struct ata_channel *ch = drive->channel; - int ret; - - /* For an ATAPI device, first try an ATAPI SRST. - */ - - if (drive->type != ATA_DISK) { - check_crc_errors(drive); - ata_select(drive, 20); - udelay(1); - ata_irq_enable(drive, 0); - OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); - if (drive->quirk_list == 2) - ata_irq_enable(drive, 1); - udelay(1); - ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_WORSTCASE, NULL); - ata_mask(drive); - - if (ret == ATA_OP_READY) { - printk("%s: ATAPI reset complete\n", drive->name); - - return ATA_OP_CONTINUES; - } else - printk(KERN_ERR "%s: ATAPI reset timed out, status=0x%02x\n", - drive->name, drive->status); - } - - /* Reset all devices on channel. - */ - - /* First, reset any device state data we were maintaining for - * any of the drives on this interface. - */ - for (unit = 0; unit < MAX_DRIVES; ++unit) - check_crc_errors(&ch->drives[unit]); - - /* And now actually perform the reset operation. - */ - printk("%s: ATA reset...\n", ch->name); - ata_select(drive, 20); - udelay(1); - ata_irq_enable(drive, 0); - - OUT_BYTE(0x04, ch->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - OUT_BYTE(0x00, ch->io_ports[IDE_CONTROL_OFFSET]); - ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_WORSTCASE, NULL); - ata_mask(drive); - - if (ret == ATA_OP_READY) - printk("%s: ATA reset complete\n", drive->name); - else - printk(KERN_ERR "%s: ATA reset timed out, status=0x%02x\n", - drive->name, drive->status); - mdelay(100); - } - - /* signal that we should retry this request */ - return ATA_OP_CONTINUES; -} - -/* - * Issue a new request. - * Caller must have already done spin_lock_irqsave(channel->lock, ...) - */ -void do_ide_request(request_queue_t *q) -{ - struct ata_device *drive = q->queuedata; - struct ata_channel *ch = drive->channel; - - while (!test_and_set_bit(IDE_BUSY, ch->active)) { - unsigned int unit; - ide_startstop_t ret; - - if (drive) { - /* No request pending?! */ - if (blk_queue_empty(&drive->queue)) - drive = NULL; - /* Still resorting requests?! */ - else if (blk_queue_plugged(&drive->queue)) - drive = NULL; - } - - if (!drive) { - /* We should never get here! */ - /* Unless someone called us from IRQ context after - * finishing the actual request already. (Shrug!) - */ - // printk(KERN_INFO "no device found!\n"); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device *tmp = &ch->drives[unit]; - - if (!tmp->present) - continue; - - /* There are no requests pending for this - * device. - */ - if (blk_queue_empty(&tmp->queue)) - continue; - - /* Take this device, if there is no device - * choosen thus far and the queue is ready for - * processing. - */ - if (!drive && !blk_queue_plugged(&tmp->queue)) - drive = tmp; - } - } - - if (!drive) { - /* Ugly, but how can we sleep for the lock otherwise? - */ - - ide_release_lock(&ide_irq_lock);/* for atari only */ - clear_bit(IDE_BUSY, ch->active); - - /* All requests are done. - * - * Disable IRQs from the last drive on this channel, to - * make sure that it wan't throw stones at us when we - * are not prepared to take them. - */ - - if (ch->drive && !ch->drive->using_tcq) - ata_irq_enable(ch->drive, 0); - - return; - } - - /* Remember the last drive we where acting on. - */ - ch->drive = drive; - - /* Feed commands to a drive until it barfs. - */ - do { - struct request *rq = NULL; - - /* Abort early if we can't queue another command. for - * non tcq, ata_can_queue is always 1 since we never - * get here unless the drive is idle. - */ - - if (!ata_can_queue(drive)) { - if (!ata_pending_commands(drive)) { - clear_bit(IDE_BUSY, ch->active); - if (drive->using_tcq) - ata_irq_enable(drive, 0); - } - break; - } - - if (test_bit(IDE_DMA, ch->active)) { - printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name); - break; - } - - /* There's a small window between where the queue could - * be replugged while we are in here when using tcq (in - * which case the queue is probably empty anyways...), - * so check and leave if appropriate. When not using - * tcq, this is still a severe BUG! - */ - - if (blk_queue_plugged(&drive->queue)) { - BUG_ON(!drive->using_tcq); - break; - } - - if (!(rq = elv_next_request(&drive->queue))) { - if (!ata_pending_commands(drive)) { - clear_bit(IDE_BUSY, ch->active); - if (drive->using_tcq) - ata_irq_enable(drive, 0); - } - drive->rq = NULL; - - break; - } - - /* If there are queued commands, we can't start a - * non-fs request (really, a non-queuable command) - * until the queue is empty. - */ - if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive)) - break; - - drive->rq = rq; - - spin_unlock(ch->lock); - /* allow other IRQs while we start this request */ - local_irq_enable(); - - /* - * This initiates handling of a new I/O request. - */ - BUG_ON(!(rq->flags & REQ_STARTED)); - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) - goto kill_rq; - - - ata_select(drive, 0); - ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT, - WAIT_READY, rq); - - if (ret != ATA_OP_READY) { - printk(KERN_ERR "%s: drive not ready for command\n", drive->name); - - goto kill_rq; - } - - if (!ata_ops(drive)) { - printk(KERN_WARNING "%s: device type %d not supported\n", - drive->name, drive->type); - goto kill_rq; - } - - /* The normal way of execution is to pass and execute the request - * handler down to the device type driver. - */ - - if (ata_ops(drive)->do_request) - ret = ata_ops(drive)->do_request(drive, rq, rq->sector); - else { -kill_rq: - if (ata_ops(drive) && ata_ops(drive)->end_request) - ata_ops(drive)->end_request(drive, rq, 0); - else - ata_end_request(drive, rq, 0, 0); - ret = ATA_OP_FINISHED; - - } - spin_lock_irq(ch->lock); - /* continue if command started, so we are busy */ - } while (ret != ATA_OP_CONTINUES); - } -} - -/* - * This is our timeout function for all drive operations. But note that it can - * also be invoked as a result of a "sleep" operation triggered by the - * mod_timer() call in do_ide_request. - * - * FIXME: This should take a drive context instead of a channel. - * FIXME: This should not explicitly reenter the request handling engine. - */ -void ide_timer_expiry(unsigned long data) -{ - unsigned long flags; - struct ata_channel *ch = (struct ata_channel *) data; - - spin_lock_irqsave(ch->lock, flags); - del_timer(&ch->timer); - - if (!ch->drive) { - printk(KERN_ERR "%s: channel->drive was NULL\n", __FUNCTION__); - ch->handler = NULL; - } else if (!ch->handler) { - - /* - * Either a marginal timeout occurred (got the interrupt just - * as timer expired), or we were "sleeping" to give other - * devices a chance. Either way, we don't really want to - * complain about anything. - * - * FIXME: Do we really still have to clear IDE_BUSY here? - */ - - if (test_and_clear_bit(IDE_SLEEP, ch->active)) - clear_bit(IDE_BUSY, ch->active); - } else { - struct ata_device *drive = ch->drive; - ide_startstop_t ret; - ata_handler_t *handler; - - /* paranoia */ - if (!test_and_set_bit(IDE_BUSY, ch->active)) - printk(KERN_ERR "%s: %s: channel was not busy?!\n", - drive->name, __FUNCTION__); - - if (ch->expiry) { - unsigned long wait; - - /* continue */ - ret = ch->expiry(drive, drive->rq, &wait); - if (ret == ATA_OP_CONTINUES) { - /* reengage timer */ - if (wait) { - ch->timer.expires = jiffies + wait; - add_timer(&ch->timer); - } - - spin_unlock_irqrestore(ch->lock, flags); - - return; - } - } - - /* - * We need to simulate a real interrupt when invoking the - * handler() function, which means we need to globally mask the - * specific IRQ: - */ - - handler = ch->handler; - ch->handler = NULL; - - spin_unlock(ch->lock); -#if DISABLE_IRQ_NOSYNC - disable_irq_nosync(ch->irq); -#else - disable_irq(ch->irq); /* disable_irq_nosync ?? */ -#endif - - local_irq_disable(); - if (ch->poll_timeout) { - ret = handler(drive, drive->rq); - } else if (ata_status_irq(drive)) { - if (test_bit(IDE_DMA, ch->active)) - udma_irq_lost(drive); - (void) ide_ack_intr(ch); - printk("%s: lost interrupt\n", drive->name); - ret = handler(drive, drive->rq); - } else if (test_bit(IDE_DMA, ch->active)) { - struct request *rq = drive->rq; - - /* - * Un-busy the hwgroup etc, and clear any pending DMA - * status. we want to retry the current request in PIO - * mode instead of risking tossing it all away. - */ - - udma_stop(drive); - udma_timeout(drive); - - /* Disable dma for now, but remember that we did so - * because of a timeout -- we'll reenable after we - * finish this next request (or rather the first chunk - * of it) in pio. - */ - - drive->retry_pio++; - drive->state = DMA_PIO_RETRY; - udma_enable(drive, 0, 0); - - /* Un-busy drive etc (hwgroup->busy is cleared on - * return) and make sure request is sane. - */ - - drive->rq = NULL; - - rq->errors = 0; - if (rq->bio) { - rq->sector = rq->bio->bi_sector; - rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; - rq->buffer = NULL; - } - ret = ATA_OP_FINISHED; - } else - ret = ata_error(drive, drive->rq, "irq timeout"); - - enable_irq(ch->irq); - spin_lock_irq(ch->lock); - - if (ret == ATA_OP_FINISHED) { - /* Reenter the request handling engine. */ - clear_bit(IDE_BUSY, ch->active); - do_ide_request(&drive->queue); - } - } - spin_unlock_irqrestore(ch->lock, flags); -} - -/* - * There's nothing really useful we can do with an unexpected interrupt, - * other than reading the status register (to clear it), and logging it. - * There should be no way that an irq can happen before we're ready for it, - * so we needn't worry much about losing an "important" interrupt here. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - * - * This routine assumes IRQ are disabled on entry. - * - * If an unexpected interrupt happens on irq15 while we are handling irq14 - * and if the two interfaces are "serialized" (CMD640), then it looks like - * we could screw up by interfering with a new request being set up for irq15. - * - * In reality, this is a non-issue. The new command is not sent unless the - * drive is ready to accept one, in which case we know the drive is not - * trying to interrupt us. And ata_set_handler() is always invoked before - * completing the issuance of any new drive command, so we will not be - * accidentally invoked as a result of any valid command completion interrupt. - * - */ -static void unexpected_irq(int irq) -{ - /* Try to not flood the console with msgs */ - static unsigned long last_msgtime; /* = 0 */ - static int count; /* = 0 */ - int i; - - for (i = 0; i < MAX_HWIFS; ++i) { - struct ata_channel *ch = &ide_hwifs[i]; - int j; - struct ata_device *drive; - - if (!ch->present || ch->irq != irq) - continue; - - for (j = 0; j < MAX_DRIVES; ++j) { - drive = &ch->drives[j]; - - /* this drive is idle */ - if (ata_status(drive, READY_STAT, BAD_STAT)) - continue; - - ++count; - - /* don't report too frequently */ - if (!time_after(jiffies, last_msgtime + HZ)) - continue; - - last_msgtime = jiffies; - printk("%s: unexpected interrupt, status=0x%02x, count=%d\n", - ch->name, drive->status, count); - } - } -} - -/* - * Entry point for all interrupts. Aussumes disabled IRQs. - */ -void ata_irq_request(int irq, void *data, struct pt_regs *regs) -{ - struct ata_channel *ch = data; - unsigned long flags; - struct ata_device *drive; - ata_handler_t *handler; - ide_startstop_t ret; - - spin_lock_irqsave(ch->lock, flags); - - if (!ide_ack_intr(ch)) - goto out_lock; - - handler = ch->handler; - drive = ch->drive; - if (!handler || ch->poll_timeout) { -#if 0 - printk(KERN_INFO "ide: unexpected interrupt %d %d\n", ch->unit, irq); -#endif - - /* - * Not expecting an interrupt from this drive. That means this - * could be: - * - * - an interrupt from another PCI device sharing the same PCI - * INT# as us. - * - * - a drive just entered sleep or standby mode, and is - * interrupting to let us know. - * - * - a spurious interrupt of unknown origin. - * - * For PCI, we cannot tell the difference, so in that case we - * just clear it and hope it goes away. - */ - -#ifdef CONFIG_PCI - if (ch->pci_dev && !ch->pci_dev->vendor) -#endif - unexpected_irq(irq); -#ifdef CONFIG_PCI - else - ata_status(drive, READY_STAT, BAD_STAT); -#endif - - goto out_lock; - } - if (!ata_status_irq(drive)) { - /* This happens regularly when we share a PCI IRQ with another device. - * Unfortunately, it can also happen with some buggy drives that trigger - * the IRQ before their status register is up to date. Hopefully we have - * enough advance overhead that the latter isn't a problem. - */ - - goto out_lock; - } - - /* paranoia */ - if (!test_and_set_bit(IDE_BUSY, ch->active)) - printk(KERN_ERR "%s: %s: channel was not busy!?\n", drive->name, __FUNCTION__); - - ch->handler = NULL; - del_timer(&ch->timer); - - spin_unlock(ch->lock); - - if (ch->unmask) - local_irq_enable(); - - /* - * Service this interrupt, this may setup handler for next interrupt. - */ - ret = handler(drive, drive->rq); - - spin_lock_irq(ch->lock); - - /* - * Note that handler() may have set things up for another interrupt to - * occur soon, but it cannot happen until we exit from this routine, - * because it will be the same irq as is currently being serviced here, - * and Linux won't allow another of the same (on any CPU) until we - * return. - */ - - if (ret == ATA_OP_FINISHED) { - - /* Reenter the request handling engine if we are not expecting - * another interrupt. - */ - - if (!ch->handler) { - clear_bit(IDE_BUSY, ch->active); - do_ide_request(&drive->queue); - } else - printk("%s: %s: huh? expected NULL handler on exit\n", - drive->name, __FUNCTION__); - } - -out_lock: - spin_unlock_irqrestore(ch->lock, flags); -} - -static int ide_open(struct inode * inode, struct file * filp) -{ - struct ata_device *drive; - - if ((drive = get_info_ptr(inode->i_rdev)) == NULL) - return -ENXIO; - - /* Request a particular device type module. - * - * FIXME: The function which should rather requests the drivers is - * ide_driver_module(), since it seems illogical and even a bit - * dangerous to postpone this until open time! - */ - -#ifdef CONFIG_KMOD - if (!drive->driver) { - char *module = NULL; - - switch (drive->type) { - case ATA_DISK: - module = "ide-disk"; - break; - case ATA_ROM: - module = "ide-cd"; - break; - case ATA_TAPE: - module = "ide-tape"; - break; - case ATA_FLOPPY: - module = "ide-floppy"; - break; - case ATA_SCSI: - module = "ide-scsi"; - break; - default: - /* nothing we can do about it */ ; - } - if (module) - request_module(module); - } -#endif - - if (drive->driver == NULL) - ide_driver_module(); - - ++drive->usage; - if (ata_ops(drive) && ata_ops(drive)->open) - return ata_ops(drive)->open(inode, filp, drive); - else { - --drive->usage; - return -ENODEV; - } - - printk(KERN_INFO "%s: driver not present\n", drive->name); - --drive->usage; - - return -ENXIO; -} - -/* - * Releasing a block device means we sync() it, so that it can safely - * be forgotten about... - */ -static int ide_release(struct inode * inode, struct file * file) -{ - struct ata_device *drive; - - if (!(drive = get_info_ptr(inode->i_rdev))) - return 0; - - drive->usage--; - if (ata_ops(drive) && ata_ops(drive)->release) - ata_ops(drive)->release(inode, file, drive); - - return 0; -} - -int ide_spin_wait_hwgroup(struct ata_device *drive) -{ - /* FIXME: Wait on a proper timer. Instead of playing games on the - * spin_lock(). - */ - - unsigned long timeout = jiffies + (10 * HZ); - - spin_lock_irq(drive->channel->lock); - - while (test_bit(IDE_BUSY, drive->channel->active)) { - - spin_unlock_irq(drive->channel->lock); - - if (time_after(jiffies, timeout)) { - printk("%s: channel busy\n", drive->name); - return -EBUSY; - } - - spin_lock_irq(drive->channel->lock); - } - - return 0; -} - -static int ide_check_media_change(kdev_t i_rdev) -{ - struct ata_device *drive; - int res = 0; /* not changed */ - - drive = get_info_ptr(i_rdev); - if (!drive) - return -ENODEV; - - if (ata_ops(drive)) { - ata_get(ata_ops(drive)); - if (ata_ops(drive)->check_media_change) - res = ata_ops(drive)->check_media_change(drive); - else - res = 1; /* assume it was changed */ - ata_put(ata_ops(drive)); - } - - return res; -} - -struct block_device_operations ide_fops[] = {{ - .owner = THIS_MODULE, - .open = ide_open, - .release = ide_release, - .ioctl = ata_ioctl, - .check_media_change = ide_check_media_change, - .revalidate = ide_revalidate -}}; - -EXPORT_SYMBOL(ide_fops); -EXPORT_SYMBOL(ide_spin_wait_hwgroup); - -EXPORT_SYMBOL(drive_is_flashcard); -EXPORT_SYMBOL(ide_timer_expiry); -EXPORT_SYMBOL(do_ide_request); - -EXPORT_SYMBOL(ata_set_handler); -EXPORT_SYMBOL(ata_dump); -EXPORT_SYMBOL(ata_error); - -EXPORT_SYMBOL(ata_end_request); - -EXPORT_SYMBOL(ide_setup_ports); diff -Nru a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c --- a/drivers/ide/ioctl.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,361 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* - * Generic ioctl handling for all ATA/ATAPI device drivers. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ioctl.h" - - -/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */ -struct hd_big_geometry { - u8 heads; - u8 sectors; - u32 cylinders; - unsigned long start; -}; - -/* - * Implement generic ioctls invoked from userspace to imlpement specific - * functionality. - * - * Unfortunately every single low level programm out there is using this - * interface. - */ -static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg) -{ - int err = 0; - u8 vals[4]; - u8 *argbuf = vals; - int argsize = 4; - struct ata_taskfile args; - - /* Second phase. - */ - if (copy_from_user(vals, (void *)arg, 4)) - return -EFAULT; - - memset(&args, 0, sizeof(args)); - - args.taskfile.feature = vals[2]; - args.taskfile.sector_count = vals[1]; - args.taskfile.sector_number = vals[3]; - if (vals[0] == WIN_SMART) { - args.taskfile.low_cylinder = 0x4f; - args.taskfile.high_cylinder = 0xc2; - } else { - args.taskfile.low_cylinder = 0x00; - args.taskfile.high_cylinder = 0x00; - } - args.taskfile.device_head = 0x00; - args.cmd = vals[0]; - - if (vals[3]) { - argsize = 4 + (SECTOR_WORDS * 4 * vals[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - memcpy(argbuf, vals, 4); - memset(argbuf + 4, 0, argsize - 4); - } - - /* Issue ATA command and wait for completion. - */ - err = ide_raw_taskfile(drive, &args, argbuf + 4); - - argbuf[0] = drive->status; - argbuf[1] = args.taskfile.feature; - argbuf[2] = args.taskfile.sector_count; - - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - - if (argsize > 4) - kfree(argbuf); - - return err; -} - -/* - * NOTE: Due to ridiculous coding habbits in the hdparm utility we have to - * always return unsigned long in case we are returning simple values. - */ -int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned int major, minor; - struct ata_device *drive; - kdev_t dev; - - dev = inode->i_rdev; - major = major(dev); - minor = minor(dev); - - if ((drive = get_info_ptr(inode->i_rdev)) == NULL) - return -ENODEV; - - /* Contrary to popular beleve we disallow even the reading of the ioctl - * values for users which don't have permission too. We do this becouse - * such information could be used by an attacker to deply a simple-user - * attack, which triggers bugs present only on a particular - * configuration. - */ - - switch (cmd) { - case HDIO_GET_32BIT: { - unsigned long val = drive->channel->io_32bit; - - if (put_user(val, (unsigned long *) arg)) - return -EFAULT; - return 0; - } - - case HDIO_SET_32BIT: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (drive->channel->no_io_32bit) - return -EIO; - - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - - drive->channel->io_32bit = arg; - spin_unlock_irq(drive->channel->lock); - - return 0; - - case HDIO_SET_PIO_MODE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (arg < 0 || arg > 255) - return -EINVAL; - - if (!drive->channel->tuneproc) - return -ENOSYS; - - /* FIXME: we can see that tuneproc whould do the - * locking!. - */ - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - - drive->channel->tuneproc(drive, (u8) arg); - spin_unlock_irq(drive->channel->lock); - - return 0; - - case HDIO_GET_UNMASKINTR: { - unsigned long val = drive->channel->unmask; - - if (put_user(val, (unsigned long *) arg)) - return -EFAULT; - - return 0; - } - - case HDIO_SET_UNMASKINTR: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (drive->channel->no_unmask) - return -EIO; - - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - - drive->channel->unmask = arg; - spin_unlock_irq(drive->channel->lock); - - return 0; - - case HDIO_GET_DMA: { - unsigned long val = drive->using_dma; - - if (put_user(val, (unsigned long *) arg)) - return -EFAULT; - - return 0; - } - - case HDIO_SET_DMA: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (!drive->driver) - return -EPERM; - - if (!drive->id || !(drive->id->capability & 1) || !drive->channel->udma_setup) - return -EPERM; - - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - - udma_enable(drive, arg, 1); - spin_unlock_irq(drive->channel->lock); - - return 0; - - case HDIO_GETGEO: { - struct hd_geometry *loc = (struct hd_geometry *) arg; - unsigned short bios_cyl = drive->bios_cyl; /* truncate */ - - if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY)) - return -EINVAL; - - if (put_user(drive->bios_head, (u8 *) &loc->heads)) - return -EFAULT; - - if (put_user(drive->bios_sect, (u8 *) &loc->sectors)) - return -EFAULT; - - if (put_user(bios_cyl, (u16 *) &loc->cylinders)) - return -EFAULT; - - if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect, - (unsigned long *) &loc->start)) - return -EFAULT; - - return 0; - } - - case HDIO_GETGEO_BIG_RAW: { - struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; - - if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY)) - return -EINVAL; - - if (put_user(drive->head, (u8 *) &loc->heads)) - return -EFAULT; - - if (put_user(drive->sect, (u8 *) &loc->sectors)) - return -EFAULT; - - if (put_user(drive->cyl, (unsigned int *) &loc->cylinders)) - return -EFAULT; - - if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect, - (unsigned long *) &loc->start)) - return -EFAULT; - - return 0; - } - - case HDIO_GET_IDENTITY: - - if (minor(inode->i_rdev) & PARTN_MASK) - return -EINVAL; - - if (drive->id == NULL) - return -ENOMSG; - - if (copy_to_user((char *)arg, (char *)drive->id, sizeof(*drive->id))) - return -EFAULT; - - return 0; - - case HDIO_GET_NICE: - - return put_user(drive->dsc_overlap | drive->atapi_overlap << 1, - (long *) arg); - - case HDIO_SET_NICE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (arg != (arg & 1)) - return -EPERM; - - drive->dsc_overlap = arg & 1; - - /* Only CD-ROM's and tapes support DSC overlap. */ - if (drive->dsc_overlap && !(drive->type == ATA_ROM || drive->type == ATA_TAPE)) { - drive->dsc_overlap = 0; - return -EPERM; - } - - return 0; - - case HDIO_GET_BUSSTATE: - - if (put_user(drive->channel->bus_state, (long *)arg)) - return -EFAULT; - - return 0; - - case HDIO_SET_BUSSTATE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (drive->channel->busproc) - drive->channel->busproc(drive, (int)arg); - - return 0; - - case HDIO_DRIVE_CMD: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (!arg) { - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - /* Do nothing, just unlock */ - spin_unlock_irq(drive->channel->lock); - return 0; - } - - return do_cmd_ioctl(drive, arg); - - /* - * uniform packet command handling - */ - case CDROMEJECT: - case CDROMCLOSETRAY: - return block_ioctl(inode->i_bdev, cmd, arg); - - /* Now check whatever this particular ioctl has a device type - * specific implementation. - */ - default: - if (ata_ops(drive) && ata_ops(drive)->ioctl) - return ata_ops(drive)->ioctl(drive, inode, file, cmd, arg); - - return -EINVAL; - } -} diff -Nru a/drivers/ide/ioctl.h b/drivers/ide/ioctl.h --- a/drivers/ide/ioctl.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,15 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -extern int ata_ioctl(struct inode *, struct file *, unsigned int, unsigned long); diff -Nru a/drivers/ide/it8172.c b/drivers/ide/it8172.c --- a/drivers/ide/it8172.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,237 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * IT8172 IDE controller support - * - * Copyright 2000 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * stevel@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "timing.h" -#include "pcihost.h" - - -/* FIXME: fix locking --bkz */ -static void it8172_tune_drive (struct ata_device *drive, u8 pio) -{ - struct pci_dev *dev = drive->channel->pci_dev; - unsigned long flags; - u16 drive_enables; - u32 drive_timing; - int is_slave = (&drive->channel->drives[1] == drive); - - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; - else - pio = min_t(byte, pio, 4); - - pci_read_config_word(dev, master_port, &master_data); - pci_read_config_dword(dev, slave_port, &slave_data); - - /* - * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44 - * are being left at the default values of 8 PCI clocks (242 nsec - * for a 33 MHz clock). These can be safely shortened at higher - * PIO modes. The DIOR/DIOW pulse width and recovery times only - * apply to PIO modes, not to the DMA modes. - */ - - /* - * Enable port 0x44. The IT8172G spec is confused; it calls - * this register the "Slave IDE Timing Register", but in fact, - * it controls timing for both master and slave drives. - */ - drive_enables |= 0x4000; - - if (is_slave) { - drive_enables &= 0xc006; - if (pio > 1) - /* enable prefetch and IORDY sample-point */ - drive_enables |= 0x0060; - } else { - drive_enables &= 0xc060; - if (pio > 1) - /* enable prefetch and IORDY sample-point */ - drive_enables |= 0x0006; - } - - pci_write_config_word(dev, master_port, master_data); -} - -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING) -/* - * - */ -static u8 it8172_dma_2_pio(u8 xfer_rate) -{ - switch(xfer_rate) { - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_PIO_4: - return 4; - case XFER_MW_DMA_1: - case XFER_PIO_3: - return 3; - case XFER_SW_DMA_2: - case XFER_PIO_2: - return 2; - case XFER_MW_DMA_0: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - return 0; - } -} - -static int it8172_tune_chipset(struct ata_device *drive, u8 speed) -{ - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int u_speed = 0; - int err = 0; - u8 reg48, reg4a; - - pci_read_config_byte(dev, 0x48, ®48); - pci_read_config_byte(dev, 0x4a, ®4a); - - /* - * Setting the DMA cycle time to 2 or 3 PCI clocks (60 and 91 nsec - * at 33 MHz PCI clock) seems to cause BadCRC errors during DMA - * transfers on some drives, even though both numbers meet the minimum - * ATAPI-4 spec of 73 and 54 nsec for UDMA 1 and 2 respectively. - * So the faster times are just commented out here. The good news is - * that the slower cycle time has very little affect on transfer - * performance. - */ - - 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_MW_DMA_0: - case XFER_SW_DMA_2: break; - default: return -1; - } - - if (speed >= XFER_UDMA_0) { - pci_write_config_byte(dev, 0x48, reg48 | u_flag); - reg4a &= ~a_speed; - pci_write_config_byte(dev, 0x4a, reg4a | u_speed); - } else { - pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); - pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); - } - - it8172_tune_drive(drive, it8172_dma_2_pio(speed)); - - return ide_config_drive_speed(drive, speed); -} -#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_IT8172_TUNING) */ - - -static unsigned int __init pci_init_it8172(struct pci_dev *dev) -{ - u8 progif; - - /* - * Place both IDE interfaces into PCI "native" mode - */ - pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); - pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x05); - - return IT8172_IDE_IRQ; -} - - -static void __init ide_init_it8172(struct ata_channel *hwif) -{ - struct pci_dev* dev = hwif->pci_dev; - unsigned long cmdBase, ctrlBase; - - hwif->tuneproc = &it8172_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; - -# ifdef CONFIG_IT8172_TUNING - hwif->modes_map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA | XFER_UDMA; - hwif->udma_setup = udma_generic_setup; - hwif->speedproc = &it8172_tune_chipset; -# endif - - cmdBase = dev->resource[0].start; - ctrlBase = dev->resource[1].start; - - ide_init_hwif_ports(&hwif->hw, cmdBase, ctrlBase | 2, NULL); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = 0; -} - - -/* module data table */ -static struct ata_pci_device chipset __initdata = { - .vendor = PCI_VENDOR_ID_ITE, - .device = PCI_DEVICE_ID_ITE_IT8172G, - .init_chipset = pci_init_it8172, - .init_channel = ide_init_it8172, - .exnablebits = {{0x00,0x00,0x00}, {0x40,0x00,0x01} }, - .bootable = ON_BOARD -}; - -int __init init_it8172(void) -{ - ata_register_chipset(&chipset); - - return 0; -} diff -Nru a/drivers/ide/macide.c b/drivers/ide/macide.c --- a/drivers/ide/macide.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,147 +0,0 @@ -/* - * linux/drivers/ide/macide.c -- Macintosh IDE Driver - * - * Copyright (C) 1998 by Michael Schmitz - * - * This driver was written based on information obtained from the MacOS IDE - * driver binary by Mikael Forselius - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define IDE_BASE 0x50F1A000 /* Base address of IDE controller */ - -/* - * Generic IDE registers as offsets from the base - * These match MkLinux so they should be correct. - */ - -#define IDE_DATA 0x00 -#define IDE_ERROR 0x04 /* see err-bits */ -#define IDE_NSECTOR 0x08 /* nr of sectors to read/write */ -#define IDE_SECTOR 0x0c /* starting sector */ -#define IDE_LCYL 0x10 /* starting cylinder */ -#define IDE_HCYL 0x14 /* high byte of starting cyl */ -#define IDE_SELECT 0x18 /* 101dhhhh , d=drive, hhhh=head */ -#define IDE_STATUS 0x1c /* see status-bits */ -#define IDE_CONTROL 0x38 /* control/altstatus */ - -/* - * Mac-specific registers - */ - -/* - * this register is odd; it doesn't seem to do much and it's - * not word-aligned like virtually every other hardware register - * on the Mac... - */ - -#define IDE_IFR 0x101 /* (0x101) IDE interrupt flags on Quadra: - * - * Bit 0+1: some interrupt flags - * Bit 2+3: some interrupt enable - * Bit 4: ?? - * Bit 5: IDE interrupt flag (any hwif) - * Bit 6: maybe IDE interrupt enable (any hwif) ?? - * Bit 7: Any interrupt condition - */ - -volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR); - -static int macide_offsets[IDE_NR_PORTS] = { - IDE_DATA, IDE_ERROR, IDE_NSECTOR, IDE_SECTOR, IDE_LCYL, - IDE_HCYL, IDE_SELECT, IDE_STATUS, IDE_CONTROL -}; - -int macide_ack_intr(struct ata_channel *hwif) -{ - if (*ide_ifr & 0x20) { - *ide_ifr &= ~0x20; - return 1; - } - return 0; -} - -#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY -static void macide_mediabay_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - int state = baboon->mb_status & 0x04; - - printk("macide: media bay %s detected\n", state? "removal":"insertion"); -} -#endif - -/* - * Probe for a Macintosh IDE interface - */ - -void macide_init(void) -{ - hw_regs_t hw; - int index = -1; - - switch (macintosh_config->ide_type) { - case MAC_IDE_QUADRA: - ide_setup_ports(&hw, (ide_ioreg_t)IDE_BASE, macide_offsets, - 0, 0, macide_ack_intr, IRQ_NUBUS_F); - index = ide_register_hw(&hw); - break; - case MAC_IDE_PB: - ide_setup_ports(&hw, (ide_ioreg_t)IDE_BASE, macide_offsets, - 0, 0, macide_ack_intr, IRQ_NUBUS_C); - index = ide_register_hw(&hw); - break; - case MAC_IDE_BABOON: - ide_setup_ports(&hw, (ide_ioreg_t)BABOON_BASE, macide_offsets, - 0, 0, NULL, IRQ_BABOON_1); - index = ide_register_hw(&hw); - 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 cna't get that without */ - /* probing the drive which freezes a 190. */ - - struct ata_device *drive = &ide_hwifs[index].drives[0]; - drive->capacity = drive->cyl*drive->head*drive->sect; - -#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY - request_irq(IRQ_BABOON_2, macide_mediabay_interrupt, - IRQ_FLG_FAST, "mediabay", - macide_mediabay_interrupt); -#endif - } - break; - - default: - return; - } - - if (index != -1) { - if (macintosh_config->ide_type == MAC_IDE_QUADRA) - printk("ide%d: Macintosh Quadra IDE interface\n", index); - else if (macintosh_config->ide_type == MAC_IDE_PB) - printk("ide%d: Macintosh Powerbook IDE interface\n", index); - else if (macintosh_config->ide_type == MAC_IDE_BABOON) - printk("ide%d: Macintosh Powerbook Baboon IDE interface\n", index); - else - printk("ide%d: Unknown Macintosh IDE interface\n", index); - } -} diff -Nru a/drivers/ide/main.c b/drivers/ide/main.c --- a/drivers/ide/main.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1441 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 1994-1998,2002 Linus Torvalds and authors: - * - * Mark Lord - * Gadi Oxman - * Andre Hedrick - * Jens Axboe - * Marcin Dalecki - * - * See linux/MAINTAINERS for address of current maintainer. - */ - -/* - * Handle overall infrastructure of the driver - */ - -#define VERSION "7.0.0" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef MODULE -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "timing.h" -#include "pcihost.h" -#include "ioctl.h" - - -MODULE_DESCRIPTION("ATA/ATAPI driver infrastructure"); -MODULE_PARM(options,"s"); -MODULE_LICENSE("GPL"); - -/* - * Those will be moved into separate header files eventually. - */ -#ifdef CONFIG_ETRAX_IDE -extern void init_e100_ide(void); -#endif -#ifdef CONFIG_BLK_DEV_CMD640 -extern void ide_probe_for_cmd640x(void); -#endif -#ifdef CONFIG_BLK_DEV_PDC4030 -extern int ide_probe_for_pdc4030(void); -#endif -#ifdef CONFIG_BLK_DEV_IDE_PMAC -extern void pmac_ide_probe(void); -#endif -#ifdef CONFIG_BLK_DEV_IDE_ICSIDE -extern void icside_init(void); -#endif -#ifdef CONFIG_BLK_DEV_IDE_RAPIDE -extern void rapide_init(void); -#endif -#ifdef CONFIG_BLK_DEV_GAYLE -extern void gayle_init(void); -#endif -#ifdef CONFIG_BLK_DEV_FALCON_IDE -extern void falconide_init(void); -#endif -#ifdef CONFIG_BLK_DEV_MAC_IDE -extern void macide_init(void); -#endif -#ifdef CONFIG_BLK_DEV_Q40IDE -extern void q40ide_init(void); -#endif -#ifdef CONFIG_BLK_DEV_BUDDHA -extern void buddha_init(void); -#endif -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) -extern void pnpide_init(int); -#endif - -/* default maximum number of failures */ -#define IDE_DEFAULT_MAX_FAILURES 1 - -int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ - -static int initializing; /* set while initializing built-in drivers */ -static int idebus_parameter; /* the "idebus=" parameter */ - -/* - * Protects access to global structures etc. - */ -spinlock_t ide_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; - -#ifdef CONFIG_PCI -static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ -#endif - -#ifdef ATA_ARCH_LOCK -/* - * This is used by the Atari code to obtain access to the IDE interrupt, - * which is shared between several drivers. - */ -int ide_irq_lock; -#endif - -int noautodma = 0; - -/* Single linked list of sub device type drivers */ -static struct ata_operations *ata_drivers; /* = NULL */ -static spinlock_t ata_drivers_lock = SPIN_LOCK_UNLOCKED; - -/* - * This is declared extern in ide.h, for access by other IDE modules: - */ -struct ata_channel ide_hwifs[MAX_HWIFS]; /* master data repository */ - -/* - * FIXME: This function should be unrolled in the palces where it get's used, - * since in reality it's simple architecture specific initialization. - * - * Setup hw_regs_t structure described by parameters. You may set up the hw - * structure yourself OR use this routine to do it for you. - */ -void ide_setup_ports(hw_regs_t *hw, ide_ioreg_t base, int *offsets, - ide_ioreg_t ctrl, ide_ioreg_t intr, - int (*ack_intr)(struct ata_channel *), - int irq) -{ - int i; - - for (i = 0; i < IDE_NR_PORTS; i++) { - if (offsets[i] != -1) - hw->io_ports[i] = base + offsets[i]; - else - hw->io_ports[i] = 0; - } - if (offsets[IDE_CONTROL_OFFSET] == -1) - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl; - - /* FIMXE: check if we can remove this ifdef */ -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (offsets[IDE_IRQ_OFFSET] == -1) - hw->io_ports[IDE_IRQ_OFFSET] = intr; -#endif - - hw->irq = irq; - hw->dma = NO_DMA; - hw->ack_intr = ack_intr; -} - -static void init_hwif_data(struct ata_channel *ch, unsigned int index) -{ - static const unsigned int majors[] = { - IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, - IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR - }; - - unsigned int unit; - - /* bulk initialize channel & drive info with zeros */ - memset(ch, 0, sizeof(struct ata_channel)); - - /* fill in any non-zero initial values */ - ch->index = index; - ide_init_hwif_ports(&ch->hw, ide_default_io_base(index), 0, &ch->irq); - - memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->hw.io_ports)); - - /* Most controllers cannot do transfers across 64kB boundaries. - trm290 can do transfers within a 4GB boundary, so it changes - this mask accordingly. */ - ch->seg_boundary_mask = 0xffff; - - /* Some chipsets (cs5530, any others?) think a 64kB transfer - is 0 byte transfer, so set the limit one sector smaller. - In the future, we may default to 64kB transfers and let - invidual chipsets with this problem change ch->max_segment_size. */ - ch->max_segment_size = (1<<16) - 512; - - ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET]; -#ifdef CONFIG_BLK_DEV_HD - - /* Ignore disks for which handling by the legacy driver was requested - * by the used. - */ - if (ch->io_ports[IDE_DATA_OFFSET] == 0x1f0) - ch->noprobe = 1; /* may be overridden by ide_setup() */ -#endif - - ch->major = majors[index]; - sprintf(ch->name, "ide%d", index); - ch->bus_state = BUSSTATE_ON; - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device *drive = &ch->drives[unit]; - - drive->type = ATA_DISK; - drive->select.all = (unit << 4) | 0xa0; - drive->channel = ch; - drive->ready_stat = READY_STAT; - drive->bad_wstat = BAD_W_STAT; - sprintf(drive->name, "hd%c", 'a' + (index * MAX_DRIVES) + unit); - drive->max_failures = IDE_DEFAULT_MAX_FAILURES; - - init_waitqueue_head(&drive->wqueue); - } -} - -extern struct block_device_operations ide_fops[]; - -/* - * Returns the (struct ata_device *) for a given device number. Return - * NULL if the given device number does not match any present drives. - */ -struct ata_device *get_info_ptr(kdev_t i_rdev) -{ - unsigned int major = major(i_rdev); - int h; - - for (h = 0; h < MAX_HWIFS; ++h) { - struct ata_channel *ch = &ide_hwifs[h]; - if (ch->present && major == ch->major) { - int unit = DEVICE_NR(i_rdev); - if (unit < MAX_DRIVES) { - struct ata_device *drive = &ch->drives[unit]; - if (drive->present) - return drive; - } - break; - } - } - return NULL; -} - -/* - * This routine is called to flush all partitions and partition tables - * for a changed disk, and then re-read the new partition table. - * If we are revalidating a disk because of a media change, then we - * enter with usage == 0. If we are using an ioctl, we automatically have - * usage == 1 (we need an open channel to use an ioctl :-), so this - * is our limit. - */ -int ide_revalidate(kdev_t dev) -{ - struct ata_device *drive; - struct ata_channel *channel; - struct gendisk *disk; - int unit; - - if ((drive = get_info_ptr(dev)) == NULL) - return -ENODEV; - if (ata_ops(drive) && ata_ops(drive)->revalidate) { - ata_get(ata_ops(drive)); - ata_ops(drive)->revalidate(drive); - ata_put(ata_ops(drive)); - } - channel = drive->channel; - unit = drive - channel->drives; - disk = channel->gd[unit]; - disk->part[0].nr_sects = ata_capacity(drive); - return 0; -} - -void ide_driver_module(void) -{ - int i; - - /* Don't reinit the probe if there is already one channel detected. */ - for (i = 0; i < MAX_HWIFS; ++i) { - if (ide_hwifs[i].present) - return; - } - - ideprobe_init(); -} - -/* - * Release the data associated with a channel. - */ -void ide_unregister(struct ata_channel *ch) -{ - struct gendisk *gd; - struct ata_device *d; - spinlock_t *lock; - int unit; - int i; - unsigned long flags; - unsigned int p, minor; - struct ata_channel old; - int n_irq; - int n_ch; - - spin_lock_irqsave(&ide_lock, flags); - - if (!ch->present) - goto abort; - - put_device(&ch->dev); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device * drive = &ch->drives[unit]; - - if (!drive->present) - continue; - - if (drive->busy || drive->usage) - goto abort; - - if (ata_ops(drive)) { - if (ata_ops(drive)->cleanup) { - if (ata_ops(drive)->cleanup(drive)) - goto abort; - } else - ata_unregister_device(drive); - } - } - ch->present = 0; - - /* - * All clear? Then blow away the buffer cache - */ - spin_unlock_irqrestore(&ide_lock, flags); - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device * drive = &ch->drives[unit]; - - if (!drive->present) - continue; - - minor = drive->select.b.unit << PARTN_BITS; - for (p = 0; p < (1<part[p].nr_sects > 0) { - kdev_t devp = mk_kdev(ch->major, minor+p); - invalidate_device(devp, 0); - } - } - } - - spin_lock_irqsave(&ide_lock, flags); - - /* - * Note that we only release the standard ports, and do not even try to - * handle any extra ports allocated for weird IDE interface chipsets. - */ - - if (ch->straight8) { - release_region(ch->io_ports[IDE_DATA_OFFSET], 8); - } else { - for (i = 0; i < 8; i++) - if (ch->io_ports[i]) - release_region(ch->io_ports[i], 1); - } - if (ch->io_ports[IDE_CONTROL_OFFSET]) - release_region(ch->io_ports[IDE_CONTROL_OFFSET], 1); -/* FIXME: check if we can remove this ifdef */ -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (ch->io_ports[IDE_IRQ_OFFSET]) - release_region(ch->io_ports[IDE_IRQ_OFFSET], 1); -#endif - - /* - * Remove us from the lock group. - */ - - lock = ch->lock; - d = ch->drive; - for (i = 0; i < MAX_DRIVES; ++i) { - struct ata_device *drive = &ch->drives[i]; - - if (drive->de) { - devfs_unregister(drive->de); - drive->de = NULL; - } - if (!drive->present) - continue; - - /* FIXME: possibly unneccessary */ - if (ch->drive == drive) - ch->drive = NULL; - - if (drive->id != NULL) { - kfree(drive->id); - drive->id = NULL; - } - drive->present = 0; - blk_cleanup_queue(&drive->queue); - } - if (d->present) - ch->drive = d; - - - /* - * Free the irq if we were the only channel using it. - * - * Free the lock group if we were the only member. - */ - n_irq = n_ch = 0; - for (i = 0; i < MAX_HWIFS; ++i) { - struct ata_channel *tmp = &ide_hwifs[i]; - - if (!tmp->present) - continue; - - if (tmp->irq == ch->irq) - ++n_irq; - if (tmp->lock == ch->lock) - ++n_ch; - } - if (n_irq == 1) - free_irq(ch->irq, ch); - if (n_ch == 1) { - kfree(ch->lock); - kfree(ch->active); - ch->lock = NULL; - ch->active = NULL; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - ide_release_dma(ch); -#endif - - /* - * Remove us from the kernel's knowledge. - */ - unregister_blkdev(ch->major, ch->name); - blk_dev[ch->major].data = NULL; - blk_dev[ch->major].queue = NULL; - blk_clear(ch->major); - gd = ch->gd[0]; - if (gd) { - int i; - for (i = 0; i < MAX_DRIVES; i++) - del_gendisk(gd + i); - kfree(gd->major_name); - kfree(gd->part); - if (gd->de_arr) - kfree (gd->de_arr); - if (gd->flags) - kfree (gd->flags); - kfree(gd); - for (i = 0; i < MAX_DRIVES; i++) - ch->gd[i] = NULL; - } - - /* - * Reinitialize the channel handler, but preserve any special methods for - * it. - */ - - old = *ch; - init_hwif_data(ch, ch->index); - ch->lock = old.lock; - ch->tuneproc = old.tuneproc; - ch->speedproc = old.speedproc; - ch->selectproc = old.selectproc; - ch->resetproc = old.resetproc; - ch->intrproc = old.intrproc; - ch->maskproc = old.maskproc; - ch->quirkproc = old.quirkproc; - ch->ata_read = old.ata_read; - ch->ata_write = old.ata_write; - ch->atapi_read = old.atapi_read; - ch->atapi_write = old.atapi_write; - ch->udma_setup = old.udma_setup; - ch->udma_enable = old.udma_enable; - ch->udma_start = old.udma_start; - ch->udma_stop = old.udma_stop; - ch->udma_init = old.udma_init; - ch->udma_irq_status = old.udma_irq_status; - ch->udma_timeout = old.udma_timeout; - ch->udma_irq_lost = old.udma_irq_lost; - ch->busproc = old.busproc; - ch->bus_state = old.bus_state; - ch->dma_base = old.dma_base; - ch->dma_extra = old.dma_extra; - ch->config_data = old.config_data; - ch->select_data = old.select_data; - ch->proc = old.proc; - /* FIXME: most propably this is always right:! */ -#ifndef CONFIG_BLK_DEV_IDECS - ch->irq = old.irq; -#endif - ch->major = old.major; - ch->chipset = old.chipset; - ch->autodma = old.autodma; - ch->udma_four = old.udma_four; -#ifdef CONFIG_PCI - ch->pci_dev = old.pci_dev; -#endif - ch->straight8 = old.straight8; - -abort: - spin_unlock_irqrestore(&ide_lock, flags); -} - -static int subdriver_match(struct ata_channel *channel, struct ata_operations *ops) -{ - int count, unit; - - if (!channel->present) - return 0; - - count = 0; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device *drive = &channel->drives[unit]; - if (drive->present && !drive->driver) { - (*ops->attach)(drive); - if (drive->driver != NULL) - ++count; - } - } - return count; -} - -/* - * Register an IDE interface, specifing exactly the registers etc - * Set initializing=1 iff calling before probes have taken place. - */ -int ide_register_hw(hw_regs_t *hw) -{ - int h; - int retry = 1; - struct ata_channel *ch; - - do { - for (h = 0; h < MAX_HWIFS; ++h) { - ch = &ide_hwifs[h]; - if (ch->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET]) - goto found; - } - for (h = 0; h < MAX_HWIFS; ++h) { - ch = &ide_hwifs[h]; - if ((!ch->present && (ch->unit == ATA_PRIMARY) && !initializing) || - (!ch->hw.io_ports[IDE_DATA_OFFSET] && initializing)) - goto found; - } - for (h = 0; h < MAX_HWIFS; ++h) - ide_unregister(&ide_hwifs[h]); - } while (retry--); - - return -1; - -found: - ide_unregister(ch); - if (ch->present) - return -1; - memcpy(&ch->hw, hw, sizeof(*hw)); - memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->hw.io_ports)); - ch->irq = hw->irq; - ch->noprobe = 0; - ch->chipset = hw->chipset; - - if (!initializing) { - ideprobe_init(); - /* FIXME: Do we really have to call it second time here?! */ - ide_driver_module(); - } - - /* Look up whatever there is a subdriver, which will serve this - * device and execute the attach method it is providing. - */ - { - struct ata_operations *tmp; - unsigned long flags; - - spin_lock_irqsave(&ata_drivers_lock, flags); - for(tmp = ata_drivers; tmp; tmp = tmp->next) { - if (subdriver_match(ch, tmp) > 0) - break; - } - spin_unlock_irqrestore(&ata_drivers_lock, flags); - } - - return (initializing || ch->present) ? h : -1; -} - -/**************************************************************************** - * FIXME: rewrite the following crap: - */ - -/* - * Parsing for ide_setup(): - * - * 1. the first char of s must be '='. - * 2. if the remainder matches one of the supplied keywords, - * the index (1 based) of the keyword is negated and returned. - * 3. if the remainder is a series of no more than max_vals numbers - * separated by commas, the numbers are saved in vals[] and a - * count of how many were saved is returned. Base10 is assumed, - * and base16 is allowed when prefixed with "0x". The number of - * values read will be placed in vals[0], and the values read will - * placed in vals[1] to vals[max_vals]. - * 4. otherwise, zero is returned. - */ -static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals) -{ - int i; - - if (*s++ == '=') { - /* - * Try matching against the supplied keywords, - * and return -(index+1) if we match one - */ - if (keywords != NULL) { - for (i = 0; *keywords != NULL; ++i) { - if (!strcmp(s, *keywords++)) - return -(i+1); - } - } - /* - * Look for a series of no more than "max_vals" - * numeric values separated by commas, in base10, - * or base16 when prefixed with "0x". - * Return a count of how many were found. - */ - get_options(s, max_vals+1, vals); - return vals[0]; - } - return 0; -} - -/* - * This sets reasonable default values into all fields of all instances of the - * channles and drives, but only on the first call. Subsequent calls have no - * effect (they don't wipe out anything). - * - * This routine is normally called at driver initialization time, but may also - * be called MUCH earlier during kernel "command-line" parameter processing. - * As such, we cannot depend on any other parts of the kernel (such as memory - * allocation) to be functioning yet. - * - * This is too bad, as otherwise we could dynamically allocate the ata_device - * structs as needed, rather than always consuming memory for the max possible - * number (MAX_HWIFS * MAX_DRIVES) of them. - */ -#define MAGIC_COOKIE 0x12345678 -static void __init init_global_data(void) -{ - unsigned int h; - static unsigned long magic_cookie = MAGIC_COOKIE; - - if (magic_cookie != MAGIC_COOKIE) - return; /* already initialized */ - magic_cookie = 0; - - /* Initialize all interface structures */ - for (h = 0; h < MAX_HWIFS; ++h) - init_hwif_data(&ide_hwifs[h], h); - - /* Add default hw interfaces */ - ide_init_default_hwifs(); -} - -/* - * This gets called VERY EARLY during initialization, to handle kernel "command - * line" strings beginning with "hdx=". It gets called even before the actual - * module gets initialized. - * - * Please look at Documentation/ide.txt to see the complete list of supported - * options. - */ -static int __init ata_hd_setup(char *s) -{ - int vals[4]; - struct ata_channel *ch; /* FIXME: Channel parms should not be accessed in ata_hd_setup */ - struct ata_device *drive; - unsigned int hw, unit; - const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); - - if (s[0] == '=') /* hd= is for hd.c driver and not us */ - return 0; - - printk(KERN_INFO "hd%s", s); - init_global_data(); - - if (s[0] >= 'a' && s[0] <= max_drive) { - static const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom", - "serialize", "autotune", "noautotune", - "slow", "flash", "scsi", NULL}; - unit = s[0] - 'a'; - hw = unit / MAX_DRIVES; - unit = unit % MAX_DRIVES; - ch = &ide_hwifs[hw]; - drive = &ch->drives[unit]; - - /* Look for hdx=ide-* */ - if (!strncmp(s+1, "=ide-", 5)) { - strncpy(drive->driver_req, s+2, 9); - goto done; - } - /* - * Look for last lun option: "hdxlun=" - */ - if (!strncmp(s+1, "lun=", 4)) { - if (*get_options(s+5, 2, vals) || vals[0]!=1) - goto bad_option; - if (vals[1] >= 0 && vals[1] <= 7) { - drive->last_lun = vals[1]; - drive->forced_lun = 1; - } else - printk(" -- BAD LAST LUN! Expected value from 0 to 7"); - goto done; - } - switch (match_parm(s+1, hd_words, vals, 3)) { - case -1: /* "none" */ - drive->nobios = 1; /* drop into "noprobe" */ - case -2: /* "noprobe" */ - drive->noprobe = 1; - goto done; - case -3: /* "nowerr" */ - drive->bad_wstat = BAD_R_STAT; - ch->noprobe = 0; /* FIXME: Channel parm */ - goto done; - case -4: /* "cdrom" */ - drive->present = 1; - drive->type = ATA_ROM; - ch->noprobe = 0; /* FIXME: Channel parm */ - goto done; - case -5: /* "serialize" */ - printk(" -- USE \"ide%d=serialize\" INSTEAD", hw); - goto bad_option; - case -6: /* "autotune" */ - drive->autotune = 1; - goto done; - case -7: /* "noautotune" */ - drive->autotune = 2; - goto done; - case -8: /* "slow" */ - ch->slow = 1; /* FIXME: Channel parm */ - goto done; - case -9: /* "flash" */ - drive->ata_flash = 1; - goto done; - case -10: /* "scsi" */ -#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) - drive->scsi = 1; - goto done; -#else - drive->scsi = 0; - goto bad_option; -#endif - case 3: /* cyl,head,sect */ - drive->type = ATA_DISK; - drive->cyl = drive->bios_cyl = vals[1]; - drive->head = drive->bios_head = vals[2]; - drive->sect = drive->bios_sect = vals[3]; - drive->present = 1; - drive->forced_geom = 1; - ch->noprobe = 0; - goto done; - default: - goto bad_option; - } - } - -bad_option: - printk(" -- BAD OPTION\n"); - return 1; - -done: - printk("\n"); - - return 1; -} - -/* - * This gets called VERY EARLY during initialization, to handle kernel "command - * line" strings beginning with "ide". It gets called even before the actual - * module gets initialized. - * - * Please look at Documentation/ide.txt to see the complete list of supported - * options. - */ -int __init ide_setup(char *s) -{ - int i, vals[4]; - struct ata_channel *ch; - unsigned int hw; - const char max_ch = '0' + (MAX_HWIFS - 1); - - printk(KERN_INFO "ide%s", s); - init_global_data(); - -#ifdef CONFIG_BLK_DEV_IDEDOUBLER - if (!strcmp(s, "=doubler")) { - extern int ide_doubler; - - printk(KERN_INFO" : Enabled support for ATA doublers\n"); - ide_doubler = 1; - return 1; - } -#endif - - if (!strcmp(s, "=nodma")) { - printk(KERN_INFO "ATA: Prevented DMA\n"); - noautodma = 1; - return 1; - } - -#ifdef CONFIG_PCI - if (!strcmp(s, "=reverse")) { - ide_scan_direction = 1; - printk(" : Enabled support for IDE inverse scan order.\n"); - return 1; - } -#endif - - /* - * Look for bus speed option: "idebus=" - */ - if (!strncmp(s, "bus=", 4)) { - if (*get_options(s+4, 2, vals) || vals[0] != 1) - goto bad_option; - idebus_parameter = vals[1]; - goto done; - } - - /* - * Look for interface options: "idex=" - */ - if (s[0] >= '0' && s[0] <= max_ch) { - /* - * Be VERY CAREFUL changing this: note hardcoded indexes below - */ - const char *ide_options[] = { - "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", NULL }; - const char *ide_words[] = { - "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; - hw = s[0] - '0'; - ch = &ide_hwifs[hw]; - - - switch (match_parm(s + 1, ide_options, vals, 1)) { - case -7: /* ata66 */ -#ifdef CONFIG_PCI - ch->udma_four = 1; - goto done; -#else - ch->udma_four = 0; - goto bad_channel; -#endif - case -6: /* dma */ - ch->autodma = 1; - goto done; - case -5: /* reset */ - ch->reset = 1; - goto done; - case -4: /* noautotune */ - ch->drives[0].autotune = 2; - ch->drives[1].autotune = 2; - goto done; - case -3: /* autotune */ - ch->drives[0].autotune = 1; - ch->drives[1].autotune = 1; - goto done; - case -2: /* "serialize" */ - { - struct ata_channel *mate; - - mate = &ide_hwifs[hw ^ 1]; - ch->serialized = 1; - mate->serialized = 1; - } - goto done; - - case -1: /* "noprobe" */ - ch->noprobe = 1; - goto done; - } - - /* - * Check for specific chipset name - */ - i = match_parm(s + 1, ide_words, vals, 3); - - /* - * Cryptic check to ensure chipset not already set for a channel: - */ - if (i) { /* is parameter a chipset name? */ - if (ide_hwifs[hw].chipset != ide_unknown) - goto bad_option; /* chipset already specified */ - if (i != -7 && hw != 0) - goto bad_channel; /* chipset drivers are for "ide0=" only */ - if (i != -7 && ide_hwifs[1].chipset != ide_unknown) - goto bad_option; /* chipset for 2nd port already specified */ - printk("\n"); - } - - switch (i) { -#ifdef CONFIG_BLK_DEV_PDC4030 - case -7: /* "dc4030" */ - { - extern void init_pdc4030(void); - init_pdc4030(); - goto done; - } -#endif -#ifdef CONFIG_BLK_DEV_ALI14XX - case -6: /* "ali14xx" */ - { - extern void init_ali14xx(void); - init_ali14xx(); - goto done; - } -#endif -#ifdef CONFIG_BLK_DEV_UMC8672 - case -5: /* "umc8672" */ - { - extern void init_umc8672(void); - init_umc8672(); - goto done; - } -#endif -#ifdef CONFIG_BLK_DEV_DTC2278 - case -4: /* "dtc2278" */ - { - extern void init_dtc2278(void); - init_dtc2278(); - goto done; - } -#endif -#ifdef CONFIG_BLK_DEV_CMD640 - case -3: /* "cmd640_vlb" */ - { - extern int cmd640_vlb; /* flag for cmd640.c */ - cmd640_vlb = 1; - goto done; - } -#endif -#ifdef CONFIG_BLK_DEV_HT6560B - case -2: /* "ht6560b" */ - { - extern void init_ht6560b(void); - init_ht6560b(); - goto done; - } -#endif -#if CONFIG_BLK_DEV_QD65XX - case -1: /* "qd65xx" */ - { - extern void init_qd65xx(void); - init_qd65xx(); - goto done; - } -#endif - case 1: /* base */ - vals[2] = vals[1] + 0x206; /* default ctl */ - case 2: /* base,ctl */ - vals[3] = 0; /* default irq = probe for it */ - case 3: /* base,ctl,irq */ - ch->hw.irq = vals[3]; - ide_init_hwif_ports(&ch->hw, (ide_ioreg_t) vals[1], (ide_ioreg_t) vals[2], &ch->irq); - memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports)); - ch->irq = vals[3]; - ch->noprobe = 0; - ch->chipset = ide_generic; - goto done; - - case 0: - goto bad_option; - default: - printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); - return 1; - } - } - -bad_option: - printk(" -- BAD OPTION\n"); - return 1; - -bad_channel: - printk("-- NOT SUPPORTED ON ide%d", hw); - -done: - printk("\n"); - - return 1; -} - -/****************************************************************************/ - -int ata_register_device(struct ata_device *drive, struct ata_operations *driver) -{ - unsigned long flags; - - /* FIXME: The locking here doesn't make the slightest sense! */ - spin_lock_irqsave(&ide_lock, flags); - - if (!drive->present || drive->driver != NULL || drive->busy || drive->usage) { - spin_unlock_irqrestore(&ide_lock, flags); - return 1; - } - - drive->driver = driver; - spin_unlock_irqrestore(&ide_lock, flags); - - /* Default autotune or requested autotune */ - if (drive->autotune != 2) { - struct ata_channel *ch = drive->channel; - if (ch->udma_setup) { - - /* - * Force DMAing for the beginning of the check. Some - * chipsets appear to do interesting things, if not - * checked and cleared. - * - * PARANOIA!!! - */ - - spin_lock_irqsave(ch->lock, flags); - udma_enable(drive, 0, 0); - ch->udma_setup(drive, ch->modes_map); -#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT - udma_tcq_enable(drive, 1); -#endif - spin_unlock_irqrestore(ch->lock, flags); - } - - /* Only CD-ROMs and tape drives support DSC overlap. But only - * if they are alone on a channel. */ - if (drive->type == ATA_ROM || drive->type == ATA_TAPE) { - int single = 0; - int unit; - - for (unit = 0; unit < MAX_DRIVES; ++unit) - if (drive->channel->drives[unit].present) - ++single; - - drive->dsc_overlap = (single == 1); - } else - drive->dsc_overlap = 0; - - } - return 0; -} - -/* - * This is in fact the default cleanup routine. - * - * FIXME: Check whatever we maybe don't call it twice!. - */ -int ata_unregister_device(struct ata_device *drive) -{ - if (drive->usage || drive->busy || !ata_ops(drive)) - return 1; - -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE) - pnpide_init(0); -#endif - drive->driver = NULL; - - return 0; -} - - -/* - * Register an ATA subdriver for a particular device type. - */ -int register_ata_driver(struct ata_operations *driver) -{ - unsigned long flags; - int index; - int count = 0; - - spin_lock_irqsave(&ata_drivers_lock, flags); - driver->next = ata_drivers; - ata_drivers = driver; - spin_unlock_irqrestore(&ata_drivers_lock, flags); - - for (index = 0; index < MAX_HWIFS; ++index) - count += subdriver_match(&ide_hwifs[index], driver); - - return count; -} - -EXPORT_SYMBOL(register_ata_driver); - -/* - * Unregister an ATA sub-driver for a particular device type. - */ -void unregister_ata_driver(struct ata_operations *driver) -{ - struct ata_operations **tmp; - unsigned long flags; - int index; - int unit; - - spin_lock_irqsave(&ata_drivers_lock, flags); - for (tmp = &ata_drivers; *tmp != NULL; tmp = &(*tmp)->next) { - if (*tmp == driver) { - *tmp = driver->next; - break; - } - } - spin_unlock_irqrestore(&ata_drivers_lock, flags); - - for (index = 0; index < MAX_HWIFS; ++index) { - struct ata_channel *ch = &ide_hwifs[index]; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device *drive = &ch->drives[unit]; - - if (drive->driver == driver) - (*ata_ops(drive)->cleanup)(drive); - } - } -} - -EXPORT_SYMBOL(ide_hwifs); -EXPORT_SYMBOL(ide_lock); - -devfs_handle_t ide_devfs_handle; - -EXPORT_SYMBOL(ata_register_device); -EXPORT_SYMBOL(ata_unregister_device); -EXPORT_SYMBOL(ide_register_hw); -EXPORT_SYMBOL(ide_unregister); -EXPORT_SYMBOL(get_info_ptr); - -/* - * Handle power handling related events ths system informs us about. - */ -static int ata_sys_notify(struct notifier_block *this, unsigned long event, void *x) -{ - int i; - - switch (event) { - case SYS_HALT: - case SYS_POWER_OFF: - case SYS_RESTART: - break; - default: - return NOTIFY_DONE; - } - - printk(KERN_INFO "flushing ATA/ATAPI devices: "); - - for (i = 0; i < MAX_HWIFS; i++) { - int unit; - struct ata_channel *ch = &ide_hwifs[i]; - - if (!ch->present) - continue; - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device *drive = &ch->drives[unit]; - - if (!drive->present) - continue; - - /* set the drive to standby */ - printk("%s ", drive->name); - if (ata_ops(drive)) { - if (event != SYS_RESTART) { - if (ata_ops(drive)->standby && ata_ops(drive)->standby(drive)) - continue; - } - - if (ata_ops(drive)->cleanup) - ata_ops(drive)->cleanup(drive); - } - } - } - printk("\n"); - return NOTIFY_DONE; -} - -static struct notifier_block ata_notifier = { - ata_sys_notify, - NULL, - 5 -}; - -/* - * This is the global initialization entry point. - */ -static int __init ata_module_init(void) -{ - printk(KERN_INFO "ATA/ATAPI device driver v" VERSION "\n"); - - ide_devfs_handle = devfs_mk_dir(NULL, "ide", NULL); - - /* - * Because most of the ATA adapters represent the timings in unit of - * bus clocks, and there is no known reliable way to detect the bus - * clock frequency, we assume 50 MHz for non-PCI (VLB, EISA) and 33 MHz - * for PCI based systems. Since assuming only hurts performance and not - * stability, this is OK. The user can change this on the command line - * by using the "idebus=XX" parameter. While the system_bus_speed - * variable is in kHz units, we accept both MHz and kHz entry on the - * command line for backward compatibility. - */ - - system_bus_speed = 50000; - - if (pci_present()) - system_bus_speed = 33333; - - if (idebus_parameter >= 20 && idebus_parameter <= 80) { - - system_bus_speed = idebus_parameter * 1000; - - switch (system_bus_speed) { - case 33000: system_bus_speed = 33333; break; - case 37000: system_bus_speed = 37500; break; - case 41000: system_bus_speed = 41666; break; - case 66000: system_bus_speed = 66666; break; - } - } - - if (idebus_parameter >= 20000 && idebus_parameter <= 80000) - system_bus_speed = idebus_parameter; - - printk(KERN_INFO "ATA: %s bus speed %d.%dMHz\n", - pci_present() ? "PCI" : "System", system_bus_speed / 1000, system_bus_speed / 100 % 10); - - init_global_data(); - - initializing = 1; - -#ifdef CONFIG_PCI - /* - * Register the host chip drivers. - */ -# ifdef CONFIG_BLK_DEV_PIIX - init_piix(); -# endif -# ifdef CONFIG_BLK_DEV_VIA82CXXX - init_via82cxxx(); -# endif -# ifdef CONFIG_BLK_DEV_PDC202XX - init_pdc202xx(); -# endif -# ifdef CONFIG_BLK_DEV_RZ1000 - init_rz1000(); -# endif -# ifdef CONFIG_BLK_DEV_SIS5513 - init_sis5513(); -# endif -# ifdef CONFIG_BLK_DEV_CMD64X - init_cmd64x(); -# endif -# ifdef CONFIG_BLK_DEV_OPTI621 - init_opti621(); -# endif -# ifdef CONFIG_BLK_DEV_TRM290 - init_trm290(); -# endif -# ifdef CONFIG_BLK_DEV_NS87415 - init_ns87415(); -# endif -# ifdef CONFIG_BLK_DEV_AEC62XX - init_aec62xx(); -# endif -# ifdef CONFIG_BLK_DEV_SL82C105 - init_sl82c105(); -# endif -# ifdef CONFIG_BLK_DEV_HPT34X - init_hpt34x(); -# endif -# ifdef CONFIG_BLK_DEV_HPT366 - init_hpt366(); -# endif -# ifdef CONFIG_BLK_DEV_ALI15X3 - init_ali15x3(); -# endif -# ifdef CONFIG_BLK_DEV_CY82C693 - init_cy82c693(); -# endif -# ifdef CONFIG_BLK_DEV_CS5530 - init_cs5530(); -# endif -# ifdef CONFIG_BLK_DEV_AMD74XX - init_amd74xx(); -# endif -# ifdef CONFIG_BLK_DEV_SVWKS - init_svwks(); -# endif -# ifdef CONFIG_BLK_DEV_IT8172 - init_it8172(); -# endif - - init_ata_pci_misc(); - - /* - * Detect and initialize "known" IDE host chip types. - */ - if (pci_present()) { -# ifdef CONFIG_PCI - ide_scan_pcibus(ide_scan_direction); -# else -# ifdef CONFIG_BLK_DEV_RZ1000 - ide_probe_for_rz100x(); -# endif -# endif - } -#endif - -#ifdef CONFIG_ETRAX_IDE - init_e100_ide(); -#endif -#ifdef CONFIG_BLK_DEV_CMD640 - ide_probe_for_cmd640x(); -#endif -#ifdef CONFIG_BLK_DEV_PDC4030 - ide_probe_for_pdc4030(); -#endif -#ifdef CONFIG_BLK_DEV_IDE_PMAC - pmac_ide_probe(); -#endif -#ifdef CONFIG_BLK_DEV_IDE_ICSIDE - icside_init(); -#endif -#ifdef CONFIG_BLK_DEV_IDE_RAPIDE - rapide_init(); -#endif -#ifdef CONFIG_BLK_DEV_GAYLE - gayle_init(); -#endif -#ifdef CONFIG_BLK_DEV_FALCON_IDE - falconide_init(); -#endif -#ifdef CONFIG_BLK_DEV_MAC_IDE - macide_init(); -#endif -#ifdef CONFIG_BLK_DEV_Q40IDE - q40ide_init(); -#endif -#ifdef CONFIG_BLK_DEV_BUDDHA - buddha_init(); -#endif -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) - pnpide_init(1); -#endif - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -# if defined(__mc68000__) || defined(CONFIG_APUS) - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - ide_get_lock(&ide_irq_lock, NULL, NULL);/* for atari only */ - disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */ -// disable_irq_nosync(ide_hwifs[0].irq); - } -# endif - - ideprobe_init(); - -# if defined(__mc68000__) || defined(CONFIG_APUS) - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - enable_irq(ide_hwifs[0].irq); - ide_release_lock(&ide_irq_lock);/* for atari only */ - } -# endif -#endif - - /* - * Initialize all device type driver modules. - */ -#ifdef CONFIG_BLK_DEV_IDEDISK - idedisk_init(); -#endif -#ifdef CONFIG_BLK_DEV_IDECD - ide_cdrom_init(); -#endif -#ifdef CONFIG_BLK_DEV_IDETAPE - idetape_init(); -#endif -#ifdef CONFIG_BLK_DEV_IDEFLOPPY - idefloppy_init(); -#endif - - initializing = 0; - - register_reboot_notifier(&ata_notifier); - - return 0; -} - -static char *options = NULL; - -static int __init init_ata(void) -{ - - if (options != NULL && *options) { - char *next = options; - - while ((options = next) != NULL) { - if ((next = strchr(options,' ')) != NULL) - *next++ = 0; - if (!strncmp(options,"hd",2)) { - if (!ata_hd_setup(options+2)) - printk(KERN_ERR "Unknown option '%s'\n", options); - } - else if (!strncmp(options,"ide",3)) { - if (!ide_setup(options+3)) - printk(KERN_ERR "Unknown option '%s'\n", options); - } - } - } - return ata_module_init(); -} - -static void __exit cleanup_ata(void) -{ - int h; - - unregister_reboot_notifier(&ata_notifier); - for (h = 0; h < MAX_HWIFS; ++h) { - ide_unregister(&ide_hwifs[h]); - } - - devfs_unregister(ide_devfs_handle); -} - -module_init(init_ata); -module_exit(cleanup_ata); - -#ifndef MODULE - -/* command line option parser */ -__setup("ide", ide_setup); -__setup("hd", ata_hd_setup); - -#endif diff -Nru a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c --- a/drivers/ide/ns87415.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,228 +0,0 @@ -/* - * linux/drivers/ide/ns87415.c Version 1.01 Mar. 18, 2000 - * - * Copyright (C) 1997-1998 Mark Lord - * Copyright (C) 1998 Eddie C. Dost - * Copyright (C) 1999-2000 Andre Hedrick - * - * Inspired by an earlier effort from David S. Miller - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "pcihost.h" - -static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; - -/* - * This routine either enables/disables (according to drive->present) - * the IRQ associated with the port (drive->channel), - * and selects either PIO or DMA handshaking for the next I/O operation. - */ -static void ns87415_prepare_drive(struct ata_device *drive, unsigned int use_dma) -{ - struct ata_channel *hwif = drive->channel; - 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); - new = *old; - - /* Adjust IRQ enable bit */ - bit = 1 << (8 + hwif->unit); - new = drive->present ? (new & ~bit) : (new | bit); - - /* Select PIO or DMA, DMA may only be selected for one drive/channel. */ - bit = 1 << (20 + drive->select.b.unit + (hwif->unit << 1)); - other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->unit << 1)); - new = use_dma ? ((new & ~other) | bit) : (new & ~bit); - - if (new != *old) { - unsigned char stat; - - /* - * Don't change DMA engine settings while Write Buffers - * are busy. - */ - (void) pci_read_config_byte(dev, 0x43, &stat); - while (stat & 0x03) { - udelay(1); - (void) pci_read_config_byte(dev, 0x43, &stat); - } - - *old = new; - (void) pci_write_config_dword(dev, 0x40, new); - - /* - * And let things settle... - */ - udelay(10); - } - - local_irq_restore(flags); -} - -static void ns87415_selectproc(struct ata_device *drive) -{ - ns87415_prepare_drive (drive, drive->using_dma); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA - -static int ns87415_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - u8 dma_stat; - - dma_stat = inb(ch->dma_base+2); - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - outb(inb(dma_base)|6, dma_base); /* from ERRATA: clear the INTR & ERROR bits */ - udma_destroy_table(ch); /* and free any DMA resources */ - - return (dma_stat & 7) != 4; /* verify good DMA status */ - -} - -static int ns87415_udma_init(struct ata_device *drive, struct request *rq) -{ - ns87415_prepare_drive(drive, 1); /* select DMA xfer */ - - if (udma_pci_init(drive, rq)) /* use standard DMA stuff */ - return ATA_OP_CONTINUES; - - ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ - - return ATA_OP_FINISHED; -} - -static int ns87415_udma_setup(struct ata_device *drive, int map) -{ - if (drive->type != ATA_DISK) { - udma_enable(drive, 0, 0); - - return 0; - } - return udma_pci_setup(drive, map); -} -#endif - -static void __init ide_init_ns87415(struct ata_channel *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - unsigned int ctrl, using_inta; - u8 progif; - - /* Set a good latency timer and cache line size value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); -#ifdef __sparc_v9__ - (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); -#endif - - /* - * We cannot probe for IRQ: both ports share common IRQ on INTA. - * Also, leave IRQ masked during drive probing, to prevent infinite - * interrupts from a potentially floating INTA.. - * - * IRQs get unmasked in selectproc when drive is first used. - */ - (void) pci_read_config_dword(dev, 0x40, &ctrl); - (void) pci_read_config_byte(dev, 0x09, &progif); - /* is irq in "native" mode? */ - using_inta = progif & (1 << (hwif->unit << 1)); - if (!using_inta) - using_inta = ctrl & (1 << (4 + hwif->unit)); - if (hwif->unit == ATA_SECONDARY) { - - /* FIXME: If we are initializing the secondary channel, let us - * assume that the primary channel got initialized just a tad - * bit before now. It would be much cleaner if the data in - * ns87415_control just got duplicated. - */ - - if (!hwif->select_data) - hwif->select_data = (unsigned long) - &ns87415_control[ns87415_count - 1]; - } else { - if (!hwif->select_data) - hwif->select_data = (unsigned long) - &ns87415_control[ns87415_count++]; - ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */ - if (using_inta) - ctrl &= ~(1 << 6); /* unmask INTA */ - *((unsigned int *)hwif->select_data) = ctrl; - (void) pci_write_config_dword(dev, 0x40, ctrl); - - /* - * Set prefetch size to 512 bytes for both ports, - * but don't turn on/off prefetching here. - */ - pci_write_config_byte(dev, 0x55, 0xee); - -#ifdef __sparc_v9__ - /* - * XXX: Reset the device, if we don't it will not respond - * to select properly during first probe. - */ - ata_reset(hwif); -#endif - } - - if (hwif->dma_base) - outb(0x60, hwif->dma_base + 2); - - if (!using_inta) - hwif->irq = hwif->unit ? 15 : 14; /* legacy mode */ - else { - static int primary_irq = 0; - - /* Ugly way to let the primary and secondary channel on the - * chip use the same IRQ line. - */ - - if (hwif->unit == ATA_PRIMARY) - primary_irq = hwif->irq; - else if (!hwif->irq) - hwif->irq = primary_irq; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->udma_stop = ns87415_udma_stop; - hwif->udma_init = ns87415_udma_init; - hwif->udma_setup = ns87415_udma_setup; - } -#endif - - hwif->selectproc = &ns87415_selectproc; -} - -/* module data table */ -static struct ata_pci_device chipset __initdata = { - .vendor = PCI_VENDOR_ID_NS, - .device = PCI_DEVICE_ID_NS_87415, - .init_channel = ide_init_ns87415, - .bootable = ON_BOARD, -}; - -int __init init_ns87415(void) -{ - ata_register_chipset(&chipset); - - return 0; -} diff -Nru a/drivers/ide/opti621.c b/drivers/ide/opti621.c --- a/drivers/ide/opti621.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,346 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) - * - * Authors: - * Jaromir Koutek , - * Jan Harkes , - * Mark Lord - * Some parts of code are from ali14xx.c and from rz1000.c. - * - * OPTi is trademark of OPTi, Octek is trademark of Octek. - * - * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps - * and disassembled/traced setupvic.exe (DOS program). - * It increases kernel code about 2 kB. - * I don't have this card no more, but I hope I can get some in case - * of needed development. - * My card is Octek PIDE 1.01 (on card) or OPTiViC (program). - * It has a place for a secondary connector in circuit, but nothing - * is there. Also BIOS says no address for - * secondary controller (see bellow in ide_init_opti621). - * I've only tested this on my system, which only has one disk. - * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus - * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random - * lockups). I tried the OCTEK double speed CD-ROM and - * it does not work! But I can't boot DOS also, so it's probably - * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no - * problems) and Seagate 1GB (as slave, WD as master). My experiences - * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes - * it slows to about 100kB/s! I don't know why and I have - * not this drive now, so I can't try it again. - * I write this driver because I lost the paper ("manual") with - * settings of jumpers on the card and I have to boot Linux with - * Loadlin except LILO, cause I have to run the setupvic.exe program - * already or I get disk errors (my test: rpm -Vf - * /usr/X11R6/bin/XF86_SVGA - or any big file). - * Some numbers from hdparm -t /dev/hda: - * Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec - * Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec - * I have 4 Megs/s before, but I don't know why (maybe changes - * in hdparm test). - * After release of 0.1, I got some successful reports, so it might work. - * - * The main problem with OPTi is that some timings for master - * and slave must be the same. For example, if you have master - * PIO 3 and slave PIO 0, driver have to set some timings of - * master for PIO 0. Second problem is that opti621_tune_drive - * got only one drive to set, but have to set both drives. - * This is solved in compute_pios. If you don't set - * the second drive, compute_pios use ide_get_best_pio_mode - * for autoselect mode (you can change it to PIO 0, if you want). - * If you then set the second drive to another PIO, the old value - * (automatically selected) will be overrided by yours. - * There is a 25/33MHz switch in configuration - * register, but driver is written for use at any frequency which get - * (use idebus=xx to select PCI bus speed). - * Use ide0=autotune for automatical tune of the PIO modes. - * If you get strange results, do not use this and set PIO manually - * by hdparm. - * - * Version 0.1, Nov 8, 1996 - * by Jaromir Koutek, for 2.1.8. - * Initial version of driver. - * - * Version 0.2 - * Number 0.2 skipped. - * - * Version 0.3, Nov 29, 1997 - * by Mark Lord (probably), for 2.1.68 - * Updates for use with new IDE block driver. - * - * Version 0.4, Dec 14, 1997 - * by Jan Harkes - * Fixed some errors and cleaned the code. - * - * Version 0.5, Jan 2, 1998 - * by Jaromir Koutek - * Updates for use with (again) new IDE block driver. - * Update of documentation. - * - * Version 0.6, Jan 2, 1999 - * by Jaromir Koutek - * Reversed to version 0.3 of the driver, because - * 0.5 doesn't work. - */ - -#define OPTI621_DEBUG /* define for debug messages */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "pcihost.h" - -#define OPTI621_MAX_PIO 3 -/* In fact, I do not have any PIO 4 drive - * (address: 25 ns, data: 70 ns, recovery: 35 ns), - * but OPTi 82C621 is programmable and it can do (minimal values): - * on 40MHz PCI bus (pulse 25 ns): - * address: 25 ns, data: 25 ns, recovery: 50 ns; - * on 20MHz PCI bus (pulse 50 ns): - * address: 50 ns, data: 50 ns, recovery: 100 ns. - */ - -/* #define READ_PREFETCH 0 */ -/* Uncommnent for disable read prefetch. - * There is some readprefetch capatibility in hdparm, - * but when I type hdparm -P 1 /dev/hda, I got errors - * and till reset drive is inaccessible. - * This (hw) read prefetch is safe on my drive. - */ - -#ifndef READ_PREFETCH -#define READ_PREFETCH 0x40 /* read prefetch is enabled */ -#endif /* else read prefetch is disabled */ - -#define READ_REG 0 /* index of Read cycle timing register */ -#define WRITE_REG 1 /* index of Write cycle timing register */ -#define CNTRL_REG 3 /* index of Control register */ -#define STRAP_REG 5 /* index of Strap register */ -#define MISC_REG 6 /* index of Miscellaneous register */ - -int reg_base; - -#define PIO_NOT_EXIST 254 -#define PIO_DONT_KNOW 255 - -/* there are stored pio numbers from other calls of opti621_tune_drive */ - -static void compute_pios(struct ata_device *drive, u8 pio) -/* Store values into drive->drive_data - * second_contr - 0 for primary controller, 1 for secondary - * slave_drive - 0 -> pio is for master, 1 -> pio is for slave - * pio - PIO mode for selected drive (for other we don't know) - */ -{ - int d; - struct ata_channel *hwif = drive->channel; - - if (pio == PIO_DONT_KNOW) - drive->drive_data = min(ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0, OPTI621_MAX_PIO); - else - drive->drive_data = pio; - - for (d = 0; d < 2; ++d) { - drive = &hwif->drives[d]; - if (drive->present) { - if (drive->drive_data == PIO_DONT_KNOW) - drive->drive_data = min(ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0, OPTI621_MAX_PIO); -#ifdef OPTI621_DEBUG - printk("%s: Selected PIO mode %d\n", drive->name, drive->drive_data); -#endif - } else { - drive->drive_data = PIO_NOT_EXIST; - } - } -} - -static int cmpt_clk(int time, int bus_speed) -/* Returns (rounded up) time in clocks for time in ns, - * with bus_speed in MHz. - * Example: bus_speed = 40 MHz, time = 80 ns - * 1000/40 = 25 ns (clk value), - * 80/25 = 3.2, rounded up to 4 (I hope ;-)). - * Use idebus=xx to select right frequency. - */ -{ - return ((time*bus_speed+999999)/1000000); -} - -static void write_reg(u8 value, int reg) -/* Write value to register reg, base of register - * is at reg_base (0x1f0 primary, 0x170 secondary, - * if not changed by PCI configuration). - * This is from setupvic.exe program. - */ -{ - inw(reg_base+1); - inw(reg_base+1); - outb(3, reg_base+2); - outb(value, reg_base+reg); - outb(0x83, reg_base+2); -} - -static u8 read_reg(int reg) -/* Read value from register reg, base of register - * is at reg_base (0x1f0 primary, 0x170 secondary, - * if not changed by PCI configuration). - * This is from setupvic.exe program. - */ -{ - u8 ret; - inw(reg_base+1); - inw(reg_base+1); - outb(3, reg_base+2); - ret=inb(reg_base+reg); - outb(0x83, reg_base+2); - return ret; -} - -typedef struct pio_clocks_s { - int address_time; /* Address setup (clocks) */ - int data_time; /* Active/data pulse (clocks) */ - int recovery_time; /* Recovery time (clocks) */ -} pio_clocks_t; - -static void compute_clocks(int pio, pio_clocks_t *clks) -{ - if (pio != PIO_NOT_EXIST) { - int adr_setup; - int data_pls; - struct ata_timing *t; - - t = ata_timing_data(pio); - - adr_setup = t->setup; - data_pls = t->active; - clks->address_time = cmpt_clk(adr_setup, system_bus_speed); - clks->data_time = cmpt_clk(data_pls, system_bus_speed); - clks->recovery_time = cmpt_clk(t->cycle - - adr_setup-data_pls, system_bus_speed); - if (clks->address_time<1) clks->address_time = 1; - if (clks->address_time>4) clks->address_time = 4; - if (clks->data_time<1) clks->data_time = 1; - if (clks->data_time>16) clks->data_time = 16; - if (clks->recovery_time<2) clks->recovery_time = 2; - if (clks->recovery_time>17) clks->recovery_time = 17; - } else { - clks->address_time = 1; - clks->data_time = 1; - clks->recovery_time = 2; - /* minimal values */ - } - -} - -/* Main tune procedure, called from tuneproc. - Assumes IRQ's are disabled or at least that no other process will - attempt to access the IDE registers concurrently. -*/ -static void opti621_tune_drive(struct ata_device *drive, u8 pio) -{ - /* primary and secondary drives share some registers, - * so we have to program both drives - */ - u8 pio1, pio2; - pio_clocks_t first, second; - int ax, drdy; - u8 cycle1, cycle2, misc; - struct ata_channel *hwif = drive->channel; - - /* sets drive->drive_data for both drives */ - compute_pios(drive, pio); - pio1 = hwif->drives[0].drive_data; - pio2 = hwif->drives[1].drive_data; - - compute_clocks(pio1, &first); - compute_clocks(pio2, &second); - - /* ax = max(a1,a2) */ - ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; - - drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ - - cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); - cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2); - misc = READ_PREFETCH | ((ax-1)<<4) | ((drdy-2)<<1); - -#ifdef OPTI621_DEBUG - printk("%s: master: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n", - hwif->name, ax, first.data_time, first.recovery_time, drdy); - printk("%s: slave: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n", - hwif->name, ax, second.data_time, second.recovery_time, drdy); -#endif - - reg_base = hwif->io_ports[IDE_DATA_OFFSET]; - outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */ - outb(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */ - inb(reg_base+CNTRL_REG); /* if reads 0xff, adapter not exist? */ - read_reg(CNTRL_REG); /* if reads 0xc0, no interface exist? */ - read_reg(STRAP_REG); /* read version, probably 0 */ - - /* program primary drive */ - write_reg(0, MISC_REG); /* select Index-0 for Register-A */ - write_reg(cycle1, READ_REG); /* set read cycle timings */ - write_reg(cycle1, WRITE_REG); /* set write cycle timings */ - - /* program secondary drive */ - write_reg(1, MISC_REG); /* select Index-1 for Register-B */ - write_reg(cycle2, READ_REG); /* set read cycle timings */ - write_reg(cycle2, WRITE_REG); /* set write cycle timings */ - - write_reg(0x85, CNTRL_REG); /* use Register-A for drive 0 */ - /* use Register-B for drive 1 */ - - write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */ - /* and read prefetch for both drives */ -} - -/* - * ide_init_opti621() is called once for each hwif found at boot. - */ -static void __init ide_init_opti621(struct ata_channel *hwif) -{ - hwif->drives[0].drive_data = PIO_DONT_KNOW; - hwif->drives[1].drive_data = PIO_DONT_KNOW; - hwif->tuneproc = &opti621_tune_drive; -} - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_OPTI, - .device = PCI_DEVICE_ID_OPTI_82C621, - .init_channel = ide_init_opti621, - .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_OPTI, - .device = PCI_DEVICE_ID_OPTI_82C825, - .init_channel = ide_init_opti621, - .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, - .bootable = ON_BOARD - }, -}; - -int __init init_opti621(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c --- a/drivers/ide/pcidma.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,576 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * - * Based on previous work by: - * - * Copyright (c) 1999-2000 Andre Hedrick - * Copyright (c) 1995-1998 Mark Lord - * - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * Those are the generic BM DMA support functions for PCI bus based systems. - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "timing.h" - -#include -#include - -#define DEFAULT_BMIBA 0xe800 /* in case BIOS did not init it */ -#define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */ -#define DEFAULT_BMALIBA 0xd400 /* ALI's default value */ - -/* - * This is the handler for disk read/write DMA interrupts. - */ -ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq) -{ - u8 dma_stat; - dma_stat = udma_stop(drive); - - if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { - if (!dma_stat) { - ata_end_request(drive, rq, 1, rq->nr_sectors); - - return ATA_OP_FINISHED; - } - printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", - drive->name, dma_stat); - } - - return ata_error(drive, rq, __FUNCTION__); -} - -/* - * FIXME: taskfiles should be a map of pages, not a long virt address... /jens - * FIXME: I agree with Jens --mdcki! - */ -static int build_sglist(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - struct scatterlist *sg = ch->sg_table; - int nents = 0; - - if ((rq->flags & REQ_SPECIAL) && (drive->type == ATA_DISK)) { - struct ata_taskfile *args = rq->special; -#if 1 - unsigned char *virt_addr = rq->buffer; - int sector_count = rq->nr_sectors; -#else - nents = blk_rq_map_sg(&drive->queue, rq, ch->sg_table); - - if (nents > rq->nr_segments) - printk("ide-dma: received %d segments, build %d\n", rq->nr_segments, nents); -#endif - - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - ch->sg_dma_direction = PCI_DMA_TODEVICE; - else - ch->sg_dma_direction = PCI_DMA_FROMDEVICE; - - /* - * FIXME: This depends upon a hard coded page size! - */ - if (sector_count > 128) { - memset(&sg[nents], 0, sizeof(*sg)); - - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK; - sg[nents].length = 128 * SECTOR_SIZE; - ++nents; - virt_addr = virt_addr + (128 * SECTOR_SIZE); - sector_count -= 128; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK; - sg[nents].length = sector_count * SECTOR_SIZE; - ++nents; - } else { - nents = blk_rq_map_sg(&drive->queue, rq, ch->sg_table); - - if (rq->q && nents > rq->nr_phys_segments) - printk("ide-dma: received %d phys segments, build %d\n", rq->nr_phys_segments, nents); - - if (rq_data_dir(rq) == READ) - ch->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - ch->sg_dma_direction = PCI_DMA_TODEVICE; - - } - - return pci_map_sg(ch->pci_dev, sg, nents, ch->sg_dma_direction); -} - -/* - * 1 dma-ing, 2 error, 4 intr - */ -static ide_startstop_t dma_timer_expiry(struct ata_device *drive, struct request *rq, unsigned long *wait) -{ - /* FIXME: What's that? */ - u8 dma_stat = inb(drive->channel->dma_base + 2); - -#ifdef DEBUG - printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat); -#endif - -#if 0 - drive->expiry = NULL; /* one free ride for now */ -#endif - *wait = 0; - if (dma_stat & 2) { /* ERROR */ - ata_status(drive, 0, 0); - return ata_error(drive, rq, __FUNCTION__); - } - if (dma_stat & 1) { /* DMAing */ - *wait = WAIT_CMD; - return ATA_OP_CONTINUES; - } - - return ATA_OP_FINISHED; -} - -int ata_start_dma(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - unsigned int reading = 0; - - if (rq_data_dir(rq) == READ) - reading = 1 << 3; - - /* try PIO instead of DMA */ - if (!udma_new_table(drive, rq)) - return 1; - - outl(ch->dmatable_dma, dma_base + 4); /* PRD table */ - outb(reading, dma_base); /* specify r/w */ - outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ - - return 0; -} - -/* generic udma_setup() function for drivers having ->speedproc/tuneproc */ -int udma_generic_setup(struct ata_device *drive, int map) -{ - struct hd_driveid *id = drive->id; - struct ata_channel *ch = drive->channel; - int on = 0; - u8 mode; - - if (!id || (drive->type != ATA_DISK && ch->no_atapi_autodma)) - return 0; - - if ((map & XFER_UDMA_80W) && !eighty_ninty_three(drive)) - map &= ~XFER_UDMA_80W; - - if ((id->capability & 1) && ch->autodma && ch->speedproc) { - - /* Consult the list of known "bad" devices. */ - if (udma_black_list(drive)) - goto set_dma; - - mode = ata_timing_mode(drive, map); - - /* Device is UltraDMA capable. */ - if (mode & XFER_UDMA) { - if((on = !ch->speedproc(drive, mode))) - goto set_dma; - - printk(KERN_WARNING "%s: UDMA auto-tune failed.\n", drive->name); - - map &= ~XFER_UDMA_ALL; - mode = ata_timing_mode(drive, map); - } - - /* Device is regular DMA capable. */ - if (mode & (XFER_SWDMA | XFER_MWDMA)) { - if((on = !ch->speedproc(drive, mode))) - goto set_dma; - - printk(KERN_WARNING "%s: DMA auto-tune failed.\n", drive->name); - } - - /* FIXME: this seems non-functional --bkz */ - /* Consult the list of known "good" devices. */ - if (udma_white_list(drive)) { - - if (id->eide_dma_time > 150) - goto set_dma; - - printk(KERN_INFO "%s: device is on DMA whitelist.\n", drive->name); -// on = 1; - } - - /* Revert to PIO. */ - if (!on && ch->tuneproc) - ch->tuneproc(drive, 255); - } - -set_dma: - udma_enable(drive, on, !on); - - return 0; -} - -/* - * Configure a device for DMA operation. - */ -int udma_pci_setup(struct ata_device *drive, int map) -{ - int config_allows_dma = 1; - struct hd_driveid *id = drive->id; - struct ata_channel *ch = drive->channel; - -#ifdef CONFIG_IDEDMA_ONLYDISK - if (drive->type != ATA_DISK) - config_allows_dma = 0; -#endif - - if (id && (id->capability & 1) && ch->autodma && config_allows_dma) { - /* Consult the list of known "bad" drives */ - if (udma_black_list(drive)) { - udma_enable(drive, 0, 1); - - return 0; - } - - /* Enable DMA on any drive that has UltraDMA (mode 6/7/?) enabled */ - if ((id->field_valid & 4) && (eighty_ninty_three(drive))) - if ((id->dma_ultra & (id->dma_ultra >> 14) & 2)) { - udma_enable(drive, 1, 1); - - return 0; - } - /* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */ - if ((id->field_valid & 4) && (eighty_ninty_three(drive))) - if ((id->dma_ultra & (id->dma_ultra >> 11) & 7)) { - udma_enable(drive, 1, 1); - - return 0; - } - /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */ - if (id->field_valid & 4) /* UltraDMA */ - if ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) { - udma_enable(drive, 1, 1); - - return 0; - } - /* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */ - if (id->field_valid & 2) /* regular DMA */ - if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) { - udma_enable(drive, 1, 1); - - return 0; - } - /* Consult the list of known "good" drives */ - if (udma_white_list(drive)) { - udma_enable(drive, 1, 1); - - return 0; - } - } - udma_enable(drive, 0, 0); - - return 0; -} - -/* - * Needed for allowing full modular support of ide-driver - */ -void ide_release_dma(struct ata_channel *ch) -{ - if (!ch->dma_base) - return; - - if (ch->dmatable_cpu) { - pci_free_consistent(ch->pci_dev, - PRD_ENTRIES * PRD_BYTES, - ch->dmatable_cpu, - ch->dmatable_dma); - ch->dmatable_cpu = NULL; - } - if (ch->sg_table) { - kfree(ch->sg_table); - ch->sg_table = NULL; - } - if ((ch->dma_extra) && (ch->unit == 0)) - release_region((ch->dma_base + 16), ch->dma_extra); - release_region(ch->dma_base, 8); - ch->dma_base = 0; -} - -/**************************************************************************** - * PCI specific UDMA channel method implementations. - */ - -/* - * This is the generic part of the DMA setup used by the host chipset drivers - * in the corresponding DMA setup method. - * - * FIXME: there are some places where this gets used driectly for "error - * recovery" in the ATAPI drivers. This was just plain wrong before, in esp. - * not portable, and just got uncovered now. - */ -void udma_pci_enable(struct ata_device *drive, int on, int verbose) -{ - struct ata_channel *ch = drive->channel; - int set_high = 1; - u8 unit; - u64 addr; - - /* Fall back to the default implementation. */ - unit = (drive->select.b.unit & 0x01); - addr = BLK_BOUNCE_HIGH; - - if (!on) { - if (verbose) - printk("%s: DMA disabled\n", drive->name); - set_high = 0; - outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2); -#ifdef CONFIG_BLK_DEV_IDE_TCQ - udma_tcq_enable(drive, 0); -#endif - } - - /* toggle bounce buffers */ - - if (on && drive->type == ATA_DISK && drive->channel->highmem) { - if (!PCI_DMA_BUS_IS_PHYS) - addr = BLK_BOUNCE_ANY; - else - addr = drive->channel->pci_dev->dma_mask; - } - - blk_queue_bounce_limit(&drive->queue, addr); - - drive->using_dma = on; - - if (on) { - outb(inb(ch->dma_base + 2) | (1 << (5 + unit)), ch->dma_base + 2); -#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT - udma_tcq_enable(drive, 1); -#endif - } -} - -/* - * This prepares a dma request. Returns 0 if all went okay, returns 1 - * otherwise. May also be invoked from trm290.c - */ -int udma_new_table(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - unsigned int *table = ch->dmatable_cpu; - int i; - struct scatterlist *sg; - - ch->sg_nents = i = build_sglist(drive, rq); - if (!i) - return 0; - - BUG_ON(i > PRD_ENTRIES); - - sg = ch->sg_table; - while (i--) { - u32 cur_addr = sg_dma_address(sg); - u32 cur_len = sg_dma_len(sg) & 0xffff; - - /* Delete this test after linux ~2.5.35, as we care - about performance in this loop. */ - BUG_ON(cur_len > ch->max_segment_size); - - *table++ = cpu_to_le32(cur_addr); - *table++ = cpu_to_le32(cur_len); - - sg++; - } - -#ifdef CONFIG_BLK_DEV_TRM290 - if (ch->chipset == ide_trm290) - *--table |= cpu_to_le32(0x80000000); -#endif - - return ch->sg_nents; -} - -/* - * Teardown mappings after DMA has completed. - */ -void udma_destroy_table(struct ata_channel *ch) -{ - pci_unmap_sg(ch->pci_dev, ch->sg_table, ch->sg_nents, ch->sg_dma_direction); -} - -/* - * Prepare the channel for a DMA startfer. Please note that only the broken - * Pacific Digital host chip needs the reques to be passed there to decide - * about addressing modes. - */ -void udma_pci_start(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - - /* Note that this is done *after* the cmd has been issued to the drive, - * as per the BM-IDE spec. The Promise Ultra33 doesn't work correctly - * when we do this part before issuing the drive cmd. - */ - outb(inb(dma_base) | 1, dma_base); /* start DMA */ -} - -int udma_pci_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - u8 dma_stat; - - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - udma_destroy_table(ch); /* purge DMA mappings */ - - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ -} - -/* - * FIXME: This should be attached to a channel as we can see now! - */ -int udma_pci_irq_status(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - u8 dma_stat; - - /* default action */ - dma_stat = inb(ch->dma_base + 2); - - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ -} - -void udma_pci_timeout(struct ata_device *drive) -{ - printk(KERN_ERR "%s: UDMA timeout!\n", drive->name); -} - -void udma_pci_irq_lost(struct ata_device *drive) -{ -} - -/* - * This can be called for a dynamically installed interface. Don't __init it - */ -void ata_init_dma(struct ata_channel *ch, unsigned long dma_base) -{ - if (!request_region(dma_base, 8, ch->name)) { - printk(KERN_ERR "ATA: ERROR: BM DMA portst already in use!\n"); - - return; - } - printk(KERN_INFO" %s: BM-DMA at 0x%04lx-0x%04lx", ch->name, dma_base, dma_base + 7); - ch->dma_base = dma_base; - ch->dmatable_cpu = pci_alloc_consistent(ch->pci_dev, - PRD_ENTRIES * PRD_BYTES, - &ch->dmatable_dma); - if (ch->dmatable_cpu == NULL) - goto dma_alloc_failure; - - ch->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, - GFP_KERNEL); - if (ch->sg_table == NULL) { - pci_free_consistent(ch->pci_dev, PRD_ENTRIES * PRD_BYTES, - ch->dmatable_cpu, ch->dmatable_dma); - goto dma_alloc_failure; - } - - /* - * We could just assign them, and then leave it up to the chipset - * specific code to override these after they've called this function. - */ - if (!ch->udma_setup) - ch->udma_setup = udma_pci_setup; - if (!ch->udma_enable) - ch->udma_enable = udma_pci_enable; - if (!ch->udma_start) - ch->udma_start = udma_pci_start; - if (!ch->udma_stop) - ch->udma_stop = udma_pci_stop; - if (!ch->udma_init) - ch->udma_init = udma_pci_init; - if (!ch->udma_irq_status) - ch->udma_irq_status = udma_pci_irq_status; - if (!ch->udma_timeout) - ch->udma_timeout = udma_pci_timeout; - if (!ch->udma_irq_lost) - ch->udma_irq_lost = udma_pci_irq_lost; - - if (ch->chipset != ide_trm290) { - u8 dma_stat = inb(dma_base+2); - printk(", BIOS settings: %s:%s, %s:%s", - ch->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio", - ch->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio"); - } - printk("\n"); - return; - -dma_alloc_failure: - printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n"); -} - -/* - * This is the default read write function. - * - * It's exported only for host chips which use it for fallback or (too) late - * capability checking. - */ -int udma_pci_init(struct ata_device *drive, struct request *rq) -{ - u8 cmd; - - if (ata_start_dma(drive, rq)) - return ATA_OP_FINISHED; - - /* No DMA transfers on ATAPI devices. */ - if (drive->type != ATA_DISK) - return ATA_OP_CONTINUES; - - if (rq_data_dir(rq) == READ) - cmd = 0x08; - else - cmd = 0x00; - - ata_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); - if (drive->addressing) - outb(cmd ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - else - outb(cmd ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - - udma_start(drive, rq); - - return ATA_OP_CONTINUES; -} - -EXPORT_SYMBOL(ide_dma_intr); -EXPORT_SYMBOL(udma_pci_enable); -EXPORT_SYMBOL(udma_pci_start); -EXPORT_SYMBOL(udma_pci_stop); -EXPORT_SYMBOL(udma_pci_init); -EXPORT_SYMBOL(udma_pci_irq_status); -EXPORT_SYMBOL(udma_pci_timeout); -EXPORT_SYMBOL(udma_pci_irq_lost); diff -Nru a/drivers/ide/pcihost.h b/drivers/ide/pcihost.h --- a/drivers/ide/pcihost.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,129 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* - * Declarations needed for the handling of PCI (mostly) based host chip set - * interfaces. - */ - -#ifdef CONFIG_BLK_DEV_PIIX -extern int init_piix(void); -#endif -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern int init_via82cxxx(void); -#endif -#ifdef CONFIG_BLK_DEV_PDC202XX -extern int init_pdc202xx(void); -#endif -#ifdef CONFIG_BLK_DEV_RZ1000 -extern int init_rz1000(void); -#endif -#ifdef CONFIG_BLK_DEV_SIS5513 -extern int init_sis5513(void); -#endif -#ifdef CONFIG_BLK_DEV_CMD64X -extern int init_cmd64x(void); -#endif -#ifdef CONFIG_BLK_DEV_OPTI621 -extern int init_opti621(void); -#endif -#ifdef CONFIG_BLK_DEV_TRM290 -extern int init_trm290(void); -#endif -#ifdef CONFIG_BLK_DEV_NS87415 -extern int init_ns87415(void); -#endif -#ifdef CONFIG_BLK_DEV_AEC62XX -extern int init_aec62xx(void); -#endif -#ifdef CONFIG_BLK_DEV_SL82C105 -extern int init_sl82c105(void); -#endif -#ifdef CONFIG_BLK_DEV_HPT34X -extern int init_hpt34x(void); -#endif -#ifdef CONFIG_BLK_DEV_HPT366 -extern int init_hpt366(void); -#endif -#ifdef CONFIG_BLK_DEV_ALI15X3 -extern int init_ali15x3(void); -#endif -#ifdef CONFIG_BLK_DEV_CY82C693 -extern int init_cy82c693(void); -#endif -#ifdef CONFIG_BLK_DEV_CS5530 -extern int init_cs5530(void); -#endif -#ifdef CONFIG_BLK_DEV_AMD74XX -extern int init_amd74xx(void); -#endif -#ifdef CONFIG_BLK_DEV_SVWKS -extern int init_svwks(void); -#endif -#ifdef CONFIG_BLK_DEV_IT8172 -extern int init_it8172(void); -#endif -extern int init_ata_pci_misc(void); - -/* - * Some combi chips, which can be used on the PCI bus or the VL bus can be in - * some systems acessed either through the PCI config space or through the - * hosts IO bus. If the corresponding initialization driver is using the host - * IO space to deal with them please define the following. - */ - -#define ATA_PCI_IGNORE ((void *)-1) - -/* - * Just to prevent us from having too many tinny headers we have consolidated - * all those declarations here. - */ - -#ifdef CONFIG_BLK_DEV_RZ1000 -extern void ide_probe_for_rz100x(void); -#endif - -typedef struct ide_pci_enablebit_s { - u8 reg; /* pci configuration register holding the enable-bit */ - u8 mask; /* mask used to isolate the enable-bit */ - u8 val; /* expected value of masked register when "enabled" */ -} ide_pci_enablebit_t; - -/* Flags used to untangle quirk handling. - */ -#define ATA_F_DMA 0x001 -#define ATA_F_NODMA 0x002 /* no DMA mode supported at all */ -#define ATA_F_NOADMA 0x004 /* DMA has to be enabled explicitely */ -#define ATA_F_FIXIRQ 0x008 /* fixed irq wiring */ -#define ATA_F_SER 0x010 /* serialize on first and second channel interrupts */ -#define ATA_F_IRQ 0x020 /* trust IRQ information from config */ -#define ATA_F_PHACK 0x040 /* apply PROMISE hacks */ -#define ATA_F_HPTHACK 0x080 /* apply HPT366 hacks */ -#define ATA_F_SIMPLEX 0x100 /* force treatment as simple device */ - - -struct ata_pci_device { - unsigned short vendor; - unsigned short device; - unsigned int (*init_chipset)(struct pci_dev *); - void (*init_channel)(struct ata_channel *); - void (*init_dma)(struct ata_channel *, unsigned long); - ide_pci_enablebit_t enablebits[2]; - unsigned int bootable; - unsigned int extra; - unsigned int flags; - struct ata_pci_device *next; /* beware we link the netries in pleace */ -}; - -extern void ata_register_chipset(struct ata_pci_device *d); diff -Nru a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c --- a/drivers/ide/pdc202xx.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,922 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * linux/drivers/ide/pdc202xx.c Version 0.30 May. 28, 2002 - * - * Copyright (C) 1998-2000 Andre Hedrick - * Copyright (C) 2002 BartÅ^Âomiej Å»oÅ^Ânierkiewicz - * - * Portions Copyright (C) 1999-2002 Promise Technology, Inc. - * Author: Frank Tiernan - * Hank Yang - * - * May be copied or modified under the terms of the GNU General Public License - * - * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this - * compiled into the kernel if you have more than one card installed. - * Note that BIOS v1.29 is reported to fix the problem. Since this is - * safe chipset tuning, including this support is harmless - * - * Promise Ultra66 cards with BIOS v1.11 this - * compiled into the kernel if you have more than one card installed. - * - * Promise Ultra100 cards. - * - * The latest chipset code will support the following :: - * Three Ultra33 controllers and 12 drives. - * - * 8 are UDMA supported and 4 are limited to DMA mode 2 multi-word. - * The 8/4 ratio is a BIOS code limit by promise. - * - * UNLESS you enable "CONFIG_PDC202XX_BURST" - * - * History: - * Sync 2.5 driver with Promise 2.4 driver v1.20.0.7 (07/11/02): - * - Add PDC20271 support - * - Disable LBA48 support on PDC20262 - * - Fix ATAPI UDMA port value - * - Add new quirk drive - * - Adjust timings for all drives when using ATA133 - * - Update pdc202xx_reset() waiting time - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "timing.h" -#include "pcihost.h" - -#define PDC202XX_DEBUG_DRIVE_INFO 0 -#define PDC202XX_DECODE_REGISTER_INFO 0 - -/* A Register */ -#define SYNC_ERRDY_EN 0xC0 - -#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */ -#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */ -#define IORDY_EN 0x20 /* PIO: IOREADY */ -#define PREFETCH_EN 0x10 /* PIO: PREFETCH */ - -#define PDC_CLK 0x11 -#define PDC_PRIMARY 0x1a -#define PDC_SECONDARY 0x1b -#define PDC_UDMA 0x1f - -#if PDC202XX_DECODE_REGISTER_INFO - -struct pdc_bit_messages { - u8 mask; - const char *msg; -}; - -static struct pdc_bit_messages pdc_reg_A[] = { - {0x80, "SYNC_IN"}, - {0x40, "ERRDY_EN"}, - {0x20, "IORDY_EN"}, - {0x10, "PREFETCH_EN"}, - /* PA3-PA0 - PIO "A" timing */ -}; - -static struct pdc_bit_messages pdc_reg_B[] = { - /* MB2-MB0 - DMA "B" timing */ - {0x10, "PIO_FORCED/PB4"}, /* PIO_FORCE 1:0 */ - /* PB3-PB0 - PIO "B" timing */ -}; - -static struct pdc_bit_messages pdc_reg_C[] = { - {0x80, "DMARQp"}, - {0x40, "IORDYp"}, - {0x20, "DMAR_EN"}, - {0x10, "DMAW_EN"}, - /* MC3-MC0 - DMA "C" timing */ -}; - -static void pdc_dump_bits(struct pdc_bit_messages *msgs, u8 bits) -{ - int i; - - printk(KERN_DEBUG " { "); - - for (i = 0; i < ARRAY_SIZE(msgs); i++, msgs++) - if (bits & msgs->mask) - printk(KERN_DEBUG "%s ", msgs->msg); - - printk(KERN_DEBUG " }\n"); -} -#endif /* PDC202XX_DECODE_REGISTER_INFO */ - -static struct ata_device *drives[4]; - -int check_in_drive_lists(struct ata_device *drive) -{ - static const char *pdc_quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP KA9.1", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP KX13.6", - "QUANTUM FIREBALLP KX20.5", - "QUANTUM FIREBALLP KX27.3", - "QUANTUM FIREBALLP LM20.5", - NULL - }; - - const char **list = pdc_quirk_drives; - struct hd_driveid *id = drive->id; - - while (*list) - if (strstr(id->model, *list++)) - return 2; - return 0; -} - -static int __init pdc202xx_modes_map(struct ata_channel *ch) -{ - int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA | XFER_UDMA; - - switch (ch->pci_dev->device) { - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20271: - case PCI_DEVICE_ID_PROMISE_20269: - map |= XFER_UDMA_133; - case PCI_DEVICE_ID_PROMISE_20268R: - case PCI_DEVICE_ID_PROMISE_20268: - map &= ~XFER_SWDMA; - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: - map |= XFER_UDMA_100; - case PCI_DEVICE_ID_PROMISE_20262: - map |= XFER_UDMA_66; - - if (!ch->udma_four) { - printk(KERN_WARNING - "%s: 40-pin cable, speed reduced to UDMA(33) mode.\n", - ch->name); - map &= ~XFER_UDMA_80W; - } - } - - return map; -} - -static int pdc202xx_tune_chipset(struct ata_device *drive, u8 speed) -{ - struct pci_dev *dev = drive->channel->pci_dev; - u32 drive_conf; - u8 drive_pci, AP, BP, CP, TA = 0, TB, TC = 0; -#if PDC202XX_DECODE_REGISTER_INFO - u8 DP; -#endif - - drive_pci = 0x60 + (drive->dn << 2); - - if ((drive->type != ATA_DISK) && (speed < XFER_SW_DMA_0)) - return -1; - - pci_read_config_dword(dev, drive_pci, &drive_conf); - pci_read_config_byte(dev, drive_pci, &AP); - pci_read_config_byte(dev, drive_pci + 1, &BP); - pci_read_config_byte(dev, drive_pci + 2, &CP); - - switch (speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_5: - case XFER_UDMA_4: - TB = 0x20; - TC = 0x01; - break; - case XFER_UDMA_3: - TB = 0x40; - TC = 0x02; - break; - case XFER_UDMA_2: - TB = 0x20; - TC = 0x01; - break; - case XFER_UDMA_1: - TB = 0x40; - TC = 0x02; - break; - case XFER_UDMA_0: - TB = 0x60; - TC = 0x03; - break; - case XFER_MW_DMA_2: - TB = 0x60; - TC = 0x03; - break; - case XFER_MW_DMA_1: - TB = 0x60; - TC = 0x04; - break; - case XFER_MW_DMA_0: - TB = 0x60; - TC = 0x05; - break; - case XFER_SW_DMA_2: - TB = 0x60; - TC = 0x05; - break; - case XFER_SW_DMA_1: - TB = 0x80; - TC = 0x06; - break; - case XFER_SW_DMA_0: - TB = 0xC0; - TC = 0x0B; - break; -#endif - case XFER_PIO_4: - TA = 0x01; - TB = 0x04; - break; - case XFER_PIO_3: - TA = 0x02; - TB = 0x06; - break; - case XFER_PIO_2: - TA = 0x03; - TB = 0x08; - break; - case XFER_PIO_1: - TA = 0x05; - TB = 0x0C; - break; - case XFER_PIO_0: - default: - TA = 0x09; - TB = 0x13; - break; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0) { - pci_write_config_byte(dev, drive_pci + 1, - (BP & ~0xf0) | TB); - pci_write_config_byte(dev, drive_pci + 2, - (CP & ~0x0f) | TC); - } else -#endif - { - pci_write_config_byte(dev, drive_pci, (AP & ~0x0f) | TA); - pci_write_config_byte(dev, drive_pci + 1, - (BP & ~0x07) | TB); - } - -#if PDC202XX_DECODE_REGISTER_INFO - pci_read_config_byte(dev, drive_pci, &AP); - pci_read_config_byte(dev, drive_pci + 1, &BP); - pci_read_config_byte(dev, drive_pci + 2, &CP); - pci_read_config_byte(dev, drive_pci + 3, &DP); - - printk(KERN_DEBUG "AP(%x): PIO(A) = %d\n", AP, AP & 0x0f); - pdc_dump_bits(pdc_reg_A, AP); - - printk(KERN_DEBUG "BP(%x): DMA(B) = %d PIO(B) = %d\n", - BP, (BP & 0xe0) >> 5, BP & 0x0f); - pdc_dump_bits(pdc_reg_B, BP); - - printk(KERN_DEBUG "CP(%x): DMA(C) = %d\n", CP, CP & 0x0f); - pdc_dump_bits(pdc_reg_C, CP); - - printk(KERN_DEBUG "DP(%x)\n", DP); -#endif - -#if PDC202XX_DEBUG_DRIVE_INFO - printk("%s: %02x drive%d 0x%08x ", - drive->name, speed, drive->dn, drive_conf); - pci_read_config_dword(dev, drive_pci, &drive_conf); - printk("0x%08x\n", drive_conf); -#endif - - return ide_config_drive_speed(drive, speed); -} - -#define set_2regs(a, b) \ - OUT_BYTE((a + adj), indexreg); \ - OUT_BYTE(b, datareg); - -#define set_reg_and_wait(value, reg, delay) \ - OUT_BYTE(value, reg); \ - mdelay(delay); - -static int pdc202xx_new_tune_chipset(struct ata_device *drive, u8 speed) -{ - struct ata_channel *hwif = drive->channel; - u32 high_16 = pci_resource_start(hwif->pci_dev, 4); - u32 indexreg = high_16 + (hwif->unit ? 0x09 : 0x01); - u32 datareg = indexreg + 2; - - u8 adj = (drive->dn % 2) ? 0x08 : 0x00; - u8 thold = 0x10; - int err, i, j = hwif->unit ? 2 : 0; - -#ifdef CONFIG_BLK_DEV_IDEDMA - /* Setting tHOLD bit to 0 if using UDMA mode 2 */ - if (speed == XFER_UDMA_2) { - OUT_BYTE((thold + adj), indexreg); - OUT_BYTE((IN_BYTE(datareg) & 0x7f), datareg); - } -#endif - - for (i = 0; i < 2; i++) - if (hwif->drives[i].present) - drives[i + j] = &hwif->drives[i]; - - err = ide_config_drive_speed(drive, speed); - - /* For modes < UDMA mode 6 we need only to SET_FEATURE */ - if (speed < XFER_UDMA_6) - return err; - - /* We need to adjust timings to ATA133 clock if ATA133 drives exist */ - for (i = 0; i < 4; i++) { - if (!drives[i]) - continue; - - /* Primary = 0x01, Secondary = 0x09 */ - indexreg = high_16 + ((i > 1) ? 0x09 : 0x01); - datareg = indexreg + 2; - - /* Master = 0x00, Slave = 0x08 */ - adj = (i % 2) ? 0x08 : 0x00; - - switch (drives[i]->current_speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_6: - set_2regs(0x10, 0x1a); - set_2regs(0x11, 0x01); - set_2regs(0x12, 0xcb); - break; - case XFER_UDMA_5: - set_2regs(0x10, 0x1a); - set_2regs(0x11, 0x02); - set_2regs(0x12, 0xcb); - break; - case XFER_UDMA_4: - set_2regs(0x10, 0x1a); - set_2regs(0x11, 0x03); - set_2regs(0x12, 0xcd); - break; - case XFER_UDMA_3: - set_2regs(0x10, 0x1a); - set_2regs(0x11, 0x05); - set_2regs(0x12, 0xcd); - break; - case XFER_UDMA_2: - set_2regs(0x10, 0x2a); - set_2regs(0x11, 0x07); - set_2regs(0x12, 0xcd); - break; - case XFER_UDMA_1: - set_2regs(0x10, 0x3a); - set_2regs(0x11, 0x0a); - set_2regs(0x12, 0xd0); - break; - case XFER_UDMA_0: - set_2regs(0x10, 0x4a); - set_2regs(0x11, 0x0f); - set_2regs(0x12, 0xd5); - break; - case XFER_MW_DMA_2: - set_2regs(0x0e, 0x69); - set_2regs(0x0f, 0x25); - break; - case XFER_MW_DMA_1: - set_2regs(0x0e, 0x6b); - set_2regs(0x0f, 0x27); - break; - case XFER_MW_DMA_0: - set_2regs(0x0e, 0xdf); - set_2regs(0x0f, 0x5f); - break; -#endif - case XFER_PIO_4: - set_2regs(0x0c, 0x23); - set_2regs(0x0d, 0x09); - set_2regs(0x13, 0x25); - break; - case XFER_PIO_3: - set_2regs(0x0c, 0x27); - set_2regs(0x0d, 0x0d); - set_2regs(0x13, 0x35); - break; - case XFER_PIO_2: - set_2regs(0x0c, 0x23); - set_2regs(0x0d, 0x26); - set_2regs(0x13, 0x64); - break; - case XFER_PIO_1: - set_2regs(0x0c, 0x46); - set_2regs(0x0d, 0x29); - set_2regs(0x13, 0xa4); - break; - case XFER_PIO_0: - set_2regs(0x0c, 0xfb); - set_2regs(0x0d, 0x2b); - set_2regs(0x13, 0xac); - break; - default: - ; - } - } - - return err; -} - -/* 0 1 2 3 4 5 6 7 8 - * 960, 480, 390, 300, 240, 180, 120, 90, 60 - * 180, 150, 120, 90, 60 - * DMA_Speed - * 180, 120, 90, 90, 90, 60, 30 - * 11, 5, 4, 3, 2, 1, 0 - */ -static void pdc202xx_tune_drive(struct ata_device *drive, u8 pio) -{ - u8 speed; - - if (pio == 255) - speed = ata_best_pio_mode(drive); - else - speed = XFER_PIO_0 + min_t(u8, pio, 4); - - pdc202xx_tune_chipset(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int pdc202xx_tx_udma_setup(struct ata_device *drive, int map) -{ - struct hd_driveid *id = drive->id; - struct ata_channel *ch = drive->channel; - u32 indexreg = ch->dma_base + 1; - u32 datareg = indexreg + 2; - u8 adj = (drive->dn % 2) ? 0x08 : 0x00; - - if (drive->type != ATA_DISK) - return 0; - - /* IORDY_EN & PREFETCH_EN */ - if (id->capability & 4) - set_2regs(0x13, (IN_BYTE(datareg) | 0x03)); - - return udma_generic_setup(drive, map); -} - -static int pdc202xx_udma_setup(struct ata_device *drive, int map) -{ - struct hd_driveid *id = drive->id; - struct ata_channel *hwif = drive->channel; - struct hd_driveid *mate_id = hwif->drives[!(drive->dn % 2)].id; - struct pci_dev *dev = hwif->pci_dev; - u32 high_16 = pci_resource_start(dev, 4); - u32 drive_conf; - u8 drive_pci = 0, AP, tmp, mode = -1; - u8 CLKSPD, mask = hwif->unit ? 0x08 : 0x02; - - /* - * Set the control register to use the 66Mhz system - * clock for UDMA 3/4 mode operations. If one drive on - * a channel is U66 capable but the other isn't we - * fall back to U33 mode. The BIOS INT 13 hooks turn - * the clock on then off for each read/write issued. - * We can do the same in device specific udma_start/stop() - * routines or better try to readjust timings. - * - * FIXME: move this to pdc202xx_tuneproc() - * right now you can't downgrade from U66 to U33 --bkz - */ - if (id->dma_ultra & 0x0078) { /* UDMA 3, 4, 5 and 6 */ - CLKSPD = IN_BYTE(high_16 + PDC_CLK); - /* check cable and mate (must be at least udma3 capable) */ - if (!hwif->udma_four || - !mate_id || !(mate_id->dma_ultra & 0x0078)) - OUT_BYTE(CLKSPD & ~mask, high_16 + PDC_CLK); - else - /* cable ok, mate ok or single drive */ - OUT_BYTE(CLKSPD | mask, high_16 + PDC_CLK); - } - - if (drive->dn > 3) /* FIXME: remove this --bkz */ - return 0; - - drive_pci = 0x60 + (drive->dn << 2); - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - - /* FIXME: what if SYNC_ERRDY is enabled for slave - and disabled for master? --bkz */ - pci_read_config_byte(dev, drive_pci, &AP); - /* enable SYNC_ERRDY for master and slave (if enabled for master) */ - if (!(AP & SYNC_ERRDY_EN)) { - if (!(drive->dn % 2)) { - pci_write_config_byte(dev, drive_pci, - AP | SYNC_ERRDY_EN); - } else { - pci_read_config_byte(dev, drive_pci - 4, &tmp); - if (tmp & SYNC_ERRDY_EN) - pci_write_config_byte(dev, drive_pci, - AP | SYNC_ERRDY_EN); - } - } - - chipset_is_set: - - if (drive->type != ATA_DISK) - return 0; - - pci_read_config_byte(dev, drive_pci, &AP); - if (id->capability & 4) /* IORDY_EN */ - pci_write_config_byte(dev, drive_pci, AP | IORDY_EN); - pci_read_config_byte(dev, drive_pci, &AP); - if (drive->type == ATA_DISK) /* PREFETCH_EN */ - pci_write_config_byte(dev, drive_pci, AP | PREFETCH_EN); - - map = hwif->modes_map; - - if (!eighty_ninty_three(drive)) - map &= ~XFER_UDMA_80W; - - mode = ata_timing_mode(drive, map); - if (mode < XFER_SW_DMA_0) { - /* restore original pci-config space */ - pci_write_config_dword(dev, drive_pci, drive_conf); - return 0; - } - - return udma_generic_setup(drive, map); -} - -static void pdc202xx_udma_start(struct ata_device *drive, - struct request *rq) -{ - struct ata_channel *ch = drive->channel; - u32 high_16 = pci_resource_start(ch->pci_dev, 4); - unsigned long atapi_port = high_16 + (ch->unit ? 0x24 : 0x20); - - /* Enable ATAPI UDMA port for 48bit data on PDC20265/PDC20267 */ - if (drive->addressing) { - unsigned long word_count = 0, hankval; - u32 clockreg = high_16 + PDC_CLK; - u8 clock = IN_BYTE(clockreg); - - OUT_BYTE(clock | (ch->unit ? 0x08 : 0x02), clockreg); - word_count = (rq->nr_sectors << 8); - hankval = - (rq_data_dir(rq) == READ) ? 0x05 << 24 : 0x06 << 24; - hankval |= word_count; - outl(hankval, atapi_port); - } - - /* Note that this is done *after* the cmd has been issued to the drive, - * as per the BM-IDE spec. The Promise Ultra33 doesn't work correctly - * when we do this part before issuing the drive cmd. - */ - - outb(inb(ch->dma_base) | 1, ch->dma_base); /* start DMA */ -} - -static int pdc202xx_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - u32 high_16 = pci_resource_start(ch->pci_dev, 4); - unsigned long atapi_port = high_16 + (ch->unit ? 0x24 : 0x20); - unsigned long dma_base = ch->dma_base; - u8 dma_stat; - - /* Disable ATAPI UDMA port for 48bit data on PDC20265/PDC20267 */ - if (drive->addressing) { - u32 clockreg = high_16 + PDC_CLK; - u8 clock; - - outl(0, atapi_port); /* zero out extra */ - clock = IN_BYTE(clockreg); - OUT_BYTE(clock & ~(ch->unit ? 0x08 : 0x02), clockreg); - } - - outb(inb(dma_base) & ~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base + 2); /* get DMA status */ - outb(dma_stat | 6, dma_base + 2); /* clear the INTR & ERROR bits */ - udma_destroy_table(ch); /* purge DMA mappings */ - - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ -} - -static void pdc202xx_bug(struct ata_device *drive) -{ - if (!drive->channel->resetproc) - return; - /* Assume naively that resetting the drive may help. */ - drive->channel->resetproc(drive); -} - -#endif - -/* FIXME: use generic ata_reset() --bzolnier */ -static void pdc202xx_reset(struct ata_device *drive) -{ - outb(0x04, drive->channel->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - outb(0x00, drive->channel->io_ports[IDE_CONTROL_OFFSET]); - printk(KERN_INFO "PDC202XX: %s channel reset.\n", - drive->channel->unit ? "Secondary" : "Primary"); -} - -/* - * software host reset - * - * BIOS will set UDMA timing on if the drive supports it. - * The user may then want to turn it off. A bug is - * that device cannot handle a downgrade in timing from - * UDMA to DMA. Disk accesses after issuing a set - * feature command will result in errors. - * - * A software reset leaves the timing registers intact, - * but resets the drives on both channels. - */ -#if 0 -static void pdc202xx_reset_host(struct pci_dev *dev) -{ - u32 high_16 = pci_resource_start(dev, 4); - u8 burst = IN_BYTE(high_16 + PDC_UDMA); - - set_reg_and_wait(burst | 0x10, high_16 + PDC_UDMA, 100); - /* FIXME: 2 seconds ?! */ - set_reg_and_wait(burst & ~0x10, high_16 + PDC_UDMA, 2000); - printk(KERN_INFO "%s: device reseted.\n", dev->name); -} - -void pdc202xx_reset(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - printk(KERN_INFO "%s: channel needs reset.\n", ch->name); - pdc202xx_reset_host(ch->pci_dev); -} -#endif - -static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev) -{ - u32 high_16 = pci_resource_start(dev, 4); - u32 burstreg = high_16 + PDC_UDMA; - u8 burst = IN_BYTE(burstreg); - - set_reg_and_wait(burst | 0x10, burstreg, 100); - /* FIXME: 2 seconds ?! */ - set_reg_and_wait(burst & ~0x10, burstreg, 2000); - - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, - dev->resource[PCI_ROM_RESOURCE]. - start | PCI_ROM_ADDRESS_ENABLE); - printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", dev->name, - dev->resource[PCI_ROM_RESOURCE].start); - } -#if 0 - switch (dev->device) { - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20262: - pdc202xx_reset_host(dev); - break; - default: - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { - u8 irq = 0, irq2 = 0; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, - &irq); - pci_read_config_byte(dev, (PCI_INTERRUPT_LINE) | 0x80, &irq2); /* 0xbc */ - if (irq != irq2) { - pci_write_config_byte(dev, (PCI_INTERRUPT_LINE) | 0x80, irq); /* 0xbc */ - printk - ("%s: pci-config space interrupt mirror fixed.\n", - dev->name); - } - } - break; - } -#endif - -#ifdef CONFIG_PDC202XX_BURST - if (!(burst & 1)) { - printk(KERN_INFO "%s: forcing (U)DMA BURST.\n", dev->name); - OUT_BYTE(burst | 1, burstreg); - burst = IN_BYTE(burstreg); - } -#endif - printk(KERN_INFO "%s: (U)DMA BURST %sabled, " - "primary %s mode, secondary %s mode.\n", - dev->name, (burst & 1) ? "en" : "dis", - (IN_BYTE(high_16 + PDC_PRIMARY) & 1) ? "MASTER" : "PCI", - (IN_BYTE(high_16 + PDC_SECONDARY) & 1) ? "MASTER" : "PCI"); - - return dev->irq; -} - -#if 0 -/* chipsets newer then 20267 */ -static unsigned int __init pdc202xx_tx_init_chipset(struct pci_dev *dev) -{ - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, - dev->resource[PCI_ROM_RESOURCE]. - start | PCI_ROM_ADDRESS_ENABLE); - printk(KERN_INFO "%s: ROM enabled at 0x%08lx.\n", - dev->name, dev->resource[PCI_ROM_RESOURCE].start); - } - return dev->irq; -} -#endif - -static unsigned int __init pdc202xx_ata66_check(struct ata_channel *ch) -{ - u16 CIS; - - pci_read_config_word(ch->pci_dev, 0x50, &CIS); - return !(CIS & (1 << (10 + ch->unit))); -} - -/* chipsets newer then 20267 */ -static unsigned int __init pdc202xx_tx_ata66_check(struct ata_channel *ch) -{ - OUT_BYTE(0x0b, ch->dma_base + 1); - return !(IN_BYTE(ch->dma_base + 3) & 0x04); -} - -static void __init ide_init_pdc202xx(struct ata_channel *hwif) -{ - hwif->tuneproc = &pdc202xx_tune_drive; - hwif->quirkproc = &check_in_drive_lists; - hwif->resetproc = &pdc202xx_reset; - - switch (hwif->pci_dev->device) { - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20271: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20268R: - hwif->udma_four = pdc202xx_tx_ata66_check(hwif); - - hwif->speedproc = &pdc202xx_new_tune_chipset; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) - hwif->udma_setup = pdc202xx_tx_udma_setup; -#endif - break; - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: -#ifdef CONFIG_BLK_DEV_IDEDMA - /* we need special functions for lba48 */ - if (hwif->dma_base) { - hwif->udma_start = pdc202xx_udma_start; - hwif->udma_stop = pdc202xx_udma_stop; - } -#endif - /* PDC20262 doesn't support LBA48 */ - case PCI_DEVICE_ID_PROMISE_20262: - hwif->udma_four = pdc202xx_ata66_check(hwif); - - case PCI_DEVICE_ID_PROMISE_20246: -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) - hwif->udma_setup = pdc202xx_udma_setup; -#endif - hwif->speedproc = &pdc202xx_tune_chipset; - default: - break; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->modes_map = pdc202xx_modes_map(hwif); - hwif->udma_irq_lost = pdc202xx_bug; - hwif->udma_timeout = pdc202xx_bug; - hwif->highmem = 1; - } else -#endif - { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -} - - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20246, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50, 0x02, 0x02}, {0x50, 0x04, 0x04}}, -#endif - .bootable = OFF_BOARD, - .extra = 16, - .flags = ATA_F_IRQ | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20262, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50, 0x02, 0x02}, {0x50, 0x04, 0x04}}, -#endif - .bootable = OFF_BOARD, - .extra = 48, - .flags = ATA_F_IRQ | ATA_F_PHACK | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20265, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50, 0x02, 0x02}, {0x50, 0x04, 0x04}}, - .bootable = OFF_BOARD, -#else - .bootable = ON_BOARD, -#endif - .extra = 48, - .flags = ATA_F_IRQ | ATA_F_PHACK | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20267, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50, 0x02, 0x02}, {0x50, 0x04, 0x04}}, -#endif - .bootable = OFF_BOARD, - .extra = 48, - .flags = ATA_F_IRQ | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20268, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, - .bootable = OFF_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA}, - /* Promise used a different PCI identification for the raid card - * apparently to try and prevent Linux detecting it and using our own - * raid code. We want to detect it for the ataraid drivers, so we have - * to list both here.. */ - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20268R, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, - .bootable = OFF_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20269, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, - .bootable = OFF_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20271, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, - .bootable = OFF_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20275, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, - .bootable = OFF_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA}, - { - .vendor = PCI_VENDOR_ID_PROMISE, - .device = PCI_DEVICE_ID_PROMISE_20276, - .init_chipset = pdc202xx_init_chipset, - .init_channel = ide_init_pdc202xx, - .bootable = OFF_BOARD, - .flags = ATA_F_IRQ | ATA_F_DMA}, -}; - -int __init init_pdc202xx(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c --- a/drivers/ide/pdc4030.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,737 +0,0 @@ -/* -*- linux-c -*- - * - * Copyright (C) 1995-2002 Linus Torvalds & authors (see below) - * - * Principal Author/Maintainer: peterd@pnd-pc.demon.co.uk - * - * This file provides support for the second port and cache of Promise - * VLB based IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2. - * - * Thanks are due to Mark Lord for advice and patiently answering stupid - * questions, and all those mugs^H^H^H^Hbrave souls who've tested this, - * especially Andre Hedrick. - * - * Version 0.01 Initial version, #include'd in ide.c rather than - * compiled separately. - * Reads use Promise commands, writes as before. Drives - * on second channel are read-only. - * Version 0.02 Writes working on second channel, reads on both - * channels. Writes fail under high load. Suspect - * transfers of >127 sectors don't work. - * Version 0.03 Brought into line with ide.c version 5.27. - * Other minor changes. - * Version 0.04 Updated for ide.c version 5.30 - * Changed initialization strategy - * Version 0.05 Kernel integration. -ml - * Version 0.06 Ooops. Add hwgroup to direct call of ide_intr() -ml - * Version 0.07 Added support for DC4030 variants - * Secondary interface autodetection - * Version 0.08 Renamed to pdc4030.c - * Version 0.09 Obsolete - never released - did manual write request - * splitting before max_sectors[major][minor] available. - * Version 0.10 Updated for 2.1 series of kernels - * Version 0.11 Updated for 2.3 series of kernels - * Autodetection code added. - * - * Version 0.90 Transition to BETA code. No lost/unexpected interrupts - * Version 0.91 Bring in line with new bio code in 2.5.1 - * Version 0.92 Update for IDE driver taskfile changes - * Version 0.93 Sync with 2.5.10, minor taskfile changes - */ - -/* - * Once you've compiled it in, you'll have to also enable the interface - * setup routine from the kernel command line, as in - * - * 'linux ide0=dc4030' or 'linux ide1=dc4030' - * - * It should now work as a second controller also ('ide1=dc4030') but only - * if you DON'T have BIOS V4.44, which has a bug. If you have this version - * and EPROM programming facilities, you need to fix 4 bytes: - * 2496: 81 81 - * 2497: 3E 3E - * 2498: 22 98 * - * 2499: 06 05 * - * 249A: F0 F0 - * 249B: 01 01 - * ... - * 24A7: 81 81 - * 24A8: 3E 3E - * 24A9: 22 98 * - * 24AA: 06 05 * - * 24AB: 70 70 - * 24AC: 01 01 - * - * As of January 1999, Promise Technology Inc. have finally supplied me with - * some technical information which has shed a glimmer of light on some of the - * problems I was having, especially with writes. - * - * There are still potential problems with the robustness and efficiency of - * this driver because I still don't understand what the card is doing with - * interrupts, however, it has been stable for a while with no reports of ill - * effects. - */ - -#undef DEBUG_READ -#undef DEBUG_WRITE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "pdc4030.h" - -/* - * Data transfer functions for polled IO. - */ - -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static void read_vlb(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - unsigned long flags; - - local_irq_save(flags); - inb(IDE_NSECTOR_REG); - inb(IDE_NSECTOR_REG); - inb(IDE_NSECTOR_REG); - insl(IDE_DATA_REG, buffer, wcount); - local_irq_restore(flags); -} - -static void write_vlb(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - unsigned long flags; - - local_irq_save(flags); - inb(IDE_NSECTOR_REG); - inb(IDE_NSECTOR_REG); - inb(IDE_NSECTOR_REG); - outsl(IDE_DATA_REG, buffer, wcount); - local_irq_restore(flags); -} - -static void read_16(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - insw(IDE_DATA_REG, buffer, wcount<<1); -} - -static void write_16(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - outsw(IDE_DATA_REG, buffer, wcount<<1); -} - -/* - * This is used for most PIO data transfers *from* the device. - */ -static void promise_read(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - if (drive->channel->io_32bit) - read_vlb(drive, buffer, wcount); - else - read_16(drive, buffer, wcount); -} - -/* - * This is used for most PIO data transfers *to* the device interface. - */ -static void promise_write(struct ata_device *drive, void *buffer, unsigned int wcount) -{ - if (drive->channel->io_32bit) - write_vlb(drive, buffer, wcount); - else - write_16(drive, buffer, wcount); -} - -/* - * promise_selectproc() is invoked by ide.c - * in preparation for access to the specified drive. - */ -static void promise_selectproc(struct ata_device *drive) -{ - u8 number; - - number = (drive->channel->unit << 1) + drive->select.b.unit; - outb(number, IDE_FEATURE_REG); -} - -/* - * pdc4030_cmd handles the set of vendor specific commands that are initiated - * by command F0. They all have the same success/failure notification - - * 'P' (=0x50) on success, 'p' (=0x70) on failure. - */ -int pdc4030_cmd(struct ata_device *drive, u8 cmd) -{ - unsigned long timeout, timer; - u8 status_val; - - promise_selectproc(drive); /* redundant? */ - outb(0xF3, IDE_SECTOR_REG); - outb(cmd, IDE_SELECT_REG); - outb(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG); - timeout = HZ * 10; - timeout += jiffies; - do { - if(time_after(jiffies, timeout)) { - return 2; /* device timed out */ - } - /* This is out of delay_10ms() */ - /* Delays at least 10ms to give interface a chance */ - timer = jiffies + (HZ + 99)/100 + 1; - while (time_after(timer, jiffies)); - status_val = inb(IDE_SECTOR_REG); - } while (status_val != 0x50 && status_val != 0x70); - - if(status_val == 0x50) - return 0; /* device returned success */ - else - return 1; /* device returned failure */ -} - -/* - * pdc4030_identify sends a vendor-specific IDENTIFY command to the drive - */ -int pdc4030_identify(struct ata_device *drive) -{ - return pdc4030_cmd(drive, PROMISE_IDENTIFY); -} - -int enable_promise_support = 0; - -void __init init_pdc4030 (void) -{ - enable_promise_support = 1; -} - -/* - * setup_pdc4030() - * Completes the setup of a Promise DC4030 controller card, once found. - */ -int __init setup_pdc4030(struct ata_channel *hwif) -{ - struct ata_device *drive; - struct ata_channel *hwif2; - struct dc_ident ident; - int i; - ide_startstop_t ret; - - if (!hwif) - return 0; - - drive = &hwif->drives[0]; - hwif2 = &ide_hwifs[hwif->index+1]; - if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ - return 1; - - if (inb(IDE_NSECTOR_REG) == 0xFF || inb(IDE_SECTOR_REG) == 0xFF) { - return 0; - } - ata_irq_enable(drive, 1); - if (pdc4030_cmd(drive, PROMISE_GET_CONFIG)) { - return 0; - } - - /* FIXME: Make this go away. */ - spin_lock_irq(hwif->lock); - ret = ata_status_poll(drive, DATA_READY, BAD_W_STAT, WAIT_DRQ, NULL); - if (ret != ATA_OP_READY) { - printk(KERN_INFO - "%s: Failed Promise read config!\n",hwif->name); - spin_unlock_irq(hwif->lock); - - return 0; - } - spin_unlock_irq(hwif->lock); - - promise_read(drive, &ident, SECTOR_WORDS); - if (ident.id[1] != 'P' || ident.id[0] != 'T') { - return 0; - } - printk(KERN_INFO "%s: Promise caching controller, ",hwif->name); - switch(ident.type) { - case 0x43: printk("DC4030VL-2, "); break; - case 0x41: printk("DC4030VL-1, "); break; - case 0x40: printk("DC4030VL, "); break; - default: - printk("unknown - type 0x%02x - please report!\n" - ,ident.type); - printk("Please e-mail the following data to " - "promise@pnd-pc.demon.co.uk along with\n" - "a description of your card and drives:\n"); - for (i=0; i < 0x90; i++) { - printk("%02x ", ((unsigned char *)&ident)[i]); - if ((i & 0x0f) == 0x0f) printk("\n"); - } - return 0; - } - printk("%dKB cache, ",(int)ident.cache_mem); - switch(ident.irq) { - case 0x00: hwif->irq = 14; break; - case 0x01: hwif->irq = 12; break; - default: hwif->irq = 15; break; - } - printk("on IRQ %d\n",hwif->irq); - - /* - * Once found and identified, we set up the next hwif in the array - * (hwif2 = ide_hwifs[hwif->index+1]) with the same io ports, irq - * and other settings as the main hwif. This gives us two "mated" - * hwifs pointing to the Promise card. - * - * We also have to shift the default values for the remaining - * interfaces "up by one" to make room for the second interface on the - * same set of values. - */ - - hwif->chipset = hwif2->chipset = ide_pdc4030; - hwif->unit = ATA_PRIMARY; - hwif2->unit = ATA_SECONDARY; - hwif->ata_read = hwif2->ata_read = promise_read; - hwif->ata_write = hwif2->ata_write = promise_write; - hwif->selectproc = hwif2->selectproc = promise_selectproc; - hwif->serialized = hwif2->serialized = 1; - -/* Shift the remaining interfaces up by one */ - for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) { - struct ata_channel *h = &ide_hwifs[i]; - -#ifdef DEBUG - printk(KERN_DEBUG "pdc4030: Shifting i/f %d values to i/f %d\n",i-1,i); -#endif - ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL); - memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports)); - h->noprobe = (h-1)->noprobe; - } - ide_init_hwif_ports(&hwif2->hw, hwif->io_ports[IDE_DATA_OFFSET], 0, NULL); - memcpy(hwif2->io_ports, hwif->hw.io_ports, sizeof(hwif2->io_ports)); - hwif2->irq = hwif->irq; - hwif2->hw.irq = hwif->hw.irq = hwif->irq; - hwif->io_32bit = hwif2->io_32bit = 1; - for (i=0; i<2 ; i++) { - if (!ident.current_tm[i].cyl) - hwif->drives[i].noprobe = 1; - if (!ident.current_tm[i+2].cyl) - hwif2->drives[i].noprobe = 1; - } - return 1; -} - -/* - * detect_pdc4030() - * Tests for the presence of a DC4030 Promise card on this interface - * Returns: 1 if found, 0 if not found - */ -int __init detect_pdc4030(struct ata_channel *hwif) -{ - struct ata_device *drive = &hwif->drives[0]; - - if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */ - return 0; - } - outb(0xF3, IDE_SECTOR_REG); - outb(0x14, IDE_SELECT_REG); - outb(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG); - - mdelay(50); - - if (inb(IDE_ERROR_REG) == 'P' && - inb(IDE_NSECTOR_REG) == 'T' && - inb(IDE_SECTOR_REG) == 'I') { - return 1; - } else { - return 0; - } -} - -void __init ide_probe_for_pdc4030(void) -{ - unsigned int index; - struct ata_channel *hwif; - - if (enable_promise_support == 0) - return; - for (index = 0; index < MAX_HWIFS; index++) { - hwif = &ide_hwifs[index]; - if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) { - setup_pdc4030(hwif); - } - } -} - -/* - * promise_read_intr() is the handler for disk read/multread interrupts - */ -static ide_startstop_t promise_read_intr(struct ata_device *drive, struct request *rq) -{ - int total_remaining; - unsigned int sectors_left, sectors_avail, nsect; - unsigned long flags; - char *to; - - if (!ata_status(drive, DATA_READY, BAD_R_STAT)) - return ata_error(drive, rq, __FUNCTION__); - -read_again: - do { - sectors_left = inb(IDE_NSECTOR_REG); - inb(IDE_SECTOR_REG); - } while (inb(IDE_NSECTOR_REG) != sectors_left); - sectors_avail = rq->nr_sectors - sectors_left; - if (!sectors_avail) - goto read_again; - -read_next: - nsect = rq->current_nr_sectors; - if (nsect > sectors_avail) - nsect = sectors_avail; - sectors_avail -= nsect; - to = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq); - promise_read(drive, to, nsect * SECTOR_WORDS); -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: promise_read: sectors(%ld-%ld), " - "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector, - rq->sector+nsect-1, (unsigned long) to, rq->nr_sectors-nsect); -#endif - bio_kunmap_irq(to, &flags); - rq->sector += nsect; - rq->errors = 0; - rq->nr_sectors -= nsect; - total_remaining = rq->nr_sectors; - if ((rq->current_nr_sectors -= nsect) <= 0) - ata_end_request(drive, rq, 1, 0); - - /* - * Now the data has been read in, do the following: - * - * if there are still sectors left in the request, if we know there are - * still sectors available from the interface, go back and read the - * next bit of the request. else if DRQ is asserted, there are more - * sectors available, so go back and find out how many, then read them - * in. else if BUSY is asserted, we are going to get an interrupt, so - * set the handler for the interrupt and just return - */ - - if (total_remaining > 0) { - if (sectors_avail) - goto read_next; - ata_status(drive, 0, 0); - if (drive->status & DRQ_STAT) - goto read_again; - if (drive->status & BUSY_STAT) { - ata_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: promise_read: waiting for" - "interrupt\n", drive->name); -#endif - return ATA_OP_CONTINUES; - } - printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " - "!DRQ !BUSY\n", drive->name); - return ata_error(drive, rq, "promise read intr"); - } - return ATA_OP_FINISHED; -} - -/* - * promise_complete_pollfunc() - * This is the polling function for waiting (nicely!) until drive stops - * being busy. It is invoked at the end of a write, after the previous poll - * has finished. - * - * Once not busy, the end request is called. - */ -static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - - if (!ata_status(drive, 0, BUSY_STAT)) { - if (time_before(jiffies, ch->poll_timeout)) { - ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); - - return ATA_OP_CONTINUES; /* continue polling... */ - } - ch->poll_timeout = 0; - printk(KERN_ERR "%s: completion timeout - still busy!\n", - drive->name); - return ata_error(drive, rq, "busy timeout"); - } - - ch->poll_timeout = 0; -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); -#endif - ata_end_request(drive, rq, 1, rq->nr_sectors); - - return ATA_OP_FINISHED; -} - -/* - * promise_multwrite() transfers a block of up to mcount sectors of data - * to a drive as part of a disk multiple-sector write operation. - * - * Returns 0 on success. - * - * Note that we may be called from two contexts - the do_rw_disk context - * and IRQ context. The IRQ can happen any time after we've output the - * full "mcount" number of sectors, so we must make sure we update the - * state _before_ we output the final part of the data! - */ -int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int mcount) -{ - do { - char *buffer; - int nsect = rq->current_nr_sectors; - unsigned long flags; - - if (nsect > mcount) - nsect = mcount; - mcount -= nsect; - - buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq); - rq->sector += nsect; - rq->nr_sectors -= nsect; - rq->current_nr_sectors -= nsect; - - /* Do we move to the next bh after this? */ - if (!rq->current_nr_sectors) { - struct bio *bio = rq->bio->bi_next; - - /* end early early we ran out of requests */ - if (!bio) { - mcount = 0; - } else { - rq->bio = bio; - rq->current_nr_sectors = bio_sectors(bio); - rq->hard_cur_sectors = rq->current_nr_sectors; - } - } - - /* - * Ok, we're all setup for the interrupt - * re-entering us on the last transfer. - */ - promise_write(drive, buffer, nsect << 7); - bio_kunmap_irq(buffer, &flags); - } while (mcount); - - return 0; -} - -/* - * promise_write_pollfunc() is the handler for disk write completion polling. - */ -static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - - if (inb(IDE_NSECTOR_REG) != 0) { - if (time_before(jiffies, ch->poll_timeout)) { - ata_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); - - return ATA_OP_CONTINUES; /* continue polling... */ - } - ch->poll_timeout = 0; - printk(KERN_ERR "%s: write timed out!\n", drive->name); - ata_status(drive, 0, 0); - - return ata_error(drive, rq, "write timeout"); - } - - /* - * Now write out last 4 sectors and poll for not BUSY - */ - promise_multwrite(drive, rq, 4); - ch->poll_timeout = jiffies + WAIT_WORSTCASE; - ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", - drive->name, drive->status); -#endif - - return ATA_OP_CONTINUES; -} - -/* - * This transfers a block of one or more sectors of data to a drive as part of - * a disk write operation. All but 4 sectors are transferred in the first - * attempt, then the interface is polled (nicely!) for completion before the - * final 4 sectors are transferred. There is no interrupt generated on writes - * (at least on the DC4030VL-2), we just have to poll for NOT BUSY. - */ -static ide_startstop_t promise_do_write(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), " - "buffer=%p\n", drive->name, rq->sector, - rq->sector + rq->nr_sectors - 1, rq->buffer); -#endif - /* - * If there are more than 4 sectors to transfer, do n-4 then go into - * the polling strategy as defined above. - */ - if (rq->nr_sectors > 4) { - if (promise_multwrite(drive, rq, rq->nr_sectors - 4)) { - - return ATA_OP_FINISHED; - } - ch->poll_timeout = jiffies + WAIT_WORSTCASE; - ata_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); - - return ATA_OP_CONTINUES; - } else { - /* - * There are 4 or fewer sectors to transfer, do them all in one go - * and wait for NOT BUSY. - */ - if (promise_multwrite(drive, rq, rq->nr_sectors)) - return ATA_OP_FINISHED; - - ch->poll_timeout = jiffies + WAIT_WORSTCASE; - ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); - -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " - "status = %02x\n", drive->name, drive->status); -#endif - return ATA_OP_CONTINUES; - } -} - -/* - * do_pdc4030_io() is called from promise_do_request, having had the block - * number already set up. It issues a READ or WRITE command to the Promise - * controller, assuming LBA has been used to set up the block number. - */ -ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *args, struct request *rq) -{ - struct hd_drive_task_hdr *taskfile = &(args->taskfile); - unsigned long timeout; - - /* Check that it's a regular command. If not, bomb out early. */ - if (!(rq->flags & REQ_CMD)) { - blk_dump_rq_flags(rq, "pdc4030 bad flags"); - ata_end_request(drive, rq, 0, 0); - - return ATA_OP_FINISHED; - } - - ata_irq_enable(drive, 1); - ata_mask(drive); - - ata_out_regfile(drive, taskfile); - - outb(taskfile->device_head, IDE_SELECT_REG); - outb(args->cmd, IDE_COMMAND_REG); - - switch (rq_data_dir(rq)) { - case READ: - - /* - * The card's behaviour is odd at this point. If the data is - * available, DRQ will be true, and no interrupt will be - * generated by the card. If this is the case, we need to call - * the "interrupt" handler (promise_read_intr) directly. - * Otherwise, if an interrupt is going to occur, bit0 of the - * SELECT register will be high, so we can set the handler the - * just return and be interrupted. If neither of these is the - * case, we wait for up to 50ms (badly I'm afraid!) until one - * of them is. - */ - - timeout = jiffies + HZ/20; /* 50ms wait */ - do { - if (!ata_status(drive, 0, DRQ_STAT)) { - udelay(1); - return promise_read_intr(drive, rq); - } - if (inb(IDE_SELECT_REG) & 0x01) { -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: read: waiting for " - "interrupt\n", drive->name); -#endif - ata_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); - - return ATA_OP_CONTINUES; - } - udelay(1); - } while (time_before(jiffies, timeout)); - - printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n", - drive->name); - return ATA_OP_FINISHED; - - case WRITE: { - ide_startstop_t ret; - - /* - * Strategy on write is: look for the DRQ that should have been - * immediately asserted copy the request into the hwgroup's - * scratchpad call the promise_write function to deal with - * writing the data out. - * - * NOTE: No interrupts are generated on writes. Write - * completion must be polled - */ - - ret = ata_status_poll(drive, DATA_READY, drive->bad_wstat, - WAIT_DRQ, rq); - if (ret != ATA_OP_READY) { - printk(KERN_ERR "%s: no DRQ after issuing " - "PROMISE_WRITE\n", drive->name); - - return ret; - } - if (!drive->channel->unmask) - local_irq_disable(); - - return promise_do_write(drive, rq); - } - - default: - printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n"); - - ata_end_request(drive, rq, 0, 0); - return ATA_OP_FINISHED; - } -} - -ide_startstop_t promise_do_request(struct ata_device *drive, struct request *rq, sector_t block) -{ - struct ata_taskfile args; - - memset(&args, 0, sizeof(args)); - - /* The four drives on the two logical (one physical) interfaces - are distinguished by writing the drive number (0-3) to the - Feature register. - FIXME: Is promise_selectproc now redundant?? - */ - args.taskfile.feature = (drive->channel->unit << 1) + drive->select.b.unit; - args.taskfile.sector_count = rq->nr_sectors; - args.taskfile.sector_number = block; - args.taskfile.low_cylinder = (block>>=8); - args.taskfile.high_cylinder = (block>>=8); - args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; - args.cmd = (rq_data_dir(rq) == READ) ? PROMISE_READ : PROMISE_WRITE; - args.XXX_handler = NULL; - rq->special = &args; - - return do_pdc4030_io(drive, &args, rq); -} diff -Nru a/drivers/ide/pdc4030.h b/drivers/ide/pdc4030.h --- a/drivers/ide/pdc4030.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,44 +0,0 @@ -/* - * linux/drivers/ide/pdc4030.h - * - * Copyright (C) 1995-1998 Linus Torvalds & authors - */ - -/* - * Principal author: Peter Denison - */ - -#ifndef IDE_PROMISE_H -#define IDE_PROMISE_H - -#define PROMISE_EXTENDED_COMMAND 0xF0 -#define PROMISE_READ 0xF2 -#define PROMISE_WRITE 0xF3 -/* Extended commands - main command code = 0xf0 */ -#define PROMISE_GET_CONFIG 0x10 -#define PROMISE_IDENTIFY 0x20 - -struct translation_mode { - u16 cyl; - u8 head; - u8 sect; -}; - -struct dc_ident { - u8 type; - u8 unknown1; - u8 hw_revision; - u8 firmware_major; - u8 firmware_minor; - u8 bios_address; - u8 irq; - u8 unknown2; - u16 cache_mem; - u16 unknown3; - u8 id[2]; - u16 info; - struct translation_mode current_tm[4]; - u8 pad[SECTOR_WORDS*4 - 32]; -}; - -#endif /* IDE_PROMISE_H */ diff -Nru a/drivers/ide/pdcraid.c b/drivers/ide/pdcraid.c --- a/drivers/ide/pdcraid.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,569 +0,0 @@ -/* - pdcraid.c Copyright (C) 2001 Red Hat, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - (for example /usr/src/linux/COPYING); if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Authors: Arjan van de Ven - - Based on work done by Søren Schmidt for FreeBSD - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ataraid.h" - -static int pdcraid_open(struct inode *inode, struct file *filp); -static int pdcraid_release(struct inode *inode, struct file *filp); -static int pdcraid_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -static int pdcraid0_make_request(request_queue_t * q, int rw, - struct buffer_head *bh); -static int pdcraid1_make_request(request_queue_t * q, int rw, - struct buffer_head *bh); - -struct disk_dev { - int major; - int minor; - int device; -}; - -static struct disk_dev devlist[] = { - {IDE0_MAJOR, 0, -1}, - {IDE0_MAJOR, 64, -1}, - {IDE1_MAJOR, 0, -1}, - {IDE1_MAJOR, 64, -1}, - {IDE2_MAJOR, 0, -1}, - {IDE2_MAJOR, 64, -1}, - {IDE3_MAJOR, 0, -1}, - {IDE3_MAJOR, 64, -1}, - {IDE4_MAJOR, 0, -1}, - {IDE4_MAJOR, 64, -1}, - {IDE5_MAJOR, 0, -1}, - {IDE5_MAJOR, 64, -1}, - {IDE6_MAJOR, 0, -1}, - {IDE6_MAJOR, 64, -1}, -}; - - -struct pdcdisk { - kdev_t device; - unsigned long sectors; - struct block_device *bdev; - unsigned long last_pos; -}; - -struct pdcraid { - unsigned int stride; - unsigned int disks; - unsigned long sectors; - struct geom geom; - - struct pdcdisk disk[8]; - - unsigned long cutoff[8]; - unsigned int cutoff_disks[8]; -}; - -static struct raid_device_operations pdcraid0_ops = { - .open = pdcraid_open, - .release = pdcraid_release, - .ioctl = pdcraid_ioctl, - .make_request = pdcraid0_make_request -}; - -static struct raid_device_operations pdcraid1_ops = { - .open = pdcraid_open, - .release = pdcraid_release, - .ioctl = pdcraid_ioctl, - .make_request = pdcraid1_make_request -}; - -static struct pdcraid raid[16]; - - -static int pdcraid_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - unsigned int minor = minor(inode->i_rdev) >> SHIFT; - struct hd_geometry *geometry = (struct hd_geometry *) arg; - struct hd_geometry g; - if (cmd != HDIO_GETGEO) - return -EINVAL; - g.heads = raid[minor].geom.heads; - g.sectors = raid[minor].geom.sectors; - g.cylinders = raid[minor].geom.cylinders; - g.start = get_start_sect(inode->i_bdev); - return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0; -} - -static int pdcraid0_make_request(request_queue_t * q, int rw, - struct buffer_head *bh) -{ - unsigned long rsect; - unsigned long rsect_left, rsect_accum = 0; - unsigned long block; - unsigned int disk = 0, real_disk = 0; - int i; - int device; - struct pdcraid *thisraid; - - rsect = bh->b_rsector; - - /* Ok. We need to modify this sector number to a new disk + new sector number. - * If there are disks of different sizes, this gets tricky. - * Example with 3 disks (1Gb, 4Gb and 5 GB): - * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. - * Then things get interesting. The next 2Gb (RAID view) are spread across disk 2 and 3 - * and the last 1Gb is disk 3 only. - * - * the way this is solved is like this: We have a list of "cutoff" points where everytime - * a disk falls out of the "higher" count, we mark the max sector. So once we pass a cutoff - * point, we have to divide by one less. - */ - - device = minor(bh->b_rdev) >> SHIFT; - thisraid = &raid[device]; - if (thisraid->stride == 0) - thisraid->stride = 1; - - /* Woops we need to split the request to avoid crossing a stride barrier */ - if ((rsect / thisraid->stride) != - ((rsect + (bh->b_size / 512) - 1) / thisraid->stride)) { - return -1; - } - - rsect_left = rsect; - - for (i = 0; i < 8; i++) { - if (thisraid->cutoff_disks[i] == 0) - break; - if (rsect > thisraid->cutoff[i]) { - /* we're in the wrong area so far */ - rsect_left -= thisraid->cutoff[i]; - rsect_accum += - thisraid->cutoff[i] / - thisraid->cutoff_disks[i]; - } else { - block = rsect_left / thisraid->stride; - disk = block % thisraid->cutoff_disks[i]; - block = - (block / thisraid->cutoff_disks[i]) * - thisraid->stride; - rsect = - rsect_accum + (rsect_left % thisraid->stride) + - block; - break; - } - } - - for (i = 0; i < 8; i++) { - if ((disk == 0) - && (thisraid->disk[i].sectors > rsect_accum)) { - real_disk = i; - break; - } - if ((disk > 0) - && (thisraid->disk[i].sectors >= rsect_accum)) { - disk--; - } - - } - disk = real_disk; - - - /* - * The new BH_Lock semantics in ll_rw_blk.c guarantee that this - * is the only IO operation happening on this bh. - */ - bh->b_rdev = thisraid->disk[disk].device; - bh->b_rsector = rsect; - - /* - * Let the main block layer submit the IO and resolve recursion: - */ - return 1; -} - -static int pdcraid1_write_request(request_queue_t * q, int rw, - struct buffer_head *bh) -{ - struct buffer_head *bh1; - struct ataraid_bh_private *private; - int device; - int i; - - device = minor(bh->b_rdev) >> SHIFT; - private = ataraid_get_private(); - if (private == NULL) - BUG(); - - private->parent = bh; - - atomic_set(&private->count, raid[device].disks); - - - for (i = 0; i < raid[device].disks; i++) { - bh1 = ataraid_get_bhead(); - /* If this ever fails we're doomed */ - if (!bh1) - BUG(); - - /* dupe the bufferhead and update the parts that need to be different */ - memcpy(bh1, bh, sizeof(*bh)); - - bh1->b_end_io = ataraid_end_request; - bh1->b_private = private; - bh1->b_rdev = raid[device].disk[i].device; - - /* update the last known head position for the drive */ - raid[device].disk[i].last_pos = - bh1->b_rsector + (bh1->b_size >> 9); - - generic_make_request(rw, bh1); - } - return 0; -} - -static int pdcraid1_read_request(request_queue_t * q, int rw, - struct buffer_head *bh) -{ - int device; - int dist; - int bestsofar, bestdist, i; - static int previous; - - device = minor(bh->b_rdev) >> SHIFT; - - /* Reads are simple in principle. Pick a disk and go. - Initially I cheat by just picking the one which the last known - head position is closest by. - Later on, online/offline checking and performance needs adding */ - - bestsofar = 0; - bestdist = raid[device].disk[0].last_pos - bh->b_rsector; - if (bestdist < 0) - bestdist = -bestdist; - if (bestdist > 4095) - bestdist = 4095; - - for (i = 1; i < raid[device].disks; i++) { - dist = raid[device].disk[i].last_pos - bh->b_rsector; - if (dist < 0) - dist = -dist; - if (dist > 4095) - dist = 4095; - - if (bestdist == dist) { /* it's a tie; try to do some read balancing */ - if ((previous > bestsofar) && (previous <= i)) - bestsofar = i; - previous = (previous + 1) % raid[device].disks; - } else if (bestdist > dist) { - bestdist = dist; - bestsofar = i; - } - - } - - bh->b_rdev = raid[device].disk[bestsofar].device; - raid[device].disk[bestsofar].last_pos = - bh->b_rsector + (bh->b_size >> 9); - - /* - * Let the main block layer submit the IO and resolve recursion: - */ - - return 1; -} - - -static int pdcraid1_make_request(request_queue_t * q, int rw, - struct buffer_head *bh) -{ - /* Read and Write are totally different cases; split them totally here */ - if (rw == READA) - rw = READ; - - if (rw == READ) - return pdcraid1_read_request(q, rw, bh); - else - return pdcraid1_write_request(q, rw, bh); -} - -#include "pdcraid.h" - -static unsigned long calc_pdcblock_offset(struct block_device *bdev) -{ - unsigned long lba = 0; - struct ata_device *ideinfo = get_info_ptr(to_kdev_t(bdev->bd_dev)); - - if (ideinfo == NULL) - return 0; - - /* first sector of the last cluster */ - if (ideinfo->head == 0) - return 0; - if (ideinfo->sect == 0) - return 0; - lba = (ideinfo->capacity / (ideinfo->head * ideinfo->sect)); - lba = lba * (ideinfo->head * ideinfo->sect); - lba = lba - ideinfo->sect; - - return lba; -} - - -static int read_disk_sb(struct block_device *bdev, - struct promise_raid_conf *p) -{ - unsigned long sb_offset; - char *buffer; - int i; - - /* - * Calculate the position of the superblock, - * it's at first sector of the last cylinder - */ - sb_offset = calc_pdcblock_offset(bdev); - - if (sb_offset == 0) - return -1; - - for (i = 0, buffer = (char *) p; i < 4; i++, buffer += 512) { - Sector sect; - char *q = read_dev_sector(bdev, sb_offset + i, §); - if (!p) { - printk(KERN_ERR - "pdcraid: Error reading superblock.\n"); - return -1; - } - memcpy(buffer, q, 512); - put_dev_sector(§); - } - return 0; -} - -static unsigned int calc_sb_csum(unsigned int *ptr) -{ - unsigned int sum; - int count; - - sum = 0; - for (count = 0; count < 511; count++) - sum += *ptr++; - - return sum; -} - -static int cookie = 0; - -static struct promise_raid_conf __initdata prom; -static void __init probedisk(int devindex, int device, int raidlevel) -{ - int i; - int major, minor; - struct block_device *bdev; - - if (devlist[devindex].device != -1) /* already assigned to another array */ - return; - - major = devlist[devindex].major; - minor = devlist[devindex].minor; - - bdev = bdget(mk_kdev(major, minor)); - if (!bdev) - return; - - if (blkdev_get(bdev, FMODE_READ | FMODE_WRITE, 0, BDEV_RAW) != 0) - return; - - if (read_disk_sb(bdev, &prom)) - goto out; - - /* the checksums must match */ - if (prom.checksum != calc_sb_csum((unsigned int *) &prom)) - goto out; - if (prom.raid.type != raidlevel) /* different raidlevel */ - goto out; - - if ((cookie != 0) && (cookie != prom.raid.magic_1)) /* different array */ - goto out; - - cookie = prom.raid.magic_1; - - /* This looks evil. But basically, we have to search for our adapternumber - in the arraydefinition, both of which are in the superblock */ - for (i = 0; (i < prom.raid.total_disks) && (i < 8); i++) { - if ((prom.raid.disk[i].channel == prom.raid.channel) && - (prom.raid.disk[i].device == prom.raid.device)) { - - raid[device].disk[i].bdev = bdev; - raid[device].disk[i].device = - mk_kdev(major, minor); - raid[device].disk[i].sectors = prom.raid.disk_secs; - raid[device].stride = (1 << prom.raid.raid0_shift); - raid[device].disks = prom.raid.total_disks; - raid[device].sectors = prom.raid.total_secs; - raid[device].geom.heads = prom.raid.heads + 1; - raid[device].geom.sectors = prom.raid.sectors; - raid[device].geom.cylinders = - prom.raid.cylinders + 1; - devlist[devindex].device = device; - return; - } - } - out: - blkdev_put(bdev, BDEV_RAW); -} - -static void __init fill_cutoff(int device) -{ - int i, j; - unsigned long smallest; - unsigned long bar; - int count; - - bar = 0; - for (i = 0; i < 8; i++) { - smallest = ~0; - for (j = 0; j < 8; j++) - if ((raid[device].disk[j].sectors < smallest) - && (raid[device].disk[j].sectors > bar)) - smallest = raid[device].disk[j].sectors; - count = 0; - for (j = 0; j < 8; j++) - if (raid[device].disk[j].sectors >= smallest) - count++; - - smallest = smallest * count; - bar = smallest; - raid[device].cutoff[i] = smallest; - raid[device].cutoff_disks[i] = count; - } -} - -static __init int pdcraid_init_one(int device, int raidlevel) -{ - int i, count; - struct pdcraid *p = raid + device; - - for (i = 0; i < 14; i++) - probedisk(i, device, raidlevel); - - if (raidlevel == 0) - fill_cutoff(device); - - count = 0; - - for (i = 0; i < 8; i++) { - if (p->disk[i].device != 0) { - printk(KERN_INFO "Drive %i is %li Mb (%i / %i) \n", - i, p->disk[i].sectors / 2048, - major(p->disk[i].device), - minor(p->disk[i].device)); - count++; - } - } - if (count) { - ataraid_register_disk(device, p->sectors); - printk(KERN_INFO "Raid%i array consists of %i drives. \n", - raidlevel, count); - return 0; - } else { - return -ENODEV; - } -} - -static __init int pdcraid_init(void) -{ - int retval, device, count = 0; - - do { - cookie = 0; - device = ataraid_get_device(&pdcraid0_ops); - if (device < 0) - break; - retval = pdcraid_init_one(device, 0); - if (retval) { - ataraid_release_device(device); - break; - } else { - count++; - } - } while (1); - - do { - - cookie = 0; - device = ataraid_get_device(&pdcraid1_ops); - if (device < 0) - break; - retval = pdcraid_init_one(device, 1); - if (retval) { - ataraid_release_device(device); - break; - } else { - count++; - } - } while (1); - - if (count) { - printk(KERN_INFO - "Promise Fasttrak(tm) Softwareraid driver for linux version 0.03beta\n"); - return 0; - } - printk(KERN_DEBUG - "Promise Fasttrak(tm) Softwareraid driver 0.03beta: No raid array found\n"); - return -ENODEV; -} - -static void __exit pdcraid_exit(void) -{ - int i, device; - for (device = 0; device < 16; device++) { - for (i = 0; i < 8; i++) { - struct block_device *bdev = - raid[device].disk[i].bdev; - raid[device].disk[i].bdev = NULL; - if (bdev) - blkdev_put(bdev, BDEV_RAW); - } - if (raid[device].sectors) { - ataraid_unregister_disk(device); - ataraid_release_device(device); - } - } -} - -static int pdcraid_open(struct inode *inode, struct file *filp) -{ - MOD_INC_USE_COUNT; - return 0; -} -static int pdcraid_release(struct inode *inode, struct file *filp) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -module_init(pdcraid_init); -module_exit(pdcraid_exit); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/pdcraid.h b/drivers/ide/pdcraid.h --- a/drivers/ide/pdcraid.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,47 +0,0 @@ -struct promise_raid_conf { - char promise_id[24]; - - u32 dummy_0; - u32 magic_0; - u32 dummy_1; - u32 magic_1; - u16 dummy_2; - u8 filler1[470]; - struct { - u32 flags; /* 0x200 */ - u8 dummy_0; - u8 disk_number; - u8 channel; - u8 device; - u32 magic_0; - u32 dummy_1; - u32 dummy_2; /* 0x210 */ - u32 disk_secs; - u32 dummy_3; - u16 dummy_4; - u8 status; - u8 type; - u8 total_disks; /* 0x220 */ - u8 raid0_shift; - u8 raid0_disks; - u8 array_number; - u32 total_secs; - u16 cylinders; - u8 heads; - u8 sectors; - u32 magic_1; - u32 dummy_5; /* 0x230 */ - struct { - u16 dummy_0; - u8 channel; - u8 device; - u32 magic_0; - u32 disk_number; - } disk[8]; - } raid; - u32 filler2[346]; - u32 checksum; -}; - -#define PR_MAGIC "Promise Technology, Inc." - diff -Nru a/drivers/ide/piix.c b/drivers/ide/piix.c --- a/drivers/ide/piix.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,527 +0,0 @@ -/* - * piix.c, v1.5 2002/05/03 - * - * Copyright (c) 2000-2002 Vojtech Pavlik - * - * Based on the work of: - * Andrzej Krzysztofowicz - * Andre Hedrick - * - * Thanks to Daniela Egbert for advice on PIIX bugs. - * Thanks to Ulf Axelsson for noticing that ICH4 only documents UDMA100. - */ - -/* - * Intel PIIX/ICH and Efar Victory66 IDE driver for Linux. - * - * UDMA66 and higher modes are autoenabled only in case the BIOS has detected a - * 80 wire cable. To ignore the BIOS data and assume the cable is present, use - * 'ide0=ata66' or 'ide1=ata66' on the kernel command line. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to , or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "pcihost.h" - -#define PIIX_IDETIM0 0x40 -#define PIIX_IDETIM1 0x42 -#define PIIX_SIDETIM 0x44 -#define PIIX_IDESTAT 0x47 -#define PIIX_UDMACTL 0x48 -#define PIIX_UDMATIM 0x4a -#define PIIX_IDECFG 0x54 - -#define PIIX_UDMA 0x07 -#define PIIX_UDMA_NONE 0x00 -#define PIIX_UDMA_33 0x01 -#define PIIX_UDMA_66 0x02 -#define PIIX_UDMA_100 0x03 -#define PIIX_UDMA_133 0x04 -#define PIIX_NO_SITRE 0x08 /* Chip doesn't have separate slave timing */ -#define PIIX_PINGPONG 0x10 /* Enable ping-pong buffers */ -#define PIIX_VICTORY 0x20 /* Efar Victory66 has a different UDMA setup */ -#define PIIX_CHECK_REV 0x40 /* May be a buggy revision of PIIX */ -#define PIIX_NODMA 0x80 /* Don't do DMA with this chip */ - -/* - * Intel IDE chips - */ - -static struct piix_ide_chip { - unsigned short id; - unsigned char flags; -} piix_ide_chips[] = { - { PCI_DEVICE_ID_INTEL_82801DB_9, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801DB ICH4 */ - { PCI_DEVICE_ID_INTEL_82801CA_11, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801CA ICH3/ICH3-S */ - { PCI_DEVICE_ID_INTEL_82801CA_10, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801CAM ICH3-M */ - { PCI_DEVICE_ID_INTEL_82801E_9, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801E C-ICH */ - { PCI_DEVICE_ID_INTEL_82801BA_9, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801BA ICH2 */ - { PCI_DEVICE_ID_INTEL_82801BA_8, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801BAM ICH2-M */ - { PCI_DEVICE_ID_INTEL_82801AB_1, PIIX_UDMA_33 | PIIX_PINGPONG}, /* Intel 82801AB ICH0 */ - { PCI_DEVICE_ID_INTEL_82801AA_1, PIIX_UDMA_66 | PIIX_PINGPONG }, /* Intel 82801AA ICH */ - { PCI_DEVICE_ID_INTEL_82372FB_1, PIIX_UDMA_66 }, /* Intel 82372FB PIIX5 */ - { PCI_DEVICE_ID_INTEL_82443MX_1, PIIX_UDMA_33 }, /* Intel 82443MX MPIIX4 */ - { PCI_DEVICE_ID_INTEL_82371AB, PIIX_UDMA_33 }, /* Intel 82371AB/EB PIIX4/PIIX4E */ - { PCI_DEVICE_ID_INTEL_82371SB_1, PIIX_UDMA_NONE }, /* Intel 82371SB PIIX3 */ - { PCI_DEVICE_ID_INTEL_82371FB_1, PIIX_UDMA_NONE | PIIX_NO_SITRE | PIIX_CHECK_REV }, /* Intel 82371FB PIIX */ - { PCI_DEVICE_ID_EFAR_SLC90E66_1, PIIX_UDMA_66 | PIIX_VICTORY }, /* Efar Victory66 */ - { 0 } -}; - -static struct piix_ide_chip *piix_config; -static unsigned char piix_enabled; - -static char *piix_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; - -/* - * piix_set_speed() writes timing values to the chipset registers - */ - -static void piix_set_speed(struct pci_dev *dev, unsigned char dn, struct ata_timing *timing, int umul) -{ - unsigned short t; - unsigned char u; - unsigned int c; - - pci_read_config_word(dev, PIIX_IDETIM0 + (dn & 2), &t); - - switch (dn & 1) { - - case 1: - if (timing->cycle > 9) { - t &= ~0x30; - break; - } - - if (~piix_config->flags & PIIX_NO_SITRE) { - pci_read_config_byte(dev, PIIX_SIDETIM, &u); - u &= ~(0xf << ((dn & 2) << 1)); - t |= 0x30; - u |= (4 - FIT(timing->recover, 1, 4)) << ((dn & 2) << 1); - u |= (5 - FIT(timing->active, 2, 5)) << (((dn & 2) << 1) + 2); - pci_write_config_byte(dev, PIIX_SIDETIM, u); - break; - } - - case 0: - if ((~dn & 1) && timing->cycle > 9) { - t &= ~0x03; - break; - } - - t &= 0xccff; - t |= 0x03 << ((dn & 1) << 2); - t |= (4 - FIT(timing->recover, 1, 4)) << 8; - t |= (5 - FIT(timing->active, 2, 5)) << 12; - } - - pci_write_config_word(dev, PIIX_IDETIM0 + (dn & 2), t); - - if (!(piix_config->flags & PIIX_UDMA)) return; - - pci_read_config_byte(dev, PIIX_UDMACTL, &u); - u &= ~(1 << dn); - - if (timing->udma) { - - u |= 1 << dn; - - pci_read_config_word(dev, PIIX_UDMATIM, &t); - - if (piix_config->flags & PIIX_VICTORY) { - t &= ~(0x07 << (dn << 2)); - t |= (8 - FIT(timing->udma, 2, 8)) << (dn << 2); - } else { - t &= ~(0x03 << (dn << 2)); - t |= (4 - FIT(timing->udma, 2, 4)) << (dn << 2); - } - - pci_write_config_word(dev, PIIX_UDMATIM, t); - - if ((piix_config->flags & PIIX_UDMA) > PIIX_UDMA_33 - && ~piix_config->flags & PIIX_VICTORY) { - - pci_read_config_dword(dev, PIIX_IDECFG, &c); - - if ((piix_config->flags & PIIX_UDMA) > PIIX_UDMA_66) - c &= ~(1 << (dn + 12)); - c &= ~(1 << dn); - - switch (umul) { - case 2: c |= 1 << dn; break; - case 4: c |= 1 << (dn + 12); break; - } - - pci_write_config_dword(dev, PIIX_IDECFG, c); - } - } - - pci_write_config_byte(dev, PIIX_UDMACTL, u); -} - -/* - * piix_set_drive() computes timing values configures the drive and - * the chipset to a desired transfer mode. It also can be called - * by upper layers. - */ - -static int piix_set_drive(struct ata_device *drive, unsigned char speed) -{ - struct ata_device *peer = drive->channel->drives + (~drive->dn & 1); - struct ata_timing t, p; - int err, T, UT, umul = 1; - - if (speed != XFER_PIO_SLOW && speed != drive->current_speed) - if ((err = ide_config_drive_speed(drive, speed))) - return err; - - if (speed > XFER_UDMA_2 && (piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_66) - umul = 2; - if (speed > XFER_UDMA_4 && (piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_100) - umul = 4; - - T = 1000000000 / system_bus_speed; - UT = T / umul; - - ata_timing_compute(drive, speed, &t, T, UT); - - if ((piix_config->flags & PIIX_NO_SITRE) && peer->present) { - ata_timing_compute(peer, peer->current_speed, &p, T, UT); - if (t.cycle <= 9 && p.cycle <= 9) - ata_timing_merge(&p, &t, &t, IDE_TIMING_ALL); - } - - piix_set_speed(drive->channel->pci_dev, drive->dn, &t, umul); - - return 0; -} - -/* - * piix_tune_drive() is a callback from upper layers for - * PIO-only tuning. - */ - -static void piix_tune_drive(struct ata_device *drive, unsigned char pio) -{ - if (!((piix_enabled >> drive->channel->unit) & 1)) - return; - - if (pio == 255) { - piix_set_drive(drive, ata_timing_mode(drive, XFER_PIO | XFER_EPIO)); - return; - } - - piix_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int __init piix_modes_map(struct ata_channel *ch) -{ - short w80 = ch->udma_four; - int map = XFER_EPIO | - (piix_config->flags & PIIX_NODMA ? 0 : (XFER_SWDMA | XFER_MWDMA | - (piix_config->flags & PIIX_UDMA ? XFER_UDMA : 0) | - (w80 && (piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_66 ? XFER_UDMA_66 : 0) | - (w80 && (piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_100 ? XFER_UDMA_100 : 0) | - (w80 && (piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_133 ? XFER_UDMA_133 : 0))); - - return map; -} -#endif - -/* - * The initialization callback. Here we determine the IDE chip type - * and initialize its drive independent registers. - */ -static unsigned int __init piix_init_chipset(struct pci_dev *dev) -{ - struct pci_dev *orion = NULL; - unsigned int u; - unsigned short w; - unsigned char t; - int i; - -/* - * Find out which Intel IDE this is. - */ - - for (piix_config = piix_ide_chips; piix_config->id != 0; ++piix_config) - if (dev->device == piix_config->id) - break; - -/* - * Check for possibly broken DMA configs. - */ - - if (piix_config->flags & PIIX_CHECK_REV) { - pci_read_config_byte(dev, PCI_REVISION_ID, &t); - if (t < 2) { - printk(KERN_INFO "PIIX: Found buggy old PIIX rev %#x, disabling DMA\n", t); - piix_config->flags |= PIIX_NODMA; - } - } - - if ((orion = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, NULL))) { - pci_read_config_byte(orion, PCI_REVISION_ID, &t); - if (t < 4) { - printk(KERN_INFO "PIIX: Found buggy 82454GX Orion bridge rev %#x, disabling DMA\n", t); - piix_config->flags |= PIIX_NODMA; - } - } - -/* - * Enable ping-pong buffers where applicable. - */ - - if (piix_config->flags & PIIX_PINGPONG) { - pci_read_config_dword(dev, PIIX_IDECFG, &u); - u |= 0x400; - pci_write_config_dword(dev, PIIX_IDECFG, u); - } - -/* - * Detect enabled interfaces, enable slave separate timing if possible. - */ - - for (i = 0; i < 2; i++) { - pci_read_config_word(dev, PIIX_IDETIM0 + (i << 1), &w); - piix_enabled |= (w & 0x8000) ? (1 << i) : 0; - w &= 0x8c00; - if (~piix_config->flags & PIIX_NO_SITRE) w |= 0x4000; - w |= 0x44; - pci_write_config_word(dev, PIIX_IDETIM0 + (i << 1), w); - } - -/* - * Print the boot message. - */ - - printk(KERN_INFO "PIIX: %s %s controller on pci%s\n", - dev->name, piix_dma[piix_config->flags & PIIX_UDMA], dev->slot_name); - - return 0; -} - -static unsigned int __init piix_ata66_check(struct ata_channel *ch) -{ - unsigned char t; - unsigned int u; - - if ((piix_config->flags & PIIX_UDMA) < PIIX_UDMA_66) - return 0; - - if (piix_config->flags & PIIX_VICTORY) { - pci_read_config_byte(ch->pci_dev, PIIX_IDESTAT, &t); - return ch->unit ? (t & 1) : !!(t & 2); - } - - pci_read_config_dword(ch->pci_dev, PIIX_IDECFG, &u); - return ch->unit ? !!(u & 0xc0) : !!(u & 0x30); -} - -static void __init piix_init_channel(struct ata_channel *ch) -{ - int i; - - ch->udma_four = piix_ata66_check(ch); - - ch->tuneproc = &piix_tune_drive; - ch->speedproc = &piix_set_drive; - ch->io_32bit = 1; - ch->unmask = 1; - for (i = 0; i < 2; i++) { - ch->drives[i].autotune = 1; - ch->drives[i].dn = ch->unit * 2 + i; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (ch->dma_base) { - ch->highmem = 1; - ch->modes_map = piix_modes_map(ch); - ch->udma_setup = udma_generic_setup; - } -#endif -} - -/* - * We allow the BM-DMA driver only work on enabled interfaces, - * and only if DMA is safe with the chip and bridge. - */ -static void __init piix_init_dma(struct ata_channel *ch, unsigned long dmabase) -{ - if (((piix_enabled >> ch->unit) & 1) - && !(piix_config->flags & PIIX_NODMA)) - ata_init_dma(ch, dmabase); -} - - - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371FB_1, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371SB_1, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371AB, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82443MX_1, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82372FB_1, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801AA_1, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801AB_1, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801BA_9, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801BA_8, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801E_9, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_10, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_11, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_9, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_EFAR, - .device = PCI_DEVICE_ID_EFAR_SLC90E66_1, - .init_chipset = piix_init_chipset, - .init_channel = piix_init_channel, - .init_dma = piix_init_dma, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD - }, -}; - -int __init init_piix(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/ide/probe.c b/drivers/ide/probe.c --- a/drivers/ide/probe.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1215 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - * - * Mostly written by Mark Lord - * and Gadi Oxman - * and Andre Hedrick - * - * See linux/MAINTAINERS for address of current maintainer. - * - */ - -/* - * This is roughly the code related to device detection and - * device id handling. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -extern struct ata_device * get_info_ptr(kdev_t); - -/* - * This is called from the partition-table code in pt/msdos.c - * to invent a translated geometry. - * - * This is suppressed if the user specifies an explicit geometry. - * - * The ptheads parameter is either 0 or tells about the number of - * heads shown by the end of the first nonempty partition. - * If this is either 16, 32, 64, 128, 240 or 255 we'll believe it. - * - * The xparm parameter has the following meaning: - * 0 = convert to CHS with fewer than 1024 cyls - * using the same method as Ontrack DiskManager. - * 1 = same as "0", plus offset everything by 63 sectors. - * -1 = similar to "0", plus redirect sector 0 to sector 1. - * 2 = convert to a CHS geometry with "ptheads" heads. - * - * Returns 0 if the translation was not possible, if the device was not - * an IDE disk drive, or if a geometry was "forced" on the commandline. - * Returns 1 if the geometry translation was successful. - */ -int ide_xlate_1024(kdev_t i_rdev, int xparm, int ptheads, const char *msg) -{ - struct ata_device *drive; - const char *msg1 = ""; - int heads = 0; - int c, h, s; - int transl = 1; /* try translation */ - int ret = 0; - - drive = get_info_ptr(i_rdev); - if (!drive) - return 0; - - /* There used to be code here that assigned drive->id->CHS to - * drive->CHS and that to drive->bios_CHS. However, some disks have - * id->C/H/S = 4092/16/63 but are larger than 2.1 GB. In such cases - * that code was wrong. Moreover, there seems to be no reason to do - * any of these things. - * - * Please note that recent RedHat changes to the disk utils are bogous - * and will report spurious errors. - */ - - /* translate? */ - if (drive->forced_geom) - transl = 0; - - /* does ptheads look reasonable? */ - if (ptheads == 32 || ptheads == 64 || ptheads == 128 || - ptheads == 240 || ptheads == 255) - heads = ptheads; - - if (xparm == 2) { - if (!heads || - (drive->bios_head >= heads && drive->bios_sect == 63)) - transl = 0; - } - if (xparm == -1) { - if (drive->bios_head > 16) - transl = 0; /* we already have a translation */ - } - - if (transl) { - static const u8 dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0}; - const u8 *headp = dm_head_vals; - unsigned long total; - - /* - * If heads is nonzero: find a translation with this many heads - * and S=63. Otherwise: find out how OnTrack Disk Manager - * would translate the disk. - * - * The specs say: take geometry as obtained from Identify, - * compute total capacity C*H*S from that, and truncate to - * 1024*255*63. Now take S=63, H the first in the sequence 4, - * 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total. - * [Please tell aeb@cwi.nl in case this computes a geometry - * different from what OnTrack uses.] - */ - - total = ata_capacity(drive); - - s = 63; - - if (heads) { - h = heads; - c = total / (63 * heads); - } else { - while (63 * headp[0] * 1024 < total && headp[1] != 0) - headp++; - h = headp[0]; - c = total / (63 * headp[0]); - } - - drive->bios_cyl = c; - drive->bios_head = h; - drive->bios_sect = s; - ret = 1; - } - - drive->part[0].nr_sects = ata_capacity(drive); - - if (ret) - printk("%s%s [%d/%d/%d]", msg, msg1, - drive->bios_cyl, drive->bios_head, drive->bios_sect); - return ret; -} - -/* - * Drive ID data come as little endian, it needs to be converted on big endian - * machines. - */ -void ata_fix_driveid(struct hd_driveid *id) -{ -#ifndef __LITTLE_ENDIAN -# ifdef __BIG_ENDIAN - int i; - u16 *stringcast; - - id->config = __le16_to_cpu(id->config); - id->cyls = __le16_to_cpu(id->cyls); - id->reserved2 = __le16_to_cpu(id->reserved2); - id->heads = __le16_to_cpu(id->heads); - id->track_bytes = __le16_to_cpu(id->track_bytes); - id->sector_bytes = __le16_to_cpu(id->sector_bytes); - id->sectors = __le16_to_cpu(id->sectors); - id->vendor0 = __le16_to_cpu(id->vendor0); - id->vendor1 = __le16_to_cpu(id->vendor1); - id->vendor2 = __le16_to_cpu(id->vendor2); - stringcast = (u16 *)&id->serial_no[0]; - for (i = 0; i < (20/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - id->buf_type = __le16_to_cpu(id->buf_type); - id->buf_size = __le16_to_cpu(id->buf_size); - id->ecc_bytes = __le16_to_cpu(id->ecc_bytes); - stringcast = (u16 *)&id->fw_rev[0]; - for (i = 0; i < (8/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - stringcast = (u16 *)&id->model[0]; - for (i = 0; i < (40/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - id->dword_io = __le16_to_cpu(id->dword_io); - id->reserved50 = __le16_to_cpu(id->reserved50); - id->field_valid = __le16_to_cpu(id->field_valid); - id->cur_cyls = __le16_to_cpu(id->cur_cyls); - id->cur_heads = __le16_to_cpu(id->cur_heads); - id->cur_sectors = __le16_to_cpu(id->cur_sectors); - id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0); - id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1); - id->lba_capacity = __le32_to_cpu(id->lba_capacity); - id->dma_1word = __le16_to_cpu(id->dma_1word); - id->dma_mword = __le16_to_cpu(id->dma_mword); - id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes); - id->eide_dma_min = __le16_to_cpu(id->eide_dma_min); - id->eide_dma_time = __le16_to_cpu(id->eide_dma_time); - id->eide_pio = __le16_to_cpu(id->eide_pio); - id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy); - for (i = 0; i < 2; ++i) - id->words69_70[i] = __le16_to_cpu(id->words69_70[i]); - for (i = 0; i < 4; ++i) - id->words71_74[i] = __le16_to_cpu(id->words71_74[i]); - id->queue_depth = __le16_to_cpu(id->queue_depth); - for (i = 0; i < 4; ++i) - id->words76_79[i] = __le16_to_cpu(id->words76_79[i]); - id->major_rev_num = __le16_to_cpu(id->major_rev_num); - id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); - id->command_set_1 = __le16_to_cpu(id->command_set_1); - id->command_set_2 = __le16_to_cpu(id->command_set_2); - id->cfsse = __le16_to_cpu(id->cfsse); - id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1); - id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); - id->csf_default = __le16_to_cpu(id->csf_default); - id->dma_ultra = __le16_to_cpu(id->dma_ultra); - id->word89 = __le16_to_cpu(id->word89); - id->word90 = __le16_to_cpu(id->word90); - id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); - id->word92 = __le16_to_cpu(id->word92); - id->hw_config = __le16_to_cpu(id->hw_config); - id->acoustic = __le16_to_cpu(id->acoustic); - for (i = 0; i < 5; i++) - id->words95_99[i] = __le16_to_cpu(id->words95_99[i]); - id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); - for (i = 0; i < 22; i++) - id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); - id->last_lun = __le16_to_cpu(id->last_lun); - id->word127 = __le16_to_cpu(id->word127); - id->dlf = __le16_to_cpu(id->dlf); - id->csfo = __le16_to_cpu(id->csfo); - for (i = 0; i < 26; i++) - id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); - id->word156 = __le16_to_cpu(id->word156); - for (i = 0; i < 3; i++) - id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); - id->cfa_power = __le16_to_cpu(id->cfa_power); - for (i = 0; i < 14; i++) - id->words161_175[i] = __le16_to_cpu(id->words161_175[i]); - for (i = 0; i < 31; i++) - id->words176_205[i] = __le16_to_cpu(id->words176_205[i]); - for (i = 0; i < 48; i++) - id->words206_254[i] = __le16_to_cpu(id->words206_254[i]); - id->integrity_word = __le16_to_cpu(id->integrity_word); -# else -# error "Please fix " -# endif -#endif -} - -void ide_fixstring(char *s, const int bytecount, const int byteswap) -{ - char *p = s; - char *end = &s[bytecount & ~1]; /* bytecount must be even */ - - if (byteswap) { - /* convert from big-endian to host byte order */ - for (p = end ; p != s;) { - unsigned short *pp = (unsigned short *) (p -= 2); - *pp = ntohs(*pp); - } - } - - /* strip leading blanks */ - while (s != end && *s == ' ') - ++s; - - /* compress internal blanks and strip trailing blanks */ - while (s != end && *s) { - if (*s++ != ' ' || (s != end && *s && *s != ' ')) - *p++ = *(s-1); - } - - /* wipe out trailing garbage */ - while (p != end) - *p++ = '\0'; -} - -/* - * All hosts that use the 80c ribbon must use this! - */ -int eighty_ninty_three(struct ata_device *drive) -{ - return ((drive->channel->udma_four) && -#ifndef CONFIG_IDEDMA_IVB - (drive->id->hw_config & 0x4000) && -#endif - (drive->id->hw_config & 0x6000)) ? 1 : 0; -} - -/* FIXME: Channel lock should be held. - */ -int ide_config_drive_speed(struct ata_device *drive, u8 speed) -{ - struct ata_channel *ch = drive->channel; - int ret; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(__CRIS__) - u8 unit = (drive->select.b.unit & 0x01); - outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2); -#endif - - /* - * Select the drive, and issue the SETFEATURES command. - */ - disable_irq(ch->irq); /* disable_irq_nosync ?? */ - udelay(1); - ata_select(drive, 0); - ata_mask(drive); - udelay(1); - ata_irq_enable(drive, 0); - OUT_BYTE(speed, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - if (drive->quirk_list == 2) - ata_irq_enable(drive, 1); - udelay(1); - ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_CMD, NULL); - ata_mask(drive); - enable_irq(ch->irq); - - if (ret != ATA_OP_READY) { - ata_dump(drive, NULL, "set drive speed"); - return 1; - } - - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(__CRIS__) - if (speed > XFER_PIO_4) { - outb(inb(ch->dma_base + 2)|(1 << (5 + unit)), ch->dma_base + 2); - } else { - outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2); - } -#endif - - switch(speed) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; - } - - drive->current_speed = speed; - - return 0; -} - -static inline void do_identify(struct ata_device *drive, u8 cmd) -{ - int bswap = 1; - struct hd_driveid *id; - - id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */ - if (!id) { - printk(KERN_WARNING "(ide-probe::do_identify) Out of memory.\n"); - goto err_kmalloc; - } - - /* Read 512 bytes of id info. - * - * Please note that it is well known that some *very* old drives are - * able to provide only 256 of them, since this was the amount read by - * DOS. - * - * However let's try to get away with this... - */ - - ata_read(drive, id, SECTOR_WORDS); - local_irq_enable(); - ata_fix_driveid(id); - - if (id->word156 == 0x4d42) { - printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156); - } - - if (!drive->forced_lun) - drive->last_lun = id->last_lun & 0x7; -#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) - /* - * EATA SCSI controllers do a hardware ATA emulation: - * Ignore them if there is a driver for them available. - */ - if ((id->model[0] == 'P' && id->model[1] == 'M') - || (id->model[0] == 'S' && id->model[1] == 'K')) { - printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model); - goto err_misc; - } -#endif - - /* - * WIN_IDENTIFY returns little-endian info, - * WIN_PIDENTIFY *usually* returns little-endian info. - */ - if (cmd == WIN_PIDENTIFY) { - if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */ - || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ - || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ - bswap ^= 1; /* Vertos drives may still be weird */ - } - ide_fixstring(id->model, sizeof(id->model), bswap); - ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap); - ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap); - - if (strstr(id->model, "E X A B Y T E N E S T")) - goto err_misc; - - id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */ - printk("%s: %s, ", drive->name, id->model); - drive->present = 1; - - /* - * Check for an ATAPI device: - */ - if (cmd == WIN_PIDENTIFY) { - u8 type = (id->config >> 8) & 0x1f; - printk("ATAPI "); -#ifdef CONFIG_BLK_DEV_PDC4030 - if (drive->channel->unit == 1 && drive->channel->chipset == ide_pdc4030) { - printk(" -- not supported on 2nd Promise port\n"); - goto err_misc; - } -#endif - switch (type) { - case ATA_FLOPPY: - if (!strstr(id->model, "CD-ROM")) { - if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) - printk("cdrom or floppy?, assuming "); - if (drive->type != ATA_ROM) { - printk ("FLOPPY"); - break; - } - } - type = ATA_ROM; /* Early cdrom models used zero */ - case ATA_ROM: - drive->removable = 1; -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) { - printk ("FLOPPY"); - type = ATA_FLOPPY; - break; - } -#endif - printk ("CD/DVD-ROM"); - break; - case ATA_TAPE: - printk ("TAPE"); - break; - case ATA_MOD: - printk ("OPTICAL"); - drive->removable = 1; - break; - default: - printk("UNKNOWN (type %d)", type); - break; - } - printk (" drive\n"); - drive->type = type; - return; - } - - /* - * Not an ATAPI device: looks like a "regular" hard disk: - */ - if (id->config & (1<<7)) - drive->removable = 1; - - /* - * FIXME: This is just plain ugly or plain unnecessary. - * - * Prevent long system lockup probing later for non-existant slave - * drive if the hwif is actually a flash memory card of some variety: - */ - - if (drive_is_flashcard(drive)) { - struct ata_device *mate = &drive->channel->drives[1 ^ drive->select.b.unit]; - if (!mate->ata_flash) { - mate->present = 0; - mate->noprobe = 1; - } - } - drive->type = ATA_DISK; - printk("DISK drive\n"); - - /* Initialize our quirk list. */ - if (drive->channel->quirkproc) - drive->quirk_list = drive->channel->quirkproc(drive); - - /* Initialize queue depth settings */ - drive->queue_depth = 1; -#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEPTH - drive->queue_depth = CONFIG_BLK_DEV_IDE_TCQ_DEPTH; -#else - drive->queue_depth = drive->id->queue_depth + 1; -#endif - if (drive->queue_depth < 1 || drive->queue_depth > IDE_MAX_TAG) - drive->queue_depth = IDE_MAX_TAG; - - return; - -err_misc: - kfree(id); -err_kmalloc: - drive->present = 0; - - return; -} - -/* - * Sends an ATA(PI) IDENTIFY request to a drive and wait for a response. It - * also monitor irqs while this is happening, in hope of automatically - * determining which one is being used by the interface. - * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) - */ -static int identify(struct ata_device *drive, u8 cmd) -{ - struct ata_channel *ch = drive->channel; - int rc = 1; - int autoprobe = 0; - unsigned long cookie = 0; - ide_ioreg_t hd_status; - unsigned long timeout; - - - /* FIXME: perhaps we should be just using allways the status register, - * since it should simplify the code significantly. - */ - if (ch->io_ports[IDE_CONTROL_OFFSET]) { - u8 s; - u8 a; - - if (!drive->channel->irq) { - autoprobe = 1; - cookie = probe_irq_on(); - ata_irq_enable(drive, 1); /* enable device irq */ - } - - /* take a deep breath */ - mdelay(50); - a = IN_BYTE(ch->io_ports[IDE_ALTSTATUS_OFFSET]); - s = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); - if ((a ^ s) & ~INDEX_STAT) { - printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a); - hd_status = ch->io_ports[IDE_STATUS_OFFSET]; /* ancient Seagate drives, broken interfaces */ - } else { - hd_status = ch->io_ports[IDE_ALTSTATUS_OFFSET]; /* use non-intrusive polling */ - } - } else { - mdelay(50); - hd_status = ch->io_ports[IDE_STATUS_OFFSET]; - } - - /* set features register for atapi identify command to be sure of reply */ - if ((cmd == WIN_PIDENTIFY)) - OUT_BYTE(0,IDE_FEATURE_REG); /* disable dma & overlap */ - -#if CONFIG_BLK_DEV_PDC4030 - if (drive->channel->chipset == ide_pdc4030) { - /* DC4030 hosted drives need their own identify... */ - extern int pdc4030_identify(struct ata_device *); - - if (pdc4030_identify(drive)) - goto out; - } else -#endif - OUT_BYTE(cmd, IDE_COMMAND_REG); /* ask drive for ID */ - timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; - timeout += jiffies; - do { - if (time_after(jiffies, timeout)) - goto out; /* drive timed-out */ - mdelay(50); /* give drive a breather */ - } while (IN_BYTE(hd_status) & BUSY_STAT); - - mdelay(50); /* wait for IRQ and DRQ_STAT */ - - if (ata_status(drive, DRQ_STAT, BAD_R_STAT)) { - unsigned long flags; - - local_irq_save(flags); /* some systems need this */ - do_identify(drive, cmd); /* drive returned ID */ - rc = 0; /* drive responded with ID */ - ata_status(drive, 0, 0); /* clear drive IRQ */ - local_irq_restore(flags); /* local CPU only */ - } else - rc = 2; /* drive refused ID */ - -out: - if (autoprobe) { - int irq; - - ata_irq_enable(drive, 0); /* mask device irq */ - ata_status(drive, 0, 0); /* clear drive IRQ */ - udelay(5); - irq = probe_irq_off(cookie); - if (!drive->channel->irq) { - if (irq > 0) - drive->channel->irq = irq; - else /* Mmmm.. multiple IRQs.. don't know which was ours */ - printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie); - } - } - - return rc; -} - - -/* - * This has the difficult job of finding a drive if it exists, without getting - * hung up if it doesn't exist, without trampling on ethernet cards, and - * without leaving any IRQs dangling to haunt us later. - * - * If a drive is "known" to exist (from CMOS or kernel parameters), but does - * not respond right away, the probe will "hang in there" for the maximum wait - * time (about 30 seconds), otherwise it will exit much more quickly. - * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) - * 3 bad status from device (possible for ATAPI drives) - * 4 probe was not attempted because failure was obvious - */ -static int do_probe(struct ata_device *drive, u8 cmd) -{ - int rc; - struct ata_channel *ch = drive->channel; - u8 select; - - if (drive->present) { /* avoid waiting for inappropriate probes */ - if ((drive->type != ATA_DISK) && (cmd == WIN_IDENTIFY)) - return 4; - } -#ifdef DEBUG - printk("probing for %s: present=%d, type=%02x, probetype=%s\n", - drive->name, drive->present, drive->type, - (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); -#endif - mdelay(50); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */ - ata_select(drive, 50000); - select = IN_BYTE(IDE_SELECT_REG); - if (select != drive->select.all && !drive->present) { - if (drive->select.b.unit != 0) { - ata_select(&ch->drives[0], 50000); /* exit with drive0 selected */ - } - return 3; /* no i/f present: mmm.. this should be a 4 -ml */ - } - - if (ata_status(drive, READY_STAT, BUSY_STAT) || drive->present || cmd == WIN_PIDENTIFY) { - if ((rc = identify(drive,cmd))) /* send cmd and wait */ - rc = identify(drive,cmd); /* failed: try again */ - if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) { - unsigned long timeout; - printk("%s: no response (status = 0x%02x), resetting drive\n", - drive->name, drive->status); - mdelay(50); - OUT_BYTE(drive->select.all, IDE_SELECT_REG); - mdelay(50); - OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); - timeout = jiffies; - while (!ata_status(drive, 0, BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE)) - mdelay(50); - rc = identify(drive, cmd); - } - if (rc == 1) - printk("%s: no response (status = 0x%02x)\n", - drive->name, drive->status); - ata_status(drive, 0, 0); /* ensure drive irq is clear */ - } else - rc = 3; /* not present or maybe ATAPI */ - - if (drive->select.b.unit != 0) { - ata_select(&ch->drives[0], 50000); /* exit with drive0 selected */ - ata_status(drive, 0, 0); /* ensure drive irq is clear */ - } - - return rc; -} - -/* - * Probe for drivers on a channel. - * - * 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 channel_probe(struct ata_channel *ch) -{ - unsigned int i; - unsigned long flags; - int error; - - if (ch->noprobe) - return; - - ch->straight8 = 0; - - local_save_flags(flags); - local_irq_enable(); /* needed for jiffies and irq probing */ - - /* - * Check for the presence of a channel by probing for drives on it. - */ - for (i = 0; i < MAX_DRIVES; ++i) { - struct ata_device *drive = &ch->drives[i]; - - if (drive->noprobe) /* don't look for this one */ - continue; - - if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ - do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ - } - - /* Special handling of EXABYTE controller cards. */ - if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T")) { - unsigned long timeout; - - printk("%s: enabling %s -- ", drive->channel->name, drive->id->model); - ata_select(drive, 50000); - OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (time_after(jiffies, timeout)) { - printk("failed (timeout)\n"); - return; - } - mdelay(50); - } while (!ata_status(drive, 0, BUSY_STAT)); - mdelay(50); - if (!ata_status(drive, 0, BAD_STAT)) - printk("failed (status = 0x%02x)\n", drive->status); - else - printk("success\n"); - - if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ - do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ - } - } - - if (!drive->present) - continue; /* drive not found */ - - if (!drive->id) { /* identification failed? */ - if (drive->type == ATA_DISK) - printk ("%s: pre-ATA drive, CHS=%d/%d/%d\n", - drive->name, drive->cyl, drive->head, drive->sect); - else if (drive->type == ATA_ROM) - printk("%s: ATAPI cdrom (?)\n", drive->name); - else - drive->present = 0; /* nuke it */ - } - - /* drive found, there is a channel it is attached too. */ - if (drive->present) - ch->present = 1; - } - - if (!ch->present) - goto not_found; - - error = 0; - - if (((unsigned long)ch->io_ports[IDE_DATA_OFFSET] | 7) == - ((unsigned long)ch->io_ports[IDE_STATUS_OFFSET])) { - error += !request_region(ch->io_ports[IDE_DATA_OFFSET], 8, ch->name); - ch->straight8 = 1; - } else { - for (i = 0; i < 8; i++) - error += !request_region(ch->io_ports[i], 1, ch->name); - } - if (ch->io_ports[IDE_CONTROL_OFFSET]) - error += !request_region(ch->io_ports[IDE_CONTROL_OFFSET], 1, ch->name); -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (ch->io_ports[IDE_IRQ_OFFSET]) - error += !request_region(ch->io_ports[IDE_IRQ_OFFSET], 1, ch->name); -#endif - - /* Some neccessary register area was already used. Skip this device. - */ - - if ( -#if CONFIG_BLK_DEV_PDC4030 - (ch->chipset != ide_pdc4030 || ch->unit == 0) && -#endif - error) { - - /* FIXME: We should be dealing properly with partial IO region - * allocations here. - */ - - ch->present = 0; - printk("%s: error: ports already in use!\n", ch->name); - } - - if (!ch->present) - goto not_found; - - /* Register this hardware interface within the global device tree. - * - * FIXME: This should be handled as a pci subdevice in a generic way. - */ - sprintf(ch->dev.bus_id, "ata@%02x", ch->unit); - strcpy(ch->dev.name, "ATA/ATAPI Host-Channel"); - ch->dev.driver_data = ch; -#ifdef CONFIG_PCI - if (ch->pci_dev) - ch->dev.parent = &ch->pci_dev->dev; - else -#endif - ch->dev.parent = NULL; /* Would like to do = &device_legacy */ - - device_register(&ch->dev); - - if (ch->reset) - ata_reset(ch); - - local_irq_restore(flags); - - /* - * Now setup the PIO transfer modes of the drives on this channel. - */ - for (i = 0; i < MAX_DRIVES; ++i) { - struct ata_device *drive = &ch->drives[i]; - - if (drive->present && (drive->autotune == 1)) { - if (drive->channel->tuneproc) - drive->channel->tuneproc(drive, 255); /* auto-tune PIO mode */ - } - } - - return; - -not_found: - local_irq_restore(flags); -} - -/* - * This routine sets up the irq for an ide interface, and creates a new hwgroup - * for the irq/channel if none was previously assigned. - * - * 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 SA_INTERRUPT in sa_flags means ata_irq_request() 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(struct ata_channel *ch) -{ - unsigned long flags; - int i; - spinlock_t *lock; - spinlock_t *new_lock; - unsigned long *active; - unsigned long *new_active; - struct ata_channel *match = NULL; - - /* Spare allocation before sleep. */ - new_lock = kmalloc(sizeof(*lock), GFP_KERNEL); - new_active = kmalloc(sizeof(*active), GFP_KERNEL); - *new_active = 0L; - - spin_lock_irqsave(&ide_lock, flags); - ch->lock = NULL; - -#if MAX_HWIFS > 1 - /* - * Group up with any other channels that share our irq(s). - */ - for (i = 0; i < MAX_HWIFS; ++i) { - struct ata_channel *h = &ide_hwifs[i]; - - /* scan only initialized channels */ - if (!h->lock) - continue; - - if (ch->irq != h->irq) - continue; - - ch->sharing_irq = h->sharing_irq = 1; - - if (ch->chipset != ide_pci || h->chipset != ide_pci || - ch->serialized || h->serialized) { - if (match && match->lock && match->lock != h->lock) - printk("%s: potential irq problem with %s and %s\n", ch->name, h->name, match->name); - /* don't undo a prior perfect match */ - if (!match || match->irq != ch->irq) - match = h; - } - } -#endif - /* - * If we are still without a lock group, then form a new one - */ - if (!match) { - lock = new_lock; - active = new_active; - if (!lock) { - spin_unlock_irqrestore(&ide_lock, flags); - - return 1; - } - spin_lock_init(lock); - } else { - lock = match->lock; - active = match->active; - if(new_lock) - kfree(new_lock); - } - - /* - * Allocate the irq, if not already obtained for another channel - */ - if (!match || match->irq != ch->irq) { - struct ata_device tmp; -#ifdef CONFIG_IDEPCI_SHARE_IRQ - int sa = IDE_CHIPSET_IS_PCI(ch->chipset) ? SA_SHIRQ : SA_INTERRUPT; -#else - int sa = IDE_CHIPSET_IS_PCI(ch->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT; -#endif - - /* Enable interrupts triggered by the drive. We use a shallow - * device structure, just to use the generic function very - * early. - */ - tmp.channel = ch; - ata_irq_enable(&tmp, 1); - - if (request_irq(ch->irq, &ata_irq_request, sa, ch->name, ch)) { - if (!match) { - kfree(lock); - kfree(active); - } - - spin_unlock_irqrestore(&ide_lock, flags); - - return 1; - } - } - - /* - * Everything is okay. Tag us as member of this lock group. - */ - ch->lock = lock; - ch->active = active; - - init_timer(&ch->timer); - ch->timer.function = &ide_timer_expiry; - ch->timer.data = (unsigned long) ch; - - for (i = 0; i < MAX_DRIVES; ++i) { - struct ata_device *drive = &ch->drives[i]; - request_queue_t *q; - int max_sectors = 255; - - if (!drive->present) - continue; - - if (!ch->drive) - ch->drive = drive; - - /* - * Init the per device request queue. - */ - - q = &drive->queue; - q->queuedata = drive; - blk_init_queue(q, do_ide_request, drive->channel->lock); - blk_queue_segment_boundary(q, ch->seg_boundary_mask); - blk_queue_max_segment_size(q, ch->max_segment_size); - - /* ATA can do up to 128K per request, pdc4030 needs smaller - * limit. */ -#ifdef CONFIG_BLK_DEV_PDC4030 - if (drive->channel->chipset == ide_pdc4030) - max_sectors = 127; -#endif - blk_queue_max_sectors(q, max_sectors); - - /* ATA DMA can do PRD_ENTRIES number of segments. */ - blk_queue_max_hw_segments(q, PRD_ENTRIES); - - /* FIXME: This is a driver limit and could be eliminated. */ - blk_queue_max_phys_segments(q, PRD_ENTRIES); - } - spin_unlock_irqrestore(&ide_lock, flags); - -#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) - printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", ch->name, - ch->io_ports[IDE_DATA_OFFSET], - ch->io_ports[IDE_DATA_OFFSET]+7, - ch->io_ports[IDE_CONTROL_OFFSET], ch->irq); -#elif defined(__sparc__) - printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", ch->name, - ch->io_ports[IDE_DATA_OFFSET], - ch->io_ports[IDE_DATA_OFFSET]+7, - ch->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(ch->irq)); -#else - printk("%s at %p on irq 0x%08x", ch->name, - ch->io_ports[IDE_DATA_OFFSET], ch->irq); -#endif - if (match) - printk(" (%sed with %s)", - ch->sharing_irq ? "shar" : "serializ", match->name); - printk("\n"); - - return 0; -} - -/* - * Returns the queue which corresponds to a given device. - * - * FIXME: this should take struct block_device * as argument in future. - */ -static request_queue_t *ata_get_queue(kdev_t dev) -{ - struct ata_channel *ch = (struct ata_channel *)blk_dev[major(dev)].data; - - /* FIXME: ALLERT: This discriminates between master and slave! */ - return &ch->drives[DEVICE_NR(dev) & 1].queue; -} - -/* Number of minor numbers we consume par channel. */ -#define ATA_MINORS (MAX_DRIVES * (1 << PARTN_BITS)) - -static void channel_init(struct ata_channel *ch) -{ - struct gendisk *gd; - struct hd_struct *part; - devfs_handle_t *de_arr; - char *flags; - unsigned int unit; - extern devfs_handle_t ide_devfs_handle; - char *names; - - if (!ch->present) - return; - - /* we set it back to 1 if all is ok below */ - ch->present = 0; - - if (!ch->irq) { - if (!(ch->irq = ide_default_irq(ch->io_ports[IDE_DATA_OFFSET]))) { - printk("%s: DISABLED, NO IRQ\n", ch->name); - - return; - } - } -#ifdef CONFIG_BLK_DEV_HD - - /* The first "legacy" HD gets distinguished by the IRQ it is attached - * to and the IO port it takes. - */ - - if (ch->irq == 14 && ch->io_ports[IDE_DATA_OFFSET] != 0x1f0) { - printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", ch->name); - - return; - } -#endif - - if (register_blkdev(ch->major, ch->name, ide_fops)) { - printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", ch->name, ch->major); - - return; - } - - if (init_irq(ch)) { - int irq = ch->irq; - /* - * It failed to initialise. Find the default IRQ for - * this port and try that. - */ - if (!(ch->irq = ide_default_irq(ch->io_ports[IDE_DATA_OFFSET]))) { - printk(KERN_INFO "%s: disabled; unable to get IRQ %d.\n", ch->name, irq); - (void) unregister_blkdev (ch->major, ch->name); - - return; - } - if (init_irq(ch)) { - printk(KERN_INFO "%s: probed IRQ %d and default IRQ %d failed.\n", - ch->name, irq, ch->irq); - (void) unregister_blkdev(ch->major, ch->name); - - return; - } - printk(KERN_INFO "%s: probed IRQ %d failed, using default.\n", ch->name, ch->irq); - } - - /* Initialize partition and global device data. - */ - - gd = kmalloc (MAX_DRIVES * sizeof(struct gendisk), GFP_KERNEL); - if (!gd) - goto err_kmalloc_gd; - - memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk)); - - part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL); - if (!part) - goto err_kmalloc_gd_part; - memset(part, 0, ATA_MINORS * sizeof(struct hd_struct)); - - de_arr = kmalloc (sizeof(devfs_handle_t) * MAX_DRIVES, GFP_KERNEL); - if (!de_arr) - goto err_kmalloc_gd_de_arr; - memset(de_arr, 0, sizeof(devfs_handle_t) * MAX_DRIVES); - - flags = kmalloc (sizeof(char) * MAX_DRIVES, GFP_KERNEL); - if (!flags) - goto err_kmalloc_gd_flags; - memset(flags, 0, sizeof(char) * MAX_DRIVES); - - names = kmalloc (4 * MAX_DRIVES, GFP_KERNEL); - if (!names) - goto err_kmalloc_gd_names; - memset(names, 0, 4 * MAX_DRIVES); - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - gd[unit].part = part + (unit << PARTN_BITS); - gd[unit].de_arr = de_arr + unit; - gd[unit].flags = flags + unit; - ch->drives[unit].part = gd[unit].part; - gd[unit].major = ch->major; - gd[unit].first_minor = unit << PARTN_BITS; - sprintf(names + 4*unit, "hd%c", 'a'+ch->index*MAX_DRIVES+unit); - gd[unit].major_name = names + 4*unit; - gd[unit].minor_shift = PARTN_BITS; - gd[unit].nr_real = 1; - gd[unit].fops = ide_fops; - ch->gd[unit] = gd + unit; - add_gendisk(gd + unit); - } - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - char name[80]; - - ch->drives[unit].dn = ((ch->unit ? 2 : 0) + unit); - sprintf(name, "host%d/bus%d/target%d/lun%d", - ch->index, ch->unit, unit, ch->drives[unit].lun); - if (ch->drives[unit].present) - ch->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL); - } - - blk_dev[ch->major].data = ch; - blk_dev[ch->major].queue = ata_get_queue; - - /* All went well, flag this channel entry as valid again. */ - ch->present = 1; - - return; - -err_kmalloc_gd_names: - kfree(names); -err_kmalloc_gd_flags: - kfree(de_arr); -err_kmalloc_gd_de_arr: - kfree(part); -err_kmalloc_gd_part: - kfree(gd); -err_kmalloc_gd: - printk(KERN_CRIT "(%s) Out of memory\n", __FUNCTION__); -} - -/* - * FIXME: consider moving this to main.c, since this is the only place where - * it's used. - * - * Probe only for drives on channes which are not already present. - */ -int ideprobe_init(void) -{ - unsigned int i; - int probe[MAX_HWIFS]; - - for (i = 0; i < MAX_HWIFS; ++i) - probe[i] = !ide_hwifs[i].present; - - /* - * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports - */ - for (i = 0; i < MAX_HWIFS; ++i) { - if (!probe[i]) - continue; - channel_probe(&ide_hwifs[i]); - } - for (i = 0; i < MAX_HWIFS; ++i) { - if (!probe[i]) - continue; - channel_init(&ide_hwifs[i]); - } - return 0; -} - -EXPORT_SYMBOL(ata_fix_driveid); -EXPORT_SYMBOL(ide_fixstring); -EXPORT_SYMBOL(eighty_ninty_three); -EXPORT_SYMBOL(ide_config_drive_speed); diff -Nru a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c --- a/drivers/ide/q40ide.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,88 +0,0 @@ -/* - * linux/drivers/ide/q40ide.c -- Q40 I/O port IDE Driver - * - * (c) Richard Zidlicky - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * - */ - -#include -#include -#include -#include -#include - -#include - - /* - * Bases of the IDE interfaces - */ - -#define Q40IDE_NUM_HWIFS 2 - -#define PCIDE_BASE1 0x1f0 -#define PCIDE_BASE2 0x170 -#define PCIDE_BASE3 0x1e8 -#define PCIDE_BASE4 0x168 -#define PCIDE_BASE5 0x1e0 -#define PCIDE_BASE6 0x160 - -static const q40ide_ioreg_t pcide_bases[Q40IDE_NUM_HWIFS] = { - PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5, - PCIDE_BASE6 */ -}; - - - /* - * Offsets from one of the above bases - */ - - -/* HD_DATA was redefined in asm-m68k/ide.h */ -#undef HD_DATA -#define HD_DATA 0x1f0 - - -#define PCIDE_REG(x) ((q40ide_ioreg_t)(HD_##x-PCIDE_BASE1)) - -static const int pcide_offsets[IDE_NR_PORTS] = { - PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR), - PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS), - PCIDE_REG(CMD) -}; - -static int q40ide_default_irq(q40ide_ioreg_t base) -{ - switch (base) { - case 0x1f0: return 14; - case 0x170: return 15; - case 0x1e8: return 11; - default: - return 0; - } -} - -/* - * Probe for Q40 IDE interfaces - */ -void q40ide_init(void) -{ - int i; - - if (!MACH_IS_Q40) - return ; - - for (i = 0; i < Q40IDE_NUM_HWIFS; i++) { - hw_regs_t hw; - - ide_setup_ports(&hw, (ide_ioreg_t)pcide_bases[i], (int *)pcide_offsets, - (ide_ioreg_t)pcide_bases[i]+0x206, - 0, NULL, q40ide_default_irq(pcide_bases[i])); - ide_register_hw(&hw); - } -} - diff -Nru a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c --- a/drivers/ide/qd65xx.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,429 +0,0 @@ -/* - * Copyright (C) 1996-2001 Linus Torvalds & author (see below) - * - * Version 0.03 Cleaned auto-tune, added probe - * Version 0.04 Added second channel tuning - * Version 0.05 Enhanced tuning ; added qd6500 support - * Version 0.06 Added dos driver's list - * Version 0.07 Second channel bug fix - * - * QDI QD6500/QD6580 EIDE controller fast support - * - * Please set local bus speed using kernel parameter idebus - * for example, "idebus=33" stands for 33Mhz VLbus - * To activate controller support, use "ide0=qd65xx" - * To enable tuning, use "ide0=autotune" - * To enable second channel tuning (qd6580 only), use "ide1=autotune" - * - * Rewritten from the work of Colten Edwards by - * Samuel Thibault - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "qd65xx.h" - -/* - * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580) - * or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580) - * -- qd6500 is a single IDE interface - * -- qd6580 is a dual IDE interface - * - * More research on qd6580 being done by willmore@cig.mot.com (David) - * More Information given by Petr Soucek (petr@ryston.cz) - * http://www.ryston.cz/petr/vlb - */ - -/* - * base: Timer1 - * - * - * base+0x01: Config (R/O) - * - * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500) - * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30 - * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz - * bit 3: qd6500: 1 = disabled, 0 = enabled - * qd6580: 1 - * upper nibble: - * qd6500: 1100 - * qd6580: either 1010 or 0101 - * - * - * base+0x02: Timer2 (qd6580 only) - * - * - * base+0x03: Control (qd6580 only) - * - * bits 0-3 must always be set 1 - * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock - * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb - * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb - * channel 1 for hdc & hdd - * bit 1 : 1 = only disks on primary port - * 0 = disks & ATAPI devices on primary port - * bit 2-4 : always 0 - * bit 5 : status, but of what ? - * bit 6 : always set 1 by dos driver - * bit 7 : set 1 for non-ATAPI devices on primary port - * (maybe read-ahead and post-write buffer ?) - */ - -static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ - -/* - * This routine is invoked from ide.c to prepare for access to a given drive. - */ - -static void qd_select(struct ata_device *drive) -{ - u8 index = (((QD_TIMREG(drive)) & 0x80 ) >> 7) | - (QD_TIMREG(drive) & 0x02); - - if (timings[index] != QD_TIMING(drive)) - outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); -} - -/* - * computes the timing value where - * lower nibble represents active time, in count of VLB clocks - * upper nibble represents recovery time, in count of VLB clocks - */ - -static u8 qd6500_compute_timing(struct ata_channel *hwif, int active_time, int recovery_time) -{ - u8 active_cycle,recovery_cycle; - - if (system_bus_speed <= 33333) { - active_cycle = 9 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 9); - recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 0, 15); - } else { - active_cycle = 8 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 1, 8); - recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 3, 18); - } - - return((recovery_cycle<<4) | 0x08 | active_cycle); -} - -/* - * idem for qd6580 - */ - -static u8 qd6580_compute_timing(int active_time, int recovery_time) -{ - u8 active_cycle = 17 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 17); - u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 2, 15); - - return (recovery_cycle<<4) | active_cycle; -} - -/* - * tries to find timing from dos driver's table - */ - -static int qd_find_disk_type(struct ata_device *drive, - int *active_time, int *recovery_time) -{ - struct qd65xx_timing_s *p; - char model[40]; - - if (!*drive->id->model) return 0; - - strncpy(model,drive->id->model, 40); - for (p = qd65xx_timing ; p->offset != -1 ; p++) { - if (!strncmp(p->model, model+p->offset, 4)) { - printk(KERN_DEBUG "%s: listed !\n", drive->name); - *active_time = p->active; - *recovery_time = p->recovery; - return 1; - } - } - return 0; -} - -/* - * check whether timings don't conflict - */ - -static int qd_timing_ok(struct ata_device drives[]) -{ - return (IDE_IMPLY(drives[0].present && drives[1].present, - IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1), - QD_TIMING(drives) == QD_TIMING(drives+1)))); - /* if same timing register, must be same timing */ -} - -/* - * records the timing, and enables selectproc as needed - */ - -static void qd_set_timing(struct ata_device *drive, u8 timing) -{ - struct ata_channel *hwif = drive->channel; - - drive->drive_data &= 0xff00; - drive->drive_data |= timing; - if (qd_timing_ok(hwif->drives)) { - qd_select(drive); /* selects once */ - hwif->selectproc = NULL; - } else - hwif->selectproc = &qd_select; - - printk(KERN_DEBUG "%s: %#x\n", drive->name, timing); -} - -static void qd6500_tune_drive(struct ata_device *drive, u8 pio) -{ - int active_time = 175; - int recovery_time = 415; /* worst case values from the dos driver */ - - if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time) - && drive->id->tPIO && (drive->id->field_valid & 0x02) - && drive->id->eide_pio >= 240) { - - printk(KERN_INFO "%s: PIO mode%d\n", drive->name, drive->id->tPIO); - active_time = 110; - recovery_time = drive->id->eide_pio - 120; - } - - qd_set_timing(drive, qd6500_compute_timing(drive->channel, active_time, recovery_time)); -} - -static void qd6580_tune_drive(struct ata_device *drive, u8 pio) -{ - struct ata_timing *t; - int base = drive->channel->select_data; - int active_time = 175; - int recovery_time = 415; /* worst case values from the dos driver */ - - if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) { - - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); - else - pio = XFER_PIO_0 + min_t(u8, pio, 4); - - t = ata_timing_data(pio); - - switch (pio) { - case 0: break; - case 3: - if (t->cycle >= 110) { - active_time = 86; - recovery_time = t->cycle - 102; - } else - printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); - break; - case 4: - if (t->cycle >= 69) { - active_time = 70; - recovery_time = t->cycle - 61; - } else - printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); - break; - default: - if (t->cycle >= 180) { - active_time = 110; - recovery_time = t->cycle - 120; - } else { - active_time = t->active; - recovery_time = t->cycle - active_time; - } - } - printk(KERN_INFO "%s: PIO mode%d\n", drive->name, pio - XFER_PIO_0); - } - - if (!drive->channel->unit && drive->type != ATA_DISK) { - outb(0x5f, QD_CONTROL_PORT); - printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n", drive->name, drive->channel->name); - } - - qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time)); -} - -/* - * tests if the given port is a register - */ - -static int __init qd_testreg(int port) -{ - u8 savereg; - u8 readreg; - - savereg = inb_p(port); - outb_p(QD_TESTVAL, port); /* safe value */ - readreg = inb_p(port); - outb(savereg, port); - - if (savereg == QD_TESTVAL) { - printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); - printk(KERN_ERR "Please contact maintainers to tell about your hardware\n"); - printk(KERN_ERR "Assuming qd65xx is not present.\n"); - return 1; - } - - return (readreg != QD_TESTVAL); -} - -/* - * called to setup an ata channel : adjusts attributes & links for tuning - */ - -void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (struct ata_device *, u8 pio)) -{ - struct ata_channel *hwif = &ide_hwifs[unit]; - - hwif->chipset = ide_qd65xx; - hwif->unit = unit; - hwif->select_data = base; - hwif->config_data = config; - hwif->drives[0].drive_data = data0; - hwif->drives[1].drive_data = data1; - hwif->io_32bit = 1; - hwif->tuneproc = tuneproc; -} - -/* - * called to unsetup an ata channel : back to default values, unlinks tuning - */ -void __init qd_unsetup(int unit) { - struct ata_channel *hwif = &ide_hwifs[unit]; - u8 config = hwif->config_data; - int base = hwif->select_data; - void *tuneproc = (void *) hwif->tuneproc; - - if (!(hwif->chipset == ide_qd65xx)) return; - - printk(KERN_NOTICE "%s: back to defaults\n", hwif->name); - - hwif->selectproc = NULL; - hwif->tuneproc = NULL; - - if (tuneproc == (void *) qd6500_tune_drive) { - // will do it for both - outb(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0])); - } else if (tuneproc == (void *) qd6580_tune_drive) { - if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) { - outb(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); - outb(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1])); - } else { - outb(unit ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); - } - } else { - printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n"); - printk(KERN_WARNING "keeping settings !\n"); - } -} - -/* - * looks at the specified baseport, and if qd found, registers & initialises it - * return 1 if another qd may be probed - */ - -int __init qd_probe(int base) -{ - u8 config; - int unit; - - config = inb(QD_CONFIG_PORT); - - if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1; - - unit = ! (config & QD_CONFIG_IDE_BASEPORT); - - if ((config & 0xf0) == QD_CONFIG_QD6500) { - if (qd_testreg(base)) return 1; /* bad register */ - - /* qd6500 found */ - - printk(KERN_NOTICE "%s: qd6500 at %#x\n", ide_hwifs[unit].name, base); - printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", config, QD_ID3); - - if (config & QD_CONFIG_DISABLED) { - printk(KERN_WARNING "qd6500 is disabled !\n"); - return 1; - } - - qd_setup(unit, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA, &qd6500_tune_drive); - return 1; - } - - if (((config & 0xf0) == QD_CONFIG_QD6580_A) || ((config & 0xf0) == QD_CONFIG_QD6580_B)) { - u8 control; - - if (qd_testreg(base) || qd_testreg(base+0x02)) return 1; - /* bad registers */ - - /* qd6580 found */ - - control = inb(QD_CONTROL_PORT); - - printk(KERN_NOTICE "qd6580 at %#x\n", base); - printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", config, control, QD_ID3); - - if (control & QD_CONTR_SEC_DISABLED) { - /* secondary disabled */ - printk(KERN_INFO "%s: qd6580: single IDE board\n", ide_hwifs[unit].name); - qd_setup(unit, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA2, &qd6580_tune_drive); - outb(QD_DEF_CONTR, QD_CONTROL_PORT); - - return 1; - } else { - /* secondary enabled */ - printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", ide_hwifs[0].name, ide_hwifs[1].name); - - qd_setup(ATA_PRIMARY, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA, &qd6580_tune_drive); - qd_setup(ATA_SECONDARY, base, config | (control << 8), QD6580_DEF_DATA2, QD6580_DEF_DATA2, &qd6580_tune_drive); - outb(QD_DEF_CONTR, QD_CONTROL_PORT); - - return 0; /* no other qd65xx possible */ - } - } - /* no qd65xx found */ - return 1; -} - -#ifndef MODULE -/* - * called by ide.c when parsing command line - */ - -void __init init_qd65xx(void) -{ - if (qd_probe(0x30)) qd_probe(0xb0); -} - -#else - -MODULE_AUTHOR("Samuel Thibault"); -MODULE_DESCRIPTION("support of qd65xx vlb ide chipset"); -MODULE_LICENSE("GPL"); - -int __init qd65xx_mod_init(void) -{ - if (qd_probe(0x30)) qd_probe(0xb0); - if (ide_hwifs[0].chipset != ide_qd65xx && ide_hwifs[1].chipset != ide_qd65xx) return -ENODEV; - return 0; -} -module_init(qd65xx_mod_init); - -void __init qd65xx_mod_exit(void) -{ - qd_unsetup(ATA_PRIMARY); - qd_unsetup(ATA_SECONDARY); -} -module_exit(qd65xx_mod_exit); -#endif diff -Nru a/drivers/ide/qd65xx.h b/drivers/ide/qd65xx.h --- a/drivers/ide/qd65xx.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,140 +0,0 @@ -/* - * linux/drivers/ide/qd65xx.h - * - * Copyright (c) 2000 Linus Torvalds & authors - */ - -/* - * Authors: Petr Soucek - * Samuel Thibault - */ - -/* truncates a in [b,c] */ -#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) - -#define IDE_IMPLY(a,b) ((!(a)) || (b)) - -#define QD_TIM1_PORT (base) -#define QD_CONFIG_PORT (base+0x01) -#define QD_TIM2_PORT (base+0x02) -#define QD_CONTROL_PORT (base+0x03) - -#define QD_CONFIG_IDE_BASEPORT 0x01 -#define QD_CONFIG_BASEPORT 0x02 -#define QD_CONFIG_ID3 0x04 -#define QD_CONFIG_DISABLED 0x08 -#define QD_CONFIG_QD6500 0xc0 -#define QD_CONFIG_QD6580_A 0xa0 -#define QD_CONFIG_QD6580_B 0x50 - -#define QD_CONTR_SEC_DISABLED 0x01 - -#define QD_ID3 ((config & QD_CONFIG_ID3)!=0) - -#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff) -#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8) - -#define QD_TIMING(drive) (u8)(((drive)->drive_data) & 0x00ff) -#define QD_TIMREG(drive) (u8)((((drive)->drive_data) & 0xff00) >> 8) - -#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08)) -#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) -#define QD6580_DEF_DATA2 ((QD_TIM2_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) -#define QD_DEF_CONTR (0x40 | ((control & 0x02) ? 0x9f : 0x1f)) - -#define QD_TESTVAL 0x19 /* safe value */ - -/* Drive specific timing taken from DOS driver v3.7 */ - -struct qd65xx_timing_s { - char offset; /* ofset from the beginning of Model Number" */ - char model[4]; /* 4 chars from Model number, no conversion */ - short active; /* active time */ - short recovery; /* recovery time */ -} qd65xx_timing [] = { - { 30, "2040", 110, 225 }, /* Conner CP30204 */ - { 30, "2045", 135, 225 }, /* Conner CP30254 */ - { 30, "1040", 155, 325 }, /* Conner CP30104 */ - { 30, "1047", 135, 265 }, /* Conner CP30174 */ - { 30, "5344", 135, 225 }, /* Conner CP3544 */ - { 30, "01 4", 175, 405 }, /* Conner CP-3104 */ - { 27, "C030", 175, 375 }, /* Conner CP3000 */ - { 8, "PL42", 110, 295 }, /* Quantum LP240 */ - { 8, "PL21", 110, 315 }, /* Quantum LP120 */ - { 8, "PL25", 175, 385 }, /* Quantum LP52 */ - { 4, "PA24", 110, 285 }, /* WD Piranha SP4200 */ - { 6, "2200", 110, 260 }, /* WD Caviar AC2200 */ - { 6, "3204", 110, 235 }, /* WD Caviar AC2340 */ - { 6, "1202", 110, 265 }, /* WD Caviar AC2120 */ - { 0, "DS3-", 135, 315 }, /* Teac SD340 */ - { 8, "KM32", 175, 355 }, /* Toshiba MK234 */ - { 2, "53A1", 175, 355 }, /* Seagate ST351A */ - { 2, "4108", 175, 295 }, /* Seagate ST1480A */ - { 2, "1344", 175, 335 }, /* Seagate ST3144A */ - { 6, "7 12", 110, 225 }, /* Maxtor 7213A */ - { 30, "02F4", 145, 295 }, /* Conner 3204F */ - { 2, "1302", 175, 335 }, /* Seagate ST3120A */ - { 2, "2334", 145, 265 }, /* Seagate ST3243A */ - { 2, "2338", 145, 275 }, /* Seagate ST3283A */ - { 2, "3309", 145, 275 }, /* Seagate ST3390A */ - { 2, "5305", 145, 275 }, /* Seagate ST3550A */ - { 2, "4100", 175, 295 }, /* Seagate ST1400A */ - { 2, "4110", 175, 295 }, /* Seagate ST1401A */ - { 2, "6300", 135, 265 }, /* Seagate ST3600A */ - { 2, "5300", 135, 265 }, /* Seagate ST3500A */ - { 6, "7 31", 135, 225 }, /* Maxtor 7131 AT */ - { 6, "7 43", 115, 265 }, /* Maxtor 7345 AT */ - { 6, "7 42", 110, 255 }, /* Maxtor 7245 AT */ - { 6, "3 04", 135, 265 }, /* Maxtor 340 AT */ - { 6, "61 0", 135, 285 }, /* WD AC160 */ - { 6, "1107", 135, 235 }, /* WD AC1170 */ - { 6, "2101", 110, 220 }, /* WD AC1210 */ - { 6, "4202", 135, 245 }, /* WD AC2420 */ - { 6, "41 0", 175, 355 }, /* WD Caviar 140 */ - { 6, "82 0", 175, 355 }, /* WD Caviar 280 */ - { 8, "PL01", 175, 375 }, /* Quantum LP105 */ - { 8, "PL25", 110, 295 }, /* Quantum LP525 */ - { 10, "4S 2", 175, 385 }, /* Quantum ELS42 */ - { 10, "8S 5", 175, 385 }, /* Quantum ELS85 */ - { 10, "1S72", 175, 385 }, /* Quantum ELS127 */ - { 10, "1S07", 175, 385 }, /* Quantum ELS170 */ - { 8, "ZE42", 135, 295 }, /* Quantum EZ240 */ - { 8, "ZE21", 175, 385 }, /* Quantum EZ127 */ - { 8, "ZE58", 175, 385 }, /* Quantum EZ85 */ - { 8, "ZE24", 175, 385 }, /* Quantum EZ42 */ - { 27, "C036", 155, 325 }, /* Conner CP30064 */ - { 27, "C038", 155, 325 }, /* Conner CP30084 */ - { 6, "2205", 110, 255 }, /* WDC AC2250 */ - { 2, " CHA", 140, 415 }, /* WDC AH series; WDC AH260, WDC */ - { 2, " CLA", 140, 415 }, /* WDC AL series: WDC AL2120, 2170, */ - { 4, "UC41", 140, 415 }, /* WDC CU140 */ - { 6, "1207", 130, 275 }, /* WDC AC2170 */ - { 6, "2107", 130, 275 }, /* WDC AC1270 */ - { 6, "5204", 130, 275 }, /* WDC AC2540 */ - { 30, "3004", 110, 235 }, /* Conner CP30340 */ - { 30, "0345", 135, 255 }, /* Conner CP30544 */ - { 12, "12A3", 175, 320 }, /* MAXTOR LXT-213A */ - { 12, "43A0", 145, 240 }, /* MAXTOR LXT-340A */ - { 6, "7 21", 180, 290 }, /* Maxtor 7120 AT */ - { 6, "7 71", 135, 240 }, /* Maxtor 7170 AT */ - { 12, "45\0000", 110, 205 }, /* MAXTOR MXT-540 */ - { 8, "PL11", 180, 290 }, /* QUANTUM LP110A */ - { 8, "OG21", 150, 275 }, /* QUANTUM GO120 */ - { 12, "42A5", 175, 320 }, /* MAXTOR LXT-245A */ - { 2, "2309", 175, 295 }, /* ST3290A */ - { 2, "3358", 180, 310 }, /* ST3385A */ - { 2, "6355", 180, 310 }, /* ST3655A */ - { 2, "1900", 175, 270 }, /* ST9100A */ - { 2, "1954", 175, 270 }, /* ST9145A */ - { 2, "1909", 175, 270 }, /* ST9190AG */ - { 2, "2953", 175, 270 }, /* ST9235A */ - { 2, "1359", 175, 270 }, /* ST3195A */ - { 24, "3R11", 175, 290 }, /* ALPS ELECTRIC Co.,LTD, DR311C */ - { 0, "2M26", 175, 215 }, /* M262XT-0Ah */ - { 4, "2253", 175, 300 }, /* HP C2235A */ - { 4, "-32A", 145, 245 }, /* H3133-A2 */ - { 30, "0326", 150, 270 }, /* Samsung Electronics 120MB */ - { 30, "3044", 110, 195 }, /* Conner CFA340A */ - { 30, "43A0", 110, 195 }, /* Conner CFA340A */ - { -1, " ", 175, 415 } /* unknown disk name */ -}; diff -Nru a/drivers/ide/quirks.c b/drivers/ide/quirks.c --- a/drivers/ide/quirks.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,232 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 2002 Marcin Dalecki - * - * Copyright (c) 1999-2000 Andre Hedrick - * Copyright (c) 1995-1998 Mark Lord - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -/* - * Just the black and white list handling for BM-DMA operation. - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - -struct drive_list_entry { - char * id_model; - char * id_firmware; -}; - -struct drive_list_entry drive_whitelist[] = { - { "Micropolis 2112A", NULL }, - { "CONNER CTMA 4000", NULL }, - { "CONNER CTT8000-A", NULL }, - { "ST34342A", NULL }, - { NULL, NULL } -}; - -struct drive_list_entry drive_blacklist[] = { - - { "WDC AC11000H", NULL }, - { "WDC AC22100H", NULL }, - { "WDC AC32500H", NULL }, - { "WDC AC33100H", NULL }, - { "WDC AC31600H", NULL }, - { "WDC AC32100H", "24.09P07" }, - { "WDC AC23200L", "21.10N21" }, - { "Compaq CRD-8241B", NULL }, - { "CRD-8400B", NULL }, - { "CRD-8480B", NULL }, - { "CRD-8480C", NULL }, - { "CRD-8482B", NULL }, - { "CRD-84", NULL }, - { "SanDisk SDP3B", NULL }, - { "SanDisk SDP3B-64", NULL }, - { "SANYO CD-ROM CRD", NULL }, - { "HITACHI CDR-8", NULL }, - { "HITACHI CDR-8335", NULL }, - { "HITACHI CDR-8435", NULL }, - { "Toshiba CD-ROM XM-6202B", NULL }, - { "CD-532E-A", NULL }, - { "E-IDE CD-ROM CR-840", NULL }, - { "CD-ROM Drive/F5A", NULL }, - { "RICOH CD-R/RW MP7083A", NULL }, - { "WPI CDD-820", NULL }, - { "SAMSUNG CD-ROM SC-148C", NULL }, - { "SAMSUNG CD-ROM SC-148F", NULL }, - { "SAMSUNG CD-ROM SC", NULL }, - { "SanDisk SDP3B-64", NULL }, - { "SAMSUNG CD-ROM SN-124", NULL }, - { "PLEXTOR CD-R PX-W8432T", NULL }, - { "ATAPI CD-ROM DRIVE 40X MAXIMUM", NULL }, - { "_NEC DV5800A", NULL }, - { NULL, NULL } - -}; - -static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) -{ - for ( ; drive_table->id_model ; drive_table++) - if ((!strcmp(drive_table->id_model, id->model)) && - ((drive_table->id_firmware && !strstr(drive_table->id_firmware, id->fw_rev)) || - (!drive_table->id_firmware))) - return 1; - return 0; -} - -#else - -/* - * good_dma_drives() lists the model names (from "hdparm -i") - * of drives which do not support mode2 DMA but which are - * known to work fine with this interface under Linux. - */ -const char *good_dma_drives[] = {"Micropolis 2112A", - "CONNER CTMA 4000", - "CONNER CTT8000-A", - "ST34342A", /* for Sun Ultra */ - NULL}; - -/* - * bad_dma_drives() lists the model names (from "hdparm -i") - * of drives which supposedly support (U)DMA but which are - * known to corrupt data with this interface under Linux. - * - * This is an empirical list. Its generated from bug reports. That means - * while it reflects actual problem distributions it doesn't answer whether - * the drive or the controller, or cabling, or software, or some combination - * thereof is the fault. If you don't happen to agree with the kernel's - * opinion of your drive - use hdparm to turn DMA on. - */ -const char *bad_dma_drives[] = {"WDC AC11000H", - "WDC AC22100H", - "WDC AC32100H", - "WDC AC32500H", - "WDC AC33100H", - "WDC AC31600H", - NULL}; - -#endif - -/* - * For both Blacklisted and Whitelisted drives. - * This is setup to be called as an extern for future support - * to other special driver code. - */ -int check_drive_lists(struct ata_device *drive, int good_bad) -{ - struct hd_driveid *id = drive->id; - -#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - if (good_bad) { - return in_drive_list(id, drive_whitelist); - } else { - int blacklist = in_drive_list(id, drive_blacklist); - if (blacklist) - printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model); - return(blacklist); - } -#else - const char **list; - - if (good_bad) { - /* Consult the list of known "good" drives */ - list = good_dma_drives; - while (*list) { - if (!strcmp(*list++, id->model)) - return 1; - } - } else { - /* Consult the list of known "bad" drives */ - list = bad_dma_drives; - while (*list) { - if (!strcmp(*list++, id->model)) { - printk("%s: Disabling (U)DMA for %s\n", - drive->name, id->model); - return 1; - } - } - } -#endif - return 0; -} - -void udma_print(struct ata_device *drive) -{ -#ifdef CONFIG_ARCH_ACORN - printk(", DMA"); -#else - struct hd_driveid *id = drive->id; - char *str = NULL; - - if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && - (id->dma_ultra & (id->dma_ultra >> 14) & 3)) { - if ((id->dma_ultra >> 15) & 1) - str = ", UDMA(mode 7)"; /* UDMA BIOS-enabled! */ - else - str = ", UDMA(133)"; /* UDMA BIOS-enabled! */ - } else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && - (id->dma_ultra & (id->dma_ultra >> 11) & 7)) { - if ((id->dma_ultra >> 13) & 1) { - str = ", UDMA(100)"; /* UDMA BIOS-enabled! */ - } else if ((id->dma_ultra >> 12) & 1) { - str = ", UDMA(66)"; /* UDMA BIOS-enabled! */ - } else { - str = ", UDMA(44)"; /* UDMA BIOS-enabled! */ - } - } else if ((id->field_valid & 4) && - (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { - if ((id->dma_ultra >> 10) & 1) { - str = ", UDMA(33)"; /* UDMA BIOS-enabled! */ - } else if ((id->dma_ultra >> 9) & 1) { - str = ", UDMA(25)"; /* UDMA BIOS-enabled! */ - } else { - str = ", UDMA(16)"; /* UDMA BIOS-enabled! */ - } - } else if (id->field_valid & 4) - str = ", (U)DMA"; /* Can be BIOS-enabled! */ - else - str = ", DMA"; - - printk(str); -#endif -} - -/* - * Drive back/white list handling for UDMA capability: - */ - -int udma_black_list(struct ata_device *drive) -{ - return check_drive_lists(drive, 0); -} - -int udma_white_list(struct ata_device *drive) -{ - return check_drive_lists(drive, 1); -} - -EXPORT_SYMBOL(udma_print); -EXPORT_SYMBOL(udma_black_list); -EXPORT_SYMBOL(udma_white_list); diff -Nru a/drivers/ide/rapide.c b/drivers/ide/rapide.c --- a/drivers/ide/rapide.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,94 +0,0 @@ -/* - * linux/drivers/ide/rapide.c - * - * Copyright (c) 1996-1998 Russell King. - * - * Changelog: - * 08-06-1996 RMK Created - * 13-04-1998 RMK Added manufacturer and product IDs - */ - -#include -#include -#include -#include -#include -#include - -#include - -static card_ids __init rapide_cids[] = { - { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, - { 0xffff, 0xffff } -}; - -static struct expansion_card *ec[MAX_ECARDS]; -static int result[MAX_ECARDS]; - -static inline int rapide_register(struct expansion_card *ec) -{ - unsigned long port = ecard_address (ec, ECARD_MEMC, 0); - hw_regs_t hw; - - int i; - - memset(&hw, 0, sizeof(hw)); - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw.io_ports[i] = (ide_ioreg_t)port; - port += 1 << 4; - } - hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206; - hw.irq = ec->irq; - - return ide_register_hw(&hw); -} - -int __init rapide_init(void) -{ - int i; - - for (i = 0; i < MAX_ECARDS; i++) - ec[i] = NULL; - - ecard_startfind(); - - for (i = 0; ; i++) { - if ((ec[i] = ecard_find(0, rapide_cids)) == NULL) - break; - - ecard_claim(ec[i]); - result[i] = rapide_register(ec[i]); - } - for (i = 0; i < MAX_ECARDS; i++) - if (ec[i] && result[i] < 0) { - ecard_release(ec[i]); - ec[i] = NULL; - } - return 0; -} - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module (void) -{ - return rapide_init(); -} - -void cleanup_module (void) -{ - int i; - - for (i = 0; i < MAX_ECARDS; i++) - if (ec[i]) { - unsigned long port; - port = ecard_address(ec[i], ECARD_MEMC, 0); - - ide_unregister_port(port, ec[i]->irq, 16); - ecard_release(ec[i]); - ec[i] = NULL; - } -} -#endif - diff -Nru a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c --- a/drivers/ide/rz1000.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,119 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * Copyright (C) 1995-1998 Linus Torvalds & author (see below) - * - * Principal Author: mlord@pobox.com (Mark Lord) - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This file provides support for disabling the buggy read-ahead - * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards. - * - * Dunno if this fixes both ports, or only the primary port (?). - */ - -#include /* for CONFIG_PCI */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef CONFIG_PCI - -#include "pcihost.h" - -static void __init rz1000_init_channel(struct ata_channel *hwif) -{ - unsigned short reg; - struct pci_dev *dev = hwif->pci_dev; - - hwif->chipset = ide_rz1000; - if (!pci_read_config_word (dev, 0x40, ®) - && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) - { - printk("%s: disabled chipset read-ahead (buggy RZ1000/RZ1001)\n", hwif->name); - } else { - hwif->serialized = 1; - hwif->no_unmask = 1; - printk("%s: serialized, disabled unmasking (buggy RZ1000/RZ1001)\n", hwif->name); - } -} - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_PCTECH, - .device = PCI_DEVICE_ID_PCTECH_RZ1000, - .init_channel = rz1000_init_channel, - .bootable = ON_BOARD - }, - { - .vendor = PCI_VENDOR_ID_PCTECH, - .device = PCI_DEVICE_ID_PCTECH_RZ1001, - .init_channel = rz1000_init_channel, - .bootable = ON_BOARD - }, -}; - -int __init init_rz1000(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} - -#else - -static void __init init_rz1000 (struct pci_dev *dev, const char *name) -{ - unsigned short reg, h; - - if (!pci_read_config_word (dev, PCI_COMMAND, ®) && !(reg & PCI_COMMAND_IO)) { - printk("%s: buggy IDE controller disabled (BIOS)\n", name); - return; - } - if (!pci_read_config_word (dev, 0x40, ®) - && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) - { - printk("IDE: disabled chipset read-ahead (buggy %s)\n", name); - } else { - for (h = 0; h < MAX_HWIFS; ++h) { - struct ata_channel *hwif = &ide_hwifs[h]; - if ((hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0 || hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - && (hwif->chipset == ide_unknown || hwif->chipset == ide_generic)) - { - hwif->chipset = ide_rz1000; - hwif->serialized = 1; - hwif->drives[0].no_unmask = 1; - hwif->drives[1].no_unmask = 1; - if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - hwif->unit = 1; - printk("%s: serialized, disabled unmasking (buggy %s)\n", hwif->name, name); - } - } - } -} - -void __init ide_probe_for_rz100x (void) /* called from ide.c */ -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, dev))!=NULL) - rz1000_init (dev, "RZ1000"); - while ((dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, dev))!=NULL) - rz1000_init (dev, "RZ1001"); -} - -#endif diff -Nru a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c --- a/drivers/ide/serverworks.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,422 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * linux/drivers/ide/serverworks.c Version 0.3 26 Oct 2001 - * - * May be copied or modified under the terms of the GNU General Public License - * - * Copyright (C) 1998-2000 Michel Aubry - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz - * Copyright (C) 1998-2000 Andre Hedrick - * Portions copyright (c) 2001 Sun Microsystems - * - * - * RCC/ServerWorks IDE driver for Linux - * - * OSB4: `Open South Bridge' IDE Interface (fn 1) - * supports UDMA mode 2 (33 MB/s) - * - * CSB5: `Champion South Bridge' IDE Interface (fn 1) - * all revisions support UDMA mode 4 (66 MB/s) - * revision A2.0 and up support UDMA mode 5 (100 MB/s) - * - * *** The CSB5 does not provide ANY register *** - * *** to detect 80-conductor cable presence. *** - * - * - * here's the default lspci: - * - * 00:0f.1 IDE interface: ServerWorks: Unknown device 0211 (prog-if 8a [Master SecP PriP]) - * Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- - * Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- SERR- TAbort- SERR- -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "pcihost.h" - -#undef SVWKS_DEBUG_DRIVE_INFO - -static u8 svwks_revision; - -#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ - -static struct pci_dev *isa_dev; - -static int __init svwks_modes_map(struct ata_channel *ch) -{ - int map = XFER_EPIO | XFER_MWDMA; - - switch(ch->pci_dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) - map |= XFER_UDMA_100; - map |= XFER_UDMA_66; - case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: - map |= XFER_UDMA; - break; - } - - return map; -} - -static int svwks_tune_chipset(struct ata_device *drive, u8 speed) -{ - static u8 dma_modes[] = { 0x77, 0x21, 0x20 }; - static u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; - - struct ata_channel *ch = drive->channel; - struct pci_dev *dev = ch->pci_dev; - u8 unit = drive->select.b.unit & 0x01; - u8 drive_pci, drive_pci2; - u8 drive_pci3 = ch->unit ? 0x57 : 0x56; - - u8 ultra_enable, ultra_timing, dma_timing, pio_timing; - u16 csb5_pio; - - u8 pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; - - switch (drive->dn) { - case 0: drive_pci = 0x41; break; - case 1: drive_pci = 0x40; break; - case 2: drive_pci = 0x43; break; - case 3: drive_pci = 0x42; break; - default: - return -1; - } - drive_pci2 = drive_pci + 4; - - pci_read_config_byte(dev, drive_pci, &pio_timing); - pci_read_config_byte(dev, drive_pci2, &dma_timing); - pci_read_config_byte(dev, drive_pci3, &ultra_timing); - pci_read_config_word(dev, 0x4A, &csb5_pio); - pci_read_config_byte(dev, 0x54, &ultra_enable); - -#ifdef DEBUG - printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", - drive->name, ultra_timing, dma_timing, pio_timing); -#endif - - pio_timing &= ~0xFF; - dma_timing &= ~0xFF; - ultra_timing &= ~(0x0F << (4*unit)); - ultra_enable &= ~(0x01 << drive->dn); - csb5_pio &= ~(0x0F << (4*drive->dn)); - - switch(speed) { - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - pio_timing |= pio_modes[speed - XFER_PIO_0]; - csb5_pio |= ((speed - XFER_PIO_0) << (4*drive->dn)); - break; - - /* FIXME: check SWDMA modes --bkz */ -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - pio_timing |= pio_modes[pio]; - csb5_pio |= (pio << (4*drive->dn)); - 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: - pio_timing |= pio_modes[pio]; - csb5_pio |= (pio << (4*drive->dn)); - dma_timing |= dma_modes[2]; - ultra_timing |= ((speed - XFER_UDMA_0) << (4*unit)); - ultra_enable |= (0x01 << drive->dn); -#endif - default: - break; - } - -#ifdef DEBUG - printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", - drive->name, ultra_timing, dma_timing, pio_timing); -#endif - -#if SVWKS_DEBUG_DRIVE_INFO - printk("%s: %02x drive%d\n", drive->name, speed, drive->dn); -#endif - - pci_write_config_byte(dev, drive_pci, pio_timing); - - if (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) - pci_write_config_word(dev, 0x4A, csb5_pio); - -#ifdef CONFIG_BLK_DEV_IDEDMA - pci_write_config_byte(dev, drive_pci2, dma_timing); - pci_write_config_byte(dev, drive_pci3, ultra_timing); - pci_write_config_byte(dev, 0x54, ultra_enable); -#endif - - return ide_config_drive_speed(drive, speed); -} - -/* FIXME: pio == 255 -> ata_best_pio_mode(drive) --bkz */ -static void svwks_tune_drive(struct ata_device *drive, u8 pio) -{ - (void) svwks_tune_chipset(drive, XFER_PIO_0 + min_t(u8, pio, 4)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int svwks_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - unsigned long dma_base = ch->dma_base; - u8 dma_stat; - - if(inb(dma_base+0x02)&1) - { -#if 0 - int i; - printk(KERN_ERR "Curious - OSB4 thinks the DMA is still running.\n"); - for(i=0;i<10;i++) - { - if(!(inb(dma_base+0x02)&1)) - { - printk(KERN_ERR "OSB4 now finished.\n"); - break; - } - udelay(5); - } -#endif - printk(KERN_CRIT "Serverworks OSB4 in impossible state.\n"); - printk(KERN_CRIT "Disable UDMA or if you are using Seagate then try switching disk types\n"); - printk(KERN_CRIT "on this controller. Please report this event to osb4-bug@ide.cabal.tm\n"); -#if 0 - /* Panic might sys_sync -> death by corrupt disk */ - panic("OSB4: continuing might cause disk corruption.\n"); -#else - printk(KERN_CRIT "OSB4: continuing might cause disk corruption.\n"); - while(1) - cpu_relax(); -#endif - } - - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - udma_destroy_table(ch); /* purge DMA mappings */ - - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ -} -#endif - -static unsigned int __init svwks_init_chipset(struct pci_dev *dev) -{ - unsigned int reg; - u8 btr; - - /* save revision id to determine DMA capability */ - pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); - - /* force Master Latency Timer value to 64 PCICLKs */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); - - /* OSB4 : South Bridge and IDE */ - if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { - isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); - if (isa_dev) { - pci_read_config_dword(isa_dev, 0x64, ®); - reg &= ~0x00002000; /* disable 600ns interrupt mask */ - reg |= 0x00004000; /* enable UDMA/33 support */ - pci_write_config_dword(isa_dev, 0x64, reg); - } - } - - /* setup CSB5 : South Bridge and IDE */ - else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) { - /* setup the UDMA Control register - * - * 1. clear bit 6 to enable DMA - * 2. enable DMA modes with bits 0-1 - * 00 : legacy - * 01 : udma2 - * 10 : udma2/udma4 - * 11 : udma2/udma4/udma5 - */ - pci_read_config_byte(dev, 0x5A, &btr); - btr &= ~0x40; - btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; - pci_write_config_byte(dev, 0x5A, btr); - } - - return 0; -} - -/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits - * of the subsystem device ID indicate presence of an 80-pin cable. - * Bit 15 clear = secondary IDE channel does not have 80-pin cable. - * Bit 15 set = secondary IDE channel has 80-pin cable. - * Bit 14 clear = primary IDE channel does not have 80-pin cable. - * Bit 14 set = primary IDE channel has 80-pin cable. - */ -static unsigned int __init ata66_svwks_dell(struct ata_channel *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS && - (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE || - dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) - return ((1 << (hwif->unit + 14)) & - dev->subsystem_device) ? 1 : 0; - return 0; -} - -/* Sun Cobalt Alpine hardware avoids the 80-pin cable - * detect issue by attaching the drives directly to the board. - * This check follows the Dell precedent (how scary is that?!) - * - * WARNING: this only works on Alpine hardware! - */ -static unsigned int __init ata66_svwks_cobalt(struct ata_channel *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS && - dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) - return ((1 << (hwif->unit + 14)) & - dev->subsystem_device) ? 1 : 0; - return 0; -} - -static unsigned int __init svwks_ata66_check(struct ata_channel *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - - /* Dell PowerEdge */ - if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) - return ata66_svwks_dell (hwif); - - /* Cobalt Alpine */ - if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN) - return ata66_svwks_cobalt (hwif); - - return 0; -} - -static void __init ide_init_svwks(struct ata_channel *hwif) -{ - if (!hwif->irq) - hwif->irq = hwif->unit ? 15 : 14; - - hwif->udma_four = svwks_ata66_check(hwif); - - hwif->tuneproc = &svwks_tune_drive; - hwif->speedproc = &svwks_tune_chipset; - -#ifndef CONFIG_BLK_DEV_IDEDMA - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; -#else - if (hwif->dma_base) { - hwif->modes_map = svwks_modes_map(hwif); - hwif->udma_setup = udma_generic_setup; - hwif->udma_stop = svwks_udma_stop; - hwif->highmem = 1; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -#endif -} - - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, - .init_chipset = svwks_init_chipset, - .init_channel = ide_init_svwks, - .bootable = ON_BOARD, - .flags = ATA_F_DMA - }, - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, - .init_chipset = svwks_init_chipset, - .init_channel = ide_init_svwks, - .bootable = ON_BOARD, - .flags = ATA_F_SIMPLEX - }, -}; - -int __init init_svwks(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c --- a/drivers/ide/sis5513.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,523 +0,0 @@ -/* - * linux/drivers/ide/sis5513.c Version 0.13 March 6, 2002 - * - * Copyright (C) 1999-2000 Andre Hedrick - * Copyright (C) 2002 Lionel Bouton , Maintainer - * May be copied or modified under the terms of the GNU General Public License - * - * - * Thanks : - * - * SiS Taiwan : for direct support and hardware. - * Daniela Engert : for initial ATA100 advices and numerous others. - * John Fremlin, Manfred Spraul : - * for checking code correctness, providing patches. - */ - -/* - * Original tests and design on the SiS620/5513 chipset. - * ATA100 tests and design on the SiS735/5513 chipset. - * ATA16/33 design from specs - */ - -/* - * TODO: - * - Get ridden of SisHostChipInfo[] completness dependancy. - * - Get ATA-133 datasheets, implement ATA-133 init code. - * - Are there pre-ATA_16 SiS chips ? -> tune init code for them - * or remove ATA_00 define - * - More checks in the config registers (force values instead of - * relying on the BIOS setting them correctly). - * - Further optimisations ? - * . for example ATA66+ regs 0x48 & 0x4A - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "timing.h" -#include "pcihost.h" - -/* When DEBUG is defined it outputs initial PCI config register - values and changes made to them by the driver */ -// #define DEBUG -/* When BROKEN_LEVEL is defined it limits the DMA mode - at boot time to its value */ -// #define BROKEN_LEVEL XFER_SW_DMA_0 - -/* Miscellaneaous flags */ -#define SIS5513_LATENCY 0x01 - -/* registers layout and init values are chipset family dependant */ -/* 1/ define families */ -#define ATA_00 0x00 -#define ATA_16 0x01 -#define ATA_33 0x02 -#define ATA_66 0x03 -#define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout -#define ATA_100 0x05 -#define ATA_133 0x06 - -/* 2/ variable holding the controller chipset family value */ -static unsigned char chipset_family; - -/* - * Debug code: following IDE config registers' changes - */ -#ifdef DEBUG -/* Copy of IDE Config registers 0x00 -> 0x57 - Fewer might be used depending on the actual chipset */ -static unsigned char ide_regs_copy[0x58]; - -static u8 sis5513_max_config_register(void) { - switch(chipset_family) { - case ATA_00: - case ATA_16: return 0x4f; - case ATA_33: return 0x52; - case ATA_66: - case ATA_100a: - case ATA_100: - case ATA_133: - default: return 0x57; - } -} - -/* Read config registers, print differences from previous read */ -static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) { - int i; - u8 reg_val; - u8 changed = 0; - u8 max = sis5513_max_config_register(); - - printk("SIS5513: %s, changed registers:\n", info); - for(i=0; i<=max; i++) { - pci_read_config_byte(dev, i, ®_val); - if (reg_val != ide_regs_copy[i]) { - printk("%0#x: %0#x -> %0#x\n", - i, ide_regs_copy[i], reg_val); - ide_regs_copy[i]=reg_val; - changed=1; - } - } - - if (!changed) { - printk("none\n"); - } -} - -/* Load config registers, no printing */ -static void sis5513_load_registers(struct pci_dev* dev) -{ - int i; - u8 max = sis5513_max_config_register(); - - for(i=0; i<=max; i++) { - pci_read_config_byte(dev, i, &(ide_regs_copy[i])); - } -} - -/* Print a register */ -static void sis5513_print_register(int reg) -{ - printk(" %0#x:%0#x", reg, ide_regs_copy[reg]); -} - -/* Print valuable registers */ -static void sis5513_print_registers(struct pci_dev* dev, char* marker) { - int i; - u8 max = sis5513_max_config_register(); - - sis5513_load_registers(dev); - printk("SIS5513 %s\n", marker); - printk("SIS5513 dump:"); - for(i=0x00; i<0x40; i++) { - if ((i % 0x10)==0) printk("\n "); - sis5513_print_register(i); - } - for(; i<49; i++) { - sis5513_print_register(i); - } - printk("\n "); - - for(; i<=max; i++) { - sis5513_print_register(i); - } - printk("\n"); -} -#endif - - -/* - * Devices supported - */ -static const struct { - const char *name; - unsigned short host_id; - unsigned char chipset_family; - unsigned char flags; -} SiSHostChipInfo[] = { - { "SiS750", PCI_DEVICE_ID_SI_750, ATA_100, SIS5513_LATENCY }, - { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100, SIS5513_LATENCY }, - { "SiS740", PCI_DEVICE_ID_SI_740, ATA_100, SIS5513_LATENCY }, - { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100, SIS5513_LATENCY }, - { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a, SIS5513_LATENCY }, - { "SiS650", PCI_DEVICE_ID_SI_650, ATA_100, SIS5513_LATENCY }, - { "SiS645", PCI_DEVICE_ID_SI_645, ATA_100, SIS5513_LATENCY }, - { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100, SIS5513_LATENCY }, - { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66, SIS5513_LATENCY }, - { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66, SIS5513_LATENCY }, - { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66, SIS5513_LATENCY }, - { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66, 0}, - { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66, 0}, - { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33, 0}, - { "SiS5598", PCI_DEVICE_ID_SI_5598, ATA_33, 0}, - { "SiS5597", PCI_DEVICE_ID_SI_5597, ATA_33, 0}, - { "SiS5591", PCI_DEVICE_ID_SI_5591, ATA_33, 0}, - { "SiS5513", PCI_DEVICE_ID_SI_5513, ATA_16, 0}, - { "SiS5511", PCI_DEVICE_ID_SI_5511, ATA_16, 0}, -}; - -/* Cycle time bits and values vary accross chip dma capabilities - These three arrays hold the register layout and the values to set. - Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ -static u8 cycle_time_offset[] = {0,0,5,4,4,0,0}; -static u8 cycle_time_range[] = {0,0,2,3,3,4,4}; -static u8 cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = { - {0,0,0,0,0,0}, /* no udma */ - {0,0,0,0,0,0}, /* no udma */ - {3,2,1,0,0,0}, - {7,5,3,2,1,0}, - {7,5,3,2,1,0}, - {11,7,5,4,2,1}, - {0,0,0,0,0,0} /* not yet known, ask SiS */ -}; - -static struct pci_dev *host_dev = NULL; - -static int __init sis5513_modes_map(struct ata_channel *ch) -{ - int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA; - - switch(chipset_family) { - case ATA_133: /* map |= XFER_UDMA_133; */ - case ATA_100: - case ATA_100a: - map |= XFER_UDMA_100; - case ATA_66: - map |= XFER_UDMA_66; - case ATA_33: - map |= XFER_UDMA; - break; - } - - return map; -} - -/* - * Configuration functions - */ -/* Enables per-drive prefetch and postwrite */ -static void config_drive_art_rwp(struct ata_device *drive) -{ - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - - u8 reg4bh = 0; - u8 rw_prefetch = (0x11 << drive->dn); - -#ifdef DEBUG - printk("SIS5513: config_drive_art_rwp, drive %d\n", drive->dn); - sis5513_load_verify_registers(dev, "config_drive_art_rwp start"); -#endif - - if (drive->type != ATA_DISK) - return; - pci_read_config_byte(dev, 0x4b, ®4bh); - - if ((reg4bh & rw_prefetch) != rw_prefetch) - pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); -#ifdef DEBUG - sis5513_load_verify_registers(dev, "config_drive_art_rwp end"); -#endif -} - - -/* Set per-drive active and recovery time */ -static int config_art_rwp_pio(struct ata_device *drive, u8 pio) -{ - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - u8 drive_pci, test1, test2; - -#ifdef DEBUG - sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start"); -#endif - - config_drive_art_rwp(drive); - -#ifdef DEBUG - printk("SIS5513: config_drive_art_rwp_pio, drive %d, pio %d, timing %d\n", - drive->dn, pio, timing); -#endif - - drive_pci = 0x40 + (drive->dn << 1); - - /* register layout changed with newer ATA100 chips */ - if (chipset_family < ATA_100) { - pci_read_config_byte(dev, drive_pci, &test1); - pci_read_config_byte(dev, drive_pci+1, &test2); - - /* Clear active and recovery timings */ - test1 &= ~0x0F; - test2 &= ~0x07; - - switch(pio) { - case 4: test1 |= 0x01; test2 |= 0x03; break; - case 3: test1 |= 0x03; test2 |= 0x03; break; - case 2: test1 |= 0x04; test2 |= 0x04; break; - case 1: test1 |= 0x07; test2 |= 0x06; break; - default: break; - } - pci_write_config_byte(dev, drive_pci, test1); - pci_write_config_byte(dev, drive_pci+1, test2); - } else { - switch(pio) { /* active recovery - v v */ - case 4: test1 = 0x30|0x01; break; - case 3: test1 = 0x30|0x03; break; - case 2: test1 = 0x40|0x04; break; - case 1: test1 = 0x60|0x07; break; - default: break; - } - pci_write_config_byte(dev, drive_pci, test1); - } - -#ifdef DEBUG - sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start"); -#endif - - return ide_config_drive_speed(drive, XFER_PIO_0 + min_t(u8, pio, 4)); -} - -static int sis5513_tune_chipset(struct ata_device *drive, u8 speed) -{ - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - - u8 drive_pci, reg; - -#ifdef DEBUG - sis5513_load_verify_registers(dev, "sis5513_tune_chipset start"); - printk("SIS5513: sis5513_tune_chipset, drive %d, speed %d\n", - drive->dn, speed); -#endif - - if (drive->dn > 3) /* FIXME: remove this --bkz */ - return 1; - - drive_pci = 0x40 + (drive->dn << 1); - -#ifdef BROKEN_LEVEL -#ifdef DEBUG - printk("SIS5513: BROKEN_LEVEL activated, speed=%d -> speed=%d\n", speed, BROKEN_LEVEL); -#endif - if (speed > BROKEN_LEVEL) speed = BROKEN_LEVEL; -#endif - - pci_read_config_byte(dev, drive_pci+1, ®); - /* Disable UDMA bit for non UDMA modes on UDMA chips */ - if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { - reg &= 0x7F; - pci_write_config_byte(dev, drive_pci+1, reg); - } - - /* Config chip for mode */ - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - /* 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-ATA_00][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: - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - return config_art_rwp_pio(drive, speed - XFER_PIO_0); - default: - return config_art_rwp_pio(drive, 0); - } -#ifdef DEBUG - sis5513_load_verify_registers(dev, "sis5513_tune_chipset end"); -#endif - return ide_config_drive_speed(drive, speed); -} - -static void sis5513_tune_drive(struct ata_device *drive, u8 pio) -{ - if (pio == 255) - pio = ata_best_pio_mode(drive) - XFER_PIO_0; - - (void)config_art_rwp_pio(drive, min_t(u8, pio, 4)); -} - -/* Chip detection and general config */ -static unsigned int __init pci_init_sis5513(struct pci_dev *dev) -{ - struct pci_dev *host; - int i = 0; - - /* Find the chip */ - for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) { - host = pci_find_device (PCI_VENDOR_ID_SI, - SiSHostChipInfo[i].host_id, - NULL); - if (!host) - continue; - - host_dev = host; - chipset_family = SiSHostChipInfo[i].chipset_family; - printk(SiSHostChipInfo[i].name); - printk("\n"); - -#ifdef DEBUG - sis5513_print_registers(dev, "pci_init_sis5513 start"); -#endif - - if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) { - u8 latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); - } - } - - /* Make general config ops here - 1/ tell IDE channels to operate in Compabitility mode only - 2/ tell old chips to allow per drive IDE timings */ - if (host_dev) { - u8 reg; - switch(chipset_family) { - case ATA_133: - case ATA_100: - /* Set compatibility bit */ - pci_read_config_byte(dev, 0x49, ®); - if (!(reg & 0x01)) { - pci_write_config_byte(dev, 0x49, reg|0x01); - } - break; - case ATA_100a: - case ATA_66: - /* On ATA_66 chips the bit was elsewhere */ - pci_read_config_byte(dev, 0x52, ®); - if (!(reg & 0x04)) { - pci_write_config_byte(dev, 0x52, reg|0x04); - } - break; - case ATA_33: - /* On ATA_33 we didn't have a single bit to set */ - pci_read_config_byte(dev, 0x09, ®); - if ((reg & 0x0f) != 0x00) { - pci_write_config_byte(dev, 0x09, reg&0xf0); - } - case ATA_16: - /* force per drive recovery and active timings - needed on ATA_33 and below chips */ - pci_read_config_byte(dev, 0x52, ®); - if (!(reg & 0x08)) { - pci_write_config_byte(dev, 0x52, reg|0x08); - } - break; - case ATA_00: - default: break; - } - } -#ifdef DEBUG - sis5513_load_verify_registers(dev, "pci_init_sis5513 end"); -#endif - return 0; -} - -static unsigned int __init ata66_sis5513(struct ata_channel *hwif) -{ - u8 reg48h, ata66 = 0; - u8 mask = hwif->unit ? 0x20 : 0x10; - pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); - - if (chipset_family >= ATA_66) { - ata66 = (reg48h & mask) ? 0 : 1; - } - return ata66; -} - -static void __init ide_init_sis5513(struct ata_channel *hwif) -{ - - hwif->irq = hwif->unit ? 15 : 14; - - hwif->udma_four = ata66_sis5513(hwif); - - hwif->tuneproc = &sis5513_tune_drive; - hwif->speedproc = &sis5513_tune_chipset; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base && host_dev && chipset_family > ATA_16) { - hwif->highmem = 1; - hwif->modes_map = sis5513_modes_map(hwif); - hwif->udma_setup = udma_generic_setup; - } -#endif - - return; -} - - -/* module data table */ -static struct ata_pci_device chipset __initdata = { - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_5513, - .init_chipset = pci_init_sis5513, - .init_channel = ide_init_sis5513, - .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04} }, - .bootable = ON_BOARD, -}; - -int __init init_sis5513(void) -{ - ata_register_chipset(&chipset); - - return 0; -} diff -Nru a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c --- a/drivers/ide/sl82c105.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,377 +0,0 @@ -/* - * linux/drivers/ide/sl82c105.c - * - * SL82C105/Winbond 553 IDE driver - * - * Maintainer unknown. - * - * Changelog: - * - * 15/11/1998 RMK Drive tuning added from Rebel.com's kernel - * sources - * 30/03/2002 RMK Add fixes specified in W83C553F errata. - * (with special thanks to Todd Inglett) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "timing.h" -#include "pcihost.h" - -/* - * SL82C105 PCI config register 0x40 bits. - */ -#define CTRL_IDE_IRQB (1 << 30) -#define CTRL_IDE_IRQA (1 << 28) -#define CTRL_LEGIRQ (1 << 11) -#define CTRL_P1F16 (1 << 5) -#define CTRL_P1EN (1 << 4) -#define CTRL_P0F16 (1 << 1) -#define CTRL_P0EN (1 << 0) - -/* - * Convert a PIO mode and cycle time to the required on/off - * times for the interface. This has protection against run-away - * timings. - */ -static unsigned int get_timing_sl82c105(struct ata_timing *t) -{ - unsigned int cmd_on; - unsigned int cmd_off; - - cmd_on = (t->active + 29) / 30; - cmd_off = (t->cycle - 30 * cmd_on + 29) / 30; - - if (cmd_on > 32) - cmd_on = 32; - if (cmd_on == 0) - cmd_on = 1; - - if (cmd_off > 32) - cmd_off = 32; - if (cmd_off == 0) - cmd_off = 1; - - return (cmd_on - 1) << 8 | (cmd_off - 1) | ((t->mode > XFER_PIO_2) ? 0x40 : 0x00); -} - -/* - * Configure the drive and chipset for PIO - */ -static void config_for_pio(struct ata_device *drive, int pio, int report) -{ - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - struct ata_timing *t; - unsigned short drv_ctrl = 0x909; - unsigned int xfer_mode, reg; - - reg = (hwif->unit ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); - - if (pio == 255) - xfer_mode = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); - else - xfer_mode = XFER_PIO_0 + min_t(u8, pio, 4); - - t = ata_timing_data(xfer_mode); - - if (ide_config_drive_speed(drive, xfer_mode) == 0) - drv_ctrl = get_timing_sl82c105(t); - - 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); - - if (report) { - printk("%s: selected %02x (%dns) (%04X)\n", - drive->name, xfer_mode, - t->cycle, drv_ctrl); - } - } -} - -/* - * Configure the drive and the chipset for DMA - */ -static int config_for_dma(struct ata_device *drive) -{ - struct ata_channel *hwif = drive->channel; - struct pci_dev *dev = hwif->pci_dev; - unsigned short drv_ctrl = 0x909; - unsigned int reg; - - reg = (hwif->unit ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); - - if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0) - drv_ctrl = 0x0240; - - pci_write_config_word(dev, reg, drv_ctrl); - - return 0; -} - - -/* - * Check to see if the drive and - * chipset is capable of DMA mode - */ -static int sl82c105_dma_setup(struct ata_device *drive, int map) -{ - int on = 0; - - do { - struct hd_driveid *id = drive->id; - struct ata_channel *hwif = drive->channel; - - if (!hwif->autodma) - break; - - if (!id || !(id->capability & 1)) - break; - - /* Consult the list of known "bad" drives */ - if (udma_black_list(drive)) { - on = 0; - break; - } - - if (id->field_valid & 2) { - if (id->dma_mword & 7 || id->dma_1word & 7) - on = 1; - break; - } - - if (udma_white_list(drive)) { - on = 1; - break; - } - } while (0); - - if (on) - config_for_dma(drive); - else - config_for_pio(drive, 4, 0); - - udma_enable(drive, on, 0); - - return 0; -} - -/* - * The SL82C105 holds off all IDE interrupts while in DMA mode until - * all DMA activity is completed. Sometimes this causes problems (eg, - * when the drive wants to report an error condition). - * - * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller - * state machine. We need to kick this to work around various bugs. - */ -static inline void sl82c105_reset_host(struct pci_dev *dev) -{ - u16 val; - - pci_read_config_word(dev, 0x7e, &val); - pci_write_config_word(dev, 0x7e, val | (1 << 2)); - pci_write_config_word(dev, 0x7e, val & ~(1 << 2)); -} - -static void sl82c105_dma_enable(struct ata_device *drive, int on, int verbose) -{ - if (!on || config_for_dma(drive)) { - config_for_pio(drive, 4, 0); - on = 0; - } - udma_pci_enable(drive, on, verbose); -} - -/* - * ATAPI devices can cause the SL82C105 DMA state machine to go gaga. - * Winbond recommend that the DMA state machine is reset prior to - * setting the bus master DMA enable bit. - * - * The generic IDE core will have disabled the BMEN bit before this - * function is called. - */ -static int sl82c105_dma_init(struct ata_device *drive, struct request *rq) -{ - sl82c105_reset_host(drive->channel->pci_dev); - - return udma_pci_init(drive, rq); -} - -static void sl82c105_timeout(struct ata_device *drive) -{ - sl82c105_reset_host(drive->channel->pci_dev); -} - -/* - * If we get an IRQ timeout, it might be that the DMA state machine - * got confused. Fix from Todd Inglett. Details from Winbond. - * - * This function is called when the IDE timer expires, the drive - * indicates that it is READY, and we were waiting for DMA to complete. - */ -static void sl82c105_lostirq(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - struct pci_dev *dev = ch->pci_dev; - u32 val, mask = ch->unit ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; - unsigned long dma_base = ch->dma_base; - - printk("sl82c105: lost IRQ: resetting host\n"); - - /* - * Check the raw interrupt from the drive. - */ - pci_read_config_dword(dev, 0x40, &val); - if (val & mask) - printk("sl82c105: drive was requesting IRQ, but host lost it\n"); - - /* - * Was DMA enabled? If so, disable it - we're resetting the - * host. The IDE layer will be handling the drive for us. - */ - val = inb(dma_base); - if (val & 1) { - outb(val & ~1, dma_base); - printk("sl82c105: DMA was enabled\n"); - } - - sl82c105_reset_host(dev); -} - -/* - * We only deal with PIO mode here - DMA mode 'using_dma' is not - * initialised at the point that this function is called. - */ -static void tune_sl82c105(struct ata_device *drive, u8 pio) -{ - config_for_pio(drive, pio, 1); - - /* - * We support 32-bit I/O on this interface, and it - * doesn't have problems with interrupts. - */ - drive->channel->io_32bit = 1; - drive->channel->unmask = 1; -} - -/* - * Return the revision of the Winbond bridge - * which this function is part of. - */ -static __init unsigned int sl82c105_bridge_revision(struct pci_dev *dev) -{ - struct pci_dev *bridge; - unsigned char rev; - - /* - * The bridge should be part of the same device, but function 0. - */ - bridge = pci_find_slot(dev->bus->number, - PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); - if (!bridge) - return -1; - - /* - * Make sure it is a Winbond 553 and is an ISA bridge. - */ - if (bridge->vendor != PCI_VENDOR_ID_WINBOND || - bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || - bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) - return -1; - - /* - * We need to find function 0's revision, not function 1 - */ - pci_read_config_byte(bridge, PCI_REVISION_ID, &rev); - - return rev; -} - -/* - * Enable the PCI device - */ -static unsigned int __init sl82c105_init_chipset(struct pci_dev *dev) -{ - u32 val; - - pci_read_config_dword(dev, 0x40, &val); - val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1EN | CTRL_P1F16; - pci_write_config_dword(dev, 0x40, val); - - return dev->irq; -} - -static void __init sl82c105_init_dma(struct ata_channel *ch, unsigned long dma_base) -{ - unsigned int bridge_rev; - u8 dma_state; - - dma_state = inb(dma_base + 2); - bridge_rev = sl82c105_bridge_revision(ch->pci_dev); - if (bridge_rev <= 5) { - ch->autodma = 0; - ch->drives[0].autotune = 1; - ch->drives[1].autotune = 1; - printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", - ch->name, bridge_rev); - dma_state &= ~0x60; - } else { - dma_state |= 0x60; - } - outb(dma_state, dma_base + 2); - - ata_init_dma(ch, dma_base); - - if (bridge_rev <= 5) - ch->udma_setup = NULL; - else { - ch->udma_setup = sl82c105_dma_setup; - ch->udma_enable = sl82c105_dma_enable; - ch->udma_init = sl82c105_dma_init; - ch->udma_timeout = sl82c105_timeout; - ch->udma_irq_lost = sl82c105_lostirq; - } -} - -/* - * Initialise the chip - */ -static void __init sl82c105_init_channel(struct ata_channel *ch) -{ - ch->tuneproc = tune_sl82c105; -} - - -/* module data table */ -static struct ata_pci_device chipset __initdata = { - .vendor = PCI_VENDOR_ID_WINBOND, - .device = PCI_DEVICE_ID_WINBOND_82C105, - .init_chipset = sl82c105_init_chipset, - .init_channel = sl82c105_init_channel, - .init_dma = sl82c105_init_dma, - .enablebits = { {0x40,0x01,0x01}, {0x40,0x10,0x10} }, - .bootable = ON_BOARD -}; - -int __init init_sl82c105(void) -{ - ata_register_chipset(&chipset); - - return 0; -} diff -Nru a/drivers/ide/tcq.c b/drivers/ide/tcq.c --- a/drivers/ide/tcq.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,649 +0,0 @@ -/* - * Copyright (C) 2001, 2002 Jens Axboe - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Support for the DMA queued protocol, which enables ATA disk drives to - * use tagged command queueing. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * warning: it will be _very_ verbose if defined - */ -#undef IDE_TCQ_DEBUG - -#ifdef IDE_TCQ_DEBUG -#define TCQ_PRINTK printk -#else -#define TCQ_PRINTK(x...) -#endif - -/* - * use nIEN or not - */ -#undef IDE_TCQ_NIEN - -/* - * We are leaving the SERVICE interrupt alone, IBM drives have it - * on per default and it can't be turned off. Doesn't matter, this - * is the sane config. - */ -#undef IDE_TCQ_FIDDLE_SI - -static ide_startstop_t ide_dmaq_intr(struct ata_device *drive, struct request *rq); -static ide_startstop_t service(struct ata_device *drive, struct request *rq); - -static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request *rq) -{ - unsigned long flags; - struct ata_taskfile *args = rq->special; - struct ata_channel *ch = drive->channel; - - local_irq_enable(); - - spin_lock_irqsave(ch->lock, flags); - - blkdev_dequeue_request(rq); - drive->rq = NULL; - end_that_request_last(rq); - - spin_unlock_irqrestore(ch->lock, flags); - - kfree(args); - - return ATA_OP_FINISHED; -} - -/* - * If we encounter _any_ error doing I/O to one of the tags, we must - * invalidate the pending queue. Clear the software busy queue and requeue - * on the request queue for restart. Issue a WIN_NOP to clear hardware queue. - */ -static void tcq_invalidate_queue(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - request_queue_t *q = &drive->queue; - struct ata_taskfile *ar; - struct request *rq; - unsigned long flags; - - printk(KERN_INFO "ATA: %s: invalidating pending queue (%d)\n", drive->name, ata_pending_commands(drive)); - - spin_lock_irqsave(ch->lock, flags); - - del_timer(&ch->timer); - - if (test_bit(IDE_DMA, ch->active)) - udma_stop(drive); - - blk_queue_invalidate_tags(q); - - drive->using_tcq = 0; - drive->queue_depth = 1; - clear_bit(IDE_BUSY, ch->active); - clear_bit(IDE_DMA, ch->active); - ch->handler = NULL; - - /* - * Do some internal stuff -- we really need this command to be - * executed before any new commands are started. issue a NOP - * to clear internal queue on drive. - */ - ar = kmalloc(sizeof(*ar), GFP_ATOMIC); - if (!ar) { - printk(KERN_ERR "ATA: %s: failed to issue NOP\n", drive->name); - goto out; - } - - rq = __blk_get_request(&drive->queue, READ); - if (!rq) - rq = __blk_get_request(&drive->queue, WRITE); - - /* - * blk_queue_invalidate_tags() just added back at least one command - * to the free list, so there _must_ be at least one free. - */ - BUG_ON(!rq); - - /* WIN_NOP is a special request so set it's flags ?? */ - rq->flags = REQ_SPECIAL; - rq->special = ar; - ar->cmd = WIN_NOP; - ar->XXX_handler = tcq_nop_handler; - ar->command_type = IDE_DRIVE_TASK_NO_DATA; - - _elv_add_request(q, rq, 0, 0); - -out: -#ifdef IDE_TCQ_NIEN - ata_irq_enable(drive, 1); -#endif - - /* - * start doing stuff again - */ - q->request_fn(q); - spin_unlock_irqrestore(ch->lock, flags); - printk(KERN_DEBUG "ATA: tcq_invalidate_queue: done\n"); -} - -static void ata_tcq_irq_timeout(unsigned long data) -{ - struct ata_device *drive = (struct ata_device *) data; - struct ata_channel *ch = drive->channel; - unsigned long flags; - - printk(KERN_ERR "ATA: %s: timeout waiting for interrupt...\n", __FUNCTION__); - - spin_lock_irqsave(ch->lock, flags); - - if (test_and_set_bit(IDE_BUSY, ch->active)) - printk(KERN_ERR "ATA: %s: IRQ handler not busy\n", __FUNCTION__); - if (!ch->handler) - printk(KERN_ERR "ATA: %s: missing ISR!\n", __FUNCTION__); - - spin_unlock_irqrestore(ch->lock, flags); - - /* - * if pending commands, try service before giving up - */ - if (ata_pending_commands(drive) && !ata_status(drive, 0, SERVICE_STAT)) - if (service(drive, drive->rq) == ATA_OP_CONTINUES) - return; - - if (drive) - tcq_invalidate_queue(drive); -} - -static void __set_irq(struct ata_channel *ch, ata_handler_t *handler) -{ - /* - * always just bump the timer for now, the timeout handling will - * have to be changed to be per-command - * - * FIXME: Jens - this is broken it will interfere with - * the normal timer function on serialized drives! - */ - - ch->timer.function = ata_tcq_irq_timeout; - ch->timer.data = (unsigned long) ch->drive; - mod_timer(&ch->timer, jiffies + 5 * HZ); - ch->handler = handler; -} - -static void set_irq(struct ata_device *drive, ata_handler_t *handler) -{ - struct ata_channel *ch = drive->channel; - unsigned long flags; - - spin_lock_irqsave(ch->lock, flags); - __set_irq(ch, handler); - spin_unlock_irqrestore(ch->lock, flags); -} - -/* - * wait 400ns, then poll for busy_mask to clear from alt status - */ -#define IDE_TCQ_WAIT (10000) -static int wait_altstat(struct ata_device *drive, u8 *stat, u8 busy_mask) -{ - int i = 0; - - udelay(1); - - while ((*stat = GET_ALTSTAT()) & busy_mask) { - if (unlikely(i++ > IDE_TCQ_WAIT)) - return 1; - - udelay(10); - } - - return 0; -} - -static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *rq); - -/* - * issue SERVICE command to drive -- drive must have been selected first, - * and it must have reported a need for service (status has SERVICE_STAT set) - * - * Also, nIEN must be set as not to need protection against ide_dmaq_intr - */ -static ide_startstop_t service(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - unsigned long flags; - u8 feat, stat; - int tag; - - TCQ_PRINTK("%s: started service\n", drive->name); - - /* - * Could be called with IDE_DMA in-progress from invalidate - * handler, refuse to do anything. - */ - if (test_bit(IDE_DMA, drive->channel->active)) - return ATA_OP_FINISHED; - - /* - * need to select the right drive first... - */ - if (drive != drive->channel->drive) - ata_select(drive, 10); - -#ifdef IDE_TCQ_NIEN - ata_irq_enable(drive, 0); -#endif - /* - * send SERVICE, wait 400ns, wait for BUSY_STAT to clear - */ - OUT_BYTE(WIN_QUEUED_SERVICE, IDE_COMMAND_REG); - - if (wait_altstat(drive, &stat, BUSY_STAT)) { - ata_dump(drive, rq, "BUSY clear took too long"); - tcq_invalidate_queue(drive); - - return ATA_OP_FINISHED; - } - -#ifdef IDE_TCQ_NIEN - ata_irq_enable(drive, 1); -#endif - - /* - * FIXME, invalidate queue - */ - if (stat & ERR_STAT) { - ata_dump(drive, rq, "ERR condition"); - tcq_invalidate_queue(drive); - - return ATA_OP_FINISHED; - } - - /* - * should not happen, a buggy device could introduce loop - */ - if ((feat = GET_FEAT()) & NSEC_REL) { - drive->rq = NULL; - printk("%s: release in service\n", drive->name); - return ATA_OP_FINISHED; - } - - tag = feat >> 3; - - TCQ_PRINTK("%s: stat %x, feat %x\n", __FUNCTION__, stat, feat); - - spin_lock_irqsave(ch->lock, flags); - - rq = blk_queue_find_tag(&drive->queue, tag); - if (!rq) { - printk(KERN_ERR"%s: missing request for tag %d\n", __FUNCTION__, tag); - spin_unlock_irqrestore(ch->lock, flags); - return ATA_OP_FINISHED; - } - - drive->rq = rq; - - spin_unlock_irqrestore(ch->lock, flags); - /* - * we'll start a dma read or write, device will trigger - * interrupt to indicate end of transfer, release is not allowed - */ - TCQ_PRINTK("%s: starting command %x\n", __FUNCTION__, stat); - - return udma_tcq_start(drive, rq); -} - -static ide_startstop_t check_service(struct ata_device *drive, struct request *rq) -{ - TCQ_PRINTK("%s: %s\n", drive->name, __FUNCTION__); - - if (!ata_pending_commands(drive)) - return ATA_OP_FINISHED; - - if (!ata_status(drive, 0, SERVICE_STAT)) - return service(drive, rq); - - /* - * we have pending commands, wait for interrupt - */ - set_irq(drive, ide_dmaq_intr); - - return ATA_OP_CONTINUES; -} - -static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *rq) -{ - u8 dma_stat; - - /* - * transfer was in progress, stop DMA engine - */ - dma_stat = udma_stop(drive); - - /* - * must be end of I/O, check status and complete as necessary - */ - if (!ata_status(drive, READY_STAT, drive->bad_wstat | DRQ_STAT)) { - ata_dump(drive, rq, __FUNCTION__); - tcq_invalidate_queue(drive); - - return ATA_OP_FINISHED; - } - - if (dma_stat) - printk("%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); - - TCQ_PRINTK("%s: ending %p, tag %d\n", __FUNCTION__, rq, rq->tag); - - ata_end_request(drive, rq, !dma_stat, rq->nr_sectors); - - /* - * we completed this command, check if we can service a new command - */ - return check_service(drive, rq); -} - -/* - * Interrupt handler for queued dma operations. this can be entered for two - * reasons: - * - * 1) device has completed dma transfer - * 2) service request to start a command - * - * if the drive has an active tag, we first complete that request before - * processing any pending SERVICE. - */ -static ide_startstop_t ide_dmaq_intr(struct ata_device *drive, struct request *rq) -{ - int ok; - - ok = !ata_status(drive, 0, SERVICE_STAT); - TCQ_PRINTK("%s: stat=%x\n", __FUNCTION__, drive->status); - - /* - * If a command completion interrupt is pending, do that first and - * check service afterwards. - */ - if (rq) - return dmaq_complete(drive, rq); - - /* - * service interrupt - */ - if (ok) { - TCQ_PRINTK("%s: SERV (stat=%x)\n", __FUNCTION__, drive->status); - return service(drive, rq); - } - - printk("%s: stat=%x, not expected\n", __FUNCTION__, drive->status); - - return check_service(drive, rq); -} - -/* - * Check if the ata adapter this drive is attached to supports the - * NOP auto-poll for multiple tcq enabled drives on one channel. - */ -static int check_autopoll(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - struct ata_taskfile args; - int drives = 0, i; - - /* - * only need to probe if both drives on a channel support tcq - */ - for (i = 0; i < MAX_DRIVES; i++) - if (drive->channel->drives[i].present &&drive->type == ATA_DISK) - drives++; - - if (drives <= 1) - return 0; - - /* - * do taskfile and check ABRT bit -- intelligent adapters will not - * pass NOP with sub-code 0x01 to device, so the command will not - * fail there - */ - memset(&args, 0, sizeof(args)); - args.taskfile.feature = 0x01; - args.cmd = WIN_NOP; - ide_raw_taskfile(drive, &args, NULL); - if (args.taskfile.feature & ABRT_ERR) - return 1; - - ch->auto_poll = 1; - printk("%s: NOP Auto-poll enabled\n", ch->name); - return 0; -} - -/* - * configure the drive for tcq - */ -static int configure_tcq(struct ata_device *drive) -{ - int tcq_mask = 1 << 1 | 1 << 14; - int tcq_bits = tcq_mask | 1 << 15; - struct ata_taskfile args; - - /* - * bit 14 and 1 must be set in word 83 of the device id to indicate - * support for dma queued protocol, and bit 15 must be cleared - */ - if ((drive->id->command_set_2 & tcq_bits) ^ tcq_mask) - return -EIO; - - memset(&args, 0, sizeof(args)); - args.taskfile.feature = SETFEATURES_EN_WCACHE; - args.cmd = WIN_SETFEATURES; - if (ide_raw_taskfile(drive, &args, NULL)) { - printk("%s: failed to enable write cache\n", drive->name); - return 1; - } - - /* - * disable RELease interrupt, it's quicker to poll this after - * having sent the command opcode - */ - memset(&args, 0, sizeof(args)); - args.taskfile.feature = SETFEATURES_DIS_RI; - args.cmd = WIN_SETFEATURES; - if (ide_raw_taskfile(drive, &args, NULL)) { - printk("%s: disabling release interrupt fail\n", drive->name); - return 1; - } - -#ifdef IDE_TCQ_FIDDLE_SI - /* - * enable SERVICE interrupt - */ - memset(&args, 0, sizeof(args)); - args.taskfile.feature = SETFEATURES_EN_SI; - args.cmd = WIN_SETFEATURES; - if (ide_raw_taskfile(drive, &args, NULL)) { - printk("%s: enabling service interrupt fail\n", drive->name); - return 1; - } -#endif - - return 0; -} - -static int tcq_wait_dataphase(struct ata_device *drive) -{ - int i; - - while (!ata_status(drive, 0, BUSY_STAT)) - udelay(10); - - if (ata_status(drive, READY_STAT | DRQ_STAT, drive->bad_wstat)) - return 0; - - i = 0; - udelay(1); - while (!ata_status(drive, READY_STAT | DRQ_STAT, drive->bad_wstat)) { - ++i; - if (i > IDE_TCQ_WAIT) - return 1; - - udelay(10); - } - - return 0; -} - -/**************************************************************************** - * UDMA transfer handling functions. - */ - -/* - * Invoked from a SERVICE interrupt, command etc already known. Just need to - * start the dma engine for this tag. - */ -static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - - TCQ_PRINTK("%s: setting up queued %d\n", __FUNCTION__, rq->tag); - if (!test_bit(IDE_BUSY, ch->active)) - printk("queued_rw: IDE_BUSY not set\n"); - - if (tcq_wait_dataphase(drive)) - return ATA_OP_FINISHED; - - if (ata_start_dma(drive, rq)) - return ATA_OP_FINISHED; - - __set_irq(ch, ide_dmaq_intr); - udma_start(drive, rq); - - return ATA_OP_CONTINUES; -} - -/* - * Start a queued command from scratch. - */ -ide_startstop_t udma_tcq_init(struct ata_device *drive, struct request *rq) -{ - u8 stat; - u8 feat; - - struct ata_taskfile *args = rq->special; - - TCQ_PRINTK("%s: start tag %d\n", drive->name, rq->tag); - - /* - * set nIEN, tag start operation will enable again when - * it is safe - */ -#ifdef IDE_TCQ_NIEN - ata_irq_enable(drive, 0); -#endif - - OUT_BYTE(args->cmd, IDE_COMMAND_REG); - - if (wait_altstat(drive, &stat, BUSY_STAT)) { - ata_dump(drive, rq, "queued start"); - tcq_invalidate_queue(drive); - return ATA_OP_FINISHED; - } - -#ifdef IDE_TCQ_NIEN - ata_irq_enable(drive, 1); -#endif - - if (stat & ERR_STAT) { - ata_dump(drive, rq, "tcq_start"); - return ATA_OP_FINISHED; - } - - /* - * drive released the bus, clear active tag and - * check for service - */ - if ((feat = GET_FEAT()) & NSEC_REL) { - drive->immed_rel++; - drive->rq = NULL; - set_irq(drive, ide_dmaq_intr); - - TCQ_PRINTK("REL in queued_start\n"); - - if (!ata_status(drive, 0, SERVICE_STAT)) - return service(drive, rq); - - return ATA_OP_RELEASED; - } - - TCQ_PRINTK("IMMED in queued_start\n"); - drive->immed_comp++; - - return udma_tcq_start(drive, rq); -} - -/* - * For now assume that command list is always as big as we need and don't - * attempt to shrink it on tcq disable. - */ -int udma_tcq_enable(struct ata_device *drive, int on) -{ - int depth = drive->using_tcq ? drive->queue_depth : 0; - - /* - * disable or adjust queue depth - */ - if (!on) { - if (drive->using_tcq) - printk("%s: TCQ disabled\n", drive->name); - drive->using_tcq = 0; - return 0; - } - - if (configure_tcq(drive)) { - drive->using_tcq = 0; - return 1; - } - - /* - * enable block tagging - */ - if (!blk_queue_tagged(&drive->queue)) - blk_queue_init_tags(&drive->queue, IDE_MAX_TAG); - - /* - * check auto-poll support - */ - check_autopoll(drive); - - if (depth != drive->queue_depth) - printk("%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth); - - drive->using_tcq = 1; - return 0; -} - -/* FIXME: This should go away! */ -EXPORT_SYMBOL(udma_tcq_enable); diff -Nru a/drivers/ide/timing.h b/drivers/ide/timing.h --- a/drivers/ide/timing.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,83 +0,0 @@ -/* - * Copyright (C) 1996 Linus Torvalds, Igor Abramov, and Mark Lord - * Copyright (C) 1999-2001 Vojtech Pavlik - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define XFER_PIO_5 0x0d -#define XFER_UDMA_SLOW 0x4f - -struct ata_timing { - short mode; - short setup; /* t1 */ - short act8b; /* t2 for 8-bit io */ - short rec8b; /* t2i for 8-bit io */ - short cyc8b; /* t0 for 8-bit io */ - short active; /* t2 or tD */ - short recover; /* t2i or tK */ - short cycle; /* t0 */ - short udma; /* t2CYCTYP/2 */ -}; - -extern struct ata_timing ata_timing[]; - -#define IDE_TIMING_SETUP 0x01 -#define IDE_TIMING_ACT8B 0x02 -#define IDE_TIMING_REC8B 0x04 -#define IDE_TIMING_CYC8B 0x08 -#define IDE_TIMING_8BIT 0x0e -#define IDE_TIMING_ACTIVE 0x10 -#define IDE_TIMING_RECOVER 0x20 -#define IDE_TIMING_CYCLE 0x40 -#define IDE_TIMING_UDMA 0x80 -#define IDE_TIMING_ALL 0xff - -#define FIT(v,x,y) max_t(int,min_t(int,v,y),x) -#define ENOUGH(v,unit) (((v)-1)/(unit)+1) -#define EZ(v,unit) ((v)?ENOUGH(v,unit):0) - -/* see hpt366.c for details */ -#define XFER_UDMA_66_3 0x100 -#define XFER_UDMA_66_4 0x200 - -#define XFER_MODE 0xff0 -#define XFER_UDMA_133 0x800 -#define XFER_UDMA_100 0x400 -#define XFER_UDMA_66 0x300 -#define XFER_UDMA 0x040 -#define XFER_MWDMA 0x020 -#define XFER_SWDMA 0x010 -#define XFER_EPIO 0x001 -#define XFER_PIO 0x000 - -#define XFER_UDMA_ALL 0xf40 -#define XFER_UDMA_80W 0xf00 - -/* External interface to host chips channel timing setup. - * - * It's a bit elaborate due to the legacy we have to bear. - */ - -extern short ata_timing_mode(struct ata_device *drive, int map); -extern void ata_timing_quantize(struct ata_timing *t, struct ata_timing *q, - int T, int UT); -extern void ata_timing_merge(struct ata_timing *a, struct ata_timing *b, - struct ata_timing *m, unsigned int what); -void ata_timing_merge_8bit(struct ata_timing *t); -extern struct ata_timing* ata_timing_data(short speed); -extern int ata_timing_compute(struct ata_device *drive, - short speed, struct ata_timing *t, int T, int UT); -extern u8 ata_best_pio_mode(struct ata_device *drive); diff -Nru a/drivers/ide/trm290.c b/drivers/ide/trm290.c --- a/drivers/ide/trm290.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,340 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * linux/drivers/ide/trm290.c Version 1.02 Mar. 18, 2000 - * - * Copyright (c) 1997-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * This module provides support for the bus-master IDE DMA function - * of the Tekram TRM290 chip, used on a variety of PCI IDE add-on boards, - * including a "Precision Instruments" board. The TRM290 pre-dates - * the sff-8038 standard (ide-dma.c) by a few months, and differs - * significantly enough to warrant separate routines for some functions, - * while re-using others from ide-dma.c. - * - * EXPERIMENTAL! It works for me (a sample of one). - * - * Works reliably for me in DMA mode (READs only), - * DMA WRITEs are disabled by default (see #define below); - * - * DMA is not enabled automatically for this chipset, - * but can be turned on manually (with "hdparm -d1") at run time. - * - * I need volunteers with "spare" drives for further testing - * and development, and maybe to help figure out the peculiarities. - * Even knowing the registers (below), some things behave strangely. - */ - -#define TRM290_NO_DMA_WRITES /* DMA writes seem unreliable sometimes */ - -/* - * TRM-290 PCI-IDE2 Bus Master Chip - * ================================ - * The configuration registers are addressed in normal I/O port space - * and are used as follows: - * - * trm290_base depends on jumper settings, and is probed for by ide-dma.c - * - * trm290_base+2 when WRITTEN: chiptest register (byte, write-only) - * bit7 must always be written as "1" - * bits6-2 undefined - * bit1 1=legacy_compatible_mode, 0=native_pci_mode - * bit0 1=test_mode, 0=normal(default) - * - * trm290_base+2 when READ: status register (byte, read-only) - * bits7-2 undefined - * bit1 channel0 busmaster interrupt status 0=none, 1=asserted - * bit0 channel0 interrupt status 0=none, 1=asserted - * - * trm290_base+3 Interrupt mask register - * bits7-5 undefined - * bit4 legacy_header: 1=present, 0=absent - * bit3 channel1 busmaster interrupt status 0=none, 1=asserted (read only) - * bit2 channel1 interrupt status 0=none, 1=asserted (read only) - * bit1 channel1 interrupt mask: 1=masked, 0=unmasked(default) - * bit0 channel0 interrupt mask: 1=masked, 0=unmasked(default) - * - * trm290_base+1 "CPR" Config Pointer Register (byte) - * bit7 1=autoincrement CPR bits 2-0 after each access of CDR - * bit6 1=min. 1 wait-state posted write cycle (default), 0=0 wait-state - * bit5 0=enabled master burst access (default), 1=disable (write only) - * bit4 PCI DEVSEL# timing select: 1=medium(default), 0=fast - * bit3 0=primary IDE channel, 1=secondary IDE channel - * bits2-0 register index for accesses through CDR port - * - * trm290_base+0 "CDR" Config Data Register (word) - * two sets of seven config registers, - * selected by CPR bit 3 (channel) and CPR bits 2-0 (index 0 to 6), - * each index defined below: - * - * Index-0 Base address register for command block (word) - * defaults: 0x1f0 for primary, 0x170 for secondary - * - * Index-1 general config register (byte) - * bit7 1=DMA enable, 0=DMA disable - * bit6 1=activate IDE_RESET, 0=no action (default) - * bit5 1=enable IORDY, 0=disable IORDY (default) - * bit4 0=16-bit data port(default), 1=8-bit (XT) data port - * bit3 interrupt polarity: 1=active_low, 0=active_high(default) - * bit2 power-saving-mode(?): 1=enable, 0=disable(default) (write only) - * bit1 bus_master_mode(?): 1=enable, 0=disable(default) - * bit0 enable_io_ports: 1=enable(default), 0=disable - * - * Index-2 read-ahead counter preload bits 0-7 (byte, write only) - * bits7-0 bits7-0 of readahead count - * - * Index-3 read-ahead config register (byte, write only) - * bit7 1=enable_readahead, 0=disable_readahead(default) - * bit6 1=clear_FIFO, 0=no_action - * bit5 undefined - * bit4 mode4 timing control: 1=enable, 0=disable(default) - * bit3 undefined - * bit2 undefined - * bits1-0 bits9-8 of read-ahead count - * - * Index-4 base address register for control block (word) - * defaults: 0x3f6 for primary, 0x376 for secondary - * - * Index-5 data port timings (shared by both drives) (byte) - * standard PCI "clk" (clock) counts, default value = 0xf5 - * - * bits7-6 setup time: 00=1clk, 01=2clk, 10=3clk, 11=4clk - * bits5-3 hold time: 000=1clk, 001=2clk, 010=3clk, - * 011=4clk, 100=5clk, 101=6clk, - * 110=8clk, 111=12clk - * bits2-0 active time: 000=2clk, 001=3clk, 010=4clk, - * 011=5clk, 100=6clk, 101=8clk, - * 110=12clk, 111=16clk - * - * Index-6 command/control port timings (shared by both drives) (byte) - * same layout as Index-5, default value = 0xde - * - * Suggested CDR programming for PIO mode0 (600ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0xf5,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0xf5,0xde ; secondary - * - * Suggested CDR programming for PIO mode3 (180ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0x09,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0x09,0xde ; secondary - * - * Suggested CDR programming for PIO mode4 (120ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0x00,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0x00,0xde ; secondary - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "pcihost.h" - -static void trm290_prepare_drive(struct ata_device *drive, unsigned int use_dma) -{ - struct ata_channel *hwif = drive->channel; - unsigned int reg; - unsigned long flags; - - /* select PIO or DMA */ - reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82); - - local_irq_save(flags); - - if (reg != hwif->select_data) { - hwif->select_data = reg; - outb(0x51|(hwif->unit<<3), hwif->config_data+1); /* set PIO/DMA */ - outw(reg & 0xff, hwif->config_data); - } - - /* enable IRQ if not probing */ - if (drive->present) { - reg = inw(hwif->config_data+3) & 0x13; - reg &= ~(1 << hwif->unit); - outw(reg, hwif->config_data+3); - } - - local_irq_restore(flags); -} - -static void trm290_selectproc(struct ata_device *drive) -{ - trm290_prepare_drive(drive, drive->using_dma); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static void trm290_udma_start(struct ata_device *drive, struct request *__rq) -{ - /* Nothing to be done here. */ -} - -static int trm290_udma_stop(struct ata_device *drive) -{ - struct ata_channel *ch = drive->channel; - - udma_destroy_table(ch); /* purge DMA mappings */ - - return (inw(ch->dma_base + 2) != 0x00ff); -} - -static int trm290_udma_init(struct ata_device *drive, struct request *rq) -{ - struct ata_channel *ch = drive->channel; - unsigned int count; - int writing; - int reading; - - - if (rq_data_dir(rq) == READ) - reading = 1; - else - reading = 0; - - if (!reading) { - reading = 0; - writing = 1; -#ifdef TRM290_NO_DMA_WRITES - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - - return ATA_OP_FINISHED; -#endif - } else { - reading = 2; - writing = 0; - } - - if (!(count = udma_new_table(drive, rq))) { - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return ATA_OP_FINISHED; /* try PIO instead of DMA */ - } - - trm290_prepare_drive(drive, 1); /* select DMA xfer */ - - outl(ch->dmatable_dma|reading|writing, ch->dma_base); - outw((count * 2) - 1, ch->dma_base+2); /* start DMA */ - - if (drive->type == ATA_DISK) { - ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); - outb(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - } - - return ATA_OP_CONTINUES; -} - -static int trm290_udma_irq_status(struct ata_device *drive) -{ - return (inw(drive->channel->dma_base + 2) == 0x00ff); -} - -static int trm290_udma_setup(struct ata_device *drive, int map) -{ - return udma_pci_setup(drive, map); -} -#endif - -/* - * Invoked from ide-dma.c at boot time. - */ -static void __init trm290_init_channel(struct ata_channel *hwif) -{ - unsigned int cfgbase = 0; - unsigned long flags; - u8 reg; - struct pci_dev *dev = hwif->pci_dev; - - hwif->chipset = ide_trm290; - hwif->seg_boundary_mask = 0xffffffff; - cfgbase = pci_resource_start(dev, 4); - if ((dev->class & 5) && cfgbase) - { - hwif->config_data = cfgbase; - printk("TRM290: chip config base at 0x%04lx\n", hwif->config_data); - } else { - hwif->config_data = 0x3df0; - printk("TRM290: using default config base at 0x%04lx\n", hwif->config_data); - } - - local_irq_save(flags); - /* put config reg into first byte of hwif->select_data */ - outb(0x51|(hwif->unit<<3), hwif->config_data+1); - hwif->select_data = 0x21; /* select PIO as default */ - outb(hwif->select_data, hwif->config_data); - reg = inb(hwif->config_data+3); /* get IRQ info */ - reg = (reg & 0x10) | 0x03; /* mask IRQs for both ports */ - outb(reg, hwif->config_data+3); - local_irq_restore(flags); - - if ((reg & 0x10)) - hwif->irq = hwif->unit ? 15 : 14; /* legacy mode */ - else { - static int primary_irq = 0; - - /* Ugly way to let the primary and secondary channel on the - * chip use the same IRQ line. - */ - - if (hwif->unit == ATA_PRIMARY) - primary_irq = hwif->irq; - else if (!hwif->irq) - hwif->irq = primary_irq; - } - - ata_init_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000)); - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->udma_start = trm290_udma_start; - hwif->udma_stop = trm290_udma_stop; - hwif->udma_init = trm290_udma_init; - hwif->udma_irq_status = trm290_udma_irq_status; - hwif->udma_setup = trm290_udma_setup; -#endif - - hwif->selectproc = &trm290_selectproc; -#if 1 - { - /* - * My trm290-based card doesn't seem to work with all possible values - * for the control basereg, so this kludge ensures that we use only - * values that are known to work. Ugh. -ml - */ - unsigned short old, compat = hwif->unit ? 0x374 : 0x3f4; - static unsigned short next_offset = 0; - - outb(0x54|(hwif->unit<<3), hwif->config_data+1); - old = inw(hwif->config_data) & ~1; - if (old != compat && inb(old+2) == 0xff) { - compat += (next_offset += 0x400); /* leave lower 10 bits untouched */ - hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2; - outw(compat|1, hwif->config_data); - printk("%s: control basereg workaround: old=0x%04x, new=0x%04x\n", hwif->name, old, inw(hwif->config_data) & ~1); - } - } -#endif -} - -/* module data table */ -static struct ata_pci_device chipset __initdata = { - .vendor = PCI_VENDOR_ID_TEKRAM, - .device = PCI_DEVICE_ID_TEKRAM_DC290, - .init_channel = trm290_init_channel, - .bootable = ON_BOARD -}; - -int __init init_trm290(void) -{ - ata_register_chipset(&chipset); - - return 0; -} diff -Nru a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c --- a/drivers/ide/umc8672.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,150 +0,0 @@ -/* - * linux/drivers/ide/umc8672.c Version 0.05 Jul 31, 1996 - * - * Copyright (C) 1995-1996 Linus Torvalds & author (see below) - */ - -/* - * Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien) - * - * This file provides support for the advanced features - * of the UMC 8672 IDE interface. - * - * Version 0.01 Initial version, hacked out of ide.c, - * and #include'd rather than compiled separately. - * This will get cleaned up in a subsequent release. - * - * Version 0.02 now configs/compiles separate from ide.c -ml - * Version 0.03 enhanced auto-tune, fix display bug - * Version 0.05 replace sti() with restore_flags() -ml - * add detection of possible race condition -ml - */ - -/* - * VLB Controller Support from - * Wolfram Podien - * Rohoefe 3 - * D28832 Achim - * Germany - * - * To enable UMC8672 support there must a lilo line like - * append="ide0=umc8672"... - * To set the speed according to the abilities of the hardware there must be a - * line like - * #define UMC_DRIVE0 11 - * in the beginning of the driver, which sets the speed of drive 0 to 11 (there - * are some lines present). 0 - 11 are allowed speed values. These values are - * the results from the DOS speed test program supplied from UMC. 11 is the - * highest speed (about PIO mode 3) - */ -#define REALLY_SLOW_IO /* some systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" - -/* - * Default speeds. These can be changed with "auto-tune" and/or hdparm. - */ -#define UMC_DRIVE0 1 /* DOS measured drive speeds */ -#define UMC_DRIVE1 1 /* 0 to 11 allowed */ -#define UMC_DRIVE2 1 /* 11 = Fastest Speed */ -#define UMC_DRIVE3 1 /* In case of crash reduce speed */ - -static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; -static const u8 pio_to_umc[5] = {0,3,7,10,11}; /* rough guesses */ - -/* 0 1 2 3 4 5 6 7 8 9 10 11 */ -static const u8 speedtab[3][12] = { - {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}}; - -static void out_umc (char port,char wert) -{ - outb_p (port,0x108); - outb_p (wert,0x109); -} - -static inline u8 in_umc (char port) -{ - outb_p (port,0x108); - return inb_p (0x109); -} - -static void umc_set_speeds(u8 speeds[]) -{ - int i, tmp; - - outb_p (0x5A,0x108); /* enable umc */ - - out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); - out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); - tmp = 0; - for (i = 3; i >= 0; i--) { - tmp = (tmp << 2) | speedtab[1][speeds[i]]; - } - out_umc (0xdc,tmp); - for (i = 0;i < 4; i++) { - out_umc (0xd0+i,speedtab[2][speeds[i]]); - out_umc (0xd8+i,speedtab[2][speeds[i]]); - } - outb_p (0xa5,0x108); /* disable umc */ - - printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", - speeds[0], speeds[1], speeds[2], speeds[3]); -} - -static void tune_umc(struct ata_device *drive, u8 pio) -{ - if (pio == 255) - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; - else - pio = min_t(u8, pio, 4); - - printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); - current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; - umc_set_speeds (current_speeds); -} - -void __init init_umc8672(void) /* called from ide.c */ -{ - unsigned long flags; - - local_irq_save(flags); - if (!request_region(0x108, 2, "umc8672")) { - local_irq_restore(flags); - printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n"); - return; - } - outb_p (0x5A,0x108); /* enable umc */ - if (in_umc (0xd5) != 0xa0) - { - local_irq_restore(flags); - release_region(0x108, 2); - printk ("umc8672: not found\n"); - return; - } - outb_p (0xa5,0x108); /* disable umc */ - - umc_set_speeds(current_speeds); - local_irq_restore(flags); - - ide_hwifs[0].chipset = ide_umc8672; - ide_hwifs[1].chipset = ide_umc8672; - ide_hwifs[0].tuneproc = tune_umc; - ide_hwifs[1].tuneproc = tune_umc; - ide_hwifs[0].unit = ATA_PRIMARY; - ide_hwifs[1].unit = ATA_SECONDARY; -} diff -Nru a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c --- a/drivers/ide/via82cxxx.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,411 +0,0 @@ -/**** vi:set ts=8 sts=8 sw=8:************************************************ - * - * $Id: via82cxxx.c,v 3.34 2002/02/12 11:26:11 vojtech Exp $ - * - * Copyright (c) 2000-2001 Vojtech Pavlik - * - * Based on the work of: - * Michel Aubry - * Jeff Garzik - * Andre Hedrick - */ - -/* - * VIA IDE driver for Linux. Supports - * - * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, - * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a - * - * southbridges, which can be found in - * - * VIA Apollo Master, VP, VP2, VP2/97, VP3, VPX, VPX/97, MVP3, MVP4, P6, Pro, - * ProII, ProPlus, Pro133, Pro133+, Pro133A, Pro133A Dual, Pro133T, Pro133Z, - * PLE133, PLE133T, Pro266, Pro266T, ProP4X266, PM601, PM133, PN133, PL133T, - * PX266, PM266, KX133, KT133, KT133A, KT133E, KLE133, KT266, KX266, KM133, - * KM133A, KL133, KN133, KM266 - * PC-Chips VXPro, VXPro+, VXTwo, TXPro-III, TXPro-AGP, AGPPro, ViaGra, BXToo, - * BXTel, BXpert - * AMD 640, 640 AGP, 750 IronGate, 760, 760MP - * ETEQ 6618, 6628, 6629, 6638 - * Micron Samurai - * - * chipsets. Supports - * - * PIO 0-5, MWDMA 0-2, SWDMA 0-2 and UDMA 0-6 - * - * (this includes UDMA33, 66, 100 and 133) modes. UDMA66 and higher modes are - * autoenabled only in case the BIOS has detected a 80 wire cable. To ignore - * the BIOS data and assume the cable is present, use 'ide0=ata66' or - * 'ide1=ata66' on the kernel command line. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to , or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "timing.h" -#include "pcihost.h" - -#define VIA_IDE_ENABLE 0x40 -#define VIA_IDE_CONFIG 0x41 -#define VIA_FIFO_CONFIG 0x43 -#define VIA_MISC_1 0x44 -#define VIA_MISC_2 0x45 -#define VIA_MISC_3 0x46 -#define VIA_DRIVE_TIMING 0x48 -#define VIA_8BIT_TIMING 0x4e -#define VIA_ADDRESS_SETUP 0x4c -#define VIA_UDMA_TIMING 0x50 - -#define VIA_UDMA 0x007 -#define VIA_UDMA_NONE 0x000 -#define VIA_UDMA_33 0x001 -#define VIA_UDMA_66 0x002 -#define VIA_UDMA_100 0x003 -#define VIA_UDMA_133 0x004 -#define VIA_BAD_PREQ 0x010 /* Crashes if PREQ# till DDACK# set */ -#define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */ -#define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */ -#define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */ -#define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */ - -/* - * VIA SouthBridge chips. - */ - -static struct via_isa_bridge { - char *name; - unsigned short id; - unsigned char rev_min; - unsigned char rev_max; - unsigned short flags; -} via_isa_bridges [] __initdata = { -#ifdef FUTURE_BRIDGES - { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 }, - { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 }, -#endif - { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 }, - { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, - { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, - { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, - { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 }, - { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO }, - { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK }, - { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, - { NULL } -}; - -static struct via_isa_bridge *via_config; -static unsigned char via_enabled; -static unsigned int via_80w; -static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; - -/* - * via_set_speed() writes timing values to the chipset registers - */ - -static void via_set_speed(struct pci_dev *dev, unsigned char dn, struct ata_timing *timing) -{ - unsigned char t; - - pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); - t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); - pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); - - pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)), - ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1)); - - pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn), - ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1)); - - switch (via_config->flags & VIA_UDMA) { - case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; - case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break; - case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break; - case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break; - default: return; - } - - pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t); -} - -/* - * via_set_drive() computes timing values configures the drive and - * the chipset to a desired transfer mode. It also can be called - * by upper layers. - */ - -static int via_set_drive(struct ata_device *drive, unsigned char speed) -{ - struct ata_device *peer = drive->channel->drives + (~drive->dn & 1); - struct ata_timing t, p; - unsigned int T, UT; - - if (speed != XFER_PIO_SLOW && speed != drive->current_speed) - if (ide_config_drive_speed(drive, speed)) - printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", - drive->dn >> 1, drive->dn & 1); - - T = 1000000000 / system_bus_speed; - - switch (via_config->flags & VIA_UDMA) { - case VIA_UDMA_33: UT = T; break; - case VIA_UDMA_66: UT = T/2; break; - case VIA_UDMA_100: UT = T/3; break; - case VIA_UDMA_133: UT = T/4; break; - default: UT = T; - } - - ata_timing_compute(drive, speed, &t, T, UT); - - if (peer->present) { - ata_timing_compute(peer, peer->current_speed, &p, T, UT); - ata_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); - } - - via_set_speed(drive->channel->pci_dev, drive->dn, &t); - - return 0; -} - -/* - * via82cxxx_tune_drive() is a callback from upper layers for - * PIO-only tuning. - */ - -static void via82cxxx_tune_drive(struct ata_device *drive, unsigned char pio) -{ - if (!((via_enabled >> drive->channel->unit) & 1)) - return; - - if (pio == 255) { - via_set_drive(drive, ata_timing_mode(drive, XFER_PIO | XFER_EPIO)); - return; - } - - via_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int __init via_modes_map(struct ata_channel *ch) -{ - short w80 = ch->udma_four; - int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA | - (via_config->flags & VIA_UDMA ? XFER_UDMA : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0); - - return map; -} -#endif - -/* - * The initialization callback. Here we determine the IDE chip type - * and initialize its drive independent registers. - */ - -static unsigned int __init via82cxxx_init_chipset(struct pci_dev *dev) -{ - struct pci_dev *isa = NULL; - unsigned char t, v; - unsigned int u; - int i; - -/* - * Find the ISA bridge to see how good the IDE is. - */ - - for (via_config = via_isa_bridges; via_config->id; via_config++) - if ((isa = pci_find_device(PCI_VENDOR_ID_VIA + - !!(via_config->flags & VIA_BAD_ID), via_config->id, NULL))) { - - pci_read_config_byte(isa, PCI_REVISION_ID, &t); - if (t >= via_config->rev_min && t <= via_config->rev_max) - break; - } - - if (!via_config->id) { - printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, contact Vojtech Pavlik \n"); - return -ENODEV; - } - -/* - * Check 80-wire cable presence and setup Clk66. - */ - - switch (via_config->flags & VIA_UDMA) { - - case VIA_UDMA_66: - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Enable Clk66 */ - pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008); - for (i = 24; i >= 0; i -= 8) - if (((u >> (i & 16)) & 8) && ((u >> i) & 0x20) && (((u >> i) & 7) < 2)) - via_80w |= (1 << (1 - (i >> 4))); /* 2x PCI clock and UDMA w/ < 3T/cycle */ - break; - - case VIA_UDMA_100: - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 4))) - via_80w |= (1 << (1 - (i >> 4))); /* BIOS 80-wire bit or UDMA w/ < 60ns/cycle */ - break; - - case VIA_UDMA_133: - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 8))) - via_80w |= (1 << (1 - (i >> 4))); /* BIOS 80-wire bit or UDMA w/ < 60ns/cycle */ - break; - - } - - if (via_config->flags & VIA_BAD_CLK66) { /* Disable Clk66 */ - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Would cause trouble on 596a and 686 */ - pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); - } - -/* - * Check whether interfaces are enabled. - */ - - pci_read_config_byte(dev, VIA_IDE_ENABLE, &v); - via_enabled = ((v & 1) ? 2 : 0) | ((v & 2) ? 1 : 0); - -/* - * Set up FIFO sizes and thresholds. - */ - - pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t); - - if (via_config->flags & VIA_BAD_PREQ) /* Disable PREQ# till DDACK# */ - t &= 0x7f; /* Would crash on 586b rev 41 */ - - if (via_config->flags & VIA_SET_FIFO) { /* Fix FIFO split between channels */ - t &= (t & 0x9f); - switch (via_enabled) { - case 1: t |= 0x00; break; /* 16 on primary */ - case 2: t |= 0x60; break; /* 16 on secondary */ - case 3: t |= 0x20; break; /* 8 pri 8 sec */ - } - } - - pci_write_config_byte(dev, VIA_FIFO_CONFIG, t); - -/* - * Print the boot message. - */ - - pci_read_config_byte(isa, PCI_REVISION_ID, &t); - printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) ATA %s controller on PCI %s\n", - via_config->name, t, via_dma[via_config->flags & VIA_UDMA], dev->slot_name); - - return 0; -} - -static unsigned int __init via82cxxx_ata66_check(struct ata_channel *hwif) -{ - return ((via_enabled & via_80w) >> hwif->unit) & 1; -} - -static void __init via82cxxx_init_channel(struct ata_channel *hwif) -{ - int i; - - hwif->udma_four = via82cxxx_ata66_check(hwif); - - hwif->tuneproc = &via82cxxx_tune_drive; - hwif->speedproc = &via_set_drive; - hwif->io_32bit = 1; - - hwif->unmask = (via_config->flags & VIA_NO_UNMASK) ? 0 : 1; - for (i = 0; i < 2; i++) { - hwif->drives[i].autotune = 1; - hwif->drives[i].dn = hwif->unit * 2 + i; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->highmem = 1; - hwif->modes_map = via_modes_map(hwif); - hwif->udma_setup = udma_generic_setup; - } -#endif -} - -/* - * We allow the BM-DMA driver to only work on enabled interfaces. - */ - -static void __init via82cxxx_init_dma(struct ata_channel *hwif, unsigned long dmabase) -{ - if ((via_enabled >> hwif->unit) & 1) - ata_init_dma(hwif, dmabase); -} - -/* module data table */ -static struct ata_pci_device chipsets[] __initdata = { - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C576_1, - .init_chipset = via82cxxx_init_chipset, - .init_channel = via82cxxx_init_channel, - .init_dma = via82cxxx_init_dma, - .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, - .bootable = ON_BOARD, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C586_1, - .init_chipset = via82cxxx_init_chipset, - .init_channel = via82cxxx_init_channel, - .init_dma = via82cxxx_init_dma, - .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, - .bootable = ON_BOARD, - }, -}; - -int __init init_via82cxxx(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(chipsets); ++i) - ata_register_chipset(&chipsets[i]); - - return 0; -} diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,786 +0,0 @@ -/* - * Copyright (C) 1996 - 1999 Gadi Oxman - * - * Emulation of a SCSI host adapter for IDE ATAPI devices. - * - * With this driver, one can use the Linux SCSI drivers instead of the - * native IDE ATAPI drivers. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "scsi.h" -#include "hosts.h" -#include "sd.h" - -/* FIXME: Right now we always register a single scsi host for every single - * device. We should be just registering a single scsi host per ATA host chip - * and deal properly with channels! The reentrancy efforts are therefore not - * quite right done now. - */ - -/* - * SCSI command transformation layer - */ -#define IDESCSI_TRANSFORM 0 /* Enable/Disable transformation */ -#define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ - -/* - * Log flags - */ -#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ - -typedef struct { - struct ata_device *drive; - struct atapi_packet_command *pc; /* Current packet command */ - unsigned long flags; /* Status/Action flags */ - unsigned long transform; /* SCSI cmd translation layer */ - unsigned long log; /* log flags */ -} idescsi_scsi_t; - -/* - * Per ATAPI device status bits. - */ -#define IDESCSI_DRQ_INTERRUPT 0 /* DRQ interrupt device */ - -/* - * ide-scsi requests. - */ -#define IDESCSI_PC_RQ 90 - -/* - * Bits of the interrupt reason register. - */ -#define IDESCSI_IREASON_COD 0x1 /* Information transferred is command */ -#define IDESCSI_IREASON_IO 0x2 /* The device requests us to read */ - -/* - * PIO data transfer routines using the scatter gather table. - */ -static void idescsi_input_buffers(struct ata_device *drive, struct atapi_packet_command *pc, unsigned int bcount) -{ - int count; - char *buf; - - while (bcount) { - if (pc->s.sg - (struct scatterlist *) pc->s.scsi_cmd->request_buffer > pc->s.scsi_cmd->use_sg) { - printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); - atapi_discard_data(drive, bcount); - return; - } - count = min(pc->s.sg->length - pc->s.b_count, bcount); - buf = page_address(pc->s.sg->page) + pc->s.sg->offset; - atapi_read(drive, buf + pc->s.b_count, count); - bcount -= count; pc->s.b_count += count; - if (pc->s.b_count == pc->s.sg->length) { - pc->s.sg++; - pc->s.b_count = 0; - } - } -} - -static void idescsi_output_buffers(struct ata_device *drive, struct atapi_packet_command *pc, unsigned int bcount) -{ - int count; - char *buf; - - while (bcount) { - if (pc->s.sg - (struct scatterlist *) pc->s.scsi_cmd->request_buffer > pc->s.scsi_cmd->use_sg) { - printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); - atapi_write_zeros(drive, bcount); - return; - } - count = min(pc->s.sg->length - pc->s.b_count, bcount); - buf = page_address(pc->s.sg->page) + pc->s.sg->offset; - atapi_write(drive, buf + pc->s.b_count, count); - bcount -= count; pc->s.b_count += count; - if (pc->s.b_count == pc->s.sg->length) { - pc->s.sg++; - pc->s.b_count = 0; - } - } -} - -/* - * Most of the SCSI commands are supported directly by ATAPI devices. - * idescsi_transform_pc handles the few exceptions. - */ -static inline void idescsi_transform_pc1(struct ata_device *drive, struct atapi_packet_command *pc) -{ - u8 *c = pc->c; - char *scsi_buf = pc->buffer; - u8 *sc = pc->s.scsi_cmd->cmnd; - char *atapi_buf; - - if (!test_bit(PC_TRANSFORM, &pc->flags)) - return; - if (drive->type == ATA_ROM || drive->type == ATA_MOD) { - if (c[0] == READ_6 || c[0] == WRITE_6) { - c[8] = c[4]; c[5] = c[3]; c[4] = c[2]; - c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0; - c[0] += (READ_10 - READ_6); - } - if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { - if (!scsi_buf) - return; - if ((atapi_buf = kmalloc(pc->buffer_size + 4, GFP_ATOMIC)) == NULL) - return; - memset(atapi_buf, 0, pc->buffer_size + 4); - memset (c, 0, 12); - c[0] = sc[0] | 0x40; c[1] = sc[1]; c[2] = sc[2]; - c[8] = sc[4] + 4; c[9] = sc[5]; - if (sc[4] + 4 > 255) - c[7] = sc[4] + 4 - 255; - if (c[0] == MODE_SELECT_10) { - atapi_buf[1] = scsi_buf[0]; /* Mode data length */ - atapi_buf[2] = scsi_buf[1]; /* Medium type */ - atapi_buf[3] = scsi_buf[2]; /* Device specific parameter */ - atapi_buf[7] = scsi_buf[3]; /* Block descriptor length */ - memcpy(atapi_buf + 8, scsi_buf + 4, pc->buffer_size - 4); - } - pc->buffer = atapi_buf; - pc->request_transfer += 4; - pc->buffer_size += 4; - } - } -} - -static inline void idescsi_transform_pc2(struct ata_device *drive, struct atapi_packet_command *pc) -{ - u8 *atapi_buf = pc->buffer; - u8 *sc = pc->s.scsi_cmd->cmnd; - u8 *scsi_buf = pc->s.scsi_cmd->request_buffer; - - if (!test_bit(PC_TRANSFORM, &pc->flags)) - return; - if (drive->type == ATA_ROM || drive->type == ATA_MOD) { - if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) { - scsi_buf[0] = atapi_buf[1]; /* Mode data length */ - scsi_buf[1] = atapi_buf[2]; /* Medium type */ - scsi_buf[2] = atapi_buf[3]; /* Device specific parameter */ - scsi_buf[3] = atapi_buf[7]; /* Block descriptor length */ - memcpy(scsi_buf + 4, atapi_buf + 8, pc->request_transfer - 8); - } - if (pc->c[0] == INQUIRY) { - scsi_buf[2] |= 2; /* ansi_revision */ - scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; /* response data format */ - } - } - if (atapi_buf && atapi_buf != scsi_buf) - kfree(atapi_buf); -} - -static inline void idescsi_free_bio(struct bio *bio) -{ - struct bio *bhp; - - while (bio) { - bhp = bio; - bio = bio->bi_next; - bio_put(bhp); - } -} - -static void hexdump(u8 *x, int len) -{ - int i; - - printk("[ "); - for (i = 0; i < len; i++) - printk("%x ", x[i]); - printk("]\n"); -} - -static inline idescsi_scsi_t *idescsi_private(struct Scsi_Host *host) -{ - return (idescsi_scsi_t*) &host[1]; -} - -static int idescsi_end_request(struct ata_device *drive, struct request *rq, int uptodate) -{ - unsigned long flags; - struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); - struct atapi_packet_command *pc = (struct atapi_packet_command *) rq->special; - int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); - u8 *scsi_buf; - - if (!(rq->flags & REQ_PC)) { - ata_end_request(drive, rq, uptodate, 0); - return 0; - } - - spin_lock_irqsave(drive->channel->lock, flags); - - blkdev_dequeue_request(rq); - drive->rq = NULL; - end_that_request_last(rq); - - spin_unlock_irqrestore(drive->channel->lock, flags); - - if (rq->errors >= ERROR_MAX) { - pc->s.scsi_cmd->result = DID_ERROR << 16; - if (log) - printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->s.scsi_cmd->serial_number); - } else if (rq->errors) { - pc->s.scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); - if (log) - printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->s.scsi_cmd->serial_number); - } else { - pc->s.scsi_cmd->result = DID_OK << 16; - idescsi_transform_pc2 (drive, pc); - if (log) { - printk ("ide-scsi: %s: suc %lu", drive->name, pc->s.scsi_cmd->serial_number); - if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) { - printk(", rst = "); - scsi_buf = pc->s.scsi_cmd->request_buffer; - hexdump(scsi_buf, min(16U, pc->s.scsi_cmd->request_bufflen)); - } else printk("\n"); - } - } - host = pc->s.scsi_cmd->host; - pc->s.done(pc->s.scsi_cmd); - idescsi_free_bio(rq->bio); - kfree(pc); kfree(rq); - scsi->pc = NULL; - - return 0; -} - -static inline unsigned long get_timeout(struct atapi_packet_command *pc) -{ - return max((unsigned long) WAIT_CMD, pc->s.timeout - jiffies); -} - -/* - * Our interrupt handler. - */ -static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request *rq) -{ - struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); - u8 ireason; - int bcount; - struct atapi_packet_command *pc=scsi->pc; - unsigned int temp; - -#ifdef DEBUG - printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n"); -#endif - - if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { -#ifdef DEBUG - printk ("ide-scsi: %s: DMA complete\n", drive->name); -#endif - pc->actually_transferred=pc->request_transfer; - udma_stop(drive); - } - - /* Clear the interrupt */ - if (ata_status(drive, 0, DRQ_STAT)) { /* No more interrupts */ - if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) - printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); - local_irq_enable(); - if (drive->status & ERR_STAT) - rq->errors++; - idescsi_end_request(drive, rq, 1); - - return ATA_OP_FINISHED; - } - bcount = IN_BYTE (IDE_BCOUNTH_REG) << 8 | IN_BYTE (IDE_BCOUNTL_REG); - ireason = IN_BYTE (IDE_IREASON_REG); - - if (ireason & IDESCSI_IREASON_COD) { - printk (KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n"); - return ATA_OP_FINISHED; - } - if (ireason & IDESCSI_IREASON_IO) { - temp = pc->actually_transferred + bcount; - if ( temp > pc->request_transfer) { - if (temp > pc->buffer_size) { - printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n"); - temp = pc->buffer_size - pc->actually_transferred; - if (temp) { - clear_bit(PC_WRITING, &pc->flags); - if (pc->s.sg) - idescsi_input_buffers(drive, pc, temp); - else - atapi_read(drive, pc->current_position, temp); - printk(KERN_ERR "ide-scsi: transferred %d of %d bytes\n", temp, bcount); - } - pc->actually_transferred += temp; - pc->current_position += temp; - atapi_discard_data(drive,bcount - temp); - - ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); - - return ATA_OP_CONTINUES; - } -#ifdef DEBUG - printk (KERN_NOTICE "ide-scsi: The scsi wants to send us more data than expected - allowing transfer\n"); -#endif - } - } - if (ireason & IDESCSI_IREASON_IO) { - clear_bit(PC_WRITING, &pc->flags); - if (pc->s.sg) - idescsi_input_buffers (drive, pc, bcount); - else - atapi_read(drive,pc->current_position,bcount); - } else { - set_bit(PC_WRITING, &pc->flags); - if (pc->s.sg) - idescsi_output_buffers (drive, pc, bcount); - else - atapi_write(drive,pc->current_position,bcount); - } - pc->actually_transferred+=bcount; /* Update the current position */ - pc->current_position+=bcount; - - /* And set the interrupt handler again */ - ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); - - return ATA_OP_CONTINUES; -} - -static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct request *rq) -{ - struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); - struct atapi_packet_command *pc = scsi->pc; - u8 ireason; - int ret; - - ret = ata_status_poll(drive, DRQ_STAT, BUSY_STAT, - WAIT_READY, rq); - if (ret != ATA_OP_READY) { - printk (KERN_ERR "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted\n"); - - return ret; - } - - ireason = IN_BYTE(IDE_IREASON_REG); - - if ((ireason & (IDESCSI_IREASON_IO | IDESCSI_IREASON_COD)) != IDESCSI_IREASON_COD) { - printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n"); - ret = ATA_OP_FINISHED; - } else { - ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); - atapi_write(drive, scsi->pc->c, 12); - ret = ATA_OP_CONTINUES; - } - - return ret; -} - -/* - * Issue a packet command - */ -static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request *rq, - struct atapi_packet_command *pc) -{ - struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); - int bcount; - int dma_ok = 0; - - scsi->pc=pc; /* Set the current packet command */ - pc->actually_transferred=0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; - bcount = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */ - - if (drive->using_dma && rq->bio) - dma_ok = udma_init(drive, rq); - - ata_select(drive, 10); - ata_irq_enable(drive, 1); - OUT_BYTE(dma_ok,IDE_FEATURE_REG); - OUT_BYTE(bcount >> 8,IDE_BCOUNTH_REG); - OUT_BYTE(bcount & 0xff,IDE_BCOUNTL_REG); - - if (dma_ok) { - set_bit(PC_DMA_IN_PROGRESS, &pc->flags); - udma_start(drive, rq); - } - if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { - ata_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL); - - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); - return ATA_OP_CONTINUES; - } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); - return idescsi_transfer_pc(drive, rq); - } -} - -/* - * This is our request handling function. - */ -static ide_startstop_t idescsi_do_request(struct ata_device *drive, struct request *rq, sector_t block) -{ - int ret; - -#ifdef DEBUG - printk(KERN_INFO "rq_status: %d, cmd: %d, errors: %d\n", - rq->rq_status, - (unsigned int) - rq->cmd, - rq->errors); - printk(KERN_INFO "sector: %lu, nr_sectors: %lu, current_nr_sectors: %lu\n", - rq->sector, - rq->nr_sectors, - rq->current_nr_sectors); -#endif - - if (rq->flags & REQ_PC) { - ret = idescsi_issue_pc(drive, rq, (struct atapi_packet_command *) rq->special); - } else { - blk_dump_rq_flags(rq, "ide-scsi: unsup command"); - idescsi_end_request(drive, rq, 0); - ret = ATA_OP_FINISHED; - } - - return ret; -} - -static int idescsi_open(struct inode *inode, struct file *filp, struct ata_device *drive) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static void idescsi_release(struct inode *inode, struct file *filp, struct ata_device *drive) -{ - MOD_DEC_USE_COUNT; -} - -static Scsi_Host_Template template; -static int idescsi_cleanup (struct ata_device *drive) -{ - if (ata_unregister_device(drive)) - return 1; - scsi_unregister_host(&template); - - return 0; -} - -static void idescsi_revalidate(struct ata_device *_dummy) -{ - /* The partition information will be handled by the SCSI layer. - */ -} - -static void idescsi_attach(struct ata_device *drive); - -/* - * IDE subdriver functions, registered with ide.c - */ -static struct ata_operations ata_ops = { - owner: THIS_MODULE, - attach: idescsi_attach, - cleanup: idescsi_cleanup, - do_request: idescsi_do_request, - end_request: idescsi_end_request, - open: idescsi_open, - release: idescsi_release, - revalidate: idescsi_revalidate, -}; - -static int idescsi_detect(Scsi_Host_Template *host_template) -{ - return register_ata_driver(&ata_ops); -} - -static const char *idescsi_info(struct Scsi_Host *host) -{ - static const char *msg = "SCSI host adapter emulation for ATAPI devices"; - - return msg; -} - -static int idescsi_ioctl(Scsi_Device *dev, int cmd, void *arg) -{ - idescsi_scsi_t *scsi = idescsi_private(dev->host); - - if (cmd == SG_SET_TRANSFORM) { - if (arg) - set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); - else - clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); - return 0; - } else if (cmd == SG_GET_TRANSFORM) - return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int *) arg); - - return -EINVAL; -} - -static inline struct bio *idescsi_kmalloc_bio(int count) -{ - struct bio *bh, *bhp, *first_bh; - - if ((first_bh = bhp = bh = bio_alloc(GFP_ATOMIC, 1)) == NULL) - goto abort; - bio_init(bh); - bh->bi_vcnt = 1; - while (--count) { - if ((bh = bio_alloc(GFP_ATOMIC, 1)) == NULL) - goto abort; - bio_init(bh); - bh->bi_vcnt = 1; - bhp->bi_next = bh; - bhp = bh; - bh->bi_next = NULL; - } - return first_bh; -abort: - idescsi_free_bio(first_bh); - - return NULL; -} - -static inline int idescsi_set_direction(struct atapi_packet_command *pc) -{ - switch (pc->c[0]) { - case READ_6: - case READ_10: - case READ_12: - clear_bit(PC_WRITING, &pc->flags); - return 0; - case WRITE_6: - case WRITE_10: - case WRITE_12: - set_bit(PC_WRITING, &pc->flags); - return 0; - default: - return 1; - } -} - -static inline struct bio *idescsi_dma_bio(struct ata_device *drive, struct atapi_packet_command *pc) -{ - struct bio *bh = NULL, *first_bh = NULL; - int segments = pc->s.scsi_cmd->use_sg; - struct scatterlist *sg = pc->s.scsi_cmd->request_buffer; - - if (!drive->using_dma || !pc->request_transfer || pc->request_transfer % 1024) - return NULL; - if (idescsi_set_direction(pc)) - return NULL; - if (segments) { - if ((first_bh = bh = idescsi_kmalloc_bio (segments)) == NULL) - return NULL; -#ifdef DEBUG - printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10); -#endif - while (segments--) { - bh->bi_io_vec[0].bv_page = sg->page; - bh->bi_io_vec[0].bv_len = sg->length; - bh->bi_io_vec[0].bv_offset = sg->offset; - bh->bi_size = sg->length; - bh = bh->bi_next; - sg++; - } - } else { - if ((first_bh = bh = idescsi_kmalloc_bio (1)) == NULL) - return NULL; -#ifdef DEBUG - printk ("ide-scsi: %s: building DMA table for a single buffer (%dkB)\n", drive->name, pc->request_transfer >> 10); -#endif - bh->bi_io_vec[0].bv_page = virt_to_page(pc->s.scsi_cmd->request_buffer); - bh->bi_io_vec[0].bv_len = pc->request_transfer; - bh->bi_io_vec[0].bv_offset = (unsigned long) pc->s.scsi_cmd->request_buffer & ~PAGE_MASK; - bh->bi_size = pc->request_transfer; - } - return first_bh; -} - -static inline int should_transform(struct ata_device *drive, Scsi_Cmnd *cmd) -{ - struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); - - if (major(cmd->request->rq_dev) == SCSI_GENERIC_MAJOR) - return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); - return test_bit(IDESCSI_TRANSFORM, &scsi->transform); -} - -static int idescsi_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) -{ - idescsi_scsi_t *scsi = idescsi_private(cmd->host); - struct ata_device *drive = scsi->drive; - struct request *rq = NULL; - struct atapi_packet_command *pc = NULL; - - pc = kmalloc(sizeof(*pc), GFP_ATOMIC); - rq = kmalloc(sizeof(*rq), GFP_ATOMIC); - if (rq == NULL || pc == NULL) { - printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name); - goto abort; - } - - memset (pc->c, 0, 12); - pc->flags = 0; - memcpy (pc->c, cmd->cmnd, cmd->cmd_len); - if (cmd->use_sg) { - pc->buffer = NULL; - pc->s.sg = cmd->request_buffer; - } else { - pc->buffer = cmd->request_buffer; - pc->s.sg = NULL; - } - pc->s.b_count = 0; - pc->request_transfer = pc->buffer_size = cmd->request_bufflen; - pc->s.scsi_cmd = cmd; - pc->s.done = done; - pc->s.timeout = jiffies + cmd->timeout_per_command; - - if (should_transform(drive, cmd)) - set_bit(PC_TRANSFORM, &pc->flags); - idescsi_transform_pc1 (drive, pc); - - if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { - printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); - hexdump(cmd->cmnd, cmd->cmd_len); - if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) { - printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number); - hexdump(pc->c, 12); - } - } - - memset(rq, 0, sizeof(*rq)); - rq->flags = REQ_PC; - rq->special = (char *) pc; - rq->bio = idescsi_dma_bio (drive, pc); - ide_do_drive_cmd(drive, rq, ide_end); - - return 0; -abort: - if (pc) - kfree (pc); - if (rq) - kfree (rq); - cmd->result = DID_ERROR << 16; - done(cmd); - - return 0; -} - -/* FIXME: This needs further investigation. - */ -static int idescsi_device_reset(Scsi_Cmnd *cmd) -{ - return SUCCESS; -} - -static int idescsi_bios(Disk *disk, struct block_device *dev, int *parm) -{ - idescsi_scsi_t *scsi = idescsi_private(disk->device->host); - struct ata_device *drive = scsi->drive; - - if (drive->bios_cyl && drive->bios_head && drive->bios_sect) { - parm[0] = drive->bios_head; - parm[1] = drive->bios_sect; - parm[2] = drive->bios_cyl; - } - return 0; -} - -static Scsi_Host_Template template = { - module: THIS_MODULE, - name: "idescsi", - detect: idescsi_detect, - release: NULL, /* unregister_ata_driver is always - called before scsi_unregister_host, - there never controllers left to - release by that point. */ - info: idescsi_info, - ioctl: idescsi_ioctl, - queuecommand: idescsi_queue, - eh_device_reset_handler: - idescsi_device_reset, - bios_param: idescsi_bios, - can_queue: 10, - this_id: -1, - sg_tablesize: 256, - cmd_per_lun: 5, - use_clustering: DISABLE_CLUSTERING, - emulated: 1, - /* FIXME: Buggy generic SCSI code doesn't remove /proc/entires! */ - proc_name: "atapi" -}; - -/* - * Driver initialization. - */ -static void idescsi_attach(struct ata_device *drive) -{ - idescsi_scsi_t *scsi; - struct Scsi_Host *host; - - - if (drive->type == ATA_DISK) - return; - - host = scsi_register(&template, sizeof(idescsi_scsi_t)); - if (!host) { - printk(KERN_ERR - "ide-scsi: %s: Can't allocate a scsi host structure\n", - drive->name); - return; - } - - host->max_lun = drive->last_lun + 1; - host->max_id = 1; - - if (ata_register_device(drive, &ata_ops)) { - printk(KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name); - scsi_unregister(host); - return; - } - - drive->driver_data = host; - drive->ready_stat = 0; - - scsi = idescsi_private(host); - memset(scsi,0, sizeof (*scsi)); - scsi->drive = drive; - - if (drive->id && (drive->id->config & 0x0060) == 0x20) - set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); - set_bit(IDESCSI_TRANSFORM, &scsi->transform); - clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); -#ifdef DEBUG - set_bit(IDESCSI_LOG_CMD, &scsi->log); -#endif -} - -static int __init init_idescsi_module(void) -{ - return scsi_register_host(&template); -} - -static void __exit exit_idescsi_module(void) -{ - unregister_ata_driver(&ata_ops); -} - -module_init(init_idescsi_module); -module_exit(exit_idescsi_module); -MODULE_LICENSE("GPL"); diff -Nru a/include/linux/ide.h b/include/linux/ide.h --- a/include/linux/ide.h Fri Aug 16 14:52:59 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1281 +0,0 @@ -#ifndef _IDE_H -#define _IDE_H - -/* - * Copyright (C) 1994-2002 Linus Torvalds & authors - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This is the multiple IDE interface driver, as evolved from hd.c. - * It supports up to four IDE interfaces, on one or more IRQs (usually 14, 15). - * There can be up to two drives per interface, as per the ATA-2 spec. - * - * Primary i/f: ide0: major=3; (hda) minor=0; (hdb) minor=64 - * Secondary i/f: ide1: major=22; (hdc) minor=0; (hdd) minor=64 - * Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64 - * Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64 - */ - -/****************************************************************************** - * IDE driver configuration options (play with these as desired): - */ -#define INITIAL_MULT_COUNT 0 /* off=0; on=2,4,8,16,32, etc.. */ - -#ifndef SUPPORT_SLOW_DATA_PORTS /* 1 to support slow data ports */ -# define SUPPORT_SLOW_DATA_PORTS 1 /* 0 to reduce kernel size */ -#endif - -#ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */ -# define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */ -#endif -#ifndef DISABLE_IRQ_NOSYNC -# define DISABLE_IRQ_NOSYNC 0 -#endif - -/* - * "No user-serviceable parts" beyond this point - *****************************************************************************/ - - -/* ATA/ATAPI Commands pre T13 Spec */ -#define WIN_NOP 0x00 -#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ -#define WIN_SRST 0x08 /* ATAPI soft reset command */ -#define WIN_DEVICE_RESET 0x08 -#define WIN_RESTORE 0x10 -#define WIN_READ 0x20 /* 28-Bit */ -#define WIN_READ_EXT 0x24 /* 48-Bit */ -#define WIN_READDMA_EXT 0x25 /* 48-Bit */ -#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ -#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ -#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ -#define WIN_WRITE 0x30 /* 28-Bit */ -#define WIN_WRITE_EXT 0x34 /* 48-Bit */ -#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ -#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ -#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ -#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ -#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ -#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ -#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ -#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ -#define WIN_FORMAT 0x50 -#define WIN_INIT 0x60 -#define WIN_SEEK 0x70 -#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ -#define WIN_DIAGNOSE 0x90 -#define WIN_SPECIFY 0x91 /* set drive geometry translation */ -#define WIN_DOWNLOAD_MICROCODE 0x92 -#define WIN_STANDBYNOW2 0x94 -#define WIN_SETIDLE2 0x97 -#define WIN_CHECKPOWERMODE2 0x98 -#define WIN_SLEEPNOW2 0x99 -#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ -#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ -#define WIN_QUEUED_SERVICE 0xA2 -#define WIN_SMART 0xB0 /* self-monitoring and reporting */ -#define CFA_ERASE_SECTORS 0xC0 -#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ -#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ -#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ -#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ -#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ -#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ -#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ -#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ -#define WIN_GETMEDIASTATUS 0xDA -#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ -#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ -#define WIN_STANDBYNOW1 0xE0 -#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ -#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ -#define WIN_SETIDLE1 0xE3 -#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ -#define WIN_CHECKPOWERMODE1 0xE5 -#define WIN_SLEEPNOW1 0xE6 -#define WIN_FLUSH_CACHE 0xE7 -#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ -#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ -#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ -#define WIN_MEDIAEJECT 0xED -#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ -#define WIN_SETFEATURES 0xEF /* set special drive features */ -#define EXABYTE_ENABLE_NEST 0xF0 -#define WIN_SECURITY_SET_PASS 0xF1 -#define WIN_SECURITY_UNLOCK 0xF2 -#define WIN_SECURITY_ERASE_PREPARE 0xF3 -#define WIN_SECURITY_ERASE_UNIT 0xF4 -#define WIN_SECURITY_FREEZE_LOCK 0xF5 -#define WIN_SECURITY_DISABLE 0xF6 -#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ -#define WIN_SET_MAX 0xF9 -#define DISABLE_SEAGATE 0xFB - -/* WIN_SMART sub-commands */ - -#define SMART_READ_VALUES 0xD0 -#define SMART_READ_THRESHOLDS 0xD1 -#define SMART_AUTOSAVE 0xD2 -#define SMART_SAVE 0xD3 -#define SMART_IMMEDIATE_OFFLINE 0xD4 -#define SMART_READ_LOG_SECTOR 0xD5 -#define SMART_WRITE_LOG_SECTOR 0xD6 -#define SMART_WRITE_THRESHOLDS 0xD7 -#define SMART_ENABLE 0xD8 -#define SMART_DISABLE 0xD9 -#define SMART_STATUS 0xDA -#define SMART_AUTO_OFFLINE 0xDB - -/* Password used in TF4 & TF5 executing SMART commands */ - -#define SMART_LCYL_PASS 0x4F -#define SMART_HCYL_PASS 0xC2 - -/* WIN_SETFEATURES sub-commands */ - -#define SETFEATURES_EN_WCACHE 0x02 /* Enable write cache */ - -#define SETFEATURES_XFER 0x03 /* Set transfer mode */ -# define XFER_UDMA_7 0x47 /* 0100|0111 */ -# define XFER_UDMA_6 0x46 /* 0100|0110 */ -# define XFER_UDMA_5 0x45 /* 0100|0101 */ -# define XFER_UDMA_4 0x44 /* 0100|0100 */ -# define XFER_UDMA_3 0x43 /* 0100|0011 */ -# define XFER_UDMA_2 0x42 /* 0100|0010 */ -# define XFER_UDMA_1 0x41 /* 0100|0001 */ -# define XFER_UDMA_0 0x40 /* 0100|0000 */ -# define XFER_MW_DMA_2 0x22 /* 0010|0010 */ -# define XFER_MW_DMA_1 0x21 /* 0010|0001 */ -# define XFER_MW_DMA_0 0x20 /* 0010|0000 */ -# define XFER_SW_DMA_2 0x12 /* 0001|0010 */ -# define XFER_SW_DMA_1 0x11 /* 0001|0001 */ -# define XFER_SW_DMA_0 0x10 /* 0001|0000 */ -# define XFER_PIO_4 0x0C /* 0000|1100 */ -# define XFER_PIO_3 0x0B /* 0000|1011 */ -# define XFER_PIO_2 0x0A /* 0000|1010 */ -# define XFER_PIO_1 0x09 /* 0000|1001 */ -# define XFER_PIO_0 0x08 /* 0000|1000 */ -# define XFER_PIO_SLOW 0x00 /* 0000|0000 */ - -#define SETFEATURES_DIS_DEFECT 0x04 /* Disable Defect Management */ -#define SETFEATURES_EN_APM 0x05 /* Enable advanced power management */ -#define SETFEATURES_DIS_MSN 0x31 /* Disable Media Status Notification */ -#define SETFEATURES_EN_AAM 0x42 /* Enable Automatic Acoustic Management */ -#define SETFEATURES_DIS_RLA 0x55 /* Disable read look-ahead feature */ -#define SETFEATURES_EN_RI 0x5D /* Enable release interrupt */ -#define SETFEATURES_EN_SI 0x5E /* Enable SERVICE interrupt */ -#define SETFEATURES_DIS_RPOD 0x66 /* Disable reverting to power on defaults */ -#define SETFEATURES_DIS_WCACHE 0x82 /* Disable write cache */ -#define SETFEATURES_EN_DEFECT 0x84 /* Enable Defect Management */ -#define SETFEATURES_DIS_APM 0x85 /* Disable advanced power management */ -#define SETFEATURES_EN_MSN 0x95 /* Enable Media Status Notification */ -#define SETFEATURES_EN_RLA 0xAA /* Enable read look-ahead feature */ -#define SETFEATURES_PREFETCH 0xAB /* Sets drive prefetch value */ -#define SETFEATURES_DIS_AAM 0xC2 /* Disable Automatic Acoustic Management */ -#define SETFEATURES_EN_RPOD 0xCC /* Enable reverting to power on defaults */ -#define SETFEATURES_DIS_RI 0xDD /* Disable release interrupt */ -#define SETFEATURES_DIS_SI 0xDE /* Disable SERVICE interrupt */ - -/* WIN_SECURITY sub-commands */ - -#define SECURITY_SET_PASSWORD 0xBA -#define SECURITY_UNLOCK 0xBB -#define SECURITY_ERASE_PREPARE 0xBC -#define SECURITY_ERASE_UNIT 0xBD -#define SECURITY_FREEZE_LOCK 0xBE -#define SECURITY_DISABLE_PASSWORD 0xBF - - -/* Taskfile related constants. - */ -#define IDE_DRIVE_TASK_INVALID -1 -#define IDE_DRIVE_TASK_NO_DATA 0 -#define IDE_DRIVE_TASK_SET_XFER 1 - -#define IDE_DRIVE_TASK_IN 2 - -#define IDE_DRIVE_TASK_OUT 3 -#define IDE_DRIVE_TASK_RAW_WRITE 4 - -struct hd_drive_task_hdr { - u8 feature; - u8 sector_count; - u8 sector_number; - u8 low_cylinder; - u8 high_cylinder; - u8 device_head; -} __attribute__((packed)); - -/* - * Define standard taskfile in/out register - */ -#define IDE_TASKFILE_STD_OUT_FLAGS 0xFE -#define IDE_TASKFILE_STD_IN_FLAGS 0xFE -#define IDE_HOB_STD_OUT_FLAGS 0xC0 -#define IDE_HOB_STD_IN_FLAGS 0xC0 - -#define TASKFILE_INVALID 0x7fff -#define TASKFILE_48 0x8000 - -#define TASKFILE_NO_DATA 0x0000 - -#define TASKFILE_IN 0x0001 -#define TASKFILE_MULTI_IN 0x0002 - -#define TASKFILE_OUT 0x0004 -#define TASKFILE_MULTI_OUT 0x0008 -#define TASKFILE_IN_OUT 0x0010 - -#define TASKFILE_IN_DMA 0x0020 -#define TASKFILE_OUT_DMA 0x0040 -#define TASKFILE_IN_DMAQ 0x0080 -#define TASKFILE_OUT_DMAQ 0x0100 - -#define TASKFILE_P_IN 0x0200 -#define TASKFILE_P_OUT 0x0400 -#define TASKFILE_P_IN_DMA 0x0800 -#define TASKFILE_P_OUT_DMA 0x1000 -#define TASKFILE_P_IN_DMAQ 0x2000 -#define TASKFILE_P_OUT_DMAQ 0x4000 - -/* bus states */ -enum { - BUSSTATE_OFF = 0, - BUSSTATE_ON, - BUSSTATE_TRISTATE -}; - -/* - * Structure returned by HDIO_GET_IDENTITY, as per ANSI NCITS ATA6 rev.1b spec. - * - * If you change something here, please remember to update fix_driveid() in - * ide/probe.c. - */ -struct hd_driveid { - u16 config; /* lots of obsolete bit flags */ - u16 cyls; /* Obsolete, "physical" cyls */ - u16 reserved2; /* reserved (word 2) */ - u16 heads; /* Obsolete, "physical" heads */ - u16 track_bytes; /* unformatted bytes per track */ - u16 sector_bytes; /* unformatted bytes per sector */ - u16 sectors; /* Obsolete, "physical" sectors per track */ - u16 vendor0; /* vendor unique */ - u16 vendor1; /* vendor unique */ - u16 vendor2; /* Retired vendor unique */ - u8 serial_no[20]; /* 0 = not_specified */ - u16 buf_type; /* Retired */ - u16 buf_size; /* Retired, 512 byte increments - * 0 = not_specified - */ - u16 ecc_bytes; /* for r/w long cmds; 0 = not_specified */ - u8 fw_rev[8]; /* 0 = not_specified */ - char model[40]; /* 0 = not_specified */ - u8 max_multsect; /* 0=not_implemented */ - u8 vendor3; /* vendor unique */ - u16 dword_io; /* 0=not_implemented; 1=implemented */ - u8 vendor4; /* vendor unique */ - u8 capability; /* (upper byte of word 49) - * 3: IORDYsup - * 2: IORDYsw - * 1: LBA - * 0: DMA - */ - u16 reserved50; /* reserved (word 50) */ - u8 vendor5; /* Obsolete, vendor unique */ - u8 tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */ - u8 vendor6; /* Obsolete, vendor unique */ - u8 tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */ - u16 field_valid; /* (word 53) - * 2: ultra_ok word 88 - * 1: eide_ok words 64-70 - * 0: cur_ok words 54-58 - */ - u16 cur_cyls; /* Obsolete, logical cylinders */ - u16 cur_heads; /* Obsolete, l heads */ - u16 cur_sectors; /* Obsolete, l sectors per track */ - u16 cur_capacity0; /* Obsolete, l total sectors on drive */ - u16 cur_capacity1; /* Obsolete, (2 words, misaligned int) */ - u8 multsect; /* current multiple sector count */ - u8 multsect_valid; /* when (bit0==1) multsect is ok */ - u32 lba_capacity; /* Obsolete, total number of sectors */ - u16 dma_1word; /* Obsolete, single-word dma info */ - u16 dma_mword; /* multiple-word dma info */ - u16 eide_pio_modes; /* bits 0:mode3 1:mode4 */ - u16 eide_dma_min; /* min mword dma cycle time (ns) */ - u16 eide_dma_time; /* recommended mword dma cycle time (ns) */ - u16 eide_pio; /* min cycle time (ns), no IORDY */ - u16 eide_pio_iordy; /* min cycle time (ns), with IORDY */ - u16 words69_70[2]; /* reserved words 69-70 - * future command overlap and queuing - */ - /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */ - u16 words71_74[4]; /* reserved words 71-74 - * for IDENTIFY PACKET DEVICE command - */ - u16 queue_depth; /* (word 75) - * 15:5 reserved - * 4:0 Maximum queue depth -1 - */ - u16 words76_79[4]; /* reserved words 76-79 */ - u16 major_rev_num; /* (word 80) */ - u16 minor_rev_num; /* (word 81) */ - u16 command_set_1; /* (word 82) supported - * 15: Obsolete - * 14: NOP command - * 13: READ_BUFFER - * 12: WRITE_BUFFER - * 11: Obsolete - * 10: Host Protected Area - * 9: DEVICE Reset - * 8: SERVICE Interrupt - * 7: Release Interrupt - * 6: look-ahead - * 5: write cache - * 4: PACKET Command - * 3: Power Management Feature Set - * 2: Removable Feature Set - * 1: Security Feature Set - * 0: SMART Feature Set - */ - u16 command_set_2; /* (word 83) - * 15: Shall be ZERO - * 14: Shall be ONE - * 13: FLUSH CACHE EXT - * 12: FLUSH CACHE - * 11: Device Configuration Overlay - * 10: 48-bit Address Feature Set - * 9: Automatic Acoustic Management - * 8: SET MAX security - * 7: reserved 1407DT PARTIES - * 6: SetF sub-command Power-Up - * 5: Power-Up in Standby Feature Set - * 4: Removable Media Notification - * 3: APM Feature Set - * 2: CFA Feature Set - * 1: READ/WRITE DMA QUEUED - * 0: Download MicroCode - */ - u16 cfsse; /* (word 84) - * cmd set-feature supported extensions - * 15: Shall be ZERO - * 14: Shall be ONE - * 13:3 reserved - * 2: Media Serial Number Valid - * 1: SMART selt-test supported - * 0: SMART error logging - */ - u16 cfs_enable_1; /* (word 85) - * command set-feature enabled - * 15: Obsolete - * 14: NOP command - * 13: READ_BUFFER - * 12: WRITE_BUFFER - * 11: Obsolete - * 10: Host Protected Area - * 9: DEVICE Reset - * 8: SERVICE Interrupt - * 7: Release Interrupt - * 6: look-ahead - * 5: write cache - * 4: PACKET Command - * 3: Power Management Feature Set - * 2: Removable Feature Set - * 1: Security Feature Set - * 0: SMART Feature Set - */ - u16 cfs_enable_2; /* (word 86) - * command set-feature enabled - * 15: Shall be ZERO - * 14: Shall be ONE - * 13: FLUSH CACHE EXT - * 12: FLUSH CACHE - * 11: Device Configuration Overlay - * 10: 48-bit Address Feature Set - * 9: Automatic Acoustic Management - * 8: SET MAX security - * 7: reserved 1407DT PARTIES - * 6: SetF sub-command Power-Up - * 5: Power-Up in Standby Feature Set - * 4: Removable Media Notification - * 3: APM Feature Set - * 2: CFA Feature Set - * 1: READ/WRITE DMA QUEUED - * 0: Download MicroCode - */ - u16 csf_default; /* (word 87) - * command set-feature default - * 15: Shall be ZERO - * 14: Shall be ONE - * 13:3 reserved - * 2: Media Serial Number Valid - * 1: SMART selt-test supported - * 0: SMART error logging - */ - u16 dma_ultra; /* (word 88) */ - u16 word89; /* reserved (word 89) */ - u16 word90; /* reserved (word 90) */ - u16 CurAPMvalues; /* current APM values */ - u16 word92; /* reserved (word 92) */ - u16 hw_config; /* hardware config (word 93) - * 15: - * 14: - * 13: - * 12: - * 11: - * 10: - * 9: - * 8: - * 7: - * 6: - * 5: - * 4: - * 3: - * 2: - * 1: - * 0: - */ - u16 acoustic; /* (word 94) - * 15:8 Vendor's recommended value - * 7:0 current value - */ - u16 words95_99[5]; /* reserved words 95-99 */ - u64 lba_capacity_2; /* 48-bit total number of sectors */ - u16 words104_125[22];/* reserved words 104-125 */ - u16 last_lun; /* (word 126) */ - u16 word127; /* (word 127) Feature Set - * Removable Media Notification - * 15:2 reserved - * 1:0 00 = not supported - * 01 = supported - * 10 = reserved - * 11 = reserved - */ - u16 dlf; /* (word 128) - * device lock function - * 15:9 reserved - * 8 security level 1:max 0:high - * 7:6 reserved - * 5 enhanced erase - * 4 expire - * 3 frozen - * 2 locked - * 1 en/disabled - * 0 capability - */ - u16 csfo; /* (word 129) - * current set features options - * 15:4 reserved - * 3: auto reassign - * 2: reverting - * 1: read-look-ahead - * 0: write cache - */ - u16 words130_155[26];/* reserved vendor words 130-155 */ - u16 word156; /* reserved vendor word 156 */ - u16 words157_159[3];/* reserved vendor words 157-159 */ - u16 cfa_power; /* (word 160) CFA Power Mode - * 15 word 160 supported - * 14 reserved - * 13 - * 12 - * 11:0 - */ - u16 words161_175[14];/* Reserved for CFA */ - u16 words176_205[31];/* Current Media Serial Number */ - u16 words206_254[48];/* reserved words 206-254 */ - u16 integrity_word; /* (word 255) - * 15:8 Checksum - * 7:0 Signature - */ -} __attribute__((packed)); - -#define IDE_NICE_DSC_OVERLAP (0) /* per the DSC overlap protocol */ - -/* - * Probably not wise to fiddle with these - */ -#define ERROR_MAX 8 /* Max read/write errors per sector */ -#define ERROR_RESET 3 /* Reset controller every 4th retry */ - -/* - * State flags. - */ -#define DMA_PIO_RETRY 1 /* retrying in PIO */ - -/* - * Definitions for accessing IDE controller registers. - */ - -enum { - IDE_DATA_OFFSET = 0, - IDE_ERROR_OFFSET = 1, - IDE_FEATURE_OFFSET = 1, - IDE_NSECTOR_OFFSET = 2, - IDE_SECTOR_OFFSET = 3, - IDE_LCYL_OFFSET = 4, - IDE_HCYL_OFFSET = 5, - IDE_SELECT_OFFSET = 6, - IDE_STATUS_OFFSET = 7, - IDE_COMMAND_OFFSET = 7, - IDE_CONTROL_OFFSET = 8, - IDE_ALTSTATUS_OFFSET = 8, - IDE_IRQ_OFFSET = 9, - IDE_NR_PORTS = 10 -}; - - -#define IDE_DATA_REG (drive->channel->io_ports[IDE_DATA_OFFSET]) -#define IDE_ERROR_REG (drive->channel->io_ports[IDE_ERROR_OFFSET]) -#define IDE_NSECTOR_REG (drive->channel->io_ports[IDE_NSECTOR_OFFSET]) -#define IDE_SECTOR_REG (drive->channel->io_ports[IDE_SECTOR_OFFSET]) -#define IDE_LCYL_REG (drive->channel->io_ports[IDE_LCYL_OFFSET]) -#define IDE_HCYL_REG (drive->channel->io_ports[IDE_HCYL_OFFSET]) -#define IDE_SELECT_REG (drive->channel->io_ports[IDE_SELECT_OFFSET]) -#define IDE_COMMAND_REG (drive->channel->io_ports[IDE_STATUS_OFFSET]) -#define IDE_IRQ_REG (drive->channel->io_ports[IDE_IRQ_OFFSET]) - -#define IDE_FEATURE_REG IDE_ERROR_REG -#define IDE_IREASON_REG IDE_NSECTOR_REG -#define IDE_BCOUNTL_REG IDE_LCYL_REG -#define IDE_BCOUNTH_REG IDE_HCYL_REG - -#define GET_ERR() IN_BYTE(IDE_ERROR_REG) -#define GET_ALTSTAT() IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET]) -#define GET_FEAT() IN_BYTE(IDE_NSECTOR_REG) - -/* Bits of HD_STATUS */ -#define ERR_STAT 0x01 -#define INDEX_STAT 0x02 -#define ECC_STAT 0x04 /* Corrected error */ -#define DRQ_STAT 0x08 -#define SEEK_STAT 0x10 -#define SERVICE_STAT SEEK_STAT -#define WRERR_STAT 0x20 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits for HD_ERROR */ -#define MARK_ERR 0x01 /* Bad address mark */ -#define TRK0_ERR 0x02 /* couldn't find track 0 */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* media change request */ -#define ID_ERR 0x10 /* ID field not found */ -#define MC_ERR 0x20 /* media changed */ -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ -#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ - -/* - * sector count bits - */ -#define NSEC_CD 0x01 -#define NSEC_IO 0x02 -#define NSEC_REL 0x04 - -#define BAD_R_STAT (BUSY_STAT | ERR_STAT) -#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT) -#define BAD_STAT (BAD_R_STAT | DRQ_STAT) - -#define DRIVE_READY (READY_STAT | SEEK_STAT) -#define DATA_READY (DRQ_STAT) - -/* - * Our Physical Region Descriptor (PRD) table should be large enough - * to handle the biggest I/O request we are likely to see. Since requests - * can have no more than 256 sectors, and since the typical blocksize is - * two or more sectors, we could get by with a limit of 128 entries here for - * the usual worst case. Most requests seem to include some contiguous blocks, - * further reducing the number of table entries required. - * - * As it turns out though, we must allocate a full 4KB page for this, - * so the two PRD tables (ide0 & ide1) will each get half of that, - * allowing each to have about 256 entries (8 bytes each) from this. - */ -#define PRD_BYTES 8 -#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES)) - -/* - * Some more useful definitions - */ -#define IDE_MAJOR_NAME "hd" /* the same for all i/f; see also genhd.c */ -#define MAJOR_NAME IDE_MAJOR_NAME -#define PARTN_BITS 6 /* number of minor dev bits for partitions */ -#define PARTN_MASK ((1<> (c)) & 1) - -/* - * Structure to hold all information about the location of this port - */ -typedef struct hw_regs_s { - ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */ - int irq; /* our irq number */ - int dma; /* our dma entry */ - int (*ack_intr)(struct ata_channel *); /* acknowledge interrupt */ - hwif_chipset_t chipset; -} hw_regs_t; - -/* - * Set up hw_regs_t structure before calling ide_register_hw (optional) - */ -extern void ide_setup_ports(hw_regs_t *hw, - ide_ioreg_t base, int *offsets, - ide_ioreg_t ctrl, ide_ioreg_t intr, - int (*ack_intr)(struct ata_channel *), - int irq); - -#include - -/* Currently only m68k, apus and m8xx need it */ -#ifdef ATA_ARCH_ACK_INTR -extern int ide_irq_lock; -# define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1) -#else -# define ide_ack_intr(hwif) (1) -#endif - -/* Currently only Atari needs it */ -#ifndef ATA_ARCH_LOCK -# define ide_release_lock(lock) do {} while (0) -# define ide_get_lock(lock, hdlr, data) do {} while (0) -#endif - -/* - * If the arch-dependant ide.h did not declare/define any OUT_BYTE or IN_BYTE - * functions, we make some defaults here. The only architecture currently - * needing this is Cris. - */ - -#ifndef HAVE_ARCH_IN_OUT -# define OUT_BYTE(b,p) outb((b),(p)) -# define OUT_WORD(w,p) outw((w),(p)) -# define IN_BYTE(p) (u8)inb(p) -# define IN_WORD(p) (u16)inw(p) -#endif - -/* - * Device types - the nomenclature is analogous to SCSI code. - */ - -#define ATA_DISK 0x20 -#define ATA_TAPE 0x01 -#define ATA_ROM 0x05 /* CD-ROM */ -#define ATA_MOD 0x07 /* optical */ -#define ATA_FLOPPY 0x00 -#define ATA_SCSI 0x21 -#define ATA_NO_LUN 0x7f - -typedef union { - unsigned all : 8; /* all of the bits together */ - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned head : 4; /* always zeros here */ - unsigned unit : 1; /* drive select number: 0/1 */ - unsigned bit5 : 1; /* always 1 */ - unsigned lba : 1; /* using LBA instead of CHS */ - unsigned bit7 : 1; /* always 1 */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned bit7 : 1; - unsigned lba : 1; - unsigned bit5 : 1; - unsigned unit : 1; - unsigned head : 4; -#else -#error "Please fix " -#endif - } b; -} select_t; - -/* - * ATA/ATAPI device structure : - */ -struct ata_device { - struct ata_channel * channel; - char name[6]; /* device name */ - - unsigned int usage; /* current "open()" count for drive */ - char type; /* distingiush different devices: disk, cdrom, tape, floppy, ... */ - - request_queue_t queue; /* per device request queue */ - struct request *rq; /* current request */ - - u8 retry_pio; /* retrying dma capable host in pio */ - u8 state; /* retry state */ - - unsigned using_dma : 1; /* disk is using dma for read/write */ - unsigned using_tcq : 1; /* disk is using queueing */ - unsigned dsc_overlap : 1; /* flag: DSC overlap */ - - unsigned busy : 1; /* currently doing revalidate_disk() */ - unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */ - - unsigned present : 1; /* drive is physically present */ - unsigned noprobe : 1; /* from: hdx=noprobe */ - unsigned removable : 1; /* 1 if need to do check_media_change */ - unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */ - unsigned nobios : 1; /* flag: do not probe bios for drive */ - unsigned revalidate : 1; /* request revalidation */ - unsigned atapi_overlap : 1; /* flag: ATAPI overlap (not supported) */ - unsigned doorlocking : 1; /* flag: for removable only: door lock/unlock works */ - unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */ - unsigned ata_flash : 1; /* 1=present, 0=default */ - unsigned addressing; /* : 2; 0=28-bit, 1=48-bit, 2=64-bit */ - u8 scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */ - - select_t select; /* basic drive/head select reg value */ - u8 status; /* last retrived status value for device */ - - u8 ready_stat; /* min status value for drive ready */ - u8 mult_count; /* current multiple sector setting */ - u8 bad_wstat; /* used for ignoring WRERR_STAT */ - u8 nowerr; /* used for ignoring WRERR_STAT */ - u8 head; /* "real" number of heads */ - u8 sect; /* "real" sectors per track */ - u8 bios_head; /* BIOS/fdisk/LILO number of heads */ - u8 bios_sect; /* BIOS/fdisk/LILO sectors per track */ - unsigned int bios_cyl; /* BIOS/fdisk/LILO number of cyls */ - unsigned int cyl; /* "real" number of cyls */ - u64 capacity; /* total number of sectors */ - unsigned int drive_data; /* for use by tuneproc/selectproc as needed */ - - wait_queue_head_t wqueue; /* used to wait for drive in open() */ - - struct hd_driveid *id; /* drive model identification info */ - struct hd_struct *part; /* drive partition table */ - - struct ata_operations *driver; - - void *driver_data; /* extra driver data */ - devfs_handle_t de; /* directory for device */ - - char driver_req[10]; /* requests specific driver */ - - int last_lun; /* last logical unit */ - int forced_lun; /* if hdxlun was given at boot */ - int lun; /* logical unit */ - - int crc_count; /* crc counter to reduce drive speed */ - int quirk_list; /* drive is considered quirky if set for a specific host */ - u8 current_speed; /* current transfer rate set */ - u8 dn; /* now wide spread use */ - u8 wcache; /* status of write cache */ - u8 acoustic; /* acoustic management */ - unsigned int queue_depth; /* max queue depth */ - unsigned int failures; /* current failure count */ - unsigned int max_failures; /* maximum allowed failure count */ - struct device dev; /* global device tree handle */ - - /* - * tcq statistics - */ - unsigned long immed_rel; - unsigned long immed_comp; - int max_last_depth; - int max_depth; -}; - -/* - * Status returned by various functions. - */ -typedef enum { - ATA_OP_FINISHED, /* no drive operation was started */ - ATA_OP_CONTINUES, /* a drive operation was started, and a handler was set */ - ATA_OP_RELEASED, /* started and released bus */ - ATA_OP_READY /* indicate status poll finished fine */ -} ide_startstop_t; - -/* - * Interrupt and timeout handler type. - */ -typedef ide_startstop_t (ata_handler_t)(struct ata_device *, struct request *); -typedef ide_startstop_t (ata_expiry_t)(struct ata_device *, struct request *, unsigned long *); - -enum { - ATA_PRIMARY = 0, - ATA_SECONDARY = 1 -}; - -enum { - IDE_BUSY, /* awaiting an interrupt */ - IDE_SLEEP, - IDE_PIO, /* PIO in progress */ - IDE_DMA /* DMA in progress */ -}; - -struct ata_channel { - struct device dev; /* device handle */ - int unit; /* channel number */ - - /* This lock is used to serialize requests on the same device queue or - * between differen queues sharing the same irq line. - */ - spinlock_t *lock; - unsigned long *active; /* active processing request */ - ide_startstop_t (*handler)(struct ata_device *, struct request *); /* irq handler, if active */ - - /* FIXME: Only still used in PDC4030. Localize this code there by - * replacing with busy waits. - */ - struct timer_list timer; /* failsafe timer */ - ide_startstop_t (*expiry)(struct ata_device *, struct request *, unsigned long *); /* irq handler, if active */ - unsigned long poll_timeout; /* timeout value during polled operations */ - - struct ata_device *drive; /* last serviced drive */ - - - ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */ - hw_regs_t hw; /* hardware info */ -#ifdef CONFIG_PCI - struct pci_dev *pci_dev; /* for pci chipsets */ -#endif - struct ata_device drives[MAX_DRIVES]; /* drive info */ - struct gendisk *gd[MAX_DRIVES]; /* gendisk structure */ - - /* - * Routines to tune PIO and DMA mode for drives. - * - * A value of 255 indicates that the function should choose the optimal - * mode itself. - */ - - /* setup disk on a channel for a particular PIO transfer mode */ - void (*tuneproc) (struct ata_device *, u8 pio); - - /* setup the chipset timing for a particular transfer mode */ - int (*speedproc) (struct ata_device *, u8 pio); - - /* tweaks hardware to select drive */ - void (*selectproc) (struct ata_device *); - - /* routine to reset controller after a disk reset */ - void (*resetproc) (struct ata_device *); - - /* special interrupt handling for shared pci interrupts */ - void (*intrproc) (struct ata_device *); - - /* special host masking for drive selection */ - void (*maskproc) (struct ata_device *); - - /* check host's drive quirk list */ - int (*quirkproc) (struct ata_device *); - - /* driver soft-power interface */ - int (*busproc)(struct ata_device *, int); - - /* CPU-polled transfer routines */ - void (*ata_read)(struct ata_device *, void *, unsigned int); - void (*ata_write)(struct ata_device *, void *, unsigned int); - void (*atapi_read)(struct ata_device *, void *, unsigned int); - void (*atapi_write)(struct ata_device *, void *, unsigned int); - - int (*udma_setup)(struct ata_device *, int); - - void (*udma_enable)(struct ata_device *, int, int); - void (*udma_start) (struct ata_device *, struct request *); - int (*udma_stop) (struct ata_device *); - int (*udma_init) (struct ata_device *, struct request *); - int (*udma_irq_status) (struct ata_device *); - void (*udma_timeout) (struct ata_device *); - void (*udma_irq_lost) (struct ata_device *); - - unsigned long seg_boundary_mask; - unsigned int max_segment_size; - unsigned int *dmatable_cpu; /* dma physical region descriptor table (cpu view) */ - dma_addr_t dmatable_dma; /* dma physical region descriptor table (dma view) */ - struct scatterlist *sg_table; /* Scatter-gather list used to build the above */ - int sg_nents; /* Current number of entries in it */ - int sg_dma_direction; /* dma transfer direction */ - unsigned long dma_base; /* base addr for dma ports */ - unsigned dma_extra; /* extra addr for dma ports */ - unsigned long config_data; /* for use by chipset-specific code */ - unsigned long select_data; /* for use by chipset-specific code */ - struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ - int irq; /* our irq number */ - int major; /* our major number */ - char name[8]; /* name of interface */ - int index; /* 0 for ide0; 1 for ide1; ... */ - hwif_chipset_t chipset; /* sub-module for tuning.. */ - unsigned noprobe : 1; /* don't probe for this interface */ - unsigned present : 1; /* there is a device on this interface */ - unsigned serialized : 1; /* serialized operation between channels */ - unsigned sharing_irq : 1; /* 1 = sharing irq with another hwif */ - unsigned reset : 1; /* reset after probe */ - unsigned autodma : 1; /* automatically try to enable DMA at boot */ - unsigned udma_four : 1; /* 1=ATA-66 capable, 0=default */ - unsigned highmem : 1; /* can do full 32-bit dma */ - unsigned straight8 : 1; /* Alan's straight 8 check */ - unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */ - unsigned no_unmask : 1; /* disallow setting unmask bit */ - unsigned auto_poll : 1; /* supports nop auto-poll */ - unsigned unmask : 1; /* flag: okay to unmask other irqs */ - unsigned slow : 1; /* flag: slow data port */ - unsigned io_32bit : 1; /* 0=16-bit, 1=32-bit */ - unsigned no_atapi_autodma : 1; /* flag: use auto DMA only for disks */ - unsigned char bus_state; /* power state of the IDE bus */ - int modes_map; /* map of supported transfer modes */ -}; - -/* - * Register new hardware with ide - */ -extern int ide_register_hw(hw_regs_t *hw); -extern void ide_unregister(struct ata_channel *); - -#define IDE_MAX_TAG 32 - -#ifdef CONFIG_BLK_DEV_IDE_TCQ -static inline int ata_pending_commands(struct ata_device *drive) -{ - if (drive->using_tcq) - return blk_queue_tag_depth(&drive->queue); - - return 0; -} - -static inline int ata_can_queue(struct ata_device *drive) -{ - if (drive->using_tcq) - return blk_queue_tag_queue(&drive->queue); - - return 1; -} -#else -# define ata_pending_commands(drive) (0) -# define ata_can_queue(drive) (1) -#endif - -/* FIXME: kill this as soon as possible */ -#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0; - -/* - * This structure describes the operations possible on a particular device type - * (CD-ROM, tape, DISK and so on). - * - * This is the main hook for device type support submodules. - */ - -struct ata_operations { - struct module *owner; - void (*attach) (struct ata_device *); - int (*cleanup)(struct ata_device *); - int (*standby)(struct ata_device *); - ide_startstop_t (*do_request)(struct ata_device *, struct request *, sector_t); - int (*end_request)(struct ata_device *, struct request *, int); - - int (*ioctl)(struct ata_device *, struct inode *, struct file *, unsigned int, unsigned long); - int (*open)(struct inode *, struct file *, struct ata_device *); - void (*release)(struct inode *, struct file *, struct ata_device *); - int (*check_media_change)(struct ata_device *); - void (*revalidate)(struct ata_device *); - - sector_t (*capacity)(struct ata_device *); - - /* linked list of rgistered device type drivers */ - struct ata_operations *next; -}; - -/* Alas, no aliases. Too much hassle with bringing module.h everywhere */ -#define ata_get(ata) \ - (((ata) && (ata)->owner) \ - ? ( try_inc_mod_count((ata)->owner) ? (ata) : NULL ) \ - : (ata)) - -#define ata_put(ata) \ -do { \ - if ((ata) && (ata)->owner) \ - __MOD_DEC_USE_COUNT((ata)->owner); \ -} while(0) - -extern sector_t ata_capacity(struct ata_device *drive); - -extern void unregister_ata_driver(struct ata_operations *driver); -extern int register_ata_driver(struct ata_operations *driver); -static inline int ata_driver_module(struct ata_operations *driver) -{ -#ifdef MODULE - if (register_ata_driver(driver) <= 0) { - unregister_ata_driver(driver); - return -ENODEV; - } -#else - register_ata_driver(driver); -#endif - return 0; -} - -#define ata_ops(drive) ((drive)->driver) - -extern struct ata_channel ide_hwifs[]; /* master data repository */ -extern int noautodma; - -/* - * We need blk.h, but we replace its end_request by our own version. - */ -#define IDE_DRIVER /* Toggle some magic bits in blk.h */ -#define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */ -#define DEVICE_NR(device) (minor(device) >> PARTN_BITS) -#include - -extern int ata_end_request(struct ata_device *, struct request *, int, unsigned int); -extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler, - unsigned long timeout, ata_expiry_t expiry); - -extern u8 ata_dump(struct ata_device *, struct request *, const char *); -extern ide_startstop_t ata_error(struct ata_device *, struct request *rq, const char *); - -extern void ide_fixstring(char *s, const int bytecount, const int byteswap); - -/* - * This routine is called from the partition-table code in genhd.c - * to "convert" a drive to a logical geometry with fewer than 1024 cyls. - */ -int ide_xlate_1024(kdev_t, int, int, const char *); - -/* - * Convert kdev_t structure into struct ata_device * one. - */ -struct ata_device *get_info_ptr(kdev_t i_rdev); - -/* - * temporarily mapping a (possible) highmem bio for PIO transfer - */ -#define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9) - -struct ata_taskfile { - struct hd_drive_task_hdr taskfile; - struct hd_drive_task_hdr hobfile; - u8 cmd; /* actual ATA command */ - int command_type; - ide_startstop_t (*XXX_handler)(struct ata_device *, struct request *); -}; - -extern void ata_read(struct ata_device *, void *, unsigned int); -extern void ata_write(struct ata_device *, void *, unsigned int); - -extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *, char *); -extern int ide_config_drive_speed(struct ata_device *, u8); -extern int eighty_ninty_three(struct ata_device *); - -extern int system_bus_speed; - -/* - * CompactFlash cards and their brethern pretend to be removable hard disks, - * but they never have a slave unit, and they don't have doorlock mechanisms. - * This test catches them, and is invoked elsewhere when setting appropriate - * config bits. - */ - -extern int drive_is_flashcard(struct ata_device *); - -extern int ide_spin_wait_hwgroup(struct ata_device *); -extern void ide_timer_expiry(unsigned long data); -extern void ata_irq_request(int irq, void *data, struct pt_regs *regs); -extern void do_ide_request(request_queue_t * q); -extern void ide_init_subdrivers(void); - -extern struct block_device_operations ide_fops[]; - -/* Probe for devices attached to the systems host controllers. - */ -extern int ideprobe_init(void); -#ifdef CONFIG_BLK_DEV_IDEDISK -extern int idedisk_init(void); -#endif -#ifdef CONFIG_BLK_DEV_IDECD -extern int ide_cdrom_init(void); -#endif -#ifdef CONFIG_BLK_DEV_IDETAPE -extern int idetape_init(void); -#endif -#ifdef CONFIG_BLK_DEV_IDEFLOPPY -extern int idefloppy_init(void); -#endif -#ifdef CONFIG_BLK_DEV_IDESCSI -extern int idescsi_init(void); -#endif - -extern int ata_register_device(struct ata_device *, struct ata_operations *); -extern int ata_unregister_device(struct ata_device *drive); -extern int ide_revalidate(kdev_t i_rdev); -extern void ide_driver_module(void); - -#ifdef CONFIG_PCI -# define ON_BOARD 0 -# define NEVER_BOARD 1 -# ifdef CONFIG_BLK_DEV_OFFBOARD -# define OFF_BOARD ON_BOARD -# else -# define OFF_BOARD NEVER_BOARD -# endif - -void __init ide_scan_pcibus(int scan_direction); -#endif - -static inline void udma_enable(struct ata_device *drive, int on, int verbose) -{ - drive->channel->udma_enable(drive, on, verbose); -} - -static inline void udma_start(struct ata_device *drive, struct request *rq) -{ - drive->channel->udma_start(drive, rq); -} - -static inline int udma_stop(struct ata_device *drive) -{ - int ret; - - ret = drive->channel->udma_stop(drive); - clear_bit(IDE_DMA, drive->channel->active); - - return ret; -} - -/* - * Initiate actual DMA data transfer. The direction is encoded in the request. - */ -static inline ide_startstop_t udma_init(struct ata_device *drive, struct request *rq) -{ - int ret; - - set_bit(IDE_DMA, drive->channel->active); - ret = drive->channel->udma_init(drive, rq); - if (ret != ATA_OP_CONTINUES) - clear_bit(IDE_DMA, drive->channel->active); - - return ret; -} - -static inline int udma_irq_status(struct ata_device *drive) -{ - return drive->channel->udma_irq_status(drive); -} - -static inline void udma_timeout(struct ata_device *drive) -{ - drive->channel->udma_timeout(drive); -} - -static inline void udma_irq_lost(struct ata_device *drive) -{ - drive->channel->udma_irq_lost(drive); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA - -extern void udma_pci_enable(struct ata_device *drive, int on, int verbose); -extern void udma_pci_start(struct ata_device *drive, struct request *rq); -extern int udma_pci_stop(struct ata_device *drive); -extern int udma_pci_init(struct ata_device *drive, struct request *rq); -extern int udma_pci_irq_status(struct ata_device *drive); -extern void udma_pci_timeout(struct ata_device *drive); -extern void udma_pci_irq_lost(struct ata_device *); -extern int udma_pci_setup(struct ata_device *, int); - -extern int udma_generic_setup(struct ata_device *, int); - -extern int udma_new_table(struct ata_device *, struct request *); -extern void udma_destroy_table(struct ata_channel *); -extern void udma_print(struct ata_device *); - -extern int udma_black_list(struct ata_device *); -extern int udma_white_list(struct ata_device *); - -extern ide_startstop_t udma_tcq_init(struct ata_device *, struct request *); -extern int udma_tcq_enable(struct ata_device *, int); - -extern ide_startstop_t ide_dma_intr(struct ata_device *, struct request *); -extern int check_drive_lists(struct ata_device *, int good_bad); -extern void ide_release_dma(struct ata_channel *); -extern int ata_start_dma(struct ata_device *, struct request *rq); - -extern void ata_init_dma(struct ata_channel *, unsigned long) __init; - -#endif - -extern void ata_fix_driveid(struct hd_driveid *); - -extern spinlock_t ide_lock; - -#define DRIVE_LOCK(drive) ((drive)->queue.queue_lock) - -/* Low level device access functions. */ - -extern void ata_select(struct ata_device *, unsigned long); -extern void ata_mask(struct ata_device *); -extern int ata_status(struct ata_device *, u8, u8); -extern int ata_status_irq(struct ata_device *drive); -extern int ata_status_poll( struct ata_device *, u8, u8, - unsigned long, struct request *rq); - -extern int ata_irq_enable(struct ata_device *, int); -extern void ata_reset(struct ata_channel *); -extern void ata_out_regfile(struct ata_device *, struct hd_drive_task_hdr *); -extern void ata_in_regfile(struct ata_device *, struct hd_drive_task_hdr *); - -#endif