Commit 12105c89 authored by Jens Axboe's avatar Jens Axboe

Delete 2.5 IDE core

parent c2480c85
#
# 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
#
# Makefile for the kernel ata, atapi, and ide block device drivers.
#
# 12 September 2000, Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
# Rewritten to use lists instead of if-statements.
#
# Note : at this point, these files are compiled on all systems.
# In the future, some of these should be built conditionally.
#
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
/*
*
* 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 <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#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;
}
/*
* 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 <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#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;
}
}
This diff is collapsed.
This diff is collapsed.
/*
* $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 <vojtech@ucw.cz>, or by paper mail: Vojtech Pavlik,
* Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#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);
}
/**** vi:set ts=8 sts=8 sw=8:************************************************
*
* Copyright (C) 2002 Marcin Dalecki <martin@dalecki.de>
*
* 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 <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/cdrom.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/atapi.h>
#include <asm/byteorder.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
/*
* 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");
/*
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 <arjanv@redhat.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/semaphore.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/genhd.h>
#include <linux/ioctl.h>
#include <linux/kdev_t.h>
#include <linux/swap.h>
#include <linux/buffer_head.h>
#include <linux/ide.h>
#include <asm/uaccess.h>
#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");
/*
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 <arjanv@redhat.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/semaphore.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/genhd.h>
#include <linux/ioctl.h>
#include <linux/ide.h>
#include <asm/uaccess.h>
#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);
/*
* 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 <linux/types.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/zorro.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
/*
* 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<buddha_num_hwifs;i++) {
if(type != BOARD_XSURF) {
ide_setup_ports(&hw, (ide_ioreg_t)(buddha_board+buddha_bases[i]),
buddha_offsets, 0,
(ide_ioreg_t)(buddha_board+buddha_irqports[i]),
buddha_ack_intr, IRQ_AMIGA_PORTS);
} else {
ide_setup_ports(&hw, (ide_ioreg_t)(buddha_board+xsurf_bases[i]),
xsurf_offsets, 0,
(ide_ioreg_t)(buddha_board+xsurf_irqports[i]),
xsurf_ack_intr, IRQ_AMIGA_PORTS);
}
index = ide_register_hw(&hw);
if (index != -1) {
printk("ide%d: ", index);
switch(type) {
case BOARD_BUDDHA:
printk("Buddha");
break;
case BOARD_CATWEASEL:
printk("Catweasel");
break;
case BOARD_XSURF:
printk("X-Surf");
break;
}
printk(" IDE interface\n");
}
}
}
}
This diff is collapsed.
This diff is collapsed.
/**** vi:set ts=8 sts=8 sw=8:************************************************
*
* linux/drivers/ide/cs5530.c Version 0.6 Mar. 18, 2000
*
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
* Ditto of GNU General Public License.
*
* Copyright (C) 2000 Mark Lord <mlord@pobox.com>
* 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 <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#include <asm/irq.h>
#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;
}
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (C) 1996 Linus Torvalds & author (see below)
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#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 <kent@theory.caltech.edu>
*
* 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;
}
/*
* 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 <linux/types.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/setup.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
#include <asm/atari_stdma.h>
/*
* 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);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/**** vi:set ts=8 sts=8 sw=8:************************************************
*
* Copyright (C) 2002 Marcin Dalecki <martin@dalecki.de>
*
* 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);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment