ide: remove the legacy ide driver

The legay ide driver has been replace with libata starting in 2003 and has
been scheduled for removal for a while.  Finally kill it off so that we
can start cleaning up various bits of cruft it forced on the block layer.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Christoph Hellwig
2021-06-16 15:46:58 +02:00
committed by Jens Axboe
parent b90257bfdd
commit b7fb14d3ac
100 changed files with 2 additions and 41173 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -8763,22 +8763,6 @@ L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/busses/i2c-icy.c
IDE SUBSYSTEM
M: "David S. Miller" <davem@davemloft.net>
L: linux-ide@vger.kernel.org
S: Maintained
Q: http://patchwork.ozlabs.org/project/linux-ide/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide.git
F: Documentation/ide/
F: drivers/ide/
F: include/linux/ide.h
IDE/ATAPI DRIVERS
L: linux-ide@vger.kernel.org
S: Orphan
F: Documentation/cdrom/ide-cd.rst
F: drivers/ide/ide-cd*
IDEAPAD LAPTOP EXTRAS DRIVER
M: Ike Panhc <ike.pan@canonical.com>
L: platform-driver-x86@vger.kernel.org

View File

@@ -33,8 +33,6 @@ source "drivers/nvme/Kconfig"
source "drivers/misc/Kconfig"
source "drivers/ide/Kconfig"
source "drivers/scsi/Kconfig"
source "drivers/ata/Kconfig"

View File

@@ -78,7 +78,6 @@ obj-$(CONFIG_CXL_BUS) += cxl/
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
obj-$(CONFIG_NUBUS) += nubus/
obj-y += macintosh/
obj-$(CONFIG_IDE) += ide/
obj-y += scsi/
obj-y += nvme/
obj-$(CONFIG_ATA) += ata/

File diff suppressed because it is too large Load Diff

View File

@@ -1,109 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# link order is important here
#
ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \
ide-io-std.o ide-eh.o
# core IDE code
ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o
ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA_SFF) += ide-dma-sff.o
ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o
ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
ide-core-$(CONFIG_IDE_LEGACY) += ide-legacy.o
obj-$(CONFIG_IDE) += ide-core.o
obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o
obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o
obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o
obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
obj-$(CONFIG_BLK_DEV_4DRIVES) += ide-4drives.o
obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o
obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o
obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o
obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o
obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o
obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o
obj-$(CONFIG_BLK_DEV_ATIIXP) += atiixp.o
obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o
obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o
obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o
obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o
obj-$(CONFIG_BLK_DEV_CS5536) += cs5536.o
obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o
obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o
obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o
obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o
obj-$(CONFIG_BLK_DEV_IT8213) += it8213.o
obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o
obj-$(CONFIG_BLK_DEV_JMICRON) += jmicron.o
obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o
obj-$(CONFIG_BLK_DEV_PDC202XX_NEW) += pdc202xx_new.o
obj-$(CONFIG_BLK_DEV_PIIX) += piix.o
obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o
obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o
obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o
obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o
obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o
obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o
obj-$(CONFIG_BLK_DEV_TC86C001) += tc86c001.o
obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o
obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o
obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o
# Must appear at the end of the block
obj-$(CONFIG_BLK_DEV_GENERIC) += ide-pci-generic.o
obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o
obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o
obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
ide-gd_mod-y += ide-gd.o
ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
ifeq ($(CONFIG_IDE_GD_ATA), y)
ide-gd_mod-y += ide-disk.o ide-disk_ioctl.o
ifeq ($(CONFIG_IDE_PROC_FS), y)
ide-gd_mod-y += ide-disk_proc.o
endif
endif
ifeq ($(CONFIG_IDE_GD_ATAPI), y)
ide-gd_mod-y += ide-floppy.o ide-floppy_ioctl.o
ifeq ($(CONFIG_IDE_PROC_FS), y)
ide-gd_mod-y += ide-floppy_proc.o
endif
endif
obj-$(CONFIG_IDE_GD) += ide-gd_mod.o
obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o
obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o
obj-$(CONFIG_BLK_DEV_PLATFORM) += ide_platform.o
obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710) += palm_bk3710.o
obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o
obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o

View File

@@ -1,331 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
#define DRV_NAME "aec62xx"
struct chipset_bus_clock_list_entry {
u8 xfer_speed;
u8 chipset_settings;
u8 ultra_settings;
};
static const struct chipset_bus_clock_list_entry aec6xxx_33_base [] = {
{ XFER_UDMA_6, 0x31, 0x07 },
{ XFER_UDMA_5, 0x31, 0x06 },
{ XFER_UDMA_4, 0x31, 0x05 },
{ XFER_UDMA_3, 0x31, 0x04 },
{ XFER_UDMA_2, 0x31, 0x03 },
{ XFER_UDMA_1, 0x31, 0x02 },
{ XFER_UDMA_0, 0x31, 0x01 },
{ XFER_MW_DMA_2, 0x31, 0x00 },
{ XFER_MW_DMA_1, 0x31, 0x00 },
{ XFER_MW_DMA_0, 0x0a, 0x00 },
{ XFER_PIO_4, 0x31, 0x00 },
{ XFER_PIO_3, 0x33, 0x00 },
{ XFER_PIO_2, 0x08, 0x00 },
{ XFER_PIO_1, 0x0a, 0x00 },
{ XFER_PIO_0, 0x00, 0x00 },
{ 0, 0x00, 0x00 }
};
static const struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
{ XFER_UDMA_6, 0x41, 0x06 },
{ XFER_UDMA_5, 0x41, 0x05 },
{ XFER_UDMA_4, 0x41, 0x04 },
{ XFER_UDMA_3, 0x41, 0x03 },
{ XFER_UDMA_2, 0x41, 0x02 },
{ XFER_UDMA_1, 0x41, 0x01 },
{ XFER_UDMA_0, 0x41, 0x01 },
{ XFER_MW_DMA_2, 0x41, 0x00 },
{ XFER_MW_DMA_1, 0x42, 0x00 },
{ XFER_MW_DMA_0, 0x7a, 0x00 },
{ XFER_PIO_4, 0x41, 0x00 },
{ XFER_PIO_3, 0x43, 0x00 },
{ XFER_PIO_2, 0x78, 0x00 },
{ XFER_PIO_1, 0x7a, 0x00 },
{ XFER_PIO_0, 0x70, 0x00 },
{ 0, 0x00, 0x00 }
};
/*
* TO DO: active tuning and correction of cards without a bios.
*/
static u8 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 u8 pci_bus_clock_list_ultra (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->ultra_settings;
}
return chipset_table->ultra_settings;
}
static void aec6210_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_host *host = pci_get_drvdata(dev);
struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
u16 d_conf = 0;
u8 ultra = 0, ultra_conf = 0;
u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
const u8 speed = drive->dma_mode;
unsigned long flags;
local_irq_save(flags);
/* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */
pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
tmp0 = pci_bus_clock_list(speed, bus_clock);
d_conf = ((tmp0 & 0xf0) << 4) | (tmp0 & 0xf);
pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
tmp1 = 0x00;
tmp2 = 0x00;
pci_read_config_byte(dev, 0x54, &ultra);
tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
pci_write_config_byte(dev, 0x54, tmp2);
local_irq_restore(flags);
}
static void aec6260_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_host *host = pci_get_drvdata(dev);
struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
u8 unit = drive->dn & 1;
u8 tmp1 = 0, tmp2 = 0;
u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
const u8 speed = drive->dma_mode;
unsigned long flags;
local_irq_save(flags);
/* high 4-bits: Active, low 4-bits: Recovery */
pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
drive_conf = pci_bus_clock_list(speed, bus_clock);
pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
pci_read_config_byte(dev, (0x44|hwif->channel), &ultra);
tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
pci_write_config_byte(dev, (0x44|hwif->channel), tmp2);
local_irq_restore(flags);
}
static void aec_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
drive->dma_mode = drive->pio_mode;
hwif->port_ops->set_dma_mode(hwif, drive);
}
static int init_chipset_aec62xx(struct pci_dev *dev)
{
/* These are necessary to get AEC6280 Macintosh cards to work */
if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
(dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
u8 reg49h = 0, reg4ah = 0;
/* Clear reset and test bits. */
pci_read_config_byte(dev, 0x49, &reg49h);
pci_write_config_byte(dev, 0x49, reg49h & ~0x30);
/* Enable chip interrupt output. */
pci_read_config_byte(dev, 0x4a, &reg4ah);
pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01);
/* Enable burst mode. */
pci_read_config_byte(dev, 0x4a, &reg4ah);
pci_write_config_byte(dev, 0x4a, reg4ah | 0x80);
}
return 0;
}
static u8 atp86x_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
pci_read_config_byte(dev, 0x49, &ata66);
return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
static const struct ide_port_ops atp850_port_ops = {
.set_pio_mode = aec_set_pio_mode,
.set_dma_mode = aec6210_set_mode,
};
static const struct ide_port_ops atp86x_port_ops = {
.set_pio_mode = aec_set_pio_mode,
.set_dma_mode = aec6260_set_mode,
.cable_detect = atp86x_cable_detect,
};
static const struct ide_port_info aec62xx_chipsets[] = {
{ /* 0: AEC6210 */
.name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp850_port_ops,
.host_flags = IDE_HFLAG_SERIALIZE |
IDE_HFLAG_NO_ATAPI_DMA |
IDE_HFLAG_NO_DSC |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
},
{ /* 1: AEC6260 */
.name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
},
{ /* 2: AEC6260R */
.name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
IDE_HFLAG_NON_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
},
{ /* 3: AEC6280 */
.name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
},
{ /* 4: AEC6280R */
.name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
}
};
/**
* aec62xx_init_one - called when a AEC is found
* @dev: the aec62xx device
* @id: the matching pci id
*
* Called when the PCI registration layer (or the IDE initialization)
* finds a device matching our IDE device tables.
*
* NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
* chips, pass a local copy of 'struct ide_port_info' down the call chain.
*/
static int aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
const struct chipset_bus_clock_list_entry *bus_clock;
struct ide_port_info d;
u8 idx = id->driver_data;
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
int err;
if (bus_speed <= 33)
bus_clock = aec6xxx_33_base;
else
bus_clock = aec6xxx_34_base;
err = pci_enable_device(dev);
if (err)
return err;
d = aec62xx_chipsets[idx];
if (idx == 3 || idx == 4) {
unsigned long dma_base = pci_resource_start(dev, 4);
if (inb(dma_base + 2) & 0x10) {
printk(KERN_INFO DRV_NAME " %s: AEC6880%s card detected"
"\n", pci_name(dev), (idx == 4) ? "R" : "");
d.udma_mask = ATA_UDMA6;
}
}
err = ide_pci_init_one(dev, &d, (void *)bus_clock);
if (err)
pci_disable_device(dev);
return err;
}
static void aec62xx_remove(struct pci_dev *dev)
{
ide_pci_remove(dev);
pci_disable_device(dev);
}
static const struct pci_device_id aec62xx_pci_tbl[] = {
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R), 2 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865), 3 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R), 4 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
static struct pci_driver aec62xx_pci_driver = {
.name = "AEC62xx_IDE",
.id_table = aec62xx_pci_tbl,
.probe = aec62xx_init_one,
.remove = aec62xx_remove,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
static int __init aec62xx_ide_init(void)
{
return ide_pci_register_driver(&aec62xx_pci_driver);
}
static void __exit aec62xx_ide_exit(void)
{
pci_unregister_driver(&aec62xx_pci_driver);
}
module_init(aec62xx_ide_init);
module_exit(aec62xx_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for ARTOP AEC62xx IDE");
MODULE_LICENSE("GPL");

View File

@@ -1,250 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* 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 setupDrive function. The initRegisters
* 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/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
#define DRV_NAME "ali14xx"
/* port addresses for auto-detection */
#define ALI_NUM_PORTS 4
static const int ports[ALI_NUM_PORTS] __initconst =
{ 0x074, 0x0f4, 0x034, 0x0e4 };
/* register initialization data */
typedef struct { u8 reg, data; } RegInitializer;
static const RegInitializer initData[] __initconst = {
{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; } regTab[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 basePort; /* base port address */
static int regPort; /* port for register number */
static int dataPort; /* port for register data */
static u8 regOn; /* output to base port to access registers */
static u8 regOff; /* output to base port to close registers */
/*------------------------------------------------------------------------*/
/*
* Read a controller register.
*/
static inline u8 inReg(u8 reg)
{
outb_p(reg, regPort);
return inb(dataPort);
}
/*
* Write a controller register.
*/
static void outReg(u8 data, u8 reg)
{
outb_p(reg, regPort);
outb_p(data, dataPort);
}
static DEFINE_SPINLOCK(ali14xx_lock);
/*
* Set PIO mode for the specified drive.
* This function computes timing parameters
* and sets controller registers accordingly.
*/
static void ali14xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
int driveNum;
int time1, time2;
u8 param1, param2, param3, param4;
unsigned long flags;
int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
const u8 pio = drive->pio_mode - XFER_PIO_0;
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
/* calculate timing, according to PIO mode */
time1 = ide_pio_cycle_time(drive, pio);
time2 = t->active;
param3 = param1 = (time2 * bus_speed + 999) / 1000;
param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
if (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, time1, time2, param1, param2, param3, param4);
/* stuff timing parameters into controller registers */
driveNum = (drive->hwif->index << 1) + (drive->dn & 1);
spin_lock_irqsave(&ali14xx_lock, flags);
outb_p(regOn, basePort);
outReg(param1, regTab[driveNum].reg1);
outReg(param2, regTab[driveNum].reg2);
outReg(param3, regTab[driveNum].reg3);
outReg(param4, regTab[driveNum].reg4);
outb_p(regOff, basePort);
spin_unlock_irqrestore(&ali14xx_lock, flags);
}
/*
* Auto-detect the IDE controller port.
*/
static int __init findPort(void)
{
int i;
u8 t;
unsigned long flags;
local_irq_save(flags);
for (i = 0; i < ALI_NUM_PORTS; ++i) {
basePort = ports[i];
regOff = inb(basePort);
for (regOn = 0x30; regOn <= 0x33; ++regOn) {
outb_p(regOn, basePort);
if (inb(basePort) == regOn) {
regPort = basePort + 4;
dataPort = basePort + 8;
t = inReg(0) & 0xf0;
outb_p(regOff, basePort);
local_irq_restore(flags);
if (t != 0x50)
return 0;
return 1; /* success */
}
}
outb_p(regOff, basePort);
}
local_irq_restore(flags);
return 0;
}
/*
* Initialize controller registers with default values.
*/
static int __init initRegisters(void)
{
const RegInitializer *p;
u8 t;
unsigned long flags;
local_irq_save(flags);
outb_p(regOn, basePort);
for (p = initData; p->reg != 0; ++p)
outReg(p->data, p->reg);
outb_p(0x01, regPort);
t = inb(regPort) & 0x01;
outb_p(regOff, basePort);
local_irq_restore(flags);
return t;
}
static const struct ide_port_ops ali14xx_port_ops = {
.set_pio_mode = ali14xx_set_pio_mode,
};
static const struct ide_port_info ali14xx_port_info = {
.name = DRV_NAME,
.chipset = ide_ali14xx,
.port_ops = &ali14xx_port_ops,
.host_flags = IDE_HFLAG_NO_DMA,
.pio_mask = ATA_PIO4,
};
static int __init ali14xx_probe(void)
{
printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
basePort, regOn);
/* initialize controller registers */
if (!initRegisters()) {
printk(KERN_ERR "ali14xx: Chip initialization failed.\n");
return 1;
}
return ide_legacy_device_add(&ali14xx_port_info, 0);
}
static bool probe_ali14xx;
module_param_named(probe, probe_ali14xx, bool, 0);
MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
static int __init ali14xx_init(void)
{
if (probe_ali14xx == 0)
goto out;
/* auto-detect IDE controller port */
if (findPort()) {
if (ali14xx_probe())
return -ENODEV;
return 0;
}
printk(KERN_ERR "ali14xx: not found.\n");
out:
return -ENODEV;
}
module_init(ali14xx_init);
MODULE_AUTHOR("see local file");
MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -1,343 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
* IDE driver for Linux.
*
* Copyright (c) 2000-2002 Vojtech Pavlik
* Copyright (c) 2007-2010 Bartlomiej Zolnierkiewicz
*
* Based on the work of:
* Andre Hedrick
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
#define DRV_NAME "amd74xx"
enum {
AMD_IDE_CONFIG = 0x41,
AMD_CABLE_DETECT = 0x42,
AMD_DRIVE_TIMING = 0x48,
AMD_8BIT_TIMING = 0x4e,
AMD_ADDRESS_SETUP = 0x4c,
AMD_UDMA_TIMING = 0x50,
};
static unsigned int amd_80w;
static unsigned int amd_clock;
static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
static inline u8 amd_offset(struct pci_dev *dev)
{
return (dev->vendor == PCI_VENDOR_ID_NVIDIA) ? 0x10 : 0;
}
/*
* amd_set_speed() writes timing values to the chipset registers
*/
static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
struct ide_timing *timing)
{
u8 t = 0, offset = amd_offset(dev);
pci_read_config_byte(dev, AMD_ADDRESS_SETUP + offset, &t);
t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t);
pci_write_config_byte(dev, AMD_8BIT_TIMING + offset + (1 - (dn >> 1)),
((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1));
pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn),
((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1));
switch (udma_mask) {
case ATA_UDMA2: t = timing->udma ? (0xc0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break;
case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 2, 10)]) : 0x03; break;
case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 1, 10)]) : 0x03; break;
case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 1, 15)]) : 0x03; break;
default: return;
}
if (timing->udma)
pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + 3 - dn, t);
}
/*
* amd_set_drive() computes timing values and configures the chipset
* to a desired transfer mode. It also can be called by upper layers.
*/
static void amd_set_drive(ide_hwif_t *hwif, ide_drive_t *drive)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
ide_drive_t *peer = ide_get_pair_dev(drive);
struct ide_timing t, p;
int T, UT;
u8 udma_mask = hwif->ultra_mask;
const u8 speed = drive->dma_mode;
T = 1000000000 / amd_clock;
UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
ide_timing_compute(drive, speed, &t, T, UT);
if (peer) {
ide_timing_compute(peer, peer->pio_mode, &p, T, UT);
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
}
if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
amd_set_speed(dev, drive->dn, udma_mask, &t);
}
/*
* amd_set_pio_mode() is a callback from upper layers for PIO-only tuning.
*/
static void amd_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
drive->dma_mode = drive->pio_mode;
amd_set_drive(hwif, drive);
}
static void amd7409_cable_detect(struct pci_dev *dev)
{
/* no host side cable detection */
amd_80w = 0x03;
}
static void amd7411_cable_detect(struct pci_dev *dev)
{
int i;
u32 u = 0;
u8 t = 0, offset = amd_offset(dev);
pci_read_config_byte(dev, AMD_CABLE_DETECT + offset, &t);
pci_read_config_dword(dev, AMD_UDMA_TIMING + offset, &u);
amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
printk(KERN_WARNING DRV_NAME " %s: BIOS didn't set "
"cable bits correctly. Enabling workaround.\n",
pci_name(dev));
amd_80w |= (1 << (1 - (i >> 4)));
}
}
/*
* The initialization callback. Initialize drive independent registers.
*/
static int init_chipset_amd74xx(struct pci_dev *dev)
{
u8 t = 0, offset = amd_offset(dev);
/*
* Check 80-wire cable presence.
*/
if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
; /* no UDMA > 2 */
else if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
amd7409_cable_detect(dev);
else
amd7411_cable_detect(dev);
/*
* Take care of prefetch & postwrite.
*/
pci_read_config_byte(dev, AMD_IDE_CONFIG + offset, &t);
/*
* Check for broken FIFO support.
*/
if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
t &= 0x0f;
else
t |= 0xf0;
pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
return 0;
}
static u8 amd_cable_detect(ide_hwif_t *hwif)
{
if ((amd_80w >> hwif->channel) & 1)
return ATA_CBL_PATA80;
else
return ATA_CBL_PATA40;
}
static const struct ide_port_ops amd_port_ops = {
.set_pio_mode = amd_set_pio_mode,
.set_dma_mode = amd_set_drive,
.cable_detect = amd_cable_detect,
};
#define IDE_HFLAGS_AMD \
(IDE_HFLAG_PIO_NO_BLACKLIST | \
IDE_HFLAG_POST_SET_MODE | \
IDE_HFLAG_IO_32BIT | \
IDE_HFLAG_UNMASK_IRQS)
#define DECLARE_AMD_DEV(swdma, udma) \
{ \
.name = DRV_NAME, \
.init_chipset = init_chipset_amd74xx, \
.enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
.port_ops = &amd_port_ops, \
.host_flags = IDE_HFLAGS_AMD, \
.pio_mask = ATA_PIO5, \
.swdma_mask = swdma, \
.mwdma_mask = ATA_MWDMA2, \
.udma_mask = udma, \
}
#define DECLARE_NV_DEV(udma) \
{ \
.name = DRV_NAME, \
.init_chipset = init_chipset_amd74xx, \
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
.port_ops = &amd_port_ops, \
.host_flags = IDE_HFLAGS_AMD, \
.pio_mask = ATA_PIO5, \
.swdma_mask = ATA_SWDMA2, \
.mwdma_mask = ATA_MWDMA2, \
.udma_mask = udma, \
}
static const struct ide_port_info amd74xx_chipsets[] = {
/* 0: AMD7401 */ DECLARE_AMD_DEV(0x00, ATA_UDMA2),
/* 1: AMD7409 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
/* 2: AMD7411/7441 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
/* 3: AMD8111 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA6),
/* 4: NFORCE */ DECLARE_NV_DEV(ATA_UDMA5),
/* 5: >= NFORCE2 */ DECLARE_NV_DEV(ATA_UDMA6),
/* 6: AMD5536 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
};
static int amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct ide_port_info d;
u8 idx = id->driver_data;
d = amd74xx_chipsets[idx];
/*
* Check for bad SWDMA and incorrectly wired Serenade mainboards.
*/
if (idx == 1) {
if (dev->revision <= 7)
d.swdma_mask = 0;
d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
} else if (idx == 3) {
if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
d.udma_mask = ATA_UDMA5;
}
/*
* It seems that on some nVidia controllers using AltStatus
* register can be unreliable so default to Status register
* if the device is in Compatibility Mode.
*/
if (dev->vendor == PCI_VENDOR_ID_NVIDIA &&
ide_pci_is_in_compatibility_mode(dev))
d.host_flags |= IDE_HFLAG_BROKEN_ALTSTATUS;
printk(KERN_INFO "%s %s: UDMA%s controller\n",
d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]);
/*
* Determine the system bus clock.
*/
amd_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
switch (amd_clock) {
case 33000: amd_clock = 33333; break;
case 37000: amd_clock = 37500; break;
case 41000: amd_clock = 41666; break;
}
if (amd_clock < 20000 || amd_clock > 50000) {
printk(KERN_WARNING "%s: User given PCI clock speed impossible"
" (%d), using 33 MHz instead.\n",
d.name, amd_clock);
amd_clock = 33333;
}
return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id amd74xx_pci_tbl[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7411), 2 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_OPUS_7441), 2 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_8111_IDE), 3 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE), 4 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE), 5 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), 5 },
#endif
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE), 5 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), 5 },
#endif
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 5 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 5 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 6 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
static struct pci_driver amd74xx_pci_driver = {
.name = "AMD_IDE",
.id_table = amd74xx_pci_tbl,
.probe = amd74xx_probe,
.remove = ide_pci_remove,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
static int __init amd74xx_ide_init(void)
{
return ide_pci_register_driver(&amd74xx_pci_driver);
}
static void __exit amd74xx_ide_exit(void)
{
pci_unregister_driver(&amd74xx_pci_driver);
}
module_init(amd74xx_ide_init);
module_exit(amd74xx_ide_exit);
MODULE_AUTHOR("Vojtech Pavlik, Bartlomiej Zolnierkiewicz");
MODULE_DESCRIPTION("AMD PCI IDE driver");
MODULE_LICENSE("GPL");

View File

@@ -1,212 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2003 ATI Inc. <hyu@ati.com>
* Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
#define DRV_NAME "atiixp"
#define ATIIXP_IDE_PIO_TIMING 0x40
#define ATIIXP_IDE_MDMA_TIMING 0x44
#define ATIIXP_IDE_PIO_CONTROL 0x48
#define ATIIXP_IDE_PIO_MODE 0x4a
#define ATIIXP_IDE_UDMA_CONTROL 0x54
#define ATIIXP_IDE_UDMA_MODE 0x56
struct atiixp_ide_timing {
u8 command_width;
u8 recover_width;
};
static struct atiixp_ide_timing pio_timing[] = {
{ 0x05, 0x0d },
{ 0x04, 0x07 },
{ 0x03, 0x04 },
{ 0x02, 0x02 },
{ 0x02, 0x00 },
};
static struct atiixp_ide_timing mdma_timing[] = {
{ 0x07, 0x07 },
{ 0x02, 0x01 },
{ 0x02, 0x00 },
};
static DEFINE_SPINLOCK(atiixp_lock);
/**
* atiixp_set_pio_mode - set host controller for PIO mode
* @hwif: port
* @drive: drive
*
* Set the interface PIO mode.
*/
static void atiixp_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long flags;
int timing_shift = (drive->dn ^ 1) * 8;
u32 pio_timing_data;
u16 pio_mode_data;
const u8 pio = drive->pio_mode - XFER_PIO_0;
spin_lock_irqsave(&atiixp_lock, flags);
pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
pio_mode_data &= ~(0x07 << (drive->dn * 4));
pio_mode_data |= (pio << (drive->dn * 4));
pci_write_config_word(dev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
pci_read_config_dword(dev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
pio_timing_data &= ~(0xff << timing_shift);
pio_timing_data |= (pio_timing[pio].recover_width << timing_shift) |
(pio_timing[pio].command_width << (timing_shift + 4));
pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
spin_unlock_irqrestore(&atiixp_lock, flags);
}
/**
* atiixp_set_dma_mode - set host controller for DMA mode
* @hwif: port
* @drive: drive
*
* Set a ATIIXP host controller to the desired DMA mode. This involves
* programming the right timing data into the PCI configuration space.
*/
static void atiixp_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long flags;
int timing_shift = (drive->dn ^ 1) * 8;
u32 tmp32;
u16 tmp16;
u16 udma_ctl = 0;
const u8 speed = drive->dma_mode;
spin_lock_irqsave(&atiixp_lock, flags);
pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_ctl);
if (speed >= XFER_UDMA_0) {
pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
tmp16 &= ~(0x07 << (drive->dn * 4));
tmp16 |= ((speed & 0x07) << (drive->dn * 4));
pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
udma_ctl |= (1 << drive->dn);
} else if (speed >= XFER_MW_DMA_0) {
u8 i = speed & 0x03;
pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
tmp32 &= ~(0xff << timing_shift);
tmp32 |= (mdma_timing[i].recover_width << timing_shift) |
(mdma_timing[i].command_width << (timing_shift + 4));
pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
udma_ctl &= ~(1 << drive->dn);
}
pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, udma_ctl);
spin_unlock_irqrestore(&atiixp_lock, flags);
}
static u8 atiixp_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
u8 udma_mode = 0, ch = hwif->channel;
pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
return ATA_CBL_PATA80;
else
return ATA_CBL_PATA40;
}
static const struct ide_port_ops atiixp_port_ops = {
.set_pio_mode = atiixp_set_pio_mode,
.set_dma_mode = atiixp_set_dma_mode,
.cable_detect = atiixp_cable_detect,
};
static const struct ide_port_info atiixp_pci_info[] = {
{ /* 0: IXP200/300/400/700 */
.name = DRV_NAME,
.enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
.port_ops = &atiixp_port_ops,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
},
{ /* 1: IXP600 */
.name = DRV_NAME,
.enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
.port_ops = &atiixp_port_ops,
.host_flags = IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
},
};
/**
* atiixp_init_one - called when a ATIIXP is found
* @dev: the atiixp device
* @id: the matching pci id
*
* Called when the PCI registration layer (or the IDE initialization)
* finds a device matching our IDE device tables.
*/
static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
return ide_pci_init_one(dev, &atiixp_pci_info[id->driver_data], NULL);
}
static const struct pci_device_id atiixp_pci_tbl[] = {
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP200_IDE), 0 },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), 0 },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), 0 },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), 1 },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), 0 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_HUDSON2_IDE), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
static struct pci_driver atiixp_pci_driver = {
.name = "ATIIXP_IDE",
.id_table = atiixp_pci_tbl,
.probe = atiixp_init_one,
.remove = ide_pci_remove,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
static int __init atiixp_ide_init(void)
{
return ide_pci_register_driver(&atiixp_pci_driver);
}
static void __exit atiixp_ide_exit(void)
{
pci_unregister_driver(&atiixp_pci_driver);
}
module_init(atiixp_ide_init);
module_exit(atiixp_ide_exit);
MODULE_AUTHOR("HUI YU");
MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
MODULE_LICENSE("GPL");

View File

@@ -1,238 +0,0 @@
/*
* 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/zorro.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.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
#define MAX_NUM_HWIFS 3
/*
* 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_CONTROL 0x11a
/*
* 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;
static const char *buddha_board_name[] = { "Buddha", "Catweasel", "X-Surf" };
/*
* Check and acknowledge the interrupt status
*/
static int buddha_test_irq(ide_hwif_t *hwif)
{
unsigned char ch;
ch = z_readb(hwif->io_ports.irq_addr);
if (!(ch & 0x80))
return 0;
return 1;
}
static void xsurf_clear_irq(ide_drive_t *drive)
{
/*
* X-Surf needs 0 written to IRQ register to ensure ISA bit A11 stays at 0
*/
z_writeb(0, drive->hwif->io_ports.irq_addr);
}
static void __init buddha_setup_ports(struct ide_hw *hw, unsigned long base,
unsigned long ctl, unsigned long irq_port)
{
int i;
memset(hw, 0, sizeof(*hw));
hw->io_ports.data_addr = base;
for (i = 1; i < 8; i++)
hw->io_ports_array[i] = base + 2 + i * 4;
hw->io_ports.ctl_addr = ctl;
hw->io_ports.irq_addr = irq_port;
hw->irq = IRQ_AMIGA_PORTS;
}
static const struct ide_port_ops buddha_port_ops = {
.test_irq = buddha_test_irq,
};
static const struct ide_port_ops xsurf_port_ops = {
.clear_irq = xsurf_clear_irq,
.test_irq = buddha_test_irq,
};
static const struct ide_port_info buddha_port_info = {
.port_ops = &buddha_port_ops,
.host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
.irq_flags = IRQF_SHARED,
.chipset = ide_generic,
};
/*
* Probe for a Buddha or Catweasel IDE interface
*/
static int __init buddha_init(void)
{
struct zorro_dev *z = NULL;
u_long buddha_board = 0;
BuddhaType type;
int buddha_num_hwifs, i;
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
unsigned long board;
struct ide_hw hw[MAX_NUM_HWIFS], *hws[MAX_NUM_HWIFS];
struct ide_port_info d = buddha_port_info;
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;
d.port_ops = &xsurf_port_ops;
} 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 = (unsigned long)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);
printk(KERN_INFO "ide: %s IDE controller\n",
buddha_board_name[type]);
for (i = 0; i < buddha_num_hwifs; i++) {
unsigned long base, ctl, irq_port;
if (type != BOARD_XSURF) {
base = buddha_board + buddha_bases[i];
ctl = base + BUDDHA_CONTROL;
irq_port = buddha_board + buddha_irqports[i];
} else {
base = buddha_board + xsurf_bases[i];
/* X-Surf has no CS1* (Control/AltStat) */
ctl = 0;
irq_port = buddha_board + xsurf_irqports[i];
}
buddha_setup_ports(&hw[i], base, ctl, irq_port);
hws[i] = &hw[i];
}
ide_host_add(&d, hws, i, NULL);
}
return 0;
}
module_init(buddha_init);
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -1,452 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported
* on the 646U2 and not on the 646U.
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
*
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
* Copyright (C) 2007,2009 MontaVista Software, Inc. <source@mvista.com>
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
#define DRV_NAME "cmd64x"
/*
* CMD64x specific registers definition.
*/
#define CFR 0x50
#define CFR_INTR_CH0 0x04
#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 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 UDIDETCR0 0x73
#define DTPR0 0x74
#define BMIDECR1 0x78
#define BMIDECSR 0x79
#define UDIDETCR1 0x7B
#define DTPR1 0x7C
static void cmd64x_program_timings(ide_drive_t *drive, u8 mode)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
const unsigned long T = 1000000 / bus_speed;
static const u8 recovery_values[] =
{15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
struct ide_timing t;
u8 arttim = 0;
if (drive->dn >= ARRAY_SIZE(drwtim_regs))
return;
ide_timing_compute(drive, mode, &t, T, 0);
/*
* In case we've got too long recovery phase, try to lengthen
* the active phase
*/
if (t.recover > 16) {
t.active += t.recover - 16;
t.recover = 16;
}
if (t.active > 16) /* shouldn't actually happen... */
t.active = 16;
/*
* Convert values to internal chipset representation
*/
t.recover = recovery_values[t.recover];
t.active &= 0x0f;
/* Program the active/recovery counts into the DRWTIM register */
pci_write_config_byte(dev, drwtim_regs[drive->dn],
(t.active << 4) | t.recover);
/*
* The primary channel has individual address setup timing registers
* for each drive and the hardware selects the slowest timing itself.
* The secondary channel has one common register and we have to select
* the slowest address setup timing ourselves.
*/
if (hwif->channel) {
ide_drive_t *pair = ide_get_pair_dev(drive);
if (pair) {
struct ide_timing tp;
ide_timing_compute(pair, pair->pio_mode, &tp, T, 0);
ide_timing_merge(&t, &tp, &t, IDE_TIMING_SETUP);
if (pair->dma_mode) {
ide_timing_compute(pair, pair->dma_mode,
&tp, T, 0);
ide_timing_merge(&tp, &t, &t, IDE_TIMING_SETUP);
}
}
}
if (t.setup > 5) /* shouldn't actually happen... */
t.setup = 5;
/*
* Program the address setup clocks into the ARTTIM registers.
* Avoid clearing the secondary channel's interrupt bit.
*/
(void) pci_read_config_byte (dev, arttim_regs[drive->dn], &arttim);
if (hwif->channel)
arttim &= ~ARTTIM23_INTR_CH1;
arttim &= ~0xc0;
arttim |= setup_values[t.setup];
(void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
}
/*
* Attempts to set drive's PIO mode.
* Special cases are 8: prefetch off, 9: prefetch on (both never worked)
*/
static void cmd64x_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
const u8 pio = drive->pio_mode - XFER_PIO_0;
/*
* Filter out the prefetch control values
* to prevent PIO5 from being programmed
*/
if (pio == 8 || pio == 9)
return;
cmd64x_program_timings(drive, XFER_PIO_0 + pio);
}
static void cmd64x_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 unit = drive->dn & 0x01;
u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0;
const u8 speed = drive->dma_mode;
pci_read_config_byte(dev, pciU, &regU);
regU &= ~(unit ? 0xCA : 0x35);
switch(speed) {
case XFER_UDMA_5:
regU |= unit ? 0x0A : 0x05;
break;
case XFER_UDMA_4:
regU |= unit ? 0x4A : 0x15;
break;
case XFER_UDMA_3:
regU |= unit ? 0x8A : 0x25;
break;
case XFER_UDMA_2:
regU |= unit ? 0x42 : 0x11;
break;
case XFER_UDMA_1:
regU |= unit ? 0x82 : 0x21;
break;
case XFER_UDMA_0:
regU |= unit ? 0xC2 : 0x31;
break;
case XFER_MW_DMA_2:
case XFER_MW_DMA_1:
case XFER_MW_DMA_0:
cmd64x_program_timings(drive, speed);
break;
}
pci_write_config_byte(dev, pciU, regU);
}
static void cmd648_clear_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long base = pci_resource_start(dev, 4);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
u8 mrdmode = inb(base + 1);
/* clear the interrupt bit */
outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
base + 1);
}
static void cmd64x_clear_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
u8 irq_stat = 0;
(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
/* clear the interrupt bit */
(void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
}
static int cmd648_test_irq(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long base = pci_resource_start(dev, 4);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
u8 mrdmode = inb(base + 1);
pr_debug("%s: mrdmode: 0x%02x irq_mask: 0x%02x\n",
hwif->name, mrdmode, irq_mask);
return (mrdmode & irq_mask) ? 1 : 0;
}
static int cmd64x_test_irq(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
u8 irq_stat = 0;
(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
pr_debug("%s: irq_stat: 0x%02x irq_mask: 0x%02x\n",
hwif->name, irq_stat, irq_mask);
return (irq_stat & irq_mask) ? 1 : 0;
}
/*
* ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
* event order for DMA transfers.
*/
static int cmd646_1_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u8 dma_stat = 0, dma_cmd = 0;
/* get DMA status */
dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* read DMA command state */
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
/* clear the INTR & ERROR bits */
outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
/* verify good DMA status */
return (dma_stat & 7) != 4;
}
static int init_chipset_cmd64x(struct pci_dev *dev)
{
u8 mrdmode = 0;
/* Set a good latency timer and cache line size value. */
(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
/* FIXME: pci_set_master() to ensure a good latency timer value */
/*
* Enable interrupts, select MEMORY READ LINE for reads.
*
* NOTE: although not mentioned in the PCI0646U specs,
* bits 0-1 are write only and won't be read back as
* set or not -- PCI0646U2 specs clarify this point.
*/
(void) pci_read_config_byte (dev, MRDMODE, &mrdmode);
mrdmode &= ~0x30;
(void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
return 0;
}
static u8 cmd64x_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01;
switch (dev->device) {
case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_649:
pci_read_config_byte(dev, BMIDECSR, &bmidecsr);
return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
default:
return ATA_CBL_PATA40;
}
}
static const struct ide_port_ops cmd64x_port_ops = {
.set_pio_mode = cmd64x_set_pio_mode,
.set_dma_mode = cmd64x_set_dma_mode,
.clear_irq = cmd64x_clear_irq,
.test_irq = cmd64x_test_irq,
.cable_detect = cmd64x_cable_detect,
};
static const struct ide_port_ops cmd648_port_ops = {
.set_pio_mode = cmd64x_set_pio_mode,
.set_dma_mode = cmd64x_set_dma_mode,
.clear_irq = cmd648_clear_irq,
.test_irq = cmd648_test_irq,
.cable_detect = cmd64x_cable_detect,
};
static const struct ide_dma_ops cmd646_rev1_dma_ops = {
.dma_host_set = ide_dma_host_set,
.dma_setup = ide_dma_setup,
.dma_start = ide_dma_start,
.dma_end = cmd646_1_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timer_expiry = ide_dma_sff_timer_expiry,
.dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info cmd64x_chipsets[] = {
{ /* 0: CMD643 */
.name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
.host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
IDE_HFLAG_ABUSE_PREFETCH |
IDE_HFLAG_SERIALIZE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* no udma */
},
{ /* 1: CMD646 */
.name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd648_port_ops,
.host_flags = IDE_HFLAG_ABUSE_PREFETCH |
IDE_HFLAG_SERIALIZE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
},
{ /* 2: CMD648 */
.name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd648_port_ops,
.host_flags = IDE_HFLAG_ABUSE_PREFETCH,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
},
{ /* 3: CMD649 */
.name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd648_port_ops,
.host_flags = IDE_HFLAG_ABUSE_PREFETCH,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
}
};
static int cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
struct ide_port_info d;
u8 idx = id->driver_data;
d = cmd64x_chipsets[idx];
if (idx == 1) {
/*
* 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.
*/
if (dev->revision < 5) {
d.udma_mask = 0x00;
/*
* The original PCI0646 didn't have the primary
* channel enable bit, it appeared starting with
* PCI0646U (i.e. revision ID 3).
*/
if (dev->revision < 3) {
d.enablebits[0].reg = 0;
d.port_ops = &cmd64x_port_ops;
if (dev->revision == 1)
d.dma_ops = &cmd646_rev1_dma_ops;
}
}
}
return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id cmd64x_pci_tbl[] = {
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 },
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 2 },
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 3 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
static struct pci_driver cmd64x_pci_driver = {
.name = "CMD64x_IDE",
.id_table = cmd64x_pci_tbl,
.probe = cmd64x_init_one,
.remove = ide_pci_remove,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
static int __init cmd64x_ide_init(void)
{
return ide_pci_register_driver(&cmd64x_pci_driver);
}
static void __exit cmd64x_ide_exit(void)
{
pci_unregister_driver(&cmd64x_pci_driver);
}
module_init(cmd64x_ide_init);
module_exit(cmd64x_ide_exit);
MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick, Bartlomiej Zolnierkiewicz");
MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
MODULE_LICENSE("GPL");

View File

@@ -1,168 +0,0 @@
/*
* IDE tuning and bus mastering support for the CS5510/CS5520
* chipsets
*
* The CS5510/CS5520 are slightly unusual devices. Unlike the
* typical IDE controllers they do bus mastering with the drive in
* PIO mode and smarter silicon.
*
* The practical upshot of this is that we must always tune the
* drive for the right PIO mode. We must also ignore all the blacklists
* and the drive bus mastering DMA information.
*
* *** This driver is strictly experimental ***
*
* (c) Copyright Red Hat Inc 2002
*
* 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.
*
* 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.
*
* For the avoidance of doubt the "preferred form" of this code is one which
* is in an open non patent encumbered format. Where cryptographic key signing
* forms part of the process of creating an executable the information
* including keys needed to generate an equivalently functional executable
* are deemed to be part of the source code.
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/dma-mapping.h>
#define DRV_NAME "cs5520"
struct pio_clocks
{
int address;
int assert;
int recovery;
};
static struct pio_clocks cs5520_pio_clocks[]={
{3, 6, 11},
{2, 5, 6},
{1, 4, 3},
{1, 3, 2},
{1, 2, 1}
};
static void cs5520_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
int controller = drive->dn > 1 ? 1 : 0;
const u8 pio = drive->pio_mode - XFER_PIO_0;
/* 8bit CAT/CRT - 8bit command timing for channel */
pci_write_config_byte(pdev, 0x62 + controller,
(cs5520_pio_clocks[pio].recovery << 4) |
(cs5520_pio_clocks[pio].assert));
/* 0x64 - 16bit Primary, 0x68 - 16bit Secondary */
/* FIXME: should these use address ? */
/* Data read timing */
pci_write_config_byte(pdev, 0x64 + 4*controller + (drive->dn&1),
(cs5520_pio_clocks[pio].recovery << 4) |
(cs5520_pio_clocks[pio].assert));
/* Write command timing */
pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1),
(cs5520_pio_clocks[pio].recovery << 4) |
(cs5520_pio_clocks[pio].assert));
}
static void cs5520_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
printk(KERN_ERR "cs55x0: bad ide timing.\n");
drive->pio_mode = XFER_PIO_0 + 0;
cs5520_set_pio_mode(hwif, drive);
}
static const struct ide_port_ops cs5520_port_ops = {
.set_pio_mode = cs5520_set_pio_mode,
.set_dma_mode = cs5520_set_dma_mode,
};
static const struct ide_port_info cyrix_chipset = {
.name = DRV_NAME,
.enablebits = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } },
.port_ops = &cs5520_port_ops,
.host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_CS5520,
.pio_mask = ATA_PIO4,
};
/*
* The 5510/5520 are a bit weird. They don't quite set up the way
* the PCI helper layer expects so we must do much of the set up
* work longhand.
*/
static int cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
const struct ide_port_info *d = &cyrix_chipset;
struct ide_hw hw[2], *hws[] = { NULL, NULL };
ide_setup_pci_noise(dev, d);
/* We must not grab the entire device, it has 'ISA' space in its
* BARS too and we will freak out other bits of the kernel
*/
if (pci_enable_device_io(dev)) {
printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
return -ENODEV;
}
pci_set_master(dev);
if (dma_set_mask(&dev->dev, DMA_BIT_MASK(32))) {
printk(KERN_WARNING "%s: No suitable DMA available.\n",
d->name);
return -ENODEV;
}
/*
* Now the chipset is configured we can let the core
* do all the device setup for us
*/
ide_pci_setup_ports(dev, d, &hw[0], &hws[0]);
hw[0].irq = 14;
hw[1].irq = 15;
return ide_host_add(d, hws, 2, NULL);
}
static const struct pci_device_id cs5520_pci_tbl[] = {
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), 0 },
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5520), 1 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
static struct pci_driver cs5520_pci_driver = {
.name = "Cyrix_IDE",
.id_table = cs5520_pci_tbl,
.probe = cs5520_init_one,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
static int __init cs5520_ide_init(void)
{
return ide_pci_register_driver(&cs5520_pci_driver);
}
module_init(cs5520_ide_init);
MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("PCI driver module for Cyrix 5510/5520 IDE");
MODULE_LICENSE("GPL");

View File

@@ -1,295 +0,0 @@
/*
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2000 Mark Lord <mlord@pobox.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
* 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.
*
* Documentation:
* CS5530 documentation available from National Semiconductor.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <asm/io.h>
#define DRV_NAME "cs5530"
/*
* Here are the standard PIO mode 0-4 timings for each "format".
* Format-0 uses fast data reg timings, with slower command reg timings.
* 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(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
/**
* cs5530_set_pio_mode - set host controller for PIO mode
* @hwif: port
* @drive: drive
*
* Handles setting of PIO mode for the chipset.
*
* The init_hwif_cs5530() routine guarantees that all drives
* will have valid default PIO timings set up before we get here.
*/
static void cs5530_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
unsigned long basereg = CS5530_BASEREG(hwif);
unsigned int format = (inl(basereg + 4) >> 31) & 1;
const u8 pio = drive->pio_mode - XFER_PIO_0;
outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
}
/**
* cs5530_udma_filter - UDMA filter
* @drive: drive
*
* cs5530_udma_filter() does UDMA mask filtering for the given drive
* taking into the consideration capabilities of the mate device.
*
* 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.
*
* Note: This relies on the fact we never fail from UDMA to MWDMA2
* but instead drop to PIO.
*/
static u8 cs5530_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
ide_drive_t *mate = ide_get_pair_dev(drive);
u16 *mateid;
u8 mask = hwif->ultra_mask;
if (mate == NULL)
goto out;
mateid = mate->id;
if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
(mateid[ATA_ID_UDMA_MODES] & 7))
goto out;
if (mateid[ATA_ID_MWDMA_MODES] & 7)
mask = 0;
}
out:
return mask;
}
static void cs5530_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
unsigned long basereg;
unsigned int reg, timings = 0;
switch (drive->dma_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;
}
basereg = CS5530_BASEREG(hwif);
reg = inl(basereg + 4); /* get drive0 config register */
timings |= reg & 0x80000000; /* preserve PIO format bit */
if ((drive-> dn & 1) == 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 */
}
}
/**
* init_chipset_5530 - set up 5530 bridge
* @dev: PCI device
*
* Initialize the cs5530 bridge for reliable IDE DMA operation.
*/
static int init_chipset_cs5530(struct pci_dev *dev)
{
struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
if (pci_resource_start(dev, 4) == 0)
return -EFAULT;
dev = NULL;
while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
switch (dev->device) {
case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
master_0 = pci_dev_get(dev);
break;
case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
cs5530_0 = pci_dev_get(dev);
break;
}
}
if (!master_0) {
printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
goto out;
}
if (!cs5530_0) {
printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
goto out;
}
/*
* 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_try_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);
out:
pci_dev_put(master_0);
pci_dev_put(cs5530_0);
return 0;
}
/**
* init_hwif_cs5530 - initialise an IDE channel
* @hwif: IDE to initialize
*
* This gets invoked by the IDE driver once for each channel. It
* performs channel-specific pre-initialization before drive probing.
*/
static void init_hwif_cs5530 (ide_hwif_t *hwif)
{
unsigned long basereg;
u32 d0_timings;
basereg = CS5530_BASEREG(hwif);
d0_timings = inl(basereg + 0);
if (CS5530_BAD_PIO(d0_timings))
outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
if (CS5530_BAD_PIO(inl(basereg + 8)))
outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
}
static const struct ide_port_ops cs5530_port_ops = {
.set_pio_mode = cs5530_set_pio_mode,
.set_dma_mode = cs5530_set_dma_mode,
.udma_filter = cs5530_udma_filter,
};
static const struct ide_port_info cs5530_chipset = {
.name = DRV_NAME,
.init_chipset = init_chipset_cs5530,
.init_hwif = init_hwif_cs5530,
.port_ops = &cs5530_port_ops,
.host_flags = IDE_HFLAG_SERIALIZE |
IDE_HFLAG_POST_SET_MODE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
};
static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
return ide_pci_init_one(dev, &cs5530_chipset, NULL);
}
static const struct pci_device_id cs5530_pci_tbl[] = {
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
static struct pci_driver cs5530_pci_driver = {
.name = "CS5530 IDE",
.id_table = cs5530_pci_tbl,
.probe = cs5530_init_one,
.remove = ide_pci_remove,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
static int __init cs5530_ide_init(void)
{
return ide_pci_register_driver(&cs5530_pci_driver);
}
static void __exit cs5530_ide_exit(void)
{
pci_unregister_driver(&cs5530_pci_driver);
}
module_init(cs5530_ide_init);
module_exit(cs5530_ide_exit);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE");
MODULE_LICENSE("GPL");

View File

@@ -1,216 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2004-2005 Advanced Micro Devices, Inc.
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
* History:
* 09/20/2005 - Jaya Kumar <jayakumar.ide@gmail.com>
* - Reworked tuneproc, set_drive, misc mods to prep for mainline
* - Work was sponsored by CIS (M) Sdn Bhd.
* Ported to Kernel 2.6.11 on June 26, 2005 by
* Wolfgang Zuleger <wolfgang.zuleger@gmx.de>
* Alexander Kiausch <alex.kiausch@t-online.de>
* Originally developed by AMD for 2.4/2.6
*
* Development of this chipset driver was funded
* by the nice folks at National Semiconductor/AMD.
*
* Documentation:
* CS5535 documentation available from AMD
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DRV_NAME "cs5535"
#define MSR_ATAC_BASE 0x51300000
#define ATAC_GLD_MSR_CAP (MSR_ATAC_BASE+0)
#define ATAC_GLD_MSR_CONFIG (MSR_ATAC_BASE+0x01)
#define ATAC_GLD_MSR_SMI (MSR_ATAC_BASE+0x02)
#define ATAC_GLD_MSR_ERROR (MSR_ATAC_BASE+0x03)
#define ATAC_GLD_MSR_PM (MSR_ATAC_BASE+0x04)
#define ATAC_GLD_MSR_DIAG (MSR_ATAC_BASE+0x05)
#define ATAC_IO_BAR (MSR_ATAC_BASE+0x08)
#define ATAC_RESET (MSR_ATAC_BASE+0x10)
#define ATAC_CH0D0_PIO (MSR_ATAC_BASE+0x20)
#define ATAC_CH0D0_DMA (MSR_ATAC_BASE+0x21)
#define ATAC_CH0D1_PIO (MSR_ATAC_BASE+0x22)
#define ATAC_CH0D1_DMA (MSR_ATAC_BASE+0x23)
#define ATAC_PCI_ABRTERR (MSR_ATAC_BASE+0x24)
#define ATAC_BM0_CMD_PRIM 0x00
#define ATAC_BM0_STS_PRIM 0x02
#define ATAC_BM0_PRD 0x04
#define CS5535_CABLE_DETECT 0x48
/* Format I PIO settings. We separate out cmd and data for safer timings */
static unsigned int cs5535_pio_cmd_timings[5] =
{ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 };
static unsigned int cs5535_pio_dta_timings[5] =
{ 0xF7F4, 0xF173, 0x8141, 0x5131, 0x1131 };
static unsigned int cs5535_mwdma_timings[3] =
{ 0x7F0FFFF3, 0x7F035352, 0x7f024241 };
static unsigned int cs5535_udma_timings[5] =
{ 0x7F7436A1, 0x7F733481, 0x7F723261, 0x7F713161, 0x7F703061 };
/* Macros to check if the register is the reset value - reset value is an
invalid timing and indicates the register has not been set previously */
#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL) == 0x00009172 )
#define CS5535_BAD_DMA(timings) ( (timings & 0x000FFFFF) == 0x00077771 )
/****
* cs5535_set_speed - Configure the chipset to the new speed
* @drive: Drive to set up
* @speed: desired speed
*
* cs5535_set_speed() configures the chipset to a new speed.
*/
static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
{
u32 reg = 0, dummy;
u8 unit = drive->dn & 1;
/* Set the PIO timings */
if (speed < XFER_SW_DMA_0) {
ide_drive_t *pair = ide_get_pair_dev(drive);
u8 cmd, pioa;
cmd = pioa = speed - XFER_PIO_0;
if (pair) {
u8 piob = pair->pio_mode - XFER_PIO_0;
if (piob < cmd)
cmd = piob;
}
/* Write the speed of the current drive */
reg = (cs5535_pio_cmd_timings[cmd] << 16) |
cs5535_pio_dta_timings[pioa];
wrmsr(unit ? ATAC_CH0D1_PIO : ATAC_CH0D0_PIO, reg, 0);
/* And if nessesary - change the speed of the other drive */
rdmsr(unit ? ATAC_CH0D0_PIO : ATAC_CH0D1_PIO, reg, dummy);
if (((reg >> 16) & cs5535_pio_cmd_timings[cmd]) !=
cs5535_pio_cmd_timings[cmd]) {
reg &= 0x0000FFFF;
reg |= cs5535_pio_cmd_timings[cmd] << 16;
wrmsr(unit ? ATAC_CH0D0_PIO : ATAC_CH0D1_PIO, reg, 0);
}
/* Set bit 31 of the DMA register for PIO format 1 timings */
rdmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, dummy);
wrmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA,
reg | 0x80000000UL, 0);
} else {
rdmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, dummy);
reg &= 0x80000000UL; /* Preserve the PIO format bit */
if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_4)
reg |= cs5535_udma_timings[speed - XFER_UDMA_0];
else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
reg |= cs5535_mwdma_timings[speed - XFER_MW_DMA_0];
else
return;
wrmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, 0);
}
}
/**
* cs5535_set_dma_mode - set host controller for DMA mode
* @hwif: port
* @drive: drive
*
* Programs the chipset for DMA mode.
*/
static void cs5535_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
cs5535_set_speed(drive, drive->dma_mode);
}
/**
* cs5535_set_pio_mode - set host controller for PIO mode
* @hwif: port
* @drive: drive
*
* A callback from the upper layers for PIO-only tuning.
*/
static void cs5535_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
cs5535_set_speed(drive, drive->pio_mode);
}
static u8 cs5535_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 bit;
/* if a 80 wire cable was detected */
pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
static const struct ide_port_ops cs5535_port_ops = {
.set_pio_mode = cs5535_set_pio_mode,
.set_dma_mode = cs5535_set_dma_mode,
.cable_detect = cs5535_cable_detect,
};
static const struct ide_port_info cs5535_chipset = {
.name = DRV_NAME,
.port_ops = &cs5535_port_ops,
.host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
};
static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
return ide_pci_init_one(dev, &cs5535_chipset, NULL);
}
static const struct pci_device_id cs5535_pci_tbl[] = {
{ PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_CS5535_IDE), 0 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5535_IDE), },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl);
static struct pci_driver cs5535_pci_driver = {
.name = "CS5535_IDE",
.id_table = cs5535_pci_tbl,
.probe = cs5535_init_one,
.remove = ide_pci_remove,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
static int __init cs5535_ide_init(void)
{
return ide_pci_register_driver(&cs5535_pci_driver);
}
static void __exit cs5535_ide_exit(void)
{
pci_unregister_driver(&cs5535_pci_driver);
}
module_init(cs5535_ide_init);
module_exit(cs5535_ide_exit);
MODULE_AUTHOR("AMD");
MODULE_DESCRIPTION("PCI driver module for AMD/NS CS5535 IDE");
MODULE_LICENSE("GPL");

View File

@@ -1,294 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* CS5536 PATA support
* (C) 2007 Martin K. Petersen <mkp@mkp.net>
* (C) 2009 Bartlomiej Zolnierkiewicz
*
* Documentation:
* Available from AMD web site.
*
* The IDE timing registers for the CS5536 live in the Geode Machine
* Specific Register file and not PCI config space. Most BIOSes
* virtualize the PCI registers so the chip looks like a standard IDE
* controller. Unfortunately not all implementations get this right.
* In particular some have problems with unaligned accesses to the
* virtualized PCI registers. This driver always does full dword
* writes to work around the issue. Also, in case of a bad BIOS this
* driver can be loaded with the "msr=1" parameter which forces using
* the Machine Specific Registers to configure the device.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <asm/msr.h>
#define DRV_NAME "cs5536"
enum {
MSR_IDE_CFG = 0x51300010,
PCI_IDE_CFG = 0x40,
CFG = 0,
DTC = 2,
CAST = 3,
ETC = 4,
IDE_CFG_CHANEN = (1 << 1),
IDE_CFG_CABLE = (1 << 17) | (1 << 16),
IDE_D0_SHIFT = 24,
IDE_D1_SHIFT = 16,
IDE_DRV_MASK = 0xff,
IDE_CAST_D0_SHIFT = 6,
IDE_CAST_D1_SHIFT = 4,
IDE_CAST_DRV_MASK = 0x3,
IDE_CAST_CMD_SHIFT = 24,
IDE_CAST_CMD_MASK = 0xff,
IDE_ETC_UDMA_MASK = 0xc0,
};
static int use_msr;
static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
{
if (unlikely(use_msr)) {
u32 dummy;
rdmsr(MSR_IDE_CFG + reg, *val, dummy);
return 0;
}
return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
}
static int cs5536_write(struct pci_dev *pdev, int reg, int val)
{
if (unlikely(use_msr)) {
wrmsr(MSR_IDE_CFG + reg, val, 0);
return 0;
}
return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
}
static void cs5536_program_dtc(ide_drive_t *drive, u8 tim)
{
struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
u32 dtc;
cs5536_read(pdev, DTC, &dtc);
dtc &= ~(IDE_DRV_MASK << dshift);
dtc |= tim << dshift;
cs5536_write(pdev, DTC, dtc);
}
/**
* cs5536_cable_detect - detect cable type
* @hwif: Port to detect on
*
* Perform cable detection for ATA66 capable cable.
*
* Returns a cable type.
*/
static u8 cs5536_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
u32 cfg;
cs5536_read(pdev, CFG, &cfg);
if (cfg & IDE_CFG_CABLE)
return ATA_CBL_PATA80;
else
return ATA_CBL_PATA40;
}
/**
* cs5536_set_pio_mode - PIO timing setup
* @hwif: ATA port
* @drive: ATA device
*/
static void cs5536_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
static const u8 drv_timings[5] = {
0x98, 0x55, 0x32, 0x21, 0x20,
};
static const u8 addr_timings[5] = {
0x2, 0x1, 0x0, 0x0, 0x0,
};
static const u8 cmd_timings[5] = {
0x99, 0x92, 0x90, 0x22, 0x20,
};
struct pci_dev *pdev = to_pci_dev(hwif->dev);
ide_drive_t *pair = ide_get_pair_dev(drive);
int cshift = (drive->dn & 1) ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
unsigned long timings = (unsigned long)ide_get_drivedata(drive);
u32 cast;
const u8 pio = drive->pio_mode - XFER_PIO_0;
u8 cmd_pio = pio;
if (pair)
cmd_pio = min_t(u8, pio, pair->pio_mode - XFER_PIO_0);
timings &= (IDE_DRV_MASK << 8);
timings |= drv_timings[pio];
ide_set_drivedata(drive, (void *)timings);
cs5536_program_dtc(drive, drv_timings[pio]);
cs5536_read(pdev, CAST, &cast);
cast &= ~(IDE_CAST_DRV_MASK << cshift);
cast |= addr_timings[pio] << cshift;
cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);
cast |= cmd_timings[cmd_pio] << IDE_CAST_CMD_SHIFT;
cs5536_write(pdev, CAST, cast);
}
/**
* cs5536_set_dma_mode - DMA timing setup
* @hwif: ATA port
* @drive: ATA device
*/
static void cs5536_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
static const u8 udma_timings[6] = {
0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6,
};
static const u8 mwdma_timings[3] = {
0x67, 0x21, 0x20,
};
struct pci_dev *pdev = to_pci_dev(hwif->dev);
int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
unsigned long timings = (unsigned long)ide_get_drivedata(drive);
u32 etc;
const u8 mode = drive->dma_mode;
cs5536_read(pdev, ETC, &etc);
if (mode >= XFER_UDMA_0) {
etc &= ~(IDE_DRV_MASK << dshift);
etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
} else { /* MWDMA */
etc &= ~(IDE_ETC_UDMA_MASK << dshift);
timings &= IDE_DRV_MASK;
timings |= mwdma_timings[mode - XFER_MW_DMA_0] << 8;
ide_set_drivedata(drive, (void *)timings);
}
cs5536_write(pdev, ETC, etc);
}
static void cs5536_dma_start(ide_drive_t *drive)
{
unsigned long timings = (unsigned long)ide_get_drivedata(drive);
if (drive->current_speed < XFER_UDMA_0 &&
(timings >> 8) != (timings & IDE_DRV_MASK))
cs5536_program_dtc(drive, timings >> 8);
ide_dma_start(drive);
}
static int cs5536_dma_end(ide_drive_t *drive)
{
int ret = ide_dma_end(drive);
unsigned long timings = (unsigned long)ide_get_drivedata(drive);
if (drive->current_speed < XFER_UDMA_0 &&
(timings >> 8) != (timings & IDE_DRV_MASK))
cs5536_program_dtc(drive, timings & IDE_DRV_MASK);
return ret;
}
static const struct ide_port_ops cs5536_port_ops = {
.set_pio_mode = cs5536_set_pio_mode,
.set_dma_mode = cs5536_set_dma_mode,
.cable_detect = cs5536_cable_detect,
};
static const struct ide_dma_ops cs5536_dma_ops = {
.dma_host_set = ide_dma_host_set,
.dma_setup = ide_dma_setup,
.dma_start = cs5536_dma_start,
.dma_end = cs5536_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timer_expiry = ide_dma_sff_timer_expiry,
.dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info cs5536_info = {
.name = DRV_NAME,
.port_ops = &cs5536_port_ops,
.dma_ops = &cs5536_dma_ops,
.host_flags = IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
};
/**
* cs5536_init_one
* @dev: PCI device
* @id: Entry in match table
*/
static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
u32 cfg;
if (use_msr)
printk(KERN_INFO DRV_NAME ": Using MSR regs instead of PCI\n");
cs5536_read(dev, CFG, &cfg);
if ((cfg & IDE_CFG_CHANEN) == 0) {
printk(KERN_ERR DRV_NAME ": disabled by BIOS\n");
return -ENODEV;
}
return ide_pci_init_one(dev, &cs5536_info, NULL);
}
static const struct pci_device_id cs5536_pci_tbl[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), },
{ },
};
static struct pci_driver cs5536_pci_driver = {
.name = DRV_NAME,
.id_table = cs5536_pci_tbl,
.probe = cs5536_init_one,
.remove = ide_pci_remove,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
module_pci_driver(cs5536_pci_driver);
MODULE_AUTHOR("Martin K. Petersen, Bartlomiej Zolnierkiewicz");
MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, cs5536_pci_tbl);
module_param_named(msr, use_msr, int, 0644);
MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");

View File

@@ -1,234 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
* Copyright (C) 2007-2011 Bartlomiej Zolnierkiewicz
*
* CYPRESS CY82C693 chipset IDE controller
*
* The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
#define DRV_NAME "cy82c693"
/*
* NOTE: the value for busmaster timeout is tricky and I got it by
* trial and error! By using a to low value will cause DMA timeouts
* and drop IDE performance, and by 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.
*/
/* twice the value written in cy82c693ub datasheet */
#define BUSMASTER_TIMEOUT 0x50
/*
* 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 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_CHANNEL0 0x30
#define CY82_INDEX_CHANNEL1 0x31
#define CY82_INDEX_TIMEOUT 0x32
/*
* set DMA mode a specific channel for CY82C693
*/
static void cy82c693_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
const u8 mode = drive->dma_mode;
u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
data = (mode & 3) | (single << 2);
outb(index, CY82_INDEX_PORT);
outb(data, CY82_DATA_PORT);
/*
* note: below we set the value for Bus Master IDE TimeOut Register
* I'm not absolutely 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;
outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
outb(data, CY82_DATA_PORT);
}
static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
const unsigned long T = 1000000 / bus_speed;
unsigned int addrCtrl;
struct ide_timing t;
u8 time_16, time_8;
/* select primary or secondary channel */
if (drive->dn > 1) { /* drive is on the secondary channel */
dev = pci_get_slot(dev->bus, dev->devfn+1);
if (!dev) {
printk(KERN_ERR "%s: tune_drive: "
"Cannot find secondary interface!\n",
drive->name);
return;
}
}
ide_timing_compute(drive, drive->pio_mode, &t, T, 1);
time_16 = clamp_val(t.recover - 1, 0, 15) |
(clamp_val(t.active - 1, 0, 15) << 4);
time_8 = clamp_val(t.act8b - 1, 0, 15) |
(clamp_val(t.rec8b - 1, 0, 15) << 4);
/* now let's write the clocks registers */
if ((drive->dn & 1) == 0) {
/*
* set master drive
* address setup control register
* is 32 bit !!!
*/
pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
addrCtrl &= (~0xF);
addrCtrl |= clamp_val(t.setup - 1, 0, 15);
pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
/* now let's set the remaining registers */
pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, time_16);
pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, time_16);
pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, time_8);
} else {
/*
* set slave drive
* address setup control register
* is 32 bit !!!
*/
pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
addrCtrl &= (~0xF0);
addrCtrl |= (clamp_val(t.setup - 1, 0, 15) << 4);
pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
/* now let's set the remaining registers */
pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, time_16);
pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
}
if (drive->dn > 1)
pci_dev_put(dev);
}
static void init_iops_cy82c693(ide_hwif_t *hwif)
{
static ide_hwif_t *primary;
struct pci_dev *dev = to_pci_dev(hwif->dev);
if (PCI_FUNC(dev->devfn) == 1)
primary = hwif;
else {
hwif->mate = primary;
hwif->channel = 1;
}
}
static const struct ide_port_ops cy82c693_port_ops = {
.set_pio_mode = cy82c693_set_pio_mode,
.set_dma_mode = cy82c693_set_dma_mode,
};
static const struct ide_port_info cy82c693_chipset = {
.name = DRV_NAME,
.init_iops = init_iops_cy82c693,
.port_ops = &cy82c693_port_ops,
.host_flags = IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.swdma_mask = ATA_SWDMA2,
.mwdma_mask = ATA_MWDMA2,
};
static int cy82c693_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct pci_dev *dev2;
int ret = -ENODEV;
/* CY82C693 is more than only a IDE controller.
Function 1 is primary IDE channel, function 2 - secondary. */
if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
PCI_FUNC(dev->devfn) == 1) {
dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL);
if (ret)
pci_dev_put(dev2);
}
return ret;
}
static void cy82c693_remove(struct pci_dev *dev)
{
struct ide_host *host = pci_get_drvdata(dev);
struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
ide_pci_remove(dev);
pci_dev_put(dev2);
}
static const struct pci_device_id cy82c693_pci_tbl[] = {
{ PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
static struct pci_driver cy82c693_pci_driver = {
.name = "Cypress_IDE",
.id_table = cy82c693_pci_tbl,
.probe = cy82c693_init_one,
.remove = cy82c693_remove,
.suspend = ide_pci_suspend,
.resume = ide_pci_resume,
};
static int __init cy82c693_ide_init(void)
{
return ide_pci_register_driver(&cy82c693_pci_driver);
}
static void __exit cy82c693_ide_exit(void)
{
pci_unregister_driver(&cy82c693_pci_driver);
}
module_init(cy82c693_ide_init);
module_exit(cy82c693_ide_exit);
MODULE_AUTHOR("Andreas Krebs, Andre Hedrick, Bartlomiej Zolnierkiewicz");
MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
MODULE_LICENSE("GPL");

View File

@@ -1,181 +0,0 @@
/*
* Created 20 Oct 2004 by Mark Lord
*
* Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
*
* Modeled after the 16-bit PCMCIA driver: ide-cs.c
*
* This is slightly peculiar, in that it is a PCI driver,
* but is NOT an IDE PCI driver -- the IDE layer does not directly
* support hot insertion/removal of PCI interfaces, so this driver
* is unable to use the IDE PCI interfaces. Instead, it uses the
* same interfaces as the ide-cs (PCMCIA) driver uses.
* On the plus side, the driver is also smaller/simpler this way.
*
* 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/module.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
/*
* No chip documentation has yet been found,
* so these configuration values were pulled from
* a running Win98 system using "debug".
* This gives around 3MByte/second read performance,
* which is about 2/3 of what the chip is capable of.
*
* There is also a 4KByte mmio region on the card,
* but its purpose has yet to be reverse-engineered.
*/
static const u8 setup[] = {
0x00, 0x05, 0xbe, 0x01, 0x20, 0x8f, 0x00, 0x00,
0xa4, 0x1f, 0xb3, 0x1b, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13,
};
static const struct ide_port_ops delkin_cb_port_ops = {
.quirkproc = ide_undecoded_slave,
};
static int delkin_cb_init_chipset(struct pci_dev *dev)
{
unsigned long base = pci_resource_start(dev, 0);
int i;
outb(0x02, base + 0x1e); /* set nIEN to block interrupts */
inb(base + 0x17); /* read status to clear interrupts */
for (i = 0; i < sizeof(setup); ++i) {
if (setup[i])
outb(setup[i], base + i);
}
return 0;
}
static const struct ide_port_info delkin_cb_port_info = {
.port_ops = &delkin_cb_port_ops,
.host_flags = IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS |
IDE_HFLAG_NO_DMA,
.irq_flags = IRQF_SHARED,
.init_chipset = delkin_cb_init_chipset,
.chipset = ide_pci,
};
static int delkin_cb_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct ide_host *host;
unsigned long base;
int rc;
struct ide_hw hw, *hws[] = { &hw };
rc = pci_enable_device(dev);
if (rc) {
printk(KERN_ERR "delkin_cb: pci_enable_device failed (%d)\n", rc);
return rc;
}
rc = pci_request_regions(dev, "delkin_cb");
if (rc) {
printk(KERN_ERR "delkin_cb: pci_request_regions failed (%d)\n", rc);
pci_disable_device(dev);
return rc;
}
base = pci_resource_start(dev, 0);
delkin_cb_init_chipset(dev);
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
hw.irq = dev->irq;
hw.dev = &dev->dev;
rc = ide_host_add(&delkin_cb_port_info, hws, 1, &host);
if (rc)
goto out_disable;
pci_set_drvdata(dev, host);
return 0;
out_disable:
pci_release_regions(dev);
pci_disable_device(dev);
return rc;
}
static void
delkin_cb_remove (struct pci_dev *dev)
{
struct ide_host *host = pci_get_drvdata(dev);
ide_host_remove(host);
pci_release_regions(dev);
pci_disable_device(dev);
}
#ifdef CONFIG_PM
static int delkin_cb_suspend(struct pci_dev *dev, pm_message_t state)
{
pci_save_state(dev);
pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
static int delkin_cb_resume(struct pci_dev *dev)
{
struct ide_host *host = pci_get_drvdata(dev);
int rc;
pci_set_power_state(dev, PCI_D0);
rc = pci_enable_device(dev);
if (rc)
return rc;
pci_restore_state(dev);
pci_set_master(dev);
if (host->init_chipset)
host->init_chipset(dev);
return 0;
}
#else
#define delkin_cb_suspend NULL
#define delkin_cb_resume NULL
#endif
static struct pci_device_id delkin_cb_pci_tbl[] = {
{ 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
static struct pci_driver delkin_cb_pci_driver = {
.name = "Delkin-ASKA-Workbit Cardbus IDE",
.id_table = delkin_cb_pci_tbl,
.probe = delkin_cb_probe,
.remove = delkin_cb_remove,
.suspend = delkin_cb_suspend,
.resume = delkin_cb_resume,
};
module_pci_driver(delkin_cb_pci_driver);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE");
MODULE_LICENSE("GPL");

Some files were not shown because too many files have changed in this diff Show More