From 2bfba3c444fe8b2ab1c38112a89d8f03b61136ca Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 21 Oct 2008 20:57:23 +0200 Subject: ide: remove useless subdirs from drivers/ide/ Suggested-by: Ralf Baechle Signed-off-by: Bartlomiej Zolnierkiewicz diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 093d324..9cf92ac 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -18,22 +18,66 @@ ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o obj-$(CONFIG_IDE) += ide-core.o -ifeq ($(CONFIG_IDE_ARM), y) - ide-arm-core-y += arm/ide_arm.o - obj-y += ide-arm-core.o -endif - -obj-$(CONFIG_IDE) += legacy/ pci/ +obj-$(CONFIG_IDE_ARM) += ide_arm.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_MAC_IDE) += macide.o +obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.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_CELLEB) += scc_pata.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_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_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_SGIIOC4) += sgiioc4.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 +ide-pci-generic-y += generic.o obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o -ifeq ($(CONFIG_BLK_DEV_CMD640), y) - cmd640-core-y += pci/cmd640.o - obj-y += cmd640-core.o -endif +obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o + +obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o + +obj-$(CONFIG_IDE_H8300) += ide-h8300.o -obj-$(CONFIG_IDE) += ppc/ -obj-$(CONFIG_IDE_H8300) += h8300/ obj-$(CONFIG_IDE_GENERIC) += ide-generic.o obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o @@ -58,14 +102,12 @@ 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 -ifeq ($(CONFIG_BLK_DEV_IDECS), y) - ide-cs-core-y += legacy/ide-cs.o - obj-y += ide-cs-core.o -endif +obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o -ifeq ($(CONFIG_BLK_DEV_PLATFORM), y) - ide-platform-core-y += legacy/ide_platform.o - obj-y += ide-platform-core.o -endif +obj-$(CONFIG_BLK_DEV_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_IDE) += arm/ mips/ +obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c new file mode 100644 index 0000000..4142c69 --- /dev/null +++ b/drivers/ide/aec62xx.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) 1999-2002 Andre Hedrick + * Copyright (C) 2007 MontaVista Software, Inc. + * + */ + +#include +#include +#include +#include +#include + +#include + +#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_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_host *host = pci_get_drvdata(dev); + struct chipset_bus_clock_list_entry *bus_clock = host->host_priv; + u16 d_conf = 0; + u8 ultra = 0, ultra_conf = 0; + u8 tmp0 = 0, tmp1 = 0, tmp2 = 0; + 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_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_host *host = pci_get_drvdata(dev); + struct chipset_bus_clock_list_entry *bus_clock = host->host_priv; + u8 unit = drive->dn & 1; + u8 tmp1 = 0, tmp2 = 0; + u8 ultra = 0, drive_conf = 0, ultra_conf = 0; + 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_drive_t *drive, const u8 pio) +{ + drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0); +} + +static unsigned 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, ®49h); + pci_write_config_byte(dev, 0x49, reg49h & ~0x30); + /* Enable chip interrupt output. */ + pci_read_config_byte(dev, 0x4a, ®4ah); + pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01); + /* Enable burst mode. */ + pci_read_config_byte(dev, 0x4a, ®4ah); + pci_write_config_byte(dev, 0x4a, reg4ah | 0x80); + } + + return dev->irq; +} + +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[] __devinitdata = { + { /* 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 __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + const struct chipset_bus_clock_list_entry *bus_clock; + struct ide_port_info d; + u8 idx = id->driver_data; + int bus_speed = ide_pci_clk ? ide_pci_clk : 33; + int err; + + if (bus_speed <= 33) + bus_clock = aec6xxx_33_base; + else + bus_clock = aec6xxx_34_base; + + err = pci_enable_device(dev); + if (err) + return err; + + 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 __devexit aec62xx_remove(struct pci_dev *dev) +{ + ide_pci_remove(dev); + pci_disable_device(dev); +} + +static const struct pci_device_id aec62xx_pci_tbl[] = { + { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 }, + { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 }, + { 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 = __devexit_p(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"); diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c new file mode 100644 index 0000000..90da1f9 --- /dev/null +++ b/drivers/ide/ali14xx.c @@ -0,0 +1,248 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "ali14xx" + +/* port addresses for auto-detection */ +#define ALI_NUM_PORTS 4 +static const int ports[ALI_NUM_PORTS] __initdata = + { 0x074, 0x0f4, 0x034, 0x0e4 }; + +/* register initialization data */ +typedef struct { u8 reg, data; } RegInitializer; + +static const RegInitializer initData[] __initdata = { + {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, + {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, + {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, + {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_drive_t *drive, const u8 pio) +{ + int driveNum; + int time1, time2; + u8 param1, param2, param3, param4; + unsigned long flags; + int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50; + struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); + + /* calculate timing, according to PIO mode */ + time1 = ide_pio_cycle_time(drive, pio); + time2 = 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 int 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"); diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c new file mode 100644 index 0000000..daf9dce --- /dev/null +++ b/drivers/ide/alim15x3.c @@ -0,0 +1,602 @@ +/* + * Copyright (C) 1998-2000 Michel Aubry, Maintainer + * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer + * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer + * + * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) + * May be copied or modified under the terms of the GNU General Public License + * Copyright (C) 2002 Alan Cox + * ALi (now ULi M5228) support by Clear Zhang + * Copyright (C) 2007 MontaVista Software, Inc. + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * + * (U)DMA capable version of ali 1533/1543(C), 1535(D) + * + ********************************************************************** + * 9/7/99 --Parts from the above author are included and need to be + * converted into standard interface, once I finish the thought. + * + * Recent changes + * Don't use LBA48 mode on ALi <= 0xC4 + * Don't poke 0x79 with a non ALi northbridge + * Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang) + * Allow UDMA6 on revisions > 0xC4 + * + * Documentation + * Chipset documentation available under NDA only + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "alim15x3" + +/* + * Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking + * (this is DANGEROUS and could result in data corruption). + */ +static int wdc_udma; + +module_param(wdc_udma, bool, 0); +MODULE_PARM_DESC(wdc_udma, + "allow UDMA on M1543C-E chipset for WDC disks (DANGEROUS)"); + +/* + * ALi devices are not plug in. Otherwise these static values would + * need to go. They ought to go away anyway + */ + +static u8 m5229_revision; +static u8 chip_is_1543c_e; +static struct pci_dev *isa_dev; + +/** + * ali_set_pio_mode - set host controller for PIO mode + * @drive: drive + * @pio: PIO mode number + * + * Program the controller for the given PIO mode. + */ + +static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); + int s_time = t->setup, a_time = t->active, c_time = t->cycle; + u8 s_clc, a_clc, r_clc; + unsigned long flags; + int bus_speed = ide_pci_clk ? ide_pci_clk : 33; + int port = hwif->channel ? 0x5c : 0x58; + int portFIFO = hwif->channel ? 0x55 : 0x54; + u8 cd_dma_fifo = 0, unit = drive->dn & 1; + + if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) + s_clc = 0; + if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) + a_clc = 0; + + if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { + r_clc = 1; + } else { + if (r_clc >= 16) + r_clc = 0; + } + local_irq_save(flags); + + /* + * PIO mode => ATA FIFO on, ATAPI FIFO off + */ + pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); + if (drive->media==ide_disk) { + if (unit) { + pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); + } else { + pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); + } + } else { + if (unit) { + pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); + } else { + pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); + } + } + + pci_write_config_byte(dev, port, s_clc); + pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc); + local_irq_restore(flags); +} + +/** + * ali_udma_filter - compute UDMA mask + * @drive: IDE device + * + * Return available UDMA modes. + * + * The actual rules for the ALi are: + * No UDMA on revisions <= 0x20 + * Disk only for revisions < 0xC2 + * Not WDC drives on M1543C-E (?) + */ + +static u8 ali_udma_filter(ide_drive_t *drive) +{ + if (m5229_revision > 0x20 && m5229_revision < 0xC2) { + if (drive->media != ide_disk) + return 0; + if (wdc_udma == 0 && chip_is_1543c_e && + strstr((char *)&drive->id[ATA_ID_PROD], "WDC ")) + return 0; + } + + return drive->hwif->ultra_mask; +} + +/** + * ali_set_dma_mode - set host controller for DMA mode + * @drive: drive + * @speed: DMA mode + * + * Configure the hardware for the desired IDE transfer mode. + */ + +static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 speed1 = speed; + u8 unit = drive->dn & 1; + u8 tmpbyte = 0x00; + int m5229_udma = (hwif->channel) ? 0x57 : 0x56; + + if (speed == XFER_UDMA_6) + speed1 = 0x47; + + if (speed < XFER_UDMA_0) { + u8 ultra_enable = (unit) ? 0x7f : 0xf7; + /* + * clear "ultra enable" bit + */ + pci_read_config_byte(dev, m5229_udma, &tmpbyte); + tmpbyte &= ultra_enable; + pci_write_config_byte(dev, m5229_udma, tmpbyte); + + /* + * FIXME: Oh, my... DMA timings are never set. + */ + } else { + pci_read_config_byte(dev, m5229_udma, &tmpbyte); + tmpbyte &= (0x0f << ((1-unit) << 2)); + /* + * enable ultra dma and set timing + */ + tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2)); + pci_write_config_byte(dev, m5229_udma, tmpbyte); + if (speed >= XFER_UDMA_3) { + pci_read_config_byte(dev, 0x4b, &tmpbyte); + tmpbyte |= 1; + pci_write_config_byte(dev, 0x4b, tmpbyte); + } + } +} + +/** + * ali15x3_dma_setup - begin a DMA phase + * @drive: target device + * + * Returns 1 if the DMA cannot be performed, zero on success. + */ + +static int ali15x3_dma_setup(ide_drive_t *drive) +{ + if (m5229_revision < 0xC2 && drive->media != ide_disk) { + if (rq_data_dir(drive->hwif->hwgroup->rq)) + return 1; /* try PIO instead of DMA */ + } + return ide_dma_setup(drive); +} + +/** + * init_chipset_ali15x3 - Initialise an ALi IDE controller + * @dev: PCI device + * + * This function initializes the ALI IDE controller and where + * appropriate also sets up the 1533 southbridge. + */ + +static unsigned int init_chipset_ali15x3(struct pci_dev *dev) +{ + unsigned long flags; + u8 tmpbyte; + struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0)); + + m5229_revision = dev->revision; + + isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); + + local_irq_save(flags); + + if (m5229_revision < 0xC2) { + /* + * revision 0x20 (1543-E, 1543-F) + * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) + * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + /* + * clear bit 7 + */ + pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); + /* + * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 + */ + if (m5229_revision >= 0x20 && isa_dev) { + pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); + chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; + } + goto out; + } + + /* + * 1543C-B?, 1535, 1535D, 1553 + * Note 1: not all "motherboard" support this detection + * Note 2: if no udma 66 device, the detection may "error". + * but in this case, we will not set the device to + * ultra 66, the detection result is not important + */ + + /* + * enable "Cable Detection", m5229, 0x4b, bit3 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); + + /* + * We should only tune the 1533 enable if we are using an ALi + * North bridge. We might have no north found on some zany + * box without a device at 0:0.0. The ALi bridge will be at + * 0:0.0 so if we didn't find one we know what is cooking. + */ + if (north && north->vendor != PCI_VENDOR_ID_AL) + goto out; + + if (m5229_revision < 0xC5 && isa_dev) + { + /* + * set south-bridge's enable bit, m1533, 0x79 + */ + + pci_read_config_byte(isa_dev, 0x79, &tmpbyte); + if (m5229_revision == 0xC2) { + /* + * 1543C-B0 (m1533, 0x79, bit 2) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); + } else if (m5229_revision >= 0xC3) { + /* + * 1553/1535 (m1533, 0x79, bit 1) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); + } + } + +out: + /* + * CD_ROM DMA on (m5229, 0x53, bit0) + * Enable this bit even if we want to use PIO. + * PIO FIFO off (m5229, 0x53, bit1) + * The hardware will use 0x54h and 0x55h to control PIO FIFO. + * (Not on later devices it seems) + * + * 0x53 changes meaning on later revs - we must no touch + * bit 1 on them. Need to check if 0x20 is the right break. + */ + if (m5229_revision >= 0x20) { + pci_read_config_byte(dev, 0x53, &tmpbyte); + + if (m5229_revision <= 0x20) + tmpbyte = (tmpbyte & (~0x02)) | 0x01; + else if (m5229_revision == 0xc7 || m5229_revision == 0xc8) + tmpbyte |= 0x03; + else + tmpbyte |= 0x01; + + pci_write_config_byte(dev, 0x53, tmpbyte); + } + pci_dev_put(north); + pci_dev_put(isa_dev); + local_irq_restore(flags); + return 0; +} + +/* + * Cable special cases + */ + +static const struct dmi_system_id cable_dmi_table[] = { + { + .ident = "HP Pavilion N5430", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"), + }, + }, + { + .ident = "Toshiba Satellite S1800-814", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"), + }, + }, + { } +}; + +static int ali_cable_override(struct pci_dev *pdev) +{ + /* Fujitsu P2000 */ + if (pdev->subsystem_vendor == 0x10CF && + pdev->subsystem_device == 0x10AF) + return 1; + + /* Mitac 8317 (Winbook-A) and relatives */ + if (pdev->subsystem_vendor == 0x1071 && + pdev->subsystem_device == 0x8317) + return 1; + + /* Systems by DMI */ + if (dmi_check_system(cable_dmi_table)) + return 1; + + return 0; +} + +/** + * ali_cable_detect - cable detection + * @hwif: IDE interface + * + * This checks if the controller and the cable are capable + * of UDMA66 transfers. It doesn't check the drives. + * But see note 2 below! + * + * FIXME: frobs bits that are not defined on newer ALi devicea + */ + +static u8 ali_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long flags; + u8 cbl = ATA_CBL_PATA40, tmpbyte; + + local_irq_save(flags); + + if (m5229_revision >= 0xC2) { + /* + * m5229 80-pin cable detection (from Host View) + * + * 0x4a bit0 is 0 => primary channel has 80-pin + * 0x4a bit1 is 0 => secondary channel has 80-pin + * + * Certain laptops use short but suitable cables + * and don't implement the detect logic. + */ + if (ali_cable_override(dev)) + cbl = ATA_CBL_PATA40_SHORT; + else { + pci_read_config_byte(dev, 0x4a, &tmpbyte); + if ((tmpbyte & (1 << hwif->channel)) == 0) + cbl = ATA_CBL_PATA80; + } + } + + local_irq_restore(flags); + + return cbl; +} + +#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) +/** + * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff + * @hwif: interface to configure + * + * Obtain the IRQ tables for an ALi based IDE solution on the PC + * class platforms. This part of the code isn't applicable to the + * Sparc and PowerPC systems. + */ + +static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 ideic, inmir; + s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, + 1, 11, 0, 12, 0, 14, 0, 15 }; + int irq = -1; + + if (dev->device == PCI_DEVICE_ID_AL_M5229) + hwif->irq = hwif->channel ? 15 : 14; + + if (isa_dev) { + /* + * read IDE interface control + */ + pci_read_config_byte(isa_dev, 0x58, &ideic); + + /* bit0, bit1 */ + ideic = ideic & 0x03; + + /* get IRQ for IDE Controller */ + if ((hwif->channel && ideic == 0x03) || + (!hwif->channel && !ideic)) { + /* + * get SIRQ1 routing table + */ + pci_read_config_byte(isa_dev, 0x44, &inmir); + inmir = inmir & 0x0f; + irq = irq_routing_table[inmir]; + } else if (hwif->channel && !(ideic & 0x01)) { + /* + * get SIRQ2 routing table + */ + pci_read_config_byte(isa_dev, 0x75, &inmir); + inmir = inmir & 0x0f; + irq = irq_routing_table[inmir]; + } + if(irq >= 0) + hwif->irq = irq; + } +} +#else +#define init_hwif_ali15x3 NULL +#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */ + +/** + * init_dma_ali15x3 - set up DMA on ALi15x3 + * @hwif: IDE interface + * @d: IDE port info + * + * Set up the DMA functionality on the ALi 15x3. + */ + +static int __devinit init_dma_ali15x3(ide_hwif_t *hwif, + const struct ide_port_info *d) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long base = ide_pci_dma_base(hwif, d); + + if (base == 0) + return -1; + + hwif->dma_base = base; + + if (ide_pci_check_simplex(hwif, d) < 0) + return -1; + + if (ide_pci_set_master(dev, d->name) < 0) + return -1; + + if (!hwif->channel) + outb(inb(base + 2) & 0x60, base + 2); + + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", + hwif->name, base, base + 7); + + if (ide_allocate_dma_engine(hwif)) + return -1; + + hwif->dma_ops = &sff_dma_ops; + + return 0; +} + +static const struct ide_port_ops ali_port_ops = { + .set_pio_mode = ali_set_pio_mode, + .set_dma_mode = ali_set_dma_mode, + .udma_filter = ali_udma_filter, + .cable_detect = ali_cable_detect, +}; + +static const struct ide_dma_ops ali_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ali15x3_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = ide_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info ali15x3_chipset __devinitdata = { + .name = DRV_NAME, + .init_chipset = init_chipset_ali15x3, + .init_hwif = init_hwif_ali15x3, + .init_dma = init_dma_ali15x3, + .port_ops = &ali_port_ops, + .pio_mask = ATA_PIO5, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, +}; + +/** + * alim15x3_init_one - set up an ALi15x3 IDE controller + * @dev: PCI device to set up + * + * Perform the actual set up for an ALi15x3 that has been found by the + * hot plug layer. + */ + +static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct ide_port_info d = ali15x3_chipset; + u8 rev = dev->revision, idx = id->driver_data; + + /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ + if (rev <= 0xC4) + d.host_flags |= IDE_HFLAG_NO_LBA48_DMA; + + if (rev >= 0x20) { + if (rev == 0x20) + d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA; + + if (rev < 0xC2) + d.udma_mask = ATA_UDMA2; + else if (rev == 0xC2 || rev == 0xC3) + d.udma_mask = ATA_UDMA4; + else if (rev == 0xC4) + d.udma_mask = ATA_UDMA5; + else + d.udma_mask = ATA_UDMA6; + + d.dma_ops = &ali_dma_ops; + } else { + d.host_flags |= IDE_HFLAG_NO_DMA; + + d.mwdma_mask = d.swdma_mask = 0; + } + + if (idx == 0) + d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX; + + return ide_pci_init_one(dev, &d, NULL); +} + + +static const struct pci_device_id alim15x3_pci_tbl[] = { + { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 }, + { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl); + +static struct pci_driver alim15x3_pci_driver = { + .name = "ALI15x3_IDE", + .id_table = alim15x3_pci_tbl, + .probe = alim15x3_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init ali15x3_ide_init(void) +{ + return ide_pci_register_driver(&alim15x3_pci_driver); +} + +static void __exit ali15x3_ide_exit(void) +{ + return pci_unregister_driver(&alim15x3_pci_driver); +} + +module_init(ali15x3_ide_init); +module_exit(ali15x3_ide_exit); + +MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox"); +MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c new file mode 100644 index 0000000..81ec731 --- /dev/null +++ b/drivers/ide/amd74xx.c @@ -0,0 +1,346 @@ +/* + * 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 Bartlomiej Zolnierkiewicz + * + * Based on the work of: + * Andre Hedrick + */ + +/* + * 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. + */ + +#include +#include +#include +#include +#include + +#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; + } + + 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_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + ide_drive_t *peer = hwif->drives + (~drive->dn & 1); + struct ide_timing t, p; + int T, UT; + u8 udma_mask = hwif->ultra_mask; + + T = 1000000000 / amd_clock; + UT = (udma_mask == ATA_UDMA2) ? T : (T / 2); + + ide_timing_compute(drive, speed, &t, T, UT); + + if (peer->dev_flags & IDE_DFLAG_PRESENT) { + ide_timing_compute(peer, peer->current_speed, &p, T, UT); + ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); + } + + 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_drive_t *drive, const u8 pio) +{ + amd_set_drive(drive, XFER_PIO_0 + pio); +} + +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 unsigned 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->vendor == PCI_DEVICE_ID_AMD_VIPER_7411) + t &= 0x0f; + else + t |= 0xf0; + pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t); + + return dev->irq; +} + +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 void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + + if (hwif->irq == 0) /* 0 is bogus but will do for now */ + hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); +} + +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, \ + .init_hwif = init_hwif_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, \ + .init_hwif = init_hwif_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[] __devinitdata = { + /* 0: AMD7401 */ DECLARE_AMD_DEV(0x00, ATA_UDMA2), + /* 1: AMD7409 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4), + /* 2: AMD7411/7441 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5), + /* 3: AMD8111 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA6), + + /* 4: NFORCE */ DECLARE_NV_DEV(ATA_UDMA5), + /* 5: >= NFORCE2 */ DECLARE_NV_DEV(ATA_UDMA6), + + /* 6: AMD5536 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5), +}; + +static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + 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; + } + + 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"); +MODULE_DESCRIPTION("AMD PCI IDE driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile deleted file mode 100644 index 5bc2605..0000000 --- a/drivers/ide/arm/Makefile +++ /dev/null @@ -1,10 +0,0 @@ - -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 - -ifeq ($(CONFIG_IDE_ARM), m) - obj-m += ide_arm.o -endif - -EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c deleted file mode 100644 index 76bdc9a..0000000 --- a/drivers/ide/arm/icside.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (c) 1996-2004 Russell King. - * - * Please note that this platform does not support 32-bit IDE IO. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DRV_NAME "icside" - -#define ICS_IDENT_OFFSET 0x2280 - -#define ICS_ARCIN_V5_INTRSTAT 0x0000 -#define ICS_ARCIN_V5_INTROFFSET 0x0004 -#define ICS_ARCIN_V5_IDEOFFSET 0x2800 -#define ICS_ARCIN_V5_IDEALTOFFSET 0x2b80 -#define ICS_ARCIN_V5_IDESTEPPING 6 - -#define ICS_ARCIN_V6_IDEOFFSET_1 0x2000 -#define ICS_ARCIN_V6_INTROFFSET_1 0x2200 -#define ICS_ARCIN_V6_INTRSTAT_1 0x2290 -#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x2380 -#define ICS_ARCIN_V6_IDEOFFSET_2 0x3000 -#define ICS_ARCIN_V6_INTROFFSET_2 0x3200 -#define ICS_ARCIN_V6_INTRSTAT_2 0x3290 -#define ICS_ARCIN_V6_IDEALTOFFSET_2 0x3380 -#define ICS_ARCIN_V6_IDESTEPPING 6 - -struct cardinfo { - unsigned int dataoffset; - unsigned int ctrloffset; - unsigned int stepping; -}; - -static struct cardinfo icside_cardinfo_v5 = { - .dataoffset = ICS_ARCIN_V5_IDEOFFSET, - .ctrloffset = ICS_ARCIN_V5_IDEALTOFFSET, - .stepping = ICS_ARCIN_V5_IDESTEPPING, -}; - -static struct cardinfo icside_cardinfo_v6_1 = { - .dataoffset = ICS_ARCIN_V6_IDEOFFSET_1, - .ctrloffset = ICS_ARCIN_V6_IDEALTOFFSET_1, - .stepping = ICS_ARCIN_V6_IDESTEPPING, -}; - -static struct cardinfo icside_cardinfo_v6_2 = { - .dataoffset = ICS_ARCIN_V6_IDEOFFSET_2, - .ctrloffset = ICS_ARCIN_V6_IDEALTOFFSET_2, - .stepping = ICS_ARCIN_V6_IDESTEPPING, -}; - -struct icside_state { - unsigned int channel; - unsigned int enabled; - void __iomem *irq_port; - void __iomem *ioc_base; - unsigned int sel; - unsigned int type; - struct ide_host *host; -}; - -#define ICS_TYPE_A3IN 0 -#define ICS_TYPE_A3USER 1 -#define ICS_TYPE_V6 3 -#define ICS_TYPE_V5 15 -#define ICS_TYPE_NOTYPE ((unsigned int)-1) - -/* ---------------- Version 5 PCB Support Functions --------------------- */ -/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) - * Purpose : enable interrupts from card - */ -static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) -{ - struct icside_state *state = ec->irq_data; - - writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET); -} - -/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) - * Purpose : disable interrupts from card - */ -static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) -{ - struct icside_state *state = ec->irq_data; - - readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET); -} - -static const expansioncard_ops_t icside_ops_arcin_v5 = { - .irqenable = icside_irqenable_arcin_v5, - .irqdisable = icside_irqdisable_arcin_v5, -}; - - -/* ---------------- Version 6 PCB Support Functions --------------------- */ -/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) - * Purpose : enable interrupts from card - */ -static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) -{ - struct icside_state *state = ec->irq_data; - void __iomem *base = state->irq_port; - - state->enabled = 1; - - switch (state->channel) { - case 0: - writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); - readb(base + ICS_ARCIN_V6_INTROFFSET_2); - break; - case 1: - writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); - readb(base + ICS_ARCIN_V6_INTROFFSET_1); - break; - } -} - -/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) - * Purpose : disable interrupts from card - */ -static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) -{ - struct icside_state *state = ec->irq_data; - - state->enabled = 0; - - readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); -} - -/* Prototype: icside_irqprobe(struct expansion_card *ec) - * Purpose : detect an active interrupt from card - */ -static int icside_irqpending_arcin_v6(struct expansion_card *ec) -{ - struct icside_state *state = ec->irq_data; - - return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || - readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; -} - -static const expansioncard_ops_t icside_ops_arcin_v6 = { - .irqenable = icside_irqenable_arcin_v6, - .irqdisable = icside_irqdisable_arcin_v6, - .irqpending = icside_irqpending_arcin_v6, -}; - -/* - * Handle routing of interrupts. This is called before - * we write the command to the drive. - */ -static void icside_maskproc(ide_drive_t *drive, int mask) -{ - ide_hwif_t *hwif = HWIF(drive); - struct expansion_card *ec = ECARD_DEV(hwif->dev); - struct icside_state *state = ecard_get_drvdata(ec); - unsigned long flags; - - local_irq_save(flags); - - state->channel = hwif->channel; - - if (state->enabled && !mask) { - switch (hwif->channel) { - case 0: - writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); - break; - case 1: - writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); - readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - break; - } - } else { - readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); - readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - } - - local_irq_restore(flags); -} - -static const struct ide_port_ops icside_v6_no_dma_port_ops = { - .maskproc = icside_maskproc, -}; - -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS -/* - * SG-DMA support. - * - * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers. - * There is only one DMA controller per card, which means that only - * one drive can be accessed at one time. NOTE! We do not enforce that - * here, but we rely on the main IDE driver spotting that both - * interfaces use the same IRQ, which should guarantee this. - */ - -/* - * Configure the IOMD to give the appropriate timings for the transfer - * mode being requested. We take the advice of the ATA standards, and - * calculate the cycle time based on the transfer mode, and the EIDE - * MW DMA specs that the drive provides in the IDENTIFY command. - * - * We have the following IOMD DMA modes to choose from: - * - * Type Active Recovery Cycle - * A 250 (250) 312 (550) 562 (800) - * B 187 250 437 - * C 125 (125) 125 (375) 250 (500) - * D 62 125 187 - * - * (figures in brackets are actual measured timings) - * - * However, we also need to take care of the read/write active and - * recovery timings: - * - * Read Write - * Mode Active -- Recovery -- Cycle IOMD type - * MW0 215 50 215 480 A - * MW1 80 50 50 150 C - * MW2 70 25 25 120 C - */ -static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) -{ - int cycle_time, use_dma_info = 0; - - switch (xfer_mode) { - case XFER_MW_DMA_2: - cycle_time = 250; - use_dma_info = 1; - break; - - case XFER_MW_DMA_1: - cycle_time = 250; - use_dma_info = 1; - break; - - case XFER_MW_DMA_0: - cycle_time = 480; - break; - - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - cycle_time = 480; - break; - } - - /* - * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should - * take care to note the values in the ID... - */ - if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time) - cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME]; - - drive->drive_data = cycle_time; - - printk("%s: %s selected (peak %dMB/s)\n", drive->name, - ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); -} - -static const struct ide_port_ops icside_v6_port_ops = { - .set_dma_mode = icside_set_dma_mode, - .maskproc = icside_maskproc, -}; - -static void icside_dma_host_set(ide_drive_t *drive, int on) -{ -} - -static int icside_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct expansion_card *ec = ECARD_DEV(hwif->dev); - - drive->waiting_for_dma = 0; - - disable_dma(ec->dma); - - /* Teardown mappings after DMA has completed. */ - ide_destroy_dmatable(drive); - - return get_dma_residue(ec->dma) != 0; -} - -static void icside_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct expansion_card *ec = ECARD_DEV(hwif->dev); - - /* We can not enable DMA on both channels simultaneously. */ - BUG_ON(dma_channel_active(ec->dma)); - enable_dma(ec->dma); -} - -static int icside_dma_setup(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct expansion_card *ec = ECARD_DEV(hwif->dev); - struct icside_state *state = ecard_get_drvdata(ec); - struct request *rq = hwif->hwgroup->rq; - unsigned int dma_mode; - - if (rq_data_dir(rq)) - dma_mode = DMA_MODE_WRITE; - else - dma_mode = DMA_MODE_READ; - - /* - * We can not enable DMA on both channels. - */ - BUG_ON(dma_channel_active(ec->dma)); - - hwif->sg_nents = ide_build_sglist(drive, rq); - - /* - * Ensure that we have the right interrupt routed. - */ - icside_maskproc(drive, 0); - - /* - * Route the DMA signals to the correct interface. - */ - writeb(state->sel | hwif->channel, state->ioc_base); - - /* - * Select the correct timing for this drive. - */ - set_dma_speed(ec->dma, drive->drive_data); - - /* - * Tell the DMA engine about the SG table and - * data direction. - */ - set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents); - set_dma_mode(ec->dma, dma_mode); - - drive->waiting_for_dma = 1; - - return 0; -} - -static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd) -{ - /* issue cmd to drive */ - ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD, NULL); -} - -static int icside_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct expansion_card *ec = ECARD_DEV(hwif->dev); - struct icside_state *state = ecard_get_drvdata(ec); - - return readb(state->irq_port + - (hwif->channel ? - ICS_ARCIN_V6_INTRSTAT_2 : - ICS_ARCIN_V6_INTRSTAT_1)) & 1; -} - -static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d) -{ - hwif->dmatable_cpu = NULL; - hwif->dmatable_dma = 0; - - return 0; -} - -static const struct ide_dma_ops icside_v6_dma_ops = { - .dma_host_set = icside_dma_host_set, - .dma_setup = icside_dma_setup, - .dma_exec_cmd = icside_dma_exec_cmd, - .dma_start = icside_dma_start, - .dma_end = icside_dma_end, - .dma_test_irq = icside_dma_test_irq, - .dma_timeout = ide_dma_timeout, - .dma_lost_irq = ide_dma_lost_irq, -}; -#else -#define icside_v6_dma_ops NULL -#endif - -static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d) -{ - return -EOPNOTSUPP; -} - -static void icside_setup_ports(hw_regs_t *hw, void __iomem *base, - struct cardinfo *info, struct expansion_card *ec) -{ - unsigned long port = (unsigned long)base + info->dataoffset; - - hw->io_ports.data_addr = port; - hw->io_ports.error_addr = port + (1 << info->stepping); - hw->io_ports.nsect_addr = port + (2 << info->stepping); - hw->io_ports.lbal_addr = port + (3 << info->stepping); - hw->io_ports.lbam_addr = port + (4 << info->stepping); - hw->io_ports.lbah_addr = port + (5 << info->stepping); - hw->io_ports.device_addr = port + (6 << info->stepping); - hw->io_ports.status_addr = port + (7 << info->stepping); - hw->io_ports.ctl_addr = (unsigned long)base + info->ctrloffset; - - hw->irq = ec->irq; - hw->dev = &ec->dev; - hw->chipset = ide_acorn; -} - -static int __init -icside_register_v5(struct icside_state *state, struct expansion_card *ec) -{ - void __iomem *base; - struct ide_host *host; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - int ret; - - base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); - if (!base) - return -ENOMEM; - - state->irq_port = base; - - ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT; - ec->irqmask = 1; - - ecard_setirq(ec, &icside_ops_arcin_v5, state); - - /* - * Be on the safe side - disable interrupts - */ - icside_irqdisable_arcin_v5(ec, 0); - - icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec); - - host = ide_host_alloc(NULL, hws); - if (host == NULL) - return -ENODEV; - - state->host = host; - - ecard_set_drvdata(ec, state); - - ret = ide_host_register(host, NULL, hws); - if (ret) - goto err_free; - - return 0; -err_free: - ide_host_free(host); - ecard_set_drvdata(ec, NULL); - return ret; -} - -static const struct ide_port_info icside_v6_port_info __initdata = { - .init_dma = icside_dma_off_init, - .port_ops = &icside_v6_no_dma_port_ops, - .dma_ops = &icside_v6_dma_ops, - .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, - .mwdma_mask = ATA_MWDMA2, - .swdma_mask = ATA_SWDMA2, -}; - -static int __init -icside_register_v6(struct icside_state *state, struct expansion_card *ec) -{ - void __iomem *ioc_base, *easi_base; - struct ide_host *host; - unsigned int sel = 0; - int ret; - hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL }; - struct ide_port_info d = icside_v6_port_info; - - ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); - if (!ioc_base) { - ret = -ENOMEM; - goto out; - } - - easi_base = ioc_base; - - if (ecard_resource_flags(ec, ECARD_RES_EASI)) { - easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0); - if (!easi_base) { - ret = -ENOMEM; - goto out; - } - - /* - * Enable access to the EASI region. - */ - sel = 1 << 5; - } - - writeb(sel, ioc_base); - - ecard_setirq(ec, &icside_ops_arcin_v6, state); - - state->irq_port = easi_base; - state->ioc_base = ioc_base; - state->sel = sel; - - /* - * Be on the safe side - disable interrupts - */ - icside_irqdisable_arcin_v6(ec, 0); - - icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec); - icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec); - - host = ide_host_alloc(&d, hws); - if (host == NULL) - return -ENODEV; - - state->host = host; - - ecard_set_drvdata(ec, state); - - if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { - d.init_dma = icside_dma_init; - d.port_ops = &icside_v6_port_ops; - d.dma_ops = NULL; - } - - ret = ide_host_register(host, NULL, hws); - if (ret) - goto err_free; - - return 0; -err_free: - ide_host_free(host); - if (d.dma_ops) - free_dma(ec->dma); - ecard_set_drvdata(ec, NULL); -out: - return ret; -} - -static int __devinit -icside_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct icside_state *state; - void __iomem *idmem; - int ret; - - ret = ecard_request_resources(ec); - if (ret) - goto out; - - state = kzalloc(sizeof(struct icside_state), GFP_KERNEL); - if (!state) { - ret = -ENOMEM; - goto release; - } - - state->type = ICS_TYPE_NOTYPE; - - idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); - if (idmem) { - unsigned int type; - - type = readb(idmem + ICS_IDENT_OFFSET) & 1; - type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1; - type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2; - type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3; - ecardm_iounmap(ec, idmem); - - state->type = type; - } - - switch (state->type) { - case ICS_TYPE_A3IN: - dev_warn(&ec->dev, "A3IN unsupported\n"); - ret = -ENODEV; - break; - - case ICS_TYPE_A3USER: - dev_warn(&ec->dev, "A3USER unsupported\n"); - ret = -ENODEV; - break; - - case ICS_TYPE_V5: - ret = icside_register_v5(state, ec); - break; - - case ICS_TYPE_V6: - ret = icside_register_v6(state, ec); - break; - - default: - dev_warn(&ec->dev, "unknown interface type\n"); - ret = -ENODEV; - break; - } - - if (ret == 0) - goto out; - - kfree(state); - release: - ecard_release_resources(ec); - out: - return ret; -} - -static void __devexit icside_remove(struct expansion_card *ec) -{ - struct icside_state *state = ecard_get_drvdata(ec); - - switch (state->type) { - case ICS_TYPE_V5: - /* FIXME: tell IDE to stop using the interface */ - - /* Disable interrupts */ - icside_irqdisable_arcin_v5(ec, 0); - break; - - case ICS_TYPE_V6: - /* FIXME: tell IDE to stop using the interface */ - if (ec->dma != NO_DMA) - free_dma(ec->dma); - - /* Disable interrupts */ - icside_irqdisable_arcin_v6(ec, 0); - - /* Reset the ROM pointer/EASI selection */ - writeb(0, state->ioc_base); - break; - } - - ecard_set_drvdata(ec, NULL); - - kfree(state); - ecard_release_resources(ec); -} - -static void icside_shutdown(struct expansion_card *ec) -{ - struct icside_state *state = ecard_get_drvdata(ec); - unsigned long flags; - - /* - * Disable interrupts from this card. We need to do - * this before disabling EASI since we may be accessing - * this register via that region. - */ - local_irq_save(flags); - ec->ops->irqdisable(ec, 0); - local_irq_restore(flags); - - /* - * Reset the ROM pointer so that we can read the ROM - * after a soft reboot. This also disables access to - * the IDE taskfile via the EASI region. - */ - if (state->ioc_base) - writeb(0, state->ioc_base); -} - -static const struct ecard_id icside_ids[] = { - { MANU_ICS, PROD_ICS_IDE }, - { MANU_ICS2, PROD_ICS2_IDE }, - { 0xffff, 0xffff } -}; - -static struct ecard_driver icside_driver = { - .probe = icside_probe, - .remove = __devexit_p(icside_remove), - .shutdown = icside_shutdown, - .id_table = icside_ids, - .drv = { - .name = "icside", - }, -}; - -static int __init icside_init(void) -{ - return ecard_register_driver(&icside_driver); -} - -static void __exit icside_exit(void); -{ - ecard_unregister_driver(&icside_driver); -} - -MODULE_AUTHOR("Russell King "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ICS IDE driver"); - -module_init(icside_init); -module_exit(icside_exit); diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c deleted file mode 100644 index f728f29..0000000 --- a/drivers/ide/arm/ide_arm.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * ARM default IDE host driver - * - * Copyright (C) 2004 Bartlomiej Zolnierkiewicz - * Based on code by: Russell King, Ian Molton and Alexander Schulz. - * - * May be copied or modified under the terms of the GNU General Public License. - */ - -#include -#include -#include - -#include - -#define DRV_NAME "ide_arm" - -#ifdef CONFIG_ARCH_CLPS7500 -# include -# -# define IDE_ARM_IO (ISASLOT_IO + 0x1f0) -# define IDE_ARM_IRQ IRQ_ISA_14 -#else -# define IDE_ARM_IO 0x1f0 -# define IDE_ARM_IRQ IRQ_HARDDISK -#endif - -static int __init ide_arm_init(void) -{ - unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - if (!request_region(base, 8, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", - DRV_NAME, base, base + 7); - return -EBUSY; - } - - if (!request_region(ctl, 1, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", - DRV_NAME, ctl); - release_region(base, 8); - return -EBUSY; - } - - memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, base, ctl); - hw.irq = IDE_ARM_IRQ; - hw.chipset = ide_generic; - - return ide_host_add(NULL, hws, NULL); -} - -module_init(ide_arm_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c deleted file mode 100644 index 122ed3c..0000000 --- a/drivers/ide/arm/palm_bk3710.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Palmchip bk3710 IDE controller - * - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software, Inc., - * - * ---------------------------------------------------------------------------- - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * ---------------------------------------------------------------------------- - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Offset of the primary interface registers */ -#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0 - -/* Primary Control Offset */ -#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6 - -/* - * PalmChip 3710 IDE Controller UDMA timing structure Definition - */ -struct palm_bk3710_udmatiming { - unsigned int rptime; /* Ready to pause time */ - unsigned int cycletime; /* Cycle Time */ -}; - -#define BK3710_BMICP 0x00 -#define BK3710_BMISP 0x02 -#define BK3710_BMIDTP 0x04 -#define BK3710_BMICS 0x08 -#define BK3710_BMISS 0x0A -#define BK3710_BMIDTS 0x0C -#define BK3710_IDETIMP 0x40 -#define BK3710_IDETIMS 0x42 -#define BK3710_SIDETIM 0x44 -#define BK3710_SLEWCTL 0x45 -#define BK3710_IDESTATUS 0x47 -#define BK3710_UDMACTL 0x48 -#define BK3710_UDMATIM 0x4A -#define BK3710_MISCCTL 0x50 -#define BK3710_REGSTB 0x54 -#define BK3710_REGRCVR 0x58 -#define BK3710_DATSTB 0x5C -#define BK3710_DATRCVR 0x60 -#define BK3710_DMASTB 0x64 -#define BK3710_DMARCVR 0x68 -#define BK3710_UDMASTB 0x6C -#define BK3710_UDMATRP 0x70 -#define BK3710_UDMAENV 0x74 -#define BK3710_IORDYTMP 0x78 -#define BK3710_IORDYTMS 0x7C - -static unsigned ideclk_period; /* in nanoseconds */ - -static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = { - {160, 240}, /* UDMA Mode 0 */ - {125, 160}, /* UDMA Mode 1 */ - {100, 120}, /* UDMA Mode 2 */ - {100, 90}, /* UDMA Mode 3 */ - {100, 60}, /* UDMA Mode 4 */ - {85, 40}, /* UDMA Mode 5 */ -}; - -static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev, - unsigned int mode) -{ - u8 tenv, trp, t0; - u32 val32; - u16 val16; - - /* DMA Data Setup */ - t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime, - ideclk_period) - 1; - tenv = DIV_ROUND_UP(20, ideclk_period) - 1; - trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime, - ideclk_period) - 1; - - /* udmatim Register */ - val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0); - val16 |= (mode << (dev ? 4 : 0)); - writew(val16, base + BK3710_UDMATIM); - - /* udmastb Ultra DMA Access Strobe Width */ - val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8)); - val32 |= (t0 << (dev ? 8 : 0)); - writel(val32, base + BK3710_UDMASTB); - - /* udmatrp Ultra DMA Ready to Pause Time */ - val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8)); - val32 |= (trp << (dev ? 8 : 0)); - writel(val32, base + BK3710_UDMATRP); - - /* udmaenv Ultra DMA envelop Time */ - val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8)); - val32 |= (tenv << (dev ? 8 : 0)); - writel(val32, base + BK3710_UDMAENV); - - /* Enable UDMA for Device */ - val16 = readw(base + BK3710_UDMACTL) | (1 << dev); - writew(val16, base + BK3710_UDMACTL); -} - -static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev, - unsigned short min_cycle, - unsigned int mode) -{ - u8 td, tkw, t0; - u32 val32; - u16 val16; - struct ide_timing *t; - int cycletime; - - t = ide_timing_find_mode(mode); - cycletime = max_t(int, t->cycle, min_cycle); - - /* DMA Data Setup */ - t0 = DIV_ROUND_UP(cycletime, ideclk_period); - td = DIV_ROUND_UP(t->active, ideclk_period); - tkw = t0 - td - 1; - td -= 1; - - val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8)); - val32 |= (td << (dev ? 8 : 0)); - writel(val32, base + BK3710_DMASTB); - - val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8)); - val32 |= (tkw << (dev ? 8 : 0)); - writel(val32, base + BK3710_DMARCVR); - - /* Disable UDMA for Device */ - val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev); - writew(val16, base + BK3710_UDMACTL); -} - -static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, - unsigned int dev, unsigned int cycletime, - unsigned int mode) -{ - u8 t2, t2i, t0; - u32 val32; - struct ide_timing *t; - - /* PIO Data Setup */ - t0 = DIV_ROUND_UP(cycletime, ideclk_period); - t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active, - ideclk_period); - - t2i = t0 - t2 - 1; - t2 -= 1; - - val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8)); - val32 |= (t2 << (dev ? 8 : 0)); - writel(val32, base + BK3710_DATSTB); - - val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8)); - val32 |= (t2i << (dev ? 8 : 0)); - writel(val32, base + BK3710_DATRCVR); - - if (mate) { - u8 mode2 = ide_get_best_pio_mode(mate, 255, 4); - - if (mode2 < mode) - mode = mode2; - } - - /* TASKFILE Setup */ - t = ide_timing_find_mode(XFER_PIO_0 + mode); - t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period); - t2 = DIV_ROUND_UP(t->act8b, ideclk_period); - - t2i = t0 - t2 - 1; - t2 -= 1; - - val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8)); - val32 |= (t2 << (dev ? 8 : 0)); - writel(val32, base + BK3710_REGSTB); - - val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8)); - val32 |= (t2i << (dev ? 8 : 0)); - writel(val32, base + BK3710_REGRCVR); -} - -static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed) -{ - int is_slave = drive->dn & 1; - void __iomem *base = (void *)drive->hwif->dma_base; - - if (xferspeed >= XFER_UDMA_0) { - palm_bk3710_setudmamode(base, is_slave, - xferspeed - XFER_UDMA_0); - } else { - palm_bk3710_setdmamode(base, is_slave, - drive->id[ATA_ID_EIDE_DMA_MIN], - xferspeed); - } -} - -static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio) -{ - unsigned int cycle_time; - int is_slave = drive->dn & 1; - ide_drive_t *mate; - void __iomem *base = (void *)drive->hwif->dma_base; - - /* - * Obtain the drive PIO data for tuning the Palm Chip registers - */ - cycle_time = ide_pio_cycle_time(drive, pio); - mate = ide_get_pair_dev(drive); - palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio); -} - -static void __devinit palm_bk3710_chipinit(void __iomem *base) -{ - /* - * enable the reset_en of ATA controller so that when ata signals - * are brought out, by writing into device config. at that - * time por_n signal should not be 'Z' and have a stable value. - */ - writel(0x0300, base + BK3710_MISCCTL); - - /* wait for some time and deassert the reset of ATA Device. */ - mdelay(100); - - /* Deassert the Reset */ - writel(0x0200, base + BK3710_MISCCTL); - - /* - * Program the IDETIMP Register Value based on the following assumptions - * - * (ATA_IDETIMP_IDEEN , ENABLE ) | - * (ATA_IDETIMP_SLVTIMEN , DISABLE) | - * (ATA_IDETIMP_RDYSMPL , 70NS) | - * (ATA_IDETIMP_RDYRCVRY , 50NS) | - * (ATA_IDETIMP_DMAFTIM1 , PIOCOMP) | - * (ATA_IDETIMP_PREPOST1 , DISABLE) | - * (ATA_IDETIMP_RDYSEN1 , DISABLE) | - * (ATA_IDETIMP_PIOFTIM1 , DISABLE) | - * (ATA_IDETIMP_DMAFTIM0 , PIOCOMP) | - * (ATA_IDETIMP_PREPOST0 , DISABLE) | - * (ATA_IDETIMP_RDYSEN0 , DISABLE) | - * (ATA_IDETIMP_PIOFTIM0 , DISABLE) - */ - writew(0xB388, base + BK3710_IDETIMP); - - /* - * Configure SIDETIM Register - * (ATA_SIDETIM_RDYSMPS1 ,120NS ) | - * (ATA_SIDETIM_RDYRCYS1 ,120NS ) - */ - writeb(0, base + BK3710_SIDETIM); - - /* - * UDMACTL Ultra-ATA DMA Control - * (ATA_UDMACTL_UDMAP1 , 0 ) | - * (ATA_UDMACTL_UDMAP0 , 0 ) - * - */ - writew(0, base + BK3710_UDMACTL); - - /* - * MISCCTL Miscellaneous Conrol Register - * (ATA_MISCCTL_RSTMODEP , 1) | - * (ATA_MISCCTL_RESETP , 0) | - * (ATA_MISCCTL_TIMORIDE , 1) - */ - writel(0x201, base + BK3710_MISCCTL); - - /* - * IORDYTMP IORDY Timer for Primary Register - * (ATA_IORDYTMP_IORDYTMP , 0xffff ) - */ - writel(0xFFFF, base + BK3710_IORDYTMP); - - /* - * Configure BMISP Register - * (ATA_BMISP_DMAEN1 , DISABLE ) | - * (ATA_BMISP_DMAEN0 , DISABLE ) | - * (ATA_BMISP_IORDYINT , CLEAR) | - * (ATA_BMISP_INTRSTAT , CLEAR) | - * (ATA_BMISP_DMAERROR , CLEAR) - */ - writew(0, base + BK3710_BMISP); - - palm_bk3710_setpiomode(base, NULL, 0, 600, 0); - palm_bk3710_setpiomode(base, NULL, 1, 600, 0); -} - -static u8 palm_bk3710_cable_detect(ide_hwif_t *hwif) -{ - return ATA_CBL_PATA80; -} - -static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif, - const struct ide_port_info *d) -{ - printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); - - if (ide_allocate_dma_engine(hwif)) - return -1; - - hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET; - - hwif->dma_ops = &sff_dma_ops; - - return 0; -} - -static const struct ide_port_ops palm_bk3710_ports_ops = { - .set_pio_mode = palm_bk3710_set_pio_mode, - .set_dma_mode = palm_bk3710_set_dma_mode, - .cable_detect = palm_bk3710_cable_detect, -}; - -static struct ide_port_info __devinitdata palm_bk3710_port_info = { - .init_dma = palm_bk3710_init_dma, - .port_ops = &palm_bk3710_ports_ops, - .host_flags = IDE_HFLAG_MMIO, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, -}; - -static int __init palm_bk3710_probe(struct platform_device *pdev) -{ - struct clk *clk; - struct resource *mem, *irq; - unsigned long base, rate; - int i, rc; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - clk = clk_get(&pdev->dev, "IDECLK"); - if (IS_ERR(clk)) - return -ENODEV; - - clk_enable(clk); - rate = clk_get_rate(clk); - ideclk_period = 1000000000UL / rate; - - /* Register the IDE interface with Linux ATA Interface */ - memset(&hw, 0, sizeof(hw)); - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem == NULL) { - printk(KERN_ERR "failed to get memory region resource\n"); - return -ENODEV; - } - - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (irq == NULL) { - printk(KERN_ERR "failed to get IRQ resource\n"); - return -ENODEV; - } - - if (request_mem_region(mem->start, mem->end - mem->start + 1, - "palm_bk3710") == NULL) { - printk(KERN_ERR "failed to request memory region\n"); - return -EBUSY; - } - - base = IO_ADDRESS(mem->start); - - /* Configure the Palm Chip controller */ - palm_bk3710_chipinit((void __iomem *)base); - - for (i = 0; i < IDE_NR_PORTS - 2; i++) - hw.io_ports_array[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i; - hw.io_ports.ctl_addr = base + IDE_PALM_ATA_PRI_CTL_OFFSET; - hw.irq = irq->start; - hw.dev = &pdev->dev; - hw.chipset = ide_palm3710; - - palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 : - ATA_UDMA5; - - rc = ide_host_add(&palm_bk3710_port_info, hws, NULL); - if (rc) - goto out; - - return 0; -out: - printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n"); - return rc; -} - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:palm_bk3710"); - -static struct platform_driver platform_bk_driver = { - .driver = { - .name = "palm_bk3710", - .owner = THIS_MODULE, - }, -}; - -static int __init palm_bk3710_init(void) -{ - return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe); -} - -module_init(palm_bk3710_init); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c deleted file mode 100644 index 78d27d9..0000000 --- a/drivers/ide/arm/rapide.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 1996-2002 Russell King. - */ - -#include -#include -#include -#include -#include -#include - -#include - -static struct const ide_port_info rapide_port_info = { - .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, -}; - -static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base, - void __iomem *ctrl, unsigned int sz, int irq) -{ - unsigned long port = (unsigned long)base; - int i; - - for (i = 0; i <= 7; i++) { - hw->io_ports_array[i] = port; - port += sz; - } - hw->io_ports.ctl_addr = (unsigned long)ctrl; - hw->irq = irq; -} - -static int __devinit -rapide_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - void __iomem *base; - struct ide_host *host; - int ret; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - ret = ecard_request_resources(ec); - if (ret) - goto out; - - base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); - if (!base) { - ret = -ENOMEM; - goto release; - } - - memset(&hw, 0, sizeof(hw)); - rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq); - hw.chipset = ide_generic; - hw.dev = &ec->dev; - - ret = ide_host_add(&rapide_port_info, hws, &host); - if (ret) - goto release; - - ecard_set_drvdata(ec, host); - goto out; - - release: - ecard_release_resources(ec); - out: - return ret; -} - -static void __devexit rapide_remove(struct expansion_card *ec) -{ - struct ide_host *host = ecard_get_drvdata(ec); - - ecard_set_drvdata(ec, NULL); - - ide_host_remove(host); - - ecard_release_resources(ec); -} - -static struct ecard_id rapide_ids[] = { - { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, - { 0xffff, 0xffff } -}; - -static struct ecard_driver rapide_driver = { - .probe = rapide_probe, - .remove = __devexit_p(rapide_remove), - .id_table = rapide_ids, - .drv = { - .name = "rapide", - }, -}; - -static int __init rapide_init(void) -{ - return ecard_register_driver(&rapide_driver); -} - -static void __exit rapide_exit(void) -{ - ecard_unregister_driver(&rapide_driver); -} - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Yellowstone RAPIDE driver"); - -module_init(rapide_init); -module_exit(rapide_exit); diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c new file mode 100644 index 0000000..b2735d2 --- /dev/null +++ b/drivers/ide/atiixp.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2003 ATI Inc. + * Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz + */ + +#include +#include +#include +#include +#include +#include + +#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 + +typedef struct { + u8 command_width; + u8 recover_width; +} atiixp_ide_timing; + +static atiixp_ide_timing pio_timing[] = { + { 0x05, 0x0d }, + { 0x04, 0x07 }, + { 0x03, 0x04 }, + { 0x02, 0x02 }, + { 0x02, 0x00 }, +}; + +static 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 + * @drive: drive + * @pio: PIO mode number + * + * Set the interface PIO mode. + */ + +static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + unsigned long flags; + int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; + u32 pio_timing_data; + u16 pio_mode_data; + + 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 + * @drive: drive + * @speed: DMA mode + * + * 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_drive_t *drive, const u8 speed) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + unsigned long flags; + int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; + u32 tmp32; + u16 tmp16; + u16 udma_ctl = 0; + + 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[] __devinitdata = { + { /* 0: IXP200/300/400/700 */ + .name = DRV_NAME, + .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, + .port_ops = &atiixp_port_ops, + .host_flags = IDE_HFLAG_LEGACY_IRQS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, + }, + { /* 1: IXP600 */ + .name = DRV_NAME, + .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}}, + .port_ops = &atiixp_port_ops, + .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS, + .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 __devinit 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 }, + { 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"); diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c new file mode 100644 index 0000000..0ec8fd1 --- /dev/null +++ b/drivers/ide/au1xxx-ide.c @@ -0,0 +1,642 @@ +/* + * BRIEF MODULE DESCRIPTION + * AMD Alchemy Au1xxx IDE interface routines over the Static Bus + * + * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE + * Interface and Linux Device Driver" Application Note. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define DRV_NAME "au1200-ide" +#define DRV_AUTHOR "Enrico Walther / Pete Popov " + +/* enable the burstmode in the dbdma */ +#define IDE_AU1XXX_BURSTMODE 1 + +static _auide_hwif auide_hwif; + +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) + +void auide_insw(unsigned long port, void *addr, u32 count) +{ + _auide_hwif *ahwif = &auide_hwif; + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + + if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, + DDMA_FLAGS_NOIE)) { + printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); + return; + } + ctp = *((chan_tab_t **)ahwif->rx_chan); + dp = ctp->cur_ptr; + while (dp->dscr_cmd0 & DSCR_CMD0_V) + ; + ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); +} + +void auide_outsw(unsigned long port, void *addr, u32 count) +{ + _auide_hwif *ahwif = &auide_hwif; + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; + + if(!put_source_flags(ahwif->tx_chan, (void*)addr, + count << 1, DDMA_FLAGS_NOIE)) { + printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); + return; + } + ctp = *((chan_tab_t **)ahwif->tx_chan); + dp = ctp->cur_ptr; + while (dp->dscr_cmd0 & DSCR_CMD0_V) + ; + ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); +} + +static void au1xxx_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + auide_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); +} + +static void au1xxx_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + auide_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); +} +#endif + +static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2); + + /* set pio mode! */ + switch(pio) { + case 0: + mem_sttime = SBC_IDE_TIMING(PIO0); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS; + break; + + case 1: + mem_sttime = SBC_IDE_TIMING(PIO1); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS; + break; + + case 2: + mem_sttime = SBC_IDE_TIMING(PIO2); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS; + break; + + case 3: + mem_sttime = SBC_IDE_TIMING(PIO3); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS; + + break; + + case 4: + mem_sttime = SBC_IDE_TIMING(PIO4); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS; + break; + } + + au_writel(mem_sttime,MEM_STTIME2); + au_writel(mem_stcfg,MEM_STCFG2); +} + +static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2); + + switch(speed) { +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + case XFER_MW_DMA_2: + mem_sttime = SBC_IDE_TIMING(MDMA2); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS; + + break; + case XFER_MW_DMA_1: + mem_sttime = SBC_IDE_TIMING(MDMA1); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS; + + break; + case XFER_MW_DMA_0: + mem_sttime = SBC_IDE_TIMING(MDMA0); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS; + + break; +#endif + } + + au_writel(mem_sttime,MEM_STTIME2); + au_writel(mem_stcfg,MEM_STCFG2); +} + +/* + * Multi-Word DMA + DbDMA functions + */ + +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA +static int auide_build_dmatable(ide_drive_t *drive) +{ + int i, iswrite, count = 0; + ide_hwif_t *hwif = HWIF(drive); + struct request *rq = HWGROUP(drive)->rq; + _auide_hwif *ahwif = &auide_hwif; + struct scatterlist *sg; + + iswrite = (rq_data_dir(rq) == WRITE); + /* Save for interrupt context */ + ahwif->drive = drive; + + hwif->sg_nents = i = ide_build_sglist(drive, rq); + + if (!i) + return 0; + + /* fill the descriptors */ + sg = hwif->sg_table; + while (i && sg_dma_len(sg)) { + u32 cur_addr; + u32 cur_len; + + cur_addr = sg_dma_address(sg); + cur_len = sg_dma_len(sg); + + while (cur_len) { + u32 flags = DDMA_FLAGS_NOIE; + unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; + + if (++count >= PRD_ENTRIES) { + printk(KERN_WARNING "%s: DMA table too small\n", + drive->name); + goto use_pio_instead; + } + + /* Lets enable intr for the last descriptor only */ + if (1==i) + flags = DDMA_FLAGS_IE; + else + flags = DDMA_FLAGS_NOIE; + + if (iswrite) { + if(!put_source_flags(ahwif->tx_chan, + (void*) sg_virt(sg), + tc, flags)) { + printk(KERN_ERR "%s failed %d\n", + __func__, __LINE__); + } + } else + { + if(!put_dest_flags(ahwif->rx_chan, + (void*) sg_virt(sg), + tc, flags)) { + printk(KERN_ERR "%s failed %d\n", + __func__, __LINE__); + } + } + + cur_addr += tc; + cur_len -= tc; + } + sg = sg_next(sg); + i--; + } + + if (count) + return 1; + + use_pio_instead: + ide_destroy_dmatable(drive); + + return 0; /* revert to PIO for this request */ +} + +static int auide_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + + if (hwif->sg_nents) { + ide_destroy_dmatable(drive); + hwif->sg_nents = 0; + } + + return 0; +} + +static void auide_dma_start(ide_drive_t *drive ) +{ +} + + +static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command) +{ + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, + (2*WAIT_CMD), NULL); +} + +static int auide_dma_setup(ide_drive_t *drive) +{ + struct request *rq = HWGROUP(drive)->rq; + + if (!auide_build_dmatable(drive)) { + ide_map_sg(drive, rq); + return 1; + } + + drive->waiting_for_dma = 1; + return 0; +} + +static int auide_dma_test_irq(ide_drive_t *drive) +{ + /* If dbdma didn't execute the STOP command yet, the + * active bit is still set + */ + drive->waiting_for_dma++; + if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { + printk(KERN_WARNING "%s: timeout waiting for ddma to \ + complete\n", drive->name); + return 1; + } + udelay(10); + return 0; +} + +static void auide_dma_host_set(ide_drive_t *drive, int on) +{ +} + +static void auide_ddma_tx_callback(int irq, void *param) +{ + _auide_hwif *ahwif = (_auide_hwif*)param; + ahwif->drive->waiting_for_dma = 0; +} + +static void auide_ddma_rx_callback(int irq, void *param) +{ + _auide_hwif *ahwif = (_auide_hwif*)param; + ahwif->drive->waiting_for_dma = 0; +} + +#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ + +static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags) +{ + dev->dev_id = dev_id; + dev->dev_physaddr = (u32)IDE_PHYS_ADDR; + dev->dev_intlevel = 0; + dev->dev_intpolarity = 0; + dev->dev_tsize = tsize; + dev->dev_devwidth = devwidth; + dev->dev_flags = flags; +} + +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA +static const struct ide_dma_ops au1xxx_dma_ops = { + .dma_host_set = auide_dma_host_set, + .dma_setup = auide_dma_setup, + .dma_exec_cmd = auide_dma_exec_cmd, + .dma_start = auide_dma_start, + .dma_end = auide_dma_end, + .dma_test_irq = auide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) +{ + _auide_hwif *auide = &auide_hwif; + dbdev_tab_t source_dev_tab, target_dev_tab; + u32 dev_id, tsize, devwidth, flags; + + dev_id = IDE_DDMA_REQ; + + tsize = 8; /* 1 */ + devwidth = 32; /* 16 */ + +#ifdef IDE_AU1XXX_BURSTMODE + flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE; +#else + flags = DEV_FLAGS_SYNC; +#endif + + /* setup dev_tab for tx channel */ + auide_init_dbdma_dev( &source_dev_tab, + dev_id, + tsize, devwidth, DEV_FLAGS_OUT | flags); + auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + + auide_init_dbdma_dev( &source_dev_tab, + dev_id, + tsize, devwidth, DEV_FLAGS_IN | flags); + auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + + /* We also need to add a target device for the DMA */ + auide_init_dbdma_dev( &target_dev_tab, + (u32)DSCR_CMD0_ALWAYS, + tsize, devwidth, DEV_FLAGS_ANYUSE); + auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab); + + /* Get a channel for TX */ + auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id, + auide->tx_dev_id, + auide_ddma_tx_callback, + (void*)auide); + + /* Get a channel for RX */ + auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, + auide->target_dev_id, + auide_ddma_rx_callback, + (void*)auide); + + auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan, + NUM_DESCRIPTORS); + auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, + NUM_DESCRIPTORS); + + /* FIXME: check return value */ + (void)ide_allocate_dma_engine(hwif); + + au1xxx_dbdma_start( auide->tx_chan ); + au1xxx_dbdma_start( auide->rx_chan ); + + return 0; +} +#else +static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) +{ + _auide_hwif *auide = &auide_hwif; + dbdev_tab_t source_dev_tab; + int flags; + +#ifdef IDE_AU1XXX_BURSTMODE + flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE; +#else + flags = DEV_FLAGS_SYNC; +#endif + + /* setup dev_tab for tx channel */ + auide_init_dbdma_dev( &source_dev_tab, + (u32)DSCR_CMD0_ALWAYS, + 8, 32, DEV_FLAGS_OUT | flags); + auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + + auide_init_dbdma_dev( &source_dev_tab, + (u32)DSCR_CMD0_ALWAYS, + 8, 32, DEV_FLAGS_IN | flags); + auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + + /* Get a channel for TX */ + auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS, + auide->tx_dev_id, + NULL, + (void*)auide); + + /* Get a channel for RX */ + auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, + DSCR_CMD0_ALWAYS, + NULL, + (void*)auide); + + auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan, + NUM_DESCRIPTORS); + auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, + NUM_DESCRIPTORS); + + au1xxx_dbdma_start( auide->tx_chan ); + au1xxx_dbdma_start( auide->rx_chan ); + + return 0; +} +#endif + +static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) +{ + int i; + unsigned long *ata_regs = hw->io_ports_array; + + /* FIXME? */ + for (i = 0; i < 8; i++) + *ata_regs++ = ahwif->regbase + (i << IDE_REG_SHIFT); + + /* set the Alternative Status register */ + *ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT); +} + +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA +static const struct ide_tp_ops au1xxx_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + .read_sff_dma_status = ide_read_sff_dma_status, + + .set_irq = ide_set_irq, + + .tf_load = ide_tf_load, + .tf_read = ide_tf_read, + + .input_data = au1xxx_input_data, + .output_data = au1xxx_output_data, +}; +#endif + +static const struct ide_port_ops au1xxx_port_ops = { + .set_pio_mode = au1xxx_set_pio_mode, + .set_dma_mode = auide_set_dma_mode, +}; + +static const struct ide_port_info au1xxx_port_info = { + .init_dma = auide_ddma_init, +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA + .tp_ops = &au1xxx_tp_ops, +#endif + .port_ops = &au1xxx_port_ops, +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + .dma_ops = &au1xxx_dma_ops, +#endif + .host_flags = IDE_HFLAG_POST_SET_MODE | + IDE_HFLAG_NO_IO_32BIT | + IDE_HFLAG_UNMASK_IRQS, + .pio_mask = ATA_PIO4, +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + .mwdma_mask = ATA_MWDMA2, +#endif +}; + +static int au_ide_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + _auide_hwif *ahwif = &auide_hwif; + struct resource *res; + struct ide_host *host; + int ret = 0; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) + char *mode = "MWDMA2"; +#elif defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) + char *mode = "PIO+DDMA(offload)"; +#endif + + memset(&auide_hwif, 0, sizeof(_auide_hwif)); + ahwif->irq = platform_get_irq(pdev, 0); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (res == NULL) { + pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id); + ret = -ENODEV; + goto out; + } + if (ahwif->irq < 0) { + pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id); + ret = -ENODEV; + goto out; + } + + if (!request_mem_region(res->start, res->end - res->start + 1, + pdev->name)) { + pr_debug("%s: request_mem_region failed\n", DRV_NAME); + ret = -EBUSY; + goto out; + } + + ahwif->regbase = (u32)ioremap(res->start, res->end - res->start + 1); + if (ahwif->regbase == 0) { + ret = -ENOMEM; + goto out; + } + + memset(&hw, 0, sizeof(hw)); + auide_setup_ports(&hw, ahwif); + hw.irq = ahwif->irq; + hw.dev = dev; + hw.chipset = ide_au1xxx; + + ret = ide_host_add(&au1xxx_port_info, hws, &host); + if (ret) + goto out; + + auide_hwif.hwif = host->ports[0]; + + dev_set_drvdata(dev, host); + + printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); + + out: + return ret; +} + +static int au_ide_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct resource *res; + struct ide_host *host = dev_get_drvdata(dev); + _auide_hwif *ahwif = &auide_hwif; + + ide_host_remove(host); + + iounmap((void *)ahwif->regbase); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + + return 0; +} + +static struct device_driver au1200_ide_driver = { + .name = "au1200-ide", + .bus = &platform_bus_type, + .probe = au_ide_probe, + .remove = au_ide_remove, +}; + +static int __init au_ide_init(void) +{ + return driver_register(&au1200_ide_driver); +} + +static void __exit au_ide_exit(void) +{ + driver_unregister(&au1200_ide_driver); +} + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AU1200 IDE driver"); + +module_init(au_ide_init); +module_exit(au_ide_exit); diff --git a/drivers/ide/buddha.c b/drivers/ide/buddha.c new file mode 100644 index 0000000..c5a3c9e --- /dev/null +++ b/drivers/ide/buddha.c @@ -0,0 +1,235 @@ +/* + * Amiga Buddha, Catweasel and X-Surf IDE Driver + * + * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others + * + * This driver was written based on the specifications in README.buddha and + * the X-Surf info from Inside_XSurf.txt available at + * http://www.jschoenfeld.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * TODO: + * - test it :-) + * - tune the timings using the speed-register + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + /* + * 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_ack_intr(ide_hwif_t *hwif) +{ + unsigned char ch; + + ch = z_readb(hwif->io_ports.irq_addr); + if (!(ch & 0x80)) + return 0; + return 1; +} + +static int xsurf_ack_intr(ide_hwif_t *hwif) +{ + unsigned char ch; + + ch = z_readb(hwif->io_ports.irq_addr); + /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */ + z_writeb(0, hwif->io_ports.irq_addr); + if (!(ch & 0x80)) + return 0; + return 1; +} + +static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, + unsigned long ctl, unsigned long irq_port, + ide_ack_intr_t *ack_intr) +{ + 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; + hw->ack_intr = ack_intr; + + hw->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; + hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; + + if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { + buddha_num_hwifs = BUDDHA_NUM_HWIFS; + 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; + +/* + * FIXME: we now have selectable mmio v/s iomio transports. + */ + + 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); + + 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; + ide_ack_intr_t *ack_intr; + + if (type != BOARD_XSURF) { + base = buddha_board + buddha_bases[i]; + ctl = base + BUDDHA_CONTROL; + irq_port = buddha_board + buddha_irqports[i]; + ack_intr = buddha_ack_intr; + } else { + base = buddha_board + xsurf_bases[i]; + /* X-Surf has no CS1* (Control/AltStat) */ + ctl = 0; + irq_port = buddha_board + xsurf_irqports[i]; + ack_intr = xsurf_ack_intr; + } + + buddha_setup_ports(&hw[i], base, ctl, irq_port, + ack_intr); + + hws[i] = &hw[i]; + } + + ide_host_add(NULL, hws, NULL); + } + + return 0; +} + +module_init(buddha_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c new file mode 100644 index 0000000..e430664 --- /dev/null +++ b/drivers/ide/cmd640.c @@ -0,0 +1,836 @@ +/* + * Copyright (C) 1995-1996 Linus Torvalds & authors (see below) + */ + +/* + * Original authors: abramov@cecmow.enet.dec.com (Igor Abramov) + * mlord@pobox.com (Mark Lord) + * + * See linux/MAINTAINERS for address of current maintainer. + * + * This file provides support for the advanced features and bugs + * of IDE interfaces using the CMD Technologies 0640 IDE interface chip. + * + * These chips are basically fucked by design, and getting this driver + * to work on every motherboard design that uses this screwed chip seems + * bloody well impossible. However, we're still trying. + * + * Version 0.97 worked for everybody. + * + * User feedback is essential. Many thanks to the beta test team: + * + * A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com, + * bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz, + * chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de, + * derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de, + * flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net, + * j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net, + * kerouac@ssnet.com, meskes@informatik.rwth-aachen.de, hzoli@cs.elte.hu, + * peter@udgaard.isgtec.com, phil@tazenda.demon.co.uk, roadcapw@cfw.com, + * s0033las@sun10.vsz.bme.hu, schaffer@tam.cornell.edu, sjd@slip.net, + * steve@ei.org, ulrpeg@bigcomm.gun.de, ism@tardis.ed.ac.uk, mack@cray.com + * liug@mama.indstate.edu, and others. + * + * Version 0.01 Initial version, hacked out of ide.c, + * and #include'd rather than compiled separately. + * This will get cleaned up in a subsequent release. + * + * Version 0.02 Fixes for vlb initialization code, enable prefetch + * for versions 'B' and 'C' of chip by default, + * some code cleanup. + * + * Version 0.03 Added reset of secondary interface, + * and black list for devices which are not compatible + * with prefetch mode. Separate function for setting + * prefetch is added, possibly it will be called some + * day from ioctl processing code. + * + * Version 0.04 Now configs/compiles separate from ide.c + * + * Version 0.05 Major rewrite of interface timing code. + * Added new function cmd640_set_mode to set PIO mode + * from ioctl call. New drives added to black list. + * + * Version 0.06 More code cleanup. Prefetch is enabled only for + * detected hard drives, not included in prefetch + * black list. + * + * Version 0.07 Changed to more conservative drive tuning policy. + * Unknown drives, which report PIO < 4 are set to + * (reported_PIO - 1) if it is supported, or to PIO0. + * List of known drives extended by info provided by + * CMD at their ftp site. + * + * Version 0.08 Added autotune/noautotune support. + * + * Version 0.09 Try to be smarter about 2nd port enabling. + * Version 0.10 Be nice and don't reset 2nd port. + * Version 0.11 Try to handle more weird situations. + * + * Version 0.12 Lots of bug fixes from Laszlo Peter + * irq unmasking disabled for reliability. + * try to be even smarter about the second port. + * tidy up source code formatting. + * Version 0.13 permit irq unmasking again. + * Version 0.90 massive code cleanup, some bugs fixed. + * defaults all drives to PIO mode0, prefetch off. + * autotune is OFF by default, with compile time flag. + * prefetch can be turned OFF/ON using "hdparm -p8/-p9" + * (requires hdparm-3.1 or newer) + * Version 0.91 first release to linux-kernel list. + * Version 0.92 move initial reg dump to separate callable function + * change "readahead" to "prefetch" to avoid confusion + * Version 0.95 respect original BIOS timings unless autotuning. + * tons of code cleanup and rearrangement. + * added CONFIG_BLK_DEV_CMD640_ENHANCED option + * prevent use of unmask when prefetch is on + * Version 0.96 prevent use of io_32bit when prefetch is off + * Version 0.97 fix VLB secondary interface for sjd@slip.net + * other minor tune-ups: 0.96 was very good. + * Version 0.98 ignore PCI version when disabled by BIOS + * Version 0.99 display setup/active/recovery clocks with PIO mode + * Version 1.00 Mmm.. cannot depend on PCMD_ENA in all systems + * Version 1.01 slow/fast devsel can be selected with "hdparm -p6/-p7" + * ("fast" is necessary for 32bit I/O in some systems) + * Version 1.02 fix bug that resulted in slow "setup times" + * (patch courtesy of Zoltan Hidvegi) + */ + +#define CMD640_PREFETCH_MASKS 1 + +/*#define CMD640_DUMP_REGS */ + +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "cmd640" + +static int cmd640_vlb; + +/* + * CMD640 specific registers definition. + */ + +#define VID 0x00 +#define DID 0x02 +#define PCMD 0x04 +#define PCMD_ENA 0x01 +#define PSTTS 0x06 +#define REVID 0x08 +#define PROGIF 0x09 +#define SUBCL 0x0a +#define BASCL 0x0b +#define BaseA0 0x10 +#define BaseA1 0x14 +#define BaseA2 0x18 +#define BaseA3 0x1c +#define INTLINE 0x3c +#define INPINE 0x3d + +#define CFR 0x50 +#define CFR_DEVREV 0x03 +#define CFR_IDE01INTR 0x04 +#define CFR_DEVID 0x18 +#define CFR_AT_VESA_078h 0x20 +#define CFR_DSA1 0x40 +#define CFR_DSA0 0x80 + +#define CNTRL 0x51 +#define CNTRL_DIS_RA0 0x40 +#define CNTRL_DIS_RA1 0x80 +#define CNTRL_ENA_2ND 0x08 + +#define CMDTIM 0x52 +#define ARTTIM0 0x53 +#define DRWTIM0 0x54 +#define ARTTIM1 0x55 +#define DRWTIM1 0x56 +#define ARTTIM23 0x57 +#define ARTTIM23_DIS_RA2 0x04 +#define ARTTIM23_DIS_RA3 0x08 +#define DRWTIM23 0x58 +#define BRST 0x59 + +/* + * Registers and masks for easy access by drive index: + */ +static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; +static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; + +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + +static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; +static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; + +/* + * Current cmd640 timing values for each drive. + * The defaults for each are the slowest possible timings. + */ +static u8 setup_counts[4] = {4, 4, 4, 4}; /* Address setup count (in clocks) */ +static u8 active_counts[4] = {16, 16, 16, 16}; /* Active count (encoded) */ +static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ + +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + +static DEFINE_SPINLOCK(cmd640_lock); + +/* + * Interface to access cmd640x registers + */ +static unsigned int cmd640_key; +static void (*__put_cmd640_reg)(u16 reg, u8 val); +static u8 (*__get_cmd640_reg)(u16 reg); + +/* + * This is read from the CFR reg, and is used in several places. + */ +static unsigned int cmd640_chip_version; + +/* + * The CMD640x chip does not support DWORD config write cycles, but some + * of the BIOSes use them to implement the config services. + * Therefore, we must use direct IO instead. + */ + +/* PCI method 1 access */ + +static void put_cmd640_reg_pci1(u16 reg, u8 val) +{ + outl_p((reg & 0xfc) | cmd640_key, 0xcf8); + outb_p(val, (reg & 3) | 0xcfc); +} + +static u8 get_cmd640_reg_pci1(u16 reg) +{ + outl_p((reg & 0xfc) | cmd640_key, 0xcf8); + return inb_p((reg & 3) | 0xcfc); +} + +/* PCI method 2 access (from CMD datasheet) */ + +static void put_cmd640_reg_pci2(u16 reg, u8 val) +{ + outb_p(0x10, 0xcf8); + outb_p(val, cmd640_key + reg); + outb_p(0, 0xcf8); +} + +static u8 get_cmd640_reg_pci2(u16 reg) +{ + u8 b; + + outb_p(0x10, 0xcf8); + b = inb_p(cmd640_key + reg); + outb_p(0, 0xcf8); + return b; +} + +/* VLB access */ + +static void put_cmd640_reg_vlb(u16 reg, u8 val) +{ + outb_p(reg, cmd640_key); + outb_p(val, cmd640_key + 4); +} + +static u8 get_cmd640_reg_vlb(u16 reg) +{ + outb_p(reg, cmd640_key); + return inb_p(cmd640_key + 4); +} + +static u8 get_cmd640_reg(u16 reg) +{ + unsigned long flags; + u8 b; + + spin_lock_irqsave(&cmd640_lock, flags); + b = __get_cmd640_reg(reg); + spin_unlock_irqrestore(&cmd640_lock, flags); + return b; +} + +static void put_cmd640_reg(u16 reg, u8 val) +{ + unsigned long flags; + + spin_lock_irqsave(&cmd640_lock, flags); + __put_cmd640_reg(reg, val); + spin_unlock_irqrestore(&cmd640_lock, flags); +} + +static int __init match_pci_cmd640_device(void) +{ + const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; + unsigned int i; + for (i = 0; i < 4; i++) { + if (get_cmd640_reg(i) != ven_dev[i]) + return 0; + } +#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT + if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) { + printk("ide: cmd640 on PCI disabled by BIOS\n"); + return 0; + } +#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */ + return 1; /* success */ +} + +/* + * Probe for CMD640x -- pci method 1 + */ +static int __init probe_for_cmd640_pci1(void) +{ + __get_cmd640_reg = get_cmd640_reg_pci1; + __put_cmd640_reg = put_cmd640_reg_pci1; + for (cmd640_key = 0x80000000; + cmd640_key <= 0x8000f800; + cmd640_key += 0x800) { + if (match_pci_cmd640_device()) + return 1; /* success */ + } + return 0; +} + +/* + * Probe for CMD640x -- pci method 2 + */ +static int __init probe_for_cmd640_pci2(void) +{ + __get_cmd640_reg = get_cmd640_reg_pci2; + __put_cmd640_reg = put_cmd640_reg_pci2; + for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { + if (match_pci_cmd640_device()) + return 1; /* success */ + } + return 0; +} + +/* + * Probe for CMD640x -- vlb + */ +static int __init probe_for_cmd640_vlb(void) +{ + u8 b; + + __get_cmd640_reg = get_cmd640_reg_vlb; + __put_cmd640_reg = put_cmd640_reg_vlb; + cmd640_key = 0x178; + b = get_cmd640_reg(CFR); + if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { + cmd640_key = 0x78; + b = get_cmd640_reg(CFR); + if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h)) + return 0; + } + return 1; /* success */ +} + +/* + * Returns 1 if an IDE interface/drive exists at 0x170, + * Returns 0 otherwise. + */ +static int __init secondary_port_responding(void) +{ + unsigned long flags; + + spin_lock_irqsave(&cmd640_lock, flags); + + outb_p(0x0a, 0x176); /* select drive0 */ + udelay(100); + if ((inb_p(0x176) & 0x1f) != 0x0a) { + outb_p(0x1a, 0x176); /* select drive1 */ + udelay(100); + if ((inb_p(0x176) & 0x1f) != 0x1a) { + spin_unlock_irqrestore(&cmd640_lock, flags); + return 0; /* nothing responded */ + } + } + spin_unlock_irqrestore(&cmd640_lock, flags); + return 1; /* success */ +} + +#ifdef CMD640_DUMP_REGS +/* + * Dump out all cmd640 registers. May be called from ide.c + */ +static void cmd640_dump_regs(void) +{ + unsigned int reg = cmd640_vlb ? 0x50 : 0x00; + + /* Dump current state of chip registers */ + printk("ide: cmd640 internal register dump:"); + for (; reg <= 0x59; reg++) { + if (!(reg & 0x0f)) + printk("\n%04x:", reg); + printk(" %02x", get_cmd640_reg(reg)); + } + printk("\n"); +} +#endif + +static void __set_prefetch_mode(ide_drive_t *drive, int mode) +{ + if (mode) { /* want prefetch on? */ +#if CMD640_PREFETCH_MASKS + drive->dev_flags |= IDE_DFLAG_NO_UNMASK; + drive->dev_flags &= ~IDE_DFLAG_UNMASK; +#endif + drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT; + } else { + drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK; + drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT; + drive->io_32bit = 0; + } +} + +#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED +/* + * Check whether prefetch is on for a drive, + * and initialize the unmask flags for safe operation. + */ +static void __init check_prefetch(ide_drive_t *drive, unsigned int index) +{ + u8 b = get_cmd640_reg(prefetch_regs[index]); + + __set_prefetch_mode(drive, (b & prefetch_masks[index]) ? 0 : 1); +} +#else + +/* + * Sets prefetch mode for a drive. + */ +static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode) +{ + unsigned long flags; + int reg = prefetch_regs[index]; + u8 b; + + spin_lock_irqsave(&cmd640_lock, flags); + b = __get_cmd640_reg(reg); + __set_prefetch_mode(drive, mode); + if (mode) + b &= ~prefetch_masks[index]; /* enable prefetch */ + else + b |= prefetch_masks[index]; /* disable prefetch */ + __put_cmd640_reg(reg, b); + spin_unlock_irqrestore(&cmd640_lock, flags); +} + +/* + * Dump out current drive clocks settings + */ +static void display_clocks(unsigned int index) +{ + u8 active_count, recovery_count; + + active_count = active_counts[index]; + if (active_count == 1) + ++active_count; + recovery_count = recovery_counts[index]; + if (active_count > 3 && recovery_count == 1) + ++recovery_count; + if (cmd640_chip_version > 1) + recovery_count += 1; /* cmd640b uses (count + 1)*/ + printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count); +} + +/* + * Pack active and recovery counts into single byte representation + * used by controller + */ +static inline u8 pack_nibbles(u8 upper, u8 lower) +{ + return ((upper & 0x0f) << 4) | (lower & 0x0f); +} + +/* + * This routine writes the prepared setup/active/recovery counts + * for a drive into the cmd640 chipset registers to active them. + */ +static void program_drive_counts(ide_drive_t *drive, unsigned int index) +{ + unsigned long flags; + u8 setup_count = setup_counts[index]; + u8 active_count = active_counts[index]; + u8 recovery_count = recovery_counts[index]; + + /* + * Set up address setup count and drive read/write timing registers. + * Primary interface has individual count/timing registers for + * each drive. Secondary interface has one common set of registers, + * so we merge the timings, using the slowest value for each timing. + */ + if (index > 1) { + ide_hwif_t *hwif = drive->hwif; + ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)]; + unsigned int mate = index ^ 1; + + if (peer->dev_flags & IDE_DFLAG_PRESENT) { + if (setup_count < setup_counts[mate]) + setup_count = setup_counts[mate]; + if (active_count < active_counts[mate]) + active_count = active_counts[mate]; + if (recovery_count < recovery_counts[mate]) + recovery_count = recovery_counts[mate]; + } + } + + /* + * Convert setup_count to internal chipset representation + */ + switch (setup_count) { + case 4: setup_count = 0x00; break; + case 3: setup_count = 0x80; break; + case 1: + case 2: setup_count = 0x40; break; + default: setup_count = 0xc0; /* case 5 */ + } + + /* + * Now that everything is ready, program the new timings + */ + spin_lock_irqsave(&cmd640_lock, flags); + /* + * Program the address_setup clocks into ARTTIM reg, + * and then the active/recovery counts into the DRWTIM reg + * (this converts counts of 16 into counts of zero -- okay). + */ + setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f; + __put_cmd640_reg(arttim_regs[index], setup_count); + __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); + spin_unlock_irqrestore(&cmd640_lock, flags); +} + +/* + * Set a specific pio_mode for a drive + */ +static void cmd640_set_mode(ide_drive_t *drive, unsigned int index, + u8 pio_mode, unsigned int cycle_time) +{ + struct ide_timing *t; + int setup_time, active_time, recovery_time, clock_time; + u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count; + int bus_speed; + + if (cmd640_vlb) + bus_speed = ide_vlb_clk ? ide_vlb_clk : 50; + else + bus_speed = ide_pci_clk ? ide_pci_clk : 33; + + if (pio_mode > 5) + pio_mode = 5; + + t = ide_timing_find_mode(XFER_PIO_0 + pio_mode); + setup_time = t->setup; + active_time = t->active; + + recovery_time = cycle_time - (setup_time + active_time); + clock_time = 1000 / bus_speed; + cycle_count = DIV_ROUND_UP(cycle_time, clock_time); + + setup_count = DIV_ROUND_UP(setup_time, clock_time); + + active_count = DIV_ROUND_UP(active_time, clock_time); + if (active_count < 2) + active_count = 2; /* minimum allowed by cmd640 */ + + recovery_count = DIV_ROUND_UP(recovery_time, clock_time); + recovery_count2 = cycle_count - (setup_count + active_count); + if (recovery_count2 > recovery_count) + recovery_count = recovery_count2; + if (recovery_count < 2) + recovery_count = 2; /* minimum allowed by cmd640 */ + if (recovery_count > 17) { + active_count += recovery_count - 17; + recovery_count = 17; + } + if (active_count > 16) + active_count = 16; /* maximum allowed by cmd640 */ + if (cmd640_chip_version > 1) + recovery_count -= 1; /* cmd640b uses (count + 1)*/ + if (recovery_count > 16) + recovery_count = 16; /* maximum allowed by cmd640 */ + + setup_counts[index] = setup_count; + active_counts[index] = active_count; + recovery_counts[index] = recovery_count; + + /* + * In a perfect world, we might set the drive pio mode here + * (using WIN_SETFEATURE) before continuing. + * + * But we do not, because: + * 1) this is the wrong place to do it (proper is do_special() in ide.c) + * 2) in practice this is rarely, if ever, necessary + */ + program_drive_counts(drive, index); +} + +static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + unsigned int index = 0, cycle_time; + u8 b; + + switch (pio) { + case 6: /* set fast-devsel off */ + case 7: /* set fast-devsel on */ + b = get_cmd640_reg(CNTRL) & ~0x27; + if (pio & 1) + b |= 0x27; + put_cmd640_reg(CNTRL, b); + printk("%s: %sabled cmd640 fast host timing (devsel)\n", + drive->name, (pio & 1) ? "en" : "dis"); + return; + case 8: /* set prefetch off */ + case 9: /* set prefetch on */ + set_prefetch_mode(drive, index, pio & 1); + printk("%s: %sabled cmd640 prefetch\n", + drive->name, (pio & 1) ? "en" : "dis"); + return; + } + + cycle_time = ide_pio_cycle_time(drive, pio); + cmd640_set_mode(drive, index, pio, cycle_time); + + printk("%s: selected cmd640 PIO mode%d (%dns)", + drive->name, pio, cycle_time); + + display_clocks(index); +} +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + +static void cmd640_init_dev(ide_drive_t *drive) +{ + unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1); + +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + /* + * Reset timing to the slowest speed and turn off prefetch. + * This way, the drive identify code has a better chance. + */ + setup_counts[i] = 4; /* max possible */ + active_counts[i] = 16; /* max possible */ + recovery_counts[i] = 16; /* max possible */ + program_drive_counts(drive, i); + set_prefetch_mode(drive, i, 0); + printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch cleared\n", i); +#else + /* + * Set the drive unmask flags to match the prefetch setting. + */ + check_prefetch(drive, i); + printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n", + i, (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) ? "off" : "on"); +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ +} + + +static const struct ide_port_ops cmd640_port_ops = { + .init_dev = cmd640_init_dev, +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + .set_pio_mode = cmd640_set_pio_mode, +#endif +}; + +static int pci_conf1(void) +{ + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&cmd640_lock, flags); + outb(0x01, 0xCFB); + tmp = inl(0xCF8); + outl(0x80000000, 0xCF8); + if (inl(0xCF8) == 0x80000000) { + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&cmd640_lock, flags); + return 1; + } + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&cmd640_lock, flags); + return 0; +} + +static int pci_conf2(void) +{ + unsigned long flags; + + spin_lock_irqsave(&cmd640_lock, flags); + outb(0x00, 0xCFB); + outb(0x00, 0xCF8); + outb(0x00, 0xCFA); + if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) { + spin_unlock_irqrestore(&cmd640_lock, flags); + return 1; + } + spin_unlock_irqrestore(&cmd640_lock, flags); + return 0; +} + +static const struct ide_port_info cmd640_port_info __initdata = { + .chipset = ide_cmd640, + .host_flags = IDE_HFLAG_SERIALIZE | + IDE_HFLAG_NO_DMA | + IDE_HFLAG_ABUSE_PREFETCH | + IDE_HFLAG_ABUSE_FAST_DEVSEL, + .port_ops = &cmd640_port_ops, + .pio_mask = ATA_PIO5, +}; + +static int cmd640x_init_one(unsigned long base, unsigned long ctl) +{ + if (!request_region(base, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, base, base + 7); + return -EBUSY; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(base, 8); + return -EBUSY; + } + + return 0; +} + +/* + * Probe for a cmd640 chipset, and initialize it if found. + */ +static int __init cmd640x_init(void) +{ + int second_port_cmd640 = 0, rc; + const char *bus_type, *port2; + u8 b, cfr; + hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; + + if (cmd640_vlb && probe_for_cmd640_vlb()) { + bus_type = "VLB"; + } else { + cmd640_vlb = 0; + /* Find out what kind of PCI probing is supported otherwise + Justin Gibbs will sulk.. */ + if (pci_conf1() && probe_for_cmd640_pci1()) + bus_type = "PCI (type1)"; + else if (pci_conf2() && probe_for_cmd640_pci2()) + bus_type = "PCI (type2)"; + else + return 0; + } + /* + * Undocumented magic (there is no 0x5b reg in specs) + */ + put_cmd640_reg(0x5b, 0xbd); + if (get_cmd640_reg(0x5b) != 0xbd) { + printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n"); + return 0; + } + put_cmd640_reg(0x5b, 0); + +#ifdef CMD640_DUMP_REGS + cmd640_dump_regs(); +#endif + + /* + * Documented magic begins here + */ + cfr = get_cmd640_reg(CFR); + cmd640_chip_version = cfr & CFR_DEVREV; + if (cmd640_chip_version == 0) { + printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version); + return 0; + } + + rc = cmd640x_init_one(0x1f0, 0x3f6); + if (rc) + return rc; + + rc = cmd640x_init_one(0x170, 0x376); + if (rc) { + release_region(0x3f6, 1); + release_region(0x1f0, 8); + return rc; + } + + memset(&hw, 0, sizeof(hw)); + + ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); + hw[0].irq = 14; + hw[0].chipset = ide_cmd640; + + ide_std_init_ports(&hw[1], 0x170, 0x376); + hw[1].irq = 15; + hw[1].chipset = ide_cmd640; + + printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" + "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); + + /* + * Initialize data for primary port + */ + hws[0] = &hw[0]; + + /* + * Ensure compatibility by always using the slowest timings + * for access to the drive's command register block, + * and reset the prefetch burstsize to default (512 bytes). + * + * Maybe we need a way to NOT do these on *some* systems? + */ + put_cmd640_reg(CMDTIM, 0); + put_cmd640_reg(BRST, 0x40); + + b = get_cmd640_reg(CNTRL); + + /* + * Try to enable the secondary interface, if not already enabled + */ + if (secondary_port_responding()) { + if ((b & CNTRL_ENA_2ND)) { + second_port_cmd640 = 1; + port2 = "okay"; + } else if (cmd640_vlb) { + second_port_cmd640 = 1; + port2 = "alive"; + } else + port2 = "not cmd640"; + } else { + put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ + if (secondary_port_responding()) { + second_port_cmd640 = 1; + port2 = "enabled"; + } else { + put_cmd640_reg(CNTRL, b); /* restore original setting */ + port2 = "not responding"; + } + } + + /* + * Initialize data for secondary cmd640 port, if enabled + */ + if (second_port_cmd640) + hws[1] = &hw[1]; + + printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n", + second_port_cmd640 ? "" : "not ", port2); + +#ifdef CMD640_DUMP_REGS + cmd640_dump_regs(); +#endif + + return ide_host_add(&cmd640_port_info, hws, NULL); +} + +module_param_named(probe_vlb, cmd640_vlb, bool, 0); +MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset"); + +module_init(cmd640x_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c new file mode 100644 index 0000000..935385c --- /dev/null +++ b/drivers/ide/cmd64x.c @@ -0,0 +1,532 @@ +/* + * 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 + * Copyright (C) 2007 MontaVista Software, Inc. + */ + +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "cmd64x" + +#define CMD_DEBUG 0 + +#if CMD_DEBUG +#define cmdprintk(x...) printk(x) +#else +#define cmdprintk(x...) +#endif + +/* + * CMD64x specific registers definition. + */ +#define CFR 0x50 +#define CFR_INTR_CH0 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 u8 quantize_timing(int timing, int quant) +{ + return (timing + quant - 1) / quant; +} + +/* + * This routine calculates active/recovery counts and then writes them into + * the chipset registers. + */ +static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33); + u8 cycle_count, active_count, recovery_count, drwtim; + static const u8 recovery_values[] = + {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; + static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3}; + + cmdprintk("program_cycle_times parameters: total=%d, active=%d\n", + cycle_time, active_time); + + cycle_count = quantize_timing( cycle_time, clock_time); + active_count = quantize_timing(active_time, clock_time); + recovery_count = cycle_count - active_count; + + /* + * In case we've got too long recovery phase, try to lengthen + * the active phase + */ + if (recovery_count > 16) { + active_count += recovery_count - 16; + recovery_count = 16; + } + if (active_count > 16) /* shouldn't actually happen... */ + active_count = 16; + + cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n", + cycle_count, active_count, recovery_count); + + /* + * Convert values to internal chipset representation + */ + recovery_count = recovery_values[recovery_count]; + active_count &= 0x0f; + + /* Program the active/recovery counts into the DRWTIM register */ + drwtim = (active_count << 4) | recovery_count; + (void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim); + cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]); +} + +/* + * This routine writes into the chipset registers + * PIO setup/active/recovery timings. + */ +static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); + unsigned int cycle_time; + u8 setup_count, arttim = 0; + + static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; + static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; + + cycle_time = ide_pio_cycle_time(drive, pio); + + program_cycle_times(drive, cycle_time, t->active); + + setup_count = quantize_timing(t->setup, + 1000 / (ide_pci_clk ? ide_pci_clk : 33)); + + /* + * 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 *drives = hwif->drives; + + drive->drive_data = setup_count; + setup_count = max(drives[0].drive_data, drives[1].drive_data); + } + + if (setup_count > 5) /* shouldn't actually happen... */ + setup_count = 5; + cmdprintk("Final address setup count: %d\n", setup_count); + + /* + * 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[setup_count]; + (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim); + cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]); +} + +/* + * 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_drive_t *drive, const u8 pio) +{ + /* + * Filter out the prefetch control values + * to prevent PIO5 from being programmed + */ + if (pio == 8 || pio == 9) + return; + + cmd64x_tune_pio(drive, pio); +} + +static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 unit = drive->dn & 0x01; + u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0; + + if (speed >= XFER_SW_DMA_0) { + (void) pci_read_config_byte(dev, pciU, ®U); + 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: + program_cycle_times(drive, 120, 70); + break; + case XFER_MW_DMA_1: + program_cycle_times(drive, 150, 80); + break; + case XFER_MW_DMA_0: + program_cycle_times(drive, 480, 215); + break; + } + + if (speed >= XFER_SW_DMA_0) + (void) pci_write_config_byte(dev, pciU, regU); +} + +static int cmd648_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long base = hwif->dma_base - (hwif->channel * 8); + int err = ide_dma_end(drive); + 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); + + return err; +} + +static int cmd64x_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + 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; + int err = ide_dma_end(drive); + + (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); + + return err; +} + +static int cmd648_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long base = hwif->dma_base - (hwif->channel * 8); + u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 : + MRDMODE_INTR_CH0; + u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + u8 mrdmode = inb(base + 1); + +#ifdef DEBUG + printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n", + drive->name, dma_stat, mrdmode, irq_mask); +#endif + if (!(mrdmode & irq_mask)) + return 0; + + /* return 1 if INTR asserted */ + if (dma_stat & 4) + return 1; + + return 0; +} + +static int cmd64x_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + 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 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + u8 irq_stat = 0; + + (void) pci_read_config_byte(dev, irq_reg, &irq_stat); + +#ifdef DEBUG + printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n", + drive->name, dma_stat, irq_stat, irq_mask); +#endif + if (!(irq_stat & irq_mask)) + return 0; + + /* return 1 if INTR asserted */ + if (dma_stat & 4) + return 1; + + return 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 = HWIF(drive); + u8 dma_stat = 0, dma_cmd = 0; + + drive->waiting_for_dma = 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); + /* and free any DMA resources */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; +} + +static unsigned 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, + .cable_detect = cmd64x_cable_detect, +}; + +static const struct ide_dma_ops cmd64x_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = cmd64x_dma_end, + .dma_test_irq = cmd64x_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_dma_ops cmd646_rev1_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = cmd646_1_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_dma_ops cmd648_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = cmd648_dma_end, + .dma_test_irq = cmd648_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { + { /* 0: CMD643 */ + .name = DRV_NAME, + .init_chipset = init_chipset_cmd64x, + .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, + .port_ops = &cmd64x_port_ops, + .dma_ops = &cmd64x_dma_ops, + .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | + IDE_HFLAG_ABUSE_PREFETCH, + .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}}, + .chipset = ide_cmd646, + .port_ops = &cmd64x_port_ops, + .dma_ops = &cmd648_dma_ops, + .host_flags = IDE_HFLAG_ABUSE_PREFETCH, + .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 = &cmd64x_port_ops, + .dma_ops = &cmd648_dma_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 = &cmd64x_port_ops, + .dma_ops = &cmd648_dma_ops, + .host_flags = IDE_HFLAG_ABUSE_PREFETCH, + .pio_mask = ATA_PIO5, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, + } +}; + +static int __devinit 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; + if (dev->revision == 1) + d.dma_ops = &cmd646_rev1_dma_ops; + else + d.dma_ops = &cmd64x_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"); +MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c new file mode 100644 index 0000000..5efb467 --- /dev/null +++ b/drivers/ide/cs5520.c @@ -0,0 +1,165 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *pdev = to_pci_dev(hwif->dev); + int controller = drive->dn > 1 ? 1 : 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_drive_t *drive, const u8 speed) +{ + printk(KERN_ERR "cs55x0: bad ide timing.\n"); + + cs5520_set_pio_mode(drive, 0); +} + +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 __devinitdata = { + .name = DRV_NAME, + .enablebits = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } }, + .port_ops = &cs5520_port_ops, + .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_CS5520, + .pio_mask = ATA_PIO4, +}; + +/* + * 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 __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + const struct ide_port_info *d = &cyrix_chipset; + hw_regs_t hw[4], *hws[] = { NULL, NULL, 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 (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { + 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, 14, &hw[0], &hws[0]); + + return ide_host_add(d, hws, 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"); diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c new file mode 100644 index 0000000..53f079c --- /dev/null +++ b/drivers/ide/cs5530.c @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2000 Andre Hedrick + * Copyright (C) 2000 Mark Lord + * 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 +#include +#include +#include +#include +#include + +#include + +#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 + * @drive: drive + * @pio: PIO mode number + * + * 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_drive_t *drive, const u8 pio) +{ + unsigned long basereg = CS5530_BASEREG(drive->hwif); + unsigned int format = (inl(basereg + 4) >> 31) & 1; + + 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 = mate->id; + u8 mask = hwif->ultra_mask; + + if (mate == NULL) + goto out; + + 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_FIELD_VALID] & 2) && + (mateid[ATA_ID_MWDMA_MODES] & 7)) + mask = 0; + } +out: + return mask; +} + +static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) +{ + unsigned long basereg; + unsigned int reg, timings = 0; + + 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; + } + basereg = CS5530_BASEREG(drive->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 unsigned 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 __devinit 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 __devinitdata = { + .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 __devinit 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"); diff --git a/drivers/ide/cs5535.c b/drivers/ide/cs5535.c new file mode 100644 index 0000000..983d957 --- /dev/null +++ b/drivers/ide/cs5535.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2004-2005 Advanced Micro Devices, Inc. + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * + * History: + * 09/20/2005 - Jaya Kumar + * - 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 + * Alexander Kiausch + * Originally developed by AMD for 2.4/2.6 + * + * Development of this chipset driver was funded + * by the nice folks at National Semiconductor/AMD. + * + * 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. + * + * Documentation: + * CS5535 documentation available from AMD + */ + +#include +#include +#include + +#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 = ide_get_best_pio_mode(pair, 255, 4); + + 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 + * @drive: drive + * @speed: DMA mode + * + * Programs the chipset for DMA mode. + */ + +static void cs5535_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + cs5535_set_speed(drive, speed); +} + +/** + * cs5535_set_pio_mode - set host controller for PIO mode + * @drive: drive + * @pio: PIO mode number + * + * A callback from the upper layers for PIO-only tuning. + */ + +static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + cs5535_set_speed(drive, XFER_PIO_0 + pio); +} + +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 __devinitdata = { + .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 __devinit 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 }, + { 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"); diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c new file mode 100644 index 0000000..5297f07 --- /dev/null +++ b/drivers/ide/cy82c693.c @@ -0,0 +1,358 @@ +/* + * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer + * Copyright (C) 1998-2002 Andre Hedrick , Integrator + * + * CYPRESS CY82C693 chipset IDE controller + * + * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. + * Writing the driver was quite simple, since most of the job is + * done by the generic pci-ide support. + * The hard part was finding the CY82C693's datasheet on Cypress's + * web page :-(. But Altavista solved this problem :-). + * + * + * Notes: + * - I recently got a 16.8G IBM DTTA, so I was able to test it with + * a large and fast disk - the results look great, so I'd say the + * driver is working fine :-) + * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA + * - this is my first linux driver, so there's probably a lot of room + * for optimizations and bug fixing, so feel free to do it. + * - if using PIO mode it's a good idea to set the PIO mode and + * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda + * - I had some problems with my IBM DHEA with PIO modes < 2 + * (lost interrupts) ????? + * - first tests with DMA look okay, they seem to work, but there is a + * problem with sound - the BusMaster IDE TimeOut should fixed this + * + * Ancient History: + * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 + * ASK@1999-01-23: v0.33 made a few minor code clean ups + * removed DMA clock speed setting by default + * added boot message + * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut + * added support to set DMA Controller Clock Speed + * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes + * on some drives. + * ASK@1998-10-29: v0.3 added support to set DMA modes + * ASK@1998-10-28: v0.2 added support to set PIO modes + * ASK@1998-10-27: v0.1 first version - chipset detection + * + */ + +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "cy82c693" + +/* + * The following are used to debug the driver. + */ +#define CY82C693_DEBUG_INFO 0 + +/* + * 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 + +/* the min and max PCI bus speed in MHz - from datasheet */ +#define CY82C963_MIN_BUS_SPEED 25 +#define CY82C963_MAX_BUS_SPEED 33 + +/* the struct for the PIO mode timings */ +typedef struct pio_clocks_s { + u8 address_time; /* Address setup (clocks) */ + u8 time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */ + u8 time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */ + u8 time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */ +} pio_clocks_t; + +/* + * calc clocks using bus_speed + * returns (rounded up) time in bus clocks for time in ns + */ +static int calc_clk(int time, int bus_speed) +{ + int clocks; + + clocks = (time*bus_speed+999)/1000 - 1; + + if (clocks < 0) + clocks = 0; + + if (clocks > 0x0F) + clocks = 0x0F; + + return clocks; +} + +/* + * compute the values for the clock registers for PIO + * mode and pci_clk [MHz] speed + * + * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used + * for mode 3 and 4 drives 8 and 16-bit timings are the same + * + */ +static void compute_clocks(u8 pio, pio_clocks_t *p_pclk) +{ + struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); + int clk1, clk2; + int bus_speed = ide_pci_clk ? ide_pci_clk : 33; + + /* we don't check against CY82C693's min and max speed, + * so you can play with the idebus=xx parameter + */ + + /* let's calc the address setup time clocks */ + p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed); + + /* let's calc the active and recovery time clocks */ + clk1 = calc_clk(t->active, bus_speed); + + /* calc recovery timing */ + clk2 = t->cycle - t->active - t->setup; + + clk2 = calc_clk(clk2, bus_speed); + + clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */ + + /* note: we use the same values for 16bit IOR and IOW + * those are all the same, since I don't have other + * timings than those from ide-lib.c + */ + + p_pclk->time_16r = (u8)clk1; + p_pclk->time_16w = (u8)clk1; + + /* what are good values for 8bit ?? */ + p_pclk->time_8 = (u8)clk1; +} + +/* + * set DMA mode a specific channel for CY82C693 + */ + +static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode) +{ + ide_hwif_t *hwif = drive->hwif; + 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); + +#if CY82C693_DEBUG_INFO + printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", + drive->name, hwif->channel, drive->dn & 1, mode & 3, single); +#endif /* CY82C693_DEBUG_INFO */ + + /* + * note: below we set the value for Bus Master IDE TimeOut Register + * I'm not absolutly sure what this does, but it solved my problem + * with IDE DMA and sound, so I now can play sound and work with + * my IDE driver at the same time :-) + * + * If you know the correct (best) value for this register please + * let me know - ASK + */ + + data = BUSMASTER_TIMEOUT; + outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); + outb(data, CY82_DATA_PORT); + +#if CY82C693_DEBUG_INFO + printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", + drive->name, data); +#endif /* CY82C693_DEBUG_INFO */ +} + +static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + pio_clocks_t pclk; + unsigned int addrCtrl; + + /* select primary or secondary channel */ + if (hwif->index > 0) { /* 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; + } + } + + /* let's calc the values for this PIO mode */ + compute_clocks(pio, &pclk); + + /* 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 |= (unsigned int)pclk.address_time; + 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, pclk.time_16r); + pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w); + pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8); + + addrCtrl &= 0xF; + } else { + /* + * set slave drive + * address setup control register + * is 32 bit !!! + */ + pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); + + addrCtrl &= (~0xF0); + addrCtrl |= ((unsigned int)pclk.address_time<<4); + pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); + + /* now let's set the remaining registers */ + pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r); + pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w); + pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8); + + addrCtrl >>= 4; + addrCtrl &= 0xF; + } + +#if CY82C693_DEBUG_INFO + printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to " + "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", + drive->name, hwif->channel, drive->dn & 1, + addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); +#endif /* CY82C693_DEBUG_INFO */ +} + +static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) +{ + static ide_hwif_t *primary; + struct pci_dev *dev = to_pci_dev(hwif->dev); + + if (PCI_FUNC(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 __devinitdata = { + .name = DRV_NAME, + .init_iops = init_iops_cy82c693, + .port_ops = &cy82c693_port_ops, + .chipset = ide_cy82c693, + .host_flags = IDE_HFLAG_SINGLE, + .pio_mask = ATA_PIO4, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, +}; + +static int __devinit 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 __devexit cy82c693_remove(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; + + ide_pci_remove(dev); + pci_dev_put(dev2); +} + +static const struct pci_device_id cy82c693_pci_tbl[] = { + { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl); + +static struct pci_driver cy82c693_pci_driver = { + .name = "Cypress_IDE", + .id_table = cy82c693_pci_tbl, + .probe = cy82c693_init_one, + .remove = __devexit_p(cy82c693_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init cy82c693_ide_init(void) +{ + return ide_pci_register_driver(&cy82c693_pci_driver); +} + +static void __exit cy82c693_ide_exit(void) +{ + pci_unregister_driver(&cy82c693_pci_driver); +} + +module_init(cy82c693_ide_init); +module_exit(cy82c693_ide_exit); + +MODULE_AUTHOR("Andreas Krebs, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c new file mode 100644 index 0000000..8f1b2d9 --- /dev/null +++ b/drivers/ide/delkin_cb.c @@ -0,0 +1,192 @@ +/* + * 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 +#include +#include +#include +#include + +#include + +/* + * 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 unsigned 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, + .init_chipset = delkin_cb_init_chipset, +}; + +static int __devinit +delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + struct ide_host *host; + unsigned long base; + int rc; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + + 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; + hw.chipset = ide_pci; /* this enables IRQ sharing */ + + rc = ide_host_add(&delkin_cb_port_info, hws, &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[] __devinitdata = { + { 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, +}; + +static int __init delkin_cb_init(void) +{ + return pci_register_driver(&delkin_cb_pci_driver); +} + +static void __exit delkin_cb_exit(void) +{ + pci_unregister_driver(&delkin_cb_pci_driver); +} + +module_init(delkin_cb_init); +module_exit(delkin_cb_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c new file mode 100644 index 0000000..689b2e4 --- /dev/null +++ b/drivers/ide/dtc2278.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 1996 Linus Torvalds & author (see below) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "dtc2278" + +/* + * Changing this #undef to #define may solve start up problems in some systems. + */ +#undef ALWAYS_SET_DTC2278_PIO_MODE + +/* + * From: andy@cercle.cts.com (Dyan Wile) + * + * Below is a patch for DTC-2278 - alike software-programmable controllers + * The code enables the secondary IDE controller and the PIO4 (3?) timings on + * the primary (EIDE). You may probably have to enable the 32-bit support to + * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 + * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my + * filesystem corrupted with -u1, but under heavy disk load only :-) + * + * This card is now forced to use the "serialize" feature, + * and irq-unmasking is disallowed. If io_32bit is enabled, + * it must be done for BOTH drives on each interface. + * + * This code was written for the DTC2278E, but might work with any of these: + * + * DTC2278S has only a single IDE interface. + * DTC2278D has two IDE interfaces and is otherwise identical to the S version. + * DTC2278E also has serial ports and a printer port + * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford + * + * There may be a fourth controller type. The S and D versions use the + * Winbond chip, and I think the E version does also. + * + */ + +static void sub22 (char b, char c) +{ + int i; + + for(i = 0; i < 3; ++i) { + inb(0x3f6); + outb_p(b,0xb0); + inb(0x3f6); + outb_p(c,0xb4); + inb(0x3f6); + if(inb(0xb4) == c) { + outb_p(7,0xb0); + inb(0x3f6); + return; /* success */ + } + } +} + +static DEFINE_SPINLOCK(dtc2278_lock); + +static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + unsigned long flags; + + if (pio >= 3) { + spin_lock_irqsave(&dtc2278_lock, flags); + /* + * This enables PIO mode4 (3?) on the first interface + */ + sub22(1,0xc3); + sub22(0,0xa0); + spin_unlock_irqrestore(&dtc2278_lock, flags); + } else { + /* we don't know how to set it back again.. */ + /* Actually we do - there is a data sheet available for the + Winbond but does anyone actually care */ + } +} + +static const struct ide_port_ops dtc2278_port_ops = { + .set_pio_mode = dtc2278_set_pio_mode, +}; + +static const struct ide_port_info dtc2278_port_info __initdata = { + .name = DRV_NAME, + .chipset = ide_dtc2278, + .port_ops = &dtc2278_port_ops, + .host_flags = IDE_HFLAG_SERIALIZE | + IDE_HFLAG_NO_UNMASK_IRQS | + IDE_HFLAG_IO_32BIT | + /* disallow ->io_32bit changes */ + IDE_HFLAG_NO_IO_32BIT | + IDE_HFLAG_NO_DMA, + .pio_mask = ATA_PIO4, +}; + +static int __init dtc2278_probe(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); + + return ide_legacy_device_add(&dtc2278_port_info, 0); +} + +static int probe_dtc2278; + +module_param_named(probe, probe_dtc2278, bool, 0); +MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); + +static int __init dtc2278_init(void) +{ + if (probe_dtc2278 == 0) + return -ENODEV; + + if (dtc2278_probe()) { + printk(KERN_ERR "dtc2278: ide interfaces already in use!\n"); + return -EBUSY; + } + return 0; +} + +module_init(dtc2278_init); + +MODULE_AUTHOR("See Local File"); +MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/falconide.c b/drivers/ide/falconide.c new file mode 100644 index 0000000..39d500d --- /dev/null +++ b/drivers/ide/falconide.c @@ -0,0 +1,153 @@ +/* + * Atari Falcon IDE Driver + * + * Created 12 Jul 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DRV_NAME "falconide" + + /* + * Base of the IDE interface + */ + +#define ATA_HD_BASE 0xfff00000 + + /* + * Offsets from the above base + */ + +#define ATA_HD_CONTROL 0x39 + + /* + * falconide_intr_lock is used to obtain access to the IDE interrupt, + * which is shared between several drivers. + */ + +int falconide_intr_lock; +EXPORT_SYMBOL(falconide_intr_lock); + +static void falconide_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) + return insw(data_addr, buf, (len + 1) / 2); + + insw_swapw(data_addr, buf, (len + 1) / 2); +} + +static void falconide_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) + return outsw(data_addr, buf, (len + 1) / 2); + + outsw_swapw(data_addr, buf, (len + 1) / 2); +} + +/* Atari has a byte-swapped IDE interface */ +static const struct ide_tp_ops falconide_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + .read_sff_dma_status = ide_read_sff_dma_status, + + .set_irq = ide_set_irq, + + .tf_load = ide_tf_load, + .tf_read = ide_tf_read, + + .input_data = falconide_input_data, + .output_data = falconide_output_data, +}; + +static const struct ide_port_info falconide_port_info = { + .tp_ops = &falconide_tp_ops, + .host_flags = IDE_HFLAG_NO_DMA, +}; + +static void __init falconide_setup_ports(hw_regs_t *hw) +{ + int i; + + memset(hw, 0, sizeof(*hw)); + + hw->io_ports.data_addr = ATA_HD_BASE; + + for (i = 1; i < 8; i++) + hw->io_ports_array[i] = ATA_HD_BASE + 1 + i * 4; + + hw->io_ports.ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL; + + hw->irq = IRQ_MFP_IDE; + hw->ack_intr = NULL; + + hw->chipset = ide_generic; +} + + /* + * Probe for a Falcon IDE interface + */ + +static int __init falconide_init(void) +{ + struct ide_host *host; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + int rc; + + if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE)) + return -ENODEV; + + printk(KERN_INFO "ide: Falcon IDE controller\n"); + + if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) { + printk(KERN_ERR "%s: resources busy\n", DRV_NAME); + return -EBUSY; + } + + falconide_setup_ports(&hw); + + host = ide_host_alloc(&falconide_port_info, hws); + if (host == NULL) { + rc = -ENOMEM; + goto err; + } + + ide_get_lock(NULL, NULL); + rc = ide_host_register(host, &falconide_port_info, hws); + ide_release_lock(); + + if (rc) + goto err_free; + + return 0; +err_free: + ide_host_free(host); +err: + release_mem_region(ATA_HD_BASE, 0x40); + return rc; +} + +module_init(falconide_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c new file mode 100644 index 0000000..6915068 --- /dev/null +++ b/drivers/ide/gayle.c @@ -0,0 +1,190 @@ +/* + * Amiga Gayle IDE Driver + * + * Created 9 Jul 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + + /* + * Bases of the IDE interfaces + */ + +#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ +#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */ + +#define GAYLE_IDEREG_SIZE 0x2000 + + /* + * Offsets from one of the above bases + */ + +#define GAYLE_CONTROL 0x101a + + /* + * These are at different offsets from the base + */ + +#define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */ +#define GAYLE_IRQ_1200 0xda9000 /* interrupt */ + + + /* + * Offset of the secondary port for IDE doublers + * Note that GAYLE_CONTROL is NOT available then! + */ + +#define GAYLE_NEXT_PORT 0x1000 + +#ifndef CONFIG_BLK_DEV_IDEDOUBLER +#define GAYLE_NUM_HWIFS 1 +#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS +#define GAYLE_HAS_CONTROL_REG 1 +#else /* CONFIG_BLK_DEV_IDEDOUBLER */ +#define GAYLE_NUM_HWIFS 2 +#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \ + GAYLE_NUM_HWIFS-1) +#define GAYLE_HAS_CONTROL_REG (!ide_doubler) + +static int ide_doubler; +module_param_named(doubler, ide_doubler, bool, 0); +MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); +#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ + + + /* + * Check and acknowledge the interrupt status + */ + +static int gayle_ack_intr_a4000(ide_hwif_t *hwif) +{ + unsigned char ch; + + ch = z_readb(hwif->io_ports.irq_addr); + if (!(ch & GAYLE_IRQ_IDE)) + return 0; + return 1; +} + +static int gayle_ack_intr_a1200(ide_hwif_t *hwif) +{ + unsigned char ch; + + ch = z_readb(hwif->io_ports.irq_addr); + if (!(ch & GAYLE_IRQ_IDE)) + return 0; + (void)z_readb(hwif->io_ports.status_addr); + z_writeb(0x7c, hwif->io_ports.irq_addr); + return 1; +} + +static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, + unsigned long ctl, unsigned long irq_port, + ide_ack_intr_t *ack_intr) +{ + 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; + hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; +} + + /* + * Probe for a Gayle IDE interface (and optionally for an IDE doubler) + */ + +static int __init gayle_init(void) +{ + unsigned long phys_base, res_start, res_n; + unsigned long base, ctrlport, irqport; + ide_ack_intr_t *ack_intr; + int a4000, i, rc; + hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; + + if (!MACH_IS_AMIGA) + return -ENODEV; + + if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) + goto found; + +#ifdef CONFIG_ZORRO + if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE, + NULL)) + goto found; +#endif + return -ENODEV; + +found: + printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", + a4000 ? 4000 : 1200, +#ifdef CONFIG_BLK_DEV_IDEDOUBLER + ide_doubler ? ", IDE doubler" : +#endif + ""); + + if (a4000) { + phys_base = GAYLE_BASE_4000; + irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000); + ack_intr = gayle_ack_intr_a4000; + } else { + phys_base = GAYLE_BASE_1200; + irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200); + ack_intr = gayle_ack_intr_a1200; + } +/* + * FIXME: we now have selectable modes between mmio v/s iomio + */ + + res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); + res_n = GAYLE_IDEREG_SIZE; + + if (!request_mem_region(res_start, res_n, "IDE")) + return -EBUSY; + + for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { + base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT); + ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; + + gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr); + + hws[i] = &hw[i]; + } + + rc = ide_host_add(NULL, hws, NULL); + if (rc) + release_mem_region(res_start, res_n); + + return rc; +} + +module_init(gayle_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/generic.c b/drivers/ide/generic.c new file mode 100644 index 0000000..474f96a --- /dev/null +++ b/drivers/ide/generic.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2001-2002 Andre Hedrick + * Portions (C) Copyright 2002 Red Hat Inc + * + * 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 +#include +#include +#include +#include +#include + +#define DRV_NAME "ide_pci_generic" + +static int ide_generic_all; /* Set to claim all devices */ + +module_param_named(all_generic_ide, ide_generic_all, bool, 0444); +MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); + +#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS) + +#define DECLARE_GENERIC_PCI_DEV(extra_flags) \ + { \ + .name = DRV_NAME, \ + .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \ + extra_flags, \ + .swdma_mask = ATA_SWDMA2, \ + .mwdma_mask = ATA_MWDMA2, \ + .udma_mask = ATA_UDMA6, \ + } + +static const struct ide_port_info generic_chipsets[] __devinitdata = { + /* 0: Unknown */ + DECLARE_GENERIC_PCI_DEV(0), + + { /* 1: NS87410 */ + .name = DRV_NAME, + .enablebits = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} }, + .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + }, + + /* 2: SAMURAI / HT6565 / HINT_IDE */ + DECLARE_GENERIC_PCI_DEV(0), + /* 3: UM8673F / UM8886A / UM8886BF */ + DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC), + /* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */ + DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA), + + { /* 5: VIA8237SATA */ + .name = DRV_NAME, + .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | + IDE_HFLAG_OFF_BOARD, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + }, + + { /* 6: Revolution */ + .name = DRV_NAME, + .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | + IDE_HFLAG_TRUST_BIOS_FOR_DMA | + IDE_HFLAG_OFF_BOARD, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + } +}; + +/** + * generic_init_one - called when a PIIX is found + * @dev: the generic 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 __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + const struct ide_port_info *d = &generic_chipsets[id->driver_data]; + int ret = -ENODEV; + + /* Don't use the generic entry unless instructed to do so */ + if (id->driver_data == 0 && ide_generic_all == 0) + goto out; + + switch (dev->vendor) { + case PCI_VENDOR_ID_UMC: + if (dev->device == PCI_DEVICE_ID_UMC_UM8886A && + !(PCI_FUNC(dev->devfn) & 1)) + goto out; /* UM8886A/BF pair */ + break; + case PCI_VENDOR_ID_OPTI: + if (dev->device == PCI_DEVICE_ID_OPTI_82C558 && + !(PCI_FUNC(dev->devfn) & 1)) + goto out; + break; + case PCI_VENDOR_ID_JMICRON: + if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && + PCI_FUNC(dev->devfn) != 1) + goto out; + break; + case PCI_VENDOR_ID_NS: + if (dev->device == PCI_DEVICE_ID_NS_87410 && + (dev->class >> 8) != PCI_CLASS_STORAGE_IDE) + goto out; + break; + } + + if (dev->vendor != PCI_VENDOR_ID_JMICRON) { + u16 command; + pci_read_config_word(dev, PCI_COMMAND, &command); + if (!(command & PCI_COMMAND_IO)) { + printk(KERN_INFO "%s %s: skipping disabled " + "controller\n", d->name, pci_name(dev)); + goto out; + } + } + ret = ide_pci_init_one(dev, d, NULL); +out: + return ret; +} + +static const struct pci_device_id generic_pci_tbl[] = { + { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), 1 }, + { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), 2 }, + { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 2 }, + { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 3 }, + { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 3 }, + { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 3 }, + { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 2 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 4 }, + { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 4 }, +#ifdef CONFIG_BLK_DEV_IDE_SATA + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 5 }, +#endif + { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 4 }, + { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 4 }, + { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 4 }, + { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 6 }, + /* + * Must come last. If you add entries adjust + * this table and generic_chipsets[] appropriately. + */ + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, generic_pci_tbl); + +static struct pci_driver generic_pci_driver = { + .name = "PCI_IDE", + .id_table = generic_pci_tbl, + .probe = generic_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init generic_ide_init(void) +{ + return ide_pci_register_driver(&generic_pci_driver); +} + +static void __exit generic_ide_exit(void) +{ + pci_unregister_driver(&generic_pci_driver); +} + +module_init(generic_ide_init); +module_exit(generic_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for generic PCI IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/h8300/Makefile b/drivers/ide/h8300/Makefile deleted file mode 100644 index 5eba16f..0000000 --- a/drivers/ide/h8300/Makefile +++ /dev/null @@ -1,2 +0,0 @@ - -obj-$(CONFIG_IDE_H8300) += ide-h8300.o diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c deleted file mode 100644 index e2cdd2e..0000000 --- a/drivers/ide/h8300/ide-h8300.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * H8/300 generic IDE interface - */ - -#include -#include - -#include -#include - -#define DRV_NAME "ide-h8300" - -#define bswap(d) \ -({ \ - u16 r; \ - __asm__("mov.b %w1,r1h\n\t" \ - "mov.b %x1,r1l\n\t" \ - "mov.w r1,%0" \ - :"=r"(r) \ - :"r"(d) \ - :"er1"); \ - (r); \ -}) - -static void mm_outw(u16 d, unsigned long a) -{ - __asm__("mov.b %w0,r2h\n\t" - "mov.b %x0,r2l\n\t" - "mov.w r2,@%1" - : - :"r"(d),"r"(a) - :"er2"); -} - -static u16 mm_inw(unsigned long a) -{ - register u16 r __asm__("er0"); - __asm__("mov.w @%1,r2\n\t" - "mov.b r2l,%x0\n\t" - "mov.b r2h,%w0" - :"=r"(r) - :"r"(a) - :"er2"); - return r; -} - -static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; - - if (task->tf_flags & IDE_TFLAG_FLAGGED) - HIHI = 0xFF; - - if (task->tf_flags & IDE_TFLAG_OUT_DATA) - mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) - outb(tf->hob_feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) - outb(tf->hob_nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) - outb(tf->hob_lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) - outb(tf->hob_lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) - outb(tf->hob_lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) - outb(tf->feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_NSECT) - outb(tf->nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAL) - outb(tf->lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAM) - outb(tf->lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAH) - outb(tf->lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - outb((tf->device & HIHI) | drive->select, - io_ports->device_addr); -} - -static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - - if (task->tf_flags & IDE_TFLAG_IN_DATA) { - u16 data = mm_inw(io_ports->data_addr); - - tf->data = data & 0xff; - tf->hob_data = (data >> 8) & 0xff; - } - - /* be sure we're looking at the low order bits */ - outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_FEATURE) - tf->feature = inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_NSECT) - tf->nsect = inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAL) - tf->lbal = inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAM) - tf->lbam = inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAH) - tf->lbah = inb(io_ports->lbah_addr); - if (task->tf_flags & IDE_TFLAG_IN_DEVICE) - tf->device = inb(io_ports->device_addr); - - if (task->tf_flags & IDE_TFLAG_LBA48) { - outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) - tf->hob_feature = inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) - tf->hob_nsect = inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) - tf->hob_lbal = inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) - tf->hob_lbam = inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) - tf->hob_lbah = inb(io_ports->lbah_addr); - } -} - -static void mm_outsw(unsigned long addr, void *buf, u32 len) -{ - unsigned short *bp = (unsigned short *)buf; - for (; len > 0; len--, bp++) - *(volatile u16 *)addr = bswap(*bp); -} - -static void mm_insw(unsigned long addr, void *buf, u32 len) -{ - unsigned short *bp = (unsigned short *)buf; - for (; len > 0; len--, bp++) - *bp = bswap(*(volatile u16 *)addr); -} - -static void h8300_input_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); -} - -static void h8300_output_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); -} - -static const struct ide_tp_ops h8300_tp_ops = { - .exec_command = ide_exec_command, - .read_status = ide_read_status, - .read_altstatus = ide_read_altstatus, - .read_sff_dma_status = ide_read_sff_dma_status, - - .set_irq = ide_set_irq, - - .tf_load = h8300_tf_load, - .tf_read = h8300_tf_read, - - .input_data = h8300_input_data, - .output_data = h8300_output_data, -}; - -#define H8300_IDE_GAP (2) - -static inline void hw_setup(hw_regs_t *hw) -{ - int i; - - memset(hw, 0, sizeof(hw_regs_t)); - for (i = 0; i <= 7; i++) - hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; - hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT; - hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; - hw->chipset = ide_generic; -} - -static const struct ide_port_info h8300_port_info = { - .tp_ops = &h8300_tp_ops, - .host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA, -}; - -static int __init h8300_ide_init(void) -{ - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n"); - - if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300")) - goto out_busy; - if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) { - release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8); - goto out_busy; - } - - hw_setup(&hw); - - return ide_host_add(&h8300_port_info, hws, NULL); - -out_busy: - printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); - - return -EBUSY; -} - -module_init(h8300_ide_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c new file mode 100644 index 0000000..a7909e9 --- /dev/null +++ b/drivers/ide/hpt366.c @@ -0,0 +1,1643 @@ +/* + * Copyright (C) 1999-2003 Andre Hedrick + * Portions Copyright (C) 2001 Sun Microsystems, Inc. + * Portions Copyright (C) 2003 Red Hat Inc + * Portions Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * Portions Copyright (C) 2005-2008 MontaVista Software, Inc. + * + * Thanks to HighPoint Technologies for their assistance, and hardware. + * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his + * donation of an ABit BP6 mainboard, processor, and memory acellerated + * development and support. + * + * + * HighPoint has its own drivers (open source except for the RAID part) + * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/. + * This may be useful to anyone wanting to work on this driver, however do not + * trust them too much since the code tends to become less and less meaningful + * as the time passes... :-/ + * + * Note that final HPT370 support was done by force extraction of GPL. + * + * - add function for getting/setting power status of drive + * - the HPT370's state machine can get confused. reset it before each dma + * xfer to prevent that from happening. + * - reset state engine whenever we get an error. + * - check for busmaster state at end of dma. + * - use new highpoint timings. + * - detect bus speed using highpoint register. + * - use pll if we don't have a clock table. added a 66MHz table that's + * just 2x the 33MHz table. + * - removed turnaround. NOTE: we never want to switch between pll and + * pci clocks as the chip can glitch in those cases. the highpoint + * approved workaround slows everything down too much to be useful. in + * addition, we would have to serialize access to each chip. + * Adrian Sun + * + * add drive timings for 66MHz PCI bus, + * fix ATA Cable signal detection, fix incorrect /proc info + * add /proc display for per-drive PIO/DMA/UDMA mode and + * per-channel ATA-33/66 Cable detect. + * Duncan Laurie + * + * fixup /proc output for multiple controllers + * Tim Hockin + * + * On hpt366: + * Reset the hpt366 on error, reset on dma + * Fix disabling Fast Interrupt hpt366. + * Mike Waychison + * + * Added support for 372N clocking and clock switching. The 372N needs + * different clocks on read/write. This requires overloading rw_disk and + * other deeply crazy things. Thanks to for + * keeping me sane. + * Alan Cox + * + * - fix the clock turnaround code: it was writing to the wrong ports when + * called for the secondary channel, caching the current clock mode per- + * channel caused the cached register value to get out of sync with the + * actual one, the channels weren't serialized, the turnaround shouldn't + * be done on 66 MHz PCI bus + * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used + * does not allow for this speed anyway + * - avoid touching disabled channels (e.g. HPT371/N are single channel chips, + * their primary channel is kind of virtual, it isn't tied to any pins) + * - fix/remove bad/unused timing tables and use one set of tables for the whole + * HPT37x chip family; save space by introducing the separate transfer mode + * table in which the mode lookup is done + * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives + * the wrong PCI frequency since DPLL has already been calibrated by BIOS; + * read it only from the function 0 of HPT374 chips + * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, + * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead + * - pass to init_chipset() handlers a copy of the IDE PCI device structure as + * they tamper with its fields + * - pass to the init_setup handlers a copy of the ide_pci_device_t structure + * since they may tamper with its fields + * - prefix the driver startup messages with the real chip name + * - claim the extra 240 bytes of I/O space for all chips + * - optimize the UltraDMA filtering and the drive list lookup code + * - use pci_get_slot() to get to the function 1 of HPT36x/374 + * - cache offset of the channel's misc. control registers (MCRs) being used + * throughout the driver + * - only touch the relevant MCR when detecting the cable type on HPT374's + * function 1 + * - rename all the register related variables consistently + * - move all the interrupt twiddling code from the speedproc handlers into + * init_hwif_hpt366(), also grouping all the DMA related code together there + * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and + * separate the UltraDMA and MWDMA masks there to avoid changing PIO timings + * when setting an UltraDMA mode + * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select + * the best possible one + * - clean up DMA timeout handling for HPT370 + * - switch to using the enumeration type to differ between the numerous chip + * variants, matching PCI device/revision ID with the chip type early, at the + * init_setup stage + * - extend the hpt_info structure to hold the DPLL and PCI clock frequencies, + * stop duplicating it for each channel by storing the pointer in the pci_dev + * structure: first, at the init_setup stage, point it to a static "template" + * with only the chip type and its specific base DPLL frequency, the highest + * UltraDMA mode, and the chip settings table pointer filled, then, at the + * init_chipset stage, allocate per-chip instance and fill it with the rest + * of the necessary information + * - get rid of the constant thresholds in the HPT37x PCI clock detection code, + * switch to calculating PCI clock frequency based on the chip's base DPLL + * frequency + * - switch to using the DPLL clock and enable UltraATA/133 mode by default on + * anything newer than HPT370/A (except HPT374 that is not capable of this + * mode according to the manual) + * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(), + * also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips; + * unify HPT36x/37x timing setup code and the speedproc handlers by joining + * the register setting lists into the table indexed by the clock selected + * - set the correct hwif->ultra_mask for each individual chip + * - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards + * Sergei Shtylyov, or + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DRV_NAME "hpt366" + +/* various tuning parameters */ +#define HPT_RESET_STATE_ENGINE +#undef HPT_DELAY_INTERRUPT +#define HPT_SERIALIZE_IO 0 + +static const char *quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + +static const char *bad_ata100_5[] = { + "IBM-DTLA-307075", + "IBM-DTLA-307060", + "IBM-DTLA-307045", + "IBM-DTLA-307030", + "IBM-DTLA-307020", + "IBM-DTLA-307015", + "IBM-DTLA-305040", + "IBM-DTLA-305030", + "IBM-DTLA-305020", + "IC35L010AVER07-0", + "IC35L020AVER07-0", + "IC35L030AVER07-0", + "IC35L040AVER07-0", + "IC35L060AVER07-0", + "WDC AC310200R", + NULL +}; + +static const char *bad_ata66_4[] = { + "IBM-DTLA-307075", + "IBM-DTLA-307060", + "IBM-DTLA-307045", + "IBM-DTLA-307030", + "IBM-DTLA-307020", + "IBM-DTLA-307015", + "IBM-DTLA-305040", + "IBM-DTLA-305030", + "IBM-DTLA-305020", + "IC35L010AVER07-0", + "IC35L020AVER07-0", + "IC35L030AVER07-0", + "IC35L040AVER07-0", + "IC35L060AVER07-0", + "WDC AC310200R", + "MAXTOR STM3320620A", + NULL +}; + +static const char *bad_ata66_3[] = { + "WDC AC310200R", + NULL +}; + +static const char *bad_ata33[] = { + "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", + "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", + "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", + "Maxtor 90510D4", + "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", + "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", + "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", + NULL +}; + +static u8 xfer_speeds[] = { + XFER_UDMA_6, + XFER_UDMA_5, + XFER_UDMA_4, + XFER_UDMA_3, + XFER_UDMA_2, + XFER_UDMA_1, + XFER_UDMA_0, + + XFER_MW_DMA_2, + XFER_MW_DMA_1, + XFER_MW_DMA_0, + + XFER_PIO_4, + XFER_PIO_3, + XFER_PIO_2, + XFER_PIO_1, + XFER_PIO_0 +}; + +/* Key for bus clock timings + * 36x 37x + * bits bits + * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA. + * cycles = value + 1 + * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA. + * cycles = value + 1 + * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file + * register access. + * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file + * register access. + * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer. + * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock. + * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and + * MW DMA xfer. + * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for + * task file register access. + * 28 28 UDMA enable. + * 29 29 DMA enable. + * 30 30 PIO MST enable. If set, the chip is in bus master mode during + * PIO xfer. + * 31 31 FIFO enable. + */ + +static u32 forty_base_hpt36x[] = { + /* XFER_UDMA_6 */ 0x900fd943, + /* XFER_UDMA_5 */ 0x900fd943, + /* XFER_UDMA_4 */ 0x900fd943, + /* XFER_UDMA_3 */ 0x900ad943, + /* XFER_UDMA_2 */ 0x900bd943, + /* XFER_UDMA_1 */ 0x9008d943, + /* XFER_UDMA_0 */ 0x9008d943, + + /* XFER_MW_DMA_2 */ 0xa008d943, + /* XFER_MW_DMA_1 */ 0xa010d955, + /* XFER_MW_DMA_0 */ 0xa010d9fc, + + /* XFER_PIO_4 */ 0xc008d963, + /* XFER_PIO_3 */ 0xc010d974, + /* XFER_PIO_2 */ 0xc010d997, + /* XFER_PIO_1 */ 0xc010d9c7, + /* XFER_PIO_0 */ 0xc018d9d9 +}; + +static u32 thirty_three_base_hpt36x[] = { + /* XFER_UDMA_6 */ 0x90c9a731, + /* XFER_UDMA_5 */ 0x90c9a731, + /* XFER_UDMA_4 */ 0x90c9a731, + /* XFER_UDMA_3 */ 0x90cfa731, + /* XFER_UDMA_2 */ 0x90caa731, + /* XFER_UDMA_1 */ 0x90cba731, + /* XFER_UDMA_0 */ 0x90c8a731, + + /* XFER_MW_DMA_2 */ 0xa0c8a731, + /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */ + /* XFER_MW_DMA_0 */ 0xa0c8a797, + + /* XFER_PIO_4 */ 0xc0c8a731, + /* XFER_PIO_3 */ 0xc0c8a742, + /* XFER_PIO_2 */ 0xc0d0a753, + /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */ + /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */ +}; + +static u32 twenty_five_base_hpt36x[] = { + /* XFER_UDMA_6 */ 0x90c98521, + /* XFER_UDMA_5 */ 0x90c98521, + /* XFER_UDMA_4 */ 0x90c98521, + /* XFER_UDMA_3 */ 0x90cf8521, + /* XFER_UDMA_2 */ 0x90cf8521, + /* XFER_UDMA_1 */ 0x90cb8521, + /* XFER_UDMA_0 */ 0x90cb8521, + + /* XFER_MW_DMA_2 */ 0xa0ca8521, + /* XFER_MW_DMA_1 */ 0xa0ca8532, + /* XFER_MW_DMA_0 */ 0xa0ca8575, + + /* XFER_PIO_4 */ 0xc0ca8521, + /* XFER_PIO_3 */ 0xc0ca8532, + /* XFER_PIO_2 */ 0xc0ca8542, + /* XFER_PIO_1 */ 0xc0d08572, + /* XFER_PIO_0 */ 0xc0d08585 +}; + +#if 0 +/* These are the timing tables from the HighPoint open source drivers... */ +static u32 thirty_three_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */ + /* XFER_UDMA_5 */ 0x12446231, + /* XFER_UDMA_4 */ 0x12446231, + /* XFER_UDMA_3 */ 0x126c6231, + /* XFER_UDMA_2 */ 0x12486231, + /* XFER_UDMA_1 */ 0x124c6233, + /* XFER_UDMA_0 */ 0x12506297, + + /* XFER_MW_DMA_2 */ 0x22406c31, + /* XFER_MW_DMA_1 */ 0x22406c33, + /* XFER_MW_DMA_0 */ 0x22406c97, + + /* XFER_PIO_4 */ 0x06414e31, + /* XFER_PIO_3 */ 0x06414e42, + /* XFER_PIO_2 */ 0x06414e53, + /* XFER_PIO_1 */ 0x06814e93, + /* XFER_PIO_0 */ 0x06814ea7 +}; + +static u32 fifty_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x12848242, + /* XFER_UDMA_5 */ 0x12848242, + /* XFER_UDMA_4 */ 0x12ac8242, + /* XFER_UDMA_3 */ 0x128c8242, + /* XFER_UDMA_2 */ 0x120c8242, + /* XFER_UDMA_1 */ 0x12148254, + /* XFER_UDMA_0 */ 0x121882ea, + + /* XFER_MW_DMA_2 */ 0x22808242, + /* XFER_MW_DMA_1 */ 0x22808254, + /* XFER_MW_DMA_0 */ 0x228082ea, + + /* XFER_PIO_4 */ 0x0a81f442, + /* XFER_PIO_3 */ 0x0a81f443, + /* XFER_PIO_2 */ 0x0a81f454, + /* XFER_PIO_1 */ 0x0ac1f465, + /* XFER_PIO_0 */ 0x0ac1f48a +}; + +static u32 sixty_six_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x1c869c62, + /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */ + /* XFER_UDMA_4 */ 0x1c8a9c62, + /* XFER_UDMA_3 */ 0x1c8e9c62, + /* XFER_UDMA_2 */ 0x1c929c62, + /* XFER_UDMA_1 */ 0x1c9a9c62, + /* XFER_UDMA_0 */ 0x1c829c62, + + /* XFER_MW_DMA_2 */ 0x2c829c62, + /* XFER_MW_DMA_1 */ 0x2c829c66, + /* XFER_MW_DMA_0 */ 0x2c829d2e, + + /* XFER_PIO_4 */ 0x0c829c62, + /* XFER_PIO_3 */ 0x0c829c84, + /* XFER_PIO_2 */ 0x0c829ca6, + /* XFER_PIO_1 */ 0x0d029d26, + /* XFER_PIO_0 */ 0x0d029d5e +}; +#else +/* + * The following are the new timing tables with PIO mode data/taskfile transfer + * overclocking fixed... + */ + +/* This table is taken from the HPT370 data manual rev. 1.02 */ +static u32 thirty_three_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x16455031, /* 0x16655031 ?? */ + /* XFER_UDMA_5 */ 0x16455031, + /* XFER_UDMA_4 */ 0x16455031, + /* XFER_UDMA_3 */ 0x166d5031, + /* XFER_UDMA_2 */ 0x16495031, + /* XFER_UDMA_1 */ 0x164d5033, + /* XFER_UDMA_0 */ 0x16515097, + + /* XFER_MW_DMA_2 */ 0x26515031, + /* XFER_MW_DMA_1 */ 0x26515033, + /* XFER_MW_DMA_0 */ 0x26515097, + + /* XFER_PIO_4 */ 0x06515021, + /* XFER_PIO_3 */ 0x06515022, + /* XFER_PIO_2 */ 0x06515033, + /* XFER_PIO_1 */ 0x06915065, + /* XFER_PIO_0 */ 0x06d1508a +}; + +static u32 fifty_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x1a861842, + /* XFER_UDMA_5 */ 0x1a861842, + /* XFER_UDMA_4 */ 0x1aae1842, + /* XFER_UDMA_3 */ 0x1a8e1842, + /* XFER_UDMA_2 */ 0x1a0e1842, + /* XFER_UDMA_1 */ 0x1a161854, + /* XFER_UDMA_0 */ 0x1a1a18ea, + + /* XFER_MW_DMA_2 */ 0x2a821842, + /* XFER_MW_DMA_1 */ 0x2a821854, + /* XFER_MW_DMA_0 */ 0x2a8218ea, + + /* XFER_PIO_4 */ 0x0a821842, + /* XFER_PIO_3 */ 0x0a821843, + /* XFER_PIO_2 */ 0x0a821855, + /* XFER_PIO_1 */ 0x0ac218a8, + /* XFER_PIO_0 */ 0x0b02190c +}; + +static u32 sixty_six_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x1c86fe62, + /* XFER_UDMA_5 */ 0x1caefe62, /* 0x1c8afe62 */ + /* XFER_UDMA_4 */ 0x1c8afe62, + /* XFER_UDMA_3 */ 0x1c8efe62, + /* XFER_UDMA_2 */ 0x1c92fe62, + /* XFER_UDMA_1 */ 0x1c9afe62, + /* XFER_UDMA_0 */ 0x1c82fe62, + + /* XFER_MW_DMA_2 */ 0x2c82fe62, + /* XFER_MW_DMA_1 */ 0x2c82fe66, + /* XFER_MW_DMA_0 */ 0x2c82ff2e, + + /* XFER_PIO_4 */ 0x0c82fe62, + /* XFER_PIO_3 */ 0x0c82fe84, + /* XFER_PIO_2 */ 0x0c82fea6, + /* XFER_PIO_1 */ 0x0d02ff26, + /* XFER_PIO_0 */ 0x0d42ff7f +}; +#endif + +#define HPT366_DEBUG_DRIVE_INFO 0 +#define HPT371_ALLOW_ATA133_6 1 +#define HPT302_ALLOW_ATA133_6 1 +#define HPT372_ALLOW_ATA133_6 1 +#define HPT370_ALLOW_ATA100_5 0 +#define HPT366_ALLOW_ATA66_4 1 +#define HPT366_ALLOW_ATA66_3 1 +#define HPT366_MAX_DEVS 8 + +/* Supported ATA clock frequencies */ +enum ata_clock { + ATA_CLOCK_25MHZ, + ATA_CLOCK_33MHZ, + ATA_CLOCK_40MHZ, + ATA_CLOCK_50MHZ, + ATA_CLOCK_66MHZ, + NUM_ATA_CLOCKS +}; + +struct hpt_timings { + u32 pio_mask; + u32 dma_mask; + u32 ultra_mask; + u32 *clock_table[NUM_ATA_CLOCKS]; +}; + +/* + * Hold all the HighPoint chip information in one place. + */ + +struct hpt_info { + char *chip_name; /* Chip name */ + u8 chip_type; /* Chip type */ + u8 udma_mask; /* Allowed UltraDMA modes mask. */ + u8 dpll_clk; /* DPLL clock in MHz */ + u8 pci_clk; /* PCI clock in MHz */ + struct hpt_timings *timings; /* Chipset timing data */ + u8 clock; /* ATA clock selected */ +}; + +/* Supported HighPoint chips */ +enum { + HPT36x, + HPT370, + HPT370A, + HPT374, + HPT372, + HPT372A, + HPT302, + HPT371, + HPT372N, + HPT302N, + HPT371N +}; + +static struct hpt_timings hpt36x_timings = { + .pio_mask = 0xc1f8ffff, + .dma_mask = 0x303800ff, + .ultra_mask = 0x30070000, + .clock_table = { + [ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x, + [ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x, + [ATA_CLOCK_40MHZ] = forty_base_hpt36x, + [ATA_CLOCK_50MHZ] = NULL, + [ATA_CLOCK_66MHZ] = NULL + } +}; + +static struct hpt_timings hpt37x_timings = { + .pio_mask = 0xcfc3ffff, + .dma_mask = 0x31c001ff, + .ultra_mask = 0x303c0000, + .clock_table = { + [ATA_CLOCK_25MHZ] = NULL, + [ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x, + [ATA_CLOCK_40MHZ] = NULL, + [ATA_CLOCK_50MHZ] = fifty_base_hpt37x, + [ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x + } +}; + +static const struct hpt_info hpt36x __devinitdata = { + .chip_name = "HPT36x", + .chip_type = HPT36x, + .udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2, + .dpll_clk = 0, /* no DPLL */ + .timings = &hpt36x_timings +}; + +static const struct hpt_info hpt370 __devinitdata = { + .chip_name = "HPT370", + .chip_type = HPT370, + .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, + .dpll_clk = 48, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt370a __devinitdata = { + .chip_name = "HPT370A", + .chip_type = HPT370A, + .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, + .dpll_clk = 48, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt374 __devinitdata = { + .chip_name = "HPT374", + .chip_type = HPT374, + .udma_mask = ATA_UDMA5, + .dpll_clk = 48, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt372 __devinitdata = { + .chip_name = "HPT372", + .chip_type = HPT372, + .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, + .dpll_clk = 55, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt372a __devinitdata = { + .chip_name = "HPT372A", + .chip_type = HPT372A, + .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, + .dpll_clk = 66, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt302 __devinitdata = { + .chip_name = "HPT302", + .chip_type = HPT302, + .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, + .dpll_clk = 66, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt371 __devinitdata = { + .chip_name = "HPT371", + .chip_type = HPT371, + .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, + .dpll_clk = 66, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt372n __devinitdata = { + .chip_name = "HPT372N", + .chip_type = HPT372N, + .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, + .dpll_clk = 77, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt302n __devinitdata = { + .chip_name = "HPT302N", + .chip_type = HPT302N, + .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, + .dpll_clk = 77, + .timings = &hpt37x_timings +}; + +static const struct hpt_info hpt371n __devinitdata = { + .chip_name = "HPT371N", + .chip_type = HPT371N, + .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, + .dpll_clk = 77, + .timings = &hpt37x_timings +}; + +static int check_in_drive_list(ide_drive_t *drive, const char **list) +{ + char *m = (char *)&drive->id[ATA_ID_PROD]; + + while (*list) + if (!strcmp(*list++, m)) + return 1; + return 0; +} + +static struct hpt_info *hpt3xx_get_info(struct device *dev) +{ + struct ide_host *host = dev_get_drvdata(dev); + struct hpt_info *info = (struct hpt_info *)host->host_priv; + + return dev == host->dev[1] ? info + 1 : info; +} + +/* + * The Marvell bridge chips used on the HighPoint SATA cards do not seem + * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes... + */ + +static u8 hpt3xx_udma_filter(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); + u8 mask = hwif->ultra_mask; + + switch (info->chip_type) { + case HPT36x: + if (!HPT366_ALLOW_ATA66_4 || + check_in_drive_list(drive, bad_ata66_4)) + mask = ATA_UDMA3; + + if (!HPT366_ALLOW_ATA66_3 || + check_in_drive_list(drive, bad_ata66_3)) + mask = ATA_UDMA2; + break; + case HPT370: + if (!HPT370_ALLOW_ATA100_5 || + check_in_drive_list(drive, bad_ata100_5)) + mask = ATA_UDMA4; + break; + case HPT370A: + if (!HPT370_ALLOW_ATA100_5 || + check_in_drive_list(drive, bad_ata100_5)) + return ATA_UDMA4; + case HPT372 : + case HPT372A: + case HPT372N: + case HPT374 : + if (ata_id_is_sata(drive->id)) + mask &= ~0x0e; + /* Fall thru */ + default: + return mask; + } + + return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask; +} + +static u8 hpt3xx_mdma_filter(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); + + switch (info->chip_type) { + case HPT372 : + case HPT372A: + case HPT372N: + case HPT374 : + if (ata_id_is_sata(drive->id)) + return 0x00; + /* Fall thru */ + default: + return 0x07; + } +} + +static u32 get_speed_setting(u8 speed, struct hpt_info *info) +{ + int i; + + /* + * Lookup the transfer mode table to get the index into + * the timing table. + * + * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used. + */ + for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) + if (xfer_speeds[i] == speed) + break; + + return info->timings->clock_table[info->clock][i]; +} + +static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); + struct hpt_timings *t = info->timings; + u8 itr_addr = 0x40 + (drive->dn * 4); + u32 old_itr = 0; + u32 new_itr = get_speed_setting(speed, info); + u32 itr_mask = speed < XFER_MW_DMA_0 ? t->pio_mask : + (speed < XFER_UDMA_0 ? t->dma_mask : + t->ultra_mask); + + pci_read_config_dword(dev, itr_addr, &old_itr); + new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask); + /* + * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) + * to avoid problems handling I/O errors later + */ + new_itr &= ~0xc0000000; + + pci_write_config_dword(dev, itr_addr, new_itr); +} + +static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + hpt3xx_set_mode(drive, XFER_PIO_0 + pio); +} + +static void hpt3xx_quirkproc(ide_drive_t *drive) +{ + char *m = (char *)&drive->id[ATA_ID_PROD]; + const char **list = quirk_drives; + + while (*list) + if (strstr(m, *list++)) { + drive->quirk_list = 1; + return; + } + + drive->quirk_list = 0; +} + +static void hpt3xx_maskproc(ide_drive_t *drive, int mask) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); + + if (drive->quirk_list == 0) + return; + + if (info->chip_type >= HPT370) { + u8 scr1 = 0; + + pci_read_config_byte(dev, 0x5a, &scr1); + if (((scr1 & 0x10) >> 4) != mask) { + if (mask) + scr1 |= 0x10; + else + scr1 &= ~0x10; + pci_write_config_byte(dev, 0x5a, scr1); + } + } else if (mask) + disable_irq(hwif->irq); + else + enable_irq(hwif->irq); +} + +/* + * This is specific to the HPT366 UDMA chipset + * by HighPoint|Triones Technologies, Inc. + */ +static void hpt366_dma_lost_irq(ide_drive_t *drive) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u8 mcr1 = 0, mcr3 = 0, scr1 = 0; + + pci_read_config_byte(dev, 0x50, &mcr1); + pci_read_config_byte(dev, 0x52, &mcr3); + pci_read_config_byte(dev, 0x5a, &scr1); + printk("%s: (%s) mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n", + drive->name, __func__, mcr1, mcr3, scr1); + if (scr1 & 0x10) + pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); + ide_dma_lost_irq(drive); +} + +static void hpt370_clear_engine(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + + pci_write_config_byte(dev, hwif->select_data, 0x37); + udelay(10); +} + +static void hpt370_irq_timeout(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u16 bfifo = 0; + u8 dma_cmd; + + pci_read_config_word(dev, hwif->select_data + 2, &bfifo); + printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff); + + /* get DMA command mode */ + dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); + /* stop DMA */ + outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD); + hpt370_clear_engine(drive); +} + +static void hpt370_dma_start(ide_drive_t *drive) +{ +#ifdef HPT_RESET_STATE_ENGINE + hpt370_clear_engine(drive); +#endif + ide_dma_start(drive); +} + +static int hpt370_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + + if (dma_stat & 0x01) { + /* wait a little */ + udelay(20); + dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + if (dma_stat & 0x01) + hpt370_irq_timeout(drive); + } + return ide_dma_end(drive); +} + +static void hpt370_dma_timeout(ide_drive_t *drive) +{ + hpt370_irq_timeout(drive); + ide_dma_timeout(drive); +} + +/* returns 1 if DMA IRQ issued, 0 otherwise */ +static int hpt374_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u16 bfifo = 0; + u8 dma_stat; + + pci_read_config_word(dev, hwif->select_data + 2, &bfifo); + if (bfifo & 0x1FF) { +// printk("%s: %d bytes in FIFO\n", drive->name, bfifo); + return 0; + } + + dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + /* return 1 if INTR asserted */ + if (dma_stat & 4) + return 1; + + return 0; +} + +static int hpt374_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 mcr = 0, mcr_addr = hwif->select_data; + u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01; + + pci_read_config_byte(dev, 0x6a, &bwsr); + pci_read_config_byte(dev, mcr_addr, &mcr); + if (bwsr & mask) + pci_write_config_byte(dev, mcr_addr, mcr | 0x30); + return ide_dma_end(drive); +} + +/** + * hpt3xxn_set_clock - perform clock switching dance + * @hwif: hwif to switch + * @mode: clocking mode (0x21 for write, 0x23 otherwise) + * + * Switch the DPLL clock on the HPT3xxN devices. This is a right mess. + */ + +static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) +{ + unsigned long base = hwif->extra_base; + u8 scr2 = inb(base + 0x6b); + + if ((scr2 & 0x7f) == mode) + return; + + /* Tristate the bus */ + outb(0x80, base + 0x63); + outb(0x80, base + 0x67); + + /* Switch clock and reset channels */ + outb(mode, base + 0x6b); + outb(0xc0, base + 0x69); + + /* + * Reset the state machines. + * NOTE: avoid accidentally enabling the disabled channels. + */ + outb(inb(base + 0x60) | 0x32, base + 0x60); + outb(inb(base + 0x64) | 0x32, base + 0x64); + + /* Complete reset */ + outb(0x00, base + 0x69); + + /* Reconnect channels to bus */ + outb(0x00, base + 0x63); + outb(0x00, base + 0x67); +} + +/** + * hpt3xxn_rw_disk - prepare for I/O + * @drive: drive for command + * @rq: block request structure + * + * This is called when a disk I/O is issued to HPT3xxN. + * We need it because of the clock switching. + */ + +static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) +{ + hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21); +} + +/** + * hpt37x_calibrate_dpll - calibrate the DPLL + * @dev: PCI device + * + * Perform a calibration cycle on the DPLL. + * Returns 1 if this succeeds + */ +static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) +{ + u32 dpll = (f_high << 16) | f_low | 0x100; + u8 scr2; + int i; + + pci_write_config_dword(dev, 0x5c, dpll); + + /* Wait for oscillator ready */ + for(i = 0; i < 0x5000; ++i) { + udelay(50); + pci_read_config_byte(dev, 0x5b, &scr2); + if (scr2 & 0x80) + break; + } + /* See if it stays ready (we'll just bail out if it's not yet) */ + for(i = 0; i < 0x1000; ++i) { + pci_read_config_byte(dev, 0x5b, &scr2); + /* DPLL destabilized? */ + if(!(scr2 & 0x80)) + return 0; + } + /* Turn off tuning, we have the DPLL set */ + pci_read_config_dword (dev, 0x5c, &dpll); + pci_write_config_dword(dev, 0x5c, (dpll & ~0x100)); + return 1; +} + +static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]); + u8 chip_type = info->chip_type; + u8 new_mcr, old_mcr = 0; + + /* + * Disable the "fast interrupt" prediction. Don't hold off + * on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, mcr_addr + 1, &old_mcr); + + if (chip_type >= HPT374) + new_mcr = old_mcr & ~0x07; + else if (chip_type >= HPT370) { + new_mcr = old_mcr; + new_mcr &= ~0x02; +#ifdef HPT_DELAY_INTERRUPT + new_mcr &= ~0x01; +#else + new_mcr |= 0x01; +#endif + } else /* HPT366 and HPT368 */ + new_mcr = old_mcr & ~0x80; + + if (new_mcr != old_mcr) + pci_write_config_byte(dev, mcr_addr + 1, new_mcr); +} + +static unsigned int init_chipset_hpt366(struct pci_dev *dev) +{ + unsigned long io_base = pci_resource_start(dev, 4); + struct hpt_info *info = hpt3xx_get_info(&dev->dev); + const char *name = DRV_NAME; + u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ + u8 chip_type; + enum ata_clock clock; + + chip_type = info->chip_type; + + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + + /* + * First, try to estimate the PCI clock frequency... + */ + if (chip_type >= HPT370) { + u8 scr1 = 0; + u16 f_cnt = 0; + u32 temp = 0; + + /* Interrupt force enable. */ + pci_read_config_byte(dev, 0x5a, &scr1); + if (scr1 & 0x10) + pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); + + /* + * HighPoint does this for HPT372A. + * NOTE: This register is only writeable via I/O space. + */ + if (chip_type == HPT372A) + outb(0x0e, io_base + 0x9c); + + /* + * Default to PCI clock. Make sure MA15/16 are set to output + * to prevent drives having problems with 40-pin cables. + */ + pci_write_config_byte(dev, 0x5b, 0x23); + + /* + * We'll have to read f_CNT value in order to determine + * the PCI clock frequency according to the following ratio: + * + * f_CNT = Fpci * 192 / Fdpll + * + * First try reading the register in which the HighPoint BIOS + * saves f_CNT value before reprogramming the DPLL from its + * default setting (which differs for the various chips). + * + * NOTE: This register is only accessible via I/O space; + * HPT374 BIOS only saves it for the function 0, so we have to + * always read it from there -- no need to check the result of + * pci_get_slot() for the function 0 as the whole device has + * been already "pinned" (via function 1) in init_setup_hpt374() + */ + if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { + struct pci_dev *dev1 = pci_get_slot(dev->bus, + dev->devfn - 1); + unsigned long io_base = pci_resource_start(dev1, 4); + + temp = inl(io_base + 0x90); + pci_dev_put(dev1); + } else + temp = inl(io_base + 0x90); + + /* + * In case the signature check fails, we'll have to + * resort to reading the f_CNT register itself in hopes + * that nobody has touched the DPLL yet... + */ + if ((temp & 0xFFFFF000) != 0xABCDE000) { + int i; + + printk(KERN_WARNING "%s %s: no clock data saved by " + "BIOS\n", name, pci_name(dev)); + + /* Calculate the average value of f_CNT. */ + for (temp = i = 0; i < 128; i++) { + pci_read_config_word(dev, 0x78, &f_cnt); + temp += f_cnt & 0x1ff; + mdelay(1); + } + f_cnt = temp / 128; + } else + f_cnt = temp & 0x1ff; + + dpll_clk = info->dpll_clk; + pci_clk = (f_cnt * dpll_clk) / 192; + + /* Clamp PCI clock to bands. */ + if (pci_clk < 40) + pci_clk = 33; + else if(pci_clk < 45) + pci_clk = 40; + else if(pci_clk < 55) + pci_clk = 50; + else + pci_clk = 66; + + printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, " + "assuming %d MHz PCI\n", name, pci_name(dev), + dpll_clk, f_cnt, pci_clk); + } else { + u32 itr1 = 0; + + pci_read_config_dword(dev, 0x40, &itr1); + + /* Detect PCI clock by looking at cmd_high_time. */ + switch((itr1 >> 8) & 0x07) { + case 0x09: + pci_clk = 40; + break; + case 0x05: + pci_clk = 25; + break; + case 0x07: + default: + pci_clk = 33; + break; + } + } + + /* Let's assume we'll use PCI clock for the ATA clock... */ + switch (pci_clk) { + case 25: + clock = ATA_CLOCK_25MHZ; + break; + case 33: + default: + clock = ATA_CLOCK_33MHZ; + break; + case 40: + clock = ATA_CLOCK_40MHZ; + break; + case 50: + clock = ATA_CLOCK_50MHZ; + break; + case 66: + clock = ATA_CLOCK_66MHZ; + break; + } + + /* + * Only try the DPLL if we don't have a table for the PCI clock that + * we are running at for HPT370/A, always use it for anything newer... + * + * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI. + * We also don't like using the DPLL because this causes glitches + * on PRST-/SRST- when the state engine gets reset... + */ + if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) { + u16 f_low, delta = pci_clk < 50 ? 2 : 4; + int adjust; + + /* + * Select 66 MHz DPLL clock only if UltraATA/133 mode is + * supported/enabled, use 50 MHz DPLL clock otherwise... + */ + if (info->udma_mask == ATA_UDMA6) { + dpll_clk = 66; + clock = ATA_CLOCK_66MHZ; + } else if (dpll_clk) { /* HPT36x chips don't have DPLL */ + dpll_clk = 50; + clock = ATA_CLOCK_50MHZ; + } + + if (info->timings->clock_table[clock] == NULL) { + printk(KERN_ERR "%s %s: unknown bus timing!\n", + name, pci_name(dev)); + return -EIO; + } + + /* Select the DPLL clock. */ + pci_write_config_byte(dev, 0x5b, 0x21); + + /* + * Adjust the DPLL based upon PCI clock, enable it, + * and wait for stabilization... + */ + f_low = (pci_clk * 48) / dpll_clk; + + for (adjust = 0; adjust < 8; adjust++) { + if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta)) + break; + + /* + * See if it'll settle at a fractionally different clock + */ + if (adjust & 1) + f_low -= adjust >> 1; + else + f_low += adjust >> 1; + } + if (adjust == 8) { + printk(KERN_ERR "%s %s: DPLL did not stabilize!\n", + name, pci_name(dev)); + return -EIO; + } + + printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n", + name, pci_name(dev), dpll_clk); + } else { + /* Mark the fact that we're not using the DPLL. */ + dpll_clk = 0; + + printk(KERN_INFO "%s %s: using %d MHz PCI clock\n", + name, pci_name(dev), pci_clk); + } + + /* Store the clock frequencies. */ + info->dpll_clk = dpll_clk; + info->pci_clk = pci_clk; + info->clock = clock; + + if (chip_type >= HPT370) { + u8 mcr1, mcr4; + + /* + * Reset the state engines. + * NOTE: Avoid accidentally enabling the disabled channels. + */ + pci_read_config_byte (dev, 0x50, &mcr1); + pci_read_config_byte (dev, 0x54, &mcr4); + pci_write_config_byte(dev, 0x50, (mcr1 | 0x32)); + pci_write_config_byte(dev, 0x54, (mcr4 | 0x32)); + udelay(100); + } + + /* + * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in + * the MISC. register to stretch the UltraDMA Tss timing. + * NOTE: This register is only writeable via I/O space. + */ + if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) + outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); + + hpt3xx_disable_fast_irq(dev, 0x50); + hpt3xx_disable_fast_irq(dev, 0x54); + + return dev->irq; +} + +static u8 hpt3xx_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); + u8 chip_type = info->chip_type; + u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02; + + /* + * The HPT37x uses the CBLID pins as outputs for MA15/MA16 + * address lines to access an external EEPROM. To read valid + * cable detect state the pins must be enabled as inputs. + */ + if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { + /* + * HPT374 PCI function 1 + * - set bit 15 of reg 0x52 to enable TCBLID as input + * - set bit 15 of reg 0x56 to enable FCBLID as input + */ + u8 mcr_addr = hwif->select_data + 2; + u16 mcr; + + pci_read_config_word(dev, mcr_addr, &mcr); + pci_write_config_word(dev, mcr_addr, (mcr | 0x8000)); + /* now read cable id register */ + pci_read_config_byte(dev, 0x5a, &scr1); + pci_write_config_word(dev, mcr_addr, mcr); + } else if (chip_type >= HPT370) { + /* + * HPT370/372 and 374 pcifn 0 + * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs + */ + u8 scr2 = 0; + + pci_read_config_byte(dev, 0x5b, &scr2); + pci_write_config_byte(dev, 0x5b, (scr2 & ~1)); + /* now read cable id register */ + pci_read_config_byte(dev, 0x5a, &scr1); + pci_write_config_byte(dev, 0x5b, scr2); + } else + pci_read_config_byte(dev, 0x5a, &scr1); + + return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + +static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) +{ + struct hpt_info *info = hpt3xx_get_info(hwif->dev); + int serialize = HPT_SERIALIZE_IO; + u8 chip_type = info->chip_type; + + /* Cache the channel's MISC. control registers' offset */ + hwif->select_data = hwif->channel ? 0x54 : 0x50; + + /* + * HPT3xxN chips have some complications: + * + * - on 33 MHz PCI we must clock switch + * - on 66 MHz PCI we must NOT use the PCI clock + */ + if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) { + /* + * Clock is shared between the channels, + * so we'll have to serialize them... :-( + */ + serialize = 1; + hwif->rw_disk = &hpt3xxn_rw_disk; + } + + /* Serialize access to this device if needed */ + if (serialize && hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; +} + +static int __devinit init_dma_hpt366(ide_hwif_t *hwif, + const struct ide_port_info *d) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long flags, base = ide_pci_dma_base(hwif, d); + u8 dma_old, dma_new, masterdma = 0, slavedma = 0; + + if (base == 0) + return -1; + + hwif->dma_base = base; + + if (ide_pci_check_simplex(hwif, d) < 0) + return -1; + + if (ide_pci_set_master(dev, d->name) < 0) + return -1; + + dma_old = inb(base + 2); + + local_irq_save(flags); + + dma_new = dma_old; + pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma); + pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47, &slavedma); + + if (masterdma & 0x30) dma_new |= 0x20; + if ( slavedma & 0x30) dma_new |= 0x40; + if (dma_new != dma_old) + outb(dma_new, base + 2); + + local_irq_restore(flags); + + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", + hwif->name, base, base + 7); + + hwif->extra_base = base + (hwif->channel ? 8 : 16); + + if (ide_allocate_dma_engine(hwif)) + return -1; + + hwif->dma_ops = &sff_dma_ops; + + return 0; +} + +static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2) +{ + if (dev2->irq != dev->irq) { + /* FIXME: we need a core pci_set_interrupt() */ + dev2->irq = dev->irq; + printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt " + "fixed\n", pci_name(dev2)); + } +} + +static void __devinit hpt371_init(struct pci_dev *dev) +{ + u8 mcr1 = 0; + + /* + * HPT371 chips physically have only one channel, the secondary one, + * but the primary channel registers do exist! Go figure... + * So, we manually disable the non-existing channel here + * (if the BIOS hasn't done this already). + */ + pci_read_config_byte(dev, 0x50, &mcr1); + if (mcr1 & 0x04) + pci_write_config_byte(dev, 0x50, mcr1 & ~0x04); +} + +static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) +{ + u8 mcr1 = 0, pin1 = 0, pin2 = 0; + + /* + * Now we'll have to force both channels enabled if + * at least one of them has been enabled by BIOS... + */ + pci_read_config_byte(dev, 0x50, &mcr1); + if (mcr1 & 0x30) + pci_write_config_byte(dev, 0x50, mcr1 | 0x30); + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); + pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); + + if (pin1 != pin2 && dev->irq == dev2->irq) { + printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, " + "pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2); + return 1; + } + + return 0; +} + +#define IDE_HFLAGS_HPT3XX \ + (IDE_HFLAG_NO_ATAPI_DMA | \ + IDE_HFLAG_OFF_BOARD) + +static const struct ide_port_ops hpt3xx_port_ops = { + .set_pio_mode = hpt3xx_set_pio_mode, + .set_dma_mode = hpt3xx_set_mode, + .quirkproc = hpt3xx_quirkproc, + .maskproc = hpt3xx_maskproc, + .mdma_filter = hpt3xx_mdma_filter, + .udma_filter = hpt3xx_udma_filter, + .cable_detect = hpt3xx_cable_detect, +}; + +static const struct ide_dma_ops hpt37x_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = hpt374_dma_end, + .dma_test_irq = hpt374_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_dma_ops hpt370_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = hpt370_dma_start, + .dma_end = hpt370_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = hpt370_dma_timeout, +}; + +static const struct ide_dma_ops hpt36x_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = ide_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = hpt366_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info hpt366_chipsets[] __devinitdata = { + { /* 0: HPT36x */ + .name = DRV_NAME, + .init_chipset = init_chipset_hpt366, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + /* + * HPT36x chips have one channel per function and have + * both channel enable bits located differently and visible + * to both functions -- really stupid design decision... :-( + * Bit 4 is for the primary channel, bit 5 for the secondary. + */ + .enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}}, + .port_ops = &hpt3xx_port_ops, + .dma_ops = &hpt36x_dma_ops, + .host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + }, + { /* 1: HPT3xx */ + .name = DRV_NAME, + .init_chipset = init_chipset_hpt366, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, + .port_ops = &hpt3xx_port_ops, + .dma_ops = &hpt37x_dma_ops, + .host_flags = IDE_HFLAGS_HPT3XX, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + } +}; + +/** + * hpt366_init_one - called when an HPT366 is found + * @dev: the hpt366 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 __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + const struct hpt_info *info = NULL; + struct hpt_info *dyn_info; + struct pci_dev *dev2 = NULL; + struct ide_port_info d; + u8 idx = id->driver_data; + u8 rev = dev->revision; + int ret; + + if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1)) + return -ENODEV; + + switch (idx) { + case 0: + if (rev < 3) + info = &hpt36x; + else { + switch (min_t(u8, rev, 6)) { + case 3: info = &hpt370; break; + case 4: info = &hpt370a; break; + case 5: info = &hpt372; break; + case 6: info = &hpt372n; break; + } + idx++; + } + break; + case 1: + info = (rev > 1) ? &hpt372n : &hpt372a; + break; + case 2: + info = (rev > 1) ? &hpt302n : &hpt302; + break; + case 3: + hpt371_init(dev); + info = (rev > 1) ? &hpt371n : &hpt371; + break; + case 4: + info = &hpt374; + break; + case 5: + info = &hpt372n; + break; + } + + printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name); + + d = hpt366_chipsets[min_t(u8, idx, 1)]; + + d.udma_mask = info->udma_mask; + + /* fixup ->dma_ops for HPT370/HPT370A */ + if (info == &hpt370 || info == &hpt370a) + d.dma_ops = &hpt370_dma_ops; + + if (info == &hpt36x || info == &hpt374) + dev2 = pci_get_slot(dev->bus, dev->devfn + 1); + + dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL); + if (dyn_info == NULL) { + printk(KERN_ERR "%s %s: out of memory!\n", + d.name, pci_name(dev)); + pci_dev_put(dev2); + return -ENOMEM; + } + + /* + * Copy everything from a static "template" structure + * to just allocated per-chip hpt_info structure. + */ + memcpy(dyn_info, info, sizeof(*dyn_info)); + + if (dev2) { + memcpy(dyn_info + 1, info, sizeof(*dyn_info)); + + if (info == &hpt374) + hpt374_init(dev, dev2); + else { + if (hpt36x_init(dev, dev2)) + d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE; + } + + ret = ide_pci_init_two(dev, dev2, &d, dyn_info); + if (ret < 0) { + pci_dev_put(dev2); + kfree(dyn_info); + } + return ret; + } + + ret = ide_pci_init_one(dev, &d, dyn_info); + if (ret < 0) + kfree(dyn_info); + + return ret; +} + +static void __devexit hpt366_remove(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct ide_info *info = host->host_priv; + struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; + + ide_pci_remove(dev); + pci_dev_put(dev2); + kfree(info); +} + +static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = { + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), 0 }, + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), 1 }, + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), 2 }, + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), 3 }, + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374), 4 }, + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl); + +static struct pci_driver hpt366_pci_driver = { + .name = "HPT366_IDE", + .id_table = hpt366_pci_tbl, + .probe = hpt366_init_one, + .remove = __devexit_p(hpt366_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init hpt366_ide_init(void) +{ + return ide_pci_register_driver(&hpt366_pci_driver); +} + +static void __exit hpt366_ide_exit(void) +{ + pci_unregister_driver(&hpt366_pci_driver); +} + +module_init(hpt366_ide_init); +module_exit(hpt366_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c new file mode 100644 index 0000000..c7e5c22 --- /dev/null +++ b/drivers/ide/ht6560b.c @@ -0,0 +1,351 @@ +/* + * Copyright (C) 1995-2000 Linus Torvalds & author (see below) + */ + +/* + * HT-6560B EIDE-controller support + * To activate controller support use kernel parameter "ide0=ht6560b". + * Use hdparm utility to enable PIO mode support. + * + * Author: Mikko Ala-Fossi + * Jan Evert van Grootheest + * + * Try: http://www.maf.iki.fi/~maf/ht6560b/ + */ + +#define DRV_NAME "ht6560b" +#define HT6560B_VERSION "v0.08" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* #define DEBUG */ /* remove comments for DEBUG messages */ + +/* + * The special i/o-port that HT-6560B uses to configuration: + * bit0 (0x01): "1" selects secondary interface + * bit2 (0x04): "1" enables FIFO function + * bit5 (0x20): "1" enables prefetched data read function (???) + * + * The special i/o-port that HT-6560A uses to configuration: + * bit0 (0x01): "1" selects secondary interface + * bit1 (0x02): "1" enables prefetched data read function + * bit2 (0x04): "0" enables multi-master system (?) + * bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?) + */ +#define HT_CONFIG_PORT 0x3e6 +#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8) +/* + * FIFO + PREFETCH (both a/b-model) + */ +#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */ +/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */ +#define HT_SECONDARY_IF 0x01 +#define HT_PREFETCH_MODE 0x20 + +/* + * ht6560b Timing values: + * + * I reviewed some assembler source listings of htide drivers and found + * out how they setup those cycle time interfacing values, as they at Holtek + * call them. IDESETUP.COM that is supplied with the drivers figures out + * optimal values and fetches those values to drivers. I found out that + * they use Select register to fetch timings to the ide board right after + * interface switching. After that it was quite easy to add code to + * ht6560b.c. + * + * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine + * for hda and hdc. But hdb needed higher values to work, so I guess + * that sometimes it is necessary to give higher value than IDESETUP + * gives. [see cmd640.c for an extreme example of this. -ml] + * + * Perhaps I should explain something about these timing values: + * The higher nibble of value is the Recovery Time (rt) and the lower nibble + * of the value is the Active Time (at). Minimum value 2 is the fastest and + * the maximum value 15 is the slowest. Default values should be 15 for both. + * So 0x24 means 2 for rt and 4 for at. Each of the drives should have + * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or + * similar. If value is too small there will be all sorts of failures. + * + * Timing byte consists of + * High nibble: Recovery Cycle Time (rt) + * The valid values range from 2 to 15. The default is 15. + * + * Low nibble: Active Cycle Time (at) + * The valid values range from 2 to 15. The default is 15. + * + * You can obtain optimized timing values by running Holtek IDESETUP.COM + * for DOS. DOS drivers get their timing values from command line, where + * the first value is the Recovery Time and the second value is the + * Active Time for each drive. Smaller value gives higher speed. + * In case of failures you should probably fall back to a higher value. + */ +#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff) +#define HT_TIMING_DEFAULT 0xff + +/* + * This routine handles interface switching for the peculiar hardware design + * on the F.G.I./Holtek HT-6560B VLB IDE interface. + * The HT-6560B can only enable one IDE port at a time, and requires a + * silly sequence (below) whenever we switch between primary and secondary. + */ + +/* + * This routine is invoked from ide.c to prepare for access to a given drive. + */ +static void ht6560b_selectproc (ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + unsigned long flags; + static u8 current_select = 0; + static u8 current_timing = 0; + u8 select, timing; + + local_irq_save(flags); + + select = HT_CONFIG(drive); + timing = HT_TIMING(drive); + + /* + * Need to enforce prefetch sometimes because otherwise + * it'll hang (hard). + */ + if (drive->media != ide_disk || + (drive->dev_flags & IDE_DFLAG_PRESENT) == 0) + select |= HT_PREFETCH_MODE; + + if (select != current_select || timing != current_timing) { + current_select = select; + current_timing = timing; + (void)inb(HT_CONFIG_PORT); + (void)inb(HT_CONFIG_PORT); + (void)inb(HT_CONFIG_PORT); + (void)inb(HT_CONFIG_PORT); + outb(select, HT_CONFIG_PORT); + /* + * Set timing for this drive: + */ + outb(timing, hwif->io_ports.device_addr); + (void)inb(hwif->io_ports.status_addr); +#ifdef DEBUG + printk("ht6560b: %s: select=%#x timing=%#x\n", + drive->name, select, timing); +#endif + } + local_irq_restore(flags); +} + +/* + * Autodetection and initialization of ht6560b + */ +static int __init try_to_init_ht6560b(void) +{ + u8 orig_value; + int i; + + /* Autodetect ht6560b */ + if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff) + return 0; + + for (i=3;i>0;i--) { + outb(0x00, HT_CONFIG_PORT); + if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) { + outb(orig_value, HT_CONFIG_PORT); + return 0; + } + } + outb(0x00, HT_CONFIG_PORT); + if ((~inb(HT_CONFIG_PORT))& 0x3f) { + outb(orig_value, HT_CONFIG_PORT); + return 0; + } + /* + * Ht6560b autodetected + */ + outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); + outb(HT_TIMING_DEFAULT, 0x1f6); /* Select register */ + (void)inb(0x1f7); /* Status register */ + + printk("ht6560b " HT6560B_VERSION + ": chipset detected and initialized" +#ifdef DEBUG + " with debug enabled" +#endif + "\n" + ); + return 1; +} + +static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio) +{ + int active_time, recovery_time; + int active_cycles, recovery_cycles; + int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50; + + if (pio) { + unsigned int cycle_time; + struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); + + cycle_time = ide_pio_cycle_time(drive, pio); + + /* + * Just like opti621.c we try to calculate the + * actual cycle time for recovery and activity + * according system bus speed. + */ + active_time = t->active; + recovery_time = cycle_time - active_time - t->setup; + /* + * Cycle times should be Vesa bus cycles + */ + active_cycles = (active_time * bus_speed + 999) / 1000; + recovery_cycles = (recovery_time * bus_speed + 999) / 1000; + /* + * Upper and lower limits + */ + if (active_cycles < 2) active_cycles = 2; + if (recovery_cycles < 2) recovery_cycles = 2; + if (active_cycles > 15) active_cycles = 15; + if (recovery_cycles > 15) recovery_cycles = 0; /* 0==16 */ + +#ifdef DEBUG + printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time); +#endif + + return (u8)((recovery_cycles << 4) | active_cycles); + } else { + +#ifdef DEBUG + printk("ht6560b: drive %s setting pio=0\n", drive->name); +#endif + + return HT_TIMING_DEFAULT; /* default setting */ + } +} + +static DEFINE_SPINLOCK(ht6560b_lock); + +/* + * Enable/Disable so called prefetch mode + */ +static void ht_set_prefetch(ide_drive_t *drive, u8 state) +{ + unsigned long flags; + int t = HT_PREFETCH_MODE << 8; + + spin_lock_irqsave(&ht6560b_lock, flags); + + /* + * Prefetch mode and unmask irq seems to conflict + */ + if (state) { + drive->drive_data |= t; /* enable prefetch mode */ + drive->dev_flags |= IDE_DFLAG_NO_UNMASK; + drive->dev_flags &= ~IDE_DFLAG_UNMASK; + } else { + drive->drive_data &= ~t; /* disable prefetch mode */ + drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK; + } + + spin_unlock_irqrestore(&ht6560b_lock, flags); + +#ifdef DEBUG + printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); +#endif +} + +static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + unsigned long flags; + u8 timing; + + switch (pio) { + case 8: /* set prefetch off */ + case 9: /* set prefetch on */ + ht_set_prefetch(drive, pio & 1); + return; + } + + timing = ht_pio2timings(drive, pio); + + spin_lock_irqsave(&ht6560b_lock, flags); + drive->drive_data &= 0xff00; + drive->drive_data |= timing; + spin_unlock_irqrestore(&ht6560b_lock, flags); + +#ifdef DEBUG + printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); +#endif +} + +static void __init ht6560b_init_dev(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + /* Setting default configurations for drives. */ + int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT; + + if (hwif->channel) + t |= (HT_SECONDARY_IF << 8); + + drive->drive_data = t; +} + +static int probe_ht6560b; + +module_param_named(probe, probe_ht6560b, bool, 0); +MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); + +static const struct ide_port_ops ht6560b_port_ops = { + .init_dev = ht6560b_init_dev, + .set_pio_mode = ht6560b_set_pio_mode, + .selectproc = ht6560b_selectproc, +}; + +static const struct ide_port_info ht6560b_port_info __initdata = { + .name = DRV_NAME, + .chipset = ide_ht6560b, + .port_ops = &ht6560b_port_ops, + .host_flags = IDE_HFLAG_SERIALIZE | /* is this needed? */ + IDE_HFLAG_NO_DMA | + IDE_HFLAG_ABUSE_PREFETCH, + .pio_mask = ATA_PIO4, +}; + +static int __init ht6560b_init(void) +{ + if (probe_ht6560b == 0) + return -ENODEV; + + if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) { + printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n", + __func__); + return -ENODEV; + } + + if (!try_to_init_ht6560b()) { + printk(KERN_NOTICE "%s: HBA not found\n", __func__); + goto release_region; + } + + return ide_legacy_device_add(&ht6560b_port_info, 0); + +release_region: + release_region(HT_CONFIG_PORT, 1); + return -ENODEV; +} + +module_init(ht6560b_init); + +MODULE_AUTHOR("See Local File"); +MODULE_DESCRIPTION("HT-6560B EIDE-controller support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c new file mode 100644 index 0000000..76bdc9a --- /dev/null +++ b/drivers/ide/icside.c @@ -0,0 +1,703 @@ +/* + * Copyright (c) 1996-2004 Russell King. + * + * Please note that this platform does not support 32-bit IDE IO. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DRV_NAME "icside" + +#define ICS_IDENT_OFFSET 0x2280 + +#define ICS_ARCIN_V5_INTRSTAT 0x0000 +#define ICS_ARCIN_V5_INTROFFSET 0x0004 +#define ICS_ARCIN_V5_IDEOFFSET 0x2800 +#define ICS_ARCIN_V5_IDEALTOFFSET 0x2b80 +#define ICS_ARCIN_V5_IDESTEPPING 6 + +#define ICS_ARCIN_V6_IDEOFFSET_1 0x2000 +#define ICS_ARCIN_V6_INTROFFSET_1 0x2200 +#define ICS_ARCIN_V6_INTRSTAT_1 0x2290 +#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x2380 +#define ICS_ARCIN_V6_IDEOFFSET_2 0x3000 +#define ICS_ARCIN_V6_INTROFFSET_2 0x3200 +#define ICS_ARCIN_V6_INTRSTAT_2 0x3290 +#define ICS_ARCIN_V6_IDEALTOFFSET_2 0x3380 +#define ICS_ARCIN_V6_IDESTEPPING 6 + +struct cardinfo { + unsigned int dataoffset; + unsigned int ctrloffset; + unsigned int stepping; +}; + +static struct cardinfo icside_cardinfo_v5 = { + .dataoffset = ICS_ARCIN_V5_IDEOFFSET, + .ctrloffset = ICS_ARCIN_V5_IDEALTOFFSET, + .stepping = ICS_ARCIN_V5_IDESTEPPING, +}; + +static struct cardinfo icside_cardinfo_v6_1 = { + .dataoffset = ICS_ARCIN_V6_IDEOFFSET_1, + .ctrloffset = ICS_ARCIN_V6_IDEALTOFFSET_1, + .stepping = ICS_ARCIN_V6_IDESTEPPING, +}; + +static struct cardinfo icside_cardinfo_v6_2 = { + .dataoffset = ICS_ARCIN_V6_IDEOFFSET_2, + .ctrloffset = ICS_ARCIN_V6_IDEALTOFFSET_2, + .stepping = ICS_ARCIN_V6_IDESTEPPING, +}; + +struct icside_state { + unsigned int channel; + unsigned int enabled; + void __iomem *irq_port; + void __iomem *ioc_base; + unsigned int sel; + unsigned int type; + struct ide_host *host; +}; + +#define ICS_TYPE_A3IN 0 +#define ICS_TYPE_A3USER 1 +#define ICS_TYPE_V6 3 +#define ICS_TYPE_V5 15 +#define ICS_TYPE_NOTYPE ((unsigned int)-1) + +/* ---------------- Version 5 PCB Support Functions --------------------- */ +/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) + * Purpose : enable interrupts from card + */ +static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) +{ + struct icside_state *state = ec->irq_data; + + writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET); +} + +/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) + * Purpose : disable interrupts from card + */ +static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) +{ + struct icside_state *state = ec->irq_data; + + readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET); +} + +static const expansioncard_ops_t icside_ops_arcin_v5 = { + .irqenable = icside_irqenable_arcin_v5, + .irqdisable = icside_irqdisable_arcin_v5, +}; + + +/* ---------------- Version 6 PCB Support Functions --------------------- */ +/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) + * Purpose : enable interrupts from card + */ +static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) +{ + struct icside_state *state = ec->irq_data; + void __iomem *base = state->irq_port; + + state->enabled = 1; + + switch (state->channel) { + case 0: + writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); + readb(base + ICS_ARCIN_V6_INTROFFSET_2); + break; + case 1: + writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); + readb(base + ICS_ARCIN_V6_INTROFFSET_1); + break; + } +} + +/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) + * Purpose : disable interrupts from card + */ +static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) +{ + struct icside_state *state = ec->irq_data; + + state->enabled = 0; + + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); +} + +/* Prototype: icside_irqprobe(struct expansion_card *ec) + * Purpose : detect an active interrupt from card + */ +static int icside_irqpending_arcin_v6(struct expansion_card *ec) +{ + struct icside_state *state = ec->irq_data; + + return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || + readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; +} + +static const expansioncard_ops_t icside_ops_arcin_v6 = { + .irqenable = icside_irqenable_arcin_v6, + .irqdisable = icside_irqdisable_arcin_v6, + .irqpending = icside_irqpending_arcin_v6, +}; + +/* + * Handle routing of interrupts. This is called before + * we write the command to the drive. + */ +static void icside_maskproc(ide_drive_t *drive, int mask) +{ + ide_hwif_t *hwif = HWIF(drive); + struct expansion_card *ec = ECARD_DEV(hwif->dev); + struct icside_state *state = ecard_get_drvdata(ec); + unsigned long flags; + + local_irq_save(flags); + + state->channel = hwif->channel; + + if (state->enabled && !mask) { + switch (hwif->channel) { + case 0: + writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + break; + case 1: + writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + break; + } + } else { + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + } + + local_irq_restore(flags); +} + +static const struct ide_port_ops icside_v6_no_dma_port_ops = { + .maskproc = icside_maskproc, +}; + +#ifdef CONFIG_BLK_DEV_IDEDMA_ICS +/* + * SG-DMA support. + * + * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers. + * There is only one DMA controller per card, which means that only + * one drive can be accessed at one time. NOTE! We do not enforce that + * here, but we rely on the main IDE driver spotting that both + * interfaces use the same IRQ, which should guarantee this. + */ + +/* + * Configure the IOMD to give the appropriate timings for the transfer + * mode being requested. We take the advice of the ATA standards, and + * calculate the cycle time based on the transfer mode, and the EIDE + * MW DMA specs that the drive provides in the IDENTIFY command. + * + * We have the following IOMD DMA modes to choose from: + * + * Type Active Recovery Cycle + * A 250 (250) 312 (550) 562 (800) + * B 187 250 437 + * C 125 (125) 125 (375) 250 (500) + * D 62 125 187 + * + * (figures in brackets are actual measured timings) + * + * However, we also need to take care of the read/write active and + * recovery timings: + * + * Read Write + * Mode Active -- Recovery -- Cycle IOMD type + * MW0 215 50 215 480 A + * MW1 80 50 50 150 C + * MW2 70 25 25 120 C + */ +static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) +{ + int cycle_time, use_dma_info = 0; + + switch (xfer_mode) { + case XFER_MW_DMA_2: + cycle_time = 250; + use_dma_info = 1; + break; + + case XFER_MW_DMA_1: + cycle_time = 250; + use_dma_info = 1; + break; + + case XFER_MW_DMA_0: + cycle_time = 480; + break; + + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + cycle_time = 480; + break; + } + + /* + * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should + * take care to note the values in the ID... + */ + if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time) + cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME]; + + drive->drive_data = cycle_time; + + printk("%s: %s selected (peak %dMB/s)\n", drive->name, + ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); +} + +static const struct ide_port_ops icside_v6_port_ops = { + .set_dma_mode = icside_set_dma_mode, + .maskproc = icside_maskproc, +}; + +static void icside_dma_host_set(ide_drive_t *drive, int on) +{ +} + +static int icside_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct expansion_card *ec = ECARD_DEV(hwif->dev); + + drive->waiting_for_dma = 0; + + disable_dma(ec->dma); + + /* Teardown mappings after DMA has completed. */ + ide_destroy_dmatable(drive); + + return get_dma_residue(ec->dma) != 0; +} + +static void icside_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct expansion_card *ec = ECARD_DEV(hwif->dev); + + /* We can not enable DMA on both channels simultaneously. */ + BUG_ON(dma_channel_active(ec->dma)); + enable_dma(ec->dma); +} + +static int icside_dma_setup(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct expansion_card *ec = ECARD_DEV(hwif->dev); + struct icside_state *state = ecard_get_drvdata(ec); + struct request *rq = hwif->hwgroup->rq; + unsigned int dma_mode; + + if (rq_data_dir(rq)) + dma_mode = DMA_MODE_WRITE; + else + dma_mode = DMA_MODE_READ; + + /* + * We can not enable DMA on both channels. + */ + BUG_ON(dma_channel_active(ec->dma)); + + hwif->sg_nents = ide_build_sglist(drive, rq); + + /* + * Ensure that we have the right interrupt routed. + */ + icside_maskproc(drive, 0); + + /* + * Route the DMA signals to the correct interface. + */ + writeb(state->sel | hwif->channel, state->ioc_base); + + /* + * Select the correct timing for this drive. + */ + set_dma_speed(ec->dma, drive->drive_data); + + /* + * Tell the DMA engine about the SG table and + * data direction. + */ + set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents); + set_dma_mode(ec->dma, dma_mode); + + drive->waiting_for_dma = 1; + + return 0; +} + +static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd) +{ + /* issue cmd to drive */ + ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD, NULL); +} + +static int icside_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct expansion_card *ec = ECARD_DEV(hwif->dev); + struct icside_state *state = ecard_get_drvdata(ec); + + return readb(state->irq_port + + (hwif->channel ? + ICS_ARCIN_V6_INTRSTAT_2 : + ICS_ARCIN_V6_INTRSTAT_1)) & 1; +} + +static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d) +{ + hwif->dmatable_cpu = NULL; + hwif->dmatable_dma = 0; + + return 0; +} + +static const struct ide_dma_ops icside_v6_dma_ops = { + .dma_host_set = icside_dma_host_set, + .dma_setup = icside_dma_setup, + .dma_exec_cmd = icside_dma_exec_cmd, + .dma_start = icside_dma_start, + .dma_end = icside_dma_end, + .dma_test_irq = icside_dma_test_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = ide_dma_lost_irq, +}; +#else +#define icside_v6_dma_ops NULL +#endif + +static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d) +{ + return -EOPNOTSUPP; +} + +static void icside_setup_ports(hw_regs_t *hw, void __iomem *base, + struct cardinfo *info, struct expansion_card *ec) +{ + unsigned long port = (unsigned long)base + info->dataoffset; + + hw->io_ports.data_addr = port; + hw->io_ports.error_addr = port + (1 << info->stepping); + hw->io_ports.nsect_addr = port + (2 << info->stepping); + hw->io_ports.lbal_addr = port + (3 << info->stepping); + hw->io_ports.lbam_addr = port + (4 << info->stepping); + hw->io_ports.lbah_addr = port + (5 << info->stepping); + hw->io_ports.device_addr = port + (6 << info->stepping); + hw->io_ports.status_addr = port + (7 << info->stepping); + hw->io_ports.ctl_addr = (unsigned long)base + info->ctrloffset; + + hw->irq = ec->irq; + hw->dev = &ec->dev; + hw->chipset = ide_acorn; +} + +static int __init +icside_register_v5(struct icside_state *state, struct expansion_card *ec) +{ + void __iomem *base; + struct ide_host *host; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + int ret; + + base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); + if (!base) + return -ENOMEM; + + state->irq_port = base; + + ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT; + ec->irqmask = 1; + + ecard_setirq(ec, &icside_ops_arcin_v5, state); + + /* + * Be on the safe side - disable interrupts + */ + icside_irqdisable_arcin_v5(ec, 0); + + icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec); + + host = ide_host_alloc(NULL, hws); + if (host == NULL) + return -ENODEV; + + state->host = host; + + ecard_set_drvdata(ec, state); + + ret = ide_host_register(host, NULL, hws); + if (ret) + goto err_free; + + return 0; +err_free: + ide_host_free(host); + ecard_set_drvdata(ec, NULL); + return ret; +} + +static const struct ide_port_info icside_v6_port_info __initdata = { + .init_dma = icside_dma_off_init, + .port_ops = &icside_v6_no_dma_port_ops, + .dma_ops = &icside_v6_dma_ops, + .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, + .mwdma_mask = ATA_MWDMA2, + .swdma_mask = ATA_SWDMA2, +}; + +static int __init +icside_register_v6(struct icside_state *state, struct expansion_card *ec) +{ + void __iomem *ioc_base, *easi_base; + struct ide_host *host; + unsigned int sel = 0; + int ret; + hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL }; + struct ide_port_info d = icside_v6_port_info; + + ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); + if (!ioc_base) { + ret = -ENOMEM; + goto out; + } + + easi_base = ioc_base; + + if (ecard_resource_flags(ec, ECARD_RES_EASI)) { + easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0); + if (!easi_base) { + ret = -ENOMEM; + goto out; + } + + /* + * Enable access to the EASI region. + */ + sel = 1 << 5; + } + + writeb(sel, ioc_base); + + ecard_setirq(ec, &icside_ops_arcin_v6, state); + + state->irq_port = easi_base; + state->ioc_base = ioc_base; + state->sel = sel; + + /* + * Be on the safe side - disable interrupts + */ + icside_irqdisable_arcin_v6(ec, 0); + + icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec); + icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec); + + host = ide_host_alloc(&d, hws); + if (host == NULL) + return -ENODEV; + + state->host = host; + + ecard_set_drvdata(ec, state); + + if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { + d.init_dma = icside_dma_init; + d.port_ops = &icside_v6_port_ops; + d.dma_ops = NULL; + } + + ret = ide_host_register(host, NULL, hws); + if (ret) + goto err_free; + + return 0; +err_free: + ide_host_free(host); + if (d.dma_ops) + free_dma(ec->dma); + ecard_set_drvdata(ec, NULL); +out: + return ret; +} + +static int __devinit +icside_probe(struct expansion_card *ec, const struct ecard_id *id) +{ + struct icside_state *state; + void __iomem *idmem; + int ret; + + ret = ecard_request_resources(ec); + if (ret) + goto out; + + state = kzalloc(sizeof(struct icside_state), GFP_KERNEL); + if (!state) { + ret = -ENOMEM; + goto release; + } + + state->type = ICS_TYPE_NOTYPE; + + idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); + if (idmem) { + unsigned int type; + + type = readb(idmem + ICS_IDENT_OFFSET) & 1; + type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1; + type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2; + type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3; + ecardm_iounmap(ec, idmem); + + state->type = type; + } + + switch (state->type) { + case ICS_TYPE_A3IN: + dev_warn(&ec->dev, "A3IN unsupported\n"); + ret = -ENODEV; + break; + + case ICS_TYPE_A3USER: + dev_warn(&ec->dev, "A3USER unsupported\n"); + ret = -ENODEV; + break; + + case ICS_TYPE_V5: + ret = icside_register_v5(state, ec); + break; + + case ICS_TYPE_V6: + ret = icside_register_v6(state, ec); + break; + + default: + dev_warn(&ec->dev, "unknown interface type\n"); + ret = -ENODEV; + break; + } + + if (ret == 0) + goto out; + + kfree(state); + release: + ecard_release_resources(ec); + out: + return ret; +} + +static void __devexit icside_remove(struct expansion_card *ec) +{ + struct icside_state *state = ecard_get_drvdata(ec); + + switch (state->type) { + case ICS_TYPE_V5: + /* FIXME: tell IDE to stop using the interface */ + + /* Disable interrupts */ + icside_irqdisable_arcin_v5(ec, 0); + break; + + case ICS_TYPE_V6: + /* FIXME: tell IDE to stop using the interface */ + if (ec->dma != NO_DMA) + free_dma(ec->dma); + + /* Disable interrupts */ + icside_irqdisable_arcin_v6(ec, 0); + + /* Reset the ROM pointer/EASI selection */ + writeb(0, state->ioc_base); + break; + } + + ecard_set_drvdata(ec, NULL); + + kfree(state); + ecard_release_resources(ec); +} + +static void icside_shutdown(struct expansion_card *ec) +{ + struct icside_state *state = ecard_get_drvdata(ec); + unsigned long flags; + + /* + * Disable interrupts from this card. We need to do + * this before disabling EASI since we may be accessing + * this register via that region. + */ + local_irq_save(flags); + ec->ops->irqdisable(ec, 0); + local_irq_restore(flags); + + /* + * Reset the ROM pointer so that we can read the ROM + * after a soft reboot. This also disables access to + * the IDE taskfile via the EASI region. + */ + if (state->ioc_base) + writeb(0, state->ioc_base); +} + +static const struct ecard_id icside_ids[] = { + { MANU_ICS, PROD_ICS_IDE }, + { MANU_ICS2, PROD_ICS2_IDE }, + { 0xffff, 0xffff } +}; + +static struct ecard_driver icside_driver = { + .probe = icside_probe, + .remove = __devexit_p(icside_remove), + .shutdown = icside_shutdown, + .id_table = icside_ids, + .drv = { + .name = "icside", + }, +}; + +static int __init icside_init(void) +{ + return ecard_register_driver(&icside_driver); +} + +static void __exit icside_exit(void); +{ + ecard_unregister_driver(&icside_driver); +} + +MODULE_AUTHOR("Russell King "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ICS IDE driver"); + +module_init(icside_init); +module_exit(icside_exit); diff --git a/drivers/ide/ide-4drives.c b/drivers/ide/ide-4drives.c new file mode 100644 index 0000000..9e85b1e --- /dev/null +++ b/drivers/ide/ide-4drives.c @@ -0,0 +1,63 @@ + +#include +#include +#include +#include + +#define DRV_NAME "ide-4drives" + +static int probe_4drives; + +module_param_named(probe, probe_4drives, bool, 0); +MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port"); + +static void ide_4drives_init_dev(ide_drive_t *drive) +{ + if (drive->hwif->channel) + drive->select ^= 0x20; +} + +static const struct ide_port_ops ide_4drives_port_ops = { + .init_dev = ide_4drives_init_dev, +}; + +static const struct ide_port_info ide_4drives_port_info = { + .port_ops = &ide_4drives_port_ops, + .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA, +}; + +static int __init ide_4drives_init(void) +{ + unsigned long base = 0x1f0, ctl = 0x3f6; + hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL }; + + if (probe_4drives == 0) + return -ENODEV; + + if (!request_region(base, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, base, base + 7); + return -EBUSY; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(base, 8); + return -EBUSY; + } + + memset(&hw, 0, sizeof(hw)); + + ide_std_init_ports(&hw, base, ctl); + hw.irq = 14; + hw.chipset = ide_4drives; + + return ide_host_add(&ide_4drives_port_info, hws, NULL); +} + +module_init(ide_4drives_init); + +MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); +MODULE_DESCRIPTION("generic IDE chipset with 4 drives/port support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c new file mode 100644 index 0000000..cb199c8 --- /dev/null +++ b/drivers/ide/ide-cs.c @@ -0,0 +1,472 @@ +/*====================================================================== + + A driver for PCMCIA IDE/ATA disk cards + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU General Public License version 2 (the "GPL"), in + which case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "ide-cs" + +/*====================================================================*/ + +/* Module parameters */ + +MODULE_AUTHOR("David Hinds "); +MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver"); +MODULE_LICENSE("Dual MPL/GPL"); + +#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) + +#ifdef CONFIG_PCMCIA_DEBUG +INT_MODULE_PARM(pc_debug, 0); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +typedef struct ide_info_t { + struct pcmcia_device *p_dev; + struct ide_host *host; + int ndev; + dev_node_t node; +} ide_info_t; + +static void ide_release(struct pcmcia_device *); +static int ide_config(struct pcmcia_device *); + +static void ide_detach(struct pcmcia_device *p_dev); + + + + +/*====================================================================== + + ide_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + +======================================================================*/ + +static int ide_probe(struct pcmcia_device *link) +{ + ide_info_t *info; + + DEBUG(0, "ide_attach()\n"); + + /* Create new ide device */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->p_dev = link; + link->priv = info; + + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = 3; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.IntType = INT_MEMORY_AND_IO; + + return ide_config(link); +} /* ide_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void ide_detach(struct pcmcia_device *link) +{ + ide_info_t *info = link->priv; + ide_hwif_t *hwif = info->host->ports[0]; + unsigned long data_addr, ctl_addr; + + DEBUG(0, "ide_detach(0x%p)\n", link); + + data_addr = hwif->io_ports.data_addr; + ctl_addr = hwif->io_ports.ctl_addr; + + ide_release(link); + + release_region(ctl_addr, 1); + release_region(data_addr, 8); + + kfree(info); +} /* ide_detach */ + +static const struct ide_port_ops idecs_port_ops = { + .quirkproc = ide_undecoded_slave, +}; + +static const struct ide_port_info idecs_port_info = { + .port_ops = &idecs_port_ops, + .host_flags = IDE_HFLAG_NO_DMA, +}; + +static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, + unsigned long irq, struct pcmcia_device *handle) +{ + struct ide_host *host; + ide_hwif_t *hwif; + int i, rc; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + + if (!request_region(io, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, io, io + 7); + return NULL; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(io, 8); + return NULL; + } + + memset(&hw, 0, sizeof(hw)); + ide_std_init_ports(&hw, io, ctl); + hw.irq = irq; + hw.chipset = ide_pci; + hw.dev = &handle->dev; + + rc = ide_host_add(&idecs_port_info, hws, &host); + if (rc) + goto out_release; + + hwif = host->ports[0]; + + if (hwif->present) + return host; + + /* retry registration in case device is still spinning up */ + for (i = 0; i < 10; i++) { + msleep(100); + ide_port_scan(hwif); + if (hwif->present) + return host; + } + + return host; + +out_release: + release_region(ctl, 1); + release_region(io, 8); + return NULL; +} + +/*====================================================================== + + ide_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + ide device available to the system. + +======================================================================*/ + +#define CS_CHECK(fn, ret) \ +do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) + +struct pcmcia_config_check { + unsigned long ctl_base; + int skip_vcc; + int is_kme; +}; + +static int pcmcia_check_one_config(struct pcmcia_device *pdev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data) +{ + struct pcmcia_config_check *stk = priv_data; + + /* Check for matching Vcc, unless we're desperate */ + if (!stk->skip_vcc) { + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) + return -ENODEV; + } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) + return -ENODEV; + } + } + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) + pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) + pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; + + if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; + pdev->conf.ConfigIndex = cfg->index; + pdev->io.BasePort1 = io->win[0].base; + pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + if (!(io->flags & CISTPL_IO_16BIT)) + pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + if (io->nwin == 2) { + pdev->io.NumPorts1 = 8; + pdev->io.BasePort2 = io->win[1].base; + pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1; + if (pcmcia_request_io(pdev, &pdev->io) != 0) + return -ENODEV; + stk->ctl_base = pdev->io.BasePort2; + } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { + pdev->io.NumPorts1 = io->win[0].len; + pdev->io.NumPorts2 = 0; + if (pcmcia_request_io(pdev, &pdev->io) != 0) + return -ENODEV; + stk->ctl_base = pdev->io.BasePort1 + 0x0e; + } else + return -ENODEV; + /* If we've got this far, we're done */ + return 0; + } + return -ENODEV; +} + +static int ide_config(struct pcmcia_device *link) +{ + ide_info_t *info = link->priv; + struct pcmcia_config_check *stk = NULL; + int last_ret = 0, last_fn = 0, is_kme = 0; + unsigned long io_base, ctl_base; + struct ide_host *host; + + DEBUG(0, "ide_config(0x%p)\n", link); + + is_kme = ((link->manf_id == MANFID_KME) && + ((link->card_id == PRODID_KME_KXLC005_A) || + (link->card_id == PRODID_KME_KXLC005_B))); + + stk = kzalloc(sizeof(*stk), GFP_KERNEL); + if (!stk) + goto err_mem; + stk->is_kme = is_kme; + stk->skip_vcc = io_base = ctl_base = 0; + + if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) { + stk->skip_vcc = 1; + if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) + goto failed; /* No suitable config found */ + } + io_base = link->io.BasePort1; + ctl_base = stk->ctl_base; + + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); + + /* disable drive interrupts during IDE probe */ + outb(0x02, ctl_base); + + /* special setup for KXLC005 card */ + if (is_kme) + outb(0x81, ctl_base+1); + + host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); + if (host == NULL && link->io.NumPorts1 == 0x20) { + outb(0x02, ctl_base + 0x10); + host = idecs_register(io_base + 0x10, ctl_base + 0x10, + link->irq.AssignedIRQ, link); + } + + if (host == NULL) + goto failed; + + info->ndev = 1; + sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2); + info->node.major = host->ports[0]->major; + info->node.minor = 0; + info->host = host; + link->dev_node = &info->node; + printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", + info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); + + kfree(stk); + return 0; + +err_mem: + printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); + goto failed; + +cs_failed: + cs_error(link, last_fn, last_ret); +failed: + kfree(stk); + ide_release(link); + return -ENODEV; +} /* ide_config */ + +/*====================================================================== + + After a card is removed, ide_release() will unregister the net + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +static void ide_release(struct pcmcia_device *link) +{ + ide_info_t *info = link->priv; + struct ide_host *host = info->host; + + DEBUG(0, "ide_release(0x%p)\n", link); + + if (info->ndev) + /* FIXME: if this fails we need to queue the cleanup somehow + -- need to investigate the required PCMCIA magic */ + ide_host_remove(host); + + info->ndev = 0; + + pcmcia_disable_device(link); +} /* ide_release */ + + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the ide drivers from + talking to the ports. + +======================================================================*/ + +static struct pcmcia_device_id ide_ids[] = { + PCMCIA_DEVICE_FUNC_ID(4), + PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ + PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ + PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ + PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ + PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), + PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904), + PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ + PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */ + PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */ + PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ + PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), + PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ + PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ + PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), + PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */ + PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */ + PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), + PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74), + PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), + PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), + PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), + PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), + PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), + PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), + PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf), + PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), + PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), + PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), + PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), + PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), + PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), + PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), + PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), + PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), + PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), + PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), + PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), + PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), + PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee), + PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c), + PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), + PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), + PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883), + PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d), + PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), + PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), + PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), + PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32), + PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), + PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), + PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), + PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), + PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), + PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), + PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, ide_ids); + +static struct pcmcia_driver ide_cs_driver = { + .owner = THIS_MODULE, + .drv = { + .name = "ide-cs", + }, + .probe = ide_probe, + .remove = ide_detach, + .id_table = ide_ids, +}; + +static int __init init_ide_cs(void) +{ + return pcmcia_register_driver(&ide_cs_driver); +} + +static void __exit exit_ide_cs(void) +{ + pcmcia_unregister_driver(&ide_cs_driver); +} + +late_initcall(init_ide_cs); +module_exit(exit_ide_cs); diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c new file mode 100644 index 0000000..e2cdd2e --- /dev/null +++ b/drivers/ide/ide-h8300.c @@ -0,0 +1,217 @@ +/* + * H8/300 generic IDE interface + */ + +#include +#include + +#include +#include + +#define DRV_NAME "ide-h8300" + +#define bswap(d) \ +({ \ + u16 r; \ + __asm__("mov.b %w1,r1h\n\t" \ + "mov.b %x1,r1l\n\t" \ + "mov.w r1,%0" \ + :"=r"(r) \ + :"r"(d) \ + :"er1"); \ + (r); \ +}) + +static void mm_outw(u16 d, unsigned long a) +{ + __asm__("mov.b %w0,r2h\n\t" + "mov.b %x0,r2l\n\t" + "mov.w r2,@%1" + : + :"r"(d),"r"(a) + :"er2"); +} + +static u16 mm_inw(unsigned long a) +{ + register u16 r __asm__("er0"); + __asm__("mov.w @%1,r2\n\t" + "mov.b r2l,%x0\n\t" + "mov.b r2h,%w0" + :"=r"(r) + :"r"(a) + :"er2"); + return r; +} + +static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) + mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + outb((tf->device & HIHI) | drive->select, + io_ports->device_addr); +} + +static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data = mm_inw(io_ports->data_addr); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_FEATURE) + tf->feature = inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = inb(io_ports->lbah_addr); + } +} + +static void mm_outsw(unsigned long addr, void *buf, u32 len) +{ + unsigned short *bp = (unsigned short *)buf; + for (; len > 0; len--, bp++) + *(volatile u16 *)addr = bswap(*bp); +} + +static void mm_insw(unsigned long addr, void *buf, u32 len) +{ + unsigned short *bp = (unsigned short *)buf; + for (; len > 0; len--, bp++) + *bp = bswap(*(volatile u16 *)addr); +} + +static void h8300_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); +} + +static void h8300_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); +} + +static const struct ide_tp_ops h8300_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + .read_sff_dma_status = ide_read_sff_dma_status, + + .set_irq = ide_set_irq, + + .tf_load = h8300_tf_load, + .tf_read = h8300_tf_read, + + .input_data = h8300_input_data, + .output_data = h8300_output_data, +}; + +#define H8300_IDE_GAP (2) + +static inline void hw_setup(hw_regs_t *hw) +{ + int i; + + memset(hw, 0, sizeof(hw_regs_t)); + for (i = 0; i <= 7; i++) + hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; + hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT; + hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; + hw->chipset = ide_generic; +} + +static const struct ide_port_info h8300_port_info = { + .tp_ops = &h8300_tp_ops, + .host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA, +}; + +static int __init h8300_ide_init(void) +{ + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + + printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n"); + + if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300")) + goto out_busy; + if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) { + release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8); + goto out_busy; + } + + hw_setup(&hw); + + return ide_host_add(&h8300_port_info, hws, NULL); + +out_busy: + printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); + + return -EBUSY; +} + +module_init(h8300_ide_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide_arm.c b/drivers/ide/ide_arm.c new file mode 100644 index 0000000..f728f29 --- /dev/null +++ b/drivers/ide/ide_arm.c @@ -0,0 +1,56 @@ +/* + * ARM default IDE host driver + * + * Copyright (C) 2004 Bartlomiej Zolnierkiewicz + * Based on code by: Russell King, Ian Molton and Alexander Schulz. + * + * May be copied or modified under the terms of the GNU General Public License. + */ + +#include +#include +#include + +#include + +#define DRV_NAME "ide_arm" + +#ifdef CONFIG_ARCH_CLPS7500 +# include +# +# define IDE_ARM_IO (ISASLOT_IO + 0x1f0) +# define IDE_ARM_IRQ IRQ_ISA_14 +#else +# define IDE_ARM_IO 0x1f0 +# define IDE_ARM_IRQ IRQ_HARDDISK +#endif + +static int __init ide_arm_init(void) +{ + unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + + if (!request_region(base, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, base, base + 7); + return -EBUSY; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(base, 8); + return -EBUSY; + } + + memset(&hw, 0, sizeof(hw)); + ide_std_init_ports(&hw, base, ctl); + hw.irq = IDE_ARM_IRQ; + hw.chipset = ide_generic; + + return ide_host_add(NULL, hws, NULL); +} + +module_init(ide_arm_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide_platform.c b/drivers/ide/ide_platform.c new file mode 100644 index 0000000..051b4ab --- /dev/null +++ b/drivers/ide/ide_platform.c @@ -0,0 +1,147 @@ +/* + * Platform IDE driver + * + * Copyright (C) 2007 MontaVista Software + * + * Maintainer: Kumar Gala + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __devinit plat_ide_setup_ports(hw_regs_t *hw, + void __iomem *base, + void __iomem *ctrl, + struct pata_platform_info *pdata, + int irq) +{ + unsigned long port = (unsigned long)base; + int i; + + hw->io_ports.data_addr = port; + + port += (1 << pdata->ioport_shift); + for (i = 1; i <= 7; + i++, port += (1 << pdata->ioport_shift)) + hw->io_ports_array[i] = port; + + hw->io_ports.ctl_addr = (unsigned long)ctrl; + + hw->irq = irq; + + hw->chipset = ide_generic; +} + +static const struct ide_port_info platform_ide_port_info = { + .host_flags = IDE_HFLAG_NO_DMA, +}; + +static int __devinit plat_ide_probe(struct platform_device *pdev) +{ + struct resource *res_base, *res_alt, *res_irq; + void __iomem *base, *alt_base; + struct pata_platform_info *pdata; + struct ide_host *host; + int ret = 0, mmio = 0; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + struct ide_port_info d = platform_ide_port_info; + + pdata = pdev->dev.platform_data; + + /* get a pointer to the register memory */ + res_base = platform_get_resource(pdev, IORESOURCE_IO, 0); + res_alt = platform_get_resource(pdev, IORESOURCE_IO, 1); + + if (!res_base || !res_alt) { + res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res_alt = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res_base || !res_alt) { + ret = -ENOMEM; + goto out; + } + mmio = 1; + } + + res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res_irq) { + ret = -EINVAL; + goto out; + } + + if (mmio) { + base = devm_ioremap(&pdev->dev, + res_base->start, res_base->end - res_base->start + 1); + alt_base = devm_ioremap(&pdev->dev, + res_alt->start, res_alt->end - res_alt->start + 1); + } else { + base = devm_ioport_map(&pdev->dev, + res_base->start, res_base->end - res_base->start + 1); + alt_base = devm_ioport_map(&pdev->dev, + res_alt->start, res_alt->end - res_alt->start + 1); + } + + memset(&hw, 0, sizeof(hw)); + plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start); + hw.dev = &pdev->dev; + + if (mmio) + d.host_flags |= IDE_HFLAG_MMIO; + + ret = ide_host_add(&d, hws, &host); + if (ret) + goto out; + + platform_set_drvdata(pdev, host); + + return 0; + +out: + return ret; +} + +static int __devexit plat_ide_remove(struct platform_device *pdev) +{ + struct ide_host *host = pdev->dev.driver_data; + + ide_host_remove(host); + + return 0; +} + +static struct platform_driver platform_ide_driver = { + .driver = { + .name = "pata_platform", + .owner = THIS_MODULE, + }, + .probe = plat_ide_probe, + .remove = __devexit_p(plat_ide_remove), +}; + +static int __init platform_ide_init(void) +{ + return platform_driver_register(&platform_ide_driver); +} + +static void __exit platform_ide_exit(void) +{ + platform_driver_unregister(&platform_ide_driver); +} + +MODULE_DESCRIPTION("Platform IDE driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pata_platform"); + +module_init(platform_ide_init); +module_exit(platform_ide_exit); diff --git a/drivers/ide/it8213.c b/drivers/ide/it8213.c new file mode 100644 index 0000000..7c2feeb --- /dev/null +++ b/drivers/ide/it8213.c @@ -0,0 +1,216 @@ +/* + * ITE 8213 IDE driver + * + * Copyright (C) 2006 Jack Lee + * Copyright (C) 2006 Alan Cox + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + */ + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "it8213" + +/** + * it8213_set_pio_mode - set host controller for PIO mode + * @drive: drive + * @pio: PIO mode number + * + * Set the interface PIO mode. + */ + +static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + int is_slave = drive->dn & 1; + int master_port = 0x40; + int slave_port = 0x44; + unsigned long flags; + u16 master_data; + u8 slave_data; + static DEFINE_SPINLOCK(tune_lock); + int control = 0; + + static const u8 timings[][2] = { + { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + spin_lock_irqsave(&tune_lock, flags); + pci_read_config_word(dev, master_port, &master_data); + + if (pio > 1) + control |= 1; /* Programmable timing on */ + if (drive->media != ide_disk) + control |= 4; /* ATAPI */ + if (pio > 2) + control |= 2; /* IORDY */ + if (is_slave) { + master_data |= 0x4000; + master_data &= ~0x0070; + if (pio > 1) + master_data = master_data | (control << 4); + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data = slave_data & 0xf0; + slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1]; + } else { + master_data &= ~0x3307; + if (pio > 1) + master_data = master_data | control; + master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); + } + pci_write_config_word(dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(dev, slave_port, slave_data); + spin_unlock_irqrestore(&tune_lock, flags); +} + +/** + * it8213_set_dma_mode - set host controller for DMA mode + * @drive: drive + * @speed: DMA mode + * + * Tune the ITE chipset for the DMA mode. + */ + +static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 maslave = 0x40; + int a_speed = 3 << (drive->dn * 4); + int u_flag = 1 << drive->dn; + int v_flag = 0x01 << drive->dn; + int w_flag = 0x10 << drive->dn; + int u_speed = 0; + u16 reg4042, reg4a; + u8 reg48, reg54, reg55; + + pci_read_config_word(dev, maslave, ®4042); + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); + + if (speed >= XFER_UDMA_0) { + u8 udma = speed - XFER_UDMA_0; + + u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4); + + if (!(reg48 & u_flag)) + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + if (speed >= XFER_UDMA_5) + pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + else + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + + if ((reg4a & a_speed) != u_speed) + pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); + if (speed > XFER_UDMA_2) { + if (!(reg54 & v_flag)) + pci_write_config_byte(dev, 0x54, reg54 | v_flag); + } else + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + } else { + const u8 mwdma_to_pio[] = { 0, 3, 4 }; + u8 pio; + + if (reg48 & u_flag) + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + if (reg54 & v_flag) + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + if (reg55 & w_flag) + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + + if (speed >= XFER_MW_DMA_0) + pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; + else + pio = 2; /* only SWDMA2 is allowed */ + + it8213_set_pio_mode(drive, pio); + } +} + +static u8 it8213_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 reg42h = 0; + + pci_read_config_byte(dev, 0x42, ®42h); + + return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + +static const struct ide_port_ops it8213_port_ops = { + .set_pio_mode = it8213_set_pio_mode, + .set_dma_mode = it8213_set_dma_mode, + .cable_detect = it8213_cable_detect, +}; + +static const struct ide_port_info it8213_chipset __devinitdata = { + .name = DRV_NAME, + .enablebits = { {0x41, 0x80, 0x80} }, + .port_ops = &it8213_port_ops, + .host_flags = IDE_HFLAG_SINGLE, + .pio_mask = ATA_PIO4, + .swdma_mask = ATA_SWDMA2_ONLY, + .mwdma_mask = ATA_MWDMA12_ONLY, + .udma_mask = ATA_UDMA6, +}; + +/** + * it8213_init_one - pci layer discovery entry + * @dev: PCI device + * @id: ident table entry + * + * Called by the PCI code when it finds an ITE8213 controller. As + * this device follows the standard interfaces we can use the + * standard helper functions to do almost all the work for us. + */ + +static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + return ide_pci_init_one(dev, &it8213_chipset, NULL); +} + +static const struct pci_device_id it8213_pci_tbl[] = { + { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), 0 }, + { 0, }, +}; + +MODULE_DEVICE_TABLE(pci, it8213_pci_tbl); + +static struct pci_driver it8213_pci_driver = { + .name = "ITE8213_IDE", + .id_table = it8213_pci_tbl, + .probe = it8213_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init it8213_ide_init(void) +{ + return ide_pci_register_driver(&it8213_pci_driver); +} + +static void __exit it8213_ide_exit(void) +{ + pci_unregister_driver(&it8213_pci_driver); +} + +module_init(it8213_ide_init); +module_exit(it8213_ide_exit); + +MODULE_AUTHOR("Jack Lee, Alan Cox"); +MODULE_DESCRIPTION("PCI driver module for the ITE 8213"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c new file mode 100644 index 0000000..995e18b --- /dev/null +++ b/drivers/ide/it821x.c @@ -0,0 +1,706 @@ +/* + * Copyright (C) 2004 Red Hat + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * + * May be copied or modified under the terms of the GNU General Public License + * Based in part on the ITE vendor provided SCSI driver. + * + * Documentation available from + * http://www.ite.com.tw/pc/IT8212F_V04.pdf + * Some other documents are NDA. + * + * The ITE8212 isn't exactly a standard IDE controller. It has two + * modes. In pass through mode then it is an IDE controller. In its smart + * mode its actually quite a capable hardware raid controller disguised + * as an IDE controller. Smart mode only understands DMA read/write and + * identify, none of the fancier commands apply. The IT8211 is identical + * in other respects but lacks the raid mode. + * + * Errata: + * o Rev 0x10 also requires master/slave hold the same DMA timings and + * cannot do ATAPI MWDMA. + * o The identify data for raid volumes lacks CHS info (technically ok) + * but also fails to set the LBA28 and other bits. We fix these in + * the IDE probe quirk code. + * o If you write LBA48 sized I/O's (ie > 256 sector) in smart mode + * raid then the controller firmware dies + * o Smart mode without RAID doesn't clear all the necessary identify + * bits to reduce the command set to the one used + * + * This has a few impacts on the driver + * - In pass through mode we do all the work you would expect + * - In smart mode the clocking set up is done by the controller generally + * but we must watch the other limits and filter. + * - There are a few extra vendor commands that actually talk to the + * controller but only work PIO with no IRQ. + * + * Vendor areas of the identify block in smart mode are used for the + * timing and policy set up. Each HDD in raid mode also has a serial + * block on the disk. The hardware extra commands are get/set chip status, + * rebuild, get rebuild status. + * + * In Linux the driver supports pass through mode as if the device was + * just another IDE controller. If the smart mode is running then + * volumes are managed by the controller firmware and each IDE "disk" + * is a raid volume. Even more cute - the controller can do automated + * hotplug and rebuild. + * + * The pass through controller itself is a little demented. It has a + * flaw that it has a single set of PIO/MWDMA timings per channel so + * non UDMA devices restrict each others performance. It also has a + * single clock source per channel so mixed UDMA100/133 performance + * isn't perfect and we have to pick a clock. Thankfully none of this + * matters in smart mode. ATAPI DMA is not currently supported. + * + * It seems the smart mode is a win for RAID1/RAID10 but otherwise not. + * + * TODO + * - ATAPI UDMA is ok but not MWDMA it seems + * - RAID configuration ioctls + * - Move to libata once it grows up + */ + +#include +#include +#include +#include +#include + +#define DRV_NAME "it821x" + +struct it821x_dev +{ + unsigned int smart:1, /* Are we in smart raid mode */ + timing10:1; /* Rev 0x10 */ + u8 clock_mode; /* 0, ATA_50 or ATA_66 */ + u8 want[2][2]; /* Mode/Pri log for master slave */ + /* We need these for switching the clock when DMA goes on/off + The high byte is the 66Mhz timing */ + u16 pio[2]; /* Cached PIO values */ + u16 mwdma[2]; /* Cached MWDMA values */ + u16 udma[2]; /* Cached UDMA values (per drive) */ +}; + +#define ATA_66 0 +#define ATA_50 1 +#define ATA_ANY 2 + +#define UDMA_OFF 0 +#define MWDMA_OFF 0 + +/* + * We allow users to force the card into non raid mode without + * flashing the alternative BIOS. This is also necessary right now + * for embedded platforms that cannot run a PC BIOS but are using this + * device. + */ + +static int it8212_noraid; + +/** + * it821x_program - program the PIO/MWDMA registers + * @drive: drive to tune + * @timing: timing info + * + * Program the PIO/MWDMA timing for this channel according to the + * current clock. + */ + +static void it821x_program(ide_drive_t *drive, u16 timing) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct it821x_dev *itdev = ide_get_hwifdata(hwif); + int channel = hwif->channel; + u8 conf; + + /* Program PIO/MWDMA timing bits */ + if(itdev->clock_mode == ATA_66) + conf = timing >> 8; + else + conf = timing & 0xFF; + + pci_write_config_byte(dev, 0x54 + 4 * channel, conf); +} + +/** + * it821x_program_udma - program the UDMA registers + * @drive: drive to tune + * @timing: timing info + * + * Program the UDMA timing for this drive according to the + * current clock. + */ + +static void it821x_program_udma(ide_drive_t *drive, u16 timing) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct it821x_dev *itdev = ide_get_hwifdata(hwif); + int channel = hwif->channel; + u8 unit = drive->dn & 1, conf; + + /* Program UDMA timing bits */ + if(itdev->clock_mode == ATA_66) + conf = timing >> 8; + else + conf = timing & 0xFF; + + if (itdev->timing10 == 0) + pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf); + else { + pci_write_config_byte(dev, 0x56 + 4 * channel, conf); + pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf); + } +} + +/** + * it821x_clock_strategy + * @drive: drive to set up + * + * Select between the 50 and 66Mhz base clocks to get the best + * results for this interface. + */ + +static void it821x_clock_strategy(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct it821x_dev *itdev = ide_get_hwifdata(hwif); + ide_drive_t *pair; + int clock, altclock, sel = 0; + u8 unit = drive->dn & 1, v; + + pair = &hwif->drives[1 - unit]; + + if(itdev->want[0][0] > itdev->want[1][0]) { + clock = itdev->want[0][1]; + altclock = itdev->want[1][1]; + } else { + clock = itdev->want[1][1]; + altclock = itdev->want[0][1]; + } + + /* + * if both clocks can be used for the mode with the higher priority + * use the clock needed by the mode with the lower priority + */ + if (clock == ATA_ANY) + clock = altclock; + + /* Nobody cares - keep the same clock */ + if(clock == ATA_ANY) + return; + /* No change */ + if(clock == itdev->clock_mode) + return; + + /* Load this into the controller ? */ + if(clock == ATA_66) + itdev->clock_mode = ATA_66; + else { + itdev->clock_mode = ATA_50; + sel = 1; + } + + pci_read_config_byte(dev, 0x50, &v); + v &= ~(1 << (1 + hwif->channel)); + v |= sel << (1 + hwif->channel); + pci_write_config_byte(dev, 0x50, v); + + /* + * Reprogram the UDMA/PIO of the pair drive for the switch + * MWDMA will be dealt with by the dma switcher + */ + if(pair && itdev->udma[1-unit] != UDMA_OFF) { + it821x_program_udma(pair, itdev->udma[1-unit]); + it821x_program(pair, itdev->pio[1-unit]); + } + /* + * Reprogram the UDMA/PIO of our drive for the switch. + * MWDMA will be dealt with by the dma switcher + */ + if(itdev->udma[unit] != UDMA_OFF) { + it821x_program_udma(drive, itdev->udma[unit]); + it821x_program(drive, itdev->pio[unit]); + } +} + +/** + * it821x_set_pio_mode - set host controller for PIO mode + * @drive: drive + * @pio: PIO mode number + * + * Tune the host to the desired PIO mode taking into the consideration + * the maximum PIO mode supported by the other device on the cable. + */ + +static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = drive->hwif; + struct it821x_dev *itdev = ide_get_hwifdata(hwif); + ide_drive_t *pair; + u8 unit = drive->dn & 1, set_pio = pio; + + /* Spec says 89 ref driver uses 88 */ + static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; + static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; + + pair = &hwif->drives[1 - unit]; + + /* + * Compute the best PIO mode we can for a given device. We must + * pick a speed that does not cause problems with the other device + * on the cable. + */ + if (pair) { + u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4); + /* trim PIO to the slowest of the master/slave */ + if (pair_pio < set_pio) + set_pio = pair_pio; + } + + /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ + itdev->want[unit][1] = pio_want[set_pio]; + itdev->want[unit][0] = 1; /* PIO is lowest priority */ + itdev->pio[unit] = pio_timings[set_pio]; + it821x_clock_strategy(drive); + it821x_program(drive, itdev->pio[unit]); +} + +/** + * it821x_tune_mwdma - tune a channel for MWDMA + * @drive: drive to set up + * @mode_wanted: the target operating mode + * + * Load the timing settings for this device mode into the + * controller when doing MWDMA in pass through mode. The caller + * must manage the whole lack of per device MWDMA/PIO timings and + * the shared MWDMA/PIO timing register. + */ + +static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif); + u8 unit = drive->dn & 1, channel = hwif->channel, conf; + + static u16 dma[] = { 0x8866, 0x3222, 0x3121 }; + static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY }; + + itdev->want[unit][1] = mwdma_want[mode_wanted]; + itdev->want[unit][0] = 2; /* MWDMA is low priority */ + itdev->mwdma[unit] = dma[mode_wanted]; + itdev->udma[unit] = UDMA_OFF; + + /* UDMA bits off - Revision 0x10 do them in pairs */ + pci_read_config_byte(dev, 0x50, &conf); + if (itdev->timing10) + conf |= channel ? 0x60: 0x18; + else + conf |= 1 << (3 + 2 * channel + unit); + pci_write_config_byte(dev, 0x50, conf); + + it821x_clock_strategy(drive); + /* FIXME: do we need to program this ? */ + /* it821x_program(drive, itdev->mwdma[unit]); */ +} + +/** + * it821x_tune_udma - tune a channel for UDMA + * @drive: drive to set up + * @mode_wanted: the target operating mode + * + * Load the timing settings for this device mode into the + * controller when doing UDMA modes in pass through. + */ + +static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct it821x_dev *itdev = ide_get_hwifdata(hwif); + u8 unit = drive->dn & 1, channel = hwif->channel, conf; + + static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 }; + static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 }; + + itdev->want[unit][1] = udma_want[mode_wanted]; + itdev->want[unit][0] = 3; /* UDMA is high priority */ + itdev->mwdma[unit] = MWDMA_OFF; + itdev->udma[unit] = udma[mode_wanted]; + if(mode_wanted >= 5) + itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */ + + /* UDMA on. Again revision 0x10 must do the pair */ + pci_read_config_byte(dev, 0x50, &conf); + if (itdev->timing10) + conf &= channel ? 0x9F: 0xE7; + else + conf &= ~ (1 << (3 + 2 * channel + unit)); + pci_write_config_byte(dev, 0x50, conf); + + it821x_clock_strategy(drive); + it821x_program_udma(drive, itdev->udma[unit]); + +} + +/** + * it821x_dma_read - DMA hook + * @drive: drive for DMA + * + * The IT821x has a single timing register for MWDMA and for PIO + * operations. As we flip back and forth we have to reload the + * clock. In addition the rev 0x10 device only works if the same + * timing value is loaded into the master and slave UDMA clock + * so we must also reload that. + * + * FIXME: we could figure out in advance if we need to do reloads + */ + +static void it821x_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct it821x_dev *itdev = ide_get_hwifdata(hwif); + u8 unit = drive->dn & 1; + + if(itdev->mwdma[unit] != MWDMA_OFF) + it821x_program(drive, itdev->mwdma[unit]); + else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10) + it821x_program_udma(drive, itdev->udma[unit]); + ide_dma_start(drive); +} + +/** + * it821x_dma_write - DMA hook + * @drive: drive for DMA stop + * + * The IT821x has a single timing register for MWDMA and for PIO + * operations. As we flip back and forth we have to reload the + * clock. + */ + +static int it821x_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct it821x_dev *itdev = ide_get_hwifdata(hwif); + int ret = ide_dma_end(drive); + u8 unit = drive->dn & 1; + + if(itdev->mwdma[unit] != MWDMA_OFF) + it821x_program(drive, itdev->pio[unit]); + return ret; +} + +/** + * it821x_set_dma_mode - set host controller for DMA mode + * @drive: drive + * @speed: DMA mode + * + * Tune the ITE chipset for the desired DMA mode. + */ + +static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + /* + * MWDMA tuning is really hard because our MWDMA and PIO + * timings are kept in the same place. We can switch in the + * host dma on/off callbacks. + */ + if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_6) + it821x_tune_udma(drive, speed - XFER_UDMA_0); + else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) + it821x_tune_mwdma(drive, speed - XFER_MW_DMA_0); +} + +/** + * it821x_cable_detect - cable detection + * @hwif: interface to check + * + * Check for the presence of an ATA66 capable cable on the + * interface. Problematic as it seems some cards don't have + * the needed logic onboard. + */ + +static u8 it821x_cable_detect(ide_hwif_t *hwif) +{ + /* The reference driver also only does disk side */ + return ATA_CBL_PATA80; +} + +/** + * it821x_quirkproc - post init callback + * @drive: drive + * + * This callback is run after the drive has been probed but + * before anything gets attached. It allows drivers to do any + * final tuning that is needed, or fixups to work around bugs. + */ + +static void it821x_quirkproc(ide_drive_t *drive) +{ + struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif); + u16 *id = drive->id; + + if (!itdev->smart) { + /* + * If we are in pass through mode then not much + * needs to be done, but we do bother to clear the + * IRQ mask as we may well be in PIO (eg rev 0x10) + * for now and we know unmasking is safe on this chipset. + */ + drive->dev_flags |= IDE_DFLAG_UNMASK; + } else { + /* + * Perform fixups on smart mode. We need to "lose" some + * capabilities the firmware lacks but does not filter, and + * also patch up some capability bits that it forgets to set + * in RAID mode. + */ + + /* Check for RAID v native */ + if (strstr((char *)&id[ATA_ID_PROD], + "Integrated Technology Express")) { + /* In raid mode the ident block is slightly buggy + We need to set the bits so that the IDE layer knows + LBA28. LBA48 and DMA ar valid */ + id[ATA_ID_CAPABILITY] |= (3 << 8); /* LBA28, DMA */ + id[ATA_ID_COMMAND_SET_2] |= 0x0400; /* LBA48 valid */ + id[ATA_ID_CFS_ENABLE_2] |= 0x0400; /* LBA48 on */ + /* Reporting logic */ + printk(KERN_INFO "%s: IT8212 %sRAID %d volume", + drive->name, id[147] ? "Bootable " : "", + id[ATA_ID_CSFO]); + if (id[ATA_ID_CSFO] != 1) + printk(KERN_CONT "(%dK stripe)", id[146]); + printk(KERN_CONT ".\n"); + } else { + /* Non RAID volume. Fixups to stop the core code + doing unsupported things */ + id[ATA_ID_FIELD_VALID] &= 3; + id[ATA_ID_QUEUE_DEPTH] = 0; + id[ATA_ID_COMMAND_SET_1] = 0; + id[ATA_ID_COMMAND_SET_2] &= 0xC400; + id[ATA_ID_CFSSE] &= 0xC000; + id[ATA_ID_CFS_ENABLE_1] = 0; + id[ATA_ID_CFS_ENABLE_2] &= 0xC400; + id[ATA_ID_CSF_DEFAULT] &= 0xC000; + id[127] = 0; + id[ATA_ID_DLF] = 0; + id[ATA_ID_CSFO] = 0; + id[ATA_ID_CFA_POWER] = 0; + printk(KERN_INFO "%s: Performing identify fixups.\n", + drive->name); + } + + /* + * Set MWDMA0 mode as enabled/support - just to tell + * IDE core that DMA is supported (it821x hardware + * takes care of DMA mode programming). + */ + if (ata_id_has_dma(id)) { + id[ATA_ID_MWDMA_MODES] |= 0x0101; + drive->current_speed = XFER_MW_DMA_0; + } + } + +} + +static struct ide_dma_ops it821x_pass_through_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = it821x_dma_start, + .dma_end = it821x_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = ide_dma_lost_irq, +}; + +/** + * init_hwif_it821x - set up hwif structs + * @hwif: interface to set up + * + * We do the basic set up of the interface structure. The IT8212 + * requires several custom handlers so we override the default + * ide DMA handlers appropriately + */ + +static void __devinit init_hwif_it821x(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_host *host = pci_get_drvdata(dev); + struct it821x_dev *itdevs = host->host_priv; + struct it821x_dev *idev = itdevs + hwif->channel; + u8 conf; + + ide_set_hwifdata(hwif, idev); + + pci_read_config_byte(dev, 0x50, &conf); + if (conf & 1) { + idev->smart = 1; + hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; + /* Long I/O's although allowed in LBA48 space cause the + onboard firmware to enter the twighlight zone */ + hwif->rqsize = 256; + } + + /* Pull the current clocks from 0x50 also */ + if (conf & (1 << (1 + hwif->channel))) + idev->clock_mode = ATA_50; + else + idev->clock_mode = ATA_66; + + idev->want[0][1] = ATA_ANY; + idev->want[1][1] = ATA_ANY; + + /* + * Not in the docs but according to the reference driver + * this is necessary. + */ + + pci_read_config_byte(dev, 0x08, &conf); + if (conf == 0x10) { + idev->timing10 = 1; + hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; + if (idev->smart == 0) + printk(KERN_WARNING DRV_NAME " %s: revision 0x10, " + "workarounds activated\n", pci_name(dev)); + } + + if (idev->smart == 0) { + /* MWDMA/PIO clock switching for pass through mode */ + hwif->dma_ops = &it821x_pass_through_dma_ops; + } else + hwif->host_flags |= IDE_HFLAG_NO_SET_MODE; + + if (hwif->dma_base == 0) + return; + + hwif->ultra_mask = ATA_UDMA6; + hwif->mwdma_mask = ATA_MWDMA2; +} + +static void it8212_disable_raid(struct pci_dev *dev) +{ + /* Reset local CPU, and set BIOS not ready */ + pci_write_config_byte(dev, 0x5E, 0x01); + + /* Set to bypass mode, and reset PCI bus */ + pci_write_config_byte(dev, 0x50, 0x00); + pci_write_config_word(dev, PCI_COMMAND, + PCI_COMMAND_PARITY | PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_write_config_word(dev, 0x40, 0xA0F3); + + pci_write_config_dword(dev,0x4C, 0x02040204); + pci_write_config_byte(dev, 0x42, 0x36); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); +} + +static unsigned int init_chipset_it821x(struct pci_dev *dev) +{ + u8 conf; + static char *mode[2] = { "pass through", "smart" }; + + /* Force the card into bypass mode if so requested */ + if (it8212_noraid) { + printk(KERN_INFO DRV_NAME " %s: forcing bypass mode\n", + pci_name(dev)); + it8212_disable_raid(dev); + } + pci_read_config_byte(dev, 0x50, &conf); + printk(KERN_INFO DRV_NAME " %s: controller in %s mode\n", + pci_name(dev), mode[conf & 1]); + return 0; +} + +static const struct ide_port_ops it821x_port_ops = { + /* it821x_set_{pio,dma}_mode() are only used in pass-through mode */ + .set_pio_mode = it821x_set_pio_mode, + .set_dma_mode = it821x_set_dma_mode, + .quirkproc = it821x_quirkproc, + .cable_detect = it821x_cable_detect, +}; + +static const struct ide_port_info it821x_chipset __devinitdata = { + .name = DRV_NAME, + .init_chipset = init_chipset_it821x, + .init_hwif = init_hwif_it821x, + .port_ops = &it821x_port_ops, + .pio_mask = ATA_PIO4, +}; + +/** + * it821x_init_one - pci layer discovery entry + * @dev: PCI device + * @id: ident table entry + * + * Called by the PCI code when it finds an ITE821x controller. + * We then use the IDE PCI generic helper to do most of the work. + */ + +static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct it821x_dev *itdevs; + int rc; + + itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL); + if (itdevs == NULL) { + printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev)); + return -ENOMEM; + } + + rc = ide_pci_init_one(dev, &it821x_chipset, itdevs); + if (rc) + kfree(itdevs); + + return rc; +} + +static void __devexit it821x_remove(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct it821x_dev *itdevs = host->host_priv; + + ide_pci_remove(dev); + kfree(itdevs); +} + +static const struct pci_device_id it821x_pci_tbl[] = { + { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 }, + { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 }, + { 0, }, +}; + +MODULE_DEVICE_TABLE(pci, it821x_pci_tbl); + +static struct pci_driver it821x_pci_driver = { + .name = "ITE821x IDE", + .id_table = it821x_pci_tbl, + .probe = it821x_init_one, + .remove = __devexit_p(it821x_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init it821x_ide_init(void) +{ + return ide_pci_register_driver(&it821x_pci_driver); +} + +static void __exit it821x_ide_exit(void) +{ + pci_unregister_driver(&it821x_pci_driver); +} + +module_init(it821x_ide_init); +module_exit(it821x_ide_exit); + +module_param_named(noraid, it8212_noraid, int, S_IRUGO); +MODULE_PARM_DESC(noraid, "Force card into bypass mode"); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("PCI driver module for the ITE 821x"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/jmicron.c b/drivers/ide/jmicron.c new file mode 100644 index 0000000..9a68433 --- /dev/null +++ b/drivers/ide/jmicron.c @@ -0,0 +1,176 @@ + +/* + * Copyright (C) 2006 Red Hat + * + * May be copied or modified under the terms of the GNU General Public License + */ + +#include +#include +#include +#include +#include + +#define DRV_NAME "jmicron" + +typedef enum { + PORT_PATA0 = 0, + PORT_PATA1 = 1, + PORT_SATA = 2, +} port_type; + +/** + * jmicron_cable_detect - cable detection + * @hwif: IDE port + * + * Returns the cable type. + */ + +static u8 jmicron_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *pdev = to_pci_dev(hwif->dev); + + u32 control; + u32 control5; + + int port = hwif->channel; + port_type port_map[2]; + + pci_read_config_dword(pdev, 0x40, &control); + + /* There are two basic mappings. One has the two SATA ports merged + as master/slave and the secondary as PATA, the other has only the + SATA port mapped */ + if (control & (1 << 23)) { + port_map[0] = PORT_SATA; + port_map[1] = PORT_PATA0; + } else { + port_map[0] = PORT_SATA; + port_map[1] = PORT_SATA; + } + + /* The 365/366 may have this bit set to map the second PATA port + as the internal primary channel */ + pci_read_config_dword(pdev, 0x80, &control5); + if (control5 & (1<<24)) + port_map[0] = PORT_PATA1; + + /* The two ports may then be logically swapped by the firmware */ + if (control & (1 << 22)) + port = port ^ 1; + + /* + * Now we know which physical port we are talking about we can + * actually do our cable checking etc. Thankfully we don't need + * to do the plumbing for other cases. + */ + switch (port_map[port]) { + case PORT_PATA0: + if (control & (1 << 3)) /* 40/80 pin primary */ + return ATA_CBL_PATA40; + return ATA_CBL_PATA80; + case PORT_PATA1: + if (control5 & (1 << 19)) /* 40/80 pin secondary */ + return ATA_CBL_PATA40; + return ATA_CBL_PATA80; + case PORT_SATA: + break; + } + /* Avoid bogus "control reaches end of non-void function" */ + return ATA_CBL_PATA80; +} + +static void jmicron_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ +} + +/** + * jmicron_set_dma_mode - set host controller for DMA mode + * @drive: drive + * @mode: DMA mode + * + * As the JMicron snoops for timings we don't need to do anything here. + */ + +static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode) +{ +} + +static const struct ide_port_ops jmicron_port_ops = { + .set_pio_mode = jmicron_set_pio_mode, + .set_dma_mode = jmicron_set_dma_mode, + .cable_detect = jmicron_cable_detect, +}; + +static const struct ide_port_info jmicron_chipset __devinitdata = { + .name = DRV_NAME, + .enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } }, + .port_ops = &jmicron_port_ops, + .pio_mask = ATA_PIO5, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, +}; + +/** + * jmicron_init_one - pci layer discovery entry + * @dev: PCI device + * @id: ident table entry + * + * Called by the PCI code when it finds a Jmicron controller. + * We then use the IDE PCI generic helper to do most of the work. + */ + +static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + return ide_pci_init_one(dev, &jmicron_chipset, NULL); +} + +/* All JMB PATA controllers have and will continue to have the same + * interface. Matching vendor and device class is enough for all + * current and future controllers if the controller is programmed + * properly. + * + * If libata is configured, jmicron PCI quirk programs the controller + * into the correct mode. If libata isn't configured, match known + * device IDs too to maintain backward compatibility. + */ +static struct pci_device_id jmicron_pci_tbl[] = { +#if !defined(CONFIG_ATA) && !defined(CONFIG_ATA_MODULE) + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361) }, + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363) }, + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365) }, + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366) }, + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368) }, +#endif + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 }, + { 0, }, +}; + +MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl); + +static struct pci_driver jmicron_pci_driver = { + .name = "JMicron IDE", + .id_table = jmicron_pci_tbl, + .probe = jmicron_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init jmicron_ide_init(void) +{ + return ide_pci_register_driver(&jmicron_pci_driver); +} + +static void __exit jmicron_ide_exit(void) +{ + pci_unregister_driver(&jmicron_pci_driver); +} + +module_init(jmicron_ide_init); +module_exit(jmicron_ide_exit); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile deleted file mode 100644 index 6939329..0000000 --- a/drivers/ide/legacy/Makefile +++ /dev/null @@ -1,25 +0,0 @@ - -# link order is important here - -obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o -obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o -obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o -obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o -obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o -obj-$(CONFIG_BLK_DEV_4DRIVES) += ide-4drives.o - -obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o -obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o -obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o -obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o -obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o - -ifeq ($(CONFIG_BLK_DEV_IDECS), m) - obj-m += ide-cs.o -endif - -ifeq ($(CONFIG_BLK_DEV_PLATFORM), m) - obj-m += ide_platform.o -endif - -EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c deleted file mode 100644 index 90da1f9..0000000 --- a/drivers/ide/legacy/ali14xx.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -/* - * ALI M14xx chipset EIDE controller - * - * Works for ALI M1439/1443/1445/1487/1489 chipsets. - * - * Adapted from code developed by derekn@vw.ece.cmu.edu. -ml - * Derek's notes follow: - * - * I think the code should be pretty understandable, - * but I'll be happy to (try to) answer questions. - * - * The critical part is in the 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "ali14xx" - -/* port addresses for auto-detection */ -#define ALI_NUM_PORTS 4 -static const int ports[ALI_NUM_PORTS] __initdata = - { 0x074, 0x0f4, 0x034, 0x0e4 }; - -/* register initialization data */ -typedef struct { u8 reg, data; } RegInitializer; - -static const RegInitializer initData[] __initdata = { - {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, - {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, - {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, - {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_drive_t *drive, const u8 pio) -{ - int driveNum; - int time1, time2; - u8 param1, param2, param3, param4; - unsigned long flags; - int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50; - struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); - - /* calculate timing, according to PIO mode */ - time1 = ide_pio_cycle_time(drive, pio); - time2 = 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 int 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"); diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c deleted file mode 100644 index c5a3c9e..0000000 --- a/drivers/ide/legacy/buddha.c +++ /dev/null @@ -1,235 +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 -#include -#include -#include -#include -#include -#include - -#include -#include - - - /* - * The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2 - */ - -#define BUDDHA_NUM_HWIFS 2 -#define CATWEASEL_NUM_HWIFS 3 -#define XSURF_NUM_HWIFS 2 - -#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_ack_intr(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = z_readb(hwif->io_ports.irq_addr); - if (!(ch & 0x80)) - return 0; - return 1; -} - -static int xsurf_ack_intr(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = z_readb(hwif->io_ports.irq_addr); - /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */ - z_writeb(0, hwif->io_ports.irq_addr); - if (!(ch & 0x80)) - return 0; - return 1; -} - -static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, - unsigned long ctl, unsigned long irq_port, - ide_ack_intr_t *ack_intr) -{ - 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; - hw->ack_intr = ack_intr; - - hw->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; - hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; - - if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { - buddha_num_hwifs = BUDDHA_NUM_HWIFS; - 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; - -/* - * FIXME: we now have selectable mmio v/s iomio transports. - */ - - 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); - - 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; - ide_ack_intr_t *ack_intr; - - if (type != BOARD_XSURF) { - base = buddha_board + buddha_bases[i]; - ctl = base + BUDDHA_CONTROL; - irq_port = buddha_board + buddha_irqports[i]; - ack_intr = buddha_ack_intr; - } else { - base = buddha_board + xsurf_bases[i]; - /* X-Surf has no CS1* (Control/AltStat) */ - ctl = 0; - irq_port = buddha_board + xsurf_irqports[i]; - ack_intr = xsurf_ack_intr; - } - - buddha_setup_ports(&hw[i], base, ctl, irq_port, - ack_intr); - - hws[i] = &hw[i]; - } - - ide_host_add(NULL, hws, NULL); - } - - return 0; -} - -module_init(buddha_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c deleted file mode 100644 index 689b2e4..0000000 --- a/drivers/ide/legacy/dtc2278.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "dtc2278" - -/* - * Changing this #undef to #define may solve start up problems in some systems. - */ -#undef ALWAYS_SET_DTC2278_PIO_MODE - -/* - * From: andy@cercle.cts.com (Dyan Wile) - * - * Below is a patch for DTC-2278 - alike software-programmable controllers - * The code enables the secondary IDE controller and the PIO4 (3?) timings on - * the primary (EIDE). You may probably have to enable the 32-bit support to - * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 - * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my - * filesystem corrupted with -u1, but under heavy disk load only :-) - * - * This card is now forced to use the "serialize" feature, - * and irq-unmasking is disallowed. If io_32bit is enabled, - * it must be done for BOTH drives on each interface. - * - * This code was written for the DTC2278E, but might work with any of these: - * - * DTC2278S has only a single IDE interface. - * DTC2278D has two IDE interfaces and is otherwise identical to the S version. - * DTC2278E also has serial ports and a printer port - * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford - * - * There may be a fourth controller type. The S and D versions use the - * Winbond chip, and I think the E version does also. - * - */ - -static void sub22 (char b, char c) -{ - int i; - - for(i = 0; i < 3; ++i) { - inb(0x3f6); - outb_p(b,0xb0); - inb(0x3f6); - outb_p(c,0xb4); - inb(0x3f6); - if(inb(0xb4) == c) { - outb_p(7,0xb0); - inb(0x3f6); - return; /* success */ - } - } -} - -static DEFINE_SPINLOCK(dtc2278_lock); - -static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - unsigned long flags; - - if (pio >= 3) { - spin_lock_irqsave(&dtc2278_lock, flags); - /* - * This enables PIO mode4 (3?) on the first interface - */ - sub22(1,0xc3); - sub22(0,0xa0); - spin_unlock_irqrestore(&dtc2278_lock, flags); - } else { - /* we don't know how to set it back again.. */ - /* Actually we do - there is a data sheet available for the - Winbond but does anyone actually care */ - } -} - -static const struct ide_port_ops dtc2278_port_ops = { - .set_pio_mode = dtc2278_set_pio_mode, -}; - -static const struct ide_port_info dtc2278_port_info __initdata = { - .name = DRV_NAME, - .chipset = ide_dtc2278, - .port_ops = &dtc2278_port_ops, - .host_flags = IDE_HFLAG_SERIALIZE | - IDE_HFLAG_NO_UNMASK_IRQS | - IDE_HFLAG_IO_32BIT | - /* disallow ->io_32bit changes */ - IDE_HFLAG_NO_IO_32BIT | - IDE_HFLAG_NO_DMA, - .pio_mask = ATA_PIO4, -}; - -static int __init dtc2278_probe(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); - - return ide_legacy_device_add(&dtc2278_port_info, 0); -} - -static int probe_dtc2278; - -module_param_named(probe, probe_dtc2278, bool, 0); -MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); - -static int __init dtc2278_init(void) -{ - if (probe_dtc2278 == 0) - return -ENODEV; - - if (dtc2278_probe()) { - printk(KERN_ERR "dtc2278: ide interfaces already in use!\n"); - return -EBUSY; - } - return 0; -} - -module_init(dtc2278_init); - -MODULE_AUTHOR("See Local File"); -MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c deleted file mode 100644 index 39d500d..0000000 --- a/drivers/ide/legacy/falconide.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Atari Falcon IDE Driver - * - * Created 12 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define DRV_NAME "falconide" - - /* - * Base of the IDE interface - */ - -#define ATA_HD_BASE 0xfff00000 - - /* - * Offsets from the above base - */ - -#define ATA_HD_CONTROL 0x39 - - /* - * falconide_intr_lock is used to obtain access to the IDE interrupt, - * which is shared between several drivers. - */ - -int falconide_intr_lock; -EXPORT_SYMBOL(falconide_intr_lock); - -static void falconide_input_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - unsigned long data_addr = drive->hwif->io_ports.data_addr; - - if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) - return insw(data_addr, buf, (len + 1) / 2); - - insw_swapw(data_addr, buf, (len + 1) / 2); -} - -static void falconide_output_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - unsigned long data_addr = drive->hwif->io_ports.data_addr; - - if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) - return outsw(data_addr, buf, (len + 1) / 2); - - outsw_swapw(data_addr, buf, (len + 1) / 2); -} - -/* Atari has a byte-swapped IDE interface */ -static const struct ide_tp_ops falconide_tp_ops = { - .exec_command = ide_exec_command, - .read_status = ide_read_status, - .read_altstatus = ide_read_altstatus, - .read_sff_dma_status = ide_read_sff_dma_status, - - .set_irq = ide_set_irq, - - .tf_load = ide_tf_load, - .tf_read = ide_tf_read, - - .input_data = falconide_input_data, - .output_data = falconide_output_data, -}; - -static const struct ide_port_info falconide_port_info = { - .tp_ops = &falconide_tp_ops, - .host_flags = IDE_HFLAG_NO_DMA, -}; - -static void __init falconide_setup_ports(hw_regs_t *hw) -{ - int i; - - memset(hw, 0, sizeof(*hw)); - - hw->io_ports.data_addr = ATA_HD_BASE; - - for (i = 1; i < 8; i++) - hw->io_ports_array[i] = ATA_HD_BASE + 1 + i * 4; - - hw->io_ports.ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL; - - hw->irq = IRQ_MFP_IDE; - hw->ack_intr = NULL; - - hw->chipset = ide_generic; -} - - /* - * Probe for a Falcon IDE interface - */ - -static int __init falconide_init(void) -{ - struct ide_host *host; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - int rc; - - if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE)) - return -ENODEV; - - printk(KERN_INFO "ide: Falcon IDE controller\n"); - - if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) { - printk(KERN_ERR "%s: resources busy\n", DRV_NAME); - return -EBUSY; - } - - falconide_setup_ports(&hw); - - host = ide_host_alloc(&falconide_port_info, hws); - if (host == NULL) { - rc = -ENOMEM; - goto err; - } - - ide_get_lock(NULL, NULL); - rc = ide_host_register(host, &falconide_port_info, hws); - ide_release_lock(); - - if (rc) - goto err_free; - - return 0; -err_free: - ide_host_free(host); -err: - release_mem_region(ATA_HD_BASE, 0x40); - return rc; -} - -module_init(falconide_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c deleted file mode 100644 index 6915068..0000000 --- a/drivers/ide/legacy/gayle.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Amiga Gayle IDE Driver - * - * Created 9 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - - /* - * Bases of the IDE interfaces - */ - -#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ -#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */ - -#define GAYLE_IDEREG_SIZE 0x2000 - - /* - * Offsets from one of the above bases - */ - -#define GAYLE_CONTROL 0x101a - - /* - * These are at different offsets from the base - */ - -#define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */ -#define GAYLE_IRQ_1200 0xda9000 /* interrupt */ - - - /* - * Offset of the secondary port for IDE doublers - * Note that GAYLE_CONTROL is NOT available then! - */ - -#define GAYLE_NEXT_PORT 0x1000 - -#ifndef CONFIG_BLK_DEV_IDEDOUBLER -#define GAYLE_NUM_HWIFS 1 -#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS -#define GAYLE_HAS_CONTROL_REG 1 -#else /* CONFIG_BLK_DEV_IDEDOUBLER */ -#define GAYLE_NUM_HWIFS 2 -#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \ - GAYLE_NUM_HWIFS-1) -#define GAYLE_HAS_CONTROL_REG (!ide_doubler) - -static int ide_doubler; -module_param_named(doubler, ide_doubler, bool, 0); -MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - - - /* - * Check and acknowledge the interrupt status - */ - -static int gayle_ack_intr_a4000(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = z_readb(hwif->io_ports.irq_addr); - if (!(ch & GAYLE_IRQ_IDE)) - return 0; - return 1; -} - -static int gayle_ack_intr_a1200(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = z_readb(hwif->io_ports.irq_addr); - if (!(ch & GAYLE_IRQ_IDE)) - return 0; - (void)z_readb(hwif->io_ports.status_addr); - z_writeb(0x7c, hwif->io_ports.irq_addr); - return 1; -} - -static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, - unsigned long ctl, unsigned long irq_port, - ide_ack_intr_t *ack_intr) -{ - 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; - hw->ack_intr = ack_intr; - - hw->chipset = ide_generic; -} - - /* - * Probe for a Gayle IDE interface (and optionally for an IDE doubler) - */ - -static int __init gayle_init(void) -{ - unsigned long phys_base, res_start, res_n; - unsigned long base, ctrlport, irqport; - ide_ack_intr_t *ack_intr; - int a4000, i, rc; - hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; - - if (!MACH_IS_AMIGA) - return -ENODEV; - - if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) - goto found; - -#ifdef CONFIG_ZORRO - if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE, - NULL)) - goto found; -#endif - return -ENODEV; - -found: - printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", - a4000 ? 4000 : 1200, -#ifdef CONFIG_BLK_DEV_IDEDOUBLER - ide_doubler ? ", IDE doubler" : -#endif - ""); - - if (a4000) { - phys_base = GAYLE_BASE_4000; - irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000); - ack_intr = gayle_ack_intr_a4000; - } else { - phys_base = GAYLE_BASE_1200; - irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200); - ack_intr = gayle_ack_intr_a1200; - } -/* - * FIXME: we now have selectable modes between mmio v/s iomio - */ - - res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); - res_n = GAYLE_IDEREG_SIZE; - - if (!request_mem_region(res_start, res_n, "IDE")) - return -EBUSY; - - for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { - base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT); - ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; - - gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr); - - hws[i] = &hw[i]; - } - - rc = ide_host_add(NULL, hws, NULL); - if (rc) - release_mem_region(res_start, res_n); - - return rc; -} - -module_init(gayle_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c deleted file mode 100644 index c7e5c22..0000000 --- a/drivers/ide/legacy/ht6560b.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 1995-2000 Linus Torvalds & author (see below) - */ - -/* - * HT-6560B EIDE-controller support - * To activate controller support use kernel parameter "ide0=ht6560b". - * Use hdparm utility to enable PIO mode support. - * - * Author: Mikko Ala-Fossi - * Jan Evert van Grootheest - * - * Try: http://www.maf.iki.fi/~maf/ht6560b/ - */ - -#define DRV_NAME "ht6560b" -#define HT6560B_VERSION "v0.08" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* #define DEBUG */ /* remove comments for DEBUG messages */ - -/* - * The special i/o-port that HT-6560B uses to configuration: - * bit0 (0x01): "1" selects secondary interface - * bit2 (0x04): "1" enables FIFO function - * bit5 (0x20): "1" enables prefetched data read function (???) - * - * The special i/o-port that HT-6560A uses to configuration: - * bit0 (0x01): "1" selects secondary interface - * bit1 (0x02): "1" enables prefetched data read function - * bit2 (0x04): "0" enables multi-master system (?) - * bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?) - */ -#define HT_CONFIG_PORT 0x3e6 -#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8) -/* - * FIFO + PREFETCH (both a/b-model) - */ -#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */ -/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */ -#define HT_SECONDARY_IF 0x01 -#define HT_PREFETCH_MODE 0x20 - -/* - * ht6560b Timing values: - * - * I reviewed some assembler source listings of htide drivers and found - * out how they setup those cycle time interfacing values, as they at Holtek - * call them. IDESETUP.COM that is supplied with the drivers figures out - * optimal values and fetches those values to drivers. I found out that - * they use Select register to fetch timings to the ide board right after - * interface switching. After that it was quite easy to add code to - * ht6560b.c. - * - * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine - * for hda and hdc. But hdb needed higher values to work, so I guess - * that sometimes it is necessary to give higher value than IDESETUP - * gives. [see cmd640.c for an extreme example of this. -ml] - * - * Perhaps I should explain something about these timing values: - * The higher nibble of value is the Recovery Time (rt) and the lower nibble - * of the value is the Active Time (at). Minimum value 2 is the fastest and - * the maximum value 15 is the slowest. Default values should be 15 for both. - * So 0x24 means 2 for rt and 4 for at. Each of the drives should have - * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or - * similar. If value is too small there will be all sorts of failures. - * - * Timing byte consists of - * High nibble: Recovery Cycle Time (rt) - * The valid values range from 2 to 15. The default is 15. - * - * Low nibble: Active Cycle Time (at) - * The valid values range from 2 to 15. The default is 15. - * - * You can obtain optimized timing values by running Holtek IDESETUP.COM - * for DOS. DOS drivers get their timing values from command line, where - * the first value is the Recovery Time and the second value is the - * Active Time for each drive. Smaller value gives higher speed. - * In case of failures you should probably fall back to a higher value. - */ -#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff) -#define HT_TIMING_DEFAULT 0xff - -/* - * This routine handles interface switching for the peculiar hardware design - * on the F.G.I./Holtek HT-6560B VLB IDE interface. - * The HT-6560B can only enable one IDE port at a time, and requires a - * silly sequence (below) whenever we switch between primary and secondary. - */ - -/* - * This routine is invoked from ide.c to prepare for access to a given drive. - */ -static void ht6560b_selectproc (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned long flags; - static u8 current_select = 0; - static u8 current_timing = 0; - u8 select, timing; - - local_irq_save(flags); - - select = HT_CONFIG(drive); - timing = HT_TIMING(drive); - - /* - * Need to enforce prefetch sometimes because otherwise - * it'll hang (hard). - */ - if (drive->media != ide_disk || - (drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - select |= HT_PREFETCH_MODE; - - if (select != current_select || timing != current_timing) { - current_select = select; - current_timing = timing; - (void)inb(HT_CONFIG_PORT); - (void)inb(HT_CONFIG_PORT); - (void)inb(HT_CONFIG_PORT); - (void)inb(HT_CONFIG_PORT); - outb(select, HT_CONFIG_PORT); - /* - * Set timing for this drive: - */ - outb(timing, hwif->io_ports.device_addr); - (void)inb(hwif->io_ports.status_addr); -#ifdef DEBUG - printk("ht6560b: %s: select=%#x timing=%#x\n", - drive->name, select, timing); -#endif - } - local_irq_restore(flags); -} - -/* - * Autodetection and initialization of ht6560b - */ -static int __init try_to_init_ht6560b(void) -{ - u8 orig_value; - int i; - - /* Autodetect ht6560b */ - if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff) - return 0; - - for (i=3;i>0;i--) { - outb(0x00, HT_CONFIG_PORT); - if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) { - outb(orig_value, HT_CONFIG_PORT); - return 0; - } - } - outb(0x00, HT_CONFIG_PORT); - if ((~inb(HT_CONFIG_PORT))& 0x3f) { - outb(orig_value, HT_CONFIG_PORT); - return 0; - } - /* - * Ht6560b autodetected - */ - outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); - outb(HT_TIMING_DEFAULT, 0x1f6); /* Select register */ - (void)inb(0x1f7); /* Status register */ - - printk("ht6560b " HT6560B_VERSION - ": chipset detected and initialized" -#ifdef DEBUG - " with debug enabled" -#endif - "\n" - ); - return 1; -} - -static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio) -{ - int active_time, recovery_time; - int active_cycles, recovery_cycles; - int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50; - - if (pio) { - unsigned int cycle_time; - struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); - - cycle_time = ide_pio_cycle_time(drive, pio); - - /* - * Just like opti621.c we try to calculate the - * actual cycle time for recovery and activity - * according system bus speed. - */ - active_time = t->active; - recovery_time = cycle_time - active_time - t->setup; - /* - * Cycle times should be Vesa bus cycles - */ - active_cycles = (active_time * bus_speed + 999) / 1000; - recovery_cycles = (recovery_time * bus_speed + 999) / 1000; - /* - * Upper and lower limits - */ - if (active_cycles < 2) active_cycles = 2; - if (recovery_cycles < 2) recovery_cycles = 2; - if (active_cycles > 15) active_cycles = 15; - if (recovery_cycles > 15) recovery_cycles = 0; /* 0==16 */ - -#ifdef DEBUG - printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time); -#endif - - return (u8)((recovery_cycles << 4) | active_cycles); - } else { - -#ifdef DEBUG - printk("ht6560b: drive %s setting pio=0\n", drive->name); -#endif - - return HT_TIMING_DEFAULT; /* default setting */ - } -} - -static DEFINE_SPINLOCK(ht6560b_lock); - -/* - * Enable/Disable so called prefetch mode - */ -static void ht_set_prefetch(ide_drive_t *drive, u8 state) -{ - unsigned long flags; - int t = HT_PREFETCH_MODE << 8; - - spin_lock_irqsave(&ht6560b_lock, flags); - - /* - * Prefetch mode and unmask irq seems to conflict - */ - if (state) { - drive->drive_data |= t; /* enable prefetch mode */ - drive->dev_flags |= IDE_DFLAG_NO_UNMASK; - drive->dev_flags &= ~IDE_DFLAG_UNMASK; - } else { - drive->drive_data &= ~t; /* disable prefetch mode */ - drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK; - } - - spin_unlock_irqrestore(&ht6560b_lock, flags); - -#ifdef DEBUG - printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); -#endif -} - -static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - unsigned long flags; - u8 timing; - - switch (pio) { - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - ht_set_prefetch(drive, pio & 1); - return; - } - - timing = ht_pio2timings(drive, pio); - - spin_lock_irqsave(&ht6560b_lock, flags); - drive->drive_data &= 0xff00; - drive->drive_data |= timing; - spin_unlock_irqrestore(&ht6560b_lock, flags); - -#ifdef DEBUG - printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); -#endif -} - -static void __init ht6560b_init_dev(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - /* Setting default configurations for drives. */ - int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT; - - if (hwif->channel) - t |= (HT_SECONDARY_IF << 8); - - drive->drive_data = t; -} - -static int probe_ht6560b; - -module_param_named(probe, probe_ht6560b, bool, 0); -MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); - -static const struct ide_port_ops ht6560b_port_ops = { - .init_dev = ht6560b_init_dev, - .set_pio_mode = ht6560b_set_pio_mode, - .selectproc = ht6560b_selectproc, -}; - -static const struct ide_port_info ht6560b_port_info __initdata = { - .name = DRV_NAME, - .chipset = ide_ht6560b, - .port_ops = &ht6560b_port_ops, - .host_flags = IDE_HFLAG_SERIALIZE | /* is this needed? */ - IDE_HFLAG_NO_DMA | - IDE_HFLAG_ABUSE_PREFETCH, - .pio_mask = ATA_PIO4, -}; - -static int __init ht6560b_init(void) -{ - if (probe_ht6560b == 0) - return -ENODEV; - - if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) { - printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n", - __func__); - return -ENODEV; - } - - if (!try_to_init_ht6560b()) { - printk(KERN_NOTICE "%s: HBA not found\n", __func__); - goto release_region; - } - - return ide_legacy_device_add(&ht6560b_port_info, 0); - -release_region: - release_region(HT_CONFIG_PORT, 1); - return -ENODEV; -} - -module_init(ht6560b_init); - -MODULE_AUTHOR("See Local File"); -MODULE_DESCRIPTION("HT-6560B EIDE-controller support"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c deleted file mode 100644 index 9e85b1e..0000000 --- a/drivers/ide/legacy/ide-4drives.c +++ /dev/null @@ -1,63 +0,0 @@ - -#include -#include -#include -#include - -#define DRV_NAME "ide-4drives" - -static int probe_4drives; - -module_param_named(probe, probe_4drives, bool, 0); -MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port"); - -static void ide_4drives_init_dev(ide_drive_t *drive) -{ - if (drive->hwif->channel) - drive->select ^= 0x20; -} - -static const struct ide_port_ops ide_4drives_port_ops = { - .init_dev = ide_4drives_init_dev, -}; - -static const struct ide_port_info ide_4drives_port_info = { - .port_ops = &ide_4drives_port_ops, - .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA, -}; - -static int __init ide_4drives_init(void) -{ - unsigned long base = 0x1f0, ctl = 0x3f6; - hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL }; - - if (probe_4drives == 0) - return -ENODEV; - - if (!request_region(base, 8, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", - DRV_NAME, base, base + 7); - return -EBUSY; - } - - if (!request_region(ctl, 1, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", - DRV_NAME, ctl); - release_region(base, 8); - return -EBUSY; - } - - memset(&hw, 0, sizeof(hw)); - - ide_std_init_ports(&hw, base, ctl); - hw.irq = 14; - hw.chipset = ide_4drives; - - return ide_host_add(&ide_4drives_port_info, hws, NULL); -} - -module_init(ide_4drives_init); - -MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); -MODULE_DESCRIPTION("generic IDE chipset with 4 drives/port support"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c deleted file mode 100644 index cb199c8..0000000 --- a/drivers/ide/legacy/ide-cs.c +++ /dev/null @@ -1,472 +0,0 @@ -/*====================================================================== - - A driver for PCMCIA IDE/ATA disk cards - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in - which case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "ide-cs" - -/*====================================================================*/ - -/* Module parameters */ - -MODULE_AUTHOR("David Hinds "); -MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver"); -MODULE_LICENSE("Dual MPL/GPL"); - -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -#ifdef CONFIG_PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -typedef struct ide_info_t { - struct pcmcia_device *p_dev; - struct ide_host *host; - int ndev; - dev_node_t node; -} ide_info_t; - -static void ide_release(struct pcmcia_device *); -static int ide_config(struct pcmcia_device *); - -static void ide_detach(struct pcmcia_device *p_dev); - - - - -/*====================================================================== - - ide_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - -======================================================================*/ - -static int ide_probe(struct pcmcia_device *link) -{ - ide_info_t *info; - - DEBUG(0, "ide_attach()\n"); - - /* Create new ide device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->p_dev = link; - link->priv = info; - - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - - return ide_config(link); -} /* ide_attach */ - -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - -static void ide_detach(struct pcmcia_device *link) -{ - ide_info_t *info = link->priv; - ide_hwif_t *hwif = info->host->ports[0]; - unsigned long data_addr, ctl_addr; - - DEBUG(0, "ide_detach(0x%p)\n", link); - - data_addr = hwif->io_ports.data_addr; - ctl_addr = hwif->io_ports.ctl_addr; - - ide_release(link); - - release_region(ctl_addr, 1); - release_region(data_addr, 8); - - kfree(info); -} /* ide_detach */ - -static const struct ide_port_ops idecs_port_ops = { - .quirkproc = ide_undecoded_slave, -}; - -static const struct ide_port_info idecs_port_info = { - .port_ops = &idecs_port_ops, - .host_flags = IDE_HFLAG_NO_DMA, -}; - -static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, - unsigned long irq, struct pcmcia_device *handle) -{ - struct ide_host *host; - ide_hwif_t *hwif; - int i, rc; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - if (!request_region(io, 8, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", - DRV_NAME, io, io + 7); - return NULL; - } - - if (!request_region(ctl, 1, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", - DRV_NAME, ctl); - release_region(io, 8); - return NULL; - } - - memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, io, ctl); - hw.irq = irq; - hw.chipset = ide_pci; - hw.dev = &handle->dev; - - rc = ide_host_add(&idecs_port_info, hws, &host); - if (rc) - goto out_release; - - hwif = host->ports[0]; - - if (hwif->present) - return host; - - /* retry registration in case device is still spinning up */ - for (i = 0; i < 10; i++) { - msleep(100); - ide_port_scan(hwif); - if (hwif->present) - return host; - } - - return host; - -out_release: - release_region(ctl, 1); - release_region(io, 8); - return NULL; -} - -/*====================================================================== - - ide_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - ide device available to the system. - -======================================================================*/ - -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -struct pcmcia_config_check { - unsigned long ctl_base; - int skip_vcc; - int is_kme; -}; - -static int pcmcia_check_one_config(struct pcmcia_device *pdev, - cistpl_cftable_entry_t *cfg, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) -{ - struct pcmcia_config_check *stk = priv_data; - - /* Check for matching Vcc, unless we're desperate */ - if (!stk->skip_vcc) { - if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) - return -ENODEV; - } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) - return -ENODEV; - } - } - - if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; - else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) - pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; - - if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - pdev->conf.ConfigIndex = cfg->index; - pdev->io.BasePort1 = io->win[0].base; - pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - if (!(io->flags & CISTPL_IO_16BIT)) - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - if (io->nwin == 2) { - pdev->io.NumPorts1 = 8; - pdev->io.BasePort2 = io->win[1].base; - pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1; - if (pcmcia_request_io(pdev, &pdev->io) != 0) - return -ENODEV; - stk->ctl_base = pdev->io.BasePort2; - } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { - pdev->io.NumPorts1 = io->win[0].len; - pdev->io.NumPorts2 = 0; - if (pcmcia_request_io(pdev, &pdev->io) != 0) - return -ENODEV; - stk->ctl_base = pdev->io.BasePort1 + 0x0e; - } else - return -ENODEV; - /* If we've got this far, we're done */ - return 0; - } - return -ENODEV; -} - -static int ide_config(struct pcmcia_device *link) -{ - ide_info_t *info = link->priv; - struct pcmcia_config_check *stk = NULL; - int last_ret = 0, last_fn = 0, is_kme = 0; - unsigned long io_base, ctl_base; - struct ide_host *host; - - DEBUG(0, "ide_config(0x%p)\n", link); - - is_kme = ((link->manf_id == MANFID_KME) && - ((link->card_id == PRODID_KME_KXLC005_A) || - (link->card_id == PRODID_KME_KXLC005_B))); - - stk = kzalloc(sizeof(*stk), GFP_KERNEL); - if (!stk) - goto err_mem; - stk->is_kme = is_kme; - stk->skip_vcc = io_base = ctl_base = 0; - - if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) { - stk->skip_vcc = 1; - if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) - goto failed; /* No suitable config found */ - } - io_base = link->io.BasePort1; - ctl_base = stk->ctl_base; - - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - - /* disable drive interrupts during IDE probe */ - outb(0x02, ctl_base); - - /* special setup for KXLC005 card */ - if (is_kme) - outb(0x81, ctl_base+1); - - host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); - if (host == NULL && link->io.NumPorts1 == 0x20) { - outb(0x02, ctl_base + 0x10); - host = idecs_register(io_base + 0x10, ctl_base + 0x10, - link->irq.AssignedIRQ, link); - } - - if (host == NULL) - goto failed; - - info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2); - info->node.major = host->ports[0]->major; - info->node.minor = 0; - info->host = host; - link->dev_node = &info->node; - printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); - - kfree(stk); - return 0; - -err_mem: - printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); - goto failed; - -cs_failed: - cs_error(link, last_fn, last_ret); -failed: - kfree(stk); - ide_release(link); - return -ENODEV; -} /* ide_config */ - -/*====================================================================== - - After a card is removed, ide_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - -static void ide_release(struct pcmcia_device *link) -{ - ide_info_t *info = link->priv; - struct ide_host *host = info->host; - - DEBUG(0, "ide_release(0x%p)\n", link); - - if (info->ndev) - /* FIXME: if this fails we need to queue the cleanup somehow - -- need to investigate the required PCMCIA magic */ - ide_host_remove(host); - - info->ndev = 0; - - pcmcia_disable_device(link); -} /* ide_release */ - - -/*====================================================================== - - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the ide drivers from - talking to the ports. - -======================================================================*/ - -static struct pcmcia_device_id ide_ids[] = { - PCMCIA_DEVICE_FUNC_ID(4), - PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ - PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ - PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ - PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ - PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), - PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904), - PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ - PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */ - PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */ - PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ - PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), - PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ - PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ - PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), - PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */ - PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */ - PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), - PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74), - PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), - PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), - PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), - PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf), - PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), - PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), - PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), - PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), - PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), - PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), - PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), - PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), - PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee), - PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c), - PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), - PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883), - PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d), - PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), - PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), - PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), - PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32), - PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), - PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), - PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), - PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), - PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), - PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), - PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), - PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, ide_ids); - -static struct pcmcia_driver ide_cs_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "ide-cs", - }, - .probe = ide_probe, - .remove = ide_detach, - .id_table = ide_ids, -}; - -static int __init init_ide_cs(void) -{ - return pcmcia_register_driver(&ide_cs_driver); -} - -static void __exit exit_ide_cs(void) -{ - pcmcia_unregister_driver(&ide_cs_driver); -} - -late_initcall(init_ide_cs); -module_exit(exit_ide_cs); diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c deleted file mode 100644 index 051b4ab..0000000 --- a/drivers/ide/legacy/ide_platform.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Platform IDE driver - * - * Copyright (C) 2007 MontaVista Software - * - * Maintainer: Kumar Gala - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void __devinit plat_ide_setup_ports(hw_regs_t *hw, - void __iomem *base, - void __iomem *ctrl, - struct pata_platform_info *pdata, - int irq) -{ - unsigned long port = (unsigned long)base; - int i; - - hw->io_ports.data_addr = port; - - port += (1 << pdata->ioport_shift); - for (i = 1; i <= 7; - i++, port += (1 << pdata->ioport_shift)) - hw->io_ports_array[i] = port; - - hw->io_ports.ctl_addr = (unsigned long)ctrl; - - hw->irq = irq; - - hw->chipset = ide_generic; -} - -static const struct ide_port_info platform_ide_port_info = { - .host_flags = IDE_HFLAG_NO_DMA, -}; - -static int __devinit plat_ide_probe(struct platform_device *pdev) -{ - struct resource *res_base, *res_alt, *res_irq; - void __iomem *base, *alt_base; - struct pata_platform_info *pdata; - struct ide_host *host; - int ret = 0, mmio = 0; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - struct ide_port_info d = platform_ide_port_info; - - pdata = pdev->dev.platform_data; - - /* get a pointer to the register memory */ - res_base = platform_get_resource(pdev, IORESOURCE_IO, 0); - res_alt = platform_get_resource(pdev, IORESOURCE_IO, 1); - - if (!res_base || !res_alt) { - res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); - res_alt = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res_base || !res_alt) { - ret = -ENOMEM; - goto out; - } - mmio = 1; - } - - res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res_irq) { - ret = -EINVAL; - goto out; - } - - if (mmio) { - base = devm_ioremap(&pdev->dev, - res_base->start, res_base->end - res_base->start + 1); - alt_base = devm_ioremap(&pdev->dev, - res_alt->start, res_alt->end - res_alt->start + 1); - } else { - base = devm_ioport_map(&pdev->dev, - res_base->start, res_base->end - res_base->start + 1); - alt_base = devm_ioport_map(&pdev->dev, - res_alt->start, res_alt->end - res_alt->start + 1); - } - - memset(&hw, 0, sizeof(hw)); - plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start); - hw.dev = &pdev->dev; - - if (mmio) - d.host_flags |= IDE_HFLAG_MMIO; - - ret = ide_host_add(&d, hws, &host); - if (ret) - goto out; - - platform_set_drvdata(pdev, host); - - return 0; - -out: - return ret; -} - -static int __devexit plat_ide_remove(struct platform_device *pdev) -{ - struct ide_host *host = pdev->dev.driver_data; - - ide_host_remove(host); - - return 0; -} - -static struct platform_driver platform_ide_driver = { - .driver = { - .name = "pata_platform", - .owner = THIS_MODULE, - }, - .probe = plat_ide_probe, - .remove = __devexit_p(plat_ide_remove), -}; - -static int __init platform_ide_init(void) -{ - return platform_driver_register(&platform_ide_driver); -} - -static void __exit platform_ide_exit(void) -{ - platform_driver_unregister(&platform_ide_driver); -} - -MODULE_DESCRIPTION("Platform IDE driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pata_platform"); - -module_init(platform_ide_init); -module_exit(platform_ide_exit); diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c deleted file mode 100644 index 43f97cc..0000000 --- a/drivers/ide/legacy/macide.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Macintosh IDE Driver - * - * Copyright (C) 1998 by Michael Schmitz - * - * This driver was written based on information obtained from the MacOS IDE - * driver binary by Mikael Forselius - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define IDE_BASE 0x50F1A000 /* Base address of IDE controller */ - -/* - * Generic IDE registers as offsets from the base - * These match MkLinux so they should be correct. - */ - -#define IDE_CONTROL 0x38 /* control/altstatus */ - -/* - * Mac-specific registers - */ - -/* - * this register is odd; it doesn't seem to do much and it's - * not word-aligned like virtually every other hardware register - * on the Mac... - */ - -#define IDE_IFR 0x101 /* (0x101) IDE interrupt flags on Quadra: - * - * Bit 0+1: some interrupt flags - * Bit 2+3: some interrupt enable - * Bit 4: ?? - * Bit 5: IDE interrupt flag (any hwif) - * Bit 6: maybe IDE interrupt enable (any hwif) ?? - * Bit 7: Any interrupt condition - */ - -volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR); - -int macide_ack_intr(ide_hwif_t* hwif) -{ - if (*ide_ifr & 0x20) { - *ide_ifr &= ~0x20; - return 1; - } - return 0; -} - -static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, - int irq, ide_ack_intr_t *ack_intr) -{ - int i; - - memset(hw, 0, sizeof(*hw)); - - for (i = 0; i < 8; i++) - hw->io_ports_array[i] = base + i * 4; - - hw->io_ports.ctl_addr = base + IDE_CONTROL; - - hw->irq = irq; - hw->ack_intr = ack_intr; - - hw->chipset = ide_generic; -} - -static const char *mac_ide_name[] = - { "Quadra", "Powerbook", "Powerbook Baboon" }; - -/* - * Probe for a Macintosh IDE interface - */ - -static int __init macide_init(void) -{ - ide_ack_intr_t *ack_intr; - unsigned long base; - int irq; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - if (!MACH_IS_MAC) - return -ENODEV; - - switch (macintosh_config->ide_type) { - case MAC_IDE_QUADRA: - base = IDE_BASE; - ack_intr = macide_ack_intr; - irq = IRQ_NUBUS_F; - break; - case MAC_IDE_PB: - base = IDE_BASE; - ack_intr = macide_ack_intr; - irq = IRQ_NUBUS_C; - break; - case MAC_IDE_BABOON: - base = BABOON_BASE; - ack_intr = NULL; - irq = IRQ_BABOON_1; - break; - default: - return -ENODEV; - } - - printk(KERN_INFO "ide: Macintosh %s IDE controller\n", - mac_ide_name[macintosh_config->ide_type - 1]); - - macide_setup_ports(&hw, base, irq, ack_intr); - - return ide_host_add(NULL, hws, NULL); -} - -module_init(macide_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c deleted file mode 100644 index 4af4a8c..0000000 --- a/drivers/ide/legacy/q40ide.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Q40 I/O port IDE Driver - * - * (c) Richard Zidlicky - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * - */ - -#include -#include -#include -#include -#include - - /* - * Bases of the IDE interfaces - */ - -#define Q40IDE_NUM_HWIFS 2 - -#define PCIDE_BASE1 0x1f0 -#define PCIDE_BASE2 0x170 -#define PCIDE_BASE3 0x1e8 -#define PCIDE_BASE4 0x168 -#define PCIDE_BASE5 0x1e0 -#define PCIDE_BASE6 0x160 - -static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = { - PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5, - PCIDE_BASE6 */ -}; - -static int q40ide_default_irq(unsigned long base) -{ - switch (base) { - case 0x1f0: return 14; - case 0x170: return 15; - case 0x1e8: return 11; - default: - return 0; - } -} - - -/* - * Addresses are pretranslated for Q40 ISA access. - */ -static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, - ide_ack_intr_t *ack_intr, - int irq) -{ - memset(hw, 0, sizeof(hw_regs_t)); - /* BIG FAT WARNING: - assumption: only DATA port is ever used in 16 bit mode */ - hw->io_ports.data_addr = Q40_ISA_IO_W(base); - hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1); - hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2); - hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3); - hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4); - hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5); - hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6); - hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7); - hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206); - - hw->irq = irq; - hw->ack_intr = ack_intr; - - hw->chipset = ide_generic; -} - -static void q40ide_input_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - unsigned long data_addr = drive->hwif->io_ports.data_addr; - - if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) - return insw(data_addr, buf, (len + 1) / 2); - - insw_swapw(data_addr, buf, (len + 1) / 2); -} - -static void q40ide_output_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - unsigned long data_addr = drive->hwif->io_ports.data_addr; - - if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) - return outsw(data_addr, buf, (len + 1) / 2); - - outsw_swapw(data_addr, buf, (len + 1) / 2); -} - -/* Q40 has a byte-swapped IDE interface */ -static const struct ide_tp_ops q40ide_tp_ops = { - .exec_command = ide_exec_command, - .read_status = ide_read_status, - .read_altstatus = ide_read_altstatus, - .read_sff_dma_status = ide_read_sff_dma_status, - - .set_irq = ide_set_irq, - - .tf_load = ide_tf_load, - .tf_read = ide_tf_read, - - .input_data = q40ide_input_data, - .output_data = q40ide_output_data, -}; - -static const struct ide_port_info q40ide_port_info = { - .tp_ops = &q40ide_tp_ops, - .host_flags = IDE_HFLAG_NO_DMA, -}; - -/* - * the static array is needed to have the name reported in /proc/ioports, - * hwif->name unfortunately isn't available yet - */ -static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ - "ide0", "ide1" -}; - -/* - * Probe for Q40 IDE interfaces - */ - -static int __init q40ide_init(void) -{ - int i; - hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; - - if (!MACH_IS_Q40) - return -ENODEV; - - printk(KERN_INFO "ide: Q40 IDE controller\n"); - - for (i = 0; i < Q40IDE_NUM_HWIFS; i++) { - const char *name = q40_ide_names[i]; - - if (!request_region(pcide_bases[i], 8, name)) { - printk("could not reserve ports %lx-%lx for %s\n", - pcide_bases[i],pcide_bases[i]+8,name); - continue; - } - if (!request_region(pcide_bases[i]+0x206, 1, name)) { - printk("could not reserve port %lx for %s\n", - pcide_bases[i]+0x206,name); - release_region(pcide_bases[i], 8); - continue; - } - q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL, - q40ide_default_irq(pcide_bases[i])); - - hws[i] = &hw[i]; - } - - return ide_host_add(&q40ide_port_info, hws, NULL); -} - -module_init(q40ide_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c deleted file mode 100644 index bc27c7a..0000000 --- a/drivers/ide/legacy/qd65xx.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (C) 1996-2001 Linus Torvalds & author (see below) - */ - -/* - * Version 0.03 Cleaned auto-tune, added probe - * Version 0.04 Added second channel tuning - * Version 0.05 Enhanced tuning ; added qd6500 support - * Version 0.06 Added dos driver's list - * Version 0.07 Second channel bug fix - * - * QDI QD6500/QD6580 EIDE controller fast support - * - * To activate controller support, use "ide0=qd65xx" - */ - -/* - * Rewritten from the work of Colten Edwards by - * Samuel Thibault - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "qd65xx" - -#include "qd65xx.h" - -/* - * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580) - * or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580) - * -- qd6500 is a single IDE interface - * -- qd6580 is a dual IDE interface - * - * More research on qd6580 being done by willmore@cig.mot.com (David) - * More Information given by Petr Soucek (petr@ryston.cz) - * http://www.ryston.cz/petr/vlb - */ - -/* - * base: Timer1 - * - * - * base+0x01: Config (R/O) - * - * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500) - * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30 - * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz - * bit 3: qd6500: 1 = disabled, 0 = enabled - * qd6580: 1 - * upper nibble: - * qd6500: 1100 - * qd6580: either 1010 or 0101 - * - * - * base+0x02: Timer2 (qd6580 only) - * - * - * base+0x03: Control (qd6580 only) - * - * bits 0-3 must always be set 1 - * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock - * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb - * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb - * channel 1 for hdc & hdd - * bit 1 : 1 = only disks on primary port - * 0 = disks & ATAPI devices on primary port - * bit 2-4 : always 0 - * bit 5 : status, but of what ? - * bit 6 : always set 1 by dos driver - * bit 7 : set 1 for non-ATAPI devices on primary port - * (maybe read-ahead and post-write buffer ?) - */ - -static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ - -/* - * qd65xx_select: - * - * This routine is invoked to prepare for access to a given drive. - */ - -static void qd65xx_select(ide_drive_t *drive) -{ - u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | - (QD_TIMREG(drive) & 0x02); - - if (timings[index] != QD_TIMING(drive)) - outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); -} - -/* - * qd6500_compute_timing - * - * computes the timing value where - * lower nibble represents active time, in count of VLB clocks - * upper nibble represents recovery time, in count of VLB clocks - */ - -static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time) -{ - int clk = ide_vlb_clk ? ide_vlb_clk : 50; - u8 act_cyc, rec_cyc; - - if (clk <= 33) { - act_cyc = 9 - IDE_IN(active_time * clk / 1000 + 1, 2, 9); - rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15); - } else { - act_cyc = 8 - IDE_IN(active_time * clk / 1000 + 1, 1, 8); - rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18); - } - - return (rec_cyc << 4) | 0x08 | act_cyc; -} - -/* - * qd6580_compute_timing - * - * idem for qd6580 - */ - -static u8 qd6580_compute_timing (int active_time, int recovery_time) -{ - int clk = ide_vlb_clk ? ide_vlb_clk : 50; - u8 act_cyc, rec_cyc; - - act_cyc = 17 - IDE_IN(active_time * clk / 1000 + 1, 2, 17); - rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15); - - return (rec_cyc << 4) | act_cyc; -} - -/* - * qd_find_disk_type - * - * tries to find timing from dos driver's table - */ - -static int qd_find_disk_type (ide_drive_t *drive, - int *active_time, int *recovery_time) -{ - struct qd65xx_timing_s *p; - char *m = (char *)&drive->id[ATA_ID_PROD]; - char model[ATA_ID_PROD_LEN]; - - if (*m == 0) - return 0; - - strncpy(model, m, ATA_ID_PROD_LEN); - ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */ - - for (p = qd65xx_timing ; p->offset != -1 ; p++) { - if (!strncmp(p->model, model+p->offset, 4)) { - printk(KERN_DEBUG "%s: listed !\n", drive->name); - *active_time = p->active; - *recovery_time = p->recovery; - return 1; - } - } - return 0; -} - -/* - * qd_set_timing: - * - * records the timing - */ - -static void qd_set_timing (ide_drive_t *drive, u8 timing) -{ - drive->drive_data &= 0xff00; - drive->drive_data |= timing; - - printk(KERN_DEBUG "%s: %#x\n", drive->name, timing); -} - -static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - u16 *id = drive->id; - int active_time = 175; - int recovery_time = 415; /* worst case values from the dos driver */ - - /* - * FIXME: use "pio" value - */ - if (!qd_find_disk_type(drive, &active_time, &recovery_time) && - (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) && - id[ATA_ID_EIDE_PIO] >= 240) { - printk(KERN_INFO "%s: PIO mode%d\n", drive->name, - id[ATA_ID_OLD_PIO_MODES] & 0xff); - active_time = 110; - recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120; - } - - qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time)); -} - -static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); - unsigned int cycle_time; - int active_time = 175; - int recovery_time = 415; /* worst case values from the dos driver */ - u8 base = (hwif->config_data & 0xff00) >> 8; - - if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) { - cycle_time = ide_pio_cycle_time(drive, pio); - - switch (pio) { - case 0: break; - case 3: - if (cycle_time >= 110) { - active_time = 86; - recovery_time = cycle_time - 102; - } else - printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); - break; - case 4: - if (cycle_time >= 69) { - active_time = 70; - recovery_time = cycle_time - 61; - } else - printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); - break; - default: - if (cycle_time >= 180) { - active_time = 110; - recovery_time = cycle_time - 120; - } else { - active_time = t->active; - recovery_time = cycle_time - active_time; - } - } - printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio); - } - - if (!HWIF(drive)->channel && drive->media != ide_disk) { - outb(0x5f, QD_CONTROL_PORT); - printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO " - "and post-write buffer on %s.\n", - drive->name, HWIF(drive)->name); - } - - qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time)); -} - -/* - * qd_testreg - * - * tests if the given port is a register - */ - -static int __init qd_testreg(int port) -{ - unsigned long flags; - u8 savereg, readreg; - - local_irq_save(flags); - savereg = inb_p(port); - outb_p(QD_TESTVAL, port); /* safe value */ - readreg = inb_p(port); - outb(savereg, port); - local_irq_restore(flags); - - if (savereg == QD_TESTVAL) { - printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); - printk(KERN_ERR "Please contact maintainers to tell about your hardware\n"); - printk(KERN_ERR "Assuming qd65xx is not present.\n"); - return 1; - } - - return (readreg != QD_TESTVAL); -} - -static void __init qd6500_init_dev(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 base = (hwif->config_data & 0xff00) >> 8; - u8 config = QD_CONFIG(hwif); - - drive->drive_data = QD6500_DEF_DATA; -} - -static void __init qd6580_init_dev(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u16 t1, t2; - u8 base = (hwif->config_data & 0xff00) >> 8; - u8 config = QD_CONFIG(hwif); - - if (hwif->host_flags & IDE_HFLAG_SINGLE) { - t1 = QD6580_DEF_DATA; - t2 = QD6580_DEF_DATA2; - } else - t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA; - - drive->drive_data = (drive->dn & 1) ? t2 : t1; -} - -static const struct ide_port_ops qd6500_port_ops = { - .init_dev = qd6500_init_dev, - .set_pio_mode = qd6500_set_pio_mode, - .selectproc = qd65xx_select, -}; - -static const struct ide_port_ops qd6580_port_ops = { - .init_dev = qd6580_init_dev, - .set_pio_mode = qd6580_set_pio_mode, - .selectproc = qd65xx_select, -}; - -static const struct ide_port_info qd65xx_port_info __initdata = { - .name = DRV_NAME, - .chipset = ide_qd65xx, - .host_flags = IDE_HFLAG_IO_32BIT | - IDE_HFLAG_NO_DMA, - .pio_mask = ATA_PIO4, -}; - -/* - * qd_probe: - * - * looks at the specified baseport, and if qd found, registers & initialises it - * return 1 if another qd may be probed - */ - -static int __init qd_probe(int base) -{ - int rc; - u8 config, unit, control; - struct ide_port_info d = qd65xx_port_info; - - config = inb(QD_CONFIG_PORT); - - if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) - return -ENODEV; - - unit = ! (config & QD_CONFIG_IDE_BASEPORT); - - if (unit) - d.host_flags |= IDE_HFLAG_QD_2ND_PORT; - - switch (config & 0xf0) { - case QD_CONFIG_QD6500: - if (qd_testreg(base)) - return -ENODEV; /* bad register */ - - if (config & QD_CONFIG_DISABLED) { - printk(KERN_WARNING "qd6500 is disabled !\n"); - return -ENODEV; - } - - printk(KERN_NOTICE "qd6500 at %#x\n", base); - printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", - config, QD_ID3); - - d.port_ops = &qd6500_port_ops; - d.host_flags |= IDE_HFLAG_SINGLE; - break; - case QD_CONFIG_QD6580_A: - case QD_CONFIG_QD6580_B: - if (qd_testreg(base) || qd_testreg(base + 0x02)) - return -ENODEV; /* bad registers */ - - control = inb(QD_CONTROL_PORT); - - printk(KERN_NOTICE "qd6580 at %#x\n", base); - printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", - config, control, QD_ID3); - - outb(QD_DEF_CONTR, QD_CONTROL_PORT); - - d.port_ops = &qd6580_port_ops; - if (control & QD_CONTR_SEC_DISABLED) - d.host_flags |= IDE_HFLAG_SINGLE; - - printk(KERN_INFO "qd6580: %s IDE board\n", - (control & QD_CONTR_SEC_DISABLED) ? "single" : "dual"); - break; - default: - return -ENODEV; - } - - rc = ide_legacy_device_add(&d, (base << 8) | config); - - if (d.host_flags & IDE_HFLAG_SINGLE) - return (rc == 0) ? 1 : rc; - - return rc; -} - -static int probe_qd65xx; - -module_param_named(probe, probe_qd65xx, bool, 0); -MODULE_PARM_DESC(probe, "probe for QD65xx chipsets"); - -static int __init qd65xx_init(void) -{ - int rc1, rc2 = -ENODEV; - - if (probe_qd65xx == 0) - return -ENODEV; - - rc1 = qd_probe(0x30); - if (rc1) - rc2 = qd_probe(0xb0); - - if (rc1 < 0 && rc2 < 0) - return -ENODEV; - - return 0; -} - -module_init(qd65xx_init); - -MODULE_AUTHOR("Samuel Thibault"); -MODULE_DESCRIPTION("support of qd65xx vlb ide chipset"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h deleted file mode 100644 index c83dea8..0000000 --- a/drivers/ide/legacy/qd65xx.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2000 Linus Torvalds & authors - */ - -/* - * Authors: Petr Soucek - * Samuel Thibault - */ - -/* truncates a in [b,c] */ -#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) - -#define IDE_IMPLY(a,b) ((!(a)) || (b)) - -#define QD_TIM1_PORT (base) -#define QD_CONFIG_PORT (base+0x01) -#define QD_TIM2_PORT (base+0x02) -#define QD_CONTROL_PORT (base+0x03) - -#define QD_CONFIG_IDE_BASEPORT 0x01 -#define QD_CONFIG_BASEPORT 0x02 -#define QD_CONFIG_ID3 0x04 -#define QD_CONFIG_DISABLED 0x08 -#define QD_CONFIG_QD6500 0xc0 -#define QD_CONFIG_QD6580_A 0xa0 -#define QD_CONFIG_QD6580_B 0x50 - -#define QD_CONTR_SEC_DISABLED 0x01 - -#define QD_ID3 ((config & QD_CONFIG_ID3)!=0) - -#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff) - -#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff) -#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8) - -#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08)) -#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) -#define QD6580_DEF_DATA2 ((QD_TIM2_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) -#define QD_DEF_CONTR (0x40 | ((control & 0x02) ? 0x9f : 0x1f)) - -#define QD_TESTVAL 0x19 /* safe value */ - -/* Drive specific timing taken from DOS driver v3.7 */ - -static struct qd65xx_timing_s { - s8 offset; /* ofset from the beginning of Model Number" */ - char model[4]; /* 4 chars from Model number, no conversion */ - s16 active; /* active time */ - s16 recovery; /* recovery time */ -} qd65xx_timing [] = { - { 30, "2040", 110, 225 }, /* Conner CP30204 */ - { 30, "2045", 135, 225 }, /* Conner CP30254 */ - { 30, "1040", 155, 325 }, /* Conner CP30104 */ - { 30, "1047", 135, 265 }, /* Conner CP30174 */ - { 30, "5344", 135, 225 }, /* Conner CP3544 */ - { 30, "01 4", 175, 405 }, /* Conner CP-3104 */ - { 27, "C030", 175, 375 }, /* Conner CP3000 */ - { 8, "PL42", 110, 295 }, /* Quantum LP240 */ - { 8, "PL21", 110, 315 }, /* Quantum LP120 */ - { 8, "PL25", 175, 385 }, /* Quantum LP52 */ - { 4, "PA24", 110, 285 }, /* WD Piranha SP4200 */ - { 6, "2200", 110, 260 }, /* WD Caviar AC2200 */ - { 6, "3204", 110, 235 }, /* WD Caviar AC2340 */ - { 6, "1202", 110, 265 }, /* WD Caviar AC2120 */ - { 0, "DS3-", 135, 315 }, /* Teac SD340 */ - { 8, "KM32", 175, 355 }, /* Toshiba MK234 */ - { 2, "53A1", 175, 355 }, /* Seagate ST351A */ - { 2, "4108", 175, 295 }, /* Seagate ST1480A */ - { 2, "1344", 175, 335 }, /* Seagate ST3144A */ - { 6, "7 12", 110, 225 }, /* Maxtor 7213A */ - { 30, "02F4", 145, 295 }, /* Conner 3204F */ - { 2, "1302", 175, 335 }, /* Seagate ST3120A */ - { 2, "2334", 145, 265 }, /* Seagate ST3243A */ - { 2, "2338", 145, 275 }, /* Seagate ST3283A */ - { 2, "3309", 145, 275 }, /* Seagate ST3390A */ - { 2, "5305", 145, 275 }, /* Seagate ST3550A */ - { 2, "4100", 175, 295 }, /* Seagate ST1400A */ - { 2, "4110", 175, 295 }, /* Seagate ST1401A */ - { 2, "6300", 135, 265 }, /* Seagate ST3600A */ - { 2, "5300", 135, 265 }, /* Seagate ST3500A */ - { 6, "7 31", 135, 225 }, /* Maxtor 7131 AT */ - { 6, "7 43", 115, 265 }, /* Maxtor 7345 AT */ - { 6, "7 42", 110, 255 }, /* Maxtor 7245 AT */ - { 6, "3 04", 135, 265 }, /* Maxtor 340 AT */ - { 6, "61 0", 135, 285 }, /* WD AC160 */ - { 6, "1107", 135, 235 }, /* WD AC1170 */ - { 6, "2101", 110, 220 }, /* WD AC1210 */ - { 6, "4202", 135, 245 }, /* WD AC2420 */ - { 6, "41 0", 175, 355 }, /* WD Caviar 140 */ - { 6, "82 0", 175, 355 }, /* WD Caviar 280 */ - { 8, "PL01", 175, 375 }, /* Quantum LP105 */ - { 8, "PL25", 110, 295 }, /* Quantum LP525 */ - { 10, "4S 2", 175, 385 }, /* Quantum ELS42 */ - { 10, "8S 5", 175, 385 }, /* Quantum ELS85 */ - { 10, "1S72", 175, 385 }, /* Quantum ELS127 */ - { 10, "1S07", 175, 385 }, /* Quantum ELS170 */ - { 8, "ZE42", 135, 295 }, /* Quantum EZ240 */ - { 8, "ZE21", 175, 385 }, /* Quantum EZ127 */ - { 8, "ZE58", 175, 385 }, /* Quantum EZ85 */ - { 8, "ZE24", 175, 385 }, /* Quantum EZ42 */ - { 27, "C036", 155, 325 }, /* Conner CP30064 */ - { 27, "C038", 155, 325 }, /* Conner CP30084 */ - { 6, "2205", 110, 255 }, /* WDC AC2250 */ - { 2, " CHA", 140, 415 }, /* WDC AH series; WDC AH260, WDC */ - { 2, " CLA", 140, 415 }, /* WDC AL series: WDC AL2120, 2170, */ - { 4, "UC41", 140, 415 }, /* WDC CU140 */ - { 6, "1207", 130, 275 }, /* WDC AC2170 */ - { 6, "2107", 130, 275 }, /* WDC AC1270 */ - { 6, "5204", 130, 275 }, /* WDC AC2540 */ - { 30, "3004", 110, 235 }, /* Conner CP30340 */ - { 30, "0345", 135, 255 }, /* Conner CP30544 */ - { 12, "12A3", 175, 320 }, /* MAXTOR LXT-213A */ - { 12, "43A0", 145, 240 }, /* MAXTOR LXT-340A */ - { 6, "7 21", 180, 290 }, /* Maxtor 7120 AT */ - { 6, "7 71", 135, 240 }, /* Maxtor 7170 AT */ - { 12, "45\0000", 110, 205 }, /* MAXTOR MXT-540 */ - { 8, "PL11", 180, 290 }, /* QUANTUM LP110A */ - { 8, "OG21", 150, 275 }, /* QUANTUM GO120 */ - { 12, "42A5", 175, 320 }, /* MAXTOR LXT-245A */ - { 2, "2309", 175, 295 }, /* ST3290A */ - { 2, "3358", 180, 310 }, /* ST3385A */ - { 2, "6355", 180, 310 }, /* ST3655A */ - { 2, "1900", 175, 270 }, /* ST9100A */ - { 2, "1954", 175, 270 }, /* ST9145A */ - { 2, "1909", 175, 270 }, /* ST9190AG */ - { 2, "2953", 175, 270 }, /* ST9235A */ - { 2, "1359", 175, 270 }, /* ST3195A */ - { 24, "3R11", 175, 290 }, /* ALPS ELECTRIC Co.,LTD, DR311C */ - { 0, "2M26", 175, 215 }, /* M262XT-0Ah */ - { 4, "2253", 175, 300 }, /* HP C2235A */ - { 4, "-32A", 145, 245 }, /* H3133-A2 */ - { 30, "0326", 150, 270 }, /* Samsung Electronics 120MB */ - { 30, "3044", 110, 195 }, /* Conner CFA340A */ - { 30, "43A0", 110, 195 }, /* Conner CFA340A */ - { -1, " ", 175, 415 } /* unknown disk name */ -}; diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c deleted file mode 100644 index 1da076e..0000000 --- a/drivers/ide/legacy/umc8672.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 1995-1996 Linus Torvalds & author (see below) - */ - -/* - * Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien) - * - * This file provides support for the advanced features - * of the UMC 8672 IDE interface. - * - * Version 0.01 Initial version, hacked out of ide.c, - * and #include'd rather than compiled separately. - * This will get cleaned up in a subsequent release. - * - * Version 0.02 now configs/compiles separate from ide.c -ml - * Version 0.03 enhanced auto-tune, fix display bug - * Version 0.05 replace sti() with restore_flags() -ml - * add detection of possible race condition -ml - */ - -/* - * VLB Controller Support from - * Wolfram Podien - * Rohoefe 3 - * D28832 Achim - * Germany - * - * To enable UMC8672 support there must a lilo line like - * append="ide0=umc8672"... - * To set the speed according to the abilities of the hardware there must be a - * line like - * #define UMC_DRIVE0 11 - * in the beginning of the driver, which sets the speed of drive 0 to 11 (there - * are some lines present). 0 - 11 are allowed speed values. These values are - * the results from the DOS speed test program supplied from UMC. 11 is the - * highest speed (about PIO mode 3) - */ -#define REALLY_SLOW_IO /* some systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "umc8672" - -/* - * Default speeds. These can be changed with "auto-tune" and/or hdparm. - */ -#define UMC_DRIVE0 1 /* DOS measured drive speeds */ -#define UMC_DRIVE1 1 /* 0 to 11 allowed */ -#define UMC_DRIVE2 1 /* 11 = Fastest Speed */ -#define UMC_DRIVE3 1 /* In case of crash reduce speed */ - -static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; -static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11}; /* rough guesses */ - -/* 0 1 2 3 4 5 6 7 8 9 10 11 */ -static const u8 speedtab [3][12] = { - {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1}, - {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1}, - {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0} -}; - -static void out_umc(char port, char wert) -{ - outb_p(port, 0x108); - outb_p(wert, 0x109); -} - -static inline u8 in_umc(char port) -{ - outb_p(port, 0x108); - return inb_p(0x109); -} - -static void umc_set_speeds(u8 speeds[]) -{ - int i, tmp; - - outb_p(0x5A, 0x108); /* enable umc */ - - out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); - out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); - tmp = 0; - for (i = 3; i >= 0; i--) - tmp = (tmp << 2) | speedtab[1][speeds[i]]; - out_umc(0xdc, tmp); - for (i = 0; i < 4; i++) { - out_umc(0xd0 + i, speedtab[2][speeds[i]]); - out_umc(0xd8 + i, speedtab[2][speeds[i]]); - } - outb_p(0xa5, 0x108); /* disable umc */ - - printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", - speeds[0], speeds[1], speeds[2], speeds[3]); -} - -static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned long flags; - - printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", - drive->name, pio, pio_to_umc[pio]); - spin_lock_irqsave(&ide_lock, flags); - if (hwif->mate && hwif->mate->hwgroup->handler) { - printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); - } else { - current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; - umc_set_speeds(current_speeds); - } - spin_unlock_irqrestore(&ide_lock, flags); -} - -static const struct ide_port_ops umc8672_port_ops = { - .set_pio_mode = umc_set_pio_mode, -}; - -static const struct ide_port_info umc8672_port_info __initdata = { - .name = DRV_NAME, - .chipset = ide_umc8672, - .port_ops = &umc8672_port_ops, - .host_flags = IDE_HFLAG_NO_DMA, - .pio_mask = ATA_PIO4, -}; - -static int __init umc8672_probe(void) -{ - unsigned long flags; - - if (!request_region(0x108, 2, "umc8672")) { - printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n"); - return 1; - } - local_irq_save(flags); - outb_p(0x5A, 0x108); /* enable umc */ - if (in_umc (0xd5) != 0xa0) { - local_irq_restore(flags); - printk(KERN_ERR "umc8672: not found\n"); - release_region(0x108, 2); - return 1; - } - outb_p(0xa5, 0x108); /* disable umc */ - - umc_set_speeds(current_speeds); - local_irq_restore(flags); - - return ide_legacy_device_add(&umc8672_port_info, 0); -} - -static int probe_umc8672; - -module_param_named(probe, probe_umc8672, bool, 0); -MODULE_PARM_DESC(probe, "probe for UMC8672 chipset"); - -static int __init umc8672_init(void) -{ - if (probe_umc8672 == 0) - goto out; - - if (umc8672_probe() == 0) - return 0;; -out: - return -ENODEV;; -} - -module_init(umc8672_init); - -MODULE_AUTHOR("Wolfram Podien"); -MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/macide.c b/drivers/ide/macide.c new file mode 100644 index 0000000..43f97cc --- /dev/null +++ b/drivers/ide/macide.c @@ -0,0 +1,131 @@ +/* + * Macintosh IDE Driver + * + * Copyright (C) 1998 by Michael Schmitz + * + * This driver was written based on information obtained from the MacOS IDE + * driver binary by Mikael Forselius + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define IDE_BASE 0x50F1A000 /* Base address of IDE controller */ + +/* + * Generic IDE registers as offsets from the base + * These match MkLinux so they should be correct. + */ + +#define IDE_CONTROL 0x38 /* control/altstatus */ + +/* + * Mac-specific registers + */ + +/* + * this register is odd; it doesn't seem to do much and it's + * not word-aligned like virtually every other hardware register + * on the Mac... + */ + +#define IDE_IFR 0x101 /* (0x101) IDE interrupt flags on Quadra: + * + * Bit 0+1: some interrupt flags + * Bit 2+3: some interrupt enable + * Bit 4: ?? + * Bit 5: IDE interrupt flag (any hwif) + * Bit 6: maybe IDE interrupt enable (any hwif) ?? + * Bit 7: Any interrupt condition + */ + +volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR); + +int macide_ack_intr(ide_hwif_t* hwif) +{ + if (*ide_ifr & 0x20) { + *ide_ifr &= ~0x20; + return 1; + } + return 0; +} + +static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, + int irq, ide_ack_intr_t *ack_intr) +{ + int i; + + memset(hw, 0, sizeof(*hw)); + + for (i = 0; i < 8; i++) + hw->io_ports_array[i] = base + i * 4; + + hw->io_ports.ctl_addr = base + IDE_CONTROL; + + hw->irq = irq; + hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; +} + +static const char *mac_ide_name[] = + { "Quadra", "Powerbook", "Powerbook Baboon" }; + +/* + * Probe for a Macintosh IDE interface + */ + +static int __init macide_init(void) +{ + ide_ack_intr_t *ack_intr; + unsigned long base; + int irq; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + + if (!MACH_IS_MAC) + return -ENODEV; + + switch (macintosh_config->ide_type) { + case MAC_IDE_QUADRA: + base = IDE_BASE; + ack_intr = macide_ack_intr; + irq = IRQ_NUBUS_F; + break; + case MAC_IDE_PB: + base = IDE_BASE; + ack_intr = macide_ack_intr; + irq = IRQ_NUBUS_C; + break; + case MAC_IDE_BABOON: + base = BABOON_BASE; + ack_intr = NULL; + irq = IRQ_BABOON_1; + break; + default: + return -ENODEV; + } + + printk(KERN_INFO "ide: Macintosh %s IDE controller\n", + mac_ide_name[macintosh_config->ide_type - 1]); + + macide_setup_ports(&hw, base, irq, ack_intr); + + return ide_host_add(NULL, hws, NULL); +} + +module_init(macide_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile deleted file mode 100644 index 5873fa0..0000000 --- a/drivers/ide/mips/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o - -EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c deleted file mode 100644 index 0ec8fd1..0000000 --- a/drivers/ide/mips/au1xxx-ide.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * AMD Alchemy Au1xxx IDE interface routines over the Static Bus - * - * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE - * Interface and Linux Device Driver" Application Note. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define DRV_NAME "au1200-ide" -#define DRV_AUTHOR "Enrico Walther / Pete Popov " - -/* enable the burstmode in the dbdma */ -#define IDE_AU1XXX_BURSTMODE 1 - -static _auide_hwif auide_hwif; - -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) - -void auide_insw(unsigned long port, void *addr, u32 count) -{ - _auide_hwif *ahwif = &auide_hwif; - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, - DDMA_FLAGS_NOIE)) { - printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); - return; - } - ctp = *((chan_tab_t **)ahwif->rx_chan); - dp = ctp->cur_ptr; - while (dp->dscr_cmd0 & DSCR_CMD0_V) - ; - ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); -} - -void auide_outsw(unsigned long port, void *addr, u32 count) -{ - _auide_hwif *ahwif = &auide_hwif; - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - if(!put_source_flags(ahwif->tx_chan, (void*)addr, - count << 1, DDMA_FLAGS_NOIE)) { - printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); - return; - } - ctp = *((chan_tab_t **)ahwif->tx_chan); - dp = ctp->cur_ptr; - while (dp->dscr_cmd0 & DSCR_CMD0_V) - ; - ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); -} - -static void au1xxx_input_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - auide_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); -} - -static void au1xxx_output_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - auide_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); -} -#endif - -static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2); - - /* set pio mode! */ - switch(pio) { - case 0: - mem_sttime = SBC_IDE_TIMING(PIO0); - - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS; - break; - - case 1: - mem_sttime = SBC_IDE_TIMING(PIO1); - - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS; - break; - - case 2: - mem_sttime = SBC_IDE_TIMING(PIO2); - - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS; - break; - - case 3: - mem_sttime = SBC_IDE_TIMING(PIO3); - - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS; - - break; - - case 4: - mem_sttime = SBC_IDE_TIMING(PIO4); - - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS; - break; - } - - au_writel(mem_sttime,MEM_STTIME2); - au_writel(mem_stcfg,MEM_STCFG2); -} - -static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2); - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - case XFER_MW_DMA_2: - mem_sttime = SBC_IDE_TIMING(MDMA2); - - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS; - - break; - case XFER_MW_DMA_1: - mem_sttime = SBC_IDE_TIMING(MDMA1); - - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS; - - break; - case XFER_MW_DMA_0: - mem_sttime = SBC_IDE_TIMING(MDMA0); - - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS; - - break; -#endif - } - - au_writel(mem_sttime,MEM_STTIME2); - au_writel(mem_stcfg,MEM_STCFG2); -} - -/* - * Multi-Word DMA + DbDMA functions - */ - -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA -static int auide_build_dmatable(ide_drive_t *drive) -{ - int i, iswrite, count = 0; - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; - _auide_hwif *ahwif = &auide_hwif; - struct scatterlist *sg; - - iswrite = (rq_data_dir(rq) == WRITE); - /* Save for interrupt context */ - ahwif->drive = drive; - - hwif->sg_nents = i = ide_build_sglist(drive, rq); - - if (!i) - return 0; - - /* fill the descriptors */ - sg = hwif->sg_table; - while (i && sg_dma_len(sg)) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - while (cur_len) { - u32 flags = DDMA_FLAGS_NOIE; - unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; - - if (++count >= PRD_ENTRIES) { - printk(KERN_WARNING "%s: DMA table too small\n", - drive->name); - goto use_pio_instead; - } - - /* Lets enable intr for the last descriptor only */ - if (1==i) - flags = DDMA_FLAGS_IE; - else - flags = DDMA_FLAGS_NOIE; - - if (iswrite) { - if(!put_source_flags(ahwif->tx_chan, - (void*) sg_virt(sg), - tc, flags)) { - printk(KERN_ERR "%s failed %d\n", - __func__, __LINE__); - } - } else - { - if(!put_dest_flags(ahwif->rx_chan, - (void*) sg_virt(sg), - tc, flags)) { - printk(KERN_ERR "%s failed %d\n", - __func__, __LINE__); - } - } - - cur_addr += tc; - cur_len -= tc; - } - sg = sg_next(sg); - i--; - } - - if (count) - return 1; - - use_pio_instead: - ide_destroy_dmatable(drive); - - return 0; /* revert to PIO for this request */ -} - -static int auide_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - - if (hwif->sg_nents) { - ide_destroy_dmatable(drive); - hwif->sg_nents = 0; - } - - return 0; -} - -static void auide_dma_start(ide_drive_t *drive ) -{ -} - - -static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command) -{ - /* issue cmd to drive */ - ide_execute_command(drive, command, &ide_dma_intr, - (2*WAIT_CMD), NULL); -} - -static int auide_dma_setup(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - - if (!auide_build_dmatable(drive)) { - ide_map_sg(drive, rq); - return 1; - } - - drive->waiting_for_dma = 1; - return 0; -} - -static int auide_dma_test_irq(ide_drive_t *drive) -{ - /* If dbdma didn't execute the STOP command yet, the - * active bit is still set - */ - drive->waiting_for_dma++; - if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { - printk(KERN_WARNING "%s: timeout waiting for ddma to \ - complete\n", drive->name); - return 1; - } - udelay(10); - return 0; -} - -static void auide_dma_host_set(ide_drive_t *drive, int on) -{ -} - -static void auide_ddma_tx_callback(int irq, void *param) -{ - _auide_hwif *ahwif = (_auide_hwif*)param; - ahwif->drive->waiting_for_dma = 0; -} - -static void auide_ddma_rx_callback(int irq, void *param) -{ - _auide_hwif *ahwif = (_auide_hwif*)param; - ahwif->drive->waiting_for_dma = 0; -} - -#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ - -static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags) -{ - dev->dev_id = dev_id; - dev->dev_physaddr = (u32)IDE_PHYS_ADDR; - dev->dev_intlevel = 0; - dev->dev_intpolarity = 0; - dev->dev_tsize = tsize; - dev->dev_devwidth = devwidth; - dev->dev_flags = flags; -} - -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA -static const struct ide_dma_ops au1xxx_dma_ops = { - .dma_host_set = auide_dma_host_set, - .dma_setup = auide_dma_setup, - .dma_exec_cmd = auide_dma_exec_cmd, - .dma_start = auide_dma_start, - .dma_end = auide_dma_end, - .dma_test_irq = auide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) -{ - _auide_hwif *auide = &auide_hwif; - dbdev_tab_t source_dev_tab, target_dev_tab; - u32 dev_id, tsize, devwidth, flags; - - dev_id = IDE_DDMA_REQ; - - tsize = 8; /* 1 */ - devwidth = 32; /* 16 */ - -#ifdef IDE_AU1XXX_BURSTMODE - flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE; -#else - flags = DEV_FLAGS_SYNC; -#endif - - /* setup dev_tab for tx channel */ - auide_init_dbdma_dev( &source_dev_tab, - dev_id, - tsize, devwidth, DEV_FLAGS_OUT | flags); - auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); - - auide_init_dbdma_dev( &source_dev_tab, - dev_id, - tsize, devwidth, DEV_FLAGS_IN | flags); - auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); - - /* We also need to add a target device for the DMA */ - auide_init_dbdma_dev( &target_dev_tab, - (u32)DSCR_CMD0_ALWAYS, - tsize, devwidth, DEV_FLAGS_ANYUSE); - auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab); - - /* Get a channel for TX */ - auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id, - auide->tx_dev_id, - auide_ddma_tx_callback, - (void*)auide); - - /* Get a channel for RX */ - auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, - auide->target_dev_id, - auide_ddma_rx_callback, - (void*)auide); - - auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan, - NUM_DESCRIPTORS); - auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, - NUM_DESCRIPTORS); - - /* FIXME: check return value */ - (void)ide_allocate_dma_engine(hwif); - - au1xxx_dbdma_start( auide->tx_chan ); - au1xxx_dbdma_start( auide->rx_chan ); - - return 0; -} -#else -static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) -{ - _auide_hwif *auide = &auide_hwif; - dbdev_tab_t source_dev_tab; - int flags; - -#ifdef IDE_AU1XXX_BURSTMODE - flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE; -#else - flags = DEV_FLAGS_SYNC; -#endif - - /* setup dev_tab for tx channel */ - auide_init_dbdma_dev( &source_dev_tab, - (u32)DSCR_CMD0_ALWAYS, - 8, 32, DEV_FLAGS_OUT | flags); - auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); - - auide_init_dbdma_dev( &source_dev_tab, - (u32)DSCR_CMD0_ALWAYS, - 8, 32, DEV_FLAGS_IN | flags); - auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); - - /* Get a channel for TX */ - auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS, - auide->tx_dev_id, - NULL, - (void*)auide); - - /* Get a channel for RX */ - auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, - DSCR_CMD0_ALWAYS, - NULL, - (void*)auide); - - auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan, - NUM_DESCRIPTORS); - auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, - NUM_DESCRIPTORS); - - au1xxx_dbdma_start( auide->tx_chan ); - au1xxx_dbdma_start( auide->rx_chan ); - - return 0; -} -#endif - -static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) -{ - int i; - unsigned long *ata_regs = hw->io_ports_array; - - /* FIXME? */ - for (i = 0; i < 8; i++) - *ata_regs++ = ahwif->regbase + (i << IDE_REG_SHIFT); - - /* set the Alternative Status register */ - *ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT); -} - -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA -static const struct ide_tp_ops au1xxx_tp_ops = { - .exec_command = ide_exec_command, - .read_status = ide_read_status, - .read_altstatus = ide_read_altstatus, - .read_sff_dma_status = ide_read_sff_dma_status, - - .set_irq = ide_set_irq, - - .tf_load = ide_tf_load, - .tf_read = ide_tf_read, - - .input_data = au1xxx_input_data, - .output_data = au1xxx_output_data, -}; -#endif - -static const struct ide_port_ops au1xxx_port_ops = { - .set_pio_mode = au1xxx_set_pio_mode, - .set_dma_mode = auide_set_dma_mode, -}; - -static const struct ide_port_info au1xxx_port_info = { - .init_dma = auide_ddma_init, -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA - .tp_ops = &au1xxx_tp_ops, -#endif - .port_ops = &au1xxx_port_ops, -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - .dma_ops = &au1xxx_dma_ops, -#endif - .host_flags = IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_NO_IO_32BIT | - IDE_HFLAG_UNMASK_IRQS, - .pio_mask = ATA_PIO4, -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - .mwdma_mask = ATA_MWDMA2, -#endif -}; - -static int au_ide_probe(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - _auide_hwif *ahwif = &auide_hwif; - struct resource *res; - struct ide_host *host; - int ret = 0; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) - char *mode = "MWDMA2"; -#elif defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) - char *mode = "PIO+DDMA(offload)"; -#endif - - memset(&auide_hwif, 0, sizeof(_auide_hwif)); - ahwif->irq = platform_get_irq(pdev, 0); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (res == NULL) { - pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id); - ret = -ENODEV; - goto out; - } - if (ahwif->irq < 0) { - pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id); - ret = -ENODEV; - goto out; - } - - if (!request_mem_region(res->start, res->end - res->start + 1, - pdev->name)) { - pr_debug("%s: request_mem_region failed\n", DRV_NAME); - ret = -EBUSY; - goto out; - } - - ahwif->regbase = (u32)ioremap(res->start, res->end - res->start + 1); - if (ahwif->regbase == 0) { - ret = -ENOMEM; - goto out; - } - - memset(&hw, 0, sizeof(hw)); - auide_setup_ports(&hw, ahwif); - hw.irq = ahwif->irq; - hw.dev = dev; - hw.chipset = ide_au1xxx; - - ret = ide_host_add(&au1xxx_port_info, hws, &host); - if (ret) - goto out; - - auide_hwif.hwif = host->ports[0]; - - dev_set_drvdata(dev, host); - - printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); - - out: - return ret; -} - -static int au_ide_remove(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct resource *res; - struct ide_host *host = dev_get_drvdata(dev); - _auide_hwif *ahwif = &auide_hwif; - - ide_host_remove(host); - - iounmap((void *)ahwif->regbase); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start + 1); - - return 0; -} - -static struct device_driver au1200_ide_driver = { - .name = "au1200-ide", - .bus = &platform_bus_type, - .probe = au_ide_probe, - .remove = au_ide_remove, -}; - -static int __init au_ide_init(void) -{ - return driver_register(&au1200_ide_driver); -} - -static void __exit au_ide_exit(void) -{ - driver_unregister(&au1200_ide_driver); -} - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("AU1200 IDE driver"); - -module_init(au_ide_init); -module_exit(au_ide_exit); diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c new file mode 100644 index 0000000..1378906 --- /dev/null +++ b/drivers/ide/ns87415.c @@ -0,0 +1,366 @@ +/* + * Copyright (C) 1997-1998 Mark Lord + * Copyright (C) 1998 Eddie C. Dost + * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 2004 Grant Grundler + * + * Inspired by an earlier effort from David S. Miller + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "ns87415" + +#ifdef CONFIG_SUPERIO +/* SUPERIO 87560 is a PoS chip that NatSem denies exists. + * Unfortunately, it's built-in on all Astro-based PA-RISC workstations + * which use the integrated NS87514 cell for CD-ROM support. + * i.e we have to support for CD-ROM installs. + * See drivers/parisc/superio.c for more gory details. + */ +#include + +#define SUPERIO_IDE_MAX_RETRIES 25 + +/* Because of a defect in Super I/O, all reads of the PCI DMA status + * registers, IDE status register and the IDE select register need to be + * retried + */ +static u8 superio_ide_inb (unsigned long port) +{ + u8 tmp; + int retries = SUPERIO_IDE_MAX_RETRIES; + + /* printk(" [ reading port 0x%x with retry ] ", port); */ + + do { + tmp = inb(port); + if (tmp == 0) + udelay(50); + } while (tmp == 0 && retries-- > 0); + + return tmp; +} + +static u8 superio_read_status(ide_hwif_t *hwif) +{ + return superio_ide_inb(hwif->io_ports.status_addr); +} + +static u8 superio_read_sff_dma_status(ide_hwif_t *hwif) +{ + return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS); +} + +static void superio_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + struct ide_io_ports *io_ports = &drive->hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data = inw(io_ports->data_addr); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_FEATURE) + tf->feature = inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = superio_ide_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = inb(io_ports->lbah_addr); + } +} + +static const struct ide_tp_ops superio_tp_ops = { + .exec_command = ide_exec_command, + .read_status = superio_read_status, + .read_altstatus = ide_read_altstatus, + .read_sff_dma_status = superio_read_sff_dma_status, + + .set_irq = ide_set_irq, + + .tf_load = ide_tf_load, + .tf_read = superio_tf_read, + + .input_data = ide_input_data, + .output_data = ide_output_data, +}; + +static void __devinit superio_init_iops(struct hwif_s *hwif) +{ + struct pci_dev *pdev = to_pci_dev(hwif->dev); + u32 dma_stat; + u8 port = hwif->channel, tmp; + + dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa); + + /* Clear error/interrupt, enable dma */ + tmp = superio_ide_inb(dma_stat); + outb(tmp | 0x66, dma_stat); +} +#endif + +static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; + +/* + * This routine either enables/disables (according to IDE_DFLAG_PRESENT) + * the IRQ associated with the port (HWIF(drive)), + * and selects either PIO or DMA handshaking for the next I/O operation. + */ +static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data; + unsigned long flags; + + local_irq_save(flags); + new = *old; + + /* Adjust IRQ enable bit */ + bit = 1 << (8 + hwif->channel); + + if (drive->dev_flags & IDE_DFLAG_PRESENT) + new &= ~bit; + else + new |= bit; + + /* Select PIO or DMA, DMA may only be selected for one drive/channel. */ + bit = 1 << (20 + (drive->dn & 1) + (hwif->channel << 1)); + other = 1 << (20 + (1 - (drive->dn & 1)) + (hwif->channel << 1)); + new = use_dma ? ((new & ~other) | bit) : (new & ~bit); + + if (new != *old) { + unsigned char stat; + + /* + * Don't change DMA engine settings while Write Buffers + * are busy. + */ + (void) pci_read_config_byte(dev, 0x43, &stat); + while (stat & 0x03) { + udelay(1); + (void) pci_read_config_byte(dev, 0x43, &stat); + } + + *old = new; + (void) pci_write_config_dword(dev, 0x40, new); + + /* + * And let things settle... + */ + udelay(10); + } + + local_irq_restore(flags); +} + +static void ns87415_selectproc (ide_drive_t *drive) +{ + ns87415_prepare_drive(drive, + !!(drive->dev_flags & IDE_DFLAG_USING_DMA)); +} + +static int ns87415_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = 0, dma_cmd = 0; + + drive->waiting_for_dma = 0; + dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); + /* get DMA command mode */ + dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); + /* stop DMA */ + outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); + /* from ERRATA: clear the INTR & ERROR bits */ + dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); + outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD); + /* and free any DMA resources */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; +} + +static int ns87415_dma_setup(ide_drive_t *drive) +{ + /* select DMA xfer */ + ns87415_prepare_drive(drive, 1); + if (!ide_dma_setup(drive)) + return 0; + /* DMA failed: select PIO xfer */ + ns87415_prepare_drive(drive, 0); + return 1; +} + +static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned int ctrl, using_inta; + u8 progif; +#ifdef __sparc_v9__ + int timeout; + u8 stat; +#endif + + /* + * We cannot probe for IRQ: both ports share common IRQ on INTA. + * Also, leave IRQ masked during drive probing, to prevent infinite + * interrupts from a potentially floating INTA.. + * + * IRQs get unmasked in selectproc when drive is first used. + */ + (void) pci_read_config_dword(dev, 0x40, &ctrl); + (void) pci_read_config_byte(dev, 0x09, &progif); + /* is irq in "native" mode? */ + using_inta = progif & (1 << (hwif->channel << 1)); + if (!using_inta) + using_inta = ctrl & (1 << (4 + hwif->channel)); + if (hwif->mate) { + hwif->select_data = hwif->mate->select_data; + } else { + hwif->select_data = (unsigned long) + &ns87415_control[ns87415_count++]; + ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */ + if (using_inta) + ctrl &= ~(1 << 6); /* unmask INTA */ + *((unsigned int *)hwif->select_data) = ctrl; + (void) pci_write_config_dword(dev, 0x40, ctrl); + + /* + * Set prefetch size to 512 bytes for both ports, + * but don't turn on/off prefetching here. + */ + pci_write_config_byte(dev, 0x55, 0xee); + +#ifdef __sparc_v9__ + /* + * XXX: Reset the device, if we don't it will not respond to + * SELECT_DRIVE() properly during first ide_probe_port(). + */ + timeout = 10000; + outb(12, hwif->io_ports.ctl_addr); + udelay(10); + outb(8, hwif->io_ports.ctl_addr); + do { + udelay(50); + stat = hwif->tp_ops->read_status(hwif); + if (stat == 0xff) + break; + } while ((stat & ATA_BUSY) && --timeout); +#endif + } + + if (!using_inta) + hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); + else if (!hwif->irq && hwif->mate && hwif->mate->irq) + hwif->irq = hwif->mate->irq; /* share IRQ with mate */ + + if (!hwif->dma_base) + return; + + outb(0x60, hwif->dma_base + ATA_DMA_STATUS); +} + +static const struct ide_port_ops ns87415_port_ops = { + .selectproc = ns87415_selectproc, +}; + +static const struct ide_dma_ops ns87415_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ns87415_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = ns87415_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info ns87415_chipset __devinitdata = { + .name = DRV_NAME, + .init_hwif = init_hwif_ns87415, + .port_ops = &ns87415_port_ops, + .dma_ops = &ns87415_dma_ops, + .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | + IDE_HFLAG_NO_ATAPI_DMA, +}; + +static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct ide_port_info d = ns87415_chipset; + +#ifdef CONFIG_SUPERIO + if (PCI_SLOT(dev->devfn) == 0xE) { + /* Built-in - assume it's under superio. */ + d.init_iops = superio_init_iops; + d.tp_ops = &superio_tp_ops; + } +#endif + return ide_pci_init_one(dev, &d, NULL); +} + +static const struct pci_device_id ns87415_pci_tbl[] = { + { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87415), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl); + +static struct pci_driver ns87415_pci_driver = { + .name = "NS87415_IDE", + .id_table = ns87415_pci_tbl, + .probe = ns87415_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init ns87415_ide_init(void) +{ + return ide_pci_register_driver(&ns87415_pci_driver); +} + +static void __exit ns87415_ide_exit(void) +{ + pci_unregister_driver(&ns87415_pci_driver); +} + +module_init(ns87415_ide_init); +module_exit(ns87415_ide_exit); + +MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for NS87415 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c new file mode 100644 index 0000000..6048eda --- /dev/null +++ b/drivers/ide/opti621.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) + */ + +/* + * Authors: + * Jaromir Koutek , + * Jan Harkes , + * Mark Lord + * Some parts of code are from ali14xx.c and from rz1000.c. + * + * OPTi is trademark of OPTi, Octek is trademark of Octek. + * + * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps + * and disassembled/traced setupvic.exe (DOS program). + * It increases kernel code about 2 kB. + * I don't have this card no more, but I hope I can get some in case + * of needed development. + * My card is Octek PIDE 1.01 (on card) or OPTiViC (program). + * It has a place for a secondary connector in circuit, but nothing + * is there. Also BIOS says no address for + * secondary controller (see bellow in ide_init_opti621). + * I've only tested this on my system, which only has one disk. + * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus + * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random + * lockups). I tried the OCTEK double speed CD-ROM and + * it does not work! But I can't boot DOS also, so it's probably + * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no + * problems) and Seagate 1GB (as slave, WD as master). My experiences + * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes + * it slows to about 100kB/s! I don't know why and I have + * not this drive now, so I can't try it again. + * I write this driver because I lost the paper ("manual") with + * settings of jumpers on the card and I have to boot Linux with + * Loadlin except LILO, cause I have to run the setupvic.exe program + * already or I get disk errors (my test: rpm -Vf + * /usr/X11R6/bin/XF86_SVGA - or any big file). + * Some numbers from hdparm -t /dev/hda: + * Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec + * Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec + * I have 4 Megs/s before, but I don't know why (maybe changes + * in hdparm test). + * After release of 0.1, I got some successful reports, so it might work. + * + * The main problem with OPTi is that some timings for master + * and slave must be the same. For example, if you have master + * PIO 3 and slave PIO 0, driver have to set some timings of + * master for PIO 0. Second problem is that opti621_set_pio_mode + * got only one drive to set, but have to set both drives. + * This is solved in compute_pios. If you don't set + * the second drive, compute_pios use ide_get_best_pio_mode + * for autoselect mode (you can change it to PIO 0, if you want). + * If you then set the second drive to another PIO, the old value + * (automatically selected) will be overrided by yours. + * There is a 25/33MHz switch in configuration + * register, but driver is written for use at any frequency. + * + * Version 0.1, Nov 8, 1996 + * by Jaromir Koutek, for 2.1.8. + * Initial version of driver. + * + * Version 0.2 + * Number 0.2 skipped. + * + * Version 0.3, Nov 29, 1997 + * by Mark Lord (probably), for 2.1.68 + * Updates for use with new IDE block driver. + * + * Version 0.4, Dec 14, 1997 + * by Jan Harkes + * Fixed some errors and cleaned the code. + * + * Version 0.5, Jan 2, 1998 + * by Jaromir Koutek + * Updates for use with (again) new IDE block driver. + * Update of documentation. + * + * Version 0.6, Jan 2, 1999 + * by Jaromir Koutek + * Reversed to version 0.3 of the driver, because + * 0.5 doesn't work. + */ + +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "opti621" + +#define READ_REG 0 /* index of Read cycle timing register */ +#define WRITE_REG 1 /* index of Write cycle timing register */ +#define CNTRL_REG 3 /* index of Control register */ +#define STRAP_REG 5 /* index of Strap register */ +#define MISC_REG 6 /* index of Miscellaneous register */ + +static int reg_base; + +static DEFINE_SPINLOCK(opti621_lock); + +/* Write value to register reg, base of register + * is at reg_base (0x1f0 primary, 0x170 secondary, + * if not changed by PCI configuration). + * This is from setupvic.exe program. + */ +static void write_reg(u8 value, int reg) +{ + inw(reg_base + 1); + inw(reg_base + 1); + outb(3, reg_base + 2); + outb(value, reg_base + reg); + outb(0x83, reg_base + 2); +} + +/* Read value from register reg, base of register + * is at reg_base (0x1f0 primary, 0x170 secondary, + * if not changed by PCI configuration). + * This is from setupvic.exe program. + */ +static u8 read_reg(int reg) +{ + u8 ret = 0; + + inw(reg_base + 1); + inw(reg_base + 1); + outb(3, reg_base + 2); + ret = inb(reg_base + reg); + outb(0x83, reg_base + 2); + + return ret; +} + +static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = drive->hwif; + ide_drive_t *pair = ide_get_pair_dev(drive); + unsigned long flags; + u8 tim, misc, addr_pio = pio, clk; + + /* DRDY is default 2 (by OPTi Databook) */ + static const u8 addr_timings[2][5] = { + { 0x20, 0x10, 0x00, 0x00, 0x00 }, /* 33 MHz */ + { 0x10, 0x10, 0x00, 0x00, 0x00 }, /* 25 MHz */ + }; + static const u8 data_rec_timings[2][5] = { + { 0x5b, 0x45, 0x32, 0x21, 0x20 }, /* 33 MHz */ + { 0x48, 0x34, 0x21, 0x10, 0x10 } /* 25 MHz */ + }; + + drive->drive_data = XFER_PIO_0 + pio; + + if (pair) { + if (pair->drive_data && pair->drive_data < drive->drive_data) + addr_pio = pair->drive_data - XFER_PIO_0; + } + + spin_lock_irqsave(&opti621_lock, flags); + + reg_base = hwif->io_ports.data_addr; + + /* allow Register-B */ + outb(0xc0, reg_base + CNTRL_REG); + /* hmm, setupvic.exe does this ;-) */ + outb(0xff, reg_base + 5); + /* if reads 0xff, adapter not exist? */ + (void)inb(reg_base + CNTRL_REG); + /* if reads 0xc0, no interface exist? */ + read_reg(CNTRL_REG); + + /* check CLK speed */ + clk = read_reg(STRAP_REG) & 1; + + printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33); + + tim = data_rec_timings[clk][pio]; + misc = addr_timings[clk][addr_pio]; + + /* select Index-0/1 for Register-A/B */ + write_reg(drive->dn & 1, MISC_REG); + /* set read cycle timings */ + write_reg(tim, READ_REG); + /* set write cycle timings */ + write_reg(tim, WRITE_REG); + + /* use Register-A for drive 0 */ + /* use Register-B for drive 1 */ + write_reg(0x85, CNTRL_REG); + + /* set address setup, DRDY timings, */ + /* and read prefetch for both drives */ + write_reg(misc, MISC_REG); + + spin_unlock_irqrestore(&opti621_lock, flags); +} + +static const struct ide_port_ops opti621_port_ops = { + .set_pio_mode = opti621_set_pio_mode, +}; + +static const struct ide_port_info opti621_chipset __devinitdata = { + .name = DRV_NAME, + .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, + .port_ops = &opti621_port_ops, + .host_flags = IDE_HFLAG_NO_DMA, + .pio_mask = ATA_PIO4, +}; + +static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + return ide_pci_init_one(dev, &opti621_chipset, NULL); +} + +static const struct pci_device_id opti621_pci_tbl[] = { + { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 }, + { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, opti621_pci_tbl); + +static struct pci_driver opti621_pci_driver = { + .name = "Opti621_IDE", + .id_table = opti621_pci_tbl, + .probe = opti621_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init opti621_ide_init(void) +{ + return ide_pci_register_driver(&opti621_pci_driver); +} + +static void __exit opti621_ide_exit(void) +{ + pci_unregister_driver(&opti621_pci_driver); +} + +module_init(opti621_ide_init); +module_exit(opti621_ide_exit); + +MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for Opti621 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c new file mode 100644 index 0000000..122ed3c --- /dev/null +++ b/drivers/ide/palm_bk3710.c @@ -0,0 +1,424 @@ +/* + * Palmchip bk3710 IDE controller + * + * Copyright (C) 2006 Texas Instruments. + * Copyright (C) 2007 MontaVista Software, Inc., + * + * ---------------------------------------------------------------------------- + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Offset of the primary interface registers */ +#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0 + +/* Primary Control Offset */ +#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6 + +/* + * PalmChip 3710 IDE Controller UDMA timing structure Definition + */ +struct palm_bk3710_udmatiming { + unsigned int rptime; /* Ready to pause time */ + unsigned int cycletime; /* Cycle Time */ +}; + +#define BK3710_BMICP 0x00 +#define BK3710_BMISP 0x02 +#define BK3710_BMIDTP 0x04 +#define BK3710_BMICS 0x08 +#define BK3710_BMISS 0x0A +#define BK3710_BMIDTS 0x0C +#define BK3710_IDETIMP 0x40 +#define BK3710_IDETIMS 0x42 +#define BK3710_SIDETIM 0x44 +#define BK3710_SLEWCTL 0x45 +#define BK3710_IDESTATUS 0x47 +#define BK3710_UDMACTL 0x48 +#define BK3710_UDMATIM 0x4A +#define BK3710_MISCCTL 0x50 +#define BK3710_REGSTB 0x54 +#define BK3710_REGRCVR 0x58 +#define BK3710_DATSTB 0x5C +#define BK3710_DATRCVR 0x60 +#define BK3710_DMASTB 0x64 +#define BK3710_DMARCVR 0x68 +#define BK3710_UDMASTB 0x6C +#define BK3710_UDMATRP 0x70 +#define BK3710_UDMAENV 0x74 +#define BK3710_IORDYTMP 0x78 +#define BK3710_IORDYTMS 0x7C + +static unsigned ideclk_period; /* in nanoseconds */ + +static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = { + {160, 240}, /* UDMA Mode 0 */ + {125, 160}, /* UDMA Mode 1 */ + {100, 120}, /* UDMA Mode 2 */ + {100, 90}, /* UDMA Mode 3 */ + {100, 60}, /* UDMA Mode 4 */ + {85, 40}, /* UDMA Mode 5 */ +}; + +static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev, + unsigned int mode) +{ + u8 tenv, trp, t0; + u32 val32; + u16 val16; + + /* DMA Data Setup */ + t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime, + ideclk_period) - 1; + tenv = DIV_ROUND_UP(20, ideclk_period) - 1; + trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime, + ideclk_period) - 1; + + /* udmatim Register */ + val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0); + val16 |= (mode << (dev ? 4 : 0)); + writew(val16, base + BK3710_UDMATIM); + + /* udmastb Ultra DMA Access Strobe Width */ + val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8)); + val32 |= (t0 << (dev ? 8 : 0)); + writel(val32, base + BK3710_UDMASTB); + + /* udmatrp Ultra DMA Ready to Pause Time */ + val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8)); + val32 |= (trp << (dev ? 8 : 0)); + writel(val32, base + BK3710_UDMATRP); + + /* udmaenv Ultra DMA envelop Time */ + val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8)); + val32 |= (tenv << (dev ? 8 : 0)); + writel(val32, base + BK3710_UDMAENV); + + /* Enable UDMA for Device */ + val16 = readw(base + BK3710_UDMACTL) | (1 << dev); + writew(val16, base + BK3710_UDMACTL); +} + +static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev, + unsigned short min_cycle, + unsigned int mode) +{ + u8 td, tkw, t0; + u32 val32; + u16 val16; + struct ide_timing *t; + int cycletime; + + t = ide_timing_find_mode(mode); + cycletime = max_t(int, t->cycle, min_cycle); + + /* DMA Data Setup */ + t0 = DIV_ROUND_UP(cycletime, ideclk_period); + td = DIV_ROUND_UP(t->active, ideclk_period); + tkw = t0 - td - 1; + td -= 1; + + val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8)); + val32 |= (td << (dev ? 8 : 0)); + writel(val32, base + BK3710_DMASTB); + + val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8)); + val32 |= (tkw << (dev ? 8 : 0)); + writel(val32, base + BK3710_DMARCVR); + + /* Disable UDMA for Device */ + val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev); + writew(val16, base + BK3710_UDMACTL); +} + +static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, + unsigned int dev, unsigned int cycletime, + unsigned int mode) +{ + u8 t2, t2i, t0; + u32 val32; + struct ide_timing *t; + + /* PIO Data Setup */ + t0 = DIV_ROUND_UP(cycletime, ideclk_period); + t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active, + ideclk_period); + + t2i = t0 - t2 - 1; + t2 -= 1; + + val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8)); + val32 |= (t2 << (dev ? 8 : 0)); + writel(val32, base + BK3710_DATSTB); + + val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8)); + val32 |= (t2i << (dev ? 8 : 0)); + writel(val32, base + BK3710_DATRCVR); + + if (mate) { + u8 mode2 = ide_get_best_pio_mode(mate, 255, 4); + + if (mode2 < mode) + mode = mode2; + } + + /* TASKFILE Setup */ + t = ide_timing_find_mode(XFER_PIO_0 + mode); + t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period); + t2 = DIV_ROUND_UP(t->act8b, ideclk_period); + + t2i = t0 - t2 - 1; + t2 -= 1; + + val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8)); + val32 |= (t2 << (dev ? 8 : 0)); + writel(val32, base + BK3710_REGSTB); + + val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8)); + val32 |= (t2i << (dev ? 8 : 0)); + writel(val32, base + BK3710_REGRCVR); +} + +static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed) +{ + int is_slave = drive->dn & 1; + void __iomem *base = (void *)drive->hwif->dma_base; + + if (xferspeed >= XFER_UDMA_0) { + palm_bk3710_setudmamode(base, is_slave, + xferspeed - XFER_UDMA_0); + } else { + palm_bk3710_setdmamode(base, is_slave, + drive->id[ATA_ID_EIDE_DMA_MIN], + xferspeed); + } +} + +static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio) +{ + unsigned int cycle_time; + int is_slave = drive->dn & 1; + ide_drive_t *mate; + void __iomem *base = (void *)drive->hwif->dma_base; + + /* + * Obtain the drive PIO data for tuning the Palm Chip registers + */ + cycle_time = ide_pio_cycle_time(drive, pio); + mate = ide_get_pair_dev(drive); + palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio); +} + +static void __devinit palm_bk3710_chipinit(void __iomem *base) +{ + /* + * enable the reset_en of ATA controller so that when ata signals + * are brought out, by writing into device config. at that + * time por_n signal should not be 'Z' and have a stable value. + */ + writel(0x0300, base + BK3710_MISCCTL); + + /* wait for some time and deassert the reset of ATA Device. */ + mdelay(100); + + /* Deassert the Reset */ + writel(0x0200, base + BK3710_MISCCTL); + + /* + * Program the IDETIMP Register Value based on the following assumptions + * + * (ATA_IDETIMP_IDEEN , ENABLE ) | + * (ATA_IDETIMP_SLVTIMEN , DISABLE) | + * (ATA_IDETIMP_RDYSMPL , 70NS) | + * (ATA_IDETIMP_RDYRCVRY , 50NS) | + * (ATA_IDETIMP_DMAFTIM1 , PIOCOMP) | + * (ATA_IDETIMP_PREPOST1 , DISABLE) | + * (ATA_IDETIMP_RDYSEN1 , DISABLE) | + * (ATA_IDETIMP_PIOFTIM1 , DISABLE) | + * (ATA_IDETIMP_DMAFTIM0 , PIOCOMP) | + * (ATA_IDETIMP_PREPOST0 , DISABLE) | + * (ATA_IDETIMP_RDYSEN0 , DISABLE) | + * (ATA_IDETIMP_PIOFTIM0 , DISABLE) + */ + writew(0xB388, base + BK3710_IDETIMP); + + /* + * Configure SIDETIM Register + * (ATA_SIDETIM_RDYSMPS1 ,120NS ) | + * (ATA_SIDETIM_RDYRCYS1 ,120NS ) + */ + writeb(0, base + BK3710_SIDETIM); + + /* + * UDMACTL Ultra-ATA DMA Control + * (ATA_UDMACTL_UDMAP1 , 0 ) | + * (ATA_UDMACTL_UDMAP0 , 0 ) + * + */ + writew(0, base + BK3710_UDMACTL); + + /* + * MISCCTL Miscellaneous Conrol Register + * (ATA_MISCCTL_RSTMODEP , 1) | + * (ATA_MISCCTL_RESETP , 0) | + * (ATA_MISCCTL_TIMORIDE , 1) + */ + writel(0x201, base + BK3710_MISCCTL); + + /* + * IORDYTMP IORDY Timer for Primary Register + * (ATA_IORDYTMP_IORDYTMP , 0xffff ) + */ + writel(0xFFFF, base + BK3710_IORDYTMP); + + /* + * Configure BMISP Register + * (ATA_BMISP_DMAEN1 , DISABLE ) | + * (ATA_BMISP_DMAEN0 , DISABLE ) | + * (ATA_BMISP_IORDYINT , CLEAR) | + * (ATA_BMISP_INTRSTAT , CLEAR) | + * (ATA_BMISP_DMAERROR , CLEAR) + */ + writew(0, base + BK3710_BMISP); + + palm_bk3710_setpiomode(base, NULL, 0, 600, 0); + palm_bk3710_setpiomode(base, NULL, 1, 600, 0); +} + +static u8 palm_bk3710_cable_detect(ide_hwif_t *hwif) +{ + return ATA_CBL_PATA80; +} + +static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif, + const struct ide_port_info *d) +{ + printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); + + if (ide_allocate_dma_engine(hwif)) + return -1; + + hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET; + + hwif->dma_ops = &sff_dma_ops; + + return 0; +} + +static const struct ide_port_ops palm_bk3710_ports_ops = { + .set_pio_mode = palm_bk3710_set_pio_mode, + .set_dma_mode = palm_bk3710_set_dma_mode, + .cable_detect = palm_bk3710_cable_detect, +}; + +static struct ide_port_info __devinitdata palm_bk3710_port_info = { + .init_dma = palm_bk3710_init_dma, + .port_ops = &palm_bk3710_ports_ops, + .host_flags = IDE_HFLAG_MMIO, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, +}; + +static int __init palm_bk3710_probe(struct platform_device *pdev) +{ + struct clk *clk; + struct resource *mem, *irq; + unsigned long base, rate; + int i, rc; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + + clk = clk_get(&pdev->dev, "IDECLK"); + if (IS_ERR(clk)) + return -ENODEV; + + clk_enable(clk); + rate = clk_get_rate(clk); + ideclk_period = 1000000000UL / rate; + + /* Register the IDE interface with Linux ATA Interface */ + memset(&hw, 0, sizeof(hw)); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (mem == NULL) { + printk(KERN_ERR "failed to get memory region resource\n"); + return -ENODEV; + } + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (irq == NULL) { + printk(KERN_ERR "failed to get IRQ resource\n"); + return -ENODEV; + } + + if (request_mem_region(mem->start, mem->end - mem->start + 1, + "palm_bk3710") == NULL) { + printk(KERN_ERR "failed to request memory region\n"); + return -EBUSY; + } + + base = IO_ADDRESS(mem->start); + + /* Configure the Palm Chip controller */ + palm_bk3710_chipinit((void __iomem *)base); + + for (i = 0; i < IDE_NR_PORTS - 2; i++) + hw.io_ports_array[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i; + hw.io_ports.ctl_addr = base + IDE_PALM_ATA_PRI_CTL_OFFSET; + hw.irq = irq->start; + hw.dev = &pdev->dev; + hw.chipset = ide_palm3710; + + palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 : + ATA_UDMA5; + + rc = ide_host_add(&palm_bk3710_port_info, hws, NULL); + if (rc) + goto out; + + return 0; +out: + printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n"); + return rc; +} + +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:palm_bk3710"); + +static struct platform_driver platform_bk_driver = { + .driver = { + .name = "palm_bk3710", + .owner = THIS_MODULE, + }, +}; + +static int __init palm_bk3710_init(void) +{ + return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe); +} + +module_init(palm_bk3710_init); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile deleted file mode 100644 index ab44a1f..0000000 --- a/drivers/ide/pci/Makefile +++ /dev/null @@ -1,43 +0,0 @@ - -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_CELLEB) += scc_pata.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_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_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_SGIIOC4) += sgiioc4.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 -ide-pci-generic-y += generic.o - -ifeq ($(CONFIG_BLK_DEV_CMD640), m) - obj-m += cmd640.o -endif - -EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c deleted file mode 100644 index 4142c69..0000000 --- a/drivers/ide/pci/aec62xx.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 1999-2002 Andre Hedrick - * Copyright (C) 2007 MontaVista Software, Inc. - * - */ - -#include -#include -#include -#include -#include - -#include - -#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_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct chipset_bus_clock_list_entry *bus_clock = host->host_priv; - u16 d_conf = 0; - u8 ultra = 0, ultra_conf = 0; - u8 tmp0 = 0, tmp1 = 0, tmp2 = 0; - 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_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct chipset_bus_clock_list_entry *bus_clock = host->host_priv; - u8 unit = drive->dn & 1; - u8 tmp1 = 0, tmp2 = 0; - u8 ultra = 0, drive_conf = 0, ultra_conf = 0; - 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_drive_t *drive, const u8 pio) -{ - drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0); -} - -static unsigned 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, ®49h); - pci_write_config_byte(dev, 0x49, reg49h & ~0x30); - /* Enable chip interrupt output. */ - pci_read_config_byte(dev, 0x4a, ®4ah); - pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01); - /* Enable burst mode. */ - pci_read_config_byte(dev, 0x4a, ®4ah); - pci_write_config_byte(dev, 0x4a, reg4ah | 0x80); - } - - return dev->irq; -} - -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[] __devinitdata = { - { /* 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 __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - const struct chipset_bus_clock_list_entry *bus_clock; - struct ide_port_info d; - u8 idx = id->driver_data; - int bus_speed = ide_pci_clk ? ide_pci_clk : 33; - int err; - - if (bus_speed <= 33) - bus_clock = aec6xxx_33_base; - else - bus_clock = aec6xxx_34_base; - - err = pci_enable_device(dev); - if (err) - return err; - - 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 __devexit aec62xx_remove(struct pci_dev *dev) -{ - ide_pci_remove(dev); - pci_disable_device(dev); -} - -static const struct pci_device_id aec62xx_pci_tbl[] = { - { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 }, - { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 }, - { 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 = __devexit_p(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"); diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c deleted file mode 100644 index daf9dce..0000000 --- a/drivers/ide/pci/alim15x3.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright (C) 1998-2000 Michel Aubry, Maintainer - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer - * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer - * - * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) - * May be copied or modified under the terms of the GNU General Public License - * Copyright (C) 2002 Alan Cox - * ALi (now ULi M5228) support by Clear Zhang - * Copyright (C) 2007 MontaVista Software, Inc. - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * - * (U)DMA capable version of ali 1533/1543(C), 1535(D) - * - ********************************************************************** - * 9/7/99 --Parts from the above author are included and need to be - * converted into standard interface, once I finish the thought. - * - * Recent changes - * Don't use LBA48 mode on ALi <= 0xC4 - * Don't poke 0x79 with a non ALi northbridge - * Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang) - * Allow UDMA6 on revisions > 0xC4 - * - * Documentation - * Chipset documentation available under NDA only - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "alim15x3" - -/* - * Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking - * (this is DANGEROUS and could result in data corruption). - */ -static int wdc_udma; - -module_param(wdc_udma, bool, 0); -MODULE_PARM_DESC(wdc_udma, - "allow UDMA on M1543C-E chipset for WDC disks (DANGEROUS)"); - -/* - * ALi devices are not plug in. Otherwise these static values would - * need to go. They ought to go away anyway - */ - -static u8 m5229_revision; -static u8 chip_is_1543c_e; -static struct pci_dev *isa_dev; - -/** - * ali_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * Program the controller for the given PIO mode. - */ - -static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); - int s_time = t->setup, a_time = t->active, c_time = t->cycle; - u8 s_clc, a_clc, r_clc; - unsigned long flags; - int bus_speed = ide_pci_clk ? ide_pci_clk : 33; - int port = hwif->channel ? 0x5c : 0x58; - int portFIFO = hwif->channel ? 0x55 : 0x54; - u8 cd_dma_fifo = 0, unit = drive->dn & 1; - - if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) - s_clc = 0; - if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) - a_clc = 0; - - if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { - r_clc = 1; - } else { - if (r_clc >= 16) - r_clc = 0; - } - local_irq_save(flags); - - /* - * PIO mode => ATA FIFO on, ATAPI FIFO off - */ - pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); - if (drive->media==ide_disk) { - if (unit) { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); - } else { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); - } - } else { - if (unit) { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); - } else { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); - } - } - - pci_write_config_byte(dev, port, s_clc); - pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc); - local_irq_restore(flags); -} - -/** - * ali_udma_filter - compute UDMA mask - * @drive: IDE device - * - * Return available UDMA modes. - * - * The actual rules for the ALi are: - * No UDMA on revisions <= 0x20 - * Disk only for revisions < 0xC2 - * Not WDC drives on M1543C-E (?) - */ - -static u8 ali_udma_filter(ide_drive_t *drive) -{ - if (m5229_revision > 0x20 && m5229_revision < 0xC2) { - if (drive->media != ide_disk) - return 0; - if (wdc_udma == 0 && chip_is_1543c_e && - strstr((char *)&drive->id[ATA_ID_PROD], "WDC ")) - return 0; - } - - return drive->hwif->ultra_mask; -} - -/** - * ali_set_dma_mode - set host controller for DMA mode - * @drive: drive - * @speed: DMA mode - * - * Configure the hardware for the desired IDE transfer mode. - */ - -static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 speed1 = speed; - u8 unit = drive->dn & 1; - u8 tmpbyte = 0x00; - int m5229_udma = (hwif->channel) ? 0x57 : 0x56; - - if (speed == XFER_UDMA_6) - speed1 = 0x47; - - if (speed < XFER_UDMA_0) { - u8 ultra_enable = (unit) ? 0x7f : 0xf7; - /* - * clear "ultra enable" bit - */ - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= ultra_enable; - pci_write_config_byte(dev, m5229_udma, tmpbyte); - - /* - * FIXME: Oh, my... DMA timings are never set. - */ - } else { - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= (0x0f << ((1-unit) << 2)); - /* - * enable ultra dma and set timing - */ - tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2)); - pci_write_config_byte(dev, m5229_udma, tmpbyte); - if (speed >= XFER_UDMA_3) { - pci_read_config_byte(dev, 0x4b, &tmpbyte); - tmpbyte |= 1; - pci_write_config_byte(dev, 0x4b, tmpbyte); - } - } -} - -/** - * ali15x3_dma_setup - begin a DMA phase - * @drive: target device - * - * Returns 1 if the DMA cannot be performed, zero on success. - */ - -static int ali15x3_dma_setup(ide_drive_t *drive) -{ - if (m5229_revision < 0xC2 && drive->media != ide_disk) { - if (rq_data_dir(drive->hwif->hwgroup->rq)) - return 1; /* try PIO instead of DMA */ - } - return ide_dma_setup(drive); -} - -/** - * init_chipset_ali15x3 - Initialise an ALi IDE controller - * @dev: PCI device - * - * This function initializes the ALI IDE controller and where - * appropriate also sets up the 1533 southbridge. - */ - -static unsigned int init_chipset_ali15x3(struct pci_dev *dev) -{ - unsigned long flags; - u8 tmpbyte; - struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0)); - - m5229_revision = dev->revision; - - isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); - - local_irq_save(flags); - - if (m5229_revision < 0xC2) { - /* - * revision 0x20 (1543-E, 1543-F) - * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) - * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - /* - * clear bit 7 - */ - pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); - /* - * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 - */ - if (m5229_revision >= 0x20 && isa_dev) { - pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); - chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; - } - goto out; - } - - /* - * 1543C-B?, 1535, 1535D, 1553 - * Note 1: not all "motherboard" support this detection - * Note 2: if no udma 66 device, the detection may "error". - * but in this case, we will not set the device to - * ultra 66, the detection result is not important - */ - - /* - * enable "Cable Detection", m5229, 0x4b, bit3 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); - - /* - * We should only tune the 1533 enable if we are using an ALi - * North bridge. We might have no north found on some zany - * box without a device at 0:0.0. The ALi bridge will be at - * 0:0.0 so if we didn't find one we know what is cooking. - */ - if (north && north->vendor != PCI_VENDOR_ID_AL) - goto out; - - if (m5229_revision < 0xC5 && isa_dev) - { - /* - * set south-bridge's enable bit, m1533, 0x79 - */ - - pci_read_config_byte(isa_dev, 0x79, &tmpbyte); - if (m5229_revision == 0xC2) { - /* - * 1543C-B0 (m1533, 0x79, bit 2) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); - } else if (m5229_revision >= 0xC3) { - /* - * 1553/1535 (m1533, 0x79, bit 1) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); - } - } - -out: - /* - * CD_ROM DMA on (m5229, 0x53, bit0) - * Enable this bit even if we want to use PIO. - * PIO FIFO off (m5229, 0x53, bit1) - * The hardware will use 0x54h and 0x55h to control PIO FIFO. - * (Not on later devices it seems) - * - * 0x53 changes meaning on later revs - we must no touch - * bit 1 on them. Need to check if 0x20 is the right break. - */ - if (m5229_revision >= 0x20) { - pci_read_config_byte(dev, 0x53, &tmpbyte); - - if (m5229_revision <= 0x20) - tmpbyte = (tmpbyte & (~0x02)) | 0x01; - else if (m5229_revision == 0xc7 || m5229_revision == 0xc8) - tmpbyte |= 0x03; - else - tmpbyte |= 0x01; - - pci_write_config_byte(dev, 0x53, tmpbyte); - } - pci_dev_put(north); - pci_dev_put(isa_dev); - local_irq_restore(flags); - return 0; -} - -/* - * Cable special cases - */ - -static const struct dmi_system_id cable_dmi_table[] = { - { - .ident = "HP Pavilion N5430", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"), - }, - }, - { - .ident = "Toshiba Satellite S1800-814", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"), - }, - }, - { } -}; - -static int ali_cable_override(struct pci_dev *pdev) -{ - /* Fujitsu P2000 */ - if (pdev->subsystem_vendor == 0x10CF && - pdev->subsystem_device == 0x10AF) - return 1; - - /* Mitac 8317 (Winbook-A) and relatives */ - if (pdev->subsystem_vendor == 0x1071 && - pdev->subsystem_device == 0x8317) - return 1; - - /* Systems by DMI */ - if (dmi_check_system(cable_dmi_table)) - return 1; - - return 0; -} - -/** - * ali_cable_detect - cable detection - * @hwif: IDE interface - * - * This checks if the controller and the cable are capable - * of UDMA66 transfers. It doesn't check the drives. - * But see note 2 below! - * - * FIXME: frobs bits that are not defined on newer ALi devicea - */ - -static u8 ali_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long flags; - u8 cbl = ATA_CBL_PATA40, tmpbyte; - - local_irq_save(flags); - - if (m5229_revision >= 0xC2) { - /* - * m5229 80-pin cable detection (from Host View) - * - * 0x4a bit0 is 0 => primary channel has 80-pin - * 0x4a bit1 is 0 => secondary channel has 80-pin - * - * Certain laptops use short but suitable cables - * and don't implement the detect logic. - */ - if (ali_cable_override(dev)) - cbl = ATA_CBL_PATA40_SHORT; - else { - pci_read_config_byte(dev, 0x4a, &tmpbyte); - if ((tmpbyte & (1 << hwif->channel)) == 0) - cbl = ATA_CBL_PATA80; - } - } - - local_irq_restore(flags); - - return cbl; -} - -#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) -/** - * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff - * @hwif: interface to configure - * - * Obtain the IRQ tables for an ALi based IDE solution on the PC - * class platforms. This part of the code isn't applicable to the - * Sparc and PowerPC systems. - */ - -static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 ideic, inmir; - s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, - 1, 11, 0, 12, 0, 14, 0, 15 }; - int irq = -1; - - if (dev->device == PCI_DEVICE_ID_AL_M5229) - hwif->irq = hwif->channel ? 15 : 14; - - if (isa_dev) { - /* - * read IDE interface control - */ - pci_read_config_byte(isa_dev, 0x58, &ideic); - - /* bit0, bit1 */ - ideic = ideic & 0x03; - - /* get IRQ for IDE Controller */ - if ((hwif->channel && ideic == 0x03) || - (!hwif->channel && !ideic)) { - /* - * get SIRQ1 routing table - */ - pci_read_config_byte(isa_dev, 0x44, &inmir); - inmir = inmir & 0x0f; - irq = irq_routing_table[inmir]; - } else if (hwif->channel && !(ideic & 0x01)) { - /* - * get SIRQ2 routing table - */ - pci_read_config_byte(isa_dev, 0x75, &inmir); - inmir = inmir & 0x0f; - irq = irq_routing_table[inmir]; - } - if(irq >= 0) - hwif->irq = irq; - } -} -#else -#define init_hwif_ali15x3 NULL -#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */ - -/** - * init_dma_ali15x3 - set up DMA on ALi15x3 - * @hwif: IDE interface - * @d: IDE port info - * - * Set up the DMA functionality on the ALi 15x3. - */ - -static int __devinit init_dma_ali15x3(ide_hwif_t *hwif, - const struct ide_port_info *d) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long base = ide_pci_dma_base(hwif, d); - - if (base == 0) - return -1; - - hwif->dma_base = base; - - if (ide_pci_check_simplex(hwif, d) < 0) - return -1; - - if (ide_pci_set_master(dev, d->name) < 0) - return -1; - - if (!hwif->channel) - outb(inb(base + 2) & 0x60, base + 2); - - printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", - hwif->name, base, base + 7); - - if (ide_allocate_dma_engine(hwif)) - return -1; - - hwif->dma_ops = &sff_dma_ops; - - return 0; -} - -static const struct ide_port_ops ali_port_ops = { - .set_pio_mode = ali_set_pio_mode, - .set_dma_mode = ali_set_dma_mode, - .udma_filter = ali_udma_filter, - .cable_detect = ali_cable_detect, -}; - -static const struct ide_dma_ops ali_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ali15x3_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = ide_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_port_info ali15x3_chipset __devinitdata = { - .name = DRV_NAME, - .init_chipset = init_chipset_ali15x3, - .init_hwif = init_hwif_ali15x3, - .init_dma = init_dma_ali15x3, - .port_ops = &ali_port_ops, - .pio_mask = ATA_PIO5, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, -}; - -/** - * alim15x3_init_one - set up an ALi15x3 IDE controller - * @dev: PCI device to set up - * - * Perform the actual set up for an ALi15x3 that has been found by the - * hot plug layer. - */ - -static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct ide_port_info d = ali15x3_chipset; - u8 rev = dev->revision, idx = id->driver_data; - - /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ - if (rev <= 0xC4) - d.host_flags |= IDE_HFLAG_NO_LBA48_DMA; - - if (rev >= 0x20) { - if (rev == 0x20) - d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA; - - if (rev < 0xC2) - d.udma_mask = ATA_UDMA2; - else if (rev == 0xC2 || rev == 0xC3) - d.udma_mask = ATA_UDMA4; - else if (rev == 0xC4) - d.udma_mask = ATA_UDMA5; - else - d.udma_mask = ATA_UDMA6; - - d.dma_ops = &ali_dma_ops; - } else { - d.host_flags |= IDE_HFLAG_NO_DMA; - - d.mwdma_mask = d.swdma_mask = 0; - } - - if (idx == 0) - d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX; - - return ide_pci_init_one(dev, &d, NULL); -} - - -static const struct pci_device_id alim15x3_pci_tbl[] = { - { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 }, - { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl); - -static struct pci_driver alim15x3_pci_driver = { - .name = "ALI15x3_IDE", - .id_table = alim15x3_pci_tbl, - .probe = alim15x3_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init ali15x3_ide_init(void) -{ - return ide_pci_register_driver(&alim15x3_pci_driver); -} - -static void __exit ali15x3_ide_exit(void) -{ - return pci_unregister_driver(&alim15x3_pci_driver); -} - -module_init(ali15x3_ide_init); -module_exit(ali15x3_ide_exit); - -MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox"); -MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c deleted file mode 100644 index 81ec731..0000000 --- a/drivers/ide/pci/amd74xx.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * 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 Bartlomiej Zolnierkiewicz - * - * Based on the work of: - * Andre Hedrick - */ - -/* - * 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. - */ - -#include -#include -#include -#include -#include - -#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; - } - - 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_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - ide_drive_t *peer = hwif->drives + (~drive->dn & 1); - struct ide_timing t, p; - int T, UT; - u8 udma_mask = hwif->ultra_mask; - - T = 1000000000 / amd_clock; - UT = (udma_mask == ATA_UDMA2) ? T : (T / 2); - - ide_timing_compute(drive, speed, &t, T, UT); - - if (peer->dev_flags & IDE_DFLAG_PRESENT) { - ide_timing_compute(peer, peer->current_speed, &p, T, UT); - ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); - } - - 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_drive_t *drive, const u8 pio) -{ - amd_set_drive(drive, XFER_PIO_0 + pio); -} - -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 unsigned 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->vendor == PCI_DEVICE_ID_AMD_VIPER_7411) - t &= 0x0f; - else - t |= 0xf0; - pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t); - - return dev->irq; -} - -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 void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - if (hwif->irq == 0) /* 0 is bogus but will do for now */ - hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); -} - -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, \ - .init_hwif = init_hwif_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, \ - .init_hwif = init_hwif_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[] __devinitdata = { - /* 0: AMD7401 */ DECLARE_AMD_DEV(0x00, ATA_UDMA2), - /* 1: AMD7409 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4), - /* 2: AMD7411/7441 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5), - /* 3: AMD8111 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA6), - - /* 4: NFORCE */ DECLARE_NV_DEV(ATA_UDMA5), - /* 5: >= NFORCE2 */ DECLARE_NV_DEV(ATA_UDMA6), - - /* 6: AMD5536 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5), -}; - -static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - 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; - } - - 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"); -MODULE_DESCRIPTION("AMD PCI IDE driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c deleted file mode 100644 index b2735d2..0000000 --- a/drivers/ide/pci/atiixp.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2003 ATI Inc. - * Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz - */ - -#include -#include -#include -#include -#include -#include - -#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 - -typedef struct { - u8 command_width; - u8 recover_width; -} atiixp_ide_timing; - -static atiixp_ide_timing pio_timing[] = { - { 0x05, 0x0d }, - { 0x04, 0x07 }, - { 0x03, 0x04 }, - { 0x02, 0x02 }, - { 0x02, 0x00 }, -}; - -static 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 - * @drive: drive - * @pio: PIO mode number - * - * Set the interface PIO mode. - */ - -static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - unsigned long flags; - int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; - u32 pio_timing_data; - u16 pio_mode_data; - - 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 - * @drive: drive - * @speed: DMA mode - * - * 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_drive_t *drive, const u8 speed) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - unsigned long flags; - int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; - u32 tmp32; - u16 tmp16; - u16 udma_ctl = 0; - - 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[] __devinitdata = { - { /* 0: IXP200/300/400/700 */ - .name = DRV_NAME, - .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, - .port_ops = &atiixp_port_ops, - .host_flags = IDE_HFLAG_LEGACY_IRQS, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA5, - }, - { /* 1: IXP600 */ - .name = DRV_NAME, - .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}}, - .port_ops = &atiixp_port_ops, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS, - .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 __devinit 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 }, - { 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"); diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c deleted file mode 100644 index e430664..0000000 --- a/drivers/ide/pci/cmd640.c +++ /dev/null @@ -1,836 +0,0 @@ -/* - * Copyright (C) 1995-1996 Linus Torvalds & authors (see below) - */ - -/* - * Original authors: abramov@cecmow.enet.dec.com (Igor Abramov) - * mlord@pobox.com (Mark Lord) - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This file provides support for the advanced features and bugs - * of IDE interfaces using the CMD Technologies 0640 IDE interface chip. - * - * These chips are basically fucked by design, and getting this driver - * to work on every motherboard design that uses this screwed chip seems - * bloody well impossible. However, we're still trying. - * - * Version 0.97 worked for everybody. - * - * User feedback is essential. Many thanks to the beta test team: - * - * A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com, - * bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz, - * chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de, - * derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de, - * flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net, - * j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net, - * kerouac@ssnet.com, meskes@informatik.rwth-aachen.de, hzoli@cs.elte.hu, - * peter@udgaard.isgtec.com, phil@tazenda.demon.co.uk, roadcapw@cfw.com, - * s0033las@sun10.vsz.bme.hu, schaffer@tam.cornell.edu, sjd@slip.net, - * steve@ei.org, ulrpeg@bigcomm.gun.de, ism@tardis.ed.ac.uk, mack@cray.com - * liug@mama.indstate.edu, and others. - * - * Version 0.01 Initial version, hacked out of ide.c, - * and #include'd rather than compiled separately. - * This will get cleaned up in a subsequent release. - * - * Version 0.02 Fixes for vlb initialization code, enable prefetch - * for versions 'B' and 'C' of chip by default, - * some code cleanup. - * - * Version 0.03 Added reset of secondary interface, - * and black list for devices which are not compatible - * with prefetch mode. Separate function for setting - * prefetch is added, possibly it will be called some - * day from ioctl processing code. - * - * Version 0.04 Now configs/compiles separate from ide.c - * - * Version 0.05 Major rewrite of interface timing code. - * Added new function cmd640_set_mode to set PIO mode - * from ioctl call. New drives added to black list. - * - * Version 0.06 More code cleanup. Prefetch is enabled only for - * detected hard drives, not included in prefetch - * black list. - * - * Version 0.07 Changed to more conservative drive tuning policy. - * Unknown drives, which report PIO < 4 are set to - * (reported_PIO - 1) if it is supported, or to PIO0. - * List of known drives extended by info provided by - * CMD at their ftp site. - * - * Version 0.08 Added autotune/noautotune support. - * - * Version 0.09 Try to be smarter about 2nd port enabling. - * Version 0.10 Be nice and don't reset 2nd port. - * Version 0.11 Try to handle more weird situations. - * - * Version 0.12 Lots of bug fixes from Laszlo Peter - * irq unmasking disabled for reliability. - * try to be even smarter about the second port. - * tidy up source code formatting. - * Version 0.13 permit irq unmasking again. - * Version 0.90 massive code cleanup, some bugs fixed. - * defaults all drives to PIO mode0, prefetch off. - * autotune is OFF by default, with compile time flag. - * prefetch can be turned OFF/ON using "hdparm -p8/-p9" - * (requires hdparm-3.1 or newer) - * Version 0.91 first release to linux-kernel list. - * Version 0.92 move initial reg dump to separate callable function - * change "readahead" to "prefetch" to avoid confusion - * Version 0.95 respect original BIOS timings unless autotuning. - * tons of code cleanup and rearrangement. - * added CONFIG_BLK_DEV_CMD640_ENHANCED option - * prevent use of unmask when prefetch is on - * Version 0.96 prevent use of io_32bit when prefetch is off - * Version 0.97 fix VLB secondary interface for sjd@slip.net - * other minor tune-ups: 0.96 was very good. - * Version 0.98 ignore PCI version when disabled by BIOS - * Version 0.99 display setup/active/recovery clocks with PIO mode - * Version 1.00 Mmm.. cannot depend on PCMD_ENA in all systems - * Version 1.01 slow/fast devsel can be selected with "hdparm -p6/-p7" - * ("fast" is necessary for 32bit I/O in some systems) - * Version 1.02 fix bug that resulted in slow "setup times" - * (patch courtesy of Zoltan Hidvegi) - */ - -#define CMD640_PREFETCH_MASKS 1 - -/*#define CMD640_DUMP_REGS */ - -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "cmd640" - -static int cmd640_vlb; - -/* - * CMD640 specific registers definition. - */ - -#define VID 0x00 -#define DID 0x02 -#define PCMD 0x04 -#define PCMD_ENA 0x01 -#define PSTTS 0x06 -#define REVID 0x08 -#define PROGIF 0x09 -#define SUBCL 0x0a -#define BASCL 0x0b -#define BaseA0 0x10 -#define BaseA1 0x14 -#define BaseA2 0x18 -#define BaseA3 0x1c -#define INTLINE 0x3c -#define INPINE 0x3d - -#define CFR 0x50 -#define CFR_DEVREV 0x03 -#define CFR_IDE01INTR 0x04 -#define CFR_DEVID 0x18 -#define CFR_AT_VESA_078h 0x20 -#define CFR_DSA1 0x40 -#define CFR_DSA0 0x80 - -#define CNTRL 0x51 -#define CNTRL_DIS_RA0 0x40 -#define CNTRL_DIS_RA1 0x80 -#define CNTRL_ENA_2ND 0x08 - -#define CMDTIM 0x52 -#define ARTTIM0 0x53 -#define DRWTIM0 0x54 -#define ARTTIM1 0x55 -#define DRWTIM1 0x56 -#define ARTTIM23 0x57 -#define ARTTIM23_DIS_RA2 0x04 -#define ARTTIM23_DIS_RA3 0x08 -#define DRWTIM23 0x58 -#define BRST 0x59 - -/* - * Registers and masks for easy access by drive index: - */ -static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; -static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - -static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; -static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; - -/* - * Current cmd640 timing values for each drive. - * The defaults for each are the slowest possible timings. - */ -static u8 setup_counts[4] = {4, 4, 4, 4}; /* Address setup count (in clocks) */ -static u8 active_counts[4] = {16, 16, 16, 16}; /* Active count (encoded) */ -static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ - -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - -static DEFINE_SPINLOCK(cmd640_lock); - -/* - * Interface to access cmd640x registers - */ -static unsigned int cmd640_key; -static void (*__put_cmd640_reg)(u16 reg, u8 val); -static u8 (*__get_cmd640_reg)(u16 reg); - -/* - * This is read from the CFR reg, and is used in several places. - */ -static unsigned int cmd640_chip_version; - -/* - * The CMD640x chip does not support DWORD config write cycles, but some - * of the BIOSes use them to implement the config services. - * Therefore, we must use direct IO instead. - */ - -/* PCI method 1 access */ - -static void put_cmd640_reg_pci1(u16 reg, u8 val) -{ - outl_p((reg & 0xfc) | cmd640_key, 0xcf8); - outb_p(val, (reg & 3) | 0xcfc); -} - -static u8 get_cmd640_reg_pci1(u16 reg) -{ - outl_p((reg & 0xfc) | cmd640_key, 0xcf8); - return inb_p((reg & 3) | 0xcfc); -} - -/* PCI method 2 access (from CMD datasheet) */ - -static void put_cmd640_reg_pci2(u16 reg, u8 val) -{ - outb_p(0x10, 0xcf8); - outb_p(val, cmd640_key + reg); - outb_p(0, 0xcf8); -} - -static u8 get_cmd640_reg_pci2(u16 reg) -{ - u8 b; - - outb_p(0x10, 0xcf8); - b = inb_p(cmd640_key + reg); - outb_p(0, 0xcf8); - return b; -} - -/* VLB access */ - -static void put_cmd640_reg_vlb(u16 reg, u8 val) -{ - outb_p(reg, cmd640_key); - outb_p(val, cmd640_key + 4); -} - -static u8 get_cmd640_reg_vlb(u16 reg) -{ - outb_p(reg, cmd640_key); - return inb_p(cmd640_key + 4); -} - -static u8 get_cmd640_reg(u16 reg) -{ - unsigned long flags; - u8 b; - - spin_lock_irqsave(&cmd640_lock, flags); - b = __get_cmd640_reg(reg); - spin_unlock_irqrestore(&cmd640_lock, flags); - return b; -} - -static void put_cmd640_reg(u16 reg, u8 val) -{ - unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - __put_cmd640_reg(reg, val); - spin_unlock_irqrestore(&cmd640_lock, flags); -} - -static int __init match_pci_cmd640_device(void) -{ - const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; - unsigned int i; - for (i = 0; i < 4; i++) { - if (get_cmd640_reg(i) != ven_dev[i]) - return 0; - } -#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT - if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) { - printk("ide: cmd640 on PCI disabled by BIOS\n"); - return 0; - } -#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */ - return 1; /* success */ -} - -/* - * Probe for CMD640x -- pci method 1 - */ -static int __init probe_for_cmd640_pci1(void) -{ - __get_cmd640_reg = get_cmd640_reg_pci1; - __put_cmd640_reg = put_cmd640_reg_pci1; - for (cmd640_key = 0x80000000; - cmd640_key <= 0x8000f800; - cmd640_key += 0x800) { - if (match_pci_cmd640_device()) - return 1; /* success */ - } - return 0; -} - -/* - * Probe for CMD640x -- pci method 2 - */ -static int __init probe_for_cmd640_pci2(void) -{ - __get_cmd640_reg = get_cmd640_reg_pci2; - __put_cmd640_reg = put_cmd640_reg_pci2; - for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { - if (match_pci_cmd640_device()) - return 1; /* success */ - } - return 0; -} - -/* - * Probe for CMD640x -- vlb - */ -static int __init probe_for_cmd640_vlb(void) -{ - u8 b; - - __get_cmd640_reg = get_cmd640_reg_vlb; - __put_cmd640_reg = put_cmd640_reg_vlb; - cmd640_key = 0x178; - b = get_cmd640_reg(CFR); - if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { - cmd640_key = 0x78; - b = get_cmd640_reg(CFR); - if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h)) - return 0; - } - return 1; /* success */ -} - -/* - * Returns 1 if an IDE interface/drive exists at 0x170, - * Returns 0 otherwise. - */ -static int __init secondary_port_responding(void) -{ - unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - - outb_p(0x0a, 0x176); /* select drive0 */ - udelay(100); - if ((inb_p(0x176) & 0x1f) != 0x0a) { - outb_p(0x1a, 0x176); /* select drive1 */ - udelay(100); - if ((inb_p(0x176) & 0x1f) != 0x1a) { - spin_unlock_irqrestore(&cmd640_lock, flags); - return 0; /* nothing responded */ - } - } - spin_unlock_irqrestore(&cmd640_lock, flags); - return 1; /* success */ -} - -#ifdef CMD640_DUMP_REGS -/* - * Dump out all cmd640 registers. May be called from ide.c - */ -static void cmd640_dump_regs(void) -{ - unsigned int reg = cmd640_vlb ? 0x50 : 0x00; - - /* Dump current state of chip registers */ - printk("ide: cmd640 internal register dump:"); - for (; reg <= 0x59; reg++) { - if (!(reg & 0x0f)) - printk("\n%04x:", reg); - printk(" %02x", get_cmd640_reg(reg)); - } - printk("\n"); -} -#endif - -static void __set_prefetch_mode(ide_drive_t *drive, int mode) -{ - if (mode) { /* want prefetch on? */ -#if CMD640_PREFETCH_MASKS - drive->dev_flags |= IDE_DFLAG_NO_UNMASK; - drive->dev_flags &= ~IDE_DFLAG_UNMASK; -#endif - drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT; - } else { - drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK; - drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT; - drive->io_32bit = 0; - } -} - -#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED -/* - * Check whether prefetch is on for a drive, - * and initialize the unmask flags for safe operation. - */ -static void __init check_prefetch(ide_drive_t *drive, unsigned int index) -{ - u8 b = get_cmd640_reg(prefetch_regs[index]); - - __set_prefetch_mode(drive, (b & prefetch_masks[index]) ? 0 : 1); -} -#else - -/* - * Sets prefetch mode for a drive. - */ -static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode) -{ - unsigned long flags; - int reg = prefetch_regs[index]; - u8 b; - - spin_lock_irqsave(&cmd640_lock, flags); - b = __get_cmd640_reg(reg); - __set_prefetch_mode(drive, mode); - if (mode) - b &= ~prefetch_masks[index]; /* enable prefetch */ - else - b |= prefetch_masks[index]; /* disable prefetch */ - __put_cmd640_reg(reg, b); - spin_unlock_irqrestore(&cmd640_lock, flags); -} - -/* - * Dump out current drive clocks settings - */ -static void display_clocks(unsigned int index) -{ - u8 active_count, recovery_count; - - active_count = active_counts[index]; - if (active_count == 1) - ++active_count; - recovery_count = recovery_counts[index]; - if (active_count > 3 && recovery_count == 1) - ++recovery_count; - if (cmd640_chip_version > 1) - recovery_count += 1; /* cmd640b uses (count + 1)*/ - printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count); -} - -/* - * Pack active and recovery counts into single byte representation - * used by controller - */ -static inline u8 pack_nibbles(u8 upper, u8 lower) -{ - return ((upper & 0x0f) << 4) | (lower & 0x0f); -} - -/* - * This routine writes the prepared setup/active/recovery counts - * for a drive into the cmd640 chipset registers to active them. - */ -static void program_drive_counts(ide_drive_t *drive, unsigned int index) -{ - unsigned long flags; - u8 setup_count = setup_counts[index]; - u8 active_count = active_counts[index]; - u8 recovery_count = recovery_counts[index]; - - /* - * Set up address setup count and drive read/write timing registers. - * Primary interface has individual count/timing registers for - * each drive. Secondary interface has one common set of registers, - * so we merge the timings, using the slowest value for each timing. - */ - if (index > 1) { - ide_hwif_t *hwif = drive->hwif; - ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)]; - unsigned int mate = index ^ 1; - - if (peer->dev_flags & IDE_DFLAG_PRESENT) { - if (setup_count < setup_counts[mate]) - setup_count = setup_counts[mate]; - if (active_count < active_counts[mate]) - active_count = active_counts[mate]; - if (recovery_count < recovery_counts[mate]) - recovery_count = recovery_counts[mate]; - } - } - - /* - * Convert setup_count to internal chipset representation - */ - switch (setup_count) { - case 4: setup_count = 0x00; break; - case 3: setup_count = 0x80; break; - case 1: - case 2: setup_count = 0x40; break; - default: setup_count = 0xc0; /* case 5 */ - } - - /* - * Now that everything is ready, program the new timings - */ - spin_lock_irqsave(&cmd640_lock, flags); - /* - * Program the address_setup clocks into ARTTIM reg, - * and then the active/recovery counts into the DRWTIM reg - * (this converts counts of 16 into counts of zero -- okay). - */ - setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f; - __put_cmd640_reg(arttim_regs[index], setup_count); - __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); - spin_unlock_irqrestore(&cmd640_lock, flags); -} - -/* - * Set a specific pio_mode for a drive - */ -static void cmd640_set_mode(ide_drive_t *drive, unsigned int index, - u8 pio_mode, unsigned int cycle_time) -{ - struct ide_timing *t; - int setup_time, active_time, recovery_time, clock_time; - u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count; - int bus_speed; - - if (cmd640_vlb) - bus_speed = ide_vlb_clk ? ide_vlb_clk : 50; - else - bus_speed = ide_pci_clk ? ide_pci_clk : 33; - - if (pio_mode > 5) - pio_mode = 5; - - t = ide_timing_find_mode(XFER_PIO_0 + pio_mode); - setup_time = t->setup; - active_time = t->active; - - recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; - cycle_count = DIV_ROUND_UP(cycle_time, clock_time); - - setup_count = DIV_ROUND_UP(setup_time, clock_time); - - active_count = DIV_ROUND_UP(active_time, clock_time); - if (active_count < 2) - active_count = 2; /* minimum allowed by cmd640 */ - - recovery_count = DIV_ROUND_UP(recovery_time, clock_time); - recovery_count2 = cycle_count - (setup_count + active_count); - if (recovery_count2 > recovery_count) - recovery_count = recovery_count2; - if (recovery_count < 2) - recovery_count = 2; /* minimum allowed by cmd640 */ - if (recovery_count > 17) { - active_count += recovery_count - 17; - recovery_count = 17; - } - if (active_count > 16) - active_count = 16; /* maximum allowed by cmd640 */ - if (cmd640_chip_version > 1) - recovery_count -= 1; /* cmd640b uses (count + 1)*/ - if (recovery_count > 16) - recovery_count = 16; /* maximum allowed by cmd640 */ - - setup_counts[index] = setup_count; - active_counts[index] = active_count; - recovery_counts[index] = recovery_count; - - /* - * In a perfect world, we might set the drive pio mode here - * (using WIN_SETFEATURE) before continuing. - * - * But we do not, because: - * 1) this is the wrong place to do it (proper is do_special() in ide.c) - * 2) in practice this is rarely, if ever, necessary - */ - program_drive_counts(drive, index); -} - -static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - unsigned int index = 0, cycle_time; - u8 b; - - switch (pio) { - case 6: /* set fast-devsel off */ - case 7: /* set fast-devsel on */ - b = get_cmd640_reg(CNTRL) & ~0x27; - if (pio & 1) - b |= 0x27; - put_cmd640_reg(CNTRL, b); - printk("%s: %sabled cmd640 fast host timing (devsel)\n", - drive->name, (pio & 1) ? "en" : "dis"); - return; - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - set_prefetch_mode(drive, index, pio & 1); - printk("%s: %sabled cmd640 prefetch\n", - drive->name, (pio & 1) ? "en" : "dis"); - return; - } - - cycle_time = ide_pio_cycle_time(drive, pio); - cmd640_set_mode(drive, index, pio, cycle_time); - - printk("%s: selected cmd640 PIO mode%d (%dns)", - drive->name, pio, cycle_time); - - display_clocks(index); -} -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - -static void cmd640_init_dev(ide_drive_t *drive) -{ - unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1); - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - /* - * Reset timing to the slowest speed and turn off prefetch. - * This way, the drive identify code has a better chance. - */ - setup_counts[i] = 4; /* max possible */ - active_counts[i] = 16; /* max possible */ - recovery_counts[i] = 16; /* max possible */ - program_drive_counts(drive, i); - set_prefetch_mode(drive, i, 0); - printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch cleared\n", i); -#else - /* - * Set the drive unmask flags to match the prefetch setting. - */ - check_prefetch(drive, i); - printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n", - i, (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) ? "off" : "on"); -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ -} - - -static const struct ide_port_ops cmd640_port_ops = { - .init_dev = cmd640_init_dev, -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - .set_pio_mode = cmd640_set_pio_mode, -#endif -}; - -static int pci_conf1(void) -{ - unsigned long flags; - u32 tmp; - - spin_lock_irqsave(&cmd640_lock, flags); - outb(0x01, 0xCFB); - tmp = inl(0xCF8); - outl(0x80000000, 0xCF8); - if (inl(0xCF8) == 0x80000000) { - outl(tmp, 0xCF8); - spin_unlock_irqrestore(&cmd640_lock, flags); - return 1; - } - outl(tmp, 0xCF8); - spin_unlock_irqrestore(&cmd640_lock, flags); - return 0; -} - -static int pci_conf2(void) -{ - unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - outb(0x00, 0xCFB); - outb(0x00, 0xCF8); - outb(0x00, 0xCFA); - if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) { - spin_unlock_irqrestore(&cmd640_lock, flags); - return 1; - } - spin_unlock_irqrestore(&cmd640_lock, flags); - return 0; -} - -static const struct ide_port_info cmd640_port_info __initdata = { - .chipset = ide_cmd640, - .host_flags = IDE_HFLAG_SERIALIZE | - IDE_HFLAG_NO_DMA | - IDE_HFLAG_ABUSE_PREFETCH | - IDE_HFLAG_ABUSE_FAST_DEVSEL, - .port_ops = &cmd640_port_ops, - .pio_mask = ATA_PIO5, -}; - -static int cmd640x_init_one(unsigned long base, unsigned long ctl) -{ - if (!request_region(base, 8, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", - DRV_NAME, base, base + 7); - return -EBUSY; - } - - if (!request_region(ctl, 1, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", - DRV_NAME, ctl); - release_region(base, 8); - return -EBUSY; - } - - return 0; -} - -/* - * Probe for a cmd640 chipset, and initialize it if found. - */ -static int __init cmd640x_init(void) -{ - int second_port_cmd640 = 0, rc; - const char *bus_type, *port2; - u8 b, cfr; - hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; - - if (cmd640_vlb && probe_for_cmd640_vlb()) { - bus_type = "VLB"; - } else { - cmd640_vlb = 0; - /* Find out what kind of PCI probing is supported otherwise - Justin Gibbs will sulk.. */ - if (pci_conf1() && probe_for_cmd640_pci1()) - bus_type = "PCI (type1)"; - else if (pci_conf2() && probe_for_cmd640_pci2()) - bus_type = "PCI (type2)"; - else - return 0; - } - /* - * Undocumented magic (there is no 0x5b reg in specs) - */ - put_cmd640_reg(0x5b, 0xbd); - if (get_cmd640_reg(0x5b) != 0xbd) { - printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n"); - return 0; - } - put_cmd640_reg(0x5b, 0); - -#ifdef CMD640_DUMP_REGS - cmd640_dump_regs(); -#endif - - /* - * Documented magic begins here - */ - cfr = get_cmd640_reg(CFR); - cmd640_chip_version = cfr & CFR_DEVREV; - if (cmd640_chip_version == 0) { - printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version); - return 0; - } - - rc = cmd640x_init_one(0x1f0, 0x3f6); - if (rc) - return rc; - - rc = cmd640x_init_one(0x170, 0x376); - if (rc) { - release_region(0x3f6, 1); - release_region(0x1f0, 8); - return rc; - } - - memset(&hw, 0, sizeof(hw)); - - ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); - hw[0].irq = 14; - hw[0].chipset = ide_cmd640; - - ide_std_init_ports(&hw[1], 0x170, 0x376); - hw[1].irq = 15; - hw[1].chipset = ide_cmd640; - - printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" - "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); - - /* - * Initialize data for primary port - */ - hws[0] = &hw[0]; - - /* - * Ensure compatibility by always using the slowest timings - * for access to the drive's command register block, - * and reset the prefetch burstsize to default (512 bytes). - * - * Maybe we need a way to NOT do these on *some* systems? - */ - put_cmd640_reg(CMDTIM, 0); - put_cmd640_reg(BRST, 0x40); - - b = get_cmd640_reg(CNTRL); - - /* - * Try to enable the secondary interface, if not already enabled - */ - if (secondary_port_responding()) { - if ((b & CNTRL_ENA_2ND)) { - second_port_cmd640 = 1; - port2 = "okay"; - } else if (cmd640_vlb) { - second_port_cmd640 = 1; - port2 = "alive"; - } else - port2 = "not cmd640"; - } else { - put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ - if (secondary_port_responding()) { - second_port_cmd640 = 1; - port2 = "enabled"; - } else { - put_cmd640_reg(CNTRL, b); /* restore original setting */ - port2 = "not responding"; - } - } - - /* - * Initialize data for secondary cmd640 port, if enabled - */ - if (second_port_cmd640) - hws[1] = &hw[1]; - - printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n", - second_port_cmd640 ? "" : "not ", port2); - -#ifdef CMD640_DUMP_REGS - cmd640_dump_regs(); -#endif - - return ide_host_add(&cmd640_port_info, hws, NULL); -} - -module_param_named(probe_vlb, cmd640_vlb, bool, 0); -MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset"); - -module_init(cmd640x_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c deleted file mode 100644 index 935385c..0000000 --- a/drivers/ide/pci/cmd64x.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * 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 - * Copyright (C) 2007 MontaVista Software, Inc. - */ - -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "cmd64x" - -#define CMD_DEBUG 0 - -#if CMD_DEBUG -#define cmdprintk(x...) printk(x) -#else -#define cmdprintk(x...) -#endif - -/* - * CMD64x specific registers definition. - */ -#define CFR 0x50 -#define CFR_INTR_CH0 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 u8 quantize_timing(int timing, int quant) -{ - return (timing + quant - 1) / quant; -} - -/* - * This routine calculates active/recovery counts and then writes them into - * the chipset registers. - */ -static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33); - u8 cycle_count, active_count, recovery_count, drwtim; - static const u8 recovery_values[] = - {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; - static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3}; - - cmdprintk("program_cycle_times parameters: total=%d, active=%d\n", - cycle_time, active_time); - - cycle_count = quantize_timing( cycle_time, clock_time); - active_count = quantize_timing(active_time, clock_time); - recovery_count = cycle_count - active_count; - - /* - * In case we've got too long recovery phase, try to lengthen - * the active phase - */ - if (recovery_count > 16) { - active_count += recovery_count - 16; - recovery_count = 16; - } - if (active_count > 16) /* shouldn't actually happen... */ - active_count = 16; - - cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n", - cycle_count, active_count, recovery_count); - - /* - * Convert values to internal chipset representation - */ - recovery_count = recovery_values[recovery_count]; - active_count &= 0x0f; - - /* Program the active/recovery counts into the DRWTIM register */ - drwtim = (active_count << 4) | recovery_count; - (void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim); - cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]); -} - -/* - * This routine writes into the chipset registers - * PIO setup/active/recovery timings. - */ -static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); - unsigned int cycle_time; - u8 setup_count, arttim = 0; - - static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; - static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; - - cycle_time = ide_pio_cycle_time(drive, pio); - - program_cycle_times(drive, cycle_time, t->active); - - setup_count = quantize_timing(t->setup, - 1000 / (ide_pci_clk ? ide_pci_clk : 33)); - - /* - * 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 *drives = hwif->drives; - - drive->drive_data = setup_count; - setup_count = max(drives[0].drive_data, drives[1].drive_data); - } - - if (setup_count > 5) /* shouldn't actually happen... */ - setup_count = 5; - cmdprintk("Final address setup count: %d\n", setup_count); - - /* - * 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[setup_count]; - (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim); - cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]); -} - -/* - * 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_drive_t *drive, const u8 pio) -{ - /* - * Filter out the prefetch control values - * to prevent PIO5 from being programmed - */ - if (pio == 8 || pio == 9) - return; - - cmd64x_tune_pio(drive, pio); -} - -static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 unit = drive->dn & 0x01; - u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0; - - if (speed >= XFER_SW_DMA_0) { - (void) pci_read_config_byte(dev, pciU, ®U); - 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: - program_cycle_times(drive, 120, 70); - break; - case XFER_MW_DMA_1: - program_cycle_times(drive, 150, 80); - break; - case XFER_MW_DMA_0: - program_cycle_times(drive, 480, 215); - break; - } - - if (speed >= XFER_SW_DMA_0) - (void) pci_write_config_byte(dev, pciU, regU); -} - -static int cmd648_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long base = hwif->dma_base - (hwif->channel * 8); - int err = ide_dma_end(drive); - 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); - - return err; -} - -static int cmd64x_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - 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; - int err = ide_dma_end(drive); - - (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); - - return err; -} - -static int cmd648_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long base = hwif->dma_base - (hwif->channel * 8); - u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 : - MRDMODE_INTR_CH0; - u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - u8 mrdmode = inb(base + 1); - -#ifdef DEBUG - printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n", - drive->name, dma_stat, mrdmode, irq_mask); -#endif - if (!(mrdmode & irq_mask)) - return 0; - - /* return 1 if INTR asserted */ - if (dma_stat & 4) - return 1; - - return 0; -} - -static int cmd64x_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - 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 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - u8 irq_stat = 0; - - (void) pci_read_config_byte(dev, irq_reg, &irq_stat); - -#ifdef DEBUG - printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n", - drive->name, dma_stat, irq_stat, irq_mask); -#endif - if (!(irq_stat & irq_mask)) - return 0; - - /* return 1 if INTR asserted */ - if (dma_stat & 4) - return 1; - - return 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 = HWIF(drive); - u8 dma_stat = 0, dma_cmd = 0; - - drive->waiting_for_dma = 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); - /* and free any DMA resources */ - ide_destroy_dmatable(drive); - /* verify good DMA status */ - return (dma_stat & 7) != 4; -} - -static unsigned 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, - .cable_detect = cmd64x_cable_detect, -}; - -static const struct ide_dma_ops cmd64x_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = cmd64x_dma_end, - .dma_test_irq = cmd64x_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_dma_ops cmd646_rev1_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = cmd646_1_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_dma_ops cmd648_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = cmd648_dma_end, - .dma_test_irq = cmd648_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { - { /* 0: CMD643 */ - .name = DRV_NAME, - .init_chipset = init_chipset_cmd64x, - .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, - .port_ops = &cmd64x_port_ops, - .dma_ops = &cmd64x_dma_ops, - .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | - IDE_HFLAG_ABUSE_PREFETCH, - .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}}, - .chipset = ide_cmd646, - .port_ops = &cmd64x_port_ops, - .dma_ops = &cmd648_dma_ops, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH, - .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 = &cmd64x_port_ops, - .dma_ops = &cmd648_dma_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 = &cmd64x_port_ops, - .dma_ops = &cmd648_dma_ops, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH, - .pio_mask = ATA_PIO5, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA5, - } -}; - -static int __devinit 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; - if (dev->revision == 1) - d.dma_ops = &cmd646_rev1_dma_ops; - else - d.dma_ops = &cmd64x_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"); -MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c deleted file mode 100644 index 5efb467..0000000 --- a/drivers/ide/pci/cs5520.c +++ /dev/null @@ -1,165 +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 -#include -#include -#include -#include -#include -#include - -#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_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *pdev = to_pci_dev(hwif->dev); - int controller = drive->dn > 1 ? 1 : 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_drive_t *drive, const u8 speed) -{ - printk(KERN_ERR "cs55x0: bad ide timing.\n"); - - cs5520_set_pio_mode(drive, 0); -} - -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 __devinitdata = { - .name = DRV_NAME, - .enablebits = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } }, - .port_ops = &cs5520_port_ops, - .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_CS5520, - .pio_mask = ATA_PIO4, -}; - -/* - * 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 __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - const struct ide_port_info *d = &cyrix_chipset; - hw_regs_t hw[4], *hws[] = { NULL, NULL, 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 (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { - 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, 14, &hw[0], &hws[0]); - - return ide_host_add(d, hws, 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"); diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c deleted file mode 100644 index 53f079c..0000000 --- a/drivers/ide/pci/cs5530.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2000 Andre Hedrick - * Copyright (C) 2000 Mark Lord - * 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 -#include -#include -#include -#include -#include - -#include - -#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 - * @drive: drive - * @pio: PIO mode number - * - * 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_drive_t *drive, const u8 pio) -{ - unsigned long basereg = CS5530_BASEREG(drive->hwif); - unsigned int format = (inl(basereg + 4) >> 31) & 1; - - 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 = mate->id; - u8 mask = hwif->ultra_mask; - - if (mate == NULL) - goto out; - - 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_FIELD_VALID] & 2) && - (mateid[ATA_ID_MWDMA_MODES] & 7)) - mask = 0; - } -out: - return mask; -} - -static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) -{ - unsigned long basereg; - unsigned int reg, timings = 0; - - 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; - } - basereg = CS5530_BASEREG(drive->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 unsigned 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 __devinit 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 __devinitdata = { - .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 __devinit 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"); diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c deleted file mode 100644 index 983d957..0000000 --- a/drivers/ide/pci/cs5535.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2004-2005 Advanced Micro Devices, Inc. - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * - * History: - * 09/20/2005 - Jaya Kumar - * - 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 - * Alexander Kiausch - * Originally developed by AMD for 2.4/2.6 - * - * Development of this chipset driver was funded - * by the nice folks at National Semiconductor/AMD. - * - * 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. - * - * Documentation: - * CS5535 documentation available from AMD - */ - -#include -#include -#include - -#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 = ide_get_best_pio_mode(pair, 255, 4); - - 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 - * @drive: drive - * @speed: DMA mode - * - * Programs the chipset for DMA mode. - */ - -static void cs5535_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - cs5535_set_speed(drive, speed); -} - -/** - * cs5535_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * A callback from the upper layers for PIO-only tuning. - */ - -static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - cs5535_set_speed(drive, XFER_PIO_0 + pio); -} - -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 __devinitdata = { - .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 __devinit 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 }, - { 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"); diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c deleted file mode 100644 index 5297f07..0000000 --- a/drivers/ide/pci/cy82c693.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer - * Copyright (C) 1998-2002 Andre Hedrick , Integrator - * - * CYPRESS CY82C693 chipset IDE controller - * - * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. - * Writing the driver was quite simple, since most of the job is - * done by the generic pci-ide support. - * The hard part was finding the CY82C693's datasheet on Cypress's - * web page :-(. But Altavista solved this problem :-). - * - * - * Notes: - * - I recently got a 16.8G IBM DTTA, so I was able to test it with - * a large and fast disk - the results look great, so I'd say the - * driver is working fine :-) - * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA - * - this is my first linux driver, so there's probably a lot of room - * for optimizations and bug fixing, so feel free to do it. - * - if using PIO mode it's a good idea to set the PIO mode and - * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda - * - I had some problems with my IBM DHEA with PIO modes < 2 - * (lost interrupts) ????? - * - first tests with DMA look okay, they seem to work, but there is a - * problem with sound - the BusMaster IDE TimeOut should fixed this - * - * Ancient History: - * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 - * ASK@1999-01-23: v0.33 made a few minor code clean ups - * removed DMA clock speed setting by default - * added boot message - * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut - * added support to set DMA Controller Clock Speed - * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes - * on some drives. - * ASK@1998-10-29: v0.3 added support to set DMA modes - * ASK@1998-10-28: v0.2 added support to set PIO modes - * ASK@1998-10-27: v0.1 first version - chipset detection - * - */ - -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "cy82c693" - -/* - * The following are used to debug the driver. - */ -#define CY82C693_DEBUG_INFO 0 - -/* - * 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 - -/* the min and max PCI bus speed in MHz - from datasheet */ -#define CY82C963_MIN_BUS_SPEED 25 -#define CY82C963_MAX_BUS_SPEED 33 - -/* the struct for the PIO mode timings */ -typedef struct pio_clocks_s { - u8 address_time; /* Address setup (clocks) */ - u8 time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */ - u8 time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */ - u8 time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */ -} pio_clocks_t; - -/* - * calc clocks using bus_speed - * returns (rounded up) time in bus clocks for time in ns - */ -static int calc_clk(int time, int bus_speed) -{ - int clocks; - - clocks = (time*bus_speed+999)/1000 - 1; - - if (clocks < 0) - clocks = 0; - - if (clocks > 0x0F) - clocks = 0x0F; - - return clocks; -} - -/* - * compute the values for the clock registers for PIO - * mode and pci_clk [MHz] speed - * - * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used - * for mode 3 and 4 drives 8 and 16-bit timings are the same - * - */ -static void compute_clocks(u8 pio, pio_clocks_t *p_pclk) -{ - struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); - int clk1, clk2; - int bus_speed = ide_pci_clk ? ide_pci_clk : 33; - - /* we don't check against CY82C693's min and max speed, - * so you can play with the idebus=xx parameter - */ - - /* let's calc the address setup time clocks */ - p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed); - - /* let's calc the active and recovery time clocks */ - clk1 = calc_clk(t->active, bus_speed); - - /* calc recovery timing */ - clk2 = t->cycle - t->active - t->setup; - - clk2 = calc_clk(clk2, bus_speed); - - clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */ - - /* note: we use the same values for 16bit IOR and IOW - * those are all the same, since I don't have other - * timings than those from ide-lib.c - */ - - p_pclk->time_16r = (u8)clk1; - p_pclk->time_16w = (u8)clk1; - - /* what are good values for 8bit ?? */ - p_pclk->time_8 = (u8)clk1; -} - -/* - * set DMA mode a specific channel for CY82C693 - */ - -static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode) -{ - ide_hwif_t *hwif = drive->hwif; - 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); - -#if CY82C693_DEBUG_INFO - printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", - drive->name, hwif->channel, drive->dn & 1, mode & 3, single); -#endif /* CY82C693_DEBUG_INFO */ - - /* - * note: below we set the value for Bus Master IDE TimeOut Register - * I'm not absolutly sure what this does, but it solved my problem - * with IDE DMA and sound, so I now can play sound and work with - * my IDE driver at the same time :-) - * - * If you know the correct (best) value for this register please - * let me know - ASK - */ - - data = BUSMASTER_TIMEOUT; - outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); - outb(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", - drive->name, data); -#endif /* CY82C693_DEBUG_INFO */ -} - -static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - pio_clocks_t pclk; - unsigned int addrCtrl; - - /* select primary or secondary channel */ - if (hwif->index > 0) { /* 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; - } - } - - /* let's calc the values for this PIO mode */ - compute_clocks(pio, &pclk); - - /* 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 |= (unsigned int)pclk.address_time; - 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, pclk.time_16r); - pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w); - pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8); - - addrCtrl &= 0xF; - } else { - /* - * set slave drive - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - - addrCtrl &= (~0xF0); - addrCtrl |= ((unsigned int)pclk.address_time<<4); - pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); - - /* now let's set the remaining registers */ - pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r); - pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w); - pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8); - - addrCtrl >>= 4; - addrCtrl &= 0xF; - } - -#if CY82C693_DEBUG_INFO - printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to " - "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", - drive->name, hwif->channel, drive->dn & 1, - addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); -#endif /* CY82C693_DEBUG_INFO */ -} - -static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) -{ - static ide_hwif_t *primary; - struct pci_dev *dev = to_pci_dev(hwif->dev); - - if (PCI_FUNC(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 __devinitdata = { - .name = DRV_NAME, - .init_iops = init_iops_cy82c693, - .port_ops = &cy82c693_port_ops, - .chipset = ide_cy82c693, - .host_flags = IDE_HFLAG_SINGLE, - .pio_mask = ATA_PIO4, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, -}; - -static int __devinit 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 __devexit cy82c693_remove(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; - - ide_pci_remove(dev); - pci_dev_put(dev2); -} - -static const struct pci_device_id cy82c693_pci_tbl[] = { - { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl); - -static struct pci_driver cy82c693_pci_driver = { - .name = "Cypress_IDE", - .id_table = cy82c693_pci_tbl, - .probe = cy82c693_init_one, - .remove = __devexit_p(cy82c693_remove), - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init cy82c693_ide_init(void) -{ - return ide_pci_register_driver(&cy82c693_pci_driver); -} - -static void __exit cy82c693_ide_exit(void) -{ - pci_unregister_driver(&cy82c693_pci_driver); -} - -module_init(cy82c693_ide_init); -module_exit(cy82c693_ide_exit); - -MODULE_AUTHOR("Andreas Krebs, Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c deleted file mode 100644 index 8f1b2d9..0000000 --- a/drivers/ide/pci/delkin_cb.c +++ /dev/null @@ -1,192 +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 -#include -#include -#include -#include - -#include - -/* - * 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 unsigned 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, - .init_chipset = delkin_cb_init_chipset, -}; - -static int __devinit -delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) -{ - struct ide_host *host; - unsigned long base; - int rc; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - 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; - hw.chipset = ide_pci; /* this enables IRQ sharing */ - - rc = ide_host_add(&delkin_cb_port_info, hws, &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[] __devinitdata = { - { 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, -}; - -static int __init delkin_cb_init(void) -{ - return pci_register_driver(&delkin_cb_pci_driver); -} - -static void __exit delkin_cb_exit(void) -{ - pci_unregister_driver(&delkin_cb_pci_driver); -} - -module_init(delkin_cb_init); -module_exit(delkin_cb_exit); - -MODULE_AUTHOR("Mark Lord"); -MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c deleted file mode 100644 index 474f96a..0000000 --- a/drivers/ide/pci/generic.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2001-2002 Andre Hedrick - * Portions (C) Copyright 2002 Red Hat Inc - * - * 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 -#include -#include -#include -#include -#include - -#define DRV_NAME "ide_pci_generic" - -static int ide_generic_all; /* Set to claim all devices */ - -module_param_named(all_generic_ide, ide_generic_all, bool, 0444); -MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); - -#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS) - -#define DECLARE_GENERIC_PCI_DEV(extra_flags) \ - { \ - .name = DRV_NAME, \ - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \ - extra_flags, \ - .swdma_mask = ATA_SWDMA2, \ - .mwdma_mask = ATA_MWDMA2, \ - .udma_mask = ATA_UDMA6, \ - } - -static const struct ide_port_info generic_chipsets[] __devinitdata = { - /* 0: Unknown */ - DECLARE_GENERIC_PCI_DEV(0), - - { /* 1: NS87410 */ - .name = DRV_NAME, - .enablebits = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} }, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, - }, - - /* 2: SAMURAI / HT6565 / HINT_IDE */ - DECLARE_GENERIC_PCI_DEV(0), - /* 3: UM8673F / UM8886A / UM8886BF */ - DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC), - /* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */ - DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA), - - { /* 5: VIA8237SATA */ - .name = DRV_NAME, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_OFF_BOARD, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, - }, - - { /* 6: Revolution */ - .name = DRV_NAME, - .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | - IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_OFF_BOARD, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, - } -}; - -/** - * generic_init_one - called when a PIIX is found - * @dev: the generic 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 __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - const struct ide_port_info *d = &generic_chipsets[id->driver_data]; - int ret = -ENODEV; - - /* Don't use the generic entry unless instructed to do so */ - if (id->driver_data == 0 && ide_generic_all == 0) - goto out; - - switch (dev->vendor) { - case PCI_VENDOR_ID_UMC: - if (dev->device == PCI_DEVICE_ID_UMC_UM8886A && - !(PCI_FUNC(dev->devfn) & 1)) - goto out; /* UM8886A/BF pair */ - break; - case PCI_VENDOR_ID_OPTI: - if (dev->device == PCI_DEVICE_ID_OPTI_82C558 && - !(PCI_FUNC(dev->devfn) & 1)) - goto out; - break; - case PCI_VENDOR_ID_JMICRON: - if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && - PCI_FUNC(dev->devfn) != 1) - goto out; - break; - case PCI_VENDOR_ID_NS: - if (dev->device == PCI_DEVICE_ID_NS_87410 && - (dev->class >> 8) != PCI_CLASS_STORAGE_IDE) - goto out; - break; - } - - if (dev->vendor != PCI_VENDOR_ID_JMICRON) { - u16 command; - pci_read_config_word(dev, PCI_COMMAND, &command); - if (!(command & PCI_COMMAND_IO)) { - printk(KERN_INFO "%s %s: skipping disabled " - "controller\n", d->name, pci_name(dev)); - goto out; - } - } - ret = ide_pci_init_one(dev, d, NULL); -out: - return ret; -} - -static const struct pci_device_id generic_pci_tbl[] = { - { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), 1 }, - { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), 2 }, - { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 2 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 3 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 3 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 3 }, - { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 2 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 4 }, - { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 4 }, -#ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 5 }, -#endif - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 4 }, - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 4 }, - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 4 }, - { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 6 }, - /* - * Must come last. If you add entries adjust - * this table and generic_chipsets[] appropriately. - */ - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, generic_pci_tbl); - -static struct pci_driver generic_pci_driver = { - .name = "PCI_IDE", - .id_table = generic_pci_tbl, - .probe = generic_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init generic_ide_init(void) -{ - return ide_pci_register_driver(&generic_pci_driver); -} - -static void __exit generic_ide_exit(void) -{ - pci_unregister_driver(&generic_pci_driver); -} - -module_init(generic_ide_init); -module_exit(generic_ide_exit); - -MODULE_AUTHOR("Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for generic PCI IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c deleted file mode 100644 index a7909e9..0000000 --- a/drivers/ide/pci/hpt366.c +++ /dev/null @@ -1,1643 +0,0 @@ -/* - * Copyright (C) 1999-2003 Andre Hedrick - * Portions Copyright (C) 2001 Sun Microsystems, Inc. - * Portions Copyright (C) 2003 Red Hat Inc - * Portions Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * Portions Copyright (C) 2005-2008 MontaVista Software, Inc. - * - * Thanks to HighPoint Technologies for their assistance, and hardware. - * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his - * donation of an ABit BP6 mainboard, processor, and memory acellerated - * development and support. - * - * - * HighPoint has its own drivers (open source except for the RAID part) - * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/. - * This may be useful to anyone wanting to work on this driver, however do not - * trust them too much since the code tends to become less and less meaningful - * as the time passes... :-/ - * - * Note that final HPT370 support was done by force extraction of GPL. - * - * - add function for getting/setting power status of drive - * - the HPT370's state machine can get confused. reset it before each dma - * xfer to prevent that from happening. - * - reset state engine whenever we get an error. - * - check for busmaster state at end of dma. - * - use new highpoint timings. - * - detect bus speed using highpoint register. - * - use pll if we don't have a clock table. added a 66MHz table that's - * just 2x the 33MHz table. - * - removed turnaround. NOTE: we never want to switch between pll and - * pci clocks as the chip can glitch in those cases. the highpoint - * approved workaround slows everything down too much to be useful. in - * addition, we would have to serialize access to each chip. - * Adrian Sun - * - * add drive timings for 66MHz PCI bus, - * fix ATA Cable signal detection, fix incorrect /proc info - * add /proc display for per-drive PIO/DMA/UDMA mode and - * per-channel ATA-33/66 Cable detect. - * Duncan Laurie - * - * fixup /proc output for multiple controllers - * Tim Hockin - * - * On hpt366: - * Reset the hpt366 on error, reset on dma - * Fix disabling Fast Interrupt hpt366. - * Mike Waychison - * - * Added support for 372N clocking and clock switching. The 372N needs - * different clocks on read/write. This requires overloading rw_disk and - * other deeply crazy things. Thanks to for - * keeping me sane. - * Alan Cox - * - * - fix the clock turnaround code: it was writing to the wrong ports when - * called for the secondary channel, caching the current clock mode per- - * channel caused the cached register value to get out of sync with the - * actual one, the channels weren't serialized, the turnaround shouldn't - * be done on 66 MHz PCI bus - * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used - * does not allow for this speed anyway - * - avoid touching disabled channels (e.g. HPT371/N are single channel chips, - * their primary channel is kind of virtual, it isn't tied to any pins) - * - fix/remove bad/unused timing tables and use one set of tables for the whole - * HPT37x chip family; save space by introducing the separate transfer mode - * table in which the mode lookup is done - * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives - * the wrong PCI frequency since DPLL has already been calibrated by BIOS; - * read it only from the function 0 of HPT374 chips - * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, - * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead - * - pass to init_chipset() handlers a copy of the IDE PCI device structure as - * they tamper with its fields - * - pass to the init_setup handlers a copy of the ide_pci_device_t structure - * since they may tamper with its fields - * - prefix the driver startup messages with the real chip name - * - claim the extra 240 bytes of I/O space for all chips - * - optimize the UltraDMA filtering and the drive list lookup code - * - use pci_get_slot() to get to the function 1 of HPT36x/374 - * - cache offset of the channel's misc. control registers (MCRs) being used - * throughout the driver - * - only touch the relevant MCR when detecting the cable type on HPT374's - * function 1 - * - rename all the register related variables consistently - * - move all the interrupt twiddling code from the speedproc handlers into - * init_hwif_hpt366(), also grouping all the DMA related code together there - * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and - * separate the UltraDMA and MWDMA masks there to avoid changing PIO timings - * when setting an UltraDMA mode - * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select - * the best possible one - * - clean up DMA timeout handling for HPT370 - * - switch to using the enumeration type to differ between the numerous chip - * variants, matching PCI device/revision ID with the chip type early, at the - * init_setup stage - * - extend the hpt_info structure to hold the DPLL and PCI clock frequencies, - * stop duplicating it for each channel by storing the pointer in the pci_dev - * structure: first, at the init_setup stage, point it to a static "template" - * with only the chip type and its specific base DPLL frequency, the highest - * UltraDMA mode, and the chip settings table pointer filled, then, at the - * init_chipset stage, allocate per-chip instance and fill it with the rest - * of the necessary information - * - get rid of the constant thresholds in the HPT37x PCI clock detection code, - * switch to calculating PCI clock frequency based on the chip's base DPLL - * frequency - * - switch to using the DPLL clock and enable UltraATA/133 mode by default on - * anything newer than HPT370/A (except HPT374 that is not capable of this - * mode according to the manual) - * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(), - * also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips; - * unify HPT36x/37x timing setup code and the speedproc handlers by joining - * the register setting lists into the table indexed by the clock selected - * - set the correct hwif->ultra_mask for each individual chip - * - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards - * Sergei Shtylyov, or - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DRV_NAME "hpt366" - -/* various tuning parameters */ -#define HPT_RESET_STATE_ENGINE -#undef HPT_DELAY_INTERRUPT -#define HPT_SERIALIZE_IO 0 - -static const char *quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -static const char *bad_ata100_5[] = { - "IBM-DTLA-307075", - "IBM-DTLA-307060", - "IBM-DTLA-307045", - "IBM-DTLA-307030", - "IBM-DTLA-307020", - "IBM-DTLA-307015", - "IBM-DTLA-305040", - "IBM-DTLA-305030", - "IBM-DTLA-305020", - "IC35L010AVER07-0", - "IC35L020AVER07-0", - "IC35L030AVER07-0", - "IC35L040AVER07-0", - "IC35L060AVER07-0", - "WDC AC310200R", - NULL -}; - -static const char *bad_ata66_4[] = { - "IBM-DTLA-307075", - "IBM-DTLA-307060", - "IBM-DTLA-307045", - "IBM-DTLA-307030", - "IBM-DTLA-307020", - "IBM-DTLA-307015", - "IBM-DTLA-305040", - "IBM-DTLA-305030", - "IBM-DTLA-305020", - "IC35L010AVER07-0", - "IC35L020AVER07-0", - "IC35L030AVER07-0", - "IC35L040AVER07-0", - "IC35L060AVER07-0", - "WDC AC310200R", - "MAXTOR STM3320620A", - NULL -}; - -static const char *bad_ata66_3[] = { - "WDC AC310200R", - NULL -}; - -static const char *bad_ata33[] = { - "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", - "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", - "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", - "Maxtor 90510D4", - "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", - "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", - "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", - NULL -}; - -static u8 xfer_speeds[] = { - XFER_UDMA_6, - XFER_UDMA_5, - XFER_UDMA_4, - XFER_UDMA_3, - XFER_UDMA_2, - XFER_UDMA_1, - XFER_UDMA_0, - - XFER_MW_DMA_2, - XFER_MW_DMA_1, - XFER_MW_DMA_0, - - XFER_PIO_4, - XFER_PIO_3, - XFER_PIO_2, - XFER_PIO_1, - XFER_PIO_0 -}; - -/* Key for bus clock timings - * 36x 37x - * bits bits - * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA. - * cycles = value + 1 - * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA. - * cycles = value + 1 - * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file - * register access. - * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file - * register access. - * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer. - * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock. - * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and - * MW DMA xfer. - * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for - * task file register access. - * 28 28 UDMA enable. - * 29 29 DMA enable. - * 30 30 PIO MST enable. If set, the chip is in bus master mode during - * PIO xfer. - * 31 31 FIFO enable. - */ - -static u32 forty_base_hpt36x[] = { - /* XFER_UDMA_6 */ 0x900fd943, - /* XFER_UDMA_5 */ 0x900fd943, - /* XFER_UDMA_4 */ 0x900fd943, - /* XFER_UDMA_3 */ 0x900ad943, - /* XFER_UDMA_2 */ 0x900bd943, - /* XFER_UDMA_1 */ 0x9008d943, - /* XFER_UDMA_0 */ 0x9008d943, - - /* XFER_MW_DMA_2 */ 0xa008d943, - /* XFER_MW_DMA_1 */ 0xa010d955, - /* XFER_MW_DMA_0 */ 0xa010d9fc, - - /* XFER_PIO_4 */ 0xc008d963, - /* XFER_PIO_3 */ 0xc010d974, - /* XFER_PIO_2 */ 0xc010d997, - /* XFER_PIO_1 */ 0xc010d9c7, - /* XFER_PIO_0 */ 0xc018d9d9 -}; - -static u32 thirty_three_base_hpt36x[] = { - /* XFER_UDMA_6 */ 0x90c9a731, - /* XFER_UDMA_5 */ 0x90c9a731, - /* XFER_UDMA_4 */ 0x90c9a731, - /* XFER_UDMA_3 */ 0x90cfa731, - /* XFER_UDMA_2 */ 0x90caa731, - /* XFER_UDMA_1 */ 0x90cba731, - /* XFER_UDMA_0 */ 0x90c8a731, - - /* XFER_MW_DMA_2 */ 0xa0c8a731, - /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */ - /* XFER_MW_DMA_0 */ 0xa0c8a797, - - /* XFER_PIO_4 */ 0xc0c8a731, - /* XFER_PIO_3 */ 0xc0c8a742, - /* XFER_PIO_2 */ 0xc0d0a753, - /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */ - /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */ -}; - -static u32 twenty_five_base_hpt36x[] = { - /* XFER_UDMA_6 */ 0x90c98521, - /* XFER_UDMA_5 */ 0x90c98521, - /* XFER_UDMA_4 */ 0x90c98521, - /* XFER_UDMA_3 */ 0x90cf8521, - /* XFER_UDMA_2 */ 0x90cf8521, - /* XFER_UDMA_1 */ 0x90cb8521, - /* XFER_UDMA_0 */ 0x90cb8521, - - /* XFER_MW_DMA_2 */ 0xa0ca8521, - /* XFER_MW_DMA_1 */ 0xa0ca8532, - /* XFER_MW_DMA_0 */ 0xa0ca8575, - - /* XFER_PIO_4 */ 0xc0ca8521, - /* XFER_PIO_3 */ 0xc0ca8532, - /* XFER_PIO_2 */ 0xc0ca8542, - /* XFER_PIO_1 */ 0xc0d08572, - /* XFER_PIO_0 */ 0xc0d08585 -}; - -#if 0 -/* These are the timing tables from the HighPoint open source drivers... */ -static u32 thirty_three_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */ - /* XFER_UDMA_5 */ 0x12446231, - /* XFER_UDMA_4 */ 0x12446231, - /* XFER_UDMA_3 */ 0x126c6231, - /* XFER_UDMA_2 */ 0x12486231, - /* XFER_UDMA_1 */ 0x124c6233, - /* XFER_UDMA_0 */ 0x12506297, - - /* XFER_MW_DMA_2 */ 0x22406c31, - /* XFER_MW_DMA_1 */ 0x22406c33, - /* XFER_MW_DMA_0 */ 0x22406c97, - - /* XFER_PIO_4 */ 0x06414e31, - /* XFER_PIO_3 */ 0x06414e42, - /* XFER_PIO_2 */ 0x06414e53, - /* XFER_PIO_1 */ 0x06814e93, - /* XFER_PIO_0 */ 0x06814ea7 -}; - -static u32 fifty_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x12848242, - /* XFER_UDMA_5 */ 0x12848242, - /* XFER_UDMA_4 */ 0x12ac8242, - /* XFER_UDMA_3 */ 0x128c8242, - /* XFER_UDMA_2 */ 0x120c8242, - /* XFER_UDMA_1 */ 0x12148254, - /* XFER_UDMA_0 */ 0x121882ea, - - /* XFER_MW_DMA_2 */ 0x22808242, - /* XFER_MW_DMA_1 */ 0x22808254, - /* XFER_MW_DMA_0 */ 0x228082ea, - - /* XFER_PIO_4 */ 0x0a81f442, - /* XFER_PIO_3 */ 0x0a81f443, - /* XFER_PIO_2 */ 0x0a81f454, - /* XFER_PIO_1 */ 0x0ac1f465, - /* XFER_PIO_0 */ 0x0ac1f48a -}; - -static u32 sixty_six_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x1c869c62, - /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */ - /* XFER_UDMA_4 */ 0x1c8a9c62, - /* XFER_UDMA_3 */ 0x1c8e9c62, - /* XFER_UDMA_2 */ 0x1c929c62, - /* XFER_UDMA_1 */ 0x1c9a9c62, - /* XFER_UDMA_0 */ 0x1c829c62, - - /* XFER_MW_DMA_2 */ 0x2c829c62, - /* XFER_MW_DMA_1 */ 0x2c829c66, - /* XFER_MW_DMA_0 */ 0x2c829d2e, - - /* XFER_PIO_4 */ 0x0c829c62, - /* XFER_PIO_3 */ 0x0c829c84, - /* XFER_PIO_2 */ 0x0c829ca6, - /* XFER_PIO_1 */ 0x0d029d26, - /* XFER_PIO_0 */ 0x0d029d5e -}; -#else -/* - * The following are the new timing tables with PIO mode data/taskfile transfer - * overclocking fixed... - */ - -/* This table is taken from the HPT370 data manual rev. 1.02 */ -static u32 thirty_three_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x16455031, /* 0x16655031 ?? */ - /* XFER_UDMA_5 */ 0x16455031, - /* XFER_UDMA_4 */ 0x16455031, - /* XFER_UDMA_3 */ 0x166d5031, - /* XFER_UDMA_2 */ 0x16495031, - /* XFER_UDMA_1 */ 0x164d5033, - /* XFER_UDMA_0 */ 0x16515097, - - /* XFER_MW_DMA_2 */ 0x26515031, - /* XFER_MW_DMA_1 */ 0x26515033, - /* XFER_MW_DMA_0 */ 0x26515097, - - /* XFER_PIO_4 */ 0x06515021, - /* XFER_PIO_3 */ 0x06515022, - /* XFER_PIO_2 */ 0x06515033, - /* XFER_PIO_1 */ 0x06915065, - /* XFER_PIO_0 */ 0x06d1508a -}; - -static u32 fifty_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x1a861842, - /* XFER_UDMA_5 */ 0x1a861842, - /* XFER_UDMA_4 */ 0x1aae1842, - /* XFER_UDMA_3 */ 0x1a8e1842, - /* XFER_UDMA_2 */ 0x1a0e1842, - /* XFER_UDMA_1 */ 0x1a161854, - /* XFER_UDMA_0 */ 0x1a1a18ea, - - /* XFER_MW_DMA_2 */ 0x2a821842, - /* XFER_MW_DMA_1 */ 0x2a821854, - /* XFER_MW_DMA_0 */ 0x2a8218ea, - - /* XFER_PIO_4 */ 0x0a821842, - /* XFER_PIO_3 */ 0x0a821843, - /* XFER_PIO_2 */ 0x0a821855, - /* XFER_PIO_1 */ 0x0ac218a8, - /* XFER_PIO_0 */ 0x0b02190c -}; - -static u32 sixty_six_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x1c86fe62, - /* XFER_UDMA_5 */ 0x1caefe62, /* 0x1c8afe62 */ - /* XFER_UDMA_4 */ 0x1c8afe62, - /* XFER_UDMA_3 */ 0x1c8efe62, - /* XFER_UDMA_2 */ 0x1c92fe62, - /* XFER_UDMA_1 */ 0x1c9afe62, - /* XFER_UDMA_0 */ 0x1c82fe62, - - /* XFER_MW_DMA_2 */ 0x2c82fe62, - /* XFER_MW_DMA_1 */ 0x2c82fe66, - /* XFER_MW_DMA_0 */ 0x2c82ff2e, - - /* XFER_PIO_4 */ 0x0c82fe62, - /* XFER_PIO_3 */ 0x0c82fe84, - /* XFER_PIO_2 */ 0x0c82fea6, - /* XFER_PIO_1 */ 0x0d02ff26, - /* XFER_PIO_0 */ 0x0d42ff7f -}; -#endif - -#define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT371_ALLOW_ATA133_6 1 -#define HPT302_ALLOW_ATA133_6 1 -#define HPT372_ALLOW_ATA133_6 1 -#define HPT370_ALLOW_ATA100_5 0 -#define HPT366_ALLOW_ATA66_4 1 -#define HPT366_ALLOW_ATA66_3 1 -#define HPT366_MAX_DEVS 8 - -/* Supported ATA clock frequencies */ -enum ata_clock { - ATA_CLOCK_25MHZ, - ATA_CLOCK_33MHZ, - ATA_CLOCK_40MHZ, - ATA_CLOCK_50MHZ, - ATA_CLOCK_66MHZ, - NUM_ATA_CLOCKS -}; - -struct hpt_timings { - u32 pio_mask; - u32 dma_mask; - u32 ultra_mask; - u32 *clock_table[NUM_ATA_CLOCKS]; -}; - -/* - * Hold all the HighPoint chip information in one place. - */ - -struct hpt_info { - char *chip_name; /* Chip name */ - u8 chip_type; /* Chip type */ - u8 udma_mask; /* Allowed UltraDMA modes mask. */ - u8 dpll_clk; /* DPLL clock in MHz */ - u8 pci_clk; /* PCI clock in MHz */ - struct hpt_timings *timings; /* Chipset timing data */ - u8 clock; /* ATA clock selected */ -}; - -/* Supported HighPoint chips */ -enum { - HPT36x, - HPT370, - HPT370A, - HPT374, - HPT372, - HPT372A, - HPT302, - HPT371, - HPT372N, - HPT302N, - HPT371N -}; - -static struct hpt_timings hpt36x_timings = { - .pio_mask = 0xc1f8ffff, - .dma_mask = 0x303800ff, - .ultra_mask = 0x30070000, - .clock_table = { - [ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x, - [ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x, - [ATA_CLOCK_40MHZ] = forty_base_hpt36x, - [ATA_CLOCK_50MHZ] = NULL, - [ATA_CLOCK_66MHZ] = NULL - } -}; - -static struct hpt_timings hpt37x_timings = { - .pio_mask = 0xcfc3ffff, - .dma_mask = 0x31c001ff, - .ultra_mask = 0x303c0000, - .clock_table = { - [ATA_CLOCK_25MHZ] = NULL, - [ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x, - [ATA_CLOCK_40MHZ] = NULL, - [ATA_CLOCK_50MHZ] = fifty_base_hpt37x, - [ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x - } -}; - -static const struct hpt_info hpt36x __devinitdata = { - .chip_name = "HPT36x", - .chip_type = HPT36x, - .udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2, - .dpll_clk = 0, /* no DPLL */ - .timings = &hpt36x_timings -}; - -static const struct hpt_info hpt370 __devinitdata = { - .chip_name = "HPT370", - .chip_type = HPT370, - .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, - .dpll_clk = 48, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt370a __devinitdata = { - .chip_name = "HPT370A", - .chip_type = HPT370A, - .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, - .dpll_clk = 48, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt374 __devinitdata = { - .chip_name = "HPT374", - .chip_type = HPT374, - .udma_mask = ATA_UDMA5, - .dpll_clk = 48, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt372 __devinitdata = { - .chip_name = "HPT372", - .chip_type = HPT372, - .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, - .dpll_clk = 55, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt372a __devinitdata = { - .chip_name = "HPT372A", - .chip_type = HPT372A, - .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, - .dpll_clk = 66, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt302 __devinitdata = { - .chip_name = "HPT302", - .chip_type = HPT302, - .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, - .dpll_clk = 66, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt371 __devinitdata = { - .chip_name = "HPT371", - .chip_type = HPT371, - .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, - .dpll_clk = 66, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt372n __devinitdata = { - .chip_name = "HPT372N", - .chip_type = HPT372N, - .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, - .dpll_clk = 77, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt302n __devinitdata = { - .chip_name = "HPT302N", - .chip_type = HPT302N, - .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, - .dpll_clk = 77, - .timings = &hpt37x_timings -}; - -static const struct hpt_info hpt371n __devinitdata = { - .chip_name = "HPT371N", - .chip_type = HPT371N, - .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, - .dpll_clk = 77, - .timings = &hpt37x_timings -}; - -static int check_in_drive_list(ide_drive_t *drive, const char **list) -{ - char *m = (char *)&drive->id[ATA_ID_PROD]; - - while (*list) - if (!strcmp(*list++, m)) - return 1; - return 0; -} - -static struct hpt_info *hpt3xx_get_info(struct device *dev) -{ - struct ide_host *host = dev_get_drvdata(dev); - struct hpt_info *info = (struct hpt_info *)host->host_priv; - - return dev == host->dev[1] ? info + 1 : info; -} - -/* - * The Marvell bridge chips used on the HighPoint SATA cards do not seem - * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes... - */ - -static u8 hpt3xx_udma_filter(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct hpt_info *info = hpt3xx_get_info(hwif->dev); - u8 mask = hwif->ultra_mask; - - switch (info->chip_type) { - case HPT36x: - if (!HPT366_ALLOW_ATA66_4 || - check_in_drive_list(drive, bad_ata66_4)) - mask = ATA_UDMA3; - - if (!HPT366_ALLOW_ATA66_3 || - check_in_drive_list(drive, bad_ata66_3)) - mask = ATA_UDMA2; - break; - case HPT370: - if (!HPT370_ALLOW_ATA100_5 || - check_in_drive_list(drive, bad_ata100_5)) - mask = ATA_UDMA4; - break; - case HPT370A: - if (!HPT370_ALLOW_ATA100_5 || - check_in_drive_list(drive, bad_ata100_5)) - return ATA_UDMA4; - case HPT372 : - case HPT372A: - case HPT372N: - case HPT374 : - if (ata_id_is_sata(drive->id)) - mask &= ~0x0e; - /* Fall thru */ - default: - return mask; - } - - return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask; -} - -static u8 hpt3xx_mdma_filter(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct hpt_info *info = hpt3xx_get_info(hwif->dev); - - switch (info->chip_type) { - case HPT372 : - case HPT372A: - case HPT372N: - case HPT374 : - if (ata_id_is_sata(drive->id)) - return 0x00; - /* Fall thru */ - default: - return 0x07; - } -} - -static u32 get_speed_setting(u8 speed, struct hpt_info *info) -{ - int i; - - /* - * Lookup the transfer mode table to get the index into - * the timing table. - * - * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used. - */ - for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) - if (xfer_speeds[i] == speed) - break; - - return info->timings->clock_table[info->clock][i]; -} - -static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct hpt_info *info = hpt3xx_get_info(hwif->dev); - struct hpt_timings *t = info->timings; - u8 itr_addr = 0x40 + (drive->dn * 4); - u32 old_itr = 0; - u32 new_itr = get_speed_setting(speed, info); - u32 itr_mask = speed < XFER_MW_DMA_0 ? t->pio_mask : - (speed < XFER_UDMA_0 ? t->dma_mask : - t->ultra_mask); - - pci_read_config_dword(dev, itr_addr, &old_itr); - new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask); - /* - * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) - * to avoid problems handling I/O errors later - */ - new_itr &= ~0xc0000000; - - pci_write_config_dword(dev, itr_addr, new_itr); -} - -static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - hpt3xx_set_mode(drive, XFER_PIO_0 + pio); -} - -static void hpt3xx_quirkproc(ide_drive_t *drive) -{ - char *m = (char *)&drive->id[ATA_ID_PROD]; - const char **list = quirk_drives; - - while (*list) - if (strstr(m, *list++)) { - drive->quirk_list = 1; - return; - } - - drive->quirk_list = 0; -} - -static void hpt3xx_maskproc(ide_drive_t *drive, int mask) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct hpt_info *info = hpt3xx_get_info(hwif->dev); - - if (drive->quirk_list == 0) - return; - - if (info->chip_type >= HPT370) { - u8 scr1 = 0; - - pci_read_config_byte(dev, 0x5a, &scr1); - if (((scr1 & 0x10) >> 4) != mask) { - if (mask) - scr1 |= 0x10; - else - scr1 &= ~0x10; - pci_write_config_byte(dev, 0x5a, scr1); - } - } else if (mask) - disable_irq(hwif->irq); - else - enable_irq(hwif->irq); -} - -/* - * This is specific to the HPT366 UDMA chipset - * by HighPoint|Triones Technologies, Inc. - */ -static void hpt366_dma_lost_irq(ide_drive_t *drive) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u8 mcr1 = 0, mcr3 = 0, scr1 = 0; - - pci_read_config_byte(dev, 0x50, &mcr1); - pci_read_config_byte(dev, 0x52, &mcr3); - pci_read_config_byte(dev, 0x5a, &scr1); - printk("%s: (%s) mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n", - drive->name, __func__, mcr1, mcr3, scr1); - if (scr1 & 0x10) - pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); - ide_dma_lost_irq(drive); -} - -static void hpt370_clear_engine(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - - pci_write_config_byte(dev, hwif->select_data, 0x37); - udelay(10); -} - -static void hpt370_irq_timeout(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u16 bfifo = 0; - u8 dma_cmd; - - pci_read_config_word(dev, hwif->select_data + 2, &bfifo); - printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff); - - /* get DMA command mode */ - dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); - /* stop DMA */ - outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD); - hpt370_clear_engine(drive); -} - -static void hpt370_dma_start(ide_drive_t *drive) -{ -#ifdef HPT_RESET_STATE_ENGINE - hpt370_clear_engine(drive); -#endif - ide_dma_start(drive); -} - -static int hpt370_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - - if (dma_stat & 0x01) { - /* wait a little */ - udelay(20); - dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - if (dma_stat & 0x01) - hpt370_irq_timeout(drive); - } - return ide_dma_end(drive); -} - -static void hpt370_dma_timeout(ide_drive_t *drive) -{ - hpt370_irq_timeout(drive); - ide_dma_timeout(drive); -} - -/* returns 1 if DMA IRQ issued, 0 otherwise */ -static int hpt374_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u16 bfifo = 0; - u8 dma_stat; - - pci_read_config_word(dev, hwif->select_data + 2, &bfifo); - if (bfifo & 0x1FF) { -// printk("%s: %d bytes in FIFO\n", drive->name, bfifo); - return 0; - } - - dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - /* return 1 if INTR asserted */ - if (dma_stat & 4) - return 1; - - return 0; -} - -static int hpt374_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 mcr = 0, mcr_addr = hwif->select_data; - u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01; - - pci_read_config_byte(dev, 0x6a, &bwsr); - pci_read_config_byte(dev, mcr_addr, &mcr); - if (bwsr & mask) - pci_write_config_byte(dev, mcr_addr, mcr | 0x30); - return ide_dma_end(drive); -} - -/** - * hpt3xxn_set_clock - perform clock switching dance - * @hwif: hwif to switch - * @mode: clocking mode (0x21 for write, 0x23 otherwise) - * - * Switch the DPLL clock on the HPT3xxN devices. This is a right mess. - */ - -static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) -{ - unsigned long base = hwif->extra_base; - u8 scr2 = inb(base + 0x6b); - - if ((scr2 & 0x7f) == mode) - return; - - /* Tristate the bus */ - outb(0x80, base + 0x63); - outb(0x80, base + 0x67); - - /* Switch clock and reset channels */ - outb(mode, base + 0x6b); - outb(0xc0, base + 0x69); - - /* - * Reset the state machines. - * NOTE: avoid accidentally enabling the disabled channels. - */ - outb(inb(base + 0x60) | 0x32, base + 0x60); - outb(inb(base + 0x64) | 0x32, base + 0x64); - - /* Complete reset */ - outb(0x00, base + 0x69); - - /* Reconnect channels to bus */ - outb(0x00, base + 0x63); - outb(0x00, base + 0x67); -} - -/** - * hpt3xxn_rw_disk - prepare for I/O - * @drive: drive for command - * @rq: block request structure - * - * This is called when a disk I/O is issued to HPT3xxN. - * We need it because of the clock switching. - */ - -static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) -{ - hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21); -} - -/** - * hpt37x_calibrate_dpll - calibrate the DPLL - * @dev: PCI device - * - * Perform a calibration cycle on the DPLL. - * Returns 1 if this succeeds - */ -static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) -{ - u32 dpll = (f_high << 16) | f_low | 0x100; - u8 scr2; - int i; - - pci_write_config_dword(dev, 0x5c, dpll); - - /* Wait for oscillator ready */ - for(i = 0; i < 0x5000; ++i) { - udelay(50); - pci_read_config_byte(dev, 0x5b, &scr2); - if (scr2 & 0x80) - break; - } - /* See if it stays ready (we'll just bail out if it's not yet) */ - for(i = 0; i < 0x1000; ++i) { - pci_read_config_byte(dev, 0x5b, &scr2); - /* DPLL destabilized? */ - if(!(scr2 & 0x80)) - return 0; - } - /* Turn off tuning, we have the DPLL set */ - pci_read_config_dword (dev, 0x5c, &dpll); - pci_write_config_dword(dev, 0x5c, (dpll & ~0x100)); - return 1; -} - -static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]); - u8 chip_type = info->chip_type; - u8 new_mcr, old_mcr = 0; - - /* - * Disable the "fast interrupt" prediction. Don't hold off - * on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, mcr_addr + 1, &old_mcr); - - if (chip_type >= HPT374) - new_mcr = old_mcr & ~0x07; - else if (chip_type >= HPT370) { - new_mcr = old_mcr; - new_mcr &= ~0x02; -#ifdef HPT_DELAY_INTERRUPT - new_mcr &= ~0x01; -#else - new_mcr |= 0x01; -#endif - } else /* HPT366 and HPT368 */ - new_mcr = old_mcr & ~0x80; - - if (new_mcr != old_mcr) - pci_write_config_byte(dev, mcr_addr + 1, new_mcr); -} - -static unsigned int init_chipset_hpt366(struct pci_dev *dev) -{ - unsigned long io_base = pci_resource_start(dev, 4); - struct hpt_info *info = hpt3xx_get_info(&dev->dev); - const char *name = DRV_NAME; - u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ - u8 chip_type; - enum ata_clock clock; - - chip_type = info->chip_type; - - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - - /* - * First, try to estimate the PCI clock frequency... - */ - if (chip_type >= HPT370) { - u8 scr1 = 0; - u16 f_cnt = 0; - u32 temp = 0; - - /* Interrupt force enable. */ - pci_read_config_byte(dev, 0x5a, &scr1); - if (scr1 & 0x10) - pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); - - /* - * HighPoint does this for HPT372A. - * NOTE: This register is only writeable via I/O space. - */ - if (chip_type == HPT372A) - outb(0x0e, io_base + 0x9c); - - /* - * Default to PCI clock. Make sure MA15/16 are set to output - * to prevent drives having problems with 40-pin cables. - */ - pci_write_config_byte(dev, 0x5b, 0x23); - - /* - * We'll have to read f_CNT value in order to determine - * the PCI clock frequency according to the following ratio: - * - * f_CNT = Fpci * 192 / Fdpll - * - * First try reading the register in which the HighPoint BIOS - * saves f_CNT value before reprogramming the DPLL from its - * default setting (which differs for the various chips). - * - * NOTE: This register is only accessible via I/O space; - * HPT374 BIOS only saves it for the function 0, so we have to - * always read it from there -- no need to check the result of - * pci_get_slot() for the function 0 as the whole device has - * been already "pinned" (via function 1) in init_setup_hpt374() - */ - if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { - struct pci_dev *dev1 = pci_get_slot(dev->bus, - dev->devfn - 1); - unsigned long io_base = pci_resource_start(dev1, 4); - - temp = inl(io_base + 0x90); - pci_dev_put(dev1); - } else - temp = inl(io_base + 0x90); - - /* - * In case the signature check fails, we'll have to - * resort to reading the f_CNT register itself in hopes - * that nobody has touched the DPLL yet... - */ - if ((temp & 0xFFFFF000) != 0xABCDE000) { - int i; - - printk(KERN_WARNING "%s %s: no clock data saved by " - "BIOS\n", name, pci_name(dev)); - - /* Calculate the average value of f_CNT. */ - for (temp = i = 0; i < 128; i++) { - pci_read_config_word(dev, 0x78, &f_cnt); - temp += f_cnt & 0x1ff; - mdelay(1); - } - f_cnt = temp / 128; - } else - f_cnt = temp & 0x1ff; - - dpll_clk = info->dpll_clk; - pci_clk = (f_cnt * dpll_clk) / 192; - - /* Clamp PCI clock to bands. */ - if (pci_clk < 40) - pci_clk = 33; - else if(pci_clk < 45) - pci_clk = 40; - else if(pci_clk < 55) - pci_clk = 50; - else - pci_clk = 66; - - printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, " - "assuming %d MHz PCI\n", name, pci_name(dev), - dpll_clk, f_cnt, pci_clk); - } else { - u32 itr1 = 0; - - pci_read_config_dword(dev, 0x40, &itr1); - - /* Detect PCI clock by looking at cmd_high_time. */ - switch((itr1 >> 8) & 0x07) { - case 0x09: - pci_clk = 40; - break; - case 0x05: - pci_clk = 25; - break; - case 0x07: - default: - pci_clk = 33; - break; - } - } - - /* Let's assume we'll use PCI clock for the ATA clock... */ - switch (pci_clk) { - case 25: - clock = ATA_CLOCK_25MHZ; - break; - case 33: - default: - clock = ATA_CLOCK_33MHZ; - break; - case 40: - clock = ATA_CLOCK_40MHZ; - break; - case 50: - clock = ATA_CLOCK_50MHZ; - break; - case 66: - clock = ATA_CLOCK_66MHZ; - break; - } - - /* - * Only try the DPLL if we don't have a table for the PCI clock that - * we are running at for HPT370/A, always use it for anything newer... - * - * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI. - * We also don't like using the DPLL because this causes glitches - * on PRST-/SRST- when the state engine gets reset... - */ - if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) { - u16 f_low, delta = pci_clk < 50 ? 2 : 4; - int adjust; - - /* - * Select 66 MHz DPLL clock only if UltraATA/133 mode is - * supported/enabled, use 50 MHz DPLL clock otherwise... - */ - if (info->udma_mask == ATA_UDMA6) { - dpll_clk = 66; - clock = ATA_CLOCK_66MHZ; - } else if (dpll_clk) { /* HPT36x chips don't have DPLL */ - dpll_clk = 50; - clock = ATA_CLOCK_50MHZ; - } - - if (info->timings->clock_table[clock] == NULL) { - printk(KERN_ERR "%s %s: unknown bus timing!\n", - name, pci_name(dev)); - return -EIO; - } - - /* Select the DPLL clock. */ - pci_write_config_byte(dev, 0x5b, 0x21); - - /* - * Adjust the DPLL based upon PCI clock, enable it, - * and wait for stabilization... - */ - f_low = (pci_clk * 48) / dpll_clk; - - for (adjust = 0; adjust < 8; adjust++) { - if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta)) - break; - - /* - * See if it'll settle at a fractionally different clock - */ - if (adjust & 1) - f_low -= adjust >> 1; - else - f_low += adjust >> 1; - } - if (adjust == 8) { - printk(KERN_ERR "%s %s: DPLL did not stabilize!\n", - name, pci_name(dev)); - return -EIO; - } - - printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n", - name, pci_name(dev), dpll_clk); - } else { - /* Mark the fact that we're not using the DPLL. */ - dpll_clk = 0; - - printk(KERN_INFO "%s %s: using %d MHz PCI clock\n", - name, pci_name(dev), pci_clk); - } - - /* Store the clock frequencies. */ - info->dpll_clk = dpll_clk; - info->pci_clk = pci_clk; - info->clock = clock; - - if (chip_type >= HPT370) { - u8 mcr1, mcr4; - - /* - * Reset the state engines. - * NOTE: Avoid accidentally enabling the disabled channels. - */ - pci_read_config_byte (dev, 0x50, &mcr1); - pci_read_config_byte (dev, 0x54, &mcr4); - pci_write_config_byte(dev, 0x50, (mcr1 | 0x32)); - pci_write_config_byte(dev, 0x54, (mcr4 | 0x32)); - udelay(100); - } - - /* - * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in - * the MISC. register to stretch the UltraDMA Tss timing. - * NOTE: This register is only writeable via I/O space. - */ - if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) - outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); - - hpt3xx_disable_fast_irq(dev, 0x50); - hpt3xx_disable_fast_irq(dev, 0x54); - - return dev->irq; -} - -static u8 hpt3xx_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct hpt_info *info = hpt3xx_get_info(hwif->dev); - u8 chip_type = info->chip_type; - u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02; - - /* - * The HPT37x uses the CBLID pins as outputs for MA15/MA16 - * address lines to access an external EEPROM. To read valid - * cable detect state the pins must be enabled as inputs. - */ - if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { - /* - * HPT374 PCI function 1 - * - set bit 15 of reg 0x52 to enable TCBLID as input - * - set bit 15 of reg 0x56 to enable FCBLID as input - */ - u8 mcr_addr = hwif->select_data + 2; - u16 mcr; - - pci_read_config_word(dev, mcr_addr, &mcr); - pci_write_config_word(dev, mcr_addr, (mcr | 0x8000)); - /* now read cable id register */ - pci_read_config_byte(dev, 0x5a, &scr1); - pci_write_config_word(dev, mcr_addr, mcr); - } else if (chip_type >= HPT370) { - /* - * HPT370/372 and 374 pcifn 0 - * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs - */ - u8 scr2 = 0; - - pci_read_config_byte(dev, 0x5b, &scr2); - pci_write_config_byte(dev, 0x5b, (scr2 & ~1)); - /* now read cable id register */ - pci_read_config_byte(dev, 0x5a, &scr1); - pci_write_config_byte(dev, 0x5b, scr2); - } else - pci_read_config_byte(dev, 0x5a, &scr1); - - return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; -} - -static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) -{ - struct hpt_info *info = hpt3xx_get_info(hwif->dev); - int serialize = HPT_SERIALIZE_IO; - u8 chip_type = info->chip_type; - - /* Cache the channel's MISC. control registers' offset */ - hwif->select_data = hwif->channel ? 0x54 : 0x50; - - /* - * HPT3xxN chips have some complications: - * - * - on 33 MHz PCI we must clock switch - * - on 66 MHz PCI we must NOT use the PCI clock - */ - if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) { - /* - * Clock is shared between the channels, - * so we'll have to serialize them... :-( - */ - serialize = 1; - hwif->rw_disk = &hpt3xxn_rw_disk; - } - - /* Serialize access to this device if needed */ - if (serialize && hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; -} - -static int __devinit init_dma_hpt366(ide_hwif_t *hwif, - const struct ide_port_info *d) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long flags, base = ide_pci_dma_base(hwif, d); - u8 dma_old, dma_new, masterdma = 0, slavedma = 0; - - if (base == 0) - return -1; - - hwif->dma_base = base; - - if (ide_pci_check_simplex(hwif, d) < 0) - return -1; - - if (ide_pci_set_master(dev, d->name) < 0) - return -1; - - dma_old = inb(base + 2); - - local_irq_save(flags); - - dma_new = dma_old; - pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma); - pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47, &slavedma); - - if (masterdma & 0x30) dma_new |= 0x20; - if ( slavedma & 0x30) dma_new |= 0x40; - if (dma_new != dma_old) - outb(dma_new, base + 2); - - local_irq_restore(flags); - - printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", - hwif->name, base, base + 7); - - hwif->extra_base = base + (hwif->channel ? 8 : 16); - - if (ide_allocate_dma_engine(hwif)) - return -1; - - hwif->dma_ops = &sff_dma_ops; - - return 0; -} - -static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2) -{ - if (dev2->irq != dev->irq) { - /* FIXME: we need a core pci_set_interrupt() */ - dev2->irq = dev->irq; - printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt " - "fixed\n", pci_name(dev2)); - } -} - -static void __devinit hpt371_init(struct pci_dev *dev) -{ - u8 mcr1 = 0; - - /* - * HPT371 chips physically have only one channel, the secondary one, - * but the primary channel registers do exist! Go figure... - * So, we manually disable the non-existing channel here - * (if the BIOS hasn't done this already). - */ - pci_read_config_byte(dev, 0x50, &mcr1); - if (mcr1 & 0x04) - pci_write_config_byte(dev, 0x50, mcr1 & ~0x04); -} - -static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) -{ - u8 mcr1 = 0, pin1 = 0, pin2 = 0; - - /* - * Now we'll have to force both channels enabled if - * at least one of them has been enabled by BIOS... - */ - pci_read_config_byte(dev, 0x50, &mcr1); - if (mcr1 & 0x30) - pci_write_config_byte(dev, 0x50, mcr1 | 0x30); - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - - if (pin1 != pin2 && dev->irq == dev2->irq) { - printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, " - "pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2); - return 1; - } - - return 0; -} - -#define IDE_HFLAGS_HPT3XX \ - (IDE_HFLAG_NO_ATAPI_DMA | \ - IDE_HFLAG_OFF_BOARD) - -static const struct ide_port_ops hpt3xx_port_ops = { - .set_pio_mode = hpt3xx_set_pio_mode, - .set_dma_mode = hpt3xx_set_mode, - .quirkproc = hpt3xx_quirkproc, - .maskproc = hpt3xx_maskproc, - .mdma_filter = hpt3xx_mdma_filter, - .udma_filter = hpt3xx_udma_filter, - .cable_detect = hpt3xx_cable_detect, -}; - -static const struct ide_dma_ops hpt37x_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = hpt374_dma_end, - .dma_test_irq = hpt374_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_dma_ops hpt370_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = hpt370_dma_start, - .dma_end = hpt370_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = hpt370_dma_timeout, -}; - -static const struct ide_dma_ops hpt36x_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = ide_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = hpt366_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_port_info hpt366_chipsets[] __devinitdata = { - { /* 0: HPT36x */ - .name = DRV_NAME, - .init_chipset = init_chipset_hpt366, - .init_hwif = init_hwif_hpt366, - .init_dma = init_dma_hpt366, - /* - * HPT36x chips have one channel per function and have - * both channel enable bits located differently and visible - * to both functions -- really stupid design decision... :-( - * Bit 4 is for the primary channel, bit 5 for the secondary. - */ - .enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}}, - .port_ops = &hpt3xx_port_ops, - .dma_ops = &hpt36x_dma_ops, - .host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - }, - { /* 1: HPT3xx */ - .name = DRV_NAME, - .init_chipset = init_chipset_hpt366, - .init_hwif = init_hwif_hpt366, - .init_dma = init_dma_hpt366, - .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, - .port_ops = &hpt3xx_port_ops, - .dma_ops = &hpt37x_dma_ops, - .host_flags = IDE_HFLAGS_HPT3XX, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - } -}; - -/** - * hpt366_init_one - called when an HPT366 is found - * @dev: the hpt366 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 __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - const struct hpt_info *info = NULL; - struct hpt_info *dyn_info; - struct pci_dev *dev2 = NULL; - struct ide_port_info d; - u8 idx = id->driver_data; - u8 rev = dev->revision; - int ret; - - if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1)) - return -ENODEV; - - switch (idx) { - case 0: - if (rev < 3) - info = &hpt36x; - else { - switch (min_t(u8, rev, 6)) { - case 3: info = &hpt370; break; - case 4: info = &hpt370a; break; - case 5: info = &hpt372; break; - case 6: info = &hpt372n; break; - } - idx++; - } - break; - case 1: - info = (rev > 1) ? &hpt372n : &hpt372a; - break; - case 2: - info = (rev > 1) ? &hpt302n : &hpt302; - break; - case 3: - hpt371_init(dev); - info = (rev > 1) ? &hpt371n : &hpt371; - break; - case 4: - info = &hpt374; - break; - case 5: - info = &hpt372n; - break; - } - - printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name); - - d = hpt366_chipsets[min_t(u8, idx, 1)]; - - d.udma_mask = info->udma_mask; - - /* fixup ->dma_ops for HPT370/HPT370A */ - if (info == &hpt370 || info == &hpt370a) - d.dma_ops = &hpt370_dma_ops; - - if (info == &hpt36x || info == &hpt374) - dev2 = pci_get_slot(dev->bus, dev->devfn + 1); - - dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL); - if (dyn_info == NULL) { - printk(KERN_ERR "%s %s: out of memory!\n", - d.name, pci_name(dev)); - pci_dev_put(dev2); - return -ENOMEM; - } - - /* - * Copy everything from a static "template" structure - * to just allocated per-chip hpt_info structure. - */ - memcpy(dyn_info, info, sizeof(*dyn_info)); - - if (dev2) { - memcpy(dyn_info + 1, info, sizeof(*dyn_info)); - - if (info == &hpt374) - hpt374_init(dev, dev2); - else { - if (hpt36x_init(dev, dev2)) - d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE; - } - - ret = ide_pci_init_two(dev, dev2, &d, dyn_info); - if (ret < 0) { - pci_dev_put(dev2); - kfree(dyn_info); - } - return ret; - } - - ret = ide_pci_init_one(dev, &d, dyn_info); - if (ret < 0) - kfree(dyn_info); - - return ret; -} - -static void __devexit hpt366_remove(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct ide_info *info = host->host_priv; - struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; - - ide_pci_remove(dev); - pci_dev_put(dev2); - kfree(info); -} - -static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = { - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), 0 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), 1 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), 2 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), 3 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374), 4 }, - { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl); - -static struct pci_driver hpt366_pci_driver = { - .name = "HPT366_IDE", - .id_table = hpt366_pci_tbl, - .probe = hpt366_init_one, - .remove = __devexit_p(hpt366_remove), - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init hpt366_ide_init(void) -{ - return ide_pci_register_driver(&hpt366_pci_driver); -} - -static void __exit hpt366_ide_exit(void) -{ - pci_unregister_driver(&hpt366_pci_driver); -} - -module_init(hpt366_ide_init); -module_exit(hpt366_ide_exit); - -MODULE_AUTHOR("Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c deleted file mode 100644 index 7c2feeb..0000000 --- a/drivers/ide/pci/it8213.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * ITE 8213 IDE driver - * - * Copyright (C) 2006 Jack Lee - * Copyright (C) 2006 Alan Cox - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - */ - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "it8213" - -/** - * it8213_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * Set the interface PIO mode. - */ - -static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - int is_slave = drive->dn & 1; - int master_port = 0x40; - int slave_port = 0x44; - unsigned long flags; - u16 master_data; - u8 slave_data; - static DEFINE_SPINLOCK(tune_lock); - int control = 0; - - static const u8 timings[][2] = { - { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - spin_lock_irqsave(&tune_lock, flags); - pci_read_config_word(dev, master_port, &master_data); - - if (pio > 1) - control |= 1; /* Programmable timing on */ - if (drive->media != ide_disk) - control |= 4; /* ATAPI */ - if (pio > 2) - control |= 2; /* IORDY */ - if (is_slave) { - master_data |= 0x4000; - master_data &= ~0x0070; - if (pio > 1) - master_data = master_data | (control << 4); - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data = slave_data & 0xf0; - slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1]; - } else { - master_data &= ~0x3307; - if (pio > 1) - master_data = master_data | control; - master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); - } - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&tune_lock, flags); -} - -/** - * it8213_set_dma_mode - set host controller for DMA mode - * @drive: drive - * @speed: DMA mode - * - * Tune the ITE chipset for the DMA mode. - */ - -static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 maslave = 0x40; - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int v_flag = 0x01 << drive->dn; - int w_flag = 0x10 << drive->dn; - int u_speed = 0; - u16 reg4042, reg4a; - u8 reg48, reg54, reg55; - - pci_read_config_word(dev, maslave, ®4042); - pci_read_config_byte(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_byte(dev, 0x54, ®54); - pci_read_config_byte(dev, 0x55, ®55); - - if (speed >= XFER_UDMA_0) { - u8 udma = speed - XFER_UDMA_0; - - u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4); - - if (!(reg48 & u_flag)) - pci_write_config_byte(dev, 0x48, reg48 | u_flag); - if (speed >= XFER_UDMA_5) - pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); - else - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - - if ((reg4a & a_speed) != u_speed) - pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); - if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) - pci_write_config_byte(dev, 0x54, reg54 | v_flag); - } else - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - } else { - const u8 mwdma_to_pio[] = { 0, 3, 4 }; - u8 pio; - - if (reg48 & u_flag) - pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - if (reg54 & v_flag) - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - if (reg55 & w_flag) - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - - if (speed >= XFER_MW_DMA_0) - pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; - else - pio = 2; /* only SWDMA2 is allowed */ - - it8213_set_pio_mode(drive, pio); - } -} - -static u8 it8213_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 reg42h = 0; - - pci_read_config_byte(dev, 0x42, ®42h); - - return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; -} - -static const struct ide_port_ops it8213_port_ops = { - .set_pio_mode = it8213_set_pio_mode, - .set_dma_mode = it8213_set_dma_mode, - .cable_detect = it8213_cable_detect, -}; - -static const struct ide_port_info it8213_chipset __devinitdata = { - .name = DRV_NAME, - .enablebits = { {0x41, 0x80, 0x80} }, - .port_ops = &it8213_port_ops, - .host_flags = IDE_HFLAG_SINGLE, - .pio_mask = ATA_PIO4, - .swdma_mask = ATA_SWDMA2_ONLY, - .mwdma_mask = ATA_MWDMA12_ONLY, - .udma_mask = ATA_UDMA6, -}; - -/** - * it8213_init_one - pci layer discovery entry - * @dev: PCI device - * @id: ident table entry - * - * Called by the PCI code when it finds an ITE8213 controller. As - * this device follows the standard interfaces we can use the - * standard helper functions to do almost all the work for us. - */ - -static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &it8213_chipset, NULL); -} - -static const struct pci_device_id it8213_pci_tbl[] = { - { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), 0 }, - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, it8213_pci_tbl); - -static struct pci_driver it8213_pci_driver = { - .name = "ITE8213_IDE", - .id_table = it8213_pci_tbl, - .probe = it8213_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init it8213_ide_init(void) -{ - return ide_pci_register_driver(&it8213_pci_driver); -} - -static void __exit it8213_ide_exit(void) -{ - pci_unregister_driver(&it8213_pci_driver); -} - -module_init(it8213_ide_init); -module_exit(it8213_ide_exit); - -MODULE_AUTHOR("Jack Lee, Alan Cox"); -MODULE_DESCRIPTION("PCI driver module for the ITE 8213"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c deleted file mode 100644 index 995e18b..0000000 --- a/drivers/ide/pci/it821x.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Copyright (C) 2004 Red Hat - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * - * May be copied or modified under the terms of the GNU General Public License - * Based in part on the ITE vendor provided SCSI driver. - * - * Documentation available from - * http://www.ite.com.tw/pc/IT8212F_V04.pdf - * Some other documents are NDA. - * - * The ITE8212 isn't exactly a standard IDE controller. It has two - * modes. In pass through mode then it is an IDE controller. In its smart - * mode its actually quite a capable hardware raid controller disguised - * as an IDE controller. Smart mode only understands DMA read/write and - * identify, none of the fancier commands apply. The IT8211 is identical - * in other respects but lacks the raid mode. - * - * Errata: - * o Rev 0x10 also requires master/slave hold the same DMA timings and - * cannot do ATAPI MWDMA. - * o The identify data for raid volumes lacks CHS info (technically ok) - * but also fails to set the LBA28 and other bits. We fix these in - * the IDE probe quirk code. - * o If you write LBA48 sized I/O's (ie > 256 sector) in smart mode - * raid then the controller firmware dies - * o Smart mode without RAID doesn't clear all the necessary identify - * bits to reduce the command set to the one used - * - * This has a few impacts on the driver - * - In pass through mode we do all the work you would expect - * - In smart mode the clocking set up is done by the controller generally - * but we must watch the other limits and filter. - * - There are a few extra vendor commands that actually talk to the - * controller but only work PIO with no IRQ. - * - * Vendor areas of the identify block in smart mode are used for the - * timing and policy set up. Each HDD in raid mode also has a serial - * block on the disk. The hardware extra commands are get/set chip status, - * rebuild, get rebuild status. - * - * In Linux the driver supports pass through mode as if the device was - * just another IDE controller. If the smart mode is running then - * volumes are managed by the controller firmware and each IDE "disk" - * is a raid volume. Even more cute - the controller can do automated - * hotplug and rebuild. - * - * The pass through controller itself is a little demented. It has a - * flaw that it has a single set of PIO/MWDMA timings per channel so - * non UDMA devices restrict each others performance. It also has a - * single clock source per channel so mixed UDMA100/133 performance - * isn't perfect and we have to pick a clock. Thankfully none of this - * matters in smart mode. ATAPI DMA is not currently supported. - * - * It seems the smart mode is a win for RAID1/RAID10 but otherwise not. - * - * TODO - * - ATAPI UDMA is ok but not MWDMA it seems - * - RAID configuration ioctls - * - Move to libata once it grows up - */ - -#include -#include -#include -#include -#include - -#define DRV_NAME "it821x" - -struct it821x_dev -{ - unsigned int smart:1, /* Are we in smart raid mode */ - timing10:1; /* Rev 0x10 */ - u8 clock_mode; /* 0, ATA_50 or ATA_66 */ - u8 want[2][2]; /* Mode/Pri log for master slave */ - /* We need these for switching the clock when DMA goes on/off - The high byte is the 66Mhz timing */ - u16 pio[2]; /* Cached PIO values */ - u16 mwdma[2]; /* Cached MWDMA values */ - u16 udma[2]; /* Cached UDMA values (per drive) */ -}; - -#define ATA_66 0 -#define ATA_50 1 -#define ATA_ANY 2 - -#define UDMA_OFF 0 -#define MWDMA_OFF 0 - -/* - * We allow users to force the card into non raid mode without - * flashing the alternative BIOS. This is also necessary right now - * for embedded platforms that cannot run a PC BIOS but are using this - * device. - */ - -static int it8212_noraid; - -/** - * it821x_program - program the PIO/MWDMA registers - * @drive: drive to tune - * @timing: timing info - * - * Program the PIO/MWDMA timing for this channel according to the - * current clock. - */ - -static void it821x_program(ide_drive_t *drive, u16 timing) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int channel = hwif->channel; - u8 conf; - - /* Program PIO/MWDMA timing bits */ - if(itdev->clock_mode == ATA_66) - conf = timing >> 8; - else - conf = timing & 0xFF; - - pci_write_config_byte(dev, 0x54 + 4 * channel, conf); -} - -/** - * it821x_program_udma - program the UDMA registers - * @drive: drive to tune - * @timing: timing info - * - * Program the UDMA timing for this drive according to the - * current clock. - */ - -static void it821x_program_udma(ide_drive_t *drive, u16 timing) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int channel = hwif->channel; - u8 unit = drive->dn & 1, conf; - - /* Program UDMA timing bits */ - if(itdev->clock_mode == ATA_66) - conf = timing >> 8; - else - conf = timing & 0xFF; - - if (itdev->timing10 == 0) - pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf); - else { - pci_write_config_byte(dev, 0x56 + 4 * channel, conf); - pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf); - } -} - -/** - * it821x_clock_strategy - * @drive: drive to set up - * - * Select between the 50 and 66Mhz base clocks to get the best - * results for this interface. - */ - -static void it821x_clock_strategy(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - ide_drive_t *pair; - int clock, altclock, sel = 0; - u8 unit = drive->dn & 1, v; - - pair = &hwif->drives[1 - unit]; - - if(itdev->want[0][0] > itdev->want[1][0]) { - clock = itdev->want[0][1]; - altclock = itdev->want[1][1]; - } else { - clock = itdev->want[1][1]; - altclock = itdev->want[0][1]; - } - - /* - * if both clocks can be used for the mode with the higher priority - * use the clock needed by the mode with the lower priority - */ - if (clock == ATA_ANY) - clock = altclock; - - /* Nobody cares - keep the same clock */ - if(clock == ATA_ANY) - return; - /* No change */ - if(clock == itdev->clock_mode) - return; - - /* Load this into the controller ? */ - if(clock == ATA_66) - itdev->clock_mode = ATA_66; - else { - itdev->clock_mode = ATA_50; - sel = 1; - } - - pci_read_config_byte(dev, 0x50, &v); - v &= ~(1 << (1 + hwif->channel)); - v |= sel << (1 + hwif->channel); - pci_write_config_byte(dev, 0x50, v); - - /* - * Reprogram the UDMA/PIO of the pair drive for the switch - * MWDMA will be dealt with by the dma switcher - */ - if(pair && itdev->udma[1-unit] != UDMA_OFF) { - it821x_program_udma(pair, itdev->udma[1-unit]); - it821x_program(pair, itdev->pio[1-unit]); - } - /* - * Reprogram the UDMA/PIO of our drive for the switch. - * MWDMA will be dealt with by the dma switcher - */ - if(itdev->udma[unit] != UDMA_OFF) { - it821x_program_udma(drive, itdev->udma[unit]); - it821x_program(drive, itdev->pio[unit]); - } -} - -/** - * it821x_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * Tune the host to the desired PIO mode taking into the consideration - * the maximum PIO mode supported by the other device on the cable. - */ - -static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - ide_drive_t *pair; - u8 unit = drive->dn & 1, set_pio = pio; - - /* Spec says 89 ref driver uses 88 */ - static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; - static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; - - pair = &hwif->drives[1 - unit]; - - /* - * Compute the best PIO mode we can for a given device. We must - * pick a speed that does not cause problems with the other device - * on the cable. - */ - if (pair) { - u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4); - /* trim PIO to the slowest of the master/slave */ - if (pair_pio < set_pio) - set_pio = pair_pio; - } - - /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ - itdev->want[unit][1] = pio_want[set_pio]; - itdev->want[unit][0] = 1; /* PIO is lowest priority */ - itdev->pio[unit] = pio_timings[set_pio]; - it821x_clock_strategy(drive); - it821x_program(drive, itdev->pio[unit]); -} - -/** - * it821x_tune_mwdma - tune a channel for MWDMA - * @drive: drive to set up - * @mode_wanted: the target operating mode - * - * Load the timing settings for this device mode into the - * controller when doing MWDMA in pass through mode. The caller - * must manage the whole lack of per device MWDMA/PIO timings and - * the shared MWDMA/PIO timing register. - */ - -static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif); - u8 unit = drive->dn & 1, channel = hwif->channel, conf; - - static u16 dma[] = { 0x8866, 0x3222, 0x3121 }; - static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY }; - - itdev->want[unit][1] = mwdma_want[mode_wanted]; - itdev->want[unit][0] = 2; /* MWDMA is low priority */ - itdev->mwdma[unit] = dma[mode_wanted]; - itdev->udma[unit] = UDMA_OFF; - - /* UDMA bits off - Revision 0x10 do them in pairs */ - pci_read_config_byte(dev, 0x50, &conf); - if (itdev->timing10) - conf |= channel ? 0x60: 0x18; - else - conf |= 1 << (3 + 2 * channel + unit); - pci_write_config_byte(dev, 0x50, conf); - - it821x_clock_strategy(drive); - /* FIXME: do we need to program this ? */ - /* it821x_program(drive, itdev->mwdma[unit]); */ -} - -/** - * it821x_tune_udma - tune a channel for UDMA - * @drive: drive to set up - * @mode_wanted: the target operating mode - * - * Load the timing settings for this device mode into the - * controller when doing UDMA modes in pass through. - */ - -static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - u8 unit = drive->dn & 1, channel = hwif->channel, conf; - - static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 }; - static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 }; - - itdev->want[unit][1] = udma_want[mode_wanted]; - itdev->want[unit][0] = 3; /* UDMA is high priority */ - itdev->mwdma[unit] = MWDMA_OFF; - itdev->udma[unit] = udma[mode_wanted]; - if(mode_wanted >= 5) - itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */ - - /* UDMA on. Again revision 0x10 must do the pair */ - pci_read_config_byte(dev, 0x50, &conf); - if (itdev->timing10) - conf &= channel ? 0x9F: 0xE7; - else - conf &= ~ (1 << (3 + 2 * channel + unit)); - pci_write_config_byte(dev, 0x50, conf); - - it821x_clock_strategy(drive); - it821x_program_udma(drive, itdev->udma[unit]); - -} - -/** - * it821x_dma_read - DMA hook - * @drive: drive for DMA - * - * The IT821x has a single timing register for MWDMA and for PIO - * operations. As we flip back and forth we have to reload the - * clock. In addition the rev 0x10 device only works if the same - * timing value is loaded into the master and slave UDMA clock - * so we must also reload that. - * - * FIXME: we could figure out in advance if we need to do reloads - */ - -static void it821x_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - u8 unit = drive->dn & 1; - - if(itdev->mwdma[unit] != MWDMA_OFF) - it821x_program(drive, itdev->mwdma[unit]); - else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10) - it821x_program_udma(drive, itdev->udma[unit]); - ide_dma_start(drive); -} - -/** - * it821x_dma_write - DMA hook - * @drive: drive for DMA stop - * - * The IT821x has a single timing register for MWDMA and for PIO - * operations. As we flip back and forth we have to reload the - * clock. - */ - -static int it821x_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int ret = ide_dma_end(drive); - u8 unit = drive->dn & 1; - - if(itdev->mwdma[unit] != MWDMA_OFF) - it821x_program(drive, itdev->pio[unit]); - return ret; -} - -/** - * it821x_set_dma_mode - set host controller for DMA mode - * @drive: drive - * @speed: DMA mode - * - * Tune the ITE chipset for the desired DMA mode. - */ - -static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - /* - * MWDMA tuning is really hard because our MWDMA and PIO - * timings are kept in the same place. We can switch in the - * host dma on/off callbacks. - */ - if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_6) - it821x_tune_udma(drive, speed - XFER_UDMA_0); - else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) - it821x_tune_mwdma(drive, speed - XFER_MW_DMA_0); -} - -/** - * it821x_cable_detect - cable detection - * @hwif: interface to check - * - * Check for the presence of an ATA66 capable cable on the - * interface. Problematic as it seems some cards don't have - * the needed logic onboard. - */ - -static u8 it821x_cable_detect(ide_hwif_t *hwif) -{ - /* The reference driver also only does disk side */ - return ATA_CBL_PATA80; -} - -/** - * it821x_quirkproc - post init callback - * @drive: drive - * - * This callback is run after the drive has been probed but - * before anything gets attached. It allows drivers to do any - * final tuning that is needed, or fixups to work around bugs. - */ - -static void it821x_quirkproc(ide_drive_t *drive) -{ - struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif); - u16 *id = drive->id; - - if (!itdev->smart) { - /* - * If we are in pass through mode then not much - * needs to be done, but we do bother to clear the - * IRQ mask as we may well be in PIO (eg rev 0x10) - * for now and we know unmasking is safe on this chipset. - */ - drive->dev_flags |= IDE_DFLAG_UNMASK; - } else { - /* - * Perform fixups on smart mode. We need to "lose" some - * capabilities the firmware lacks but does not filter, and - * also patch up some capability bits that it forgets to set - * in RAID mode. - */ - - /* Check for RAID v native */ - if (strstr((char *)&id[ATA_ID_PROD], - "Integrated Technology Express")) { - /* In raid mode the ident block is slightly buggy - We need to set the bits so that the IDE layer knows - LBA28. LBA48 and DMA ar valid */ - id[ATA_ID_CAPABILITY] |= (3 << 8); /* LBA28, DMA */ - id[ATA_ID_COMMAND_SET_2] |= 0x0400; /* LBA48 valid */ - id[ATA_ID_CFS_ENABLE_2] |= 0x0400; /* LBA48 on */ - /* Reporting logic */ - printk(KERN_INFO "%s: IT8212 %sRAID %d volume", - drive->name, id[147] ? "Bootable " : "", - id[ATA_ID_CSFO]); - if (id[ATA_ID_CSFO] != 1) - printk(KERN_CONT "(%dK stripe)", id[146]); - printk(KERN_CONT ".\n"); - } else { - /* Non RAID volume. Fixups to stop the core code - doing unsupported things */ - id[ATA_ID_FIELD_VALID] &= 3; - id[ATA_ID_QUEUE_DEPTH] = 0; - id[ATA_ID_COMMAND_SET_1] = 0; - id[ATA_ID_COMMAND_SET_2] &= 0xC400; - id[ATA_ID_CFSSE] &= 0xC000; - id[ATA_ID_CFS_ENABLE_1] = 0; - id[ATA_ID_CFS_ENABLE_2] &= 0xC400; - id[ATA_ID_CSF_DEFAULT] &= 0xC000; - id[127] = 0; - id[ATA_ID_DLF] = 0; - id[ATA_ID_CSFO] = 0; - id[ATA_ID_CFA_POWER] = 0; - printk(KERN_INFO "%s: Performing identify fixups.\n", - drive->name); - } - - /* - * Set MWDMA0 mode as enabled/support - just to tell - * IDE core that DMA is supported (it821x hardware - * takes care of DMA mode programming). - */ - if (ata_id_has_dma(id)) { - id[ATA_ID_MWDMA_MODES] |= 0x0101; - drive->current_speed = XFER_MW_DMA_0; - } - } - -} - -static struct ide_dma_ops it821x_pass_through_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = it821x_dma_start, - .dma_end = it821x_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_timeout = ide_dma_timeout, - .dma_lost_irq = ide_dma_lost_irq, -}; - -/** - * init_hwif_it821x - set up hwif structs - * @hwif: interface to set up - * - * We do the basic set up of the interface structure. The IT8212 - * requires several custom handlers so we override the default - * ide DMA handlers appropriately - */ - -static void __devinit init_hwif_it821x(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct it821x_dev *itdevs = host->host_priv; - struct it821x_dev *idev = itdevs + hwif->channel; - u8 conf; - - ide_set_hwifdata(hwif, idev); - - pci_read_config_byte(dev, 0x50, &conf); - if (conf & 1) { - idev->smart = 1; - hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; - /* Long I/O's although allowed in LBA48 space cause the - onboard firmware to enter the twighlight zone */ - hwif->rqsize = 256; - } - - /* Pull the current clocks from 0x50 also */ - if (conf & (1 << (1 + hwif->channel))) - idev->clock_mode = ATA_50; - else - idev->clock_mode = ATA_66; - - idev->want[0][1] = ATA_ANY; - idev->want[1][1] = ATA_ANY; - - /* - * Not in the docs but according to the reference driver - * this is necessary. - */ - - pci_read_config_byte(dev, 0x08, &conf); - if (conf == 0x10) { - idev->timing10 = 1; - hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; - if (idev->smart == 0) - printk(KERN_WARNING DRV_NAME " %s: revision 0x10, " - "workarounds activated\n", pci_name(dev)); - } - - if (idev->smart == 0) { - /* MWDMA/PIO clock switching for pass through mode */ - hwif->dma_ops = &it821x_pass_through_dma_ops; - } else - hwif->host_flags |= IDE_HFLAG_NO_SET_MODE; - - if (hwif->dma_base == 0) - return; - - hwif->ultra_mask = ATA_UDMA6; - hwif->mwdma_mask = ATA_MWDMA2; -} - -static void it8212_disable_raid(struct pci_dev *dev) -{ - /* Reset local CPU, and set BIOS not ready */ - pci_write_config_byte(dev, 0x5E, 0x01); - - /* Set to bypass mode, and reset PCI bus */ - pci_write_config_byte(dev, 0x50, 0x00); - pci_write_config_word(dev, PCI_COMMAND, - PCI_COMMAND_PARITY | PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_write_config_word(dev, 0x40, 0xA0F3); - - pci_write_config_dword(dev,0x4C, 0x02040204); - pci_write_config_byte(dev, 0x42, 0x36); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); -} - -static unsigned int init_chipset_it821x(struct pci_dev *dev) -{ - u8 conf; - static char *mode[2] = { "pass through", "smart" }; - - /* Force the card into bypass mode if so requested */ - if (it8212_noraid) { - printk(KERN_INFO DRV_NAME " %s: forcing bypass mode\n", - pci_name(dev)); - it8212_disable_raid(dev); - } - pci_read_config_byte(dev, 0x50, &conf); - printk(KERN_INFO DRV_NAME " %s: controller in %s mode\n", - pci_name(dev), mode[conf & 1]); - return 0; -} - -static const struct ide_port_ops it821x_port_ops = { - /* it821x_set_{pio,dma}_mode() are only used in pass-through mode */ - .set_pio_mode = it821x_set_pio_mode, - .set_dma_mode = it821x_set_dma_mode, - .quirkproc = it821x_quirkproc, - .cable_detect = it821x_cable_detect, -}; - -static const struct ide_port_info it821x_chipset __devinitdata = { - .name = DRV_NAME, - .init_chipset = init_chipset_it821x, - .init_hwif = init_hwif_it821x, - .port_ops = &it821x_port_ops, - .pio_mask = ATA_PIO4, -}; - -/** - * it821x_init_one - pci layer discovery entry - * @dev: PCI device - * @id: ident table entry - * - * Called by the PCI code when it finds an ITE821x controller. - * We then use the IDE PCI generic helper to do most of the work. - */ - -static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct it821x_dev *itdevs; - int rc; - - itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL); - if (itdevs == NULL) { - printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev)); - return -ENOMEM; - } - - rc = ide_pci_init_one(dev, &it821x_chipset, itdevs); - if (rc) - kfree(itdevs); - - return rc; -} - -static void __devexit it821x_remove(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct it821x_dev *itdevs = host->host_priv; - - ide_pci_remove(dev); - kfree(itdevs); -} - -static const struct pci_device_id it821x_pci_tbl[] = { - { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 }, - { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 }, - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, it821x_pci_tbl); - -static struct pci_driver it821x_pci_driver = { - .name = "ITE821x IDE", - .id_table = it821x_pci_tbl, - .probe = it821x_init_one, - .remove = __devexit_p(it821x_remove), - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init it821x_ide_init(void) -{ - return ide_pci_register_driver(&it821x_pci_driver); -} - -static void __exit it821x_ide_exit(void) -{ - pci_unregister_driver(&it821x_pci_driver); -} - -module_init(it821x_ide_init); -module_exit(it821x_ide_exit); - -module_param_named(noraid, it8212_noraid, int, S_IRUGO); -MODULE_PARM_DESC(noraid, "Force card into bypass mode"); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("PCI driver module for the ITE 821x"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c deleted file mode 100644 index 9a68433..0000000 --- a/drivers/ide/pci/jmicron.c +++ /dev/null @@ -1,176 +0,0 @@ - -/* - * Copyright (C) 2006 Red Hat - * - * May be copied or modified under the terms of the GNU General Public License - */ - -#include -#include -#include -#include -#include - -#define DRV_NAME "jmicron" - -typedef enum { - PORT_PATA0 = 0, - PORT_PATA1 = 1, - PORT_SATA = 2, -} port_type; - -/** - * jmicron_cable_detect - cable detection - * @hwif: IDE port - * - * Returns the cable type. - */ - -static u8 jmicron_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *pdev = to_pci_dev(hwif->dev); - - u32 control; - u32 control5; - - int port = hwif->channel; - port_type port_map[2]; - - pci_read_config_dword(pdev, 0x40, &control); - - /* There are two basic mappings. One has the two SATA ports merged - as master/slave and the secondary as PATA, the other has only the - SATA port mapped */ - if (control & (1 << 23)) { - port_map[0] = PORT_SATA; - port_map[1] = PORT_PATA0; - } else { - port_map[0] = PORT_SATA; - port_map[1] = PORT_SATA; - } - - /* The 365/366 may have this bit set to map the second PATA port - as the internal primary channel */ - pci_read_config_dword(pdev, 0x80, &control5); - if (control5 & (1<<24)) - port_map[0] = PORT_PATA1; - - /* The two ports may then be logically swapped by the firmware */ - if (control & (1 << 22)) - port = port ^ 1; - - /* - * Now we know which physical port we are talking about we can - * actually do our cable checking etc. Thankfully we don't need - * to do the plumbing for other cases. - */ - switch (port_map[port]) { - case PORT_PATA0: - if (control & (1 << 3)) /* 40/80 pin primary */ - return ATA_CBL_PATA40; - return ATA_CBL_PATA80; - case PORT_PATA1: - if (control5 & (1 << 19)) /* 40/80 pin secondary */ - return ATA_CBL_PATA40; - return ATA_CBL_PATA80; - case PORT_SATA: - break; - } - /* Avoid bogus "control reaches end of non-void function" */ - return ATA_CBL_PATA80; -} - -static void jmicron_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ -} - -/** - * jmicron_set_dma_mode - set host controller for DMA mode - * @drive: drive - * @mode: DMA mode - * - * As the JMicron snoops for timings we don't need to do anything here. - */ - -static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode) -{ -} - -static const struct ide_port_ops jmicron_port_ops = { - .set_pio_mode = jmicron_set_pio_mode, - .set_dma_mode = jmicron_set_dma_mode, - .cable_detect = jmicron_cable_detect, -}; - -static const struct ide_port_info jmicron_chipset __devinitdata = { - .name = DRV_NAME, - .enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } }, - .port_ops = &jmicron_port_ops, - .pio_mask = ATA_PIO5, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, -}; - -/** - * jmicron_init_one - pci layer discovery entry - * @dev: PCI device - * @id: ident table entry - * - * Called by the PCI code when it finds a Jmicron controller. - * We then use the IDE PCI generic helper to do most of the work. - */ - -static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &jmicron_chipset, NULL); -} - -/* All JMB PATA controllers have and will continue to have the same - * interface. Matching vendor and device class is enough for all - * current and future controllers if the controller is programmed - * properly. - * - * If libata is configured, jmicron PCI quirk programs the controller - * into the correct mode. If libata isn't configured, match known - * device IDs too to maintain backward compatibility. - */ -static struct pci_device_id jmicron_pci_tbl[] = { -#if !defined(CONFIG_ATA) && !defined(CONFIG_ATA_MODULE) - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361) }, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363) }, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365) }, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366) }, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368) }, -#endif - { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 }, - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl); - -static struct pci_driver jmicron_pci_driver = { - .name = "JMicron IDE", - .id_table = jmicron_pci_tbl, - .probe = jmicron_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init jmicron_ide_init(void) -{ - return ide_pci_register_driver(&jmicron_pci_driver); -} - -static void __exit jmicron_ide_exit(void) -{ - pci_unregister_driver(&jmicron_pci_driver); -} - -module_init(jmicron_ide_init); -module_exit(jmicron_ide_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c deleted file mode 100644 index 1378906..0000000 --- a/drivers/ide/pci/ns87415.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 1997-1998 Mark Lord - * Copyright (C) 1998 Eddie C. Dost - * Copyright (C) 1999-2000 Andre Hedrick - * Copyright (C) 2004 Grant Grundler - * - * Inspired by an earlier effort from David S. Miller - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "ns87415" - -#ifdef CONFIG_SUPERIO -/* SUPERIO 87560 is a PoS chip that NatSem denies exists. - * Unfortunately, it's built-in on all Astro-based PA-RISC workstations - * which use the integrated NS87514 cell for CD-ROM support. - * i.e we have to support for CD-ROM installs. - * See drivers/parisc/superio.c for more gory details. - */ -#include - -#define SUPERIO_IDE_MAX_RETRIES 25 - -/* Because of a defect in Super I/O, all reads of the PCI DMA status - * registers, IDE status register and the IDE select register need to be - * retried - */ -static u8 superio_ide_inb (unsigned long port) -{ - u8 tmp; - int retries = SUPERIO_IDE_MAX_RETRIES; - - /* printk(" [ reading port 0x%x with retry ] ", port); */ - - do { - tmp = inb(port); - if (tmp == 0) - udelay(50); - } while (tmp == 0 && retries-- > 0); - - return tmp; -} - -static u8 superio_read_status(ide_hwif_t *hwif) -{ - return superio_ide_inb(hwif->io_ports.status_addr); -} - -static u8 superio_read_sff_dma_status(ide_hwif_t *hwif) -{ - return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS); -} - -static void superio_tf_read(ide_drive_t *drive, ide_task_t *task) -{ - struct ide_io_ports *io_ports = &drive->hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - - if (task->tf_flags & IDE_TFLAG_IN_DATA) { - u16 data = inw(io_ports->data_addr); - - tf->data = data & 0xff; - tf->hob_data = (data >> 8) & 0xff; - } - - /* be sure we're looking at the low order bits */ - outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_FEATURE) - tf->feature = inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_NSECT) - tf->nsect = inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAL) - tf->lbal = inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAM) - tf->lbam = inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAH) - tf->lbah = inb(io_ports->lbah_addr); - if (task->tf_flags & IDE_TFLAG_IN_DEVICE) - tf->device = superio_ide_inb(io_ports->device_addr); - - if (task->tf_flags & IDE_TFLAG_LBA48) { - outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) - tf->hob_feature = inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) - tf->hob_nsect = inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) - tf->hob_lbal = inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) - tf->hob_lbam = inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) - tf->hob_lbah = inb(io_ports->lbah_addr); - } -} - -static const struct ide_tp_ops superio_tp_ops = { - .exec_command = ide_exec_command, - .read_status = superio_read_status, - .read_altstatus = ide_read_altstatus, - .read_sff_dma_status = superio_read_sff_dma_status, - - .set_irq = ide_set_irq, - - .tf_load = ide_tf_load, - .tf_read = superio_tf_read, - - .input_data = ide_input_data, - .output_data = ide_output_data, -}; - -static void __devinit superio_init_iops(struct hwif_s *hwif) -{ - struct pci_dev *pdev = to_pci_dev(hwif->dev); - u32 dma_stat; - u8 port = hwif->channel, tmp; - - dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa); - - /* Clear error/interrupt, enable dma */ - tmp = superio_ide_inb(dma_stat); - outb(tmp | 0x66, dma_stat); -} -#endif - -static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; - -/* - * This routine either enables/disables (according to IDE_DFLAG_PRESENT) - * the IRQ associated with the port (HWIF(drive)), - * and selects either PIO or DMA handshaking for the next I/O operation. - */ -static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data; - unsigned long flags; - - local_irq_save(flags); - new = *old; - - /* Adjust IRQ enable bit */ - bit = 1 << (8 + hwif->channel); - - if (drive->dev_flags & IDE_DFLAG_PRESENT) - new &= ~bit; - else - new |= bit; - - /* Select PIO or DMA, DMA may only be selected for one drive/channel. */ - bit = 1 << (20 + (drive->dn & 1) + (hwif->channel << 1)); - other = 1 << (20 + (1 - (drive->dn & 1)) + (hwif->channel << 1)); - new = use_dma ? ((new & ~other) | bit) : (new & ~bit); - - if (new != *old) { - unsigned char stat; - - /* - * Don't change DMA engine settings while Write Buffers - * are busy. - */ - (void) pci_read_config_byte(dev, 0x43, &stat); - while (stat & 0x03) { - udelay(1); - (void) pci_read_config_byte(dev, 0x43, &stat); - } - - *old = new; - (void) pci_write_config_dword(dev, 0x40, new); - - /* - * And let things settle... - */ - udelay(10); - } - - local_irq_restore(flags); -} - -static void ns87415_selectproc (ide_drive_t *drive) -{ - ns87415_prepare_drive(drive, - !!(drive->dev_flags & IDE_DFLAG_USING_DMA)); -} - -static int ns87415_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u8 dma_stat = 0, dma_cmd = 0; - - drive->waiting_for_dma = 0; - dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); - /* get DMA command mode */ - dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); - /* stop DMA */ - outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); - /* from ERRATA: clear the INTR & ERROR bits */ - dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); - outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD); - /* and free any DMA resources */ - ide_destroy_dmatable(drive); - /* verify good DMA status */ - return (dma_stat & 7) != 4; -} - -static int ns87415_dma_setup(ide_drive_t *drive) -{ - /* select DMA xfer */ - ns87415_prepare_drive(drive, 1); - if (!ide_dma_setup(drive)) - return 0; - /* DMA failed: select PIO xfer */ - ns87415_prepare_drive(drive, 0); - return 1; -} - -static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned int ctrl, using_inta; - u8 progif; -#ifdef __sparc_v9__ - int timeout; - u8 stat; -#endif - - /* - * We cannot probe for IRQ: both ports share common IRQ on INTA. - * Also, leave IRQ masked during drive probing, to prevent infinite - * interrupts from a potentially floating INTA.. - * - * IRQs get unmasked in selectproc when drive is first used. - */ - (void) pci_read_config_dword(dev, 0x40, &ctrl); - (void) pci_read_config_byte(dev, 0x09, &progif); - /* is irq in "native" mode? */ - using_inta = progif & (1 << (hwif->channel << 1)); - if (!using_inta) - using_inta = ctrl & (1 << (4 + hwif->channel)); - if (hwif->mate) { - hwif->select_data = hwif->mate->select_data; - } else { - hwif->select_data = (unsigned long) - &ns87415_control[ns87415_count++]; - ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */ - if (using_inta) - ctrl &= ~(1 << 6); /* unmask INTA */ - *((unsigned int *)hwif->select_data) = ctrl; - (void) pci_write_config_dword(dev, 0x40, ctrl); - - /* - * Set prefetch size to 512 bytes for both ports, - * but don't turn on/off prefetching here. - */ - pci_write_config_byte(dev, 0x55, 0xee); - -#ifdef __sparc_v9__ - /* - * XXX: Reset the device, if we don't it will not respond to - * SELECT_DRIVE() properly during first ide_probe_port(). - */ - timeout = 10000; - outb(12, hwif->io_ports.ctl_addr); - udelay(10); - outb(8, hwif->io_ports.ctl_addr); - do { - udelay(50); - stat = hwif->tp_ops->read_status(hwif); - if (stat == 0xff) - break; - } while ((stat & ATA_BUSY) && --timeout); -#endif - } - - if (!using_inta) - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - hwif->irq = hwif->mate->irq; /* share IRQ with mate */ - - if (!hwif->dma_base) - return; - - outb(0x60, hwif->dma_base + ATA_DMA_STATUS); -} - -static const struct ide_port_ops ns87415_port_ops = { - .selectproc = ns87415_selectproc, -}; - -static const struct ide_dma_ops ns87415_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ns87415_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = ns87415_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_port_info ns87415_chipset __devinitdata = { - .name = DRV_NAME, - .init_hwif = init_hwif_ns87415, - .port_ops = &ns87415_port_ops, - .dma_ops = &ns87415_dma_ops, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_NO_ATAPI_DMA, -}; - -static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct ide_port_info d = ns87415_chipset; - -#ifdef CONFIG_SUPERIO - if (PCI_SLOT(dev->devfn) == 0xE) { - /* Built-in - assume it's under superio. */ - d.init_iops = superio_init_iops; - d.tp_ops = &superio_tp_ops; - } -#endif - return ide_pci_init_one(dev, &d, NULL); -} - -static const struct pci_device_id ns87415_pci_tbl[] = { - { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87415), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl); - -static struct pci_driver ns87415_pci_driver = { - .name = "NS87415_IDE", - .id_table = ns87415_pci_tbl, - .probe = ns87415_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init ns87415_ide_init(void) -{ - return ide_pci_register_driver(&ns87415_pci_driver); -} - -static void __exit ns87415_ide_exit(void) -{ - pci_unregister_driver(&ns87415_pci_driver); -} - -module_init(ns87415_ide_init); -module_exit(ns87415_ide_exit); - -MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for NS87415 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c deleted file mode 100644 index 6048eda..0000000 --- a/drivers/ide/pci/opti621.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) - */ - -/* - * Authors: - * Jaromir Koutek , - * Jan Harkes , - * Mark Lord - * Some parts of code are from ali14xx.c and from rz1000.c. - * - * OPTi is trademark of OPTi, Octek is trademark of Octek. - * - * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps - * and disassembled/traced setupvic.exe (DOS program). - * It increases kernel code about 2 kB. - * I don't have this card no more, but I hope I can get some in case - * of needed development. - * My card is Octek PIDE 1.01 (on card) or OPTiViC (program). - * It has a place for a secondary connector in circuit, but nothing - * is there. Also BIOS says no address for - * secondary controller (see bellow in ide_init_opti621). - * I've only tested this on my system, which only has one disk. - * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus - * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random - * lockups). I tried the OCTEK double speed CD-ROM and - * it does not work! But I can't boot DOS also, so it's probably - * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no - * problems) and Seagate 1GB (as slave, WD as master). My experiences - * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes - * it slows to about 100kB/s! I don't know why and I have - * not this drive now, so I can't try it again. - * I write this driver because I lost the paper ("manual") with - * settings of jumpers on the card and I have to boot Linux with - * Loadlin except LILO, cause I have to run the setupvic.exe program - * already or I get disk errors (my test: rpm -Vf - * /usr/X11R6/bin/XF86_SVGA - or any big file). - * Some numbers from hdparm -t /dev/hda: - * Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec - * Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec - * I have 4 Megs/s before, but I don't know why (maybe changes - * in hdparm test). - * After release of 0.1, I got some successful reports, so it might work. - * - * The main problem with OPTi is that some timings for master - * and slave must be the same. For example, if you have master - * PIO 3 and slave PIO 0, driver have to set some timings of - * master for PIO 0. Second problem is that opti621_set_pio_mode - * got only one drive to set, but have to set both drives. - * This is solved in compute_pios. If you don't set - * the second drive, compute_pios use ide_get_best_pio_mode - * for autoselect mode (you can change it to PIO 0, if you want). - * If you then set the second drive to another PIO, the old value - * (automatically selected) will be overrided by yours. - * There is a 25/33MHz switch in configuration - * register, but driver is written for use at any frequency. - * - * Version 0.1, Nov 8, 1996 - * by Jaromir Koutek, for 2.1.8. - * Initial version of driver. - * - * Version 0.2 - * Number 0.2 skipped. - * - * Version 0.3, Nov 29, 1997 - * by Mark Lord (probably), for 2.1.68 - * Updates for use with new IDE block driver. - * - * Version 0.4, Dec 14, 1997 - * by Jan Harkes - * Fixed some errors and cleaned the code. - * - * Version 0.5, Jan 2, 1998 - * by Jaromir Koutek - * Updates for use with (again) new IDE block driver. - * Update of documentation. - * - * Version 0.6, Jan 2, 1999 - * by Jaromir Koutek - * Reversed to version 0.3 of the driver, because - * 0.5 doesn't work. - */ - -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "opti621" - -#define READ_REG 0 /* index of Read cycle timing register */ -#define WRITE_REG 1 /* index of Write cycle timing register */ -#define CNTRL_REG 3 /* index of Control register */ -#define STRAP_REG 5 /* index of Strap register */ -#define MISC_REG 6 /* index of Miscellaneous register */ - -static int reg_base; - -static DEFINE_SPINLOCK(opti621_lock); - -/* Write value to register reg, base of register - * is at reg_base (0x1f0 primary, 0x170 secondary, - * if not changed by PCI configuration). - * This is from setupvic.exe program. - */ -static void write_reg(u8 value, int reg) -{ - inw(reg_base + 1); - inw(reg_base + 1); - outb(3, reg_base + 2); - outb(value, reg_base + reg); - outb(0x83, reg_base + 2); -} - -/* Read value from register reg, base of register - * is at reg_base (0x1f0 primary, 0x170 secondary, - * if not changed by PCI configuration). - * This is from setupvic.exe program. - */ -static u8 read_reg(int reg) -{ - u8 ret = 0; - - inw(reg_base + 1); - inw(reg_base + 1); - outb(3, reg_base + 2); - ret = inb(reg_base + reg); - outb(0x83, reg_base + 2); - - return ret; -} - -static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = drive->hwif; - ide_drive_t *pair = ide_get_pair_dev(drive); - unsigned long flags; - u8 tim, misc, addr_pio = pio, clk; - - /* DRDY is default 2 (by OPTi Databook) */ - static const u8 addr_timings[2][5] = { - { 0x20, 0x10, 0x00, 0x00, 0x00 }, /* 33 MHz */ - { 0x10, 0x10, 0x00, 0x00, 0x00 }, /* 25 MHz */ - }; - static const u8 data_rec_timings[2][5] = { - { 0x5b, 0x45, 0x32, 0x21, 0x20 }, /* 33 MHz */ - { 0x48, 0x34, 0x21, 0x10, 0x10 } /* 25 MHz */ - }; - - drive->drive_data = XFER_PIO_0 + pio; - - if (pair) { - if (pair->drive_data && pair->drive_data < drive->drive_data) - addr_pio = pair->drive_data - XFER_PIO_0; - } - - spin_lock_irqsave(&opti621_lock, flags); - - reg_base = hwif->io_ports.data_addr; - - /* allow Register-B */ - outb(0xc0, reg_base + CNTRL_REG); - /* hmm, setupvic.exe does this ;-) */ - outb(0xff, reg_base + 5); - /* if reads 0xff, adapter not exist? */ - (void)inb(reg_base + CNTRL_REG); - /* if reads 0xc0, no interface exist? */ - read_reg(CNTRL_REG); - - /* check CLK speed */ - clk = read_reg(STRAP_REG) & 1; - - printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33); - - tim = data_rec_timings[clk][pio]; - misc = addr_timings[clk][addr_pio]; - - /* select Index-0/1 for Register-A/B */ - write_reg(drive->dn & 1, MISC_REG); - /* set read cycle timings */ - write_reg(tim, READ_REG); - /* set write cycle timings */ - write_reg(tim, WRITE_REG); - - /* use Register-A for drive 0 */ - /* use Register-B for drive 1 */ - write_reg(0x85, CNTRL_REG); - - /* set address setup, DRDY timings, */ - /* and read prefetch for both drives */ - write_reg(misc, MISC_REG); - - spin_unlock_irqrestore(&opti621_lock, flags); -} - -static const struct ide_port_ops opti621_port_ops = { - .set_pio_mode = opti621_set_pio_mode, -}; - -static const struct ide_port_info opti621_chipset __devinitdata = { - .name = DRV_NAME, - .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, - .port_ops = &opti621_port_ops, - .host_flags = IDE_HFLAG_NO_DMA, - .pio_mask = ATA_PIO4, -}; - -static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &opti621_chipset, NULL); -} - -static const struct pci_device_id opti621_pci_tbl[] = { - { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 }, - { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, opti621_pci_tbl); - -static struct pci_driver opti621_pci_driver = { - .name = "Opti621_IDE", - .id_table = opti621_pci_tbl, - .probe = opti621_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init opti621_ide_init(void) -{ - return ide_pci_register_driver(&opti621_pci_driver); -} - -static void __exit opti621_ide_exit(void) -{ - pci_unregister_driver(&opti621_pci_driver); -} - -module_init(opti621_ide_init); -module_exit(opti621_ide_exit); - -MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord"); -MODULE_DESCRIPTION("PCI driver module for Opti621 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c deleted file mode 100644 index 211ae46..0000000 --- a/drivers/ide/pci/pdc202xx_new.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Promise TX2/TX4/TX2000/133 IDE driver - * - * 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. - * - * Split from: - * linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002 - * Copyright (C) 1998-2002 Andre Hedrick - * Copyright (C) 2005-2007 MontaVista Software, Inc. - * Portions Copyright (C) 1999 Promise Technology, Inc. - * Author: Frank Tiernan (frankt@promise.com) - * Released under terms of General Public License - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef CONFIG_PPC_PMAC -#include -#include -#endif - -#define DRV_NAME "pdc202xx_new" - -#undef DEBUG - -#ifdef DEBUG -#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args) -#else -#define DBG(fmt, args...) -#endif - -static const char *pdc_quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP KA9.1", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP KX13.6", - "QUANTUM FIREBALLP KX20.5", - "QUANTUM FIREBALLP KX27.3", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -static u8 max_dma_rate(struct pci_dev *pdev) -{ - u8 mode; - - switch(pdev->device) { - case PCI_DEVICE_ID_PROMISE_20277: - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20271: - case PCI_DEVICE_ID_PROMISE_20269: - mode = 4; - break; - case PCI_DEVICE_ID_PROMISE_20270: - case PCI_DEVICE_ID_PROMISE_20268: - mode = 3; - break; - default: - return 0; - } - - return mode; -} - -/** - * get_indexed_reg - Get indexed register - * @hwif: for the port address - * @index: index of the indexed register - */ -static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) -{ - u8 value; - - outb(index, hwif->dma_base + 1); - value = inb(hwif->dma_base + 3); - - DBG("index[%02X] value[%02X]\n", index, value); - return value; -} - -/** - * set_indexed_reg - Set indexed register - * @hwif: for the port address - * @index: index of the indexed register - */ -static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value) -{ - outb(index, hwif->dma_base + 1); - outb(value, hwif->dma_base + 3); - DBG("index[%02X] value[%02X]\n", index, value); -} - -/* - * ATA Timing Tables based on 133 MHz PLL output clock. - * - * If the PLL outputs 100 MHz clock, the ASIC hardware will set - * the timing registers automatically when "set features" command is - * issued to the device. However, if the PLL output clock is 133 MHz, - * the following tables must be used. - */ -static struct pio_timing { - u8 reg0c, reg0d, reg13; -} pio_timings [] = { - { 0xfb, 0x2b, 0xac }, /* PIO mode 0, IORDY off, Prefetch off */ - { 0x46, 0x29, 0xa4 }, /* PIO mode 1, IORDY off, Prefetch off */ - { 0x23, 0x26, 0x64 }, /* PIO mode 2, IORDY off, Prefetch off */ - { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ - { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ -}; - -static struct mwdma_timing { - u8 reg0e, reg0f; -} mwdma_timings [] = { - { 0xdf, 0x5f }, /* MWDMA mode 0 */ - { 0x6b, 0x27 }, /* MWDMA mode 1 */ - { 0x69, 0x25 }, /* MWDMA mode 2 */ -}; - -static struct udma_timing { - u8 reg10, reg11, reg12; -} udma_timings [] = { - { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ - { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ - { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ - { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ - { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ - { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ - { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ -}; - -static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 adj = (drive->dn & 1) ? 0x08 : 0x00; - - /* - * IDE core issues SETFEATURES_XFER to the drive first (thanks to - * IDE_HFLAG_POST_SET_MODE in ->host_flags). PDC202xx hardware will - * automatically set the timing registers based on 100 MHz PLL output. - * - * As we set up the PLL to output 133 MHz for UltraDMA/133 capable - * chips, we must override the default register settings... - */ - if (max_dma_rate(dev) == 4) { - u8 mode = speed & 0x07; - - if (speed >= XFER_UDMA_0) { - set_indexed_reg(hwif, 0x10 + adj, - udma_timings[mode].reg10); - set_indexed_reg(hwif, 0x11 + adj, - udma_timings[mode].reg11); - set_indexed_reg(hwif, 0x12 + adj, - udma_timings[mode].reg12); - } else { - set_indexed_reg(hwif, 0x0e + adj, - mwdma_timings[mode].reg0e); - set_indexed_reg(hwif, 0x0f + adj, - mwdma_timings[mode].reg0f); - } - } else if (speed == XFER_UDMA_2) { - /* Set tHOLD bit to 0 if using UDMA mode 2 */ - u8 tmp = get_indexed_reg(hwif, 0x10 + adj); - - set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f); - } -} - -static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 adj = (drive->dn & 1) ? 0x08 : 0x00; - - if (max_dma_rate(dev) == 4) { - set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c); - set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d); - set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13); - } -} - -static u8 pdcnew_cable_detect(ide_hwif_t *hwif) -{ - if (get_indexed_reg(hwif, 0x0b) & 0x04) - return ATA_CBL_PATA40; - else - return ATA_CBL_PATA80; -} - -static void pdcnew_quirkproc(ide_drive_t *drive) -{ - const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; - - for (list = pdc_quirk_drives; *list != NULL; list++) - if (strstr(m, *list) != NULL) { - drive->quirk_list = 2; - return; - } - - drive->quirk_list = 0; -} - -static void pdcnew_reset(ide_drive_t *drive) -{ - /* - * Deleted this because it is redundant from the caller. - */ - printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n", - HWIF(drive)->channel ? "Secondary" : "Primary"); -} - -/** - * read_counter - Read the byte count registers - * @dma_base: for the port address - */ -static long read_counter(u32 dma_base) -{ - u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08; - u8 cnt0, cnt1, cnt2, cnt3; - long count = 0, last; - int retry = 3; - - do { - last = count; - - /* Read the current count */ - outb(0x20, pri_dma_base + 0x01); - cnt0 = inb(pri_dma_base + 0x03); - outb(0x21, pri_dma_base + 0x01); - cnt1 = inb(pri_dma_base + 0x03); - outb(0x20, sec_dma_base + 0x01); - cnt2 = inb(sec_dma_base + 0x03); - outb(0x21, sec_dma_base + 0x01); - cnt3 = inb(sec_dma_base + 0x03); - - count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0; - - /* - * The 30-bit decrementing counter is read in 4 pieces. - * Incorrect value may be read when the most significant bytes - * are changing... - */ - } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count)); - - DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n", - cnt0, cnt1, cnt2, cnt3); - - return count; -} - -/** - * detect_pll_input_clock - Detect the PLL input clock in Hz. - * @dma_base: for the port address - * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock. - */ -static long detect_pll_input_clock(unsigned long dma_base) -{ - struct timeval start_time, end_time; - long start_count, end_count; - long pll_input, usec_elapsed; - u8 scr1; - - start_count = read_counter(dma_base); - do_gettimeofday(&start_time); - - /* Start the test mode */ - outb(0x01, dma_base + 0x01); - scr1 = inb(dma_base + 0x03); - DBG("scr1[%02X]\n", scr1); - outb(scr1 | 0x40, dma_base + 0x03); - - /* Let the counter run for 10 ms. */ - mdelay(10); - - end_count = read_counter(dma_base); - do_gettimeofday(&end_time); - - /* Stop the test mode */ - outb(0x01, dma_base + 0x01); - scr1 = inb(dma_base + 0x03); - DBG("scr1[%02X]\n", scr1); - outb(scr1 & ~0x40, dma_base + 0x03); - - /* - * Calculate the input clock in Hz - * (the clock counter is 30 bit wide and counts down) - */ - usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 + - (end_time.tv_usec - start_time.tv_usec); - pll_input = ((start_count - end_count) & 0x3fffffff) / 10 * - (10000000 / usec_elapsed); - - DBG("start[%ld] end[%ld]\n", start_count, end_count); - - return pll_input; -} - -#ifdef CONFIG_PPC_PMAC -static void apple_kiwi_init(struct pci_dev *pdev) -{ - struct device_node *np = pci_device_to_OF_node(pdev); - u8 conf; - - if (np == NULL || !of_device_is_compatible(np, "kiwi-root")) - return; - - if (pdev->revision >= 0x03) { - /* Setup chip magic config stuff (from darwin) */ - pci_read_config_byte (pdev, 0x40, &conf); - pci_write_config_byte(pdev, 0x40, (conf | 0x01)); - } -} -#endif /* CONFIG_PPC_PMAC */ - -static unsigned int init_chipset_pdcnew(struct pci_dev *dev) -{ - const char *name = DRV_NAME; - unsigned long dma_base = pci_resource_start(dev, 4); - unsigned long sec_dma_base = dma_base + 0x08; - long pll_input, pll_output, ratio; - int f, r; - u8 pll_ctl0, pll_ctl1; - - if (dma_base == 0) - return -EFAULT; - -#ifdef CONFIG_PPC_PMAC - apple_kiwi_init(dev); -#endif - - /* Calculate the required PLL output frequency */ - switch(max_dma_rate(dev)) { - case 4: /* it's 133 MHz for Ultra133 chips */ - pll_output = 133333333; - break; - case 3: /* and 100 MHz for Ultra100 chips */ - default: - pll_output = 100000000; - break; - } - - /* - * Detect PLL input clock. - * On some systems, where PCI bus is running at non-standard clock rate - * (e.g. 25 or 40 MHz), we have to adjust the cycle time. - * PDC20268 and newer chips employ PLL circuit to help correct timing - * registers setting. - */ - pll_input = detect_pll_input_clock(dma_base); - printk(KERN_INFO "%s %s: PLL input clock is %ld kHz\n", - name, pci_name(dev), pll_input / 1000); - - /* Sanity check */ - if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) { - printk(KERN_ERR "%s %s: Bad PLL input clock %ld Hz, giving up!" - "\n", name, pci_name(dev), pll_input); - goto out; - } - -#ifdef DEBUG - DBG("pll_output is %ld Hz\n", pll_output); - - /* Show the current clock value of PLL control register - * (maybe already configured by the BIOS) - */ - outb(0x02, sec_dma_base + 0x01); - pll_ctl0 = inb(sec_dma_base + 0x03); - outb(0x03, sec_dma_base + 0x01); - pll_ctl1 = inb(sec_dma_base + 0x03); - - DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); -#endif - - /* - * Calculate the ratio of F, R and NO - * POUT = (F + 2) / (( R + 2) * NO) - */ - ratio = pll_output / (pll_input / 1000); - if (ratio < 8600L) { /* 8.6x */ - /* Using NO = 0x01, R = 0x0d */ - r = 0x0d; - } else if (ratio < 12900L) { /* 12.9x */ - /* Using NO = 0x01, R = 0x08 */ - r = 0x08; - } else if (ratio < 16100L) { /* 16.1x */ - /* Using NO = 0x01, R = 0x06 */ - r = 0x06; - } else if (ratio < 64000L) { /* 64x */ - r = 0x00; - } else { - /* Invalid ratio */ - printk(KERN_ERR "%s %s: Bad ratio %ld, giving up!\n", - name, pci_name(dev), ratio); - goto out; - } - - f = (ratio * (r + 2)) / 1000 - 2; - - DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio); - - if (unlikely(f < 0 || f > 127)) { - /* Invalid F */ - printk(KERN_ERR "%s %s: F[%d] invalid!\n", - name, pci_name(dev), f); - goto out; - } - - pll_ctl0 = (u8) f; - pll_ctl1 = (u8) r; - - DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); - - outb(0x02, sec_dma_base + 0x01); - outb(pll_ctl0, sec_dma_base + 0x03); - outb(0x03, sec_dma_base + 0x01); - outb(pll_ctl1, sec_dma_base + 0x03); - - /* Wait the PLL circuit to be stable */ - mdelay(30); - -#ifdef DEBUG - /* - * Show the current clock value of PLL control register - */ - outb(0x02, sec_dma_base + 0x01); - pll_ctl0 = inb(sec_dma_base + 0x03); - outb(0x03, sec_dma_base + 0x01); - pll_ctl1 = inb(sec_dma_base + 0x03); - - DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); -#endif - - out: - return dev->irq; -} - -static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) -{ - struct pci_dev *dev2; - - dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1, - PCI_FUNC(dev->devfn))); - - if (dev2 && - dev2->vendor == dev->vendor && - dev2->device == dev->device) { - - if (dev2->irq != dev->irq) { - dev2->irq = dev->irq; - printk(KERN_INFO DRV_NAME " %s: PCI config space " - "interrupt fixed\n", pci_name(dev)); - } - - return dev2; - } - - return NULL; -} - -static const struct ide_port_ops pdcnew_port_ops = { - .set_pio_mode = pdcnew_set_pio_mode, - .set_dma_mode = pdcnew_set_dma_mode, - .quirkproc = pdcnew_quirkproc, - .resetproc = pdcnew_reset, - .cable_detect = pdcnew_cable_detect, -}; - -#define DECLARE_PDCNEW_DEV(udma) \ - { \ - .name = DRV_NAME, \ - .init_chipset = init_chipset_pdcnew, \ - .port_ops = &pdcnew_port_ops, \ - .host_flags = IDE_HFLAG_POST_SET_MODE | \ - IDE_HFLAG_ERROR_STOPS_FIFO | \ - IDE_HFLAG_OFF_BOARD, \ - .pio_mask = ATA_PIO4, \ - .mwdma_mask = ATA_MWDMA2, \ - .udma_mask = udma, \ - } - -static const struct ide_port_info pdcnew_chipsets[] __devinitdata = { - /* 0: PDC202{68,70} */ DECLARE_PDCNEW_DEV(ATA_UDMA5), - /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6), -}; - -/** - * pdc202new_init_one - called when a pdc202xx is found - * @dev: the pdc202new 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 __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data]; - struct pci_dev *bridge = dev->bus->self; - - if (dev->device == PCI_DEVICE_ID_PROMISE_20270 && bridge && - bridge->vendor == PCI_VENDOR_ID_DEC && - bridge->device == PCI_DEVICE_ID_DEC_21150) { - struct pci_dev *dev2; - - if (PCI_SLOT(dev->devfn) & 2) - return -ENODEV; - - dev2 = pdc20270_get_dev2(dev); - - if (dev2) { - int ret = ide_pci_init_two(dev, dev2, d, NULL); - if (ret < 0) - pci_dev_put(dev2); - return ret; - } - } - - if (dev->device == PCI_DEVICE_ID_PROMISE_20276 && bridge && - bridge->vendor == PCI_VENDOR_ID_INTEL && - (bridge->device == PCI_DEVICE_ID_INTEL_I960 || - bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) { - printk(KERN_INFO DRV_NAME " %s: attached to I2O RAID controller," - " skipping\n", pci_name(dev)); - return -ENODEV; - } - - return ide_pci_init_one(dev, d, NULL); -} - -static void __devexit pdc202new_remove(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; - - ide_pci_remove(dev); - pci_dev_put(dev2); -} - -static const struct pci_device_id pdc202new_pci_tbl[] = { - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 0 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 1 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 1 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 1 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 1 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl); - -static struct pci_driver pdc202new_pci_driver = { - .name = "Promise_IDE", - .id_table = pdc202new_pci_tbl, - .probe = pdc202new_init_one, - .remove = __devexit_p(pdc202new_remove), - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init pdc202new_ide_init(void) -{ - return ide_pci_register_driver(&pdc202new_pci_driver); -} - -static void __exit pdc202new_ide_exit(void) -{ - pci_unregister_driver(&pdc202new_pci_driver); -} - -module_init(pdc202new_ide_init); -module_exit(pdc202new_ide_exit); - -MODULE_AUTHOR("Andre Hedrick, Frank Tiernan"); -MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c deleted file mode 100644 index 799557c..0000000 --- a/drivers/ide/pci/pdc202xx_old.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) 1998-2002 Andre Hedrick - * Copyright (C) 2006-2007 MontaVista Software, Inc. - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * - * Portions Copyright (C) 1999 Promise Technology, Inc. - * Author: Frank Tiernan (frankt@promise.com) - * Released under terms of General Public License - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "pdc202xx_old" - -#define PDC202XX_DEBUG_DRIVE_INFO 0 - -static const char *pdc_quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP KA9.1", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP KX13.6", - "QUANTUM FIREBALLP KX20.5", - "QUANTUM FIREBALLP KX27.3", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -static void pdc_old_disable_66MHz_clock(ide_hwif_t *); - -static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 drive_pci = 0x60 + (drive->dn << 2); - - u8 AP = 0, BP = 0, CP = 0; - u8 TA = 0, TB = 0, TC = 0; - -#if PDC202XX_DEBUG_DRIVE_INFO - u32 drive_conf = 0; - pci_read_config_dword(dev, drive_pci, &drive_conf); -#endif - - /* - * TODO: do this once per channel - */ - if (dev->device != PCI_DEVICE_ID_PROMISE_20246) - pdc_old_disable_66MHz_clock(hwif); - - pci_read_config_byte(dev, drive_pci, &AP); - pci_read_config_byte(dev, drive_pci + 1, &BP); - pci_read_config_byte(dev, drive_pci + 2, &CP); - - switch(speed) { - case XFER_UDMA_5: - case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; - case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; - case XFER_UDMA_3: - case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; - case XFER_UDMA_0: - case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; - case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; - case XFER_MW_DMA_0: TB = 0xE0; TC = 0x0F; break; - case XFER_PIO_4: TA = 0x01; TB = 0x04; break; - case XFER_PIO_3: TA = 0x02; TB = 0x06; break; - case XFER_PIO_2: TA = 0x03; TB = 0x08; break; - case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; - case XFER_PIO_0: - default: TA = 0x09; TB = 0x13; break; - } - - if (speed < XFER_SW_DMA_0) { - /* - * preserve SYNC_INT / ERDDY_EN bits while clearing - * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A - */ - AP &= ~0x3f; - if (ata_id_iordy_disable(drive->id)) - AP |= 0x20; /* set IORDY_EN bit */ - if (drive->media == ide_disk) - AP |= 0x10; /* set Prefetch_EN bit */ - /* clear PB[4:0] bits of register B */ - BP &= ~0x1f; - pci_write_config_byte(dev, drive_pci, AP | TA); - pci_write_config_byte(dev, drive_pci + 1, BP | TB); - } else { - /* clear MB[2:0] bits of register B */ - BP &= ~0xe0; - /* clear MC[3:0] bits of register C */ - CP &= ~0x0f; - pci_write_config_byte(dev, drive_pci + 1, BP | TB); - pci_write_config_byte(dev, drive_pci + 2, CP | TC); - } - -#if PDC202XX_DEBUG_DRIVE_INFO - printk(KERN_DEBUG "%s: %s drive%d 0x%08x ", - drive->name, ide_xfer_verbose(speed), - drive->dn, drive_conf); - pci_read_config_dword(dev, drive_pci, &drive_conf); - printk("0x%08x\n", drive_conf); -#endif -} - -static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - pdc202xx_set_mode(drive, XFER_PIO_0 + pio); -} - -static u8 pdc2026x_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10); - - pci_read_config_word(dev, 0x50, &CIS); - - return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; -} - -/* - * Set the control register to use the 66MHz system - * clock for UDMA 3/4/5 mode operation when necessary. - * - * FIXME: this register is shared by both channels, some locking is needed - * - * It may also be possible to leave the 66MHz clock on - * and readjust the timing parameters. - */ -static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif) -{ - unsigned long clock_reg = hwif->extra_base + 0x01; - u8 clock = inb(clock_reg); - - outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg); -} - -static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) -{ - unsigned long clock_reg = hwif->extra_base + 0x01; - u8 clock = inb(clock_reg); - - outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); -} - -static void pdc202xx_quirkproc(ide_drive_t *drive) -{ - const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; - - for (list = pdc_quirk_drives; *list != NULL; list++) - if (strstr(m, *list) != NULL) { - drive->quirk_list = 2; - return; - } - - drive->quirk_list = 0; -} - -static void pdc202xx_dma_start(ide_drive_t *drive) -{ - if (drive->current_speed > XFER_UDMA_2) - pdc_old_enable_66MHz_clock(drive->hwif); - if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) { - struct request *rq = HWGROUP(drive)->rq; - ide_hwif_t *hwif = HWIF(drive); - unsigned long high_16 = hwif->extra_base - 16; - unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); - u32 word_count = 0; - u8 clock = inb(high_16 + 0x11); - - outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11); - word_count = (rq->nr_sectors << 8); - word_count = (rq_data_dir(rq) == READ) ? - word_count | 0x05000000 : - word_count | 0x06000000; - outl(word_count, atapi_reg); - } - ide_dma_start(drive); -} - -static int pdc202xx_dma_end(ide_drive_t *drive) -{ - if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) { - ide_hwif_t *hwif = HWIF(drive); - unsigned long high_16 = hwif->extra_base - 16; - unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); - u8 clock = 0; - - outl(0, atapi_reg); /* zero out extra */ - clock = inb(high_16 + 0x11); - outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11); - } - if (drive->current_speed > XFER_UDMA_2) - pdc_old_disable_66MHz_clock(drive->hwif); - return ide_dma_end(drive); -} - -static int pdc202xx_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long high_16 = hwif->extra_base - 16; - u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - u8 sc1d = inb(high_16 + 0x001d); - - if (hwif->channel) { - /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */ - if ((sc1d & 0x50) == 0x50) - goto somebody_else; - else if ((sc1d & 0x40) == 0x40) - return (dma_stat & 4) == 4; - } else { - /* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */ - if ((sc1d & 0x05) == 0x05) - goto somebody_else; - else if ((sc1d & 0x04) == 0x04) - return (dma_stat & 4) == 4; - } -somebody_else: - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ -} - -static void pdc202xx_reset_host (ide_hwif_t *hwif) -{ - unsigned long high_16 = hwif->extra_base - 16; - u8 udma_speed_flag = inb(high_16 | 0x001f); - - outb(udma_speed_flag | 0x10, high_16 | 0x001f); - mdelay(100); - outb(udma_speed_flag & ~0x10, high_16 | 0x001f); - mdelay(2000); /* 2 seconds ?! */ - - printk(KERN_WARNING "PDC202XX: %s channel reset.\n", - hwif->channel ? "Secondary" : "Primary"); -} - -static void pdc202xx_reset (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - ide_hwif_t *mate = hwif->mate; - - pdc202xx_reset_host(hwif); - pdc202xx_reset_host(mate); - - ide_set_max_pio(drive); -} - -static void pdc202xx_dma_lost_irq(ide_drive_t *drive) -{ - pdc202xx_reset(drive); - ide_dma_lost_irq(drive); -} - -static void pdc202xx_dma_timeout(ide_drive_t *drive) -{ - pdc202xx_reset(drive); - ide_dma_timeout(drive); -} - -static unsigned int init_chipset_pdc202xx(struct pci_dev *dev) -{ - unsigned long dmabase = pci_resource_start(dev, 4); - u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; - - if (dmabase == 0) - goto out; - - udma_speed_flag = inb(dmabase | 0x1f); - primary_mode = inb(dmabase | 0x1a); - secondary_mode = inb(dmabase | 0x1b); - printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \ - "Primary %s Mode " \ - "Secondary %s Mode.\n", pci_name(dev), - (udma_speed_flag & 1) ? "EN" : "DIS", - (primary_mode & 1) ? "MASTER" : "PCI", - (secondary_mode & 1) ? "MASTER" : "PCI" ); - - if (!(udma_speed_flag & 1)) { - printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ", - pci_name(dev), udma_speed_flag, - (udma_speed_flag|1)); - outb(udma_speed_flag | 1, dmabase | 0x1f); - printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN"); - } -out: - return dev->irq; -} - -static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, - const char *name) -{ - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { - u8 irq = 0, irq2 = 0; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - /* 0xbc */ - pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); - if (irq != irq2) { - pci_write_config_byte(dev, - (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ - printk(KERN_INFO "%s %s: PCI config space interrupt " - "mirror fixed\n", name, pci_name(dev)); - } - } -} - -#define IDE_HFLAGS_PDC202XX \ - (IDE_HFLAG_ERROR_STOPS_FIFO | \ - IDE_HFLAG_OFF_BOARD) - -static const struct ide_port_ops pdc20246_port_ops = { - .set_pio_mode = pdc202xx_set_pio_mode, - .set_dma_mode = pdc202xx_set_mode, - .quirkproc = pdc202xx_quirkproc, -}; - -static const struct ide_port_ops pdc2026x_port_ops = { - .set_pio_mode = pdc202xx_set_pio_mode, - .set_dma_mode = pdc202xx_set_mode, - .quirkproc = pdc202xx_quirkproc, - .resetproc = pdc202xx_reset, - .cable_detect = pdc2026x_cable_detect, -}; - -static const struct ide_dma_ops pdc20246_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = ide_dma_end, - .dma_test_irq = pdc202xx_dma_test_irq, - .dma_lost_irq = pdc202xx_dma_lost_irq, - .dma_timeout = pdc202xx_dma_timeout, -}; - -static const struct ide_dma_ops pdc2026x_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = pdc202xx_dma_start, - .dma_end = pdc202xx_dma_end, - .dma_test_irq = pdc202xx_dma_test_irq, - .dma_lost_irq = pdc202xx_dma_lost_irq, - .dma_timeout = pdc202xx_dma_timeout, -}; - -#define DECLARE_PDC2026X_DEV(udma, extra_flags) \ - { \ - .name = DRV_NAME, \ - .init_chipset = init_chipset_pdc202xx, \ - .port_ops = &pdc2026x_port_ops, \ - .dma_ops = &pdc2026x_dma_ops, \ - .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \ - .pio_mask = ATA_PIO4, \ - .mwdma_mask = ATA_MWDMA2, \ - .udma_mask = udma, \ - } - -static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { - { /* 0: PDC20246 */ - .name = DRV_NAME, - .init_chipset = init_chipset_pdc202xx, - .port_ops = &pdc20246_port_ops, - .dma_ops = &pdc20246_dma_ops, - .host_flags = IDE_HFLAGS_PDC202XX, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA2, - }, - - /* 1: PDC2026{2,3} */ - DECLARE_PDC2026X_DEV(ATA_UDMA4, 0), - /* 2: PDC2026{5,7} */ - DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256), -}; - -/** - * pdc202xx_init_one - called when a PDC202xx is found - * @dev: the pdc202xx 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 __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - const struct ide_port_info *d; - u8 idx = id->driver_data; - - d = &pdc202xx_chipsets[idx]; - - if (idx < 2) - pdc202ata4_fixup_irq(dev, d->name); - - if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) { - struct pci_dev *bridge = dev->bus->self; - - if (bridge && - bridge->vendor == PCI_VENDOR_ID_INTEL && - (bridge->device == PCI_DEVICE_ID_INTEL_I960 || - bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) { - printk(KERN_INFO DRV_NAME " %s: skipping Promise " - "PDC20265 attached to I2O RAID controller\n", - pci_name(dev)); - return -ENODEV; - } - } - - return ide_pci_init_one(dev, d, NULL); -} - -static const struct pci_device_id pdc202xx_pci_tbl[] = { - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 }, - { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl); - -static struct pci_driver pdc202xx_pci_driver = { - .name = "Promise_Old_IDE", - .id_table = pdc202xx_pci_tbl, - .probe = pdc202xx_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init pdc202xx_ide_init(void) -{ - return ide_pci_register_driver(&pdc202xx_pci_driver); -} - -static void __exit pdc202xx_ide_exit(void) -{ - pci_unregister_driver(&pdc202xx_pci_driver); -} - -module_init(pdc202xx_ide_init); -module_exit(pdc202xx_ide_exit); - -MODULE_AUTHOR("Andre Hedrick, Frank Tiernan"); -MODULE_DESCRIPTION("PCI driver module for older Promise IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c deleted file mode 100644 index d63f9fd..0000000 --- a/drivers/ide/pci/piix.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer - * Copyright (C) 1998-2000 Andre Hedrick - * Copyright (C) 2003 Red Hat Inc - * Copyright (C) 2006-2007 MontaVista Software, Inc. - * - * May be copied or modified under the terms of the GNU General Public License - * - * Documentation: - * - * Publically available from Intel web site. Errata documentation - * is also publically available. As an aide to anyone hacking on this - * driver the list of errata that are relevant is below.going back to - * PIIX4. Older device documentation is now a bit tricky to find. - * - * Errata of note: - * - * Unfixable - * PIIX4 errata #9 - Only on ultra obscure hw - * ICH3 errata #13 - Not observed to affect real hw - * by Intel - * - * Things we must deal with - * PIIX4 errata #10 - BM IDE hang with non UDMA - * (must stop/start dma to recover) - * 440MX errata #15 - As PIIX4 errata #10 - * PIIX4 errata #15 - Must not read control registers - * during a PIO transfer - * 440MX errata #13 - As PIIX4 errata #15 - * ICH2 errata #21 - DMA mode 0 doesn't work right - * ICH0/1 errata #55 - As ICH2 errata #21 - * ICH2 spec c #9 - Extra operations needed to handle - * drive hotswap [NOT YET SUPPORTED] - * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary - * and must be dword aligned - * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3 - * - * Should have been BIOS fixed: - * 450NX: errata #19 - DMA hangs on old 450NX - * 450NX: errata #20 - DMA hangs on old 450NX - * 450NX: errata #25 - Corruption with DMA on old 450NX - * ICH3 errata #15 - IDE deadlock under high load - * (BIOS must set dev 31 fn 0 bit 23) - * ICH3 errata #18 - Don't use native mode - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "piix" - -static int no_piix_dma; - -/** - * piix_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * Set the interface PIO mode based upon the settings done by AMI BIOS. - */ - -static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - int is_slave = drive->dn & 1; - int master_port = hwif->channel ? 0x42 : 0x40; - int slave_port = 0x44; - unsigned long flags; - u16 master_data; - u8 slave_data; - static DEFINE_SPINLOCK(tune_lock); - int control = 0; - - /* ISP RTC */ - static const u8 timings[][2]= { - { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - /* - * Master vs slave is synchronized above us but the slave register is - * shared by the two hwifs so the corner case of two slave timeouts in - * parallel must be locked. - */ - spin_lock_irqsave(&tune_lock, flags); - pci_read_config_word(dev, master_port, &master_data); - - if (pio > 1) - control |= 1; /* Programmable timing on */ - if (drive->media == ide_disk) - control |= 4; /* Prefetch, post write */ - if (pio > 2) - control |= 2; /* IORDY */ - if (is_slave) { - master_data |= 0x4000; - master_data &= ~0x0070; - if (pio > 1) { - /* Set PPE, IE and TIME */ - master_data |= control << 4; - } - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data &= hwif->channel ? 0x0f : 0xf0; - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << - (hwif->channel ? 4 : 0); - } else { - master_data &= ~0x3307; - if (pio > 1) { - /* enable PPE, IE and TIME */ - master_data |= control; - } - master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); - } - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&tune_lock, flags); -} - -/** - * piix_set_dma_mode - set host controller for DMA mode - * @drive: drive - * @speed: DMA mode - * - * Set a PIIX host controller to the desired DMA mode. This involves - * programming the right timing data into the PCI configuration space. - */ - -static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 maslave = hwif->channel ? 0x42 : 0x40; - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int v_flag = 0x01 << drive->dn; - int w_flag = 0x10 << drive->dn; - int u_speed = 0; - int sitre; - u16 reg4042, reg4a; - u8 reg48, reg54, reg55; - - pci_read_config_word(dev, maslave, ®4042); - sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_byte(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_byte(dev, 0x54, ®54); - pci_read_config_byte(dev, 0x55, ®55); - - if (speed >= XFER_UDMA_0) { - u8 udma = speed - XFER_UDMA_0; - - u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4); - - if (!(reg48 & u_flag)) - pci_write_config_byte(dev, 0x48, reg48 | u_flag); - if (speed == XFER_UDMA_5) { - pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); - } else { - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - } - if ((reg4a & a_speed) != u_speed) - pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); - if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) - pci_write_config_byte(dev, 0x54, reg54 | v_flag); - } else - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - } else { - const u8 mwdma_to_pio[] = { 0, 3, 4 }; - u8 pio; - - if (reg48 & u_flag) - pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - if (reg54 & v_flag) - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - if (reg55 & w_flag) - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - - if (speed >= XFER_MW_DMA_0) - pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; - else - pio = 2; /* only SWDMA2 is allowed */ - - piix_set_pio_mode(drive, pio); - } -} - -/** - * init_chipset_ich - set up the ICH chipset - * @dev: PCI device to set up - * - * Initialize the PCI device as required. For the ICH this turns - * out to be nice and simple. - */ - -static unsigned int init_chipset_ich(struct pci_dev *dev) -{ - u32 extra = 0; - - pci_read_config_dword(dev, 0x54, &extra); - pci_write_config_dword(dev, 0x54, extra | 0x400); - - return 0; -} - -/** - * ich_clear_irq - clear BMDMA status - * @drive: IDE drive - * - * ICHx contollers set DMA INTR no matter DMA or PIO. - * BMDMA status might need to be cleared even for - * PIO interrupts to prevent spurious/lost IRQ. - */ -static void ich_clear_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u8 dma_stat; - - /* - * ide_dma_end() needs BMDMA status for error checking. - * So, skip clearing BMDMA status here and leave it - * to ide_dma_end() if this is DMA interrupt. - */ - if (drive->waiting_for_dma || hwif->dma_base == 0) - return; - - /* clear the INTR & ERROR bits */ - dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - /* Should we force the bit as well ? */ - outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS); -} - -struct ich_laptop { - u16 device; - u16 subvendor; - u16 subdevice; -}; - -/* - * List of laptops that use short cables rather than 80 wire - */ - -static const struct ich_laptop ich_laptop[] = { - /* devid, subvendor, subdev */ - { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ - { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ - { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ - { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ - { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ - { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ - { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */ - { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ - /* end marker */ - { 0, } -}; - -static u8 piix_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *pdev = to_pci_dev(hwif->dev); - const struct ich_laptop *lap = &ich_laptop[0]; - u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30; - - /* check for specials */ - while (lap->device) { - if (lap->device == pdev->device && - lap->subvendor == pdev->subsystem_vendor && - lap->subdevice == pdev->subsystem_device) { - return ATA_CBL_PATA40_SHORT; - } - lap++; - } - - pci_read_config_byte(pdev, 0x54, ®54h); - - return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; -} - -/** - * init_hwif_piix - fill in the hwif for the PIIX - * @hwif: IDE interface - * - * Set up the ide_hwif_t for the PIIX interface according to the - * capabilities of the hardware. - */ - -static void __devinit init_hwif_piix(ide_hwif_t *hwif) -{ - if (!hwif->dma_base) - return; - - if (no_piix_dma) - hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0; -} - -static const struct ide_port_ops piix_port_ops = { - .set_pio_mode = piix_set_pio_mode, - .set_dma_mode = piix_set_dma_mode, - .cable_detect = piix_cable_detect, -}; - -static const struct ide_port_ops ich_port_ops = { - .set_pio_mode = piix_set_pio_mode, - .set_dma_mode = piix_set_dma_mode, - .clear_irq = ich_clear_irq, - .cable_detect = piix_cable_detect, -}; - -#ifndef CONFIG_IA64 - #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS -#else - #define IDE_HFLAGS_PIIX 0 -#endif - -#define DECLARE_PIIX_DEV(udma) \ - { \ - .name = DRV_NAME, \ - .init_hwif = init_hwif_piix, \ - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ - .port_ops = &piix_port_ops, \ - .host_flags = IDE_HFLAGS_PIIX, \ - .pio_mask = ATA_PIO4, \ - .swdma_mask = ATA_SWDMA2_ONLY, \ - .mwdma_mask = ATA_MWDMA12_ONLY, \ - .udma_mask = udma, \ - } - -#define DECLARE_ICH_DEV(udma) \ - { \ - .name = DRV_NAME, \ - .init_chipset = init_chipset_ich, \ - .init_hwif = init_hwif_piix, \ - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ - .port_ops = &ich_port_ops, \ - .host_flags = IDE_HFLAGS_PIIX, \ - .pio_mask = ATA_PIO4, \ - .swdma_mask = ATA_SWDMA2_ONLY, \ - .mwdma_mask = ATA_MWDMA12_ONLY, \ - .udma_mask = udma, \ - } - -static const struct ide_port_info piix_pci_info[] __devinitdata = { - /* 0: MPIIX */ - { /* - * MPIIX actually has only a single IDE channel mapped to - * the primary or secondary ports depending on the value - * of the bit 14 of the IDETIM register at offset 0x6c - */ - .name = DRV_NAME, - .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}}, - .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA | - IDE_HFLAGS_PIIX, - .pio_mask = ATA_PIO4, - /* This is a painful system best to let it self tune for now */ - }, - /* 1: PIIXa/PIIXb/PIIX3 */ - DECLARE_PIIX_DEV(0x00), /* no udma */ - /* 2: PIIX4 */ - DECLARE_PIIX_DEV(ATA_UDMA2), - /* 3: ICH0 */ - DECLARE_ICH_DEV(ATA_UDMA2), - /* 4: ICH */ - DECLARE_ICH_DEV(ATA_UDMA4), - /* 5: PIIX4 */ - DECLARE_PIIX_DEV(ATA_UDMA4), - /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */ - DECLARE_ICH_DEV(ATA_UDMA5), -}; - -/** - * piix_init_one - called when a PIIX is found - * @dev: the piix 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 __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL); -} - -/** - * piix_check_450nx - Check for problem 450NX setup - * - * Check for the present of 450NX errata #19 and errata #25. If - * they are found, disable use of DMA IDE - */ - -static void __devinit piix_check_450nx(void) -{ - struct pci_dev *pdev = NULL; - u16 cfg; - while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL) - { - /* Look for 450NX PXB. Check for problem configurations - A PCI quirk checks bit 6 already */ - pci_read_config_word(pdev, 0x41, &cfg); - /* Only on the original revision: IDE DMA can hang */ - if (pdev->revision == 0x00) - no_piix_dma = 1; - /* On all revisions below 5 PXB bus lock must be disabled for IDE */ - else if (cfg & (1<<14) && pdev->revision < 5) - no_piix_dma = 2; - } - if(no_piix_dma) - printk(KERN_WARNING DRV_NAME ": 450NX errata present, disabling IDE DMA.\n"); - if(no_piix_dma == 2) - printk(KERN_WARNING DRV_NAME ": A BIOS update may resolve this.\n"); -} - -static const struct pci_device_id piix_pci_tbl[] = { - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 1 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 0 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 1 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 2 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 3 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 2 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 4 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 5 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 2 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 6 }, -#ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 6 }, -#endif - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 6 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, piix_pci_tbl); - -static struct pci_driver piix_pci_driver = { - .name = "PIIX_IDE", - .id_table = piix_pci_tbl, - .probe = piix_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init piix_ide_init(void) -{ - piix_check_450nx(); - return ide_pci_register_driver(&piix_pci_driver); -} - -static void __exit piix_ide_exit(void) -{ - pci_unregister_driver(&piix_pci_driver); -} - -module_init(piix_ide_init); -module_exit(piix_ide_exit); - -MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz"); -MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c deleted file mode 100644 index 7daf013..0000000 --- a/drivers/ide/pci/rz1000.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 1995-1998 Linus Torvalds & author (see below) - */ - -/* - * Principal Author: mlord@pobox.com (Mark Lord) - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This file provides support for disabling the buggy read-ahead - * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards. - * - * Dunno if this fixes both ports, or only the primary port (?). - */ - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "rz1000" - -static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - u16 reg; - - if (!pci_read_config_word (dev, 0x40, ®) && - !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { - printk(KERN_INFO "%s: disabled chipset read-ahead " - "(buggy RZ1000/RZ1001)\n", hwif->name); - } else { - if (hwif->mate) - hwif->mate->serialized = hwif->serialized = 1; - hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS; - printk(KERN_INFO "%s: serialized, disabled unmasking " - "(buggy RZ1000/RZ1001)\n", hwif->name); - } -} - -static const struct ide_port_info rz1000_chipset __devinitdata = { - .name = DRV_NAME, - .init_hwif = init_hwif_rz1000, - .chipset = ide_rz1000, - .host_flags = IDE_HFLAG_NO_DMA, -}; - -static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &rz1000_chipset, NULL); -} - -static const struct pci_device_id rz1000_pci_tbl[] = { - { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), 0 }, - { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl); - -static struct pci_driver rz1000_pci_driver = { - .name = "RZ1000_IDE", - .id_table = rz1000_pci_tbl, - .probe = rz1000_init_one, - .remove = ide_pci_remove, -}; - -static int __init rz1000_ide_init(void) -{ - return ide_pci_register_driver(&rz1000_pci_driver); -} - -static void __exit rz1000_ide_exit(void) -{ - pci_unregister_driver(&rz1000_pci_driver); -} - -module_init(rz1000_ide_init); -module_exit(rz1000_ide_exit); - -MODULE_AUTHOR("Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c deleted file mode 100644 index f1a8758..0000000 --- a/drivers/ide/pci/sc1200.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (C) 2000-2002 Mark Lord - * 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: - * Available from National Semiconductor - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "sc1200" - -#define SC1200_REV_A 0x00 -#define SC1200_REV_B1 0x01 -#define SC1200_REV_B3 0x02 -#define SC1200_REV_C1 0x03 -#define SC1200_REV_D1 0x04 - -#define PCI_CLK_33 0x00 -#define PCI_CLK_48 0x01 -#define PCI_CLK_66 0x02 -#define PCI_CLK_33A 0x03 - -static unsigned short sc1200_get_pci_clock (void) -{ - unsigned char chip_id, silicon_revision; - unsigned int pci_clock; - /* - * Check the silicon revision, as not all versions of the chip - * have the register with the fast PCI bus timings. - */ - chip_id = inb (0x903c); - silicon_revision = inb (0x903d); - - // Read the fast pci clock frequency - if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) { - pci_clock = PCI_CLK_33; - } else { - // check clock generator configuration (cfcc) - // the clock is in bits 8 and 9 of this word - - pci_clock = inw (0x901e); - pci_clock >>= 8; - pci_clock &= 0x03; - if (pci_clock == PCI_CLK_33A) - pci_clock = PCI_CLK_33; - } - return pci_clock; -} - -/* - * 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 const unsigned int sc1200_pio_timings[4][5] = - {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz - {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz - {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz - {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}}; // format1, 66Mhz - -/* - * After chip reset, the PIO timings are set to 0x00009172, which is not valid. - */ -//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) - -static void sc1200_tunepio(ide_drive_t *drive, u8 pio) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *pdev = to_pci_dev(hwif->dev); - unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0; - - pci_read_config_dword(pdev, basereg + 4, &format); - format = (format >> 31) & 1; - if (format) - format += sc1200_get_pci_clock(); - pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3), - sc1200_pio_timings[format][pio]); -} - -/* - * The SC1200 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. - */ -static u8 sc1200_udma_filter(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - ide_drive_t *mate = ide_get_pair_dev(drive); - u16 *mateid = mate->id; - u8 mask = hwif->ultra_mask; - - if (mate == NULL) - goto out; - - 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_FIELD_VALID] & 2) && - (mateid[ATA_ID_MWDMA_MODES] & 7)) - mask = 0; - } -out: - return mask; -} - -static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned int reg, timings; - unsigned short pci_clock; - unsigned int basereg = hwif->channel ? 0x50 : 0x40; - - static const u32 udma_timing[3][3] = { - { 0x00921250, 0x00911140, 0x00911030 }, - { 0x00932470, 0x00922260, 0x00922140 }, - { 0x009436a1, 0x00933481, 0x00923261 }, - }; - - static const u32 mwdma_timing[3][3] = { - { 0x00077771, 0x00012121, 0x00002020 }, - { 0x000bbbb2, 0x00024241, 0x00013131 }, - { 0x000ffff3, 0x00035352, 0x00015151 }, - }; - - pci_clock = sc1200_get_pci_clock(); - - /* - * Note that each DMA mode has several timings associated with it. - * The correct timing depends on the fast PCI clock freq. - */ - - if (mode >= XFER_UDMA_0) - timings = udma_timing[pci_clock][mode - XFER_UDMA_0]; - else - timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0]; - - if ((drive->dn & 1) == 0) { - pci_read_config_dword(dev, basereg + 4, ®); - timings |= reg & 0x80000000; /* preserve PIO format bit */ - pci_write_config_dword(dev, basereg + 4, timings); - } else - pci_write_config_dword(dev, basereg + 12, timings); -} - -/* Replacement for the standard ide_dma_end action in - * dma_proc. - * - * returns 1 on error, 0 otherwise - */ -static int sc1200_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte dma_stat; - - dma_stat = inb(dma_base+2); /* get DMA status */ - - if (!(dma_stat & 4)) - printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n", - dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2)); - - outb(dma_stat|0x1b, dma_base+2); /* clear the INTR & ERROR bits */ - outb(inb(dma_base)&~1, dma_base); /* !! DO THIS HERE !! stop DMA */ - - drive->waiting_for_dma = 0; - ide_destroy_dmatable(drive); /* purge DMA mappings */ - - return (dma_stat & 7) != 4; /* verify good DMA status */ -} - -/* - * sc1200_set_pio_mode() handles setting of PIO modes - * for both the chipset and drive. - * - * All existing BIOSs for this chipset guarantee that all drives - * will have valid default PIO timings set up before we get here. - */ - -static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - int mode = -1; - - /* - * bad abuse of ->set_pio_mode interface - */ - switch (pio) { - case 200: mode = XFER_UDMA_0; break; - case 201: mode = XFER_UDMA_1; break; - case 202: mode = XFER_UDMA_2; break; - case 100: mode = XFER_MW_DMA_0; break; - case 101: mode = XFER_MW_DMA_1; break; - case 102: mode = XFER_MW_DMA_2; break; - } - if (mode != -1) { - printk("SC1200: %s: changing (U)DMA mode\n", drive->name); - ide_dma_off_quietly(drive); - if (ide_set_dma_mode(drive, mode) == 0 && - (drive->dev_flags & IDE_DFLAG_USING_DMA)) - hwif->dma_ops->dma_host_set(drive, 1); - return; - } - - sc1200_tunepio(drive, pio); -} - -#ifdef CONFIG_PM -struct sc1200_saved_state { - u32 regs[8]; -}; - -static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) -{ - printk("SC1200: suspend(%u)\n", state.event); - - /* - * we only save state when going from full power to less - */ - if (state.event == PM_EVENT_ON) { - struct ide_host *host = pci_get_drvdata(dev); - struct sc1200_saved_state *ss = host->host_priv; - unsigned int r; - - /* - * save timing registers - * (this may be unnecessary if BIOS also does it) - */ - for (r = 0; r < 8; r++) - pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]); - } - - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); - return 0; -} - -static int sc1200_resume (struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct sc1200_saved_state *ss = host->host_priv; - unsigned int r; - int i; - - i = pci_enable_device(dev); - if (i) - return i; - - /* - * restore timing registers - * (this may be unnecessary if BIOS also does it) - */ - for (r = 0; r < 8; r++) - pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]); - - return 0; -} -#endif - -static const struct ide_port_ops sc1200_port_ops = { - .set_pio_mode = sc1200_set_pio_mode, - .set_dma_mode = sc1200_set_dma_mode, - .udma_filter = sc1200_udma_filter, -}; - -static const struct ide_dma_ops sc1200_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = sc1200_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_port_info sc1200_chipset __devinitdata = { - .name = DRV_NAME, - .port_ops = &sc1200_port_ops, - .dma_ops = &sc1200_dma_ops, - .host_flags = IDE_HFLAG_SERIALIZE | - IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_ABUSE_DMA_MODES, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA2, -}; - -static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct sc1200_saved_state *ss = NULL; - int rc; - -#ifdef CONFIG_PM - ss = kmalloc(sizeof(*ss), GFP_KERNEL); - if (ss == NULL) - return -ENOMEM; -#endif - rc = ide_pci_init_one(dev, &sc1200_chipset, ss); - if (rc) - kfree(ss); - - return rc; -} - -static const struct pci_device_id sc1200_pci_tbl[] = { - { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0}, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl); - -static struct pci_driver sc1200_pci_driver = { - .name = "SC1200_IDE", - .id_table = sc1200_pci_tbl, - .probe = sc1200_init_one, - .remove = ide_pci_remove, -#ifdef CONFIG_PM - .suspend = sc1200_suspend, - .resume = sc1200_resume, -#endif -}; - -static int __init sc1200_ide_init(void) -{ - return ide_pci_register_driver(&sc1200_pci_driver); -} - -static void __exit sc1200_ide_exit(void) -{ - pci_unregister_driver(&sc1200_pci_driver); -} - -module_init(sc1200_ide_init); -module_exit(sc1200_ide_exit); - -MODULE_AUTHOR("Mark Lord"); -MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c deleted file mode 100644 index 49f163a..0000000 --- a/drivers/ide/pci/scc_pata.c +++ /dev/null @@ -1,966 +0,0 @@ -/* - * Support for IDE interfaces on Celleb platform - * - * (C) Copyright 2006 TOSHIBA CORPORATION - * - * This code is based on drivers/ide/pci/siimage.c: - * Copyright (C) 2001-2002 Andre Hedrick - * Copyright (C) 2003 Red Hat - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include - -#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4 - -#define SCC_PATA_NAME "scc IDE" - -#define TDVHSEL_MASTER 0x00000001 -#define TDVHSEL_SLAVE 0x00000004 - -#define MODE_JCUSFEN 0x00000080 - -#define CCKCTRL_ATARESET 0x00040000 -#define CCKCTRL_BUFCNT 0x00020000 -#define CCKCTRL_CRST 0x00010000 -#define CCKCTRL_OCLKEN 0x00000100 -#define CCKCTRL_ATACLKOEN 0x00000002 -#define CCKCTRL_LCLKEN 0x00000001 - -#define QCHCD_IOS_SS 0x00000001 - -#define QCHSD_STPDIAG 0x00020000 - -#define INTMASK_MSK 0xD1000012 -#define INTSTS_SERROR 0x80000000 -#define INTSTS_PRERR 0x40000000 -#define INTSTS_RERR 0x10000000 -#define INTSTS_ICERR 0x01000000 -#define INTSTS_BMSINT 0x00000010 -#define INTSTS_BMHE 0x00000008 -#define INTSTS_IOIRQS 0x00000004 -#define INTSTS_INTRQ 0x00000002 -#define INTSTS_ACTEINT 0x00000001 - -#define ECMODE_VALUE 0x01 - -static struct scc_ports { - unsigned long ctl, dma; - struct ide_host *host; /* for removing port from system */ -} scc_ports[MAX_HWIFS]; - -/* PIO transfer mode table */ -/* JCHST */ -static unsigned long JCHSTtbl[2][7] = { - {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00}, /* 100MHz */ - {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00} /* 133MHz */ -}; - -/* JCHHT */ -static unsigned long JCHHTtbl[2][7] = { - {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00}, /* 100MHz */ - {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00} /* 133MHz */ -}; - -/* JCHCT */ -static unsigned long JCHCTtbl[2][7] = { - {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00}, /* 100MHz */ - {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00} /* 133MHz */ -}; - - -/* DMA transfer mode table */ -/* JCHDCTM/JCHDCTS */ -static unsigned long JCHDCTxtbl[2][7] = { - {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00}, /* 100MHz */ - {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00} /* 133MHz */ -}; - -/* JCSTWTM/JCSTWTS */ -static unsigned long JCSTWTxtbl[2][7] = { - {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00}, /* 100MHz */ - {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02} /* 133MHz */ -}; - -/* JCTSS */ -static unsigned long JCTSStbl[2][7] = { - {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00}, /* 100MHz */ - {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05} /* 133MHz */ -}; - -/* JCENVT */ -static unsigned long JCENVTtbl[2][7] = { - {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}, /* 100MHz */ - {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} /* 133MHz */ -}; - -/* JCACTSELS/JCACTSELM */ -static unsigned long JCACTSELtbl[2][7] = { - {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00}, /* 100MHz */ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} /* 133MHz */ -}; - - -static u8 scc_ide_inb(unsigned long port) -{ - u32 data = in_be32((void*)port); - return (u8)data; -} - -static void scc_exec_command(ide_hwif_t *hwif, u8 cmd) -{ - out_be32((void *)hwif->io_ports.command_addr, cmd); - eieio(); - in_be32((void *)(hwif->dma_base + 0x01c)); - eieio(); -} - -static u8 scc_read_status(ide_hwif_t *hwif) -{ - return (u8)in_be32((void *)hwif->io_ports.status_addr); -} - -static u8 scc_read_altstatus(ide_hwif_t *hwif) -{ - return (u8)in_be32((void *)hwif->io_ports.ctl_addr); -} - -static u8 scc_read_sff_dma_status(ide_hwif_t *hwif) -{ - return (u8)in_be32((void *)(hwif->dma_base + 4)); -} - -static void scc_set_irq(ide_hwif_t *hwif, int on) -{ - u8 ctl = ATA_DEVCTL_OBS; - - if (on == 4) { /* hack for SRST */ - ctl |= 4; - on &= ~4; - } - - ctl |= on ? 0 : 2; - - out_be32((void *)hwif->io_ports.ctl_addr, ctl); - eieio(); - in_be32((void *)(hwif->dma_base + 0x01c)); - eieio(); -} - -static void scc_ide_insw(unsigned long port, void *addr, u32 count) -{ - u16 *ptr = (u16 *)addr; - while (count--) { - *ptr++ = le16_to_cpu(in_be32((void*)port)); - } -} - -static void scc_ide_insl(unsigned long port, void *addr, u32 count) -{ - u16 *ptr = (u16 *)addr; - while (count--) { - *ptr++ = le16_to_cpu(in_be32((void*)port)); - *ptr++ = le16_to_cpu(in_be32((void*)port)); - } -} - -static void scc_ide_outb(u8 addr, unsigned long port) -{ - out_be32((void*)port, addr); -} - -static void -scc_ide_outsw(unsigned long port, void *addr, u32 count) -{ - u16 *ptr = (u16 *)addr; - while (count--) { - out_be32((void*)port, cpu_to_le16(*ptr++)); - } -} - -static void -scc_ide_outsl(unsigned long port, void *addr, u32 count) -{ - u16 *ptr = (u16 *)addr; - while (count--) { - out_be32((void*)port, cpu_to_le16(*ptr++)); - out_be32((void*)port, cpu_to_le16(*ptr++)); - } -} - -/** - * scc_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * Load the timing settings for this device mode into the - * controller. - */ - -static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct scc_ports *ports = ide_get_hwifdata(hwif); - unsigned long ctl_base = ports->ctl; - unsigned long cckctrl_port = ctl_base + 0xff0; - unsigned long piosht_port = ctl_base + 0x000; - unsigned long pioct_port = ctl_base + 0x004; - unsigned long reg; - int offset; - - reg = in_be32((void __iomem *)cckctrl_port); - if (reg & CCKCTRL_ATACLKOEN) { - offset = 1; /* 133MHz */ - } else { - offset = 0; /* 100MHz */ - } - reg = JCHSTtbl[offset][pio] << 16 | JCHHTtbl[offset][pio]; - out_be32((void __iomem *)piosht_port, reg); - reg = JCHCTtbl[offset][pio]; - out_be32((void __iomem *)pioct_port, reg); -} - -/** - * scc_set_dma_mode - set host controller for DMA mode - * @drive: drive - * @speed: DMA mode - * - * Load the timing settings for this device mode into the - * controller. - */ - -static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct scc_ports *ports = ide_get_hwifdata(hwif); - unsigned long ctl_base = ports->ctl; - unsigned long cckctrl_port = ctl_base + 0xff0; - unsigned long mdmact_port = ctl_base + 0x008; - unsigned long mcrcst_port = ctl_base + 0x00c; - unsigned long sdmact_port = ctl_base + 0x010; - unsigned long scrcst_port = ctl_base + 0x014; - unsigned long udenvt_port = ctl_base + 0x018; - unsigned long tdvhsel_port = ctl_base + 0x020; - int is_slave = (&hwif->drives[1] == drive); - int offset, idx; - unsigned long reg; - unsigned long jcactsel; - - reg = in_be32((void __iomem *)cckctrl_port); - if (reg & CCKCTRL_ATACLKOEN) { - offset = 1; /* 133MHz */ - } else { - offset = 0; /* 100MHz */ - } - - idx = speed - XFER_UDMA_0; - - jcactsel = JCACTSELtbl[offset][idx]; - if (is_slave) { - out_be32((void __iomem *)sdmact_port, JCHDCTxtbl[offset][idx]); - out_be32((void __iomem *)scrcst_port, JCSTWTxtbl[offset][idx]); - jcactsel = jcactsel << 2; - out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_SLAVE) | jcactsel); - } else { - out_be32((void __iomem *)mdmact_port, JCHDCTxtbl[offset][idx]); - out_be32((void __iomem *)mcrcst_port, JCSTWTxtbl[offset][idx]); - out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_MASTER) | jcactsel); - } - reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx]; - out_be32((void __iomem *)udenvt_port, reg); -} - -static void scc_dma_host_set(ide_drive_t *drive, int on) -{ - ide_hwif_t *hwif = drive->hwif; - u8 unit = drive->dn & 1; - u8 dma_stat = scc_ide_inb(hwif->dma_base + 4); - - if (on) - dma_stat |= (1 << (5 + unit)); - else - dma_stat &= ~(1 << (5 + unit)); - - scc_ide_outb(dma_stat, hwif->dma_base + 4); -} - -/** - * scc_ide_dma_setup - begin a DMA phase - * @drive: target device - * - * Build an IDE DMA PRD (IDE speak for scatter gather table) - * and then set up the DMA transfer registers. - * - * Returns 0 on success. If a PIO fallback is required then 1 - * is returned. - */ - -static int scc_dma_setup(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct request *rq = HWGROUP(drive)->rq; - unsigned int reading; - u8 dma_stat; - - if (rq_data_dir(rq)) - reading = 0; - else - reading = 1 << 3; - - /* fall back to pio! */ - if (!ide_build_dmatable(drive, rq)) { - ide_map_sg(drive, rq); - return 1; - } - - /* PRD table */ - out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma); - - /* specify r/w */ - out_be32((void __iomem *)hwif->dma_base, reading); - - /* read DMA status for INTR & ERROR flags */ - dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4)); - - /* clear INTR & ERROR flags */ - out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6); - drive->waiting_for_dma = 1; - return 0; -} - -static void scc_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 dma_cmd = scc_ide_inb(hwif->dma_base); - - /* start DMA */ - scc_ide_outb(dma_cmd | 1, hwif->dma_base); - wmb(); -} - -static int __scc_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 dma_stat, dma_cmd; - - drive->waiting_for_dma = 0; - /* get DMA command mode */ - dma_cmd = scc_ide_inb(hwif->dma_base); - /* stop DMA */ - scc_ide_outb(dma_cmd & ~1, hwif->dma_base); - /* get DMA status */ - dma_stat = scc_ide_inb(hwif->dma_base + 4); - /* clear the INTR & ERROR bits */ - scc_ide_outb(dma_stat | 6, hwif->dma_base + 4); - /* purge DMA mappings */ - ide_destroy_dmatable(drive); - /* verify good DMA status */ - wmb(); - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; -} - -/** - * scc_dma_end - Stop DMA - * @drive: IDE drive - * - * Check and clear INT Status register. - * Then call __scc_dma_end(). - */ - -static int scc_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - void __iomem *dma_base = (void __iomem *)hwif->dma_base; - unsigned long intsts_port = hwif->dma_base + 0x014; - u32 reg; - int dma_stat, data_loss = 0; - static int retry = 0; - - /* errata A308 workaround: Step5 (check data loss) */ - /* We don't check non ide_disk because it is limited to UDMA4 */ - if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr) - & ATA_ERR) && - drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) { - reg = in_be32((void __iomem *)intsts_port); - if (!(reg & INTSTS_ACTEINT)) { - printk(KERN_WARNING "%s: operation failed (transfer data loss)\n", - drive->name); - data_loss = 1; - if (retry++) { - struct request *rq = HWGROUP(drive)->rq; - int unit; - /* ERROR_RESET and drive->crc_count are needed - * to reduce DMA transfer mode in retry process. - */ - if (rq) - rq->errors |= ERROR_RESET; - for (unit = 0; unit < MAX_DRIVES; unit++) { - ide_drive_t *drive = &hwif->drives[unit]; - drive->crc_count++; - } - } - } - } - - while (1) { - reg = in_be32((void __iomem *)intsts_port); - - if (reg & INTSTS_SERROR) { - printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME); - out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT); - - out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS); - continue; - } - - if (reg & INTSTS_PRERR) { - u32 maea0, maec0; - unsigned long ctl_base = hwif->config_data; - - maea0 = in_be32((void __iomem *)(ctl_base + 0xF50)); - maec0 = in_be32((void __iomem *)(ctl_base + 0xF54)); - - printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", SCC_PATA_NAME, maea0, maec0); - - out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT); - - out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS); - continue; - } - - if (reg & INTSTS_RERR) { - printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME); - out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT); - - out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS); - continue; - } - - if (reg & INTSTS_ICERR) { - out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS); - - printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME); - out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT); - continue; - } - - if (reg & INTSTS_BMSINT) { - printk(KERN_WARNING "%s: Internal Bus Error\n", SCC_PATA_NAME); - out_be32((void __iomem *)intsts_port, INTSTS_BMSINT); - - ide_do_reset(drive); - continue; - } - - if (reg & INTSTS_BMHE) { - out_be32((void __iomem *)intsts_port, INTSTS_BMHE); - continue; - } - - if (reg & INTSTS_ACTEINT) { - out_be32((void __iomem *)intsts_port, INTSTS_ACTEINT); - continue; - } - - if (reg & INTSTS_IOIRQS) { - out_be32((void __iomem *)intsts_port, INTSTS_IOIRQS); - continue; - } - break; - } - - dma_stat = __scc_dma_end(drive); - if (data_loss) - dma_stat |= 2; /* emulate DMA error (to retry command) */ - return dma_stat; -} - -/* returns 1 if dma irq issued, 0 otherwise */ -static int scc_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014); - - /* SCC errata A252,A308 workaround: Step4 */ - if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr) - & ATA_ERR) && - (int_stat & INTSTS_INTRQ)) - return 1; - - /* SCC errata A308 workaround: Step5 (polling IOIRQS) */ - if (int_stat & INTSTS_IOIRQS) - return 1; - - return 0; -} - -static u8 scc_udma_filter(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 mask = hwif->ultra_mask; - - /* errata A308 workaround: limit non ide_disk drive to UDMA4 */ - if ((drive->media != ide_disk) && (mask & 0xE0)) { - printk(KERN_INFO "%s: limit %s to UDMA4\n", - SCC_PATA_NAME, drive->name); - mask = ATA_UDMA4; - } - - return mask; -} - -/** - * setup_mmio_scc - map CTRL/BMID region - * @dev: PCI device we are configuring - * @name: device name - * - */ - -static int setup_mmio_scc (struct pci_dev *dev, const char *name) -{ - unsigned long ctl_base = pci_resource_start(dev, 0); - unsigned long dma_base = pci_resource_start(dev, 1); - unsigned long ctl_size = pci_resource_len(dev, 0); - unsigned long dma_size = pci_resource_len(dev, 1); - void __iomem *ctl_addr; - void __iomem *dma_addr; - int i, ret; - - for (i = 0; i < MAX_HWIFS; i++) { - if (scc_ports[i].ctl == 0) - break; - } - if (i >= MAX_HWIFS) - return -ENOMEM; - - ret = pci_request_selected_regions(dev, (1 << 2) - 1, name); - if (ret < 0) { - printk(KERN_ERR "%s: can't reserve resources\n", name); - return ret; - } - - if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL) - goto fail_0; - - if ((dma_addr = ioremap(dma_base, dma_size)) == NULL) - goto fail_1; - - pci_set_master(dev); - scc_ports[i].ctl = (unsigned long)ctl_addr; - scc_ports[i].dma = (unsigned long)dma_addr; - pci_set_drvdata(dev, (void *) &scc_ports[i]); - - return 1; - - fail_1: - iounmap(ctl_addr); - fail_0: - return -ENOMEM; -} - -static int scc_ide_setup_pci_device(struct pci_dev *dev, - const struct ide_port_info *d) -{ - struct scc_ports *ports = pci_get_drvdata(dev); - struct ide_host *host; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - int i, rc; - - memset(&hw, 0, sizeof(hw)); - for (i = 0; i <= 8; i++) - hw.io_ports_array[i] = ports->dma + 0x20 + i * 4; - hw.irq = dev->irq; - hw.dev = &dev->dev; - hw.chipset = ide_pci; - - rc = ide_host_add(d, hws, &host); - if (rc) - return rc; - - ports->host = host; - - return 0; -} - -/** - * init_setup_scc - set up an SCC PATA Controller - * @dev: PCI device - * @d: IDE port info - * - * Perform the initial set up for this device. - */ - -static int __devinit init_setup_scc(struct pci_dev *dev, - const struct ide_port_info *d) -{ - unsigned long ctl_base; - unsigned long dma_base; - unsigned long cckctrl_port; - unsigned long intmask_port; - unsigned long mode_port; - unsigned long ecmode_port; - u32 reg = 0; - struct scc_ports *ports; - int rc; - - rc = pci_enable_device(dev); - if (rc) - goto end; - - rc = setup_mmio_scc(dev, d->name); - if (rc < 0) - goto end; - - ports = pci_get_drvdata(dev); - ctl_base = ports->ctl; - dma_base = ports->dma; - cckctrl_port = ctl_base + 0xff0; - intmask_port = dma_base + 0x010; - mode_port = ctl_base + 0x024; - ecmode_port = ctl_base + 0xf00; - - /* controller initialization */ - reg = 0; - out_be32((void*)cckctrl_port, reg); - reg |= CCKCTRL_ATACLKOEN; - out_be32((void*)cckctrl_port, reg); - reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN; - out_be32((void*)cckctrl_port, reg); - reg |= CCKCTRL_CRST; - out_be32((void*)cckctrl_port, reg); - - for (;;) { - reg = in_be32((void*)cckctrl_port); - if (reg & CCKCTRL_CRST) - break; - udelay(5000); - } - - reg |= CCKCTRL_ATARESET; - out_be32((void*)cckctrl_port, reg); - - out_be32((void*)ecmode_port, ECMODE_VALUE); - out_be32((void*)mode_port, MODE_JCUSFEN); - out_be32((void*)intmask_port, INTMASK_MSK); - - rc = scc_ide_setup_pci_device(dev, d); - - end: - return rc; -} - -static void scc_tf_load(ide_drive_t *drive, ide_task_t *task) -{ - struct ide_io_ports *io_ports = &drive->hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; - - if (task->tf_flags & IDE_TFLAG_FLAGGED) - HIHI = 0xFF; - - if (task->tf_flags & IDE_TFLAG_OUT_DATA) - out_be32((void *)io_ports->data_addr, - (tf->hob_data << 8) | tf->data); - - if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) - scc_ide_outb(tf->hob_feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) - scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) - scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) - scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) - scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) - scc_ide_outb(tf->feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_NSECT) - scc_ide_outb(tf->nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAL) - scc_ide_outb(tf->lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAM) - scc_ide_outb(tf->lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAH) - scc_ide_outb(tf->lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - scc_ide_outb((tf->device & HIHI) | drive->select, - io_ports->device_addr); -} - -static void scc_tf_read(ide_drive_t *drive, ide_task_t *task) -{ - struct ide_io_ports *io_ports = &drive->hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - - if (task->tf_flags & IDE_TFLAG_IN_DATA) { - u16 data = (u16)in_be32((void *)io_ports->data_addr); - - tf->data = data & 0xff; - tf->hob_data = (data >> 8) & 0xff; - } - - /* be sure we're looking at the low order bits */ - scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_FEATURE) - tf->feature = scc_ide_inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_NSECT) - tf->nsect = scc_ide_inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAL) - tf->lbal = scc_ide_inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAM) - tf->lbam = scc_ide_inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAH) - tf->lbah = scc_ide_inb(io_ports->lbah_addr); - if (task->tf_flags & IDE_TFLAG_IN_DEVICE) - tf->device = scc_ide_inb(io_ports->device_addr); - - if (task->tf_flags & IDE_TFLAG_LBA48) { - scc_ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) - tf->hob_feature = scc_ide_inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) - tf->hob_nsect = scc_ide_inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) - tf->hob_lbal = scc_ide_inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) - tf->hob_lbam = scc_ide_inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) - tf->hob_lbah = scc_ide_inb(io_ports->lbah_addr); - } -} - -static void scc_input_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - unsigned long data_addr = drive->hwif->io_ports.data_addr; - - len++; - - if (drive->io_32bit) { - scc_ide_insl(data_addr, buf, len / 4); - - if ((len & 3) >= 2) - scc_ide_insw(data_addr, (u8 *)buf + (len & ~3), 1); - } else - scc_ide_insw(data_addr, buf, len / 2); -} - -static void scc_output_data(ide_drive_t *drive, struct request *rq, - void *buf, unsigned int len) -{ - unsigned long data_addr = drive->hwif->io_ports.data_addr; - - len++; - - if (drive->io_32bit) { - scc_ide_outsl(data_addr, buf, len / 4); - - if ((len & 3) >= 2) - scc_ide_outsw(data_addr, (u8 *)buf + (len & ~3), 1); - } else - scc_ide_outsw(data_addr, buf, len / 2); -} - -/** - * init_mmio_iops_scc - set up the iops for MMIO - * @hwif: interface to set up - * - */ - -static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct scc_ports *ports = pci_get_drvdata(dev); - unsigned long dma_base = ports->dma; - - ide_set_hwifdata(hwif, ports); - - hwif->dma_base = dma_base; - hwif->config_data = ports->ctl; -} - -/** - * init_iops_scc - set up iops - * @hwif: interface to set up - * - * Do the basic setup for the SCC hardware interface - * and then do the MMIO setup. - */ - -static void __devinit init_iops_scc(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - hwif->hwif_data = NULL; - if (pci_get_drvdata(dev) == NULL) - return; - init_mmio_iops_scc(hwif); -} - -static int __devinit scc_init_dma(ide_hwif_t *hwif, - const struct ide_port_info *d) -{ - return ide_allocate_dma_engine(hwif); -} - -static u8 scc_cable_detect(ide_hwif_t *hwif) -{ - return ATA_CBL_PATA80; -} - -/** - * init_hwif_scc - set up hwif - * @hwif: interface to set up - * - * We do the basic set up of the interface structure. The SCC - * requires several custom handlers so we override the default - * ide DMA handlers appropriately. - */ - -static void __devinit init_hwif_scc(ide_hwif_t *hwif) -{ - /* PTERADD */ - out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma); - - if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN) - hwif->ultra_mask = ATA_UDMA6; /* 133MHz */ - else - hwif->ultra_mask = ATA_UDMA5; /* 100MHz */ -} - -static const struct ide_tp_ops scc_tp_ops = { - .exec_command = scc_exec_command, - .read_status = scc_read_status, - .read_altstatus = scc_read_altstatus, - .read_sff_dma_status = scc_read_sff_dma_status, - - .set_irq = scc_set_irq, - - .tf_load = scc_tf_load, - .tf_read = scc_tf_read, - - .input_data = scc_input_data, - .output_data = scc_output_data, -}; - -static const struct ide_port_ops scc_port_ops = { - .set_pio_mode = scc_set_pio_mode, - .set_dma_mode = scc_set_dma_mode, - .udma_filter = scc_udma_filter, - .cable_detect = scc_cable_detect, -}; - -static const struct ide_dma_ops scc_dma_ops = { - .dma_host_set = scc_dma_host_set, - .dma_setup = scc_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = scc_dma_start, - .dma_end = scc_dma_end, - .dma_test_irq = scc_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -#define DECLARE_SCC_DEV(name_str) \ - { \ - .name = name_str, \ - .init_iops = init_iops_scc, \ - .init_dma = scc_init_dma, \ - .init_hwif = init_hwif_scc, \ - .tp_ops = &scc_tp_ops, \ - .port_ops = &scc_port_ops, \ - .dma_ops = &scc_dma_ops, \ - .host_flags = IDE_HFLAG_SINGLE, \ - .pio_mask = ATA_PIO4, \ - } - -static const struct ide_port_info scc_chipsets[] __devinitdata = { - /* 0 */ DECLARE_SCC_DEV("sccIDE"), -}; - -/** - * scc_init_one - pci layer discovery entry - * @dev: PCI device - * @id: ident table entry - * - * Called by the PCI code when it finds an SCC PATA controller. - * We then use the IDE PCI generic helper to do most of the work. - */ - -static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return init_setup_scc(dev, &scc_chipsets[id->driver_data]); -} - -/** - * scc_remove - pci layer remove entry - * @dev: PCI device - * - * Called by the PCI code when it removes an SCC PATA controller. - */ - -static void __devexit scc_remove(struct pci_dev *dev) -{ - struct scc_ports *ports = pci_get_drvdata(dev); - struct ide_host *host = ports->host; - - ide_host_remove(host); - - iounmap((void*)ports->dma); - iounmap((void*)ports->ctl); - pci_release_selected_regions(dev, (1 << 2) - 1); - memset(ports, 0, sizeof(*ports)); -} - -static const struct pci_device_id scc_pci_tbl[] = { - { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, scc_pci_tbl); - -static struct pci_driver scc_pci_driver = { - .name = "SCC IDE", - .id_table = scc_pci_tbl, - .probe = scc_init_one, - .remove = __devexit_p(scc_remove), -}; - -static int scc_ide_init(void) -{ - return ide_pci_register_driver(&scc_pci_driver); -} - -module_init(scc_ide_init); -/* -- No exit code? -static void scc_ide_exit(void) -{ - ide_pci_unregister_driver(&scc_pci_driver); -} -module_exit(scc_ide_exit); - */ - - -MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c deleted file mode 100644 index 437bc91..0000000 --- a/drivers/ide/pci/serverworks.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (C) 1998-2000 Michel Aubry - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz - * Copyright (C) 1998-2000 Andre Hedrick - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * Portions copyright (c) 2001 Sun Microsystems - * - * - * RCC/ServerWorks IDE driver for Linux - * - * OSB4: `Open South Bridge' IDE Interface (fn 1) - * supports UDMA mode 2 (33 MB/s) - * - * CSB5: `Champion South Bridge' IDE Interface (fn 1) - * all revisions support UDMA mode 4 (66 MB/s) - * revision A2.0 and up support UDMA mode 5 (100 MB/s) - * - * *** The CSB5 does not provide ANY register *** - * *** to detect 80-conductor cable presence. *** - * - * CSB6: `Champion South Bridge' IDE Interface (optional: third channel) - * - * HT1000: AKA BCM5785 - Hypertransport Southbridge for Opteron systems. IDE - * controller same as the CSB6. Single channel ATA100 only. - * - * Documentation: - * Available under NDA only. Errata info very hard to get. - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "serverworks" - -#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ -#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ - -/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 - * can overrun their FIFOs when used with the CSB5 */ -static const char *svwks_bad_ata100[] = { - "ST320011A", - "ST340016A", - "ST360021A", - "ST380021A", - NULL -}; - -static struct pci_dev *isa_dev; - -static int check_in_drive_lists (ide_drive_t *drive, const char **list) -{ - char *m = (char *)&drive->id[ATA_ID_PROD]; - - while (*list) - if (!strcmp(*list++, m)) - return 1; - return 0; -} - -static u8 svwks_udma_filter(ide_drive_t *drive) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u8 mask = 0; - - if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) - return 0x1f; - if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { - u32 reg = 0; - if (isa_dev) - pci_read_config_dword(isa_dev, 0x64, ®); - - /* - * Don't enable UDMA on disk devices for the moment - */ - if(drive->media == ide_disk) - return 0; - /* Check the OSB4 DMA33 enable bit */ - return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0; - } else if (dev->revision < SVWKS_CSB5_REVISION_NEW) { - return 0x07; - } else if (dev->revision >= SVWKS_CSB5_REVISION_NEW) { - u8 btr = 0, mode; - pci_read_config_byte(dev, 0x5A, &btr); - mode = btr & 0x3; - - /* If someone decides to do UDMA133 on CSB5 the same - issue will bite so be inclusive */ - if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100)) - mode = 2; - - switch(mode) { - case 3: mask = 0x3f; break; - case 2: mask = 0x1f; break; - case 1: mask = 0x07; break; - default: mask = 0x00; break; - } - } - if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || - (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && - (!(PCI_FUNC(dev->devfn) & 1))) - mask = 0x1f; - - return mask; -} - -static u8 svwks_csb_check (struct pci_dev *dev) -{ - switch (dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: - case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: - case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: - return 1; - default: - break; - } - return 0; -} - -static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; - static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 }; - - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - - pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]); - - if (svwks_csb_check(dev)) { - u16 csb_pio = 0; - - pci_read_config_word(dev, 0x4a, &csb_pio); - - csb_pio &= ~(0x0f << (4 * drive->dn)); - csb_pio |= (pio << (4 * drive->dn)); - - pci_write_config_word(dev, 0x4a, csb_pio); - } -} - -static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - static const u8 udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; - static const u8 dma_modes[] = { 0x77, 0x21, 0x20 }; - static const u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 }; - - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 unit = drive->dn & 1; - - u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0; - - pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); - pci_read_config_byte(dev, 0x54, &ultra_enable); - - ultra_timing &= ~(0x0F << (4*unit)); - ultra_enable &= ~(0x01 << drive->dn); - - if (speed >= XFER_UDMA_0) { - dma_timing |= dma_modes[2]; - ultra_timing |= (udma_modes[speed - XFER_UDMA_0] << (4 * unit)); - ultra_enable |= (0x01 << drive->dn); - } else if (speed >= XFER_MW_DMA_0) - dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; - - pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing); - pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing); - pci_write_config_byte(dev, 0x54, ultra_enable); -} - -static unsigned int init_chipset_svwks(struct pci_dev *dev) -{ - unsigned int reg; - u8 btr; - - /* force Master Latency Timer value to 64 PCICLKs */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); - - /* OSB4 : South Bridge and IDE */ - if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { - isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); - if (isa_dev) { - pci_read_config_dword(isa_dev, 0x64, ®); - reg &= ~0x00002000; /* disable 600ns interrupt mask */ - if(!(reg & 0x00004000)) - printk(KERN_DEBUG DRV_NAME " %s: UDMA not BIOS " - "enabled.\n", pci_name(dev)); - reg |= 0x00004000; /* enable UDMA/33 support */ - pci_write_config_dword(isa_dev, 0x64, reg); - } - } - - /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ - else if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || - (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || - (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) { - - /* Third Channel Test */ - if (!(PCI_FUNC(dev->devfn) & 1)) { - struct pci_dev * findev = NULL; - u32 reg4c = 0; - findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); - if (findev) { - pci_read_config_dword(findev, 0x4C, ®4c); - reg4c &= ~0x000007FF; - reg4c |= 0x00000040; - reg4c |= 0x00000020; - pci_write_config_dword(findev, 0x4C, reg4c); - pci_dev_put(findev); - } - outb_p(0x06, 0x0c00); - dev->irq = inb_p(0x0c01); - } else { - struct pci_dev * findev = NULL; - u8 reg41 = 0; - - findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL); - if (findev) { - pci_read_config_byte(findev, 0x41, ®41); - reg41 &= ~0x40; - pci_write_config_byte(findev, 0x41, reg41); - pci_dev_put(findev); - } - /* - * This is a device pin issue on CSB6. - * Since there will be a future raid mode, - * early versions of the chipset require the - * interrupt pin to be set, and it is a compatibility - * mode issue. - */ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) - dev->irq = 0; - } -// pci_read_config_dword(dev, 0x40, &pioreg) -// pci_write_config_dword(dev, 0x40, 0x99999999); -// pci_read_config_dword(dev, 0x44, &dmareg); -// pci_write_config_dword(dev, 0x44, 0xFFFFFFFF); - /* setup the UDMA Control register - * - * 1. clear bit 6 to enable DMA - * 2. enable DMA modes with bits 0-1 - * 00 : legacy - * 01 : udma2 - * 10 : udma2/udma4 - * 11 : udma2/udma4/udma5 - */ - pci_read_config_byte(dev, 0x5A, &btr); - btr &= ~0x40; - if (!(PCI_FUNC(dev->devfn) & 1)) - btr |= 0x2; - else - btr |= (dev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; - pci_write_config_byte(dev, 0x5A, btr); - } - /* Setup HT1000 SouthBridge Controller - Single Channel Only */ - else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) { - pci_read_config_byte(dev, 0x5A, &btr); - btr &= ~0x40; - btr |= 0x3; - pci_write_config_byte(dev, 0x5A, btr); - } - - return dev->irq; -} - -static u8 ata66_svwks_svwks(ide_hwif_t *hwif) -{ - return ATA_CBL_PATA80; -} - -/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits - * of the subsystem device ID indicate presence of an 80-pin cable. - * Bit 15 clear = secondary IDE channel does not have 80-pin cable. - * Bit 15 set = secondary IDE channel has 80-pin cable. - * Bit 14 clear = primary IDE channel does not have 80-pin cable. - * Bit 14 set = primary IDE channel has 80-pin cable. - */ -static u8 ata66_svwks_dell(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && - dev->vendor == PCI_VENDOR_ID_SERVERWORKS && - (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE || - dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) - return ((1 << (hwif->channel + 14)) & - dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; - return ATA_CBL_PATA40; -} - -/* Sun Cobalt Alpine hardware avoids the 80-pin cable - * detect issue by attaching the drives directly to the board. - * This check follows the Dell precedent (how scary is that?!) - * - * WARNING: this only works on Alpine hardware! - */ -static u8 ata66_svwks_cobalt(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && - dev->vendor == PCI_VENDOR_ID_SERVERWORKS && - dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) - return ((1 << (hwif->channel + 14)) & - dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; - return ATA_CBL_PATA40; -} - -static u8 svwks_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - /* Server Works */ - if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS) - return ata66_svwks_svwks (hwif); - - /* Dell PowerEdge */ - if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) - return ata66_svwks_dell (hwif); - - /* Cobalt Alpine */ - if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN) - return ata66_svwks_cobalt (hwif); - - /* Per Specified Design by OEM, and ASIC Architect */ - if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || - (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) - return ATA_CBL_PATA80; - - return ATA_CBL_PATA40; -} - -static const struct ide_port_ops osb4_port_ops = { - .set_pio_mode = svwks_set_pio_mode, - .set_dma_mode = svwks_set_dma_mode, - .udma_filter = svwks_udma_filter, -}; - -static const struct ide_port_ops svwks_port_ops = { - .set_pio_mode = svwks_set_pio_mode, - .set_dma_mode = svwks_set_dma_mode, - .udma_filter = svwks_udma_filter, - .cable_detect = svwks_cable_detect, -}; - -#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS - -static const struct ide_port_info serverworks_chipsets[] __devinitdata = { - { /* 0: OSB4 */ - .name = DRV_NAME, - .init_chipset = init_chipset_svwks, - .port_ops = &osb4_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = 0x00, /* UDMA is problematic on OSB4 */ - }, - { /* 1: CSB5 */ - .name = DRV_NAME, - .init_chipset = init_chipset_svwks, - .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA5, - }, - { /* 2: CSB6 */ - .name = DRV_NAME, - .init_chipset = init_chipset_svwks, - .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA5, - }, - { /* 3: CSB6-2 */ - .name = DRV_NAME, - .init_chipset = init_chipset_svwks, - .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA5, - }, - { /* 4: HT1000 */ - .name = DRV_NAME, - .init_chipset = init_chipset_svwks, - .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA5, - } -}; - -/** - * svwks_init_one - called when a OSB/CSB is found - * @dev: the svwks 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 __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct ide_port_info d; - u8 idx = id->driver_data; - - d = serverworks_chipsets[idx]; - - if (idx == 1) - d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX; - else if (idx == 2 || idx == 3) { - if ((PCI_FUNC(dev->devfn) & 1) == 0) { - if (pci_resource_start(dev, 0) != 0x01f1) - d.host_flags |= IDE_HFLAG_NON_BOOTABLE; - d.host_flags |= IDE_HFLAG_SINGLE; - } else - d.host_flags &= ~IDE_HFLAG_SINGLE; - } - - return ide_pci_init_one(dev, &d, NULL); -} - -static const struct pci_device_id svwks_pci_tbl[] = { - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0 }, - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 1 }, - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2 }, - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 3 }, - { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, svwks_pci_tbl); - -static struct pci_driver svwks_pci_driver = { - .name = "Serverworks_IDE", - .id_table = svwks_pci_tbl, - .probe = svwks_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init svwks_ide_init(void) -{ - return ide_pci_register_driver(&svwks_pci_driver); -} - -static void __exit svwks_ide_exit(void) -{ - pci_unregister_driver(&svwks_pci_driver); -} - -module_init(svwks_ide_init); -module_exit(svwks_ide_exit); - -MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c deleted file mode 100644 index 8af9b23..0000000 --- a/drivers/ide/pci/sgiioc4.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. - * Copyright (C) 2008 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "SGIIOC4" - -/* IOC4 Specific Definitions */ -#define IOC4_CMD_OFFSET 0x100 -#define IOC4_CTRL_OFFSET 0x120 -#define IOC4_DMA_OFFSET 0x140 -#define IOC4_INTR_OFFSET 0x0 - -#define IOC4_TIMING 0x00 -#define IOC4_DMA_PTR_L 0x01 -#define IOC4_DMA_PTR_H 0x02 -#define IOC4_DMA_ADDR_L 0x03 -#define IOC4_DMA_ADDR_H 0x04 -#define IOC4_BC_DEV 0x05 -#define IOC4_BC_MEM 0x06 -#define IOC4_DMA_CTRL 0x07 -#define IOC4_DMA_END_ADDR 0x08 - -/* Bits in the IOC4 Control/Status Register */ -#define IOC4_S_DMA_START 0x01 -#define IOC4_S_DMA_STOP 0x02 -#define IOC4_S_DMA_DIR 0x04 -#define IOC4_S_DMA_ACTIVE 0x08 -#define IOC4_S_DMA_ERROR 0x10 -#define IOC4_ATA_MEMERR 0x02 - -/* Read/Write Directions */ -#define IOC4_DMA_WRITE 0x04 -#define IOC4_DMA_READ 0x00 - -/* Interrupt Register Offsets */ -#define IOC4_INTR_REG 0x03 -#define IOC4_INTR_SET 0x05 -#define IOC4_INTR_CLEAR 0x07 - -#define IOC4_IDE_CACHELINE_SIZE 128 -#define IOC4_CMD_CTL_BLK_SIZE 0x20 -#define IOC4_SUPPORTED_FIRMWARE_REV 46 - -typedef struct { - u32 timing_reg0; - u32 timing_reg1; - u32 low_mem_ptr; - u32 high_mem_ptr; - u32 low_mem_addr; - u32 high_mem_addr; - u32 dev_byte_count; - u32 mem_byte_count; - u32 status; -} ioc4_dma_regs_t; - -/* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */ -/* IOC4 has only 1 IDE channel */ -#define IOC4_PRD_BYTES 16 -#define IOC4_PRD_ENTRIES (PAGE_SIZE /(4*IOC4_PRD_BYTES)) - - -static void -sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, - unsigned long ctrl_port, unsigned long irq_port) -{ - unsigned long reg = data_port; - int i; - - /* Registers are word (32 bit) aligned */ - for (i = 0; i <= 7; i++) - hw->io_ports_array[i] = reg + i * 4; - - hw->io_ports.ctl_addr = ctrl_port; - hw->io_ports.irq_addr = irq_port; -} - -static int -sgiioc4_checkirq(ide_hwif_t * hwif) -{ - unsigned long intr_addr = - hwif->io_ports.irq_addr + IOC4_INTR_REG * 4; - - if ((u8)readl((void __iomem *)intr_addr) & 0x03) - return 1; - - return 0; -} - -static u8 sgiioc4_read_status(ide_hwif_t *); - -static int -sgiioc4_clearirq(ide_drive_t * drive) -{ - u32 intr_reg; - ide_hwif_t *hwif = HWIF(drive); - struct ide_io_ports *io_ports = &hwif->io_ports; - unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2); - - /* Code to check for PCI error conditions */ - intr_reg = readl((void __iomem *)other_ir); - if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */ - /* - * Using sgiioc4_read_status to read the Status register has a - * side effect of clearing the interrupt. The first read should - * clear it if it is set. The second read should return - * a "clear" status if it got cleared. If not, then spin - * for a bit trying to clear it. - */ - u8 stat = sgiioc4_read_status(hwif); - int count = 0; - - stat = sgiioc4_read_status(hwif); - while ((stat & ATA_BUSY) && (count++ < 100)) { - udelay(1); - stat = sgiioc4_read_status(hwif); - } - - if (intr_reg & 0x02) { - struct pci_dev *dev = to_pci_dev(hwif->dev); - /* Error when transferring DMA data on PCI bus */ - u32 pci_err_addr_low, pci_err_addr_high, - pci_stat_cmd_reg; - - pci_err_addr_low = - readl((void __iomem *)io_ports->irq_addr); - pci_err_addr_high = - readl((void __iomem *)(io_ports->irq_addr + 4)); - pci_read_config_dword(dev, PCI_COMMAND, - &pci_stat_cmd_reg); - printk(KERN_ERR - "%s(%s) : PCI Bus Error when doing DMA:" - " status-cmd reg is 0x%x\n", - __func__, drive->name, pci_stat_cmd_reg); - printk(KERN_ERR - "%s(%s) : PCI Error Address is 0x%x%x\n", - __func__, drive->name, - pci_err_addr_high, pci_err_addr_low); - /* Clear the PCI Error indicator */ - pci_write_config_dword(dev, PCI_COMMAND, 0x00000146); - } - - /* Clear the Interrupt, Error bits on the IOC4 */ - writel(0x03, (void __iomem *)other_ir); - - intr_reg = readl((void __iomem *)other_ir); - } - - return intr_reg & 3; -} - -static void sgiioc4_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4; - unsigned int reg = readl((void __iomem *)ioc4_dma_addr); - unsigned int temp_reg = reg | IOC4_S_DMA_START; - - writel(temp_reg, (void __iomem *)ioc4_dma_addr); -} - -static u32 -sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base) -{ - unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4; - u32 ioc4_dma; - int count; - - count = 0; - ioc4_dma = readl((void __iomem *)ioc4_dma_addr); - while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) { - udelay(1); - ioc4_dma = readl((void __iomem *)ioc4_dma_addr); - } - return ioc4_dma; -} - -/* Stops the IOC4 DMA Engine */ -static int sgiioc4_dma_end(ide_drive_t *drive) -{ - u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0; - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - int dma_stat = 0; - unsigned long *ending_dma = ide_get_hwifdata(hwif); - - writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4)); - - ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); - - if (ioc4_dma & IOC4_S_DMA_STOP) { - printk(KERN_ERR - "%s(%s): IOC4 DMA STOP bit is still 1 :" - "ioc4_dma_reg 0x%x\n", - __func__, drive->name, ioc4_dma); - dma_stat = 1; - } - - /* - * The IOC4 will DMA 1's to the ending dma area to indicate that - * previous data DMA is complete. This is necessary because of relaxed - * ordering between register reads and DMA writes on the Altix. - */ - while ((cnt++ < 200) && (!valid)) { - for (num = 0; num < 16; num++) { - if (ending_dma[num]) { - valid = 1; - break; - } - } - udelay(1); - } - if (!valid) { - printk(KERN_ERR "%s(%s) : DMA incomplete\n", __func__, - drive->name); - dma_stat = 1; - } - - bc_dev = readl((void __iomem *)(dma_base + IOC4_BC_DEV * 4)); - bc_mem = readl((void __iomem *)(dma_base + IOC4_BC_MEM * 4)); - - if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) { - if (bc_dev > bc_mem + 8) { - printk(KERN_ERR - "%s(%s): WARNING!! byte_count_dev %d " - "!= byte_count_mem %d\n", - __func__, drive->name, bc_dev, bc_mem); - } - } - - drive->waiting_for_dma = 0; - ide_destroy_dmatable(drive); - - return dma_stat; -} - -static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ -} - -/* returns 1 if dma irq issued, 0 otherwise */ -static int sgiioc4_dma_test_irq(ide_drive_t *drive) -{ - return sgiioc4_checkirq(HWIF(drive)); -} - -static void sgiioc4_dma_host_set(ide_drive_t *drive, int on) -{ - if (!on) - sgiioc4_clearirq(drive); -} - -static void -sgiioc4_resetproc(ide_drive_t * drive) -{ - sgiioc4_dma_end(drive); - sgiioc4_clearirq(drive); -} - -static void -sgiioc4_dma_lost_irq(ide_drive_t * drive) -{ - sgiioc4_resetproc(drive); - - ide_dma_lost_irq(drive); -} - -static u8 sgiioc4_read_status(ide_hwif_t *hwif) -{ - unsigned long port = hwif->io_ports.status_addr; - u8 reg = (u8) readb((void __iomem *) port); - - if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */ - unsigned long other_ir = port - 0x110; - unsigned int intr_reg = (u32) readl((void __iomem *) other_ir); - - /* Clear the Interrupt, Error bits on the IOC4 */ - if (intr_reg & 0x03) { - writel(0x03, (void __iomem *) other_ir); - intr_reg = (u32) readl((void __iomem *) other_ir); - } - } - - return reg; -} - -/* Creates a dma map for the scatter-gather list entries */ -static int __devinit -ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET; - int num_ports = sizeof (ioc4_dma_regs_t); - void *pad; - - printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); - - if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) { - printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx " - "already in use\n", __func__, hwif->name, - dma_base, dma_base + num_ports - 1); - return -1; - } - - hwif->dma_base = (unsigned long)hwif->io_ports.irq_addr + - IOC4_DMA_OFFSET; - - hwif->sg_max_nents = IOC4_PRD_ENTRIES; - - hwif->prd_max_nents = IOC4_PRD_ENTRIES; - hwif->prd_ent_size = IOC4_PRD_BYTES; - - if (ide_allocate_dma_engine(hwif)) - goto dma_pci_alloc_failure; - - pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE, - (dma_addr_t *)&hwif->extra_base); - if (pad) { - ide_set_hwifdata(hwif, pad); - return 0; - } - - ide_release_dma_engine(hwif); - - printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n", - __func__, hwif->name); - printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name); - -dma_pci_alloc_failure: - release_mem_region(dma_base, num_ports); - - return -1; -} - -/* Initializes the IOC4 DMA Engine */ -static void -sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) -{ - u32 ioc4_dma; - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4; - u32 dma_addr, ending_dma_addr; - - ioc4_dma = readl((void __iomem *)ioc4_dma_addr); - - if (ioc4_dma & IOC4_S_DMA_ACTIVE) { - printk(KERN_WARNING - "%s(%s):Warning!! DMA from previous transfer was still active\n", - __func__, drive->name); - writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr); - ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); - - if (ioc4_dma & IOC4_S_DMA_STOP) - printk(KERN_ERR - "%s(%s) : IOC4 Dma STOP bit is still 1\n", - __func__, drive->name); - } - - ioc4_dma = readl((void __iomem *)ioc4_dma_addr); - if (ioc4_dma & IOC4_S_DMA_ERROR) { - printk(KERN_WARNING - "%s(%s) : Warning!! - DMA Error during Previous" - " transfer | status 0x%x\n", - __func__, drive->name, ioc4_dma); - writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr); - ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); - - if (ioc4_dma & IOC4_S_DMA_STOP) - printk(KERN_ERR - "%s(%s) : IOC4 DMA STOP bit is still 1\n", - __func__, drive->name); - } - - /* Address of the Scatter Gather List */ - dma_addr = cpu_to_le32(hwif->dmatable_dma); - writel(dma_addr, (void __iomem *)(dma_base + IOC4_DMA_PTR_L * 4)); - - /* Address of the Ending DMA */ - memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE); - ending_dma_addr = cpu_to_le32(hwif->extra_base); - writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4)); - - writel(dma_direction, (void __iomem *)ioc4_dma_addr); - drive->waiting_for_dma = 1; -} - -/* IOC4 Scatter Gather list Format */ -/* 128 Bit entries to support 64 bit addresses in the future */ -/* The Scatter Gather list Entry should be in the BIG-ENDIAN Format */ -/* --------------------------------------------------------------------- */ -/* | Upper 32 bits - Zero | Lower 32 bits- address | */ -/* --------------------------------------------------------------------- */ -/* | Upper 32 bits - Zero |EOL| 15 unused | 16 Bit Length| */ -/* --------------------------------------------------------------------- */ -/* Creates the scatter gather list, DMA Table */ -static unsigned int -sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned int *table = hwif->dmatable_cpu; - unsigned int count = 0, i = 1; - struct scatterlist *sg; - - hwif->sg_nents = i = ide_build_sglist(drive, rq); - - if (!i) - return 0; /* sglist of length Zero */ - - sg = hwif->sg_table; - while (i && sg_dma_len(sg)) { - dma_addr_t cur_addr; - int cur_len; - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - while (cur_len) { - if (count++ >= IOC4_PRD_ENTRIES) { - printk(KERN_WARNING - "%s: DMA table too small\n", - drive->name); - goto use_pio_instead; - } else { - u32 bcount = - 0x10000 - (cur_addr & 0xffff); - - if (bcount > cur_len) - bcount = cur_len; - - /* put the addr, length in - * the IOC4 dma-table format */ - *table = 0x0; - table++; - *table = cpu_to_be32(cur_addr); - table++; - *table = 0x0; - table++; - - *table = cpu_to_be32(bcount); - table++; - - cur_addr += bcount; - cur_len -= bcount; - } - } - - sg = sg_next(sg); - i--; - } - - if (count) { - table--; - *table |= cpu_to_be32(0x80000000); - return count; - } - -use_pio_instead: - ide_destroy_dmatable(drive); - - return 0; /* revert to PIO for this request */ -} - -static int sgiioc4_dma_setup(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - unsigned int count = 0; - int ddir; - - if (rq_data_dir(rq)) - ddir = PCI_DMA_TODEVICE; - else - ddir = PCI_DMA_FROMDEVICE; - - if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) { - /* try PIO instead of DMA */ - ide_map_sg(drive, rq); - return 1; - } - - if (rq_data_dir(rq)) - /* Writes TO the IOC4 FROM Main Memory */ - ddir = IOC4_DMA_READ; - else - /* Writes FROM the IOC4 TO Main Memory */ - ddir = IOC4_DMA_WRITE; - - sgiioc4_configure_for_dma(ddir, drive); - - return 0; -} - -static const struct ide_tp_ops sgiioc4_tp_ops = { - .exec_command = ide_exec_command, - .read_status = sgiioc4_read_status, - .read_altstatus = ide_read_altstatus, - .read_sff_dma_status = ide_read_sff_dma_status, - - .set_irq = ide_set_irq, - - .tf_load = ide_tf_load, - .tf_read = ide_tf_read, - - .input_data = ide_input_data, - .output_data = ide_output_data, -}; - -static const struct ide_port_ops sgiioc4_port_ops = { - .set_dma_mode = sgiioc4_set_dma_mode, - /* reset DMA engine, clear IRQs */ - .resetproc = sgiioc4_resetproc, -}; - -static const struct ide_dma_ops sgiioc4_dma_ops = { - .dma_host_set = sgiioc4_dma_host_set, - .dma_setup = sgiioc4_dma_setup, - .dma_start = sgiioc4_dma_start, - .dma_end = sgiioc4_dma_end, - .dma_test_irq = sgiioc4_dma_test_irq, - .dma_lost_irq = sgiioc4_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_port_info sgiioc4_port_info __devinitdata = { - .name = DRV_NAME, - .chipset = ide_pci, - .init_dma = ide_dma_sgiioc4, - .tp_ops = &sgiioc4_tp_ops, - .port_ops = &sgiioc4_port_ops, - .dma_ops = &sgiioc4_dma_ops, - .host_flags = IDE_HFLAG_MMIO, - .mwdma_mask = ATA_MWDMA2_ONLY, -}; - -static int __devinit -sgiioc4_ide_setup_pci_device(struct pci_dev *dev) -{ - unsigned long cmd_base, irqport; - unsigned long bar0, cmd_phys_base, ctl; - void __iomem *virt_base; - struct ide_host *host; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - struct ide_port_info d = sgiioc4_port_info; - int rc; - - /* Get the CmdBlk and CtrlBlk Base Registers */ - bar0 = pci_resource_start(dev, 0); - virt_base = ioremap(bar0, pci_resource_len(dev, 0)); - if (virt_base == NULL) { - printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n", - DRV_NAME, bar0); - return -ENOMEM; - } - cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET; - ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET; - irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET; - - cmd_phys_base = bar0 + IOC4_CMD_OFFSET; - if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE, - DRV_NAME) == NULL) { - printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx " - "already in use\n", DRV_NAME, pci_name(dev), - cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); - return -EBUSY; - } - - /* Initialize the IO registers */ - memset(&hw, 0, sizeof(hw)); - sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); - hw.irq = dev->irq; - hw.chipset = ide_pci; - hw.dev = &dev->dev; - - /* Initializing chipset IRQ Registers */ - writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); - - host = ide_host_alloc(&d, hws); - if (host == NULL) { - rc = -ENOMEM; - goto err; - } - - rc = ide_host_register(host, &d, hws); - if (rc) - goto err_free; - - return 0; -err_free: - ide_host_free(host); -err: - release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE); - iounmap(virt_base); - return rc; -} - -static unsigned int __devinit -pci_init_sgiioc4(struct pci_dev *dev) -{ - int ret; - - printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n", - DRV_NAME, pci_name(dev), dev->revision); - - if (dev->revision < IOC4_SUPPORTED_FIRMWARE_REV) { - printk(KERN_ERR "Skipping %s IDE controller in slot %s: " - "firmware is obsolete - please upgrade to " - "revision46 or higher\n", - DRV_NAME, pci_name(dev)); - ret = -EAGAIN; - goto out; - } - ret = sgiioc4_ide_setup_pci_device(dev); -out: - return ret; -} - -int -ioc4_ide_attach_one(struct ioc4_driver_data *idd) -{ - /* PCI-RT does not bring out IDE connection. - * Do not attach to this particular IOC4. - */ - if (idd->idd_variant == IOC4_VARIANT_PCI_RT) - return 0; - - return pci_init_sgiioc4(idd->idd_pdev); -} - -static struct ioc4_submodule ioc4_ide_submodule = { - .is_name = "IOC4_ide", - .is_owner = THIS_MODULE, - .is_probe = ioc4_ide_attach_one, -/* .is_remove = ioc4_ide_remove_one, */ -}; - -static int __init ioc4_ide_init(void) -{ - return ioc4_register_submodule(&ioc4_ide_submodule); -} - -late_initcall(ioc4_ide_init); /* Call only after IDE init is done */ - -MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon"); -MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c deleted file mode 100644 index eb4faf9..0000000 --- a/drivers/ide/pci/siimage.c +++ /dev/null @@ -1,857 +0,0 @@ -/* - * Copyright (C) 2001-2002 Andre Hedrick - * Copyright (C) 2003 Red Hat - * Copyright (C) 2007-2008 MontaVista Software, Inc. - * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz - * - * May be copied or modified under the terms of the GNU General Public License - * - * Documentation for CMD680: - * http://gkernel.sourceforge.net/specs/sii/sii-0680a-v1.31.pdf.bz2 - * - * Documentation for SiI 3112: - * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 - * - * Errata and other documentation only available under NDA. - * - * - * FAQ Items: - * If you are using Marvell SATA-IDE adapters with Maxtor drives - * ensure the system is set up for ATA100/UDMA5, not UDMA6. - * - * If you are using WD drives with SATA bridges you must set the - * drive to "Single". "Master" will hang. - * - * If you have strange problems with nVidia chipset systems please - * see the SI support documentation and update your system BIOS - * if necessary - * - * The Dell DRAC4 has some interesting features including effectively hot - * unplugging/replugging the virtual CD interface when the DRAC is reset. - * This often causes drivers/ide/siimage to panic but is ok with the rather - * smarter code in libata. - * - * TODO: - * - IORDY fixes - * - VDMA support - */ - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "siimage" - -/** - * pdev_is_sata - check if device is SATA - * @pdev: PCI device to check - * - * Returns true if this is a SATA controller - */ - -static int pdev_is_sata(struct pci_dev *pdev) -{ -#ifdef CONFIG_BLK_DEV_IDE_SATA - switch (pdev->device) { - case PCI_DEVICE_ID_SII_3112: - case PCI_DEVICE_ID_SII_1210SA: - return 1; - case PCI_DEVICE_ID_SII_680: - return 0; - } - BUG(); -#endif - return 0; -} - -/** - * is_sata - check if hwif is SATA - * @hwif: interface to check - * - * Returns true if this is a SATA controller - */ - -static inline int is_sata(ide_hwif_t *hwif) -{ - return pdev_is_sata(to_pci_dev(hwif->dev)); -} - -/** - * siimage_selreg - return register base - * @hwif: interface - * @r: config offset - * - * Turn a config register offset into the right address in either - * PCI space or MMIO space to access the control register in question - * Thankfully this is a configuration operation, so isn't performance - * critical. - */ - -static unsigned long siimage_selreg(ide_hwif_t *hwif, int r) -{ - unsigned long base = (unsigned long)hwif->hwif_data; - - base += 0xA0 + r; - if (hwif->host_flags & IDE_HFLAG_MMIO) - base += hwif->channel << 6; - else - base += hwif->channel << 4; - return base; -} - -/** - * siimage_seldev - return register base - * @hwif: interface - * @r: config offset - * - * Turn a config register offset into the right address in either - * PCI space or MMIO space to access the control register in question - * including accounting for the unit shift. - */ - -static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long base = (unsigned long)hwif->hwif_data; - u8 unit = drive->dn & 1; - - base += 0xA0 + r; - if (hwif->host_flags & IDE_HFLAG_MMIO) - base += hwif->channel << 6; - else - base += hwif->channel << 4; - base |= unit << unit; - return base; -} - -static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr) -{ - struct ide_host *host = pci_get_drvdata(dev); - u8 tmp = 0; - - if (host->host_priv) - tmp = readb((void __iomem *)addr); - else - pci_read_config_byte(dev, addr, &tmp); - - return tmp; -} - -static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr) -{ - struct ide_host *host = pci_get_drvdata(dev); - u16 tmp = 0; - - if (host->host_priv) - tmp = readw((void __iomem *)addr); - else - pci_read_config_word(dev, addr, &tmp); - - return tmp; -} - -static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr) -{ - struct ide_host *host = pci_get_drvdata(dev); - - if (host->host_priv) - writeb(val, (void __iomem *)addr); - else - pci_write_config_byte(dev, addr, val); -} - -static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr) -{ - struct ide_host *host = pci_get_drvdata(dev); - - if (host->host_priv) - writew(val, (void __iomem *)addr); - else - pci_write_config_word(dev, addr, val); -} - -static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr) -{ - struct ide_host *host = pci_get_drvdata(dev); - - if (host->host_priv) - writel(val, (void __iomem *)addr); - else - pci_write_config_dword(dev, addr, val); -} - -/** - * sil_udma_filter - compute UDMA mask - * @drive: IDE device - * - * Compute the available UDMA speeds for the device on the interface. - * - * For the CMD680 this depends on the clocking mode (scsc), for the - * SI3112 SATA controller life is a bit simpler. - */ - -static u8 sil_pata_udma_filter(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long base = (unsigned long)hwif->hwif_data; - u8 scsc, mask = 0; - - base += (hwif->host_flags & IDE_HFLAG_MMIO) ? 0x4A : 0x8A; - - scsc = sil_ioread8(dev, base); - - switch (scsc & 0x30) { - case 0x10: /* 133 */ - mask = ATA_UDMA6; - break; - case 0x20: /* 2xPCI */ - mask = ATA_UDMA6; - break; - case 0x00: /* 100 */ - mask = ATA_UDMA5; - break; - default: /* Disabled ? */ - BUG(); - } - - return mask; -} - -static u8 sil_sata_udma_filter(ide_drive_t *drive) -{ - char *m = (char *)&drive->id[ATA_ID_PROD]; - - return strstr(m, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6; -} - -/** - * sil_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * Load the timing settings for this device mode into the - * controller. If we are in PIO mode 3 or 4 turn on IORDY - * monitoring (bit 9). The TF timing is bits 31:16 - */ - -static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) -{ - static const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; - static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; - - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - ide_drive_t *pair = ide_get_pair_dev(drive); - u32 speedt = 0; - u16 speedp = 0; - unsigned long addr = siimage_seldev(drive, 0x04); - unsigned long tfaddr = siimage_selreg(hwif, 0x02); - unsigned long base = (unsigned long)hwif->hwif_data; - u8 tf_pio = pio; - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - u8 addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84) - : (mmio ? 0xB4 : 0x80); - u8 mode = 0; - u8 unit = drive->dn & 1; - - /* trim *taskfile* PIO to the slowest of the master/slave */ - if (pair) { - u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4); - - if (pair_pio < tf_pio) - tf_pio = pair_pio; - } - - /* cheat for now and use the docs */ - speedp = data_speed[pio]; - speedt = tf_speed[tf_pio]; - - sil_iowrite16(dev, speedp, addr); - sil_iowrite16(dev, speedt, tfaddr); - - /* now set up IORDY */ - speedp = sil_ioread16(dev, tfaddr - 2); - speedp &= ~0x200; - if (pio > 2) - speedp |= 0x200; - sil_iowrite16(dev, speedp, tfaddr - 2); - - mode = sil_ioread8(dev, base + addr_mask); - mode &= ~(unit ? 0x30 : 0x03); - mode |= unit ? 0x10 : 0x01; - sil_iowrite8(dev, mode, base + addr_mask); -} - -/** - * sil_set_dma_mode - set host controller for DMA mode - * @drive: drive - * @speed: DMA mode - * - * Tune the SiI chipset for the desired DMA mode. - */ - -static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }; - static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 }; - static const u16 dma[] = { 0x2208, 0x10C2, 0x10C1 }; - - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long base = (unsigned long)hwif->hwif_data; - u16 ultra = 0, multi = 0; - u8 mode = 0, unit = drive->dn & 1; - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - u8 scsc = 0, addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84) - : (mmio ? 0xB4 : 0x80); - unsigned long ma = siimage_seldev(drive, 0x08); - unsigned long ua = siimage_seldev(drive, 0x0C); - - scsc = sil_ioread8 (dev, base + (mmio ? 0x4A : 0x8A)); - mode = sil_ioread8 (dev, base + addr_mask); - multi = sil_ioread16(dev, ma); - ultra = sil_ioread16(dev, ua); - - mode &= ~(unit ? 0x30 : 0x03); - ultra &= ~0x3F; - scsc = ((scsc & 0x30) == 0x00) ? 0 : 1; - - scsc = is_sata(hwif) ? 1 : scsc; - - if (speed >= XFER_UDMA_0) { - multi = dma[2]; - ultra |= scsc ? ultra6[speed - XFER_UDMA_0] : - ultra5[speed - XFER_UDMA_0]; - mode |= unit ? 0x30 : 0x03; - } else { - multi = dma[speed - XFER_MW_DMA_0]; - mode |= unit ? 0x20 : 0x02; - } - - sil_iowrite8 (dev, mode, base + addr_mask); - sil_iowrite16(dev, multi, ma); - sil_iowrite16(dev, ultra, ua); -} - -/* returns 1 if dma irq issued, 0 otherwise */ -static int siimage_io_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 dma_altstat = 0; - unsigned long addr = siimage_selreg(hwif, 1); - - /* return 1 if INTR asserted */ - if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4) - return 1; - - /* return 1 if Device INTR asserted */ - pci_read_config_byte(dev, addr, &dma_altstat); - if (dma_altstat & 8) - return 0; /* return 1; */ - - return 0; -} - -/** - * siimage_mmio_dma_test_irq - check we caused an IRQ - * @drive: drive we are testing - * - * Check if we caused an IDE DMA interrupt. We may also have caused - * SATA status interrupts, if so we clean them up and continue. - */ - -static int siimage_mmio_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long addr = siimage_selreg(hwif, 0x1); - void __iomem *sata_error_addr - = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET]; - - if (sata_error_addr) { - unsigned long base = (unsigned long)hwif->hwif_data; - u32 ext_stat = readl((void __iomem *)(base + 0x10)); - u8 watchdog = 0; - - if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { - u32 sata_error = readl(sata_error_addr); - - writel(sata_error, sata_error_addr); - watchdog = (sata_error & 0x00680000) ? 1 : 0; - printk(KERN_WARNING "%s: sata_error = 0x%08x, " - "watchdog = %d, %s\n", - drive->name, sata_error, watchdog, __func__); - } else - watchdog = (ext_stat & 0x8000) ? 1 : 0; - - ext_stat >>= 16; - if (!(ext_stat & 0x0404) && !watchdog) - return 0; - } - - /* return 1 if INTR asserted */ - if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4) - return 1; - - /* return 1 if Device INTR asserted */ - if (readb((void __iomem *)addr) & 8) - return 0; /* return 1; */ - - return 0; -} - -static int siimage_dma_test_irq(ide_drive_t *drive) -{ - if (drive->hwif->host_flags & IDE_HFLAG_MMIO) - return siimage_mmio_dma_test_irq(drive); - else - return siimage_io_dma_test_irq(drive); -} - -/** - * sil_sata_reset_poll - wait for SATA reset - * @drive: drive we are resetting - * - * Poll the SATA phy and see whether it has come back from the dead - * yet. - */ - -static int sil_sata_reset_poll(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - void __iomem *sata_status_addr - = (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET]; - - if (sata_status_addr) { - /* SATA Status is available only when in MMIO mode */ - u32 sata_stat = readl(sata_status_addr); - - if ((sata_stat & 0x03) != 0x03) { - printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", - hwif->name, sata_stat); - return -ENXIO; - } - } - - return 0; -} - -/** - * sil_sata_pre_reset - reset hook - * @drive: IDE device being reset - * - * For the SATA devices we need to handle recalibration/geometry - * differently - */ - -static void sil_sata_pre_reset(ide_drive_t *drive) -{ - if (drive->media == ide_disk) { - drive->special.b.set_geometry = 0; - drive->special.b.recalibrate = 0; - } -} - -/** - * init_chipset_siimage - set up an SI device - * @dev: PCI device - * - * Perform the initial PCI set up for this device. Attempt to switch - * to 133 MHz clocking if the system isn't already set up to do it. - */ - -static unsigned int init_chipset_siimage(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - void __iomem *ioaddr = host->host_priv; - unsigned long base, scsc_addr; - u8 rev = dev->revision, tmp; - - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255); - - if (ioaddr) - pci_set_master(dev); - - base = (unsigned long)ioaddr; - - if (ioaddr && pdev_is_sata(dev)) { - u32 tmp32, irq_mask; - - /* make sure IDE0/1 interrupts are not masked */ - irq_mask = (1 << 22) | (1 << 23); - tmp32 = readl(ioaddr + 0x48); - if (tmp32 & irq_mask) { - tmp32 &= ~irq_mask; - writel(tmp32, ioaddr + 0x48); - readl(ioaddr + 0x48); /* flush */ - } - writel(0, ioaddr + 0x148); - writel(0, ioaddr + 0x1C8); - } - - sil_iowrite8(dev, 0, base ? (base + 0xB4) : 0x80); - sil_iowrite8(dev, 0, base ? (base + 0xF4) : 0x84); - - scsc_addr = base ? (base + 0x4A) : 0x8A; - tmp = sil_ioread8(dev, scsc_addr); - - switch (tmp & 0x30) { - case 0x00: - /* On 100 MHz clocking, try and switch to 133 MHz */ - sil_iowrite8(dev, tmp | 0x10, scsc_addr); - break; - case 0x30: - /* Clocking is disabled, attempt to force 133MHz clocking. */ - sil_iowrite8(dev, tmp & ~0x20, scsc_addr); - case 0x10: - /* On 133Mhz clocking. */ - break; - case 0x20: - /* On PCIx2 clocking. */ - break; - } - - tmp = sil_ioread8(dev, scsc_addr); - - sil_iowrite8 (dev, 0x72, base + 0xA1); - sil_iowrite16(dev, 0x328A, base + 0xA2); - sil_iowrite32(dev, 0x62DD62DD, base + 0xA4); - sil_iowrite32(dev, 0x43924392, base + 0xA8); - sil_iowrite32(dev, 0x40094009, base + 0xAC); - sil_iowrite8 (dev, 0x72, base ? (base + 0xE1) : 0xB1); - sil_iowrite16(dev, 0x328A, base ? (base + 0xE2) : 0xB2); - sil_iowrite32(dev, 0x62DD62DD, base ? (base + 0xE4) : 0xB4); - sil_iowrite32(dev, 0x43924392, base ? (base + 0xE8) : 0xB8); - sil_iowrite32(dev, 0x40094009, base ? (base + 0xEC) : 0xBC); - - if (base && pdev_is_sata(dev)) { - writel(0xFFFF0000, ioaddr + 0x108); - writel(0xFFFF0000, ioaddr + 0x188); - writel(0x00680000, ioaddr + 0x148); - writel(0x00680000, ioaddr + 0x1C8); - } - - /* report the clocking mode of the controller */ - if (!pdev_is_sata(dev)) { - static const char *clk_str[] = - { "== 100", "== 133", "== 2X PCI", "DISABLED!" }; - - tmp >>= 4; - printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s\n", - pci_name(dev), clk_str[tmp & 3]); - } - - return 0; -} - -/** - * init_mmio_iops_siimage - set up the iops for MMIO - * @hwif: interface to set up - * - * The basic setup here is fairly simple, we can use standard MMIO - * operations. However we do have to set the taskfile register offsets - * by hand as there isn't a standard defined layout for them this time. - * - * The hardware supports buffered taskfiles and also some rather nice - * extended PRD tables. For better SI3112 support use the libata driver - */ - -static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - void *addr = host->host_priv; - u8 ch = hwif->channel; - struct ide_io_ports *io_ports = &hwif->io_ports; - unsigned long base; - - /* - * Fill in the basic hwif bits - */ - hwif->host_flags |= IDE_HFLAG_MMIO; - - hwif->hwif_data = addr; - - /* - * Now set up the hw. We have to do this ourselves as the - * MMIO layout isn't the same as the standard port based I/O. - */ - memset(io_ports, 0, sizeof(*io_ports)); - - base = (unsigned long)addr; - if (ch) - base += 0xC0; - else - base += 0x80; - - /* - * The buffered task file doesn't have status/control, so we - * can't currently use it sanely since we want to use LBA48 mode. - */ - io_ports->data_addr = base; - io_ports->error_addr = base + 1; - io_ports->nsect_addr = base + 2; - io_ports->lbal_addr = base + 3; - io_ports->lbam_addr = base + 4; - io_ports->lbah_addr = base + 5; - io_ports->device_addr = base + 6; - io_ports->status_addr = base + 7; - io_ports->ctl_addr = base + 10; - - if (pdev_is_sata(dev)) { - base = (unsigned long)addr; - if (ch) - base += 0x80; - hwif->sata_scr[SATA_STATUS_OFFSET] = base + 0x104; - hwif->sata_scr[SATA_ERROR_OFFSET] = base + 0x108; - hwif->sata_scr[SATA_CONTROL_OFFSET] = base + 0x100; - } - - hwif->irq = dev->irq; - - hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00); -} - -static int is_dev_seagate_sata(ide_drive_t *drive) -{ - const char *s = (const char *)&drive->id[ATA_ID_PROD]; - unsigned len = strnlen(s, ATA_ID_PROD_LEN); - - if ((len > 4) && (!memcmp(s, "ST", 2))) - if ((!memcmp(s + len - 2, "AS", 2)) || - (!memcmp(s + len - 3, "ASL", 3))) { - printk(KERN_INFO "%s: applying pessimistic Seagate " - "errata fix\n", drive->name); - return 1; - } - - return 0; -} - -/** - * sil_quirkproc - post probe fixups - * @drive: drive - * - * Called after drive probe we use this to decide whether the - * Seagate fixup must be applied. This used to be in init_iops but - * that can occur before we know what drives are present. - */ - -static void sil_quirkproc(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - - /* Try and rise the rqsize */ - if (!is_sata(hwif) || !is_dev_seagate_sata(drive)) - hwif->rqsize = 128; -} - -/** - * init_iops_siimage - set up iops - * @hwif: interface to set up - * - * Do the basic setup for the SIIMAGE hardware interface - * and then do the MMIO setup if we can. This is the first - * look in we get for setting up the hwif so that we - * can get the iops right before using them. - */ - -static void __devinit init_iops_siimage(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - - hwif->hwif_data = NULL; - - /* Pessimal until we finish probing */ - hwif->rqsize = 15; - - if (host->host_priv) - init_mmio_iops_siimage(hwif); -} - -/** - * sil_cable_detect - cable detection - * @hwif: interface to check - * - * Check for the presence of an ATA66 capable cable on the interface. - */ - -static u8 sil_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long addr = siimage_selreg(hwif, 0); - u8 ata66 = sil_ioread8(dev, addr); - - return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; -} - -static const struct ide_port_ops sil_pata_port_ops = { - .set_pio_mode = sil_set_pio_mode, - .set_dma_mode = sil_set_dma_mode, - .quirkproc = sil_quirkproc, - .udma_filter = sil_pata_udma_filter, - .cable_detect = sil_cable_detect, -}; - -static const struct ide_port_ops sil_sata_port_ops = { - .set_pio_mode = sil_set_pio_mode, - .set_dma_mode = sil_set_dma_mode, - .reset_poll = sil_sata_reset_poll, - .pre_reset = sil_sata_pre_reset, - .quirkproc = sil_quirkproc, - .udma_filter = sil_sata_udma_filter, - .cable_detect = sil_cable_detect, -}; - -static const struct ide_dma_ops sil_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = ide_dma_end, - .dma_test_irq = siimage_dma_test_irq, - .dma_timeout = ide_dma_timeout, - .dma_lost_irq = ide_dma_lost_irq, -}; - -#define DECLARE_SII_DEV(p_ops) \ - { \ - .name = DRV_NAME, \ - .init_chipset = init_chipset_siimage, \ - .init_iops = init_iops_siimage, \ - .port_ops = p_ops, \ - .dma_ops = &sil_dma_ops, \ - .pio_mask = ATA_PIO4, \ - .mwdma_mask = ATA_MWDMA2, \ - .udma_mask = ATA_UDMA6, \ - } - -static const struct ide_port_info siimage_chipsets[] __devinitdata = { - /* 0: SiI680 */ DECLARE_SII_DEV(&sil_pata_port_ops), - /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops) -}; - -/** - * siimage_init_one - PCI layer discovery entry - * @dev: PCI device - * @id: ident table entry - * - * Called by the PCI code when it finds an SiI680 or SiI3112 controller. - * We then use the IDE PCI generic helper to do most of the work. - */ - -static int __devinit siimage_init_one(struct pci_dev *dev, - const struct pci_device_id *id) -{ - void __iomem *ioaddr = NULL; - resource_size_t bar5 = pci_resource_start(dev, 5); - unsigned long barsize = pci_resource_len(dev, 5); - int rc; - struct ide_port_info d; - u8 idx = id->driver_data; - u8 BA5_EN; - - d = siimage_chipsets[idx]; - - if (idx) { - static int first = 1; - - if (first) { - printk(KERN_INFO DRV_NAME ": For full SATA support you " - "should use the libata sata_sil module.\n"); - first = 0; - } - - d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA; - } - - rc = pci_enable_device(dev); - if (rc) - return rc; - - pci_read_config_byte(dev, 0x8A, &BA5_EN); - if ((BA5_EN & 0x01) || bar5) { - /* - * Drop back to PIO if we can't map the MMIO. Some systems - * seem to get terminally confused in the PCI spaces. - */ - if (!request_mem_region(bar5, barsize, d.name)) { - printk(KERN_WARNING DRV_NAME " %s: MMIO ports not " - "available\n", pci_name(dev)); - } else { - ioaddr = ioremap(bar5, barsize); - if (ioaddr == NULL) - release_mem_region(bar5, barsize); - } - } - - rc = ide_pci_init_one(dev, &d, ioaddr); - if (rc) { - if (ioaddr) { - iounmap(ioaddr); - release_mem_region(bar5, barsize); - } - pci_disable_device(dev); - } - - return rc; -} - -static void __devexit siimage_remove(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - void __iomem *ioaddr = host->host_priv; - - ide_pci_remove(dev); - - if (ioaddr) { - resource_size_t bar5 = pci_resource_start(dev, 5); - unsigned long barsize = pci_resource_len(dev, 5); - - iounmap(ioaddr); - release_mem_region(bar5, barsize); - } - - pci_disable_device(dev); -} - -static const struct pci_device_id siimage_pci_tbl[] = { - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), 0 }, -#ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112), 1 }, - { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 }, -#endif - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, siimage_pci_tbl); - -static struct pci_driver siimage_pci_driver = { - .name = "SiI_IDE", - .id_table = siimage_pci_tbl, - .probe = siimage_init_one, - .remove = __devexit_p(siimage_remove), - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init siimage_ide_init(void) -{ - return ide_pci_register_driver(&siimage_pci_driver); -} - -static void __exit siimage_ide_exit(void) -{ - pci_unregister_driver(&siimage_pci_driver); -} - -module_init(siimage_ide_init); -module_exit(siimage_ide_exit); - -MODULE_AUTHOR("Andre Hedrick, Alan Cox"); -MODULE_DESCRIPTION("PCI driver module for SiI IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c deleted file mode 100644 index ad32e18..0000000 --- a/drivers/ide/pci/sis5513.c +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Copyright (C) 1999-2000 Andre Hedrick - * Copyright (C) 2002 Lionel Bouton , Maintainer - * Copyright (C) 2003 Vojtech Pavlik - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * - * May be copied or modified under the terms of the GNU General Public License - * - * - * Thanks : - * - * SiS Taiwan : for direct support and hardware. - * Daniela Engert : for initial ATA100 advices and numerous others. - * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt : - * for checking code correctness, providing patches. - * - * - * Original tests and design on the SiS620 chipset. - * ATA100 tests and design on the SiS735 chipset. - * ATA16/33 support from specs - * ATA133 support for SiS961/962 by L.C. Chang - * ATA133 961/962/963 fixes by Vojtech Pavlik - * - * Documentation: - * SiS chipset documentation available under NDA to companies only - * (not to individuals). - */ - -/* - * The original SiS5513 comes from a SiS5511/55112/5513 chipset. The original - * SiS5513 was also used in the SiS5596/5513 chipset. Thus if we see a SiS5511 - * or SiS5596, we can assume we see the first MWDMA-16 capable SiS5513 chip. - * - * Later SiS chipsets integrated the 5513 functionality into the NorthBridge, - * starting with SiS5571 and up to SiS745. The PCI ID didn't change, though. We - * can figure out that we have a more modern and more capable 5513 by looking - * for the respective NorthBridge IDs. - * - * Even later (96x family) SiS chipsets use the MuTIOL link and place the 5513 - * into the SouthBrige. Here we cannot rely on looking up the NorthBridge PCI - * ID, while the now ATA-133 capable 5513 still has the same PCI ID. - * Fortunately the 5513 can be 'unmasked' by fiddling with some config space - * bits, changing its device id to the true one - 5517 for 961 and 5518 for - * 962/963. - */ - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "sis5513" - -/* registers layout and init values are chipset family dependant */ - -#define ATA_16 0x01 -#define ATA_33 0x02 -#define ATA_66 0x03 -#define ATA_100a 0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */ -#define ATA_100 0x05 -#define ATA_133a 0x06 /* SiS961b with 133 support */ -#define ATA_133 0x07 /* SiS962/963 */ - -static u8 chipset_family; - -/* - * Devices supported - */ -static const struct { - const char *name; - u16 host_id; - u8 chipset_family; - u8 flags; -} SiSHostChipInfo[] = { - { "SiS968", PCI_DEVICE_ID_SI_968, ATA_133 }, - { "SiS966", PCI_DEVICE_ID_SI_966, ATA_133 }, - { "SiS965", PCI_DEVICE_ID_SI_965, ATA_133 }, - { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100 }, - { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100 }, - { "SiS733", PCI_DEVICE_ID_SI_733, ATA_100 }, - { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100 }, - { "SiS633", PCI_DEVICE_ID_SI_633, ATA_100 }, - - { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a }, - { "SiS550", PCI_DEVICE_ID_SI_550, ATA_100a }, - - { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66 }, - { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66 }, - { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66 }, - { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66 }, - { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66 }, - - { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33 }, - { "SiS5598", PCI_DEVICE_ID_SI_5598, ATA_33 }, - { "SiS5597", PCI_DEVICE_ID_SI_5597, ATA_33 }, - { "SiS5591/2", PCI_DEVICE_ID_SI_5591, ATA_33 }, - { "SiS5582", PCI_DEVICE_ID_SI_5582, ATA_33 }, - { "SiS5581", PCI_DEVICE_ID_SI_5581, ATA_33 }, - - { "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 }, - { "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 }, - { "SiS5517", PCI_DEVICE_ID_SI_5517, ATA_16 }, - { "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 }, -}; - -/* Cycle time bits and values vary across chip dma capabilities - These three arrays hold the register layout and the values to set. - Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ - -/* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */ -static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 }; -static u8 cycle_time_range[] = { 0, 0, 2, 3, 3, 4, 4 }; -static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { - { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ - { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ - { 3, 2, 1, 0, 0, 0, 0 }, /* ATA_33 */ - { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_66 */ - { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific), - different cycle_time range and offset */ - { 11, 7, 5, 4, 2, 1, 0 }, /* ATA_100 */ - { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */ - { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */ -}; -/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133 - See SiS962 data sheet for more detail */ -static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { - { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ - { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ - { 2, 1, 1, 0, 0, 0, 0 }, - { 4, 3, 2, 1, 0, 0, 0 }, - { 4, 3, 2, 1, 0, 0, 0 }, - { 6, 4, 3, 1, 1, 1, 0 }, - { 9, 6, 4, 2, 2, 2, 2 }, - { 9, 6, 4, 2, 2, 2, 2 }, -}; -/* Initialize time, Active time, Recovery time vary across - IDE clock settings. These 3 arrays hold the register value - for PIO0/1/2/3/4 and DMA0/1/2 mode in order */ -static u8 ini_time_value[][8] = { - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 2, 1, 0, 0, 0, 1, 0, 0 }, - { 4, 3, 1, 1, 1, 3, 1, 1 }, - { 4, 3, 1, 1, 1, 3, 1, 1 }, - { 6, 4, 2, 2, 2, 4, 2, 2 }, - { 9, 6, 3, 3, 3, 6, 3, 3 }, - { 9, 6, 3, 3, 3, 6, 3, 3 }, -}; -static u8 act_time_value[][8] = { - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 9, 9, 9, 2, 2, 7, 2, 2 }, - { 19, 19, 19, 5, 4, 14, 5, 4 }, - { 19, 19, 19, 5, 4, 14, 5, 4 }, - { 28, 28, 28, 7, 6, 21, 7, 6 }, - { 38, 38, 38, 10, 9, 28, 10, 9 }, - { 38, 38, 38, 10, 9, 28, 10, 9 }, -}; -static u8 rco_time_value[][8] = { - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 9, 2, 0, 2, 0, 7, 1, 1 }, - { 19, 5, 1, 5, 2, 16, 3, 2 }, - { 19, 5, 1, 5, 2, 16, 3, 2 }, - { 30, 9, 3, 9, 4, 25, 6, 4 }, - { 40, 12, 4, 12, 5, 34, 12, 5 }, - { 40, 12, 4, 12, 5, 34, 12, 5 }, -}; - -/* - * Printing configuration - */ -/* Used for chipset type printing at boot time */ -static char *chipset_capability[] = { - "ATA", "ATA 16", - "ATA 33", "ATA 66", - "ATA 100 (1st gen)", "ATA 100 (2nd gen)", - "ATA 133 (1st gen)", "ATA 133 (2nd gen)" -}; - -/* - * Configuration functions - */ - -static u8 sis_ata133_get_base(ide_drive_t *drive) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u32 reg54 = 0; - - pci_read_config_dword(dev, 0x54, ®54); - - return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4; -} - -static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u16 t1 = 0; - u8 drive_pci = 0x40 + drive->dn * 2; - - const u16 pio_timings[] = { 0x000, 0x607, 0x404, 0x303, 0x301 }; - const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 }; - - pci_read_config_word(dev, drive_pci, &t1); - - /* clear active/recovery timings */ - t1 &= ~0x070f; - if (mode >= XFER_MW_DMA_0) { - if (chipset_family > ATA_16) - t1 &= ~0x8000; /* disable UDMA */ - t1 |= mwdma_timings[mode - XFER_MW_DMA_0]; - } else - t1 |= pio_timings[mode - XFER_PIO_0]; - - pci_write_config_word(dev, drive_pci, t1); -} - -static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u8 t1, drive_pci = 0x40 + drive->dn * 2; - - /* timing bits: 7:4 active 3:0 recovery */ - const u8 pio_timings[] = { 0x00, 0x67, 0x44, 0x33, 0x31 }; - const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 }; - - if (mode >= XFER_MW_DMA_0) { - u8 t2 = 0; - - pci_read_config_byte(dev, drive_pci, &t2); - t2 &= ~0x80; /* disable UDMA */ - pci_write_config_byte(dev, drive_pci, t2); - - t1 = mwdma_timings[mode - XFER_MW_DMA_0]; - } else - t1 = pio_timings[mode - XFER_PIO_0]; - - pci_write_config_byte(dev, drive_pci + 1, t1); -} - -static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u32 t1 = 0; - u8 drive_pci = sis_ata133_get_base(drive), clk, idx; - - pci_read_config_dword(dev, drive_pci, &t1); - - t1 &= 0xc0c00fff; - clk = (t1 & 0x08) ? ATA_133 : ATA_100; - if (mode >= XFER_MW_DMA_0) { - t1 &= ~0x04; /* disable UDMA */ - idx = mode - XFER_MW_DMA_0 + 5; - } else - idx = mode - XFER_PIO_0; - t1 |= ini_time_value[clk][idx] << 12; - t1 |= act_time_value[clk][idx] << 16; - t1 |= rco_time_value[clk][idx] << 24; - - pci_write_config_dword(dev, drive_pci, t1); -} - -static void sis_program_timings(ide_drive_t *drive, const u8 mode) -{ - if (chipset_family < ATA_100) /* ATA_16/33/66/100a */ - sis_ata16_program_timings(drive, mode); - else if (chipset_family < ATA_133) /* ATA_100/133a */ - sis_ata100_program_timings(drive, mode); - else /* ATA_133 */ - sis_ata133_program_timings(drive, mode); -} - -static void config_drive_art_rwp(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 reg4bh = 0; - u8 rw_prefetch = 0; - - pci_read_config_byte(dev, 0x4b, ®4bh); - - if (drive->media == ide_disk) - rw_prefetch = 0x11 << drive->dn; - - if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch) - pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); -} - -static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - config_drive_art_rwp(drive); - sis_program_timings(drive, XFER_PIO_0 + pio); -} - -static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u32 regdw = 0; - u8 drive_pci = sis_ata133_get_base(drive), clk, idx; - - pci_read_config_dword(dev, drive_pci, ®dw); - - regdw |= 0x04; - regdw &= 0xfffff00f; - /* check if ATA133 enable */ - clk = (regdw & 0x08) ? ATA_133 : ATA_100; - idx = mode - XFER_UDMA_0; - regdw |= cycle_time_value[clk][idx] << 4; - regdw |= cvs_time_value[clk][idx] << 8; - - pci_write_config_dword(dev, drive_pci, regdw); -} - -static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family; - - pci_read_config_byte(dev, drive_pci + 1, ®); - - /* force the UDMA bit on if we want to use UDMA */ - reg |= 0x80; - /* clean reg cycle time bits */ - reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]); - /* set reg cycle time bits */ - reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i]; - - pci_write_config_byte(dev, drive_pci + 1, reg); -} - -static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode) -{ - if (chipset_family >= ATA_133) /* ATA_133 */ - sis_ata133_program_udma_timings(drive, mode); - else /* ATA_33/66/100a/100/133a */ - sis_ata33_program_udma_timings(drive, mode); -} - -static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - if (speed >= XFER_UDMA_0) - sis_program_udma_timings(drive, speed); - else - sis_program_timings(drive, speed); -} - -static u8 sis_ata133_udma_filter(ide_drive_t *drive) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u32 regdw = 0; - u8 drive_pci = sis_ata133_get_base(drive); - - pci_read_config_dword(dev, drive_pci, ®dw); - - /* if ATA133 disable, we should not set speed above UDMA5 */ - return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5; -} - -static int __devinit sis_find_family(struct pci_dev *dev) -{ - struct pci_dev *host; - int i = 0; - - chipset_family = 0; - - for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) { - - host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL); - - if (!host) - continue; - - chipset_family = SiSHostChipInfo[i].chipset_family; - - /* Special case for SiS630 : 630S/ET is ATA_100a */ - if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) { - if (host->revision >= 0x30) - chipset_family = ATA_100a; - } - pci_dev_put(host); - - printk(KERN_INFO DRV_NAME " %s: %s %s controller\n", - pci_name(dev), SiSHostChipInfo[i].name, - chipset_capability[chipset_family]); - } - - if (!chipset_family) { /* Belongs to pci-quirks */ - - u32 idemisc; - u16 trueid; - - /* Disable ID masking and register remapping */ - pci_read_config_dword(dev, 0x54, &idemisc); - pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff)); - pci_read_config_word(dev, PCI_DEVICE_ID, &trueid); - pci_write_config_dword(dev, 0x54, idemisc); - - if (trueid == 0x5518) { - printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n", - pci_name(dev)); - chipset_family = ATA_133; - - /* Check for 5513 compability mapping - * We must use this, else the port enabled code will fail, - * as it expects the enablebits at 0x4a. - */ - if ((idemisc & 0x40000000) == 0) { - pci_write_config_dword(dev, 0x54, idemisc | 0x40000000); - printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n", - pci_name(dev)); - } - } - } - - if (!chipset_family) { /* Belongs to pci-quirks */ - - struct pci_dev *lpc_bridge; - u16 trueid; - u8 prefctl; - u8 idecfg; - - pci_read_config_byte(dev, 0x4a, &idecfg); - pci_write_config_byte(dev, 0x4a, idecfg | 0x10); - pci_read_config_word(dev, PCI_DEVICE_ID, &trueid); - pci_write_config_byte(dev, 0x4a, idecfg); - - if (trueid == 0x5517) { /* SiS 961/961B */ - - lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */ - pci_read_config_byte(dev, 0x49, &prefctl); - pci_dev_put(lpc_bridge); - - if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) { - printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n", - pci_name(dev)); - chipset_family = ATA_133a; - } else { - printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n", - pci_name(dev)); - chipset_family = ATA_100; - } - } - } - - return chipset_family; -} - -static unsigned int init_chipset_sis5513(struct pci_dev *dev) -{ - /* Make general config ops here - 1/ tell IDE channels to operate in Compatibility mode only - 2/ tell old chips to allow per drive IDE timings */ - - u8 reg; - u16 regw; - - switch (chipset_family) { - case ATA_133: - /* SiS962 operation mode */ - pci_read_config_word(dev, 0x50, ®w); - if (regw & 0x08) - pci_write_config_word(dev, 0x50, regw&0xfff7); - pci_read_config_word(dev, 0x52, ®w); - if (regw & 0x08) - pci_write_config_word(dev, 0x52, regw&0xfff7); - break; - case ATA_133a: - case ATA_100: - /* Fixup latency */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); - /* Set compatibility bit */ - pci_read_config_byte(dev, 0x49, ®); - if (!(reg & 0x01)) - pci_write_config_byte(dev, 0x49, reg|0x01); - break; - case ATA_100a: - case ATA_66: - /* Fixup latency */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); - - /* On ATA_66 chips the bit was elsewhere */ - pci_read_config_byte(dev, 0x52, ®); - if (!(reg & 0x04)) - pci_write_config_byte(dev, 0x52, reg|0x04); - break; - case ATA_33: - /* On ATA_33 we didn't have a single bit to set */ - pci_read_config_byte(dev, 0x09, ®); - if ((reg & 0x0f) != 0x00) - pci_write_config_byte(dev, 0x09, reg&0xf0); - case ATA_16: - /* force per drive recovery and active timings - needed on ATA_33 and below chips */ - pci_read_config_byte(dev, 0x52, ®); - if (!(reg & 0x08)) - pci_write_config_byte(dev, 0x52, reg|0x08); - break; - } - - return 0; -} - -struct sis_laptop { - u16 device; - u16 subvendor; - u16 subdevice; -}; - -static const struct sis_laptop sis_laptop[] = { - /* devid, subvendor, subdev */ - { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ - { 0x5513, 0x1734, 0x105f }, /* FSC Amilo A1630 */ - { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ - /* end marker */ - { 0, } -}; - -static u8 sis_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *pdev = to_pci_dev(hwif->dev); - const struct sis_laptop *lap = &sis_laptop[0]; - u8 ata66 = 0; - - while (lap->device) { - if (lap->device == pdev->device && - lap->subvendor == pdev->subsystem_vendor && - lap->subdevice == pdev->subsystem_device) - return ATA_CBL_PATA40_SHORT; - lap++; - } - - if (chipset_family >= ATA_133) { - u16 regw = 0; - u16 reg_addr = hwif->channel ? 0x52: 0x50; - pci_read_config_word(pdev, reg_addr, ®w); - ata66 = (regw & 0x8000) ? 0 : 1; - } else if (chipset_family >= ATA_66) { - u8 reg48h = 0; - u8 mask = hwif->channel ? 0x20 : 0x10; - pci_read_config_byte(pdev, 0x48, ®48h); - ata66 = (reg48h & mask) ? 0 : 1; - } - - return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40; -} - -static const struct ide_port_ops sis_port_ops = { - .set_pio_mode = sis_set_pio_mode, - .set_dma_mode = sis_set_dma_mode, - .cable_detect = sis_cable_detect, -}; - -static const struct ide_port_ops sis_ata133_port_ops = { - .set_pio_mode = sis_set_pio_mode, - .set_dma_mode = sis_set_dma_mode, - .udma_filter = sis_ata133_udma_filter, - .cable_detect = sis_cable_detect, -}; - -static const struct ide_port_info sis5513_chipset __devinitdata = { - .name = DRV_NAME, - .init_chipset = init_chipset_sis5513, - .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} }, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, -}; - -static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct ide_port_info d = sis5513_chipset; - u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; - int rc; - - rc = pci_enable_device(dev); - if (rc) - return rc; - - if (sis_find_family(dev) == 0) - return -ENOTSUPP; - - if (chipset_family >= ATA_133) - d.port_ops = &sis_ata133_port_ops; - else - d.port_ops = &sis_port_ops; - - d.udma_mask = udma_rates[chipset_family]; - - return ide_pci_init_one(dev, &d, NULL); -} - -static void __devexit sis5513_remove(struct pci_dev *dev) -{ - ide_pci_remove(dev); - pci_disable_device(dev); -} - -static const struct pci_device_id sis5513_pci_tbl[] = { - { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 }, - { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 }, - { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl); - -static struct pci_driver sis5513_pci_driver = { - .name = "SIS_IDE", - .id_table = sis5513_pci_tbl, - .probe = sis5513_init_one, - .remove = __devexit_p(sis5513_remove), - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init sis5513_ide_init(void) -{ - return ide_pci_register_driver(&sis5513_pci_driver); -} - -static void __exit sis5513_ide_exit(void) -{ - pci_unregister_driver(&sis5513_pci_driver); -} - -module_init(sis5513_ide_init); -module_exit(sis5513_ide_exit); - -MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik"); -MODULE_DESCRIPTION("PCI driver module for SIS IDE"); -MODULE_LICENSE("GPL"); - -/* - * TODO: - * - CLEANUP - * - More checks in the config registers (force values instead of - * relying on the BIOS setting them correctly). - * - Further optimisations ? - * . for example ATA66+ regs 0x48 & 0x4A - */ diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c deleted file mode 100644 index 84dc336..0000000 --- a/drivers/ide/pci/sl82c105.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * SL82C105/Winbond 553 IDE driver - * - * Maintainer unknown. - * - * Drive tuning added from Rebel.com's kernel sources - * -- Russell King (15/11/98) linux@arm.linux.org.uk - * - * Merge in Russell's HW workarounds, fix various problems - * with the timing registers setup. - * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org - * - * Copyright (C) 2006-2007 MontaVista Software, Inc. - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - */ - -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "sl82c105" - -#undef DEBUG - -#ifdef DEBUG -#define DBG(arg) printk arg -#else -#define DBG(fmt,...) -#endif -/* - * SL82C105 PCI config register 0x40 bits. - */ -#define CTRL_IDE_IRQB (1 << 30) -#define CTRL_IDE_IRQA (1 << 28) -#define CTRL_LEGIRQ (1 << 11) -#define CTRL_P1F16 (1 << 5) -#define CTRL_P1EN (1 << 4) -#define CTRL_P0F16 (1 << 1) -#define CTRL_P0EN (1 << 0) - -/* - * Convert a PIO mode and cycle time to the required on/off times - * for the interface. This has protection against runaway timings. - */ -static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio) -{ - struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); - unsigned int cmd_on, cmd_off; - u8 iordy = 0; - - cmd_on = (t->active + 29) / 30; - cmd_off = (ide_pio_cycle_time(drive, pio) - 30 * cmd_on + 29) / 30; - - if (cmd_on == 0) - cmd_on = 1; - - if (cmd_off == 0) - cmd_off = 1; - - if (pio > 2 || ata_id_has_iordy(drive->id)) - iordy = 0x40; - - return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy; -} - -/* - * Configure the chipset for PIO mode. - */ -static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - int reg = 0x44 + drive->dn * 4; - u16 drv_ctrl; - - drv_ctrl = get_pio_timings(drive, pio); - - /* - * Store the PIO timings so that we can restore them - * in case DMA will be turned off... - */ - drive->drive_data &= 0xffff0000; - drive->drive_data |= drv_ctrl; - - pci_write_config_word(dev, reg, drv_ctrl); - pci_read_config_word (dev, reg, &drv_ctrl); - - printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name, - ide_xfer_verbose(pio + XFER_PIO_0), - ide_pio_cycle_time(drive, pio), drv_ctrl); -} - -/* - * Configure the chipset for DMA mode. - */ -static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200}; - u16 drv_ctrl; - - DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n", - drive->name, ide_xfer_verbose(speed))); - - drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0]; - - /* - * Store the DMA timings so that we can actually program - * them when DMA will be turned on... - */ - drive->drive_data &= 0x0000ffff; - drive->drive_data |= (unsigned long)drv_ctrl << 16; -} - -/* - * The SL82C105 holds off all IDE interrupts while in DMA mode until - * all DMA activity is completed. Sometimes this causes problems (eg, - * when the drive wants to report an error condition). - * - * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller - * state machine. We need to kick this to work around various bugs. - */ -static inline void sl82c105_reset_host(struct pci_dev *dev) -{ - u16 val; - - pci_read_config_word(dev, 0x7e, &val); - pci_write_config_word(dev, 0x7e, val | (1 << 2)); - pci_write_config_word(dev, 0x7e, val & ~(1 << 2)); -} - -/* - * If we get an IRQ timeout, it might be that the DMA state machine - * got confused. Fix from Todd Inglett. Details from Winbond. - * - * This function is called when the IDE timer expires, the drive - * indicates that it is READY, and we were waiting for DMA to complete. - */ -static void sl82c105_dma_lost_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; - u8 dma_cmd; - - printk("sl82c105: lost IRQ, resetting host\n"); - - /* - * Check the raw interrupt from the drive. - */ - pci_read_config_dword(dev, 0x40, &val); - if (val & mask) - printk("sl82c105: drive was requesting IRQ, but host lost it\n"); - - /* - * Was DMA enabled? If so, disable it - we're resetting the - * host. The IDE layer will be handling the drive for us. - */ - dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); - if (dma_cmd & 1) { - outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); - printk("sl82c105: DMA was enabled\n"); - } - - sl82c105_reset_host(dev); -} - -/* - * ATAPI devices can cause the SL82C105 DMA state machine to go gaga. - * Winbond recommend that the DMA state machine is reset prior to - * setting the bus master DMA enable bit. - * - * The generic IDE core will have disabled the BMEN bit before this - * function is called. - */ -static void sl82c105_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - int reg = 0x44 + drive->dn * 4; - - DBG(("%s(drive:%s)\n", __func__, drive->name)); - - pci_write_config_word(dev, reg, drive->drive_data >> 16); - - sl82c105_reset_host(dev); - ide_dma_start(drive); -} - -static void sl82c105_dma_timeout(ide_drive_t *drive) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - - DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name)); - - sl82c105_reset_host(dev); - ide_dma_timeout(drive); -} - -static int sl82c105_dma_end(ide_drive_t *drive) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - int reg = 0x44 + drive->dn * 4; - int ret; - - DBG(("%s(drive:%s)\n", __func__, drive->name)); - - ret = ide_dma_end(drive); - - pci_write_config_word(dev, reg, drive->drive_data); - - return ret; -} - -/* - * ATA reset will clear the 16 bits mode in the control - * register, we need to reprogram it - */ -static void sl82c105_resetproc(ide_drive_t *drive) -{ - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - u32 val; - - DBG(("sl82c105_resetproc(drive:%s)\n", drive->name)); - - pci_read_config_dword(dev, 0x40, &val); - val |= (CTRL_P1F16 | CTRL_P0F16); - pci_write_config_dword(dev, 0x40, val); -} - -/* - * Return the revision of the Winbond bridge - * which this function is part of. - */ -static u8 sl82c105_bridge_revision(struct pci_dev *dev) -{ - struct pci_dev *bridge; - - /* - * The bridge should be part of the same device, but function 0. - */ - bridge = pci_get_bus_and_slot(dev->bus->number, - PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); - if (!bridge) - return -1; - - /* - * Make sure it is a Winbond 553 and is an ISA bridge. - */ - if (bridge->vendor != PCI_VENDOR_ID_WINBOND || - bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || - bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) { - pci_dev_put(bridge); - return -1; - } - /* - * We need to find function 0's revision, not function 1 - */ - pci_dev_put(bridge); - - return bridge->revision; -} - -/* - * Enable the PCI device - * - * --BenH: It's arch fixup code that should enable channels that - * have not been enabled by firmware. I decided we can still enable - * channel 0 here at least, but channel 1 has to be enabled by - * firmware or arch code. We still set both to 16 bits mode. - */ -static unsigned int init_chipset_sl82c105(struct pci_dev *dev) -{ - u32 val; - - DBG(("init_chipset_sl82c105()\n")); - - pci_read_config_dword(dev, 0x40, &val); - val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; - pci_write_config_dword(dev, 0x40, val); - - return dev->irq; -} - -static const struct ide_port_ops sl82c105_port_ops = { - .set_pio_mode = sl82c105_set_pio_mode, - .set_dma_mode = sl82c105_set_dma_mode, - .resetproc = sl82c105_resetproc, -}; - -static const struct ide_dma_ops sl82c105_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = sl82c105_dma_start, - .dma_end = sl82c105_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = sl82c105_dma_lost_irq, - .dma_timeout = sl82c105_dma_timeout, -}; - -static const struct ide_port_info sl82c105_chipset __devinitdata = { - .name = DRV_NAME, - .init_chipset = init_chipset_sl82c105, - .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, - .port_ops = &sl82c105_port_ops, - .dma_ops = &sl82c105_dma_ops, - .host_flags = IDE_HFLAG_IO_32BIT | - IDE_HFLAG_UNMASK_IRQS | -/* FIXME: check for Compatibility mode in generic IDE PCI code */ -#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT) - IDE_HFLAG_FORCE_LEGACY_IRQS | -#endif - IDE_HFLAG_SERIALIZE_DMA | - IDE_HFLAG_NO_AUTODMA, - .pio_mask = ATA_PIO5, - .mwdma_mask = ATA_MWDMA2, -}; - -static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct ide_port_info d = sl82c105_chipset; - u8 rev = sl82c105_bridge_revision(dev); - - if (rev <= 5) { - /* - * Never ever EVER under any circumstances enable - * DMA when the bridge is this old. - */ - printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge " - "revision %d, BM-DMA disabled\n", rev); - d.dma_ops = NULL; - d.mwdma_mask = 0; - d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA; - } - - return ide_pci_init_one(dev, &d, NULL); -} - -static const struct pci_device_id sl82c105_pci_tbl[] = { - { PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl); - -static struct pci_driver sl82c105_pci_driver = { - .name = "W82C105_IDE", - .id_table = sl82c105_pci_tbl, - .probe = sl82c105_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init sl82c105_ide_init(void) -{ - return ide_pci_register_driver(&sl82c105_pci_driver); -} - -static void __exit sl82c105_ide_exit(void) -{ - pci_unregister_driver(&sl82c105_pci_driver); -} - -module_init(sl82c105_ide_init); -module_exit(sl82c105_ide_exit); - -MODULE_DESCRIPTION("PCI driver module for W82C105 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c deleted file mode 100644 index 0f759e4..0000000 --- a/drivers/ide/pci/slc90e66.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2000-2002 Andre Hedrick - * Copyright (C) 2006-2007 MontaVista Software, Inc. - * - * This is a look-alike variation of the ICH0 PIIX4 Ultra-66, - * but this keeps the ISA-Bridge and slots alive. - * - */ - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "slc90e66" - -static DEFINE_SPINLOCK(slc90e66_lock); - -static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - int is_slave = drive->dn & 1; - int master_port = hwif->channel ? 0x42 : 0x40; - int slave_port = 0x44; - unsigned long flags; - u16 master_data; - u8 slave_data; - int control = 0; - /* ISP RTC */ - static const u8 timings[][2] = { - { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - spin_lock_irqsave(&slc90e66_lock, flags); - pci_read_config_word(dev, master_port, &master_data); - - if (pio > 1) - control |= 1; /* Programmable timing on */ - if (drive->media == ide_disk) - control |= 4; /* Prefetch, post write */ - if (pio > 2) - control |= 2; /* IORDY */ - if (is_slave) { - master_data |= 0x4000; - master_data &= ~0x0070; - if (pio > 1) { - /* Set PPE, IE and TIME */ - master_data |= control << 4; - } - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data &= hwif->channel ? 0x0f : 0xf0; - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << - (hwif->channel ? 4 : 0); - } else { - master_data &= ~0x3307; - if (pio > 1) { - /* enable PPE, IE and TIME */ - master_data |= control; - } - master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); - } - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&slc90e66_lock, flags); -} - -static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 maslave = hwif->channel ? 0x42 : 0x40; - int sitre = 0, a_speed = 7 << (drive->dn * 4); - int u_speed = 0, u_flag = 1 << drive->dn; - u16 reg4042, reg44, reg48, reg4a; - - pci_read_config_word(dev, maslave, ®4042); - sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_word(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - - if (speed >= XFER_UDMA_0) { - u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4); - - if (!(reg48 & u_flag)) - pci_write_config_word(dev, 0x48, reg48|u_flag); - /* FIXME: (reg4a & a_speed) ? */ - if ((reg4a & u_speed) != u_speed) { - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - pci_read_config_word(dev, 0x4a, ®4a); - pci_write_config_word(dev, 0x4a, reg4a|u_speed); - } - } else { - const u8 mwdma_to_pio[] = { 0, 3, 4 }; - u8 pio; - - if (reg48 & u_flag) - pci_write_config_word(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - - if (speed >= XFER_MW_DMA_0) - pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; - else - pio = 2; /* only SWDMA2 is allowed */ - - slc90e66_set_pio_mode(drive, pio); - } -} - -static u8 slc90e66_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02; - - pci_read_config_byte(dev, 0x47, ®47); - - /* bit[0(1)]: 0:80, 1:40 */ - return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; -} - -static const struct ide_port_ops slc90e66_port_ops = { - .set_pio_mode = slc90e66_set_pio_mode, - .set_dma_mode = slc90e66_set_dma_mode, - .cable_detect = slc90e66_cable_detect, -}; - -static const struct ide_port_info slc90e66_chipset __devinitdata = { - .name = DRV_NAME, - .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} }, - .port_ops = &slc90e66_port_ops, - .host_flags = IDE_HFLAG_LEGACY_IRQS, - .pio_mask = ATA_PIO4, - .swdma_mask = ATA_SWDMA2_ONLY, - .mwdma_mask = ATA_MWDMA12_ONLY, - .udma_mask = ATA_UDMA4, -}; - -static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &slc90e66_chipset, NULL); -} - -static const struct pci_device_id slc90e66_pci_tbl[] = { - { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl); - -static struct pci_driver slc90e66_pci_driver = { - .name = "SLC90e66_IDE", - .id_table = slc90e66_pci_tbl, - .probe = slc90e66_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init slc90e66_ide_init(void) -{ - return ide_pci_register_driver(&slc90e66_pci_driver); -} - -static void __exit slc90e66_ide_exit(void) -{ - pci_unregister_driver(&slc90e66_pci_driver); -} - -module_init(slc90e66_ide_init); -module_exit(slc90e66_ide_exit); - -MODULE_AUTHOR("Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c deleted file mode 100644 index 93e2cce..0000000 --- a/drivers/ide/pci/tc86c001.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2002 Toshiba Corporation - * Copyright (C) 2005-2006 MontaVista Software, Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include - -#define DRV_NAME "tc86c001" - -static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00); - u16 mode, scr = inw(scr_port); - - switch (speed) { - case XFER_UDMA_4: mode = 0x00c0; break; - case XFER_UDMA_3: mode = 0x00b0; break; - case XFER_UDMA_2: mode = 0x00a0; break; - case XFER_UDMA_1: mode = 0x0090; break; - case XFER_UDMA_0: mode = 0x0080; break; - case XFER_MW_DMA_2: mode = 0x0070; break; - case XFER_MW_DMA_1: mode = 0x0060; break; - case XFER_MW_DMA_0: mode = 0x0050; break; - case XFER_PIO_4: mode = 0x0400; break; - case XFER_PIO_3: mode = 0x0300; break; - case XFER_PIO_2: mode = 0x0200; break; - case XFER_PIO_1: mode = 0x0100; break; - case XFER_PIO_0: - default: mode = 0x0000; break; - } - - scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f; - scr |= mode; - outw(scr, scr_port); -} - -static void tc86c001_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - tc86c001_set_mode(drive, XFER_PIO_0 + pio); -} - -/* - * HACKITY HACK - * - * This is a workaround for the limitation 5 of the TC86C001 IDE controller: - * if a DMA transfer terminates prematurely, the controller leaves the device's - * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or - * set the interrupt bit in the DMA status register), thus no PCI interrupt - * will occur until a DMA transfer has been successfully completed. - * - * We work around this by initiating dummy, zero-length DMA transfer on - * a DMA timeout expiration. I found no better way to do this with the current - * IDE core than to temporarily replace a higher level driver's timer expiry - * handler with our own backing up to that handler in case our recovery fails. - */ -static int tc86c001_timer_expiry(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - ide_expiry_t *expiry = ide_get_hwifdata(hwif); - ide_hwgroup_t *hwgroup = HWGROUP(drive); - u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - - /* Restore a higher level driver's expiry handler first. */ - hwgroup->expiry = expiry; - - if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */ - unsigned long sc_base = hwif->config_data; - unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); - u8 dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); - - printk(KERN_WARNING "%s: DMA interrupt possibly stuck, " - "attempting recovery...\n", drive->name); - - /* Stop DMA */ - outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD); - - /* Setup the dummy DMA transfer */ - outw(0, sc_base + 0x0a); /* Sector Count */ - outw(0, twcr_port); /* Transfer Word Count 1 or 2 */ - - /* Start the dummy DMA transfer */ - - /* clear R_OR_WCTR for write */ - outb(0x00, hwif->dma_base + ATA_DMA_CMD); - /* set START_STOPBM */ - outb(0x01, hwif->dma_base + ATA_DMA_CMD); - - /* - * If an interrupt was pending, it should come thru shortly. - * If not, a higher level driver's expiry handler should - * eventually cause some kind of recovery from the DMA stall. - */ - return WAIT_MIN_SLEEP; - } - - /* Chain to the restored expiry handler if DMA wasn't active. */ - if (likely(expiry != NULL)) - return expiry(drive); - - /* If there was no handler, "emulate" that for ide_timer_expiry()... */ - return -1; -} - -static void tc86c001_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned long sc_base = hwif->config_data; - unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); - unsigned long nsectors = hwgroup->rq->nr_sectors; - - /* - * We have to manually load the sector count and size into - * the appropriate system control registers for DMA to work - * with LBA48 and ATAPI devices... - */ - outw(nsectors, sc_base + 0x0a); /* Sector Count */ - outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */ - - /* Install our timeout expiry hook, saving the current handler... */ - ide_set_hwifdata(hwif, hwgroup->expiry); - hwgroup->expiry = &tc86c001_timer_expiry; - - ide_dma_start(drive); -} - -static u8 tc86c001_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long sc_base = pci_resource_start(dev, 5); - u16 scr1 = inw(sc_base + 0x00); - - /* - * System Control 1 Register bit 13 (PDIAGN): - * 0=80-pin cable, 1=40-pin cable - */ - return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; -} - -static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long sc_base = pci_resource_start(dev, 5); - u16 scr1 = inw(sc_base + 0x00); - - /* System Control 1 Register bit 15 (Soft Reset) set */ - outw(scr1 | 0x8000, sc_base + 0x00); - - /* System Control 1 Register bit 14 (FIFO Reset) set */ - outw(scr1 | 0x4000, sc_base + 0x00); - - /* System Control 1 Register: reset clear */ - outw(scr1 & ~0xc000, sc_base + 0x00); - - /* Store the system control register base for convenience... */ - hwif->config_data = sc_base; - - if (!hwif->dma_base) - return; - - /* - * Sector Count Control Register bits 0 and 1 set: - * software sets Sector Count Register for master and slave device - */ - outw(0x0003, sc_base + 0x0c); - - /* Sector Count Register limit */ - hwif->rqsize = 0xffff; -} - -static const struct ide_port_ops tc86c001_port_ops = { - .set_pio_mode = tc86c001_set_pio_mode, - .set_dma_mode = tc86c001_set_mode, - .cable_detect = tc86c001_cable_detect, -}; - -static const struct ide_dma_ops tc86c001_dma_ops = { - .dma_host_set = ide_dma_host_set, - .dma_setup = ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = tc86c001_dma_start, - .dma_end = ide_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_port_info tc86c001_chipset __devinitdata = { - .name = DRV_NAME, - .init_hwif = init_hwif_tc86c001, - .port_ops = &tc86c001_port_ops, - .dma_ops = &tc86c001_dma_ops, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA4, -}; - -static int __devinit tc86c001_init_one(struct pci_dev *dev, - const struct pci_device_id *id) -{ - int rc; - - rc = pci_enable_device(dev); - if (rc) - goto out; - - rc = pci_request_region(dev, 5, DRV_NAME); - if (rc) { - printk(KERN_ERR DRV_NAME ": system control regs already in use"); - goto out_disable; - } - - rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL); - if (rc) - goto out_release; - - goto out; - -out_release: - pci_release_region(dev, 5); -out_disable: - pci_disable_device(dev); -out: - return rc; -} - -static void __devexit tc86c001_remove(struct pci_dev *dev) -{ - ide_pci_remove(dev); - pci_release_region(dev, 5); - pci_disable_device(dev); -} - -static const struct pci_device_id tc86c001_pci_tbl[] = { - { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl); - -static struct pci_driver tc86c001_pci_driver = { - .name = "TC86C001", - .id_table = tc86c001_pci_tbl, - .probe = tc86c001_init_one, - .remove = __devexit_p(tc86c001_remove), -}; - -static int __init tc86c001_ide_init(void) -{ - return ide_pci_register_driver(&tc86c001_pci_driver); -} - -static void __exit tc86c001_ide_exit(void) -{ - pci_unregister_driver(&tc86c001_pci_driver); -} - -module_init(tc86c001_ide_init); -module_exit(tc86c001_ide_exit); - -MODULE_AUTHOR("MontaVista Software, Inc. "); -MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c deleted file mode 100644 index b6ff403..0000000 --- a/drivers/ide/pci/triflex.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * IDE Chipset driver for the Compaq TriFlex IDE controller. - * - * Known to work with the Compaq Workstation 5x00 series. - * - * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. - * Author: Torben Mathiasen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Loosely based on the piix & svwks drivers. - * - * Documentation: - * Not publically available. - */ - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "triflex" - -static void triflex_set_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u32 triflex_timings = 0; - u16 timing = 0; - u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1; - - pci_read_config_dword(dev, channel_offset, &triflex_timings); - - switch(speed) { - case XFER_MW_DMA_2: - timing = 0x0103; - break; - case XFER_MW_DMA_1: - timing = 0x0203; - break; - case XFER_MW_DMA_0: - timing = 0x0808; - break; - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - timing = 0x0f0f; - break; - case XFER_PIO_4: - timing = 0x0202; - break; - case XFER_PIO_3: - timing = 0x0204; - break; - case XFER_PIO_2: - timing = 0x0404; - break; - case XFER_PIO_1: - timing = 0x0508; - break; - case XFER_PIO_0: - timing = 0x0808; - break; - } - - triflex_timings &= ~(0xFFFF << (16 * unit)); - triflex_timings |= (timing << (16 * unit)); - - pci_write_config_dword(dev, channel_offset, triflex_timings); -} - -static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - triflex_set_mode(drive, XFER_PIO_0 + pio); -} - -static const struct ide_port_ops triflex_port_ops = { - .set_pio_mode = triflex_set_pio_mode, - .set_dma_mode = triflex_set_mode, -}; - -static const struct ide_port_info triflex_device __devinitdata = { - .name = DRV_NAME, - .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, - .port_ops = &triflex_port_ops, - .pio_mask = ATA_PIO4, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, -}; - -static int __devinit triflex_init_one(struct pci_dev *dev, - const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &triflex_device, NULL); -} - -static const struct pci_device_id triflex_pci_tbl[] = { - { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, triflex_pci_tbl); - -static struct pci_driver triflex_pci_driver = { - .name = "TRIFLEX_IDE", - .id_table = triflex_pci_tbl, - .probe = triflex_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init triflex_ide_init(void) -{ - return ide_pci_register_driver(&triflex_pci_driver); -} - -static void __exit triflex_ide_exit(void) -{ - pci_unregister_driver(&triflex_pci_driver); -} - -module_init(triflex_ide_init); -module_exit(triflex_ide_exit); - -MODULE_AUTHOR("Torben Mathiasen"); -MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE"); -MODULE_LICENSE("GPL"); - - diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c deleted file mode 100644 index 75ea615..0000000 --- a/drivers/ide/pci/trm290.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (c) 1997-1998 Mark Lord - * Copyright (c) 2007 MontaVista Software, Inc. - * - * May be copied or modified under the terms of the GNU General Public License - * - * June 22, 2004 - get rid of check_region - * - Jesper Juhl - * - */ - -/* - * This module provides support for the bus-master IDE DMA function - * of the Tekram TRM290 chip, used on a variety of PCI IDE add-on boards, - * including a "Precision Instruments" board. The TRM290 pre-dates - * the sff-8038 standard (ide-dma.c) by a few months, and differs - * significantly enough to warrant separate routines for some functions, - * while re-using others from ide-dma.c. - * - * EXPERIMENTAL! It works for me (a sample of one). - * - * Works reliably for me in DMA mode (READs only), - * DMA WRITEs are disabled by default (see #define below); - * - * DMA is not enabled automatically for this chipset, - * but can be turned on manually (with "hdparm -d1") at run time. - * - * I need volunteers with "spare" drives for further testing - * and development, and maybe to help figure out the peculiarities. - * Even knowing the registers (below), some things behave strangely. - */ - -#define TRM290_NO_DMA_WRITES /* DMA writes seem unreliable sometimes */ - -/* - * TRM-290 PCI-IDE2 Bus Master Chip - * ================================ - * The configuration registers are addressed in normal I/O port space - * and are used as follows: - * - * trm290_base depends on jumper settings, and is probed for by ide-dma.c - * - * trm290_base+2 when WRITTEN: chiptest register (byte, write-only) - * bit7 must always be written as "1" - * bits6-2 undefined - * bit1 1=legacy_compatible_mode, 0=native_pci_mode - * bit0 1=test_mode, 0=normal(default) - * - * trm290_base+2 when READ: status register (byte, read-only) - * bits7-2 undefined - * bit1 channel0 busmaster interrupt status 0=none, 1=asserted - * bit0 channel0 interrupt status 0=none, 1=asserted - * - * trm290_base+3 Interrupt mask register - * bits7-5 undefined - * bit4 legacy_header: 1=present, 0=absent - * bit3 channel1 busmaster interrupt status 0=none, 1=asserted (read only) - * bit2 channel1 interrupt status 0=none, 1=asserted (read only) - * bit1 channel1 interrupt mask: 1=masked, 0=unmasked(default) - * bit0 channel0 interrupt mask: 1=masked, 0=unmasked(default) - * - * trm290_base+1 "CPR" Config Pointer Register (byte) - * bit7 1=autoincrement CPR bits 2-0 after each access of CDR - * bit6 1=min. 1 wait-state posted write cycle (default), 0=0 wait-state - * bit5 0=enabled master burst access (default), 1=disable (write only) - * bit4 PCI DEVSEL# timing select: 1=medium(default), 0=fast - * bit3 0=primary IDE channel, 1=secondary IDE channel - * bits2-0 register index for accesses through CDR port - * - * trm290_base+0 "CDR" Config Data Register (word) - * two sets of seven config registers, - * selected by CPR bit 3 (channel) and CPR bits 2-0 (index 0 to 6), - * each index defined below: - * - * Index-0 Base address register for command block (word) - * defaults: 0x1f0 for primary, 0x170 for secondary - * - * Index-1 general config register (byte) - * bit7 1=DMA enable, 0=DMA disable - * bit6 1=activate IDE_RESET, 0=no action (default) - * bit5 1=enable IORDY, 0=disable IORDY (default) - * bit4 0=16-bit data port(default), 1=8-bit (XT) data port - * bit3 interrupt polarity: 1=active_low, 0=active_high(default) - * bit2 power-saving-mode(?): 1=enable, 0=disable(default) (write only) - * bit1 bus_master_mode(?): 1=enable, 0=disable(default) - * bit0 enable_io_ports: 1=enable(default), 0=disable - * - * Index-2 read-ahead counter preload bits 0-7 (byte, write only) - * bits7-0 bits7-0 of readahead count - * - * Index-3 read-ahead config register (byte, write only) - * bit7 1=enable_readahead, 0=disable_readahead(default) - * bit6 1=clear_FIFO, 0=no_action - * bit5 undefined - * bit4 mode4 timing control: 1=enable, 0=disable(default) - * bit3 undefined - * bit2 undefined - * bits1-0 bits9-8 of read-ahead count - * - * Index-4 base address register for control block (word) - * defaults: 0x3f6 for primary, 0x376 for secondary - * - * Index-5 data port timings (shared by both drives) (byte) - * standard PCI "clk" (clock) counts, default value = 0xf5 - * - * bits7-6 setup time: 00=1clk, 01=2clk, 10=3clk, 11=4clk - * bits5-3 hold time: 000=1clk, 001=2clk, 010=3clk, - * 011=4clk, 100=5clk, 101=6clk, - * 110=8clk, 111=12clk - * bits2-0 active time: 000=2clk, 001=3clk, 010=4clk, - * 011=5clk, 100=6clk, 101=8clk, - * 110=12clk, 111=16clk - * - * Index-6 command/control port timings (shared by both drives) (byte) - * same layout as Index-5, default value = 0xde - * - * Suggested CDR programming for PIO mode0 (600ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0xf5,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0xf5,0xde ; secondary - * - * Suggested CDR programming for PIO mode3 (180ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0x09,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0x09,0xde ; secondary - * - * Suggested CDR programming for PIO mode4 (120ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0x00,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0x00,0xde ; secondary - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "trm290" - -static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma) -{ - ide_hwif_t *hwif = HWIF(drive); - u16 reg = 0; - unsigned long flags; - - /* select PIO or DMA */ - reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82); - - local_irq_save(flags); - - if (reg != hwif->select_data) { - hwif->select_data = reg; - /* set PIO/DMA */ - outb(0x51 | (hwif->channel << 3), hwif->config_data + 1); - outw(reg & 0xff, hwif->config_data); - } - - /* enable IRQ if not probing */ - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - reg = inw(hwif->config_data + 3); - reg &= 0x13; - reg &= ~(1 << hwif->channel); - outw(reg, hwif->config_data + 3); - } - - local_irq_restore(flags); -} - -static void trm290_selectproc (ide_drive_t *drive) -{ - trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA)); -} - -static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command) -{ - ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL); -} - -static int trm290_dma_setup(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct request *rq = hwif->hwgroup->rq; - unsigned int count, rw; - - if (rq_data_dir(rq)) { -#ifdef TRM290_NO_DMA_WRITES - /* always use PIO for writes */ - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; -#endif - rw = 1; - } else - rw = 2; - - if (!(count = ide_build_dmatable(drive, rq))) { - /* try PIO instead of DMA */ - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; - } - /* select DMA xfer */ - trm290_prepare_drive(drive, 1); - outl(hwif->dmatable_dma | rw, hwif->dma_base); - drive->waiting_for_dma = 1; - /* start DMA */ - outw(count * 2 - 1, hwif->dma_base + 2); - return 0; -} - -static void trm290_dma_start(ide_drive_t *drive) -{ -} - -static int trm290_dma_end(ide_drive_t *drive) -{ - u16 status; - - drive->waiting_for_dma = 0; - /* purge DMA mappings */ - ide_destroy_dmatable(drive); - status = inw(HWIF(drive)->dma_base + 2); - return status != 0x00ff; -} - -static int trm290_dma_test_irq(ide_drive_t *drive) -{ - u16 status; - - status = inw(HWIF(drive)->dma_base + 2); - return status == 0x00ff; -} - -static void trm290_dma_host_set(ide_drive_t *drive, int on) -{ -} - -static void __devinit init_hwif_trm290(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned int cfg_base = pci_resource_start(dev, 4); - unsigned long flags; - u8 reg = 0; - - if ((dev->class & 5) && cfg_base) - printk(KERN_INFO DRV_NAME " %s: chip", pci_name(dev)); - else { - cfg_base = 0x3df0; - printk(KERN_INFO DRV_NAME " %s: using default", pci_name(dev)); - } - printk(KERN_CONT " config base at 0x%04x\n", cfg_base); - hwif->config_data = cfg_base; - hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0); - - printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", - hwif->name, hwif->dma_base, hwif->dma_base + 3); - - if (ide_allocate_dma_engine(hwif)) - return; - - local_irq_save(flags); - /* put config reg into first byte of hwif->select_data */ - outb(0x51 | (hwif->channel << 3), hwif->config_data + 1); - /* select PIO as default */ - hwif->select_data = 0x21; - outb(hwif->select_data, hwif->config_data); - /* get IRQ info */ - reg = inb(hwif->config_data + 3); - /* mask IRQs for both ports */ - reg = (reg & 0x10) | 0x03; - outb(reg, hwif->config_data + 3); - local_irq_restore(flags); - - if (reg & 0x10) - /* legacy mode */ - hwif->irq = hwif->channel ? 15 : 14; - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - /* sharing IRQ with mate */ - hwif->irq = hwif->mate->irq; - -#if 1 - { - /* - * My trm290-based card doesn't seem to work with all possible values - * for the control basereg, so this kludge ensures that we use only - * values that are known to work. Ugh. -ml - */ - u16 new, old, compat = hwif->channel ? 0x374 : 0x3f4; - static u16 next_offset = 0; - u8 old_mask; - - outb(0x54 | (hwif->channel << 3), hwif->config_data + 1); - old = inw(hwif->config_data); - old &= ~1; - old_mask = inb(old + 2); - if (old != compat && old_mask == 0xff) { - /* leave lower 10 bits untouched */ - compat += (next_offset += 0x400); - hwif->io_ports.ctl_addr = compat + 2; - outw(compat | 1, hwif->config_data); - new = inw(hwif->config_data); - printk(KERN_INFO "%s: control basereg workaround: " - "old=0x%04x, new=0x%04x\n", - hwif->name, old, new & ~1); - } - } -#endif -} - -static const struct ide_port_ops trm290_port_ops = { - .selectproc = trm290_selectproc, -}; - -static struct ide_dma_ops trm290_dma_ops = { - .dma_host_set = trm290_dma_host_set, - .dma_setup = trm290_dma_setup, - .dma_exec_cmd = trm290_dma_exec_cmd, - .dma_start = trm290_dma_start, - .dma_end = trm290_dma_end, - .dma_test_irq = trm290_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, -}; - -static const struct ide_port_info trm290_chipset __devinitdata = { - .name = DRV_NAME, - .init_hwif = init_hwif_trm290, - .chipset = ide_trm290, - .port_ops = &trm290_port_ops, - .dma_ops = &trm290_dma_ops, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | -#if 0 /* play it safe for now */ - IDE_HFLAG_TRUST_BIOS_FOR_DMA | -#endif - IDE_HFLAG_NO_AUTODMA | - IDE_HFLAG_NO_LBA48, -}; - -static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &trm290_chipset, NULL); -} - -static const struct pci_device_id trm290_pci_tbl[] = { - { PCI_VDEVICE(TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290), 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, trm290_pci_tbl); - -static struct pci_driver trm290_pci_driver = { - .name = "TRM290_IDE", - .id_table = trm290_pci_tbl, - .probe = trm290_init_one, - .remove = ide_pci_remove, -}; - -static int __init trm290_ide_init(void) -{ - return ide_pci_register_driver(&trm290_pci_driver); -} - -static void __exit trm290_ide_exit(void) -{ - pci_unregister_driver(&trm290_pci_driver); -} - -module_init(trm290_ide_init); -module_exit(trm290_ide_exit); - -MODULE_AUTHOR("Mark Lord"); -MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c deleted file mode 100644 index 2a812d3..0000000 --- a/drivers/ide/pci/via82cxxx.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - * VIA IDE driver for Linux. Supported southbridges: - * - * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, - * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, - * vt8235, vt8237, vt8237a - * - * Copyright (c) 2000-2002 Vojtech Pavlik - * Copyright (c) 2007 Bartlomiej Zolnierkiewicz - * - * Based on the work of: - * Michel Aubry - * Jeff Garzik - * Andre Hedrick - * - * Documentation: - * Obsolete device documentation publically available from via.com.tw - * Current device documentation available under NDA only - */ - -/* - * 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. - */ - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_PPC_CHRP -#include -#endif - -#define DRV_NAME "via82cxxx" - -#define VIA_IDE_ENABLE 0x40 -#define VIA_IDE_CONFIG 0x41 -#define VIA_FIFO_CONFIG 0x43 -#define VIA_MISC_1 0x44 -#define VIA_MISC_2 0x45 -#define VIA_MISC_3 0x46 -#define VIA_DRIVE_TIMING 0x48 -#define VIA_8BIT_TIMING 0x4e -#define VIA_ADDRESS_SETUP 0x4c -#define VIA_UDMA_TIMING 0x50 - -#define VIA_BAD_PREQ 0x01 /* Crashes if PREQ# till DDACK# set */ -#define VIA_BAD_CLK66 0x02 /* 66 MHz clock doesn't work correctly */ -#define VIA_SET_FIFO 0x04 /* Needs to have FIFO split set */ -#define VIA_NO_UNMASK 0x08 /* Doesn't work with IRQ unmasking on */ -#define VIA_BAD_ID 0x10 /* Has wrong vendor ID (0x1107) */ -#define VIA_BAD_AST 0x20 /* Don't touch Address Setup Timing */ - -/* - * VIA SouthBridge chips. - */ - -static struct via_isa_bridge { - char *name; - u16 id; - u8 rev_min; - u8 rev_max; - u8 udma_mask; - u8 flags; -} via_isa_bridges[] = { - { "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, - { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, ATA_UDMA5, }, - { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, ATA_UDMA5, }, - { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, ATA_UDMA5, }, - { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, ATA_UDMA5, }, - { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, ATA_UDMA4, }, - { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 }, - { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, ATA_UDMA4, }, - { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO }, - { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO }, - { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, 0x00, VIA_SET_FIFO }, - { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK }, - { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, - { NULL } -}; - -static unsigned int via_clock; -static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" }; - -struct via82cxxx_dev -{ - struct via_isa_bridge *via_config; - unsigned int via_80w; -}; - -/** - * via_set_speed - write timing registers - * @dev: PCI device - * @dn: device - * @timing: IDE timing data to use - * - * via_set_speed writes timing values to the chipset registers - */ - -static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct via82cxxx_dev *vdev = host->host_priv; - u8 t; - - if (~vdev->via_config->flags & VIA_BAD_AST) { - pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); - t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); - pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); - } - - pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)), - ((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1)); - - pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn), - ((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1)); - - switch (vdev->via_config->udma_mask) { - case ATA_UDMA2: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break; - case ATA_UDMA4: t = timing->udma ? (0xe8 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x0f; break; - case ATA_UDMA5: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break; - case ATA_UDMA6: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break; - default: return; - } - - pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t); -} - -/** - * via_set_drive - configure transfer mode - * @drive: Drive to set up - * @speed: desired speed - * - * via_set_drive() computes timing values configures the chipset to - * a desired transfer mode. It also can be called by upper layers. - */ - -static void via_set_drive(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - ide_drive_t *peer = ide_get_pair_dev(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct via82cxxx_dev *vdev = host->host_priv; - struct ide_timing t, p; - unsigned int T, UT; - - T = 1000000000 / via_clock; - - switch (vdev->via_config->udma_mask) { - case ATA_UDMA2: UT = T; break; - case ATA_UDMA4: UT = T/2; break; - case ATA_UDMA5: UT = T/3; break; - case ATA_UDMA6: UT = T/4; break; - default: UT = T; - } - - ide_timing_compute(drive, speed, &t, T, UT); - - if (peer) { - ide_timing_compute(peer, peer->current_speed, &p, T, UT); - ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); - } - - via_set_speed(HWIF(drive), drive->dn, &t); -} - -/** - * via_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * A callback from the upper layers for PIO-only tuning. - */ - -static void via_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - via_set_drive(drive, XFER_PIO_0 + pio); -} - -static struct via_isa_bridge *via_config_find(struct pci_dev **isa) -{ - struct via_isa_bridge *via_config; - - for (via_config = via_isa_bridges; via_config->id; via_config++) - if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA + - !!(via_config->flags & VIA_BAD_ID), - via_config->id, NULL))) { - - if ((*isa)->revision >= via_config->rev_min && - (*isa)->revision <= via_config->rev_max) - break; - pci_dev_put(*isa); - } - - return via_config; -} - -/* - * Check and handle 80-wire cable presence - */ -static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u) -{ - int i; - - switch (vdev->via_config->udma_mask) { - case ATA_UDMA4: - for (i = 24; i >= 0; i -= 8) - if (((u >> (i & 16)) & 8) && - ((u >> i) & 0x20) && - (((u >> i) & 7) < 2)) { - /* - * 2x PCI clock and - * UDMA w/ < 3T/cycle - */ - vdev->via_80w |= (1 << (1 - (i >> 4))); - } - break; - - case ATA_UDMA5: - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || - (((u >> i) & 0x20) && - (((u >> i) & 7) < 4))) { - /* BIOS 80-wire bit or - * UDMA w/ < 60ns/cycle - */ - vdev->via_80w |= (1 << (1 - (i >> 4))); - } - break; - - case ATA_UDMA6: - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || - (((u >> i) & 0x20) && - (((u >> i) & 7) < 6))) { - /* BIOS 80-wire bit or - * UDMA w/ < 60ns/cycle - */ - vdev->via_80w |= (1 << (1 - (i >> 4))); - } - break; - } -} - -/** - * init_chipset_via82cxxx - initialization handler - * @dev: PCI device - * - * The initialization callback. Here we determine the IDE chip type - * and initialize its drive independent registers. - */ - -static unsigned int init_chipset_via82cxxx(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct via82cxxx_dev *vdev = host->host_priv; - struct via_isa_bridge *via_config = vdev->via_config; - u8 t, v; - u32 u; - - /* - * Detect cable and configure Clk66 - */ - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - - via_cable_detect(vdev, u); - - if (via_config->udma_mask == ATA_UDMA4) { - /* Enable Clk66 */ - pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008); - } else if (via_config->flags & VIA_BAD_CLK66) { - /* Would cause trouble on 596a and 686 */ - pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); - } - - /* - * Check whether interfaces are enabled. - */ - - pci_read_config_byte(dev, VIA_IDE_ENABLE, &v); - - /* - * Set up FIFO sizes and thresholds. - */ - - pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t); - - /* Disable PREQ# till DDACK# */ - if (via_config->flags & VIA_BAD_PREQ) { - /* Would crash on 586b rev 41 */ - t &= 0x7f; - } - - /* Fix FIFO split between channels */ - if (via_config->flags & VIA_SET_FIFO) { - t &= (t & 0x9f); - switch (v & 3) { - case 2: t |= 0x00; break; /* 16 on primary */ - case 1: t |= 0x60; break; /* 16 on secondary */ - case 3: t |= 0x20; break; /* 8 pri 8 sec */ - } - } - - pci_write_config_byte(dev, VIA_FIFO_CONFIG, t); - - return 0; -} - -/* - * Cable special cases - */ - -static const struct dmi_system_id cable_dmi_table[] = { - { - .ident = "Acer Ferrari 3400", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."), - DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"), - }, - }, - { } -}; - -static int via_cable_override(struct pci_dev *pdev) -{ - /* Systems by DMI */ - if (dmi_check_system(cable_dmi_table)) - return 1; - - /* Arima W730-K8/Targa Visionary 811/... */ - if (pdev->subsystem_vendor == 0x161F && - pdev->subsystem_device == 0x2032) - return 1; - - return 0; -} - -static u8 via82cxxx_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *pdev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(pdev); - struct via82cxxx_dev *vdev = host->host_priv; - - if (via_cable_override(pdev)) - return ATA_CBL_PATA40_SHORT; - - if ((vdev->via_80w >> hwif->channel) & 1) - return ATA_CBL_PATA80; - else - return ATA_CBL_PATA40; -} - -static const struct ide_port_ops via_port_ops = { - .set_pio_mode = via_set_pio_mode, - .set_dma_mode = via_set_drive, - .cable_detect = via82cxxx_cable_detect, -}; - -static const struct ide_port_info via82cxxx_chipset __devinitdata = { - .name = DRV_NAME, - .init_chipset = init_chipset_via82cxxx, - .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, - .port_ops = &via_port_ops, - .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | - IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_IO_32BIT, - .pio_mask = ATA_PIO5, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, -}; - -static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct pci_dev *isa = NULL; - struct via_isa_bridge *via_config; - struct via82cxxx_dev *vdev; - int rc; - u8 idx = id->driver_data; - struct ide_port_info d; - - d = via82cxxx_chipset; - - /* - * Find the ISA bridge and check we know what it is. - */ - via_config = via_config_find(&isa); - if (!via_config->id) { - printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n", - pci_name(dev)); - return -ENODEV; - } - - /* - * Print the boot message. - */ - printk(KERN_INFO DRV_NAME " %s: VIA %s (rev %02x) IDE %sDMA%s\n", - pci_name(dev), via_config->name, isa->revision, - via_config->udma_mask ? "U" : "MW", - via_dma[via_config->udma_mask ? - (fls(via_config->udma_mask) - 1) : 0]); - - pci_dev_put(isa); - - /* - * Determine system bus clock. - */ - via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000; - - switch (via_clock) { - case 33000: via_clock = 33333; break; - case 37000: via_clock = 37500; break; - case 41000: via_clock = 41666; break; - } - - if (via_clock < 20000 || via_clock > 50000) { - printk(KERN_WARNING DRV_NAME ": User given PCI clock speed " - "impossible (%d), using 33 MHz instead.\n", via_clock); - printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want " - "to assume 80-wire cable.\n"); - via_clock = 33333; - } - - if (idx == 0) - d.host_flags |= IDE_HFLAG_NO_AUTODMA; - else - d.enablebits[1].reg = d.enablebits[0].reg = 0; - - if ((via_config->flags & VIA_NO_UNMASK) == 0) - d.host_flags |= IDE_HFLAG_UNMASK_IRQS; - -#ifdef CONFIG_PPC_CHRP - if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos) - d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; -#endif - - d.udma_mask = via_config->udma_mask; - - vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); - if (!vdev) { - printk(KERN_ERR DRV_NAME " %s: out of memory :(\n", - pci_name(dev)); - return -ENOMEM; - } - - vdev->via_config = via_config; - - rc = ide_pci_init_one(dev, &d, vdev); - if (rc) - kfree(vdev); - - return rc; -} - -static void __devexit via_remove(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct via82cxxx_dev *vdev = host->host_priv; - - ide_pci_remove(dev); - kfree(vdev); -} - -static const struct pci_device_id via_pci_tbl[] = { - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), 0 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), 0 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_CX700_IDE), 0 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), 1 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, via_pci_tbl); - -static struct pci_driver via_pci_driver = { - .name = "VIA_IDE", - .id_table = via_pci_tbl, - .probe = via_init_one, - .remove = __devexit_p(via_remove), - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init via_ide_init(void) -{ - return ide_pci_register_driver(&via_pci_driver); -} - -static void __exit via_ide_exit(void) -{ - pci_unregister_driver(&via_pci_driver); -} - -module_init(via_ide_init); -module_exit(via_ide_exit); - -MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for VIA IDE"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c new file mode 100644 index 0000000..211ae46 --- /dev/null +++ b/drivers/ide/pdc202xx_new.c @@ -0,0 +1,588 @@ +/* + * Promise TX2/TX4/TX2000/133 IDE driver + * + * 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. + * + * Split from: + * linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002 + * Copyright (C) 1998-2002 Andre Hedrick + * Copyright (C) 2005-2007 MontaVista Software, Inc. + * Portions Copyright (C) 1999 Promise Technology, Inc. + * Author: Frank Tiernan (frankt@promise.com) + * Released under terms of General Public License + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_PPC_PMAC +#include +#include +#endif + +#define DRV_NAME "pdc202xx_new" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args) +#else +#define DBG(fmt, args...) +#endif + +static const char *pdc_quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP KA9.1", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP KX13.6", + "QUANTUM FIREBALLP KX20.5", + "QUANTUM FIREBALLP KX27.3", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + +static u8 max_dma_rate(struct pci_dev *pdev) +{ + u8 mode; + + switch(pdev->device) { + case PCI_DEVICE_ID_PROMISE_20277: + case PCI_DEVICE_ID_PROMISE_20276: + case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20269: + mode = 4; + break; + case PCI_DEVICE_ID_PROMISE_20270: + case PCI_DEVICE_ID_PROMISE_20268: + mode = 3; + break; + default: + return 0; + } + + return mode; +} + +/** + * get_indexed_reg - Get indexed register + * @hwif: for the port address + * @index: index of the indexed register + */ +static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) +{ + u8 value; + + outb(index, hwif->dma_base + 1); + value = inb(hwif->dma_base + 3); + + DBG("index[%02X] value[%02X]\n", index, value); + return value; +} + +/** + * set_indexed_reg - Set indexed register + * @hwif: for the port address + * @index: index of the indexed register + */ +static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value) +{ + outb(index, hwif->dma_base + 1); + outb(value, hwif->dma_base + 3); + DBG("index[%02X] value[%02X]\n", index, value); +} + +/* + * ATA Timing Tables based on 133 MHz PLL output clock. + * + * If the PLL outputs 100 MHz clock, the ASIC hardware will set + * the timing registers automatically when "set features" command is + * issued to the device. However, if the PLL output clock is 133 MHz, + * the following tables must be used. + */ +static struct pio_timing { + u8 reg0c, reg0d, reg13; +} pio_timings [] = { + { 0xfb, 0x2b, 0xac }, /* PIO mode 0, IORDY off, Prefetch off */ + { 0x46, 0x29, 0xa4 }, /* PIO mode 1, IORDY off, Prefetch off */ + { 0x23, 0x26, 0x64 }, /* PIO mode 2, IORDY off, Prefetch off */ + { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ + { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ +}; + +static struct mwdma_timing { + u8 reg0e, reg0f; +} mwdma_timings [] = { + { 0xdf, 0x5f }, /* MWDMA mode 0 */ + { 0x6b, 0x27 }, /* MWDMA mode 1 */ + { 0x69, 0x25 }, /* MWDMA mode 2 */ +}; + +static struct udma_timing { + u8 reg10, reg11, reg12; +} udma_timings [] = { + { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ + { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ + { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ + { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ + { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ + { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ + { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ +}; + +static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 adj = (drive->dn & 1) ? 0x08 : 0x00; + + /* + * IDE core issues SETFEATURES_XFER to the drive first (thanks to + * IDE_HFLAG_POST_SET_MODE in ->host_flags). PDC202xx hardware will + * automatically set the timing registers based on 100 MHz PLL output. + * + * As we set up the PLL to output 133 MHz for UltraDMA/133 capable + * chips, we must override the default register settings... + */ + if (max_dma_rate(dev) == 4) { + u8 mode = speed & 0x07; + + if (speed >= XFER_UDMA_0) { + set_indexed_reg(hwif, 0x10 + adj, + udma_timings[mode].reg10); + set_indexed_reg(hwif, 0x11 + adj, + udma_timings[mode].reg11); + set_indexed_reg(hwif, 0x12 + adj, + udma_timings[mode].reg12); + } else { + set_indexed_reg(hwif, 0x0e + adj, + mwdma_timings[mode].reg0e); + set_indexed_reg(hwif, 0x0f + adj, + mwdma_timings[mode].reg0f); + } + } else if (speed == XFER_UDMA_2) { + /* Set tHOLD bit to 0 if using UDMA mode 2 */ + u8 tmp = get_indexed_reg(hwif, 0x10 + adj); + + set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f); + } +} + +static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 adj = (drive->dn & 1) ? 0x08 : 0x00; + + if (max_dma_rate(dev) == 4) { + set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c); + set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d); + set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13); + } +} + +static u8 pdcnew_cable_detect(ide_hwif_t *hwif) +{ + if (get_indexed_reg(hwif, 0x0b) & 0x04) + return ATA_CBL_PATA40; + else + return ATA_CBL_PATA80; +} + +static void pdcnew_quirkproc(ide_drive_t *drive) +{ + const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; + + for (list = pdc_quirk_drives; *list != NULL; list++) + if (strstr(m, *list) != NULL) { + drive->quirk_list = 2; + return; + } + + drive->quirk_list = 0; +} + +static void pdcnew_reset(ide_drive_t *drive) +{ + /* + * Deleted this because it is redundant from the caller. + */ + printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n", + HWIF(drive)->channel ? "Secondary" : "Primary"); +} + +/** + * read_counter - Read the byte count registers + * @dma_base: for the port address + */ +static long read_counter(u32 dma_base) +{ + u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08; + u8 cnt0, cnt1, cnt2, cnt3; + long count = 0, last; + int retry = 3; + + do { + last = count; + + /* Read the current count */ + outb(0x20, pri_dma_base + 0x01); + cnt0 = inb(pri_dma_base + 0x03); + outb(0x21, pri_dma_base + 0x01); + cnt1 = inb(pri_dma_base + 0x03); + outb(0x20, sec_dma_base + 0x01); + cnt2 = inb(sec_dma_base + 0x03); + outb(0x21, sec_dma_base + 0x01); + cnt3 = inb(sec_dma_base + 0x03); + + count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0; + + /* + * The 30-bit decrementing counter is read in 4 pieces. + * Incorrect value may be read when the most significant bytes + * are changing... + */ + } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count)); + + DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n", + cnt0, cnt1, cnt2, cnt3); + + return count; +} + +/** + * detect_pll_input_clock - Detect the PLL input clock in Hz. + * @dma_base: for the port address + * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock. + */ +static long detect_pll_input_clock(unsigned long dma_base) +{ + struct timeval start_time, end_time; + long start_count, end_count; + long pll_input, usec_elapsed; + u8 scr1; + + start_count = read_counter(dma_base); + do_gettimeofday(&start_time); + + /* Start the test mode */ + outb(0x01, dma_base + 0x01); + scr1 = inb(dma_base + 0x03); + DBG("scr1[%02X]\n", scr1); + outb(scr1 | 0x40, dma_base + 0x03); + + /* Let the counter run for 10 ms. */ + mdelay(10); + + end_count = read_counter(dma_base); + do_gettimeofday(&end_time); + + /* Stop the test mode */ + outb(0x01, dma_base + 0x01); + scr1 = inb(dma_base + 0x03); + DBG("scr1[%02X]\n", scr1); + outb(scr1 & ~0x40, dma_base + 0x03); + + /* + * Calculate the input clock in Hz + * (the clock counter is 30 bit wide and counts down) + */ + usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 + + (end_time.tv_usec - start_time.tv_usec); + pll_input = ((start_count - end_count) & 0x3fffffff) / 10 * + (10000000 / usec_elapsed); + + DBG("start[%ld] end[%ld]\n", start_count, end_count); + + return pll_input; +} + +#ifdef CONFIG_PPC_PMAC +static void apple_kiwi_init(struct pci_dev *pdev) +{ + struct device_node *np = pci_device_to_OF_node(pdev); + u8 conf; + + if (np == NULL || !of_device_is_compatible(np, "kiwi-root")) + return; + + if (pdev->revision >= 0x03) { + /* Setup chip magic config stuff (from darwin) */ + pci_read_config_byte (pdev, 0x40, &conf); + pci_write_config_byte(pdev, 0x40, (conf | 0x01)); + } +} +#endif /* CONFIG_PPC_PMAC */ + +static unsigned int init_chipset_pdcnew(struct pci_dev *dev) +{ + const char *name = DRV_NAME; + unsigned long dma_base = pci_resource_start(dev, 4); + unsigned long sec_dma_base = dma_base + 0x08; + long pll_input, pll_output, ratio; + int f, r; + u8 pll_ctl0, pll_ctl1; + + if (dma_base == 0) + return -EFAULT; + +#ifdef CONFIG_PPC_PMAC + apple_kiwi_init(dev); +#endif + + /* Calculate the required PLL output frequency */ + switch(max_dma_rate(dev)) { + case 4: /* it's 133 MHz for Ultra133 chips */ + pll_output = 133333333; + break; + case 3: /* and 100 MHz for Ultra100 chips */ + default: + pll_output = 100000000; + break; + } + + /* + * Detect PLL input clock. + * On some systems, where PCI bus is running at non-standard clock rate + * (e.g. 25 or 40 MHz), we have to adjust the cycle time. + * PDC20268 and newer chips employ PLL circuit to help correct timing + * registers setting. + */ + pll_input = detect_pll_input_clock(dma_base); + printk(KERN_INFO "%s %s: PLL input clock is %ld kHz\n", + name, pci_name(dev), pll_input / 1000); + + /* Sanity check */ + if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) { + printk(KERN_ERR "%s %s: Bad PLL input clock %ld Hz, giving up!" + "\n", name, pci_name(dev), pll_input); + goto out; + } + +#ifdef DEBUG + DBG("pll_output is %ld Hz\n", pll_output); + + /* Show the current clock value of PLL control register + * (maybe already configured by the BIOS) + */ + outb(0x02, sec_dma_base + 0x01); + pll_ctl0 = inb(sec_dma_base + 0x03); + outb(0x03, sec_dma_base + 0x01); + pll_ctl1 = inb(sec_dma_base + 0x03); + + DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); +#endif + + /* + * Calculate the ratio of F, R and NO + * POUT = (F + 2) / (( R + 2) * NO) + */ + ratio = pll_output / (pll_input / 1000); + if (ratio < 8600L) { /* 8.6x */ + /* Using NO = 0x01, R = 0x0d */ + r = 0x0d; + } else if (ratio < 12900L) { /* 12.9x */ + /* Using NO = 0x01, R = 0x08 */ + r = 0x08; + } else if (ratio < 16100L) { /* 16.1x */ + /* Using NO = 0x01, R = 0x06 */ + r = 0x06; + } else if (ratio < 64000L) { /* 64x */ + r = 0x00; + } else { + /* Invalid ratio */ + printk(KERN_ERR "%s %s: Bad ratio %ld, giving up!\n", + name, pci_name(dev), ratio); + goto out; + } + + f = (ratio * (r + 2)) / 1000 - 2; + + DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio); + + if (unlikely(f < 0 || f > 127)) { + /* Invalid F */ + printk(KERN_ERR "%s %s: F[%d] invalid!\n", + name, pci_name(dev), f); + goto out; + } + + pll_ctl0 = (u8) f; + pll_ctl1 = (u8) r; + + DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); + + outb(0x02, sec_dma_base + 0x01); + outb(pll_ctl0, sec_dma_base + 0x03); + outb(0x03, sec_dma_base + 0x01); + outb(pll_ctl1, sec_dma_base + 0x03); + + /* Wait the PLL circuit to be stable */ + mdelay(30); + +#ifdef DEBUG + /* + * Show the current clock value of PLL control register + */ + outb(0x02, sec_dma_base + 0x01); + pll_ctl0 = inb(sec_dma_base + 0x03); + outb(0x03, sec_dma_base + 0x01); + pll_ctl1 = inb(sec_dma_base + 0x03); + + DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); +#endif + + out: + return dev->irq; +} + +static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) +{ + struct pci_dev *dev2; + + dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1, + PCI_FUNC(dev->devfn))); + + if (dev2 && + dev2->vendor == dev->vendor && + dev2->device == dev->device) { + + if (dev2->irq != dev->irq) { + dev2->irq = dev->irq; + printk(KERN_INFO DRV_NAME " %s: PCI config space " + "interrupt fixed\n", pci_name(dev)); + } + + return dev2; + } + + return NULL; +} + +static const struct ide_port_ops pdcnew_port_ops = { + .set_pio_mode = pdcnew_set_pio_mode, + .set_dma_mode = pdcnew_set_dma_mode, + .quirkproc = pdcnew_quirkproc, + .resetproc = pdcnew_reset, + .cable_detect = pdcnew_cable_detect, +}; + +#define DECLARE_PDCNEW_DEV(udma) \ + { \ + .name = DRV_NAME, \ + .init_chipset = init_chipset_pdcnew, \ + .port_ops = &pdcnew_port_ops, \ + .host_flags = IDE_HFLAG_POST_SET_MODE | \ + IDE_HFLAG_ERROR_STOPS_FIFO | \ + IDE_HFLAG_OFF_BOARD, \ + .pio_mask = ATA_PIO4, \ + .mwdma_mask = ATA_MWDMA2, \ + .udma_mask = udma, \ + } + +static const struct ide_port_info pdcnew_chipsets[] __devinitdata = { + /* 0: PDC202{68,70} */ DECLARE_PDCNEW_DEV(ATA_UDMA5), + /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6), +}; + +/** + * pdc202new_init_one - called when a pdc202xx is found + * @dev: the pdc202new 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 __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data]; + struct pci_dev *bridge = dev->bus->self; + + if (dev->device == PCI_DEVICE_ID_PROMISE_20270 && bridge && + bridge->vendor == PCI_VENDOR_ID_DEC && + bridge->device == PCI_DEVICE_ID_DEC_21150) { + struct pci_dev *dev2; + + if (PCI_SLOT(dev->devfn) & 2) + return -ENODEV; + + dev2 = pdc20270_get_dev2(dev); + + if (dev2) { + int ret = ide_pci_init_two(dev, dev2, d, NULL); + if (ret < 0) + pci_dev_put(dev2); + return ret; + } + } + + if (dev->device == PCI_DEVICE_ID_PROMISE_20276 && bridge && + bridge->vendor == PCI_VENDOR_ID_INTEL && + (bridge->device == PCI_DEVICE_ID_INTEL_I960 || + bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) { + printk(KERN_INFO DRV_NAME " %s: attached to I2O RAID controller," + " skipping\n", pci_name(dev)); + return -ENODEV; + } + + return ide_pci_init_one(dev, d, NULL); +} + +static void __devexit pdc202new_remove(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; + + ide_pci_remove(dev); + pci_dev_put(dev2); +} + +static const struct pci_device_id pdc202new_pci_tbl[] = { + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 0 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 1 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 1 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 1 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 1 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl); + +static struct pci_driver pdc202new_pci_driver = { + .name = "Promise_IDE", + .id_table = pdc202new_pci_tbl, + .probe = pdc202new_init_one, + .remove = __devexit_p(pdc202new_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init pdc202new_ide_init(void) +{ + return ide_pci_register_driver(&pdc202new_pci_driver); +} + +static void __exit pdc202new_ide_exit(void) +{ + pci_unregister_driver(&pdc202new_pci_driver); +} + +module_init(pdc202new_ide_init); +module_exit(pdc202new_ide_exit); + +MODULE_AUTHOR("Andre Hedrick, Frank Tiernan"); +MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c new file mode 100644 index 0000000..799557c --- /dev/null +++ b/drivers/ide/pdc202xx_old.c @@ -0,0 +1,453 @@ +/* + * Copyright (C) 1998-2002 Andre Hedrick + * Copyright (C) 2006-2007 MontaVista Software, Inc. + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * + * Portions Copyright (C) 1999 Promise Technology, Inc. + * Author: Frank Tiernan (frankt@promise.com) + * Released under terms of General Public License + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "pdc202xx_old" + +#define PDC202XX_DEBUG_DRIVE_INFO 0 + +static const char *pdc_quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP KA9.1", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP KX13.6", + "QUANTUM FIREBALLP KX20.5", + "QUANTUM FIREBALLP KX27.3", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + +static void pdc_old_disable_66MHz_clock(ide_hwif_t *); + +static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 drive_pci = 0x60 + (drive->dn << 2); + + u8 AP = 0, BP = 0, CP = 0; + u8 TA = 0, TB = 0, TC = 0; + +#if PDC202XX_DEBUG_DRIVE_INFO + u32 drive_conf = 0; + pci_read_config_dword(dev, drive_pci, &drive_conf); +#endif + + /* + * TODO: do this once per channel + */ + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) + pdc_old_disable_66MHz_clock(hwif); + + pci_read_config_byte(dev, drive_pci, &AP); + pci_read_config_byte(dev, drive_pci + 1, &BP); + pci_read_config_byte(dev, drive_pci + 2, &CP); + + switch(speed) { + case XFER_UDMA_5: + case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; + case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; + case XFER_UDMA_3: + case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; + case XFER_UDMA_0: + case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; + case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; + case XFER_MW_DMA_0: TB = 0xE0; TC = 0x0F; break; + case XFER_PIO_4: TA = 0x01; TB = 0x04; break; + case XFER_PIO_3: TA = 0x02; TB = 0x06; break; + case XFER_PIO_2: TA = 0x03; TB = 0x08; break; + case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; + case XFER_PIO_0: + default: TA = 0x09; TB = 0x13; break; + } + + if (speed < XFER_SW_DMA_0) { + /* + * preserve SYNC_INT / ERDDY_EN bits while clearing + * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A + */ + AP &= ~0x3f; + if (ata_id_iordy_disable(drive->id)) + AP |= 0x20; /* set IORDY_EN bit */ + if (drive->media == ide_disk) + AP |= 0x10; /* set Prefetch_EN bit */ + /* clear PB[4:0] bits of register B */ + BP &= ~0x1f; + pci_write_config_byte(dev, drive_pci, AP | TA); + pci_write_config_byte(dev, drive_pci + 1, BP | TB); + } else { + /* clear MB[2:0] bits of register B */ + BP &= ~0xe0; + /* clear MC[3:0] bits of register C */ + CP &= ~0x0f; + pci_write_config_byte(dev, drive_pci + 1, BP | TB); + pci_write_config_byte(dev, drive_pci + 2, CP | TC); + } + +#if PDC202XX_DEBUG_DRIVE_INFO + printk(KERN_DEBUG "%s: %s drive%d 0x%08x ", + drive->name, ide_xfer_verbose(speed), + drive->dn, drive_conf); + pci_read_config_dword(dev, drive_pci, &drive_conf); + printk("0x%08x\n", drive_conf); +#endif +} + +static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + pdc202xx_set_mode(drive, XFER_PIO_0 + pio); +} + +static u8 pdc2026x_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10); + + pci_read_config_word(dev, 0x50, &CIS); + + return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + +/* + * Set the control register to use the 66MHz system + * clock for UDMA 3/4/5 mode operation when necessary. + * + * FIXME: this register is shared by both channels, some locking is needed + * + * It may also be possible to leave the 66MHz clock on + * and readjust the timing parameters. + */ +static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif) +{ + unsigned long clock_reg = hwif->extra_base + 0x01; + u8 clock = inb(clock_reg); + + outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg); +} + +static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) +{ + unsigned long clock_reg = hwif->extra_base + 0x01; + u8 clock = inb(clock_reg); + + outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); +} + +static void pdc202xx_quirkproc(ide_drive_t *drive) +{ + const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; + + for (list = pdc_quirk_drives; *list != NULL; list++) + if (strstr(m, *list) != NULL) { + drive->quirk_list = 2; + return; + } + + drive->quirk_list = 0; +} + +static void pdc202xx_dma_start(ide_drive_t *drive) +{ + if (drive->current_speed > XFER_UDMA_2) + pdc_old_enable_66MHz_clock(drive->hwif); + if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) { + struct request *rq = HWGROUP(drive)->rq; + ide_hwif_t *hwif = HWIF(drive); + unsigned long high_16 = hwif->extra_base - 16; + unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); + u32 word_count = 0; + u8 clock = inb(high_16 + 0x11); + + outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11); + word_count = (rq->nr_sectors << 8); + word_count = (rq_data_dir(rq) == READ) ? + word_count | 0x05000000 : + word_count | 0x06000000; + outl(word_count, atapi_reg); + } + ide_dma_start(drive); +} + +static int pdc202xx_dma_end(ide_drive_t *drive) +{ + if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) { + ide_hwif_t *hwif = HWIF(drive); + unsigned long high_16 = hwif->extra_base - 16; + unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); + u8 clock = 0; + + outl(0, atapi_reg); /* zero out extra */ + clock = inb(high_16 + 0x11); + outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11); + } + if (drive->current_speed > XFER_UDMA_2) + pdc_old_disable_66MHz_clock(drive->hwif); + return ide_dma_end(drive); +} + +static int pdc202xx_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long high_16 = hwif->extra_base - 16; + u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + u8 sc1d = inb(high_16 + 0x001d); + + if (hwif->channel) { + /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */ + if ((sc1d & 0x50) == 0x50) + goto somebody_else; + else if ((sc1d & 0x40) == 0x40) + return (dma_stat & 4) == 4; + } else { + /* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */ + if ((sc1d & 0x05) == 0x05) + goto somebody_else; + else if ((sc1d & 0x04) == 0x04) + return (dma_stat & 4) == 4; + } +somebody_else: + return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ +} + +static void pdc202xx_reset_host (ide_hwif_t *hwif) +{ + unsigned long high_16 = hwif->extra_base - 16; + u8 udma_speed_flag = inb(high_16 | 0x001f); + + outb(udma_speed_flag | 0x10, high_16 | 0x001f); + mdelay(100); + outb(udma_speed_flag & ~0x10, high_16 | 0x001f); + mdelay(2000); /* 2 seconds ?! */ + + printk(KERN_WARNING "PDC202XX: %s channel reset.\n", + hwif->channel ? "Secondary" : "Primary"); +} + +static void pdc202xx_reset (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *mate = hwif->mate; + + pdc202xx_reset_host(hwif); + pdc202xx_reset_host(mate); + + ide_set_max_pio(drive); +} + +static void pdc202xx_dma_lost_irq(ide_drive_t *drive) +{ + pdc202xx_reset(drive); + ide_dma_lost_irq(drive); +} + +static void pdc202xx_dma_timeout(ide_drive_t *drive) +{ + pdc202xx_reset(drive); + ide_dma_timeout(drive); +} + +static unsigned int init_chipset_pdc202xx(struct pci_dev *dev) +{ + unsigned long dmabase = pci_resource_start(dev, 4); + u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; + + if (dmabase == 0) + goto out; + + udma_speed_flag = inb(dmabase | 0x1f); + primary_mode = inb(dmabase | 0x1a); + secondary_mode = inb(dmabase | 0x1b); + printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \ + "Primary %s Mode " \ + "Secondary %s Mode.\n", pci_name(dev), + (udma_speed_flag & 1) ? "EN" : "DIS", + (primary_mode & 1) ? "MASTER" : "PCI", + (secondary_mode & 1) ? "MASTER" : "PCI" ); + + if (!(udma_speed_flag & 1)) { + printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ", + pci_name(dev), udma_speed_flag, + (udma_speed_flag|1)); + outb(udma_speed_flag | 1, dmabase | 0x1f); + printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN"); + } +out: + return dev->irq; +} + +static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, + const char *name) +{ + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { + u8 irq = 0, irq2 = 0; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + /* 0xbc */ + pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); + if (irq != irq2) { + pci_write_config_byte(dev, + (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ + printk(KERN_INFO "%s %s: PCI config space interrupt " + "mirror fixed\n", name, pci_name(dev)); + } + } +} + +#define IDE_HFLAGS_PDC202XX \ + (IDE_HFLAG_ERROR_STOPS_FIFO | \ + IDE_HFLAG_OFF_BOARD) + +static const struct ide_port_ops pdc20246_port_ops = { + .set_pio_mode = pdc202xx_set_pio_mode, + .set_dma_mode = pdc202xx_set_mode, + .quirkproc = pdc202xx_quirkproc, +}; + +static const struct ide_port_ops pdc2026x_port_ops = { + .set_pio_mode = pdc202xx_set_pio_mode, + .set_dma_mode = pdc202xx_set_mode, + .quirkproc = pdc202xx_quirkproc, + .resetproc = pdc202xx_reset, + .cable_detect = pdc2026x_cable_detect, +}; + +static const struct ide_dma_ops pdc20246_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = ide_dma_end, + .dma_test_irq = pdc202xx_dma_test_irq, + .dma_lost_irq = pdc202xx_dma_lost_irq, + .dma_timeout = pdc202xx_dma_timeout, +}; + +static const struct ide_dma_ops pdc2026x_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = pdc202xx_dma_start, + .dma_end = pdc202xx_dma_end, + .dma_test_irq = pdc202xx_dma_test_irq, + .dma_lost_irq = pdc202xx_dma_lost_irq, + .dma_timeout = pdc202xx_dma_timeout, +}; + +#define DECLARE_PDC2026X_DEV(udma, extra_flags) \ + { \ + .name = DRV_NAME, \ + .init_chipset = init_chipset_pdc202xx, \ + .port_ops = &pdc2026x_port_ops, \ + .dma_ops = &pdc2026x_dma_ops, \ + .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \ + .pio_mask = ATA_PIO4, \ + .mwdma_mask = ATA_MWDMA2, \ + .udma_mask = udma, \ + } + +static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { + { /* 0: PDC20246 */ + .name = DRV_NAME, + .init_chipset = init_chipset_pdc202xx, + .port_ops = &pdc20246_port_ops, + .dma_ops = &pdc20246_dma_ops, + .host_flags = IDE_HFLAGS_PDC202XX, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, + }, + + /* 1: PDC2026{2,3} */ + DECLARE_PDC2026X_DEV(ATA_UDMA4, 0), + /* 2: PDC2026{5,7} */ + DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256), +}; + +/** + * pdc202xx_init_one - called when a PDC202xx is found + * @dev: the pdc202xx 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 __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + const struct ide_port_info *d; + u8 idx = id->driver_data; + + d = &pdc202xx_chipsets[idx]; + + if (idx < 2) + pdc202ata4_fixup_irq(dev, d->name); + + if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) { + struct pci_dev *bridge = dev->bus->self; + + if (bridge && + bridge->vendor == PCI_VENDOR_ID_INTEL && + (bridge->device == PCI_DEVICE_ID_INTEL_I960 || + bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) { + printk(KERN_INFO DRV_NAME " %s: skipping Promise " + "PDC20265 attached to I2O RAID controller\n", + pci_name(dev)); + return -ENODEV; + } + } + + return ide_pci_init_one(dev, d, NULL); +} + +static const struct pci_device_id pdc202xx_pci_tbl[] = { + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 }, + { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl); + +static struct pci_driver pdc202xx_pci_driver = { + .name = "Promise_Old_IDE", + .id_table = pdc202xx_pci_tbl, + .probe = pdc202xx_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init pdc202xx_ide_init(void) +{ + return ide_pci_register_driver(&pdc202xx_pci_driver); +} + +static void __exit pdc202xx_ide_exit(void) +{ + pci_unregister_driver(&pdc202xx_pci_driver); +} + +module_init(pdc202xx_ide_init); +module_exit(pdc202xx_ide_exit); + +MODULE_AUTHOR("Andre Hedrick, Frank Tiernan"); +MODULE_DESCRIPTION("PCI driver module for older Promise IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c new file mode 100644 index 0000000..d63f9fd --- /dev/null +++ b/drivers/ide/piix.c @@ -0,0 +1,480 @@ +/* + * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer + * Copyright (C) 1998-2000 Andre Hedrick + * Copyright (C) 2003 Red Hat Inc + * Copyright (C) 2006-2007 MontaVista Software, Inc. + * + * May be copied or modified under the terms of the GNU General Public License + * + * Documentation: + * + * Publically available from Intel web site. Errata documentation + * is also publically available. As an aide to anyone hacking on this + * driver the list of errata that are relevant is below.going back to + * PIIX4. Older device documentation is now a bit tricky to find. + * + * Errata of note: + * + * Unfixable + * PIIX4 errata #9 - Only on ultra obscure hw + * ICH3 errata #13 - Not observed to affect real hw + * by Intel + * + * Things we must deal with + * PIIX4 errata #10 - BM IDE hang with non UDMA + * (must stop/start dma to recover) + * 440MX errata #15 - As PIIX4 errata #10 + * PIIX4 errata #15 - Must not read control registers + * during a PIO transfer + * 440MX errata #13 - As PIIX4 errata #15 + * ICH2 errata #21 - DMA mode 0 doesn't work right + * ICH0/1 errata #55 - As ICH2 errata #21 + * ICH2 spec c #9 - Extra operations needed to handle + * drive hotswap [NOT YET SUPPORTED] + * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary + * and must be dword aligned + * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3 + * + * Should have been BIOS fixed: + * 450NX: errata #19 - DMA hangs on old 450NX + * 450NX: errata #20 - DMA hangs on old 450NX + * 450NX: errata #25 - Corruption with DMA on old 450NX + * ICH3 errata #15 - IDE deadlock under high load + * (BIOS must set dev 31 fn 0 bit 23) + * ICH3 errata #18 - Don't use native mode + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "piix" + +static int no_piix_dma; + +/** + * piix_set_pio_mode - set host controller for PIO mode + * @drive: drive + * @pio: PIO mode number + * + * Set the interface PIO mode based upon the settings done by AMI BIOS. + */ + +static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + int is_slave = drive->dn & 1; + int master_port = hwif->channel ? 0x42 : 0x40; + int slave_port = 0x44; + unsigned long flags; + u16 master_data; + u8 slave_data; + static DEFINE_SPINLOCK(tune_lock); + int control = 0; + + /* ISP RTC */ + static const u8 timings[][2]= { + { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + /* + * Master vs slave is synchronized above us but the slave register is + * shared by the two hwifs so the corner case of two slave timeouts in + * parallel must be locked. + */ + spin_lock_irqsave(&tune_lock, flags); + pci_read_config_word(dev, master_port, &master_data); + + if (pio > 1) + control |= 1; /* Programmable timing on */ + if (drive->media == ide_disk) + control |= 4; /* Prefetch, post write */ + if (pio > 2) + control |= 2; /* IORDY */ + if (is_slave) { + master_data |= 0x4000; + master_data &= ~0x0070; + if (pio > 1) { + /* Set PPE, IE and TIME */ + master_data |= control << 4; + } + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data &= hwif->channel ? 0x0f : 0xf0; + slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << + (hwif->channel ? 4 : 0); + } else { + master_data &= ~0x3307; + if (pio > 1) { + /* enable PPE, IE and TIME */ + master_data |= control; + } + master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); + } + pci_write_config_word(dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(dev, slave_port, slave_data); + spin_unlock_irqrestore(&tune_lock, flags); +} + +/** + * piix_set_dma_mode - set host controller for DMA mode + * @drive: drive + * @speed: DMA mode + * + * Set a PIIX host controller to the desired DMA mode. This involves + * programming the right timing data into the PCI configuration space. + */ + +static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 maslave = hwif->channel ? 0x42 : 0x40; + int a_speed = 3 << (drive->dn * 4); + int u_flag = 1 << drive->dn; + int v_flag = 0x01 << drive->dn; + int w_flag = 0x10 << drive->dn; + int u_speed = 0; + int sitre; + u16 reg4042, reg4a; + u8 reg48, reg54, reg55; + + pci_read_config_word(dev, maslave, ®4042); + sitre = (reg4042 & 0x4000) ? 1 : 0; + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); + + if (speed >= XFER_UDMA_0) { + u8 udma = speed - XFER_UDMA_0; + + u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4); + + if (!(reg48 & u_flag)) + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + if (speed == XFER_UDMA_5) { + pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + } else { + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } + if ((reg4a & a_speed) != u_speed) + pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); + if (speed > XFER_UDMA_2) { + if (!(reg54 & v_flag)) + pci_write_config_byte(dev, 0x54, reg54 | v_flag); + } else + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + } else { + const u8 mwdma_to_pio[] = { 0, 3, 4 }; + u8 pio; + + if (reg48 & u_flag) + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + if (reg54 & v_flag) + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + if (reg55 & w_flag) + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + + if (speed >= XFER_MW_DMA_0) + pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; + else + pio = 2; /* only SWDMA2 is allowed */ + + piix_set_pio_mode(drive, pio); + } +} + +/** + * init_chipset_ich - set up the ICH chipset + * @dev: PCI device to set up + * + * Initialize the PCI device as required. For the ICH this turns + * out to be nice and simple. + */ + +static unsigned int init_chipset_ich(struct pci_dev *dev) +{ + u32 extra = 0; + + pci_read_config_dword(dev, 0x54, &extra); + pci_write_config_dword(dev, 0x54, extra | 0x400); + + return 0; +} + +/** + * ich_clear_irq - clear BMDMA status + * @drive: IDE drive + * + * ICHx contollers set DMA INTR no matter DMA or PIO. + * BMDMA status might need to be cleared even for + * PIO interrupts to prevent spurious/lost IRQ. + */ +static void ich_clear_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat; + + /* + * ide_dma_end() needs BMDMA status for error checking. + * So, skip clearing BMDMA status here and leave it + * to ide_dma_end() if this is DMA interrupt. + */ + if (drive->waiting_for_dma || hwif->dma_base == 0) + return; + + /* clear the INTR & ERROR bits */ + dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + /* Should we force the bit as well ? */ + outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS); +} + +struct ich_laptop { + u16 device; + u16 subvendor; + u16 subdevice; +}; + +/* + * List of laptops that use short cables rather than 80 wire + */ + +static const struct ich_laptop ich_laptop[] = { + /* devid, subvendor, subdev */ + { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ + { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ + { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ + { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ + { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ + { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ + { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */ + { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ + /* end marker */ + { 0, } +}; + +static u8 piix_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *pdev = to_pci_dev(hwif->dev); + const struct ich_laptop *lap = &ich_laptop[0]; + u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30; + + /* check for specials */ + while (lap->device) { + if (lap->device == pdev->device && + lap->subvendor == pdev->subsystem_vendor && + lap->subdevice == pdev->subsystem_device) { + return ATA_CBL_PATA40_SHORT; + } + lap++; + } + + pci_read_config_byte(pdev, 0x54, ®54h); + + return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; +} + +/** + * init_hwif_piix - fill in the hwif for the PIIX + * @hwif: IDE interface + * + * Set up the ide_hwif_t for the PIIX interface according to the + * capabilities of the hardware. + */ + +static void __devinit init_hwif_piix(ide_hwif_t *hwif) +{ + if (!hwif->dma_base) + return; + + if (no_piix_dma) + hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0; +} + +static const struct ide_port_ops piix_port_ops = { + .set_pio_mode = piix_set_pio_mode, + .set_dma_mode = piix_set_dma_mode, + .cable_detect = piix_cable_detect, +}; + +static const struct ide_port_ops ich_port_ops = { + .set_pio_mode = piix_set_pio_mode, + .set_dma_mode = piix_set_dma_mode, + .clear_irq = ich_clear_irq, + .cable_detect = piix_cable_detect, +}; + +#ifndef CONFIG_IA64 + #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS +#else + #define IDE_HFLAGS_PIIX 0 +#endif + +#define DECLARE_PIIX_DEV(udma) \ + { \ + .name = DRV_NAME, \ + .init_hwif = init_hwif_piix, \ + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ + .port_ops = &piix_port_ops, \ + .host_flags = IDE_HFLAGS_PIIX, \ + .pio_mask = ATA_PIO4, \ + .swdma_mask = ATA_SWDMA2_ONLY, \ + .mwdma_mask = ATA_MWDMA12_ONLY, \ + .udma_mask = udma, \ + } + +#define DECLARE_ICH_DEV(udma) \ + { \ + .name = DRV_NAME, \ + .init_chipset = init_chipset_ich, \ + .init_hwif = init_hwif_piix, \ + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ + .port_ops = &ich_port_ops, \ + .host_flags = IDE_HFLAGS_PIIX, \ + .pio_mask = ATA_PIO4, \ + .swdma_mask = ATA_SWDMA2_ONLY, \ + .mwdma_mask = ATA_MWDMA12_ONLY, \ + .udma_mask = udma, \ + } + +static const struct ide_port_info piix_pci_info[] __devinitdata = { + /* 0: MPIIX */ + { /* + * MPIIX actually has only a single IDE channel mapped to + * the primary or secondary ports depending on the value + * of the bit 14 of the IDETIM register at offset 0x6c + */ + .name = DRV_NAME, + .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}}, + .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA | + IDE_HFLAGS_PIIX, + .pio_mask = ATA_PIO4, + /* This is a painful system best to let it self tune for now */ + }, + /* 1: PIIXa/PIIXb/PIIX3 */ + DECLARE_PIIX_DEV(0x00), /* no udma */ + /* 2: PIIX4 */ + DECLARE_PIIX_DEV(ATA_UDMA2), + /* 3: ICH0 */ + DECLARE_ICH_DEV(ATA_UDMA2), + /* 4: ICH */ + DECLARE_ICH_DEV(ATA_UDMA4), + /* 5: PIIX4 */ + DECLARE_PIIX_DEV(ATA_UDMA4), + /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */ + DECLARE_ICH_DEV(ATA_UDMA5), +}; + +/** + * piix_init_one - called when a PIIX is found + * @dev: the piix 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 __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL); +} + +/** + * piix_check_450nx - Check for problem 450NX setup + * + * Check for the present of 450NX errata #19 and errata #25. If + * they are found, disable use of DMA IDE + */ + +static void __devinit piix_check_450nx(void) +{ + struct pci_dev *pdev = NULL; + u16 cfg; + while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL) + { + /* Look for 450NX PXB. Check for problem configurations + A PCI quirk checks bit 6 already */ + pci_read_config_word(pdev, 0x41, &cfg); + /* Only on the original revision: IDE DMA can hang */ + if (pdev->revision == 0x00) + no_piix_dma = 1; + /* On all revisions below 5 PXB bus lock must be disabled for IDE */ + else if (cfg & (1<<14) && pdev->revision < 5) + no_piix_dma = 2; + } + if(no_piix_dma) + printk(KERN_WARNING DRV_NAME ": 450NX errata present, disabling IDE DMA.\n"); + if(no_piix_dma == 2) + printk(KERN_WARNING DRV_NAME ": A BIOS update may resolve this.\n"); +} + +static const struct pci_device_id piix_pci_tbl[] = { + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 1 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 0 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 1 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 2 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 3 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 2 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 4 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 5 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 2 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 6 }, +#ifdef CONFIG_BLK_DEV_IDE_SATA + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 6 }, +#endif + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 6 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, piix_pci_tbl); + +static struct pci_driver piix_pci_driver = { + .name = "PIIX_IDE", + .id_table = piix_pci_tbl, + .probe = piix_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init piix_ide_init(void) +{ + piix_check_450nx(); + return ide_pci_register_driver(&piix_pci_driver); +} + +static void __exit piix_ide_exit(void) +{ + pci_unregister_driver(&piix_pci_driver); +} + +module_init(piix_ide_init); +module_exit(piix_ide_exit); + +MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz"); +MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c new file mode 100644 index 0000000..2e19d62 --- /dev/null +++ b/drivers/ide/pmac.c @@ -0,0 +1,1736 @@ +/* + * Support for IDE interfaces on PowerMacs. + * + * These IDE interfaces are memory-mapped and have a DBDMA channel + * for doing DMA. + * + * Copyright (C) 1998-2003 Paul Mackerras & Ben. Herrenschmidt + * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Some code taken from drivers/ide/ide-dma.c: + * + * Copyright (c) 1995-1998 Mark Lord + * + * TODO: - Use pre-calculated (kauai) timing tables all the time and + * get rid of the "rounded" tables used previously, so we have the + * same table format for all controllers and can then just have one + * big table + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_PPC64 +#include +#endif + +#define DRV_NAME "ide-pmac" + +#undef IDE_PMAC_DEBUG + +#define DMA_WAIT_TIMEOUT 50 + +typedef struct pmac_ide_hwif { + unsigned long regbase; + int irq; + int kind; + int aapl_bus_id; + unsigned mediabay : 1; + unsigned broken_dma : 1; + unsigned broken_dma_warn : 1; + struct device_node* node; + struct macio_dev *mdev; + u32 timings[4]; + volatile u32 __iomem * *kauai_fcr; +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + /* Those fields are duplicating what is in hwif. We currently + * can't use the hwif ones because of some assumptions that are + * beeing done by the generic code about the kind of dma controller + * and format of the dma table. This will have to be fixed though. + */ + volatile struct dbdma_regs __iomem * dma_regs; + struct dbdma_cmd* dma_table_cpu; +#endif + +} pmac_ide_hwif_t; + +enum { + controller_ohare, /* OHare based */ + controller_heathrow, /* Heathrow/Paddington */ + controller_kl_ata3, /* KeyLargo ATA-3 */ + controller_kl_ata4, /* KeyLargo ATA-4 */ + controller_un_ata6, /* UniNorth2 ATA-6 */ + controller_k2_ata6, /* K2 ATA-6 */ + controller_sh_ata6, /* Shasta ATA-6 */ +}; + +static const char* model_name[] = { + "OHare ATA", /* OHare based */ + "Heathrow ATA", /* Heathrow/Paddington */ + "KeyLargo ATA-3", /* KeyLargo ATA-3 (MDMA only) */ + "KeyLargo ATA-4", /* KeyLargo ATA-4 (UDMA/66) */ + "UniNorth ATA-6", /* UniNorth2 ATA-6 (UDMA/100) */ + "K2 ATA-6", /* K2 ATA-6 (UDMA/100) */ + "Shasta ATA-6", /* Shasta ATA-6 (UDMA/133) */ +}; + +/* + * Extra registers, both 32-bit little-endian + */ +#define IDE_TIMING_CONFIG 0x200 +#define IDE_INTERRUPT 0x300 + +/* Kauai (U2) ATA has different register setup */ +#define IDE_KAUAI_PIO_CONFIG 0x200 +#define IDE_KAUAI_ULTRA_CONFIG 0x210 +#define IDE_KAUAI_POLL_CONFIG 0x220 + +/* + * Timing configuration register definitions + */ + +/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ +#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) +#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) +#define IDE_SYSCLK_NS 30 /* 33Mhz cell */ +#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ + +/* 133Mhz cell, found in shasta. + * See comments about 100 Mhz Uninorth 2... + * Note that PIO_MASK and MDMA_MASK seem to overlap + */ +#define TR_133_PIOREG_PIO_MASK 0xff000fff +#define TR_133_PIOREG_MDMA_MASK 0x00fff800 +#define TR_133_UDMAREG_UDMA_MASK 0x0003ffff +#define TR_133_UDMAREG_UDMA_EN 0x00000001 + +/* 100Mhz cell, found in Uninorth 2. I don't have much infos about + * this one yet, it appears as a pci device (106b/0033) on uninorth + * internal PCI bus and it's clock is controlled like gem or fw. It + * appears to be an evolution of keylargo ATA4 with a timing register + * extended to 2 32bits registers and a similar DBDMA channel. Other + * registers seem to exist but I can't tell much about them. + * + * So far, I'm using pre-calculated tables for this extracted from + * the values used by the MacOS X driver. + * + * The "PIO" register controls PIO and MDMA timings, the "ULTRA" + * register controls the UDMA timings. At least, it seems bit 0 + * of this one enables UDMA vs. MDMA, and bits 4..7 are the + * cycle time in units of 10ns. Bits 8..15 are used by I don't + * know their meaning yet + */ +#define TR_100_PIOREG_PIO_MASK 0xff000fff +#define TR_100_PIOREG_MDMA_MASK 0x00fff000 +#define TR_100_UDMAREG_UDMA_MASK 0x0000ffff +#define TR_100_UDMAREG_UDMA_EN 0x00000001 + + +/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on + * 40 connector cable and to 4 on 80 connector one. + * Clock unit is 15ns (66Mhz) + * + * 3 Values can be programmed: + * - Write data setup, which appears to match the cycle time. They + * also call it DIOW setup. + * - Ready to pause time (from spec) + * - Address setup. That one is weird. I don't see where exactly + * it fits in UDMA cycles, I got it's name from an obscure piece + * of commented out code in Darwin. They leave it to 0, we do as + * well, despite a comment that would lead to think it has a + * min value of 45ns. + * Apple also add 60ns to the write data setup (or cycle time ?) on + * reads. + */ +#define TR_66_UDMA_MASK 0xfff00000 +#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ +#define TR_66_UDMA_ADDRSETUP_MASK 0xe0000000 /* Address setup */ +#define TR_66_UDMA_ADDRSETUP_SHIFT 29 +#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ +#define TR_66_UDMA_RDY2PAUS_SHIFT 25 +#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ +#define TR_66_UDMA_WRDATASETUP_SHIFT 21 +#define TR_66_MDMA_MASK 0x000ffc00 +#define TR_66_MDMA_RECOVERY_MASK 0x000f8000 +#define TR_66_MDMA_RECOVERY_SHIFT 15 +#define TR_66_MDMA_ACCESS_MASK 0x00007c00 +#define TR_66_MDMA_ACCESS_SHIFT 10 +#define TR_66_PIO_MASK 0x000003ff +#define TR_66_PIO_RECOVERY_MASK 0x000003e0 +#define TR_66_PIO_RECOVERY_SHIFT 5 +#define TR_66_PIO_ACCESS_MASK 0x0000001f +#define TR_66_PIO_ACCESS_SHIFT 0 + +/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo + * Can do pio & mdma modes, clock unit is 30ns (33Mhz) + * + * The access time and recovery time can be programmed. Some older + * Darwin code base limit OHare to 150ns cycle time. I decided to do + * the same here fore safety against broken old hardware ;) + * The HalfTick bit, when set, adds half a clock (15ns) to the access + * time and removes one from recovery. It's not supported on KeyLargo + * implementation afaik. The E bit appears to be set for PIO mode 0 and + * is used to reach long timings used in this mode. + */ +#define TR_33_MDMA_MASK 0x003ff800 +#define TR_33_MDMA_RECOVERY_MASK 0x001f0000 +#define TR_33_MDMA_RECOVERY_SHIFT 16 +#define TR_33_MDMA_ACCESS_MASK 0x0000f800 +#define TR_33_MDMA_ACCESS_SHIFT 11 +#define TR_33_MDMA_HALFTICK 0x00200000 +#define TR_33_PIO_MASK 0x000007ff +#define TR_33_PIO_E 0x00000400 +#define TR_33_PIO_RECOVERY_MASK 0x000003e0 +#define TR_33_PIO_RECOVERY_SHIFT 5 +#define TR_33_PIO_ACCESS_MASK 0x0000001f +#define TR_33_PIO_ACCESS_SHIFT 0 + +/* + * Interrupt register definitions + */ +#define IDE_INTR_DMA 0x80000000 +#define IDE_INTR_DEVICE 0x40000000 + +/* + * FCR Register on Kauai. Not sure what bit 0x4 is ... + */ +#define KAUAI_FCR_UATA_MAGIC 0x00000004 +#define KAUAI_FCR_UATA_RESET_N 0x00000002 +#define KAUAI_FCR_UATA_ENABLE 0x00000001 + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + +/* Rounded Multiword DMA timings + * + * I gave up finding a generic formula for all controller + * types and instead, built tables based on timing values + * used by Apple in Darwin's implementation. + */ +struct mdma_timings_t { + int accessTime; + int recoveryTime; + int cycleTime; +}; + +struct mdma_timings_t mdma_timings_33[] = +{ + { 240, 240, 480 }, + { 180, 180, 360 }, + { 135, 135, 270 }, + { 120, 120, 240 }, + { 105, 105, 210 }, + { 90, 90, 180 }, + { 75, 75, 150 }, + { 75, 45, 120 }, + { 0, 0, 0 } +}; + +struct mdma_timings_t mdma_timings_33k[] = +{ + { 240, 240, 480 }, + { 180, 180, 360 }, + { 150, 150, 300 }, + { 120, 120, 240 }, + { 90, 120, 210 }, + { 90, 90, 180 }, + { 90, 60, 150 }, + { 90, 30, 120 }, + { 0, 0, 0 } +}; + +struct mdma_timings_t mdma_timings_66[] = +{ + { 240, 240, 480 }, + { 180, 180, 360 }, + { 135, 135, 270 }, + { 120, 120, 240 }, + { 105, 105, 210 }, + { 90, 90, 180 }, + { 90, 75, 165 }, + { 75, 45, 120 }, + { 0, 0, 0 } +}; + +/* KeyLargo ATA-4 Ultra DMA timings (rounded) */ +struct { + int addrSetup; /* ??? */ + int rdy2pause; + int wrDataSetup; +} kl66_udma_timings[] = +{ + { 0, 180, 120 }, /* Mode 0 */ + { 0, 150, 90 }, /* 1 */ + { 0, 120, 60 }, /* 2 */ + { 0, 90, 45 }, /* 3 */ + { 0, 90, 30 } /* 4 */ +}; + +/* UniNorth 2 ATA/100 timings */ +struct kauai_timing { + int cycle_time; + u32 timing_reg; +}; + +static struct kauai_timing kauai_pio_timings[] = +{ + { 930 , 0x08000fff }, + { 600 , 0x08000a92 }, + { 383 , 0x0800060f }, + { 360 , 0x08000492 }, + { 330 , 0x0800048f }, + { 300 , 0x080003cf }, + { 270 , 0x080003cc }, + { 240 , 0x0800038b }, + { 239 , 0x0800030c }, + { 180 , 0x05000249 }, + { 120 , 0x04000148 }, + { 0 , 0 }, +}; + +static struct kauai_timing kauai_mdma_timings[] = +{ + { 1260 , 0x00fff000 }, + { 480 , 0x00618000 }, + { 360 , 0x00492000 }, + { 270 , 0x0038e000 }, + { 240 , 0x0030c000 }, + { 210 , 0x002cb000 }, + { 180 , 0x00249000 }, + { 150 , 0x00209000 }, + { 120 , 0x00148000 }, + { 0 , 0 }, +}; + +static struct kauai_timing kauai_udma_timings[] = +{ + { 120 , 0x000070c0 }, + { 90 , 0x00005d80 }, + { 60 , 0x00004a60 }, + { 45 , 0x00003a50 }, + { 30 , 0x00002a30 }, + { 20 , 0x00002921 }, + { 0 , 0 }, +}; + +static struct kauai_timing shasta_pio_timings[] = +{ + { 930 , 0x08000fff }, + { 600 , 0x0A000c97 }, + { 383 , 0x07000712 }, + { 360 , 0x040003cd }, + { 330 , 0x040003cd }, + { 300 , 0x040003cd }, + { 270 , 0x040003cd }, + { 240 , 0x040003cd }, + { 239 , 0x040003cd }, + { 180 , 0x0400028b }, + { 120 , 0x0400010a }, + { 0 , 0 }, +}; + +static struct kauai_timing shasta_mdma_timings[] = +{ + { 1260 , 0x00fff000 }, + { 480 , 0x00820800 }, + { 360 , 0x00820800 }, + { 270 , 0x00820800 }, + { 240 , 0x00820800 }, + { 210 , 0x00820800 }, + { 180 , 0x00820800 }, + { 150 , 0x0028b000 }, + { 120 , 0x001ca000 }, + { 0 , 0 }, +}; + +static struct kauai_timing shasta_udma133_timings[] = +{ + { 120 , 0x00035901, }, + { 90 , 0x000348b1, }, + { 60 , 0x00033881, }, + { 45 , 0x00033861, }, + { 30 , 0x00033841, }, + { 20 , 0x00033031, }, + { 15 , 0x00033021, }, + { 0 , 0 }, +}; + + +static inline u32 +kauai_lookup_timing(struct kauai_timing* table, int cycle_time) +{ + int i; + + for (i=0; table[i].cycle_time; i++) + if (cycle_time > table[i+1].cycle_time) + return table[i].timing_reg; + BUG(); + return 0; +} + +/* allow up to 256 DBDMA commands per xfer */ +#define MAX_DCMDS 256 + +/* + * Wait 1s for disk to answer on IDE bus after a hard reset + * of the device (via GPIO/FCR). + * + * Some devices seem to "pollute" the bus even after dropping + * the BSY bit (typically some combo drives slave on the UDMA + * bus) after a hard reset. Since we hard reset all drives on + * KeyLargo ATA66, we have to keep that delay around. I may end + * up not hard resetting anymore on these and keep the delay only + * for older interfaces instead (we have to reset when coming + * from MacOS...) --BenH. + */ +#define IDE_WAKEUP_DELAY (1*HZ) + +static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *); +static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq); +static void pmac_ide_selectproc(ide_drive_t *drive); +static void pmac_ide_kauai_selectproc(ide_drive_t *drive); + +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + +#define PMAC_IDE_REG(x) \ + ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x))) + +/* + * Apply the timings of the proper unit (master/slave) to the shared + * timing register when selecting that unit. This version is for + * ASICs with a single timing register + */ +static void +pmac_ide_selectproc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + + if (drive->dn & 1) + writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG)); + else + writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG)); + (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); +} + +/* + * Apply the timings of the proper unit (master/slave) to the shared + * timing register when selecting that unit. This version is for + * ASICs with a dual timing register (Kauai) + */ +static void +pmac_ide_kauai_selectproc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + + if (drive->dn & 1) { + writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); + writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); + } else { + writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); + writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); + } + (void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); +} + +/* + * Force an update of controller timing values for a given drive + */ +static void +pmac_ide_do_update_timings(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + + if (pmif->kind == controller_sh_ata6 || + pmif->kind == controller_un_ata6 || + pmif->kind == controller_k2_ata6) + pmac_ide_kauai_selectproc(drive); + else + pmac_ide_selectproc(drive); +} + +static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd) +{ + writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); + (void)readl((void __iomem *)(hwif->io_ports.data_addr + + IDE_TIMING_CONFIG)); +} + +static void pmac_set_irq(ide_hwif_t *hwif, int on) +{ + u8 ctl = ATA_DEVCTL_OBS; + + if (on == 4) { /* hack for SRST */ + ctl |= 4; + on &= ~4; + } + + ctl |= on ? 0 : 2; + + writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); + (void)readl((void __iomem *)(hwif->io_ports.data_addr + + IDE_TIMING_CONFIG)); +} + +/* + * Old tuning functions (called on hdparm -p), sets up drive PIO timings + */ +static void +pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio); + u32 *timings, t; + unsigned accessTicks, recTicks; + unsigned accessTime, recTime; + unsigned int cycle_time; + + /* which drive is it ? */ + timings = &pmif->timings[drive->dn & 1]; + t = *timings; + + cycle_time = ide_pio_cycle_time(drive, pio); + + switch (pmif->kind) { + case controller_sh_ata6: { + /* 133Mhz cell */ + u32 tr = kauai_lookup_timing(shasta_pio_timings, cycle_time); + t = (t & ~TR_133_PIOREG_PIO_MASK) | tr; + break; + } + case controller_un_ata6: + case controller_k2_ata6: { + /* 100Mhz cell */ + u32 tr = kauai_lookup_timing(kauai_pio_timings, cycle_time); + t = (t & ~TR_100_PIOREG_PIO_MASK) | tr; + break; + } + case controller_kl_ata4: + /* 66Mhz cell */ + recTime = cycle_time - tim->active - tim->setup; + recTime = max(recTime, 150U); + accessTime = tim->active; + accessTime = max(accessTime, 150U); + accessTicks = SYSCLK_TICKS_66(accessTime); + accessTicks = min(accessTicks, 0x1fU); + recTicks = SYSCLK_TICKS_66(recTime); + recTicks = min(recTicks, 0x1fU); + t = (t & ~TR_66_PIO_MASK) | + (accessTicks << TR_66_PIO_ACCESS_SHIFT) | + (recTicks << TR_66_PIO_RECOVERY_SHIFT); + break; + default: { + /* 33Mhz cell */ + int ebit = 0; + recTime = cycle_time - tim->active - tim->setup; + recTime = max(recTime, 150U); + accessTime = tim->active; + accessTime = max(accessTime, 150U); + accessTicks = SYSCLK_TICKS(accessTime); + accessTicks = min(accessTicks, 0x1fU); + accessTicks = max(accessTicks, 4U); + recTicks = SYSCLK_TICKS(recTime); + recTicks = min(recTicks, 0x1fU); + recTicks = max(recTicks, 5U) - 4; + if (recTicks > 9) { + recTicks--; /* guess, but it's only for PIO0, so... */ + ebit = 1; + } + t = (t & ~TR_33_PIO_MASK) | + (accessTicks << TR_33_PIO_ACCESS_SHIFT) | + (recTicks << TR_33_PIO_RECOVERY_SHIFT); + if (ebit) + t |= TR_33_PIO_E; + break; + } + } + +#ifdef IDE_PMAC_DEBUG + printk(KERN_ERR "%s: Set PIO timing for mode %d, reg: 0x%08x\n", + drive->name, pio, *timings); +#endif + + *timings = t; + pmac_ide_do_update_timings(drive); +} + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + +/* + * Calculate KeyLargo ATA/66 UDMA timings + */ +static int +set_timings_udma_ata4(u32 *timings, u8 speed) +{ + unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; + + if (speed > XFER_UDMA_4) + return 1; + + rdyToPauseTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].rdy2pause); + wrDataSetupTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].wrDataSetup); + addrTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].addrSetup); + + *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) | + (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | + (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) | + (addrTicks < XFER_UDMA_5 || t == NULL) + return 1; + tr = kauai_lookup_timing(kauai_udma_timings, (int)t->udma); + *ultra_timings = ((*ultra_timings) & ~TR_100_UDMAREG_UDMA_MASK) | tr; + *ultra_timings = (*ultra_timings) | TR_100_UDMAREG_UDMA_EN; + + return 0; +} + +/* + * Calculate Shasta ATA/133 UDMA timings + */ +static int +set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed) +{ + struct ide_timing *t = ide_timing_find_mode(speed); + u32 tr; + + if (speed > XFER_UDMA_6 || t == NULL) + return 1; + tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma); + *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr; + *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN; + + return 0; +} + +/* + * Calculate MDMA timings for all cells + */ +static void +set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, + u8 speed) +{ + u16 *id = drive->id; + int cycleTime, accessTime = 0, recTime = 0; + unsigned accessTicks, recTicks; + struct mdma_timings_t* tm = NULL; + int i; + + /* Get default cycle time for mode */ + switch(speed & 0xf) { + case 0: cycleTime = 480; break; + case 1: cycleTime = 150; break; + case 2: cycleTime = 120; break; + default: + BUG(); + break; + } + + /* Check if drive provides explicit DMA cycle time */ + if ((id[ATA_ID_FIELD_VALID] & 2) && id[ATA_ID_EIDE_DMA_TIME]) + cycleTime = max_t(int, id[ATA_ID_EIDE_DMA_TIME], cycleTime); + + /* OHare limits according to some old Apple sources */ + if ((intf_type == controller_ohare) && (cycleTime < 150)) + cycleTime = 150; + /* Get the proper timing array for this controller */ + switch(intf_type) { + case controller_sh_ata6: + case controller_un_ata6: + case controller_k2_ata6: + break; + case controller_kl_ata4: + tm = mdma_timings_66; + break; + case controller_kl_ata3: + tm = mdma_timings_33k; + break; + default: + tm = mdma_timings_33; + break; + } + if (tm != NULL) { + /* Lookup matching access & recovery times */ + i = -1; + for (;;) { + if (tm[i+1].cycleTime < cycleTime) + break; + i++; + } + cycleTime = tm[i].cycleTime; + accessTime = tm[i].accessTime; + recTime = tm[i].recoveryTime; + +#ifdef IDE_PMAC_DEBUG + printk(KERN_ERR "%s: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n", + drive->name, cycleTime, accessTime, recTime); +#endif + } + switch(intf_type) { + case controller_sh_ata6: { + /* 133Mhz cell */ + u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime); + *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr; + *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN; + } + case controller_un_ata6: + case controller_k2_ata6: { + /* 100Mhz cell */ + u32 tr = kauai_lookup_timing(kauai_mdma_timings, cycleTime); + *timings = ((*timings) & ~TR_100_PIOREG_MDMA_MASK) | tr; + *timings2 = (*timings2) & ~TR_100_UDMAREG_UDMA_EN; + } + break; + case controller_kl_ata4: + /* 66Mhz cell */ + accessTicks = SYSCLK_TICKS_66(accessTime); + accessTicks = min(accessTicks, 0x1fU); + accessTicks = max(accessTicks, 0x1U); + recTicks = SYSCLK_TICKS_66(recTime); + recTicks = min(recTicks, 0x1fU); + recTicks = max(recTicks, 0x3U); + /* Clear out mdma bits and disable udma */ + *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) | + (accessTicks << TR_66_MDMA_ACCESS_SHIFT) | + (recTicks << TR_66_MDMA_RECOVERY_SHIFT); + break; + case controller_kl_ata3: + /* 33Mhz cell on KeyLargo */ + accessTicks = SYSCLK_TICKS(accessTime); + accessTicks = max(accessTicks, 1U); + accessTicks = min(accessTicks, 0x1fU); + accessTime = accessTicks * IDE_SYSCLK_NS; + recTicks = SYSCLK_TICKS(recTime); + recTicks = max(recTicks, 1U); + recTicks = min(recTicks, 0x1fU); + *timings = ((*timings) & ~TR_33_MDMA_MASK) | + (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | + (recTicks << TR_33_MDMA_RECOVERY_SHIFT); + break; + default: { + /* 33Mhz cell on others */ + int halfTick = 0; + int origAccessTime = accessTime; + int origRecTime = recTime; + + accessTicks = SYSCLK_TICKS(accessTime); + accessTicks = max(accessTicks, 1U); + accessTicks = min(accessTicks, 0x1fU); + accessTime = accessTicks * IDE_SYSCLK_NS; + recTicks = SYSCLK_TICKS(recTime); + recTicks = max(recTicks, 2U) - 1; + recTicks = min(recTicks, 0x1fU); + recTime = (recTicks + 1) * IDE_SYSCLK_NS; + if ((accessTicks > 1) && + ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && + ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) { + halfTick = 1; + accessTicks--; + } + *timings = ((*timings) & ~TR_33_MDMA_MASK) | + (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | + (recTicks << TR_33_MDMA_RECOVERY_SHIFT); + if (halfTick) + *timings |= TR_33_MDMA_HALFTICK; + } + } +#ifdef IDE_PMAC_DEBUG + printk(KERN_ERR "%s: Set MDMA timing for mode %d, reg: 0x%08x\n", + drive->name, speed & 0xf, *timings); +#endif +} +#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */ + +static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + int ret = 0; + u32 *timings, *timings2, tl[2]; + u8 unit = drive->dn & 1; + + timings = &pmif->timings[unit]; + timings2 = &pmif->timings[unit+2]; + + /* Copy timings to local image */ + tl[0] = *timings; + tl[1] = *timings2; + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + if (speed >= XFER_UDMA_0) { + if (pmif->kind == controller_kl_ata4) + ret = set_timings_udma_ata4(&tl[0], speed); + else if (pmif->kind == controller_un_ata6 + || pmif->kind == controller_k2_ata6) + ret = set_timings_udma_ata6(&tl[0], &tl[1], speed); + else if (pmif->kind == controller_sh_ata6) + ret = set_timings_udma_shasta(&tl[0], &tl[1], speed); + else + ret = -1; + } else + set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed); +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + if (ret) + return; + + /* Apply timings to controller */ + *timings = tl[0]; + *timings2 = tl[1]; + + pmac_ide_do_update_timings(drive); +} + +/* + * Blast some well known "safe" values to the timing registers at init or + * wakeup from sleep time, before we do real calculation + */ +static void +sanitize_timings(pmac_ide_hwif_t *pmif) +{ + unsigned int value, value2 = 0; + + switch(pmif->kind) { + case controller_sh_ata6: + value = 0x0a820c97; + value2 = 0x00033031; + break; + case controller_un_ata6: + case controller_k2_ata6: + value = 0x08618a92; + value2 = 0x00002921; + break; + case controller_kl_ata4: + value = 0x0008438c; + break; + case controller_kl_ata3: + value = 0x00084526; + break; + case controller_heathrow: + case controller_ohare: + default: + value = 0x00074526; + break; + } + pmif->timings[0] = pmif->timings[1] = value; + pmif->timings[2] = pmif->timings[3] = value2; +} + +/* Suspend call back, should be called after the child devices + * have actually been suspended + */ +static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif) +{ + /* We clear the timings */ + pmif->timings[0] = 0; + pmif->timings[1] = 0; + + disable_irq(pmif->irq); + + /* The media bay will handle itself just fine */ + if (pmif->mediabay) + return 0; + + /* Kauai has bus control FCRs directly here */ + if (pmif->kauai_fcr) { + u32 fcr = readl(pmif->kauai_fcr); + fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); + writel(fcr, pmif->kauai_fcr); + } + + /* Disable the bus on older machines and the cell on kauai */ + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, + 0); + + return 0; +} + +/* Resume call back, should be called before the child devices + * are resumed + */ +static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif) +{ + /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */ + if (!pmif->mediabay) { + ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1); + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1); + msleep(10); + ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0); + + /* Kauai has it different */ + if (pmif->kauai_fcr) { + u32 fcr = readl(pmif->kauai_fcr); + fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE; + writel(fcr, pmif->kauai_fcr); + } + + msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); + } + + /* Sanitize drive timings */ + sanitize_timings(pmif); + + enable_irq(pmif->irq); + + return 0; +} + +static u8 pmac_ide_cable_detect(ide_hwif_t *hwif) +{ + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + struct device_node *np = pmif->node; + const char *cable = of_get_property(np, "cable-type", NULL); + + /* Get cable type from device-tree. */ + if (cable && !strncmp(cable, "80-", 3)) + return ATA_CBL_PATA80; + + /* + * G5's seem to have incorrect cable type in device-tree. + * Let's assume they have a 80 conductor cable, this seem + * to be always the case unless the user mucked around. + */ + if (of_device_is_compatible(np, "K2-UATA") || + of_device_is_compatible(np, "shasta-ata")) + return ATA_CBL_PATA80; + + return ATA_CBL_PATA40; +} + +static void pmac_ide_init_dev(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + + if (pmif->mediabay) { +#ifdef CONFIG_PMAC_MEDIABAY + if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) { + drive->dev_flags &= ~IDE_DFLAG_NOPROBE; + return; + } +#endif + drive->dev_flags |= IDE_DFLAG_NOPROBE; + } +} + +static const struct ide_tp_ops pmac_tp_ops = { + .exec_command = pmac_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + .read_sff_dma_status = ide_read_sff_dma_status, + + .set_irq = pmac_set_irq, + + .tf_load = ide_tf_load, + .tf_read = ide_tf_read, + + .input_data = ide_input_data, + .output_data = ide_output_data, +}; + +static const struct ide_port_ops pmac_ide_ata6_port_ops = { + .init_dev = pmac_ide_init_dev, + .set_pio_mode = pmac_ide_set_pio_mode, + .set_dma_mode = pmac_ide_set_dma_mode, + .selectproc = pmac_ide_kauai_selectproc, + .cable_detect = pmac_ide_cable_detect, +}; + +static const struct ide_port_ops pmac_ide_ata4_port_ops = { + .init_dev = pmac_ide_init_dev, + .set_pio_mode = pmac_ide_set_pio_mode, + .set_dma_mode = pmac_ide_set_dma_mode, + .selectproc = pmac_ide_selectproc, + .cable_detect = pmac_ide_cable_detect, +}; + +static const struct ide_port_ops pmac_ide_port_ops = { + .init_dev = pmac_ide_init_dev, + .set_pio_mode = pmac_ide_set_pio_mode, + .set_dma_mode = pmac_ide_set_dma_mode, + .selectproc = pmac_ide_selectproc, +}; + +static const struct ide_dma_ops pmac_dma_ops; + +static const struct ide_port_info pmac_port_info = { + .name = DRV_NAME, + .init_dma = pmac_ide_init_dma, + .chipset = ide_pmac, + .tp_ops = &pmac_tp_ops, + .port_ops = &pmac_ide_port_ops, +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + .dma_ops = &pmac_dma_ops, +#endif + .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | + IDE_HFLAG_POST_SET_MODE | + IDE_HFLAG_MMIO | + IDE_HFLAG_UNMASK_IRQS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, +}; + +/* + * Setup, register & probe an IDE channel driven by this driver, this is + * called by one of the 2 probe functions (macio or PCI). + */ +static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw) +{ + struct device_node *np = pmif->node; + const int *bidp; + struct ide_host *host; + ide_hwif_t *hwif; + hw_regs_t *hws[] = { hw, NULL, NULL, NULL }; + struct ide_port_info d = pmac_port_info; + int rc; + + pmif->broken_dma = pmif->broken_dma_warn = 0; + if (of_device_is_compatible(np, "shasta-ata")) { + pmif->kind = controller_sh_ata6; + d.port_ops = &pmac_ide_ata6_port_ops; + d.udma_mask = ATA_UDMA6; + } else if (of_device_is_compatible(np, "kauai-ata")) { + pmif->kind = controller_un_ata6; + d.port_ops = &pmac_ide_ata6_port_ops; + d.udma_mask = ATA_UDMA5; + } else if (of_device_is_compatible(np, "K2-UATA")) { + pmif->kind = controller_k2_ata6; + d.port_ops = &pmac_ide_ata6_port_ops; + d.udma_mask = ATA_UDMA5; + } else if (of_device_is_compatible(np, "keylargo-ata")) { + if (strcmp(np->name, "ata-4") == 0) { + pmif->kind = controller_kl_ata4; + d.port_ops = &pmac_ide_ata4_port_ops; + d.udma_mask = ATA_UDMA4; + } else + pmif->kind = controller_kl_ata3; + } else if (of_device_is_compatible(np, "heathrow-ata")) { + pmif->kind = controller_heathrow; + } else { + pmif->kind = controller_ohare; + pmif->broken_dma = 1; + } + + bidp = of_get_property(np, "AAPL,bus-id", NULL); + pmif->aapl_bus_id = bidp ? *bidp : 0; + + /* On Kauai-type controllers, we make sure the FCR is correct */ + if (pmif->kauai_fcr) + writel(KAUAI_FCR_UATA_MAGIC | + KAUAI_FCR_UATA_RESET_N | + KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr); + + pmif->mediabay = 0; + + /* Make sure we have sane timings */ + sanitize_timings(pmif); + + host = ide_host_alloc(&d, hws); + if (host == NULL) + return -ENOMEM; + hwif = host->ports[0]; + +#ifndef CONFIG_PPC64 + /* XXX FIXME: Media bay stuff need re-organizing */ + if (np->parent && np->parent->name + && strcasecmp(np->parent->name, "media-bay") == 0) { +#ifdef CONFIG_PMAC_MEDIABAY + media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, + hwif); +#endif /* CONFIG_PMAC_MEDIABAY */ + pmif->mediabay = 1; + if (!bidp) + pmif->aapl_bus_id = 1; + } else if (pmif->kind == controller_ohare) { + /* The code below is having trouble on some ohare machines + * (timing related ?). Until I can put my hand on one of these + * units, I keep the old way + */ + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); + } else +#endif + { + /* This is necessary to enable IDE when net-booting */ + ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); + msleep(10); + ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0); + msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); + } + + printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), " + "bus ID %d%s, irq %d\n", model_name[pmif->kind], + pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id, + pmif->mediabay ? " (mediabay)" : "", hw->irq); + + rc = ide_host_register(host, &d, hws); + if (rc) { + ide_host_free(host); + return rc; + } + + return 0; +} + +static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base) +{ + int i; + + for (i = 0; i < 8; ++i) + hw->io_ports_array[i] = base + i * 0x10; + + hw->io_ports.ctl_addr = base + 0x160; +} + +/* + * Attach to a macio probed interface + */ +static int __devinit +pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) +{ + void __iomem *base; + unsigned long regbase; + pmac_ide_hwif_t *pmif; + int irq, rc; + hw_regs_t hw; + + pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); + if (pmif == NULL) + return -ENOMEM; + + if (macio_resource_count(mdev) == 0) { + printk(KERN_WARNING "ide-pmac: no address for %s\n", + mdev->ofdev.node->full_name); + rc = -ENXIO; + goto out_free_pmif; + } + + /* Request memory resource for IO ports */ + if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) { + printk(KERN_ERR "ide-pmac: can't request MMIO resource for " + "%s!\n", mdev->ofdev.node->full_name); + rc = -EBUSY; + goto out_free_pmif; + } + + /* XXX This is bogus. Should be fixed in the registry by checking + * the kind of host interrupt controller, a bit like gatwick + * fixes in irq.c. That works well enough for the single case + * where that happens though... + */ + if (macio_irq_count(mdev) == 0) { + printk(KERN_WARNING "ide-pmac: no intrs for device %s, using " + "13\n", mdev->ofdev.node->full_name); + irq = irq_create_mapping(NULL, 13); + } else + irq = macio_irq(mdev, 0); + + base = ioremap(macio_resource_start(mdev, 0), 0x400); + regbase = (unsigned long) base; + + pmif->mdev = mdev; + pmif->node = mdev->ofdev.node; + pmif->regbase = regbase; + pmif->irq = irq; + pmif->kauai_fcr = NULL; +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + if (macio_resource_count(mdev) >= 2) { + if (macio_request_resource(mdev, 1, "ide-pmac (dma)")) + printk(KERN_WARNING "ide-pmac: can't request DMA " + "resource for %s!\n", + mdev->ofdev.node->full_name); + else + pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000); + } else + pmif->dma_regs = NULL; +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + dev_set_drvdata(&mdev->ofdev.dev, pmif); + + memset(&hw, 0, sizeof(hw)); + pmac_ide_init_ports(&hw, pmif->regbase); + hw.irq = irq; + hw.dev = &mdev->bus->pdev->dev; + hw.parent = &mdev->ofdev.dev; + + rc = pmac_ide_setup_device(pmif, &hw); + if (rc != 0) { + /* The inteface is released to the common IDE layer */ + dev_set_drvdata(&mdev->ofdev.dev, NULL); + iounmap(base); + if (pmif->dma_regs) { + iounmap(pmif->dma_regs); + macio_release_resource(mdev, 1); + } + macio_release_resource(mdev, 0); + kfree(pmif); + } + + return rc; + +out_free_pmif: + kfree(pmif); + return rc; +} + +static int +pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg) +{ + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); + int rc = 0; + + if (mesg.event != mdev->ofdev.dev.power.power_state.event + && (mesg.event & PM_EVENT_SLEEP)) { + rc = pmac_ide_do_suspend(pmif); + if (rc == 0) + mdev->ofdev.dev.power.power_state = mesg; + } + + return rc; +} + +static int +pmac_ide_macio_resume(struct macio_dev *mdev) +{ + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); + int rc = 0; + + if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) { + rc = pmac_ide_do_resume(pmif); + if (rc == 0) + mdev->ofdev.dev.power.power_state = PMSG_ON; + } + + return rc; +} + +/* + * Attach to a PCI probed interface + */ +static int __devinit +pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct device_node *np; + pmac_ide_hwif_t *pmif; + void __iomem *base; + unsigned long rbase, rlen; + int rc; + hw_regs_t hw; + + np = pci_device_to_OF_node(pdev); + if (np == NULL) { + printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n"); + return -ENODEV; + } + + pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); + if (pmif == NULL) + return -ENOMEM; + + if (pci_enable_device(pdev)) { + printk(KERN_WARNING "ide-pmac: Can't enable PCI device for " + "%s\n", np->full_name); + rc = -ENXIO; + goto out_free_pmif; + } + pci_set_master(pdev); + + if (pci_request_regions(pdev, "Kauai ATA")) { + printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for " + "%s\n", np->full_name); + rc = -ENXIO; + goto out_free_pmif; + } + + pmif->mdev = NULL; + pmif->node = np; + + rbase = pci_resource_start(pdev, 0); + rlen = pci_resource_len(pdev, 0); + + base = ioremap(rbase, rlen); + pmif->regbase = (unsigned long) base + 0x2000; +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + pmif->dma_regs = base + 0x1000; +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + pmif->kauai_fcr = base; + pmif->irq = pdev->irq; + + pci_set_drvdata(pdev, pmif); + + memset(&hw, 0, sizeof(hw)); + pmac_ide_init_ports(&hw, pmif->regbase); + hw.irq = pdev->irq; + hw.dev = &pdev->dev; + + rc = pmac_ide_setup_device(pmif, &hw); + if (rc != 0) { + /* The inteface is released to the common IDE layer */ + pci_set_drvdata(pdev, NULL); + iounmap(base); + pci_release_regions(pdev); + kfree(pmif); + } + + return rc; + +out_free_pmif: + kfree(pmif); + return rc; +} + +static int +pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev); + int rc = 0; + + if (mesg.event != pdev->dev.power.power_state.event + && (mesg.event & PM_EVENT_SLEEP)) { + rc = pmac_ide_do_suspend(pmif); + if (rc == 0) + pdev->dev.power.power_state = mesg; + } + + return rc; +} + +static int +pmac_ide_pci_resume(struct pci_dev *pdev) +{ + pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev); + int rc = 0; + + if (pdev->dev.power.power_state.event != PM_EVENT_ON) { + rc = pmac_ide_do_resume(pmif); + if (rc == 0) + pdev->dev.power.power_state = PMSG_ON; + } + + return rc; +} + +static struct of_device_id pmac_ide_macio_match[] = +{ + { + .name = "IDE", + }, + { + .name = "ATA", + }, + { + .type = "ide", + }, + { + .type = "ata", + }, + {}, +}; + +static struct macio_driver pmac_ide_macio_driver = +{ + .name = "ide-pmac", + .match_table = pmac_ide_macio_match, + .probe = pmac_ide_macio_attach, + .suspend = pmac_ide_macio_suspend, + .resume = pmac_ide_macio_resume, +}; + +static const struct pci_device_id pmac_ide_pci_match[] = { + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA), 0 }, + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100), 0 }, + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100), 0 }, + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA), 0 }, + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA), 0 }, + {}, +}; + +static struct pci_driver pmac_ide_pci_driver = { + .name = "ide-pmac", + .id_table = pmac_ide_pci_match, + .probe = pmac_ide_pci_attach, + .suspend = pmac_ide_pci_suspend, + .resume = pmac_ide_pci_resume, +}; +MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match); + +int __init pmac_ide_probe(void) +{ + int error; + + if (!machine_is(powermac)) + return -ENODEV; + +#ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST + error = pci_register_driver(&pmac_ide_pci_driver); + if (error) + goto out; + error = macio_register_driver(&pmac_ide_macio_driver); + if (error) { + pci_unregister_driver(&pmac_ide_pci_driver); + goto out; + } +#else + error = macio_register_driver(&pmac_ide_macio_driver); + if (error) + goto out; + error = pci_register_driver(&pmac_ide_pci_driver); + if (error) { + macio_unregister_driver(&pmac_ide_macio_driver); + goto out; + } +#endif +out: + return error; +} + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + +/* + * pmac_ide_build_dmatable builds the DBDMA command list + * for a transfer and sets the DBDMA channel to point to it. + */ +static int +pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + struct dbdma_cmd *table; + int i, count = 0; + volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; + struct scatterlist *sg; + int wr = (rq_data_dir(rq) == WRITE); + + /* DMA table is already aligned */ + table = (struct dbdma_cmd *) pmif->dma_table_cpu; + + /* Make sure DMA controller is stopped (necessary ?) */ + writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma->control); + while (readl(&dma->status) & RUN) + udelay(1); + + hwif->sg_nents = i = ide_build_sglist(drive, rq); + + if (!i) + return 0; + + /* Build DBDMA commands list */ + sg = hwif->sg_table; + while (i && sg_dma_len(sg)) { + u32 cur_addr; + u32 cur_len; + + cur_addr = sg_dma_address(sg); + cur_len = sg_dma_len(sg); + + if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) { + if (pmif->broken_dma_warn == 0) { + printk(KERN_WARNING "%s: DMA on non aligned address, " + "switching to PIO on Ohare chipset\n", drive->name); + pmif->broken_dma_warn = 1; + } + goto use_pio_instead; + } + while (cur_len) { + unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; + + if (count++ >= MAX_DCMDS) { + printk(KERN_WARNING "%s: DMA table too small\n", + drive->name); + goto use_pio_instead; + } + st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); + st_le16(&table->req_count, tc); + st_le32(&table->phy_addr, cur_addr); + table->cmd_dep = 0; + table->xfer_status = 0; + table->res_count = 0; + cur_addr += tc; + cur_len -= tc; + ++table; + } + sg = sg_next(sg); + i--; + } + + /* convert the last command to an input/output last command */ + if (count) { + st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); + /* add the stop command to the end of the list */ + memset(table, 0, sizeof(struct dbdma_cmd)); + st_le16(&table->command, DBDMA_STOP); + mb(); + writel(hwif->dmatable_dma, &dma->cmdptr); + return 1; + } + + printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); + +use_pio_instead: + ide_destroy_dmatable(drive); + + return 0; /* revert to PIO for this request */ +} + +/* + * Prepare a DMA transfer. We build the DMA table, adjust the timings for + * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion + */ +static int +pmac_ide_dma_setup(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + struct request *rq = HWGROUP(drive)->rq; + u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4); + + if (!pmac_ide_build_dmatable(drive, rq)) { + ide_map_sg(drive, rq); + return 1; + } + + /* Apple adds 60ns to wrDataSetup on reads */ + if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { + writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0), + PMAC_IDE_REG(IDE_TIMING_CONFIG)); + (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); + } + + drive->waiting_for_dma = 1; + + return 0; +} + +static void +pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) +{ + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); +} + +/* + * Kick the DMA controller into life after the DMA command has been issued + * to the drive. + */ +static void +pmac_ide_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + volatile struct dbdma_regs __iomem *dma; + + dma = pmif->dma_regs; + + writel((RUN << 16) | RUN, &dma->control); + /* Make sure it gets to the controller right now */ + (void)readl(&dma->control); +} + +/* + * After a DMA transfer, make sure the controller is stopped + */ +static int +pmac_ide_dma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; + u32 dstat; + + drive->waiting_for_dma = 0; + dstat = readl(&dma->status); + writel(((RUN|WAKE|DEAD) << 16), &dma->control); + + ide_destroy_dmatable(drive); + + /* verify good dma status. we don't check for ACTIVE beeing 0. We should... + * in theory, but with ATAPI decices doing buffer underruns, that would + * cause us to disable DMA, which isn't what we want + */ + return (dstat & (RUN|DEAD)) != RUN; +} + +/* + * Check out that the interrupt we got was for us. We can't always know this + * for sure with those Apple interfaces (well, we could on the recent ones but + * that's not implemented yet), on the other hand, we don't have shared interrupts + * so it's not really a problem + */ +static int +pmac_ide_dma_test_irq (ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; + unsigned long status, timeout; + + /* We have to things to deal with here: + * + * - The dbdma won't stop if the command was started + * but completed with an error without transferring all + * datas. This happens when bad blocks are met during + * a multi-block transfer. + * + * - The dbdma fifo hasn't yet finished flushing to + * to system memory when the disk interrupt occurs. + * + */ + + /* If ACTIVE is cleared, the STOP command have passed and + * transfer is complete. + */ + status = readl(&dma->status); + if (!(status & ACTIVE)) + return 1; + + /* If dbdma didn't execute the STOP command yet, the + * active bit is still set. We consider that we aren't + * sharing interrupts (which is hopefully the case with + * those controllers) and so we just try to flush the + * channel for pending data in the fifo + */ + udelay(1); + writel((FLUSH << 16) | FLUSH, &dma->control); + timeout = 0; + for (;;) { + udelay(1); + status = readl(&dma->status); + if ((status & FLUSH) == 0) + break; + if (++timeout > 100) { + printk(KERN_WARNING "ide%d, ide_dma_test_irq \ + timeout flushing channel\n", HWIF(drive)->index); + break; + } + } + return 1; +} + +static void pmac_ide_dma_host_set(ide_drive_t *drive, int on) +{ +} + +static void +pmac_ide_dma_lost_irq (ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; + unsigned long status = readl(&dma->status); + + printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status); +} + +static const struct ide_dma_ops pmac_dma_ops = { + .dma_host_set = pmac_ide_dma_host_set, + .dma_setup = pmac_ide_dma_setup, + .dma_exec_cmd = pmac_ide_dma_exec_cmd, + .dma_start = pmac_ide_dma_start, + .dma_end = pmac_ide_dma_end, + .dma_test_irq = pmac_ide_dma_test_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = pmac_ide_dma_lost_irq, +}; + +/* + * Allocate the data structures needed for using DMA with an interface + * and fill the proper list of functions pointers + */ +static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, + const struct ide_port_info *d) +{ + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); + struct pci_dev *dev = to_pci_dev(hwif->dev); + + /* We won't need pci_dev if we switch to generic consistent + * DMA routines ... + */ + if (dev == NULL || pmif->dma_regs == 0) + return -ENODEV; + /* + * Allocate space for the DBDMA commands. + * The +2 is +1 for the stop command and +1 to allow for + * aligning the start address to a multiple of 16 bytes. + */ + pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent( + dev, + (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), + &hwif->dmatable_dma); + if (pmif->dma_table_cpu == NULL) { + printk(KERN_ERR "%s: unable to allocate DMA command list\n", + hwif->name); + return -ENOMEM; + } + + hwif->sg_max_nents = MAX_DCMDS; + + return 0; +} +#else +static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, + const struct ide_port_info *d) +{ + return -EOPNOTSUPP; +} +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + +module_init(pmac_ide_probe); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile deleted file mode 100644 index 74e52ad..0000000 --- a/drivers/ide/ppc/Makefile +++ /dev/null @@ -1,2 +0,0 @@ - -obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c deleted file mode 100644 index 2e19d62..0000000 --- a/drivers/ide/ppc/pmac.c +++ /dev/null @@ -1,1736 +0,0 @@ -/* - * Support for IDE interfaces on PowerMacs. - * - * These IDE interfaces are memory-mapped and have a DBDMA channel - * for doing DMA. - * - * Copyright (C) 1998-2003 Paul Mackerras & Ben. Herrenschmidt - * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Some code taken from drivers/ide/ide-dma.c: - * - * Copyright (c) 1995-1998 Mark Lord - * - * TODO: - Use pre-calculated (kauai) timing tables all the time and - * get rid of the "rounded" tables used previously, so we have the - * same table format for all controllers and can then just have one - * big table - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_PPC64 -#include -#endif - -#define DRV_NAME "ide-pmac" - -#undef IDE_PMAC_DEBUG - -#define DMA_WAIT_TIMEOUT 50 - -typedef struct pmac_ide_hwif { - unsigned long regbase; - int irq; - int kind; - int aapl_bus_id; - unsigned mediabay : 1; - unsigned broken_dma : 1; - unsigned broken_dma_warn : 1; - struct device_node* node; - struct macio_dev *mdev; - u32 timings[4]; - volatile u32 __iomem * *kauai_fcr; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - /* Those fields are duplicating what is in hwif. We currently - * can't use the hwif ones because of some assumptions that are - * beeing done by the generic code about the kind of dma controller - * and format of the dma table. This will have to be fixed though. - */ - volatile struct dbdma_regs __iomem * dma_regs; - struct dbdma_cmd* dma_table_cpu; -#endif - -} pmac_ide_hwif_t; - -enum { - controller_ohare, /* OHare based */ - controller_heathrow, /* Heathrow/Paddington */ - controller_kl_ata3, /* KeyLargo ATA-3 */ - controller_kl_ata4, /* KeyLargo ATA-4 */ - controller_un_ata6, /* UniNorth2 ATA-6 */ - controller_k2_ata6, /* K2 ATA-6 */ - controller_sh_ata6, /* Shasta ATA-6 */ -}; - -static const char* model_name[] = { - "OHare ATA", /* OHare based */ - "Heathrow ATA", /* Heathrow/Paddington */ - "KeyLargo ATA-3", /* KeyLargo ATA-3 (MDMA only) */ - "KeyLargo ATA-4", /* KeyLargo ATA-4 (UDMA/66) */ - "UniNorth ATA-6", /* UniNorth2 ATA-6 (UDMA/100) */ - "K2 ATA-6", /* K2 ATA-6 (UDMA/100) */ - "Shasta ATA-6", /* Shasta ATA-6 (UDMA/133) */ -}; - -/* - * Extra registers, both 32-bit little-endian - */ -#define IDE_TIMING_CONFIG 0x200 -#define IDE_INTERRUPT 0x300 - -/* Kauai (U2) ATA has different register setup */ -#define IDE_KAUAI_PIO_CONFIG 0x200 -#define IDE_KAUAI_ULTRA_CONFIG 0x210 -#define IDE_KAUAI_POLL_CONFIG 0x220 - -/* - * Timing configuration register definitions - */ - -/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ -#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) -#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) -#define IDE_SYSCLK_NS 30 /* 33Mhz cell */ -#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ - -/* 133Mhz cell, found in shasta. - * See comments about 100 Mhz Uninorth 2... - * Note that PIO_MASK and MDMA_MASK seem to overlap - */ -#define TR_133_PIOREG_PIO_MASK 0xff000fff -#define TR_133_PIOREG_MDMA_MASK 0x00fff800 -#define TR_133_UDMAREG_UDMA_MASK 0x0003ffff -#define TR_133_UDMAREG_UDMA_EN 0x00000001 - -/* 100Mhz cell, found in Uninorth 2. I don't have much infos about - * this one yet, it appears as a pci device (106b/0033) on uninorth - * internal PCI bus and it's clock is controlled like gem or fw. It - * appears to be an evolution of keylargo ATA4 with a timing register - * extended to 2 32bits registers and a similar DBDMA channel. Other - * registers seem to exist but I can't tell much about them. - * - * So far, I'm using pre-calculated tables for this extracted from - * the values used by the MacOS X driver. - * - * The "PIO" register controls PIO and MDMA timings, the "ULTRA" - * register controls the UDMA timings. At least, it seems bit 0 - * of this one enables UDMA vs. MDMA, and bits 4..7 are the - * cycle time in units of 10ns. Bits 8..15 are used by I don't - * know their meaning yet - */ -#define TR_100_PIOREG_PIO_MASK 0xff000fff -#define TR_100_PIOREG_MDMA_MASK 0x00fff000 -#define TR_100_UDMAREG_UDMA_MASK 0x0000ffff -#define TR_100_UDMAREG_UDMA_EN 0x00000001 - - -/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on - * 40 connector cable and to 4 on 80 connector one. - * Clock unit is 15ns (66Mhz) - * - * 3 Values can be programmed: - * - Write data setup, which appears to match the cycle time. They - * also call it DIOW setup. - * - Ready to pause time (from spec) - * - Address setup. That one is weird. I don't see where exactly - * it fits in UDMA cycles, I got it's name from an obscure piece - * of commented out code in Darwin. They leave it to 0, we do as - * well, despite a comment that would lead to think it has a - * min value of 45ns. - * Apple also add 60ns to the write data setup (or cycle time ?) on - * reads. - */ -#define TR_66_UDMA_MASK 0xfff00000 -#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ -#define TR_66_UDMA_ADDRSETUP_MASK 0xe0000000 /* Address setup */ -#define TR_66_UDMA_ADDRSETUP_SHIFT 29 -#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ -#define TR_66_UDMA_RDY2PAUS_SHIFT 25 -#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ -#define TR_66_UDMA_WRDATASETUP_SHIFT 21 -#define TR_66_MDMA_MASK 0x000ffc00 -#define TR_66_MDMA_RECOVERY_MASK 0x000f8000 -#define TR_66_MDMA_RECOVERY_SHIFT 15 -#define TR_66_MDMA_ACCESS_MASK 0x00007c00 -#define TR_66_MDMA_ACCESS_SHIFT 10 -#define TR_66_PIO_MASK 0x000003ff -#define TR_66_PIO_RECOVERY_MASK 0x000003e0 -#define TR_66_PIO_RECOVERY_SHIFT 5 -#define TR_66_PIO_ACCESS_MASK 0x0000001f -#define TR_66_PIO_ACCESS_SHIFT 0 - -/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo - * Can do pio & mdma modes, clock unit is 30ns (33Mhz) - * - * The access time and recovery time can be programmed. Some older - * Darwin code base limit OHare to 150ns cycle time. I decided to do - * the same here fore safety against broken old hardware ;) - * The HalfTick bit, when set, adds half a clock (15ns) to the access - * time and removes one from recovery. It's not supported on KeyLargo - * implementation afaik. The E bit appears to be set for PIO mode 0 and - * is used to reach long timings used in this mode. - */ -#define TR_33_MDMA_MASK 0x003ff800 -#define TR_33_MDMA_RECOVERY_MASK 0x001f0000 -#define TR_33_MDMA_RECOVERY_SHIFT 16 -#define TR_33_MDMA_ACCESS_MASK 0x0000f800 -#define TR_33_MDMA_ACCESS_SHIFT 11 -#define TR_33_MDMA_HALFTICK 0x00200000 -#define TR_33_PIO_MASK 0x000007ff -#define TR_33_PIO_E 0x00000400 -#define TR_33_PIO_RECOVERY_MASK 0x000003e0 -#define TR_33_PIO_RECOVERY_SHIFT 5 -#define TR_33_PIO_ACCESS_MASK 0x0000001f -#define TR_33_PIO_ACCESS_SHIFT 0 - -/* - * Interrupt register definitions - */ -#define IDE_INTR_DMA 0x80000000 -#define IDE_INTR_DEVICE 0x40000000 - -/* - * FCR Register on Kauai. Not sure what bit 0x4 is ... - */ -#define KAUAI_FCR_UATA_MAGIC 0x00000004 -#define KAUAI_FCR_UATA_RESET_N 0x00000002 -#define KAUAI_FCR_UATA_ENABLE 0x00000001 - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -/* Rounded Multiword DMA timings - * - * I gave up finding a generic formula for all controller - * types and instead, built tables based on timing values - * used by Apple in Darwin's implementation. - */ -struct mdma_timings_t { - int accessTime; - int recoveryTime; - int cycleTime; -}; - -struct mdma_timings_t mdma_timings_33[] = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 135, 135, 270 }, - { 120, 120, 240 }, - { 105, 105, 210 }, - { 90, 90, 180 }, - { 75, 75, 150 }, - { 75, 45, 120 }, - { 0, 0, 0 } -}; - -struct mdma_timings_t mdma_timings_33k[] = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 150, 150, 300 }, - { 120, 120, 240 }, - { 90, 120, 210 }, - { 90, 90, 180 }, - { 90, 60, 150 }, - { 90, 30, 120 }, - { 0, 0, 0 } -}; - -struct mdma_timings_t mdma_timings_66[] = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 135, 135, 270 }, - { 120, 120, 240 }, - { 105, 105, 210 }, - { 90, 90, 180 }, - { 90, 75, 165 }, - { 75, 45, 120 }, - { 0, 0, 0 } -}; - -/* KeyLargo ATA-4 Ultra DMA timings (rounded) */ -struct { - int addrSetup; /* ??? */ - int rdy2pause; - int wrDataSetup; -} kl66_udma_timings[] = -{ - { 0, 180, 120 }, /* Mode 0 */ - { 0, 150, 90 }, /* 1 */ - { 0, 120, 60 }, /* 2 */ - { 0, 90, 45 }, /* 3 */ - { 0, 90, 30 } /* 4 */ -}; - -/* UniNorth 2 ATA/100 timings */ -struct kauai_timing { - int cycle_time; - u32 timing_reg; -}; - -static struct kauai_timing kauai_pio_timings[] = -{ - { 930 , 0x08000fff }, - { 600 , 0x08000a92 }, - { 383 , 0x0800060f }, - { 360 , 0x08000492 }, - { 330 , 0x0800048f }, - { 300 , 0x080003cf }, - { 270 , 0x080003cc }, - { 240 , 0x0800038b }, - { 239 , 0x0800030c }, - { 180 , 0x05000249 }, - { 120 , 0x04000148 }, - { 0 , 0 }, -}; - -static struct kauai_timing kauai_mdma_timings[] = -{ - { 1260 , 0x00fff000 }, - { 480 , 0x00618000 }, - { 360 , 0x00492000 }, - { 270 , 0x0038e000 }, - { 240 , 0x0030c000 }, - { 210 , 0x002cb000 }, - { 180 , 0x00249000 }, - { 150 , 0x00209000 }, - { 120 , 0x00148000 }, - { 0 , 0 }, -}; - -static struct kauai_timing kauai_udma_timings[] = -{ - { 120 , 0x000070c0 }, - { 90 , 0x00005d80 }, - { 60 , 0x00004a60 }, - { 45 , 0x00003a50 }, - { 30 , 0x00002a30 }, - { 20 , 0x00002921 }, - { 0 , 0 }, -}; - -static struct kauai_timing shasta_pio_timings[] = -{ - { 930 , 0x08000fff }, - { 600 , 0x0A000c97 }, - { 383 , 0x07000712 }, - { 360 , 0x040003cd }, - { 330 , 0x040003cd }, - { 300 , 0x040003cd }, - { 270 , 0x040003cd }, - { 240 , 0x040003cd }, - { 239 , 0x040003cd }, - { 180 , 0x0400028b }, - { 120 , 0x0400010a }, - { 0 , 0 }, -}; - -static struct kauai_timing shasta_mdma_timings[] = -{ - { 1260 , 0x00fff000 }, - { 480 , 0x00820800 }, - { 360 , 0x00820800 }, - { 270 , 0x00820800 }, - { 240 , 0x00820800 }, - { 210 , 0x00820800 }, - { 180 , 0x00820800 }, - { 150 , 0x0028b000 }, - { 120 , 0x001ca000 }, - { 0 , 0 }, -}; - -static struct kauai_timing shasta_udma133_timings[] = -{ - { 120 , 0x00035901, }, - { 90 , 0x000348b1, }, - { 60 , 0x00033881, }, - { 45 , 0x00033861, }, - { 30 , 0x00033841, }, - { 20 , 0x00033031, }, - { 15 , 0x00033021, }, - { 0 , 0 }, -}; - - -static inline u32 -kauai_lookup_timing(struct kauai_timing* table, int cycle_time) -{ - int i; - - for (i=0; table[i].cycle_time; i++) - if (cycle_time > table[i+1].cycle_time) - return table[i].timing_reg; - BUG(); - return 0; -} - -/* allow up to 256 DBDMA commands per xfer */ -#define MAX_DCMDS 256 - -/* - * Wait 1s for disk to answer on IDE bus after a hard reset - * of the device (via GPIO/FCR). - * - * Some devices seem to "pollute" the bus even after dropping - * the BSY bit (typically some combo drives slave on the UDMA - * bus) after a hard reset. Since we hard reset all drives on - * KeyLargo ATA66, we have to keep that delay around. I may end - * up not hard resetting anymore on these and keep the delay only - * for older interfaces instead (we have to reset when coming - * from MacOS...) --BenH. - */ -#define IDE_WAKEUP_DELAY (1*HZ) - -static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *); -static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq); -static void pmac_ide_selectproc(ide_drive_t *drive); -static void pmac_ide_kauai_selectproc(ide_drive_t *drive); - -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - -#define PMAC_IDE_REG(x) \ - ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x))) - -/* - * Apply the timings of the proper unit (master/slave) to the shared - * timing register when selecting that unit. This version is for - * ASICs with a single timing register - */ -static void -pmac_ide_selectproc(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - - if (drive->dn & 1) - writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG)); - else - writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG)); - (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); -} - -/* - * Apply the timings of the proper unit (master/slave) to the shared - * timing register when selecting that unit. This version is for - * ASICs with a dual timing register (Kauai) - */ -static void -pmac_ide_kauai_selectproc(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - - if (drive->dn & 1) { - writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); - writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); - } else { - writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); - writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); - } - (void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); -} - -/* - * Force an update of controller timing values for a given drive - */ -static void -pmac_ide_do_update_timings(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - - if (pmif->kind == controller_sh_ata6 || - pmif->kind == controller_un_ata6 || - pmif->kind == controller_k2_ata6) - pmac_ide_kauai_selectproc(drive); - else - pmac_ide_selectproc(drive); -} - -static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd) -{ - writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); - (void)readl((void __iomem *)(hwif->io_ports.data_addr - + IDE_TIMING_CONFIG)); -} - -static void pmac_set_irq(ide_hwif_t *hwif, int on) -{ - u8 ctl = ATA_DEVCTL_OBS; - - if (on == 4) { /* hack for SRST */ - ctl |= 4; - on &= ~4; - } - - ctl |= on ? 0 : 2; - - writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); - (void)readl((void __iomem *)(hwif->io_ports.data_addr - + IDE_TIMING_CONFIG)); -} - -/* - * Old tuning functions (called on hdparm -p), sets up drive PIO timings - */ -static void -pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio); - u32 *timings, t; - unsigned accessTicks, recTicks; - unsigned accessTime, recTime; - unsigned int cycle_time; - - /* which drive is it ? */ - timings = &pmif->timings[drive->dn & 1]; - t = *timings; - - cycle_time = ide_pio_cycle_time(drive, pio); - - switch (pmif->kind) { - case controller_sh_ata6: { - /* 133Mhz cell */ - u32 tr = kauai_lookup_timing(shasta_pio_timings, cycle_time); - t = (t & ~TR_133_PIOREG_PIO_MASK) | tr; - break; - } - case controller_un_ata6: - case controller_k2_ata6: { - /* 100Mhz cell */ - u32 tr = kauai_lookup_timing(kauai_pio_timings, cycle_time); - t = (t & ~TR_100_PIOREG_PIO_MASK) | tr; - break; - } - case controller_kl_ata4: - /* 66Mhz cell */ - recTime = cycle_time - tim->active - tim->setup; - recTime = max(recTime, 150U); - accessTime = tim->active; - accessTime = max(accessTime, 150U); - accessTicks = SYSCLK_TICKS_66(accessTime); - accessTicks = min(accessTicks, 0x1fU); - recTicks = SYSCLK_TICKS_66(recTime); - recTicks = min(recTicks, 0x1fU); - t = (t & ~TR_66_PIO_MASK) | - (accessTicks << TR_66_PIO_ACCESS_SHIFT) | - (recTicks << TR_66_PIO_RECOVERY_SHIFT); - break; - default: { - /* 33Mhz cell */ - int ebit = 0; - recTime = cycle_time - tim->active - tim->setup; - recTime = max(recTime, 150U); - accessTime = tim->active; - accessTime = max(accessTime, 150U); - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = min(accessTicks, 0x1fU); - accessTicks = max(accessTicks, 4U); - recTicks = SYSCLK_TICKS(recTime); - recTicks = min(recTicks, 0x1fU); - recTicks = max(recTicks, 5U) - 4; - if (recTicks > 9) { - recTicks--; /* guess, but it's only for PIO0, so... */ - ebit = 1; - } - t = (t & ~TR_33_PIO_MASK) | - (accessTicks << TR_33_PIO_ACCESS_SHIFT) | - (recTicks << TR_33_PIO_RECOVERY_SHIFT); - if (ebit) - t |= TR_33_PIO_E; - break; - } - } - -#ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "%s: Set PIO timing for mode %d, reg: 0x%08x\n", - drive->name, pio, *timings); -#endif - - *timings = t; - pmac_ide_do_update_timings(drive); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -/* - * Calculate KeyLargo ATA/66 UDMA timings - */ -static int -set_timings_udma_ata4(u32 *timings, u8 speed) -{ - unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; - - if (speed > XFER_UDMA_4) - return 1; - - rdyToPauseTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].rdy2pause); - wrDataSetupTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].wrDataSetup); - addrTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].addrSetup); - - *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) | - (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | - (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) | - (addrTicks < XFER_UDMA_5 || t == NULL) - return 1; - tr = kauai_lookup_timing(kauai_udma_timings, (int)t->udma); - *ultra_timings = ((*ultra_timings) & ~TR_100_UDMAREG_UDMA_MASK) | tr; - *ultra_timings = (*ultra_timings) | TR_100_UDMAREG_UDMA_EN; - - return 0; -} - -/* - * Calculate Shasta ATA/133 UDMA timings - */ -static int -set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed) -{ - struct ide_timing *t = ide_timing_find_mode(speed); - u32 tr; - - if (speed > XFER_UDMA_6 || t == NULL) - return 1; - tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma); - *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr; - *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN; - - return 0; -} - -/* - * Calculate MDMA timings for all cells - */ -static void -set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, - u8 speed) -{ - u16 *id = drive->id; - int cycleTime, accessTime = 0, recTime = 0; - unsigned accessTicks, recTicks; - struct mdma_timings_t* tm = NULL; - int i; - - /* Get default cycle time for mode */ - switch(speed & 0xf) { - case 0: cycleTime = 480; break; - case 1: cycleTime = 150; break; - case 2: cycleTime = 120; break; - default: - BUG(); - break; - } - - /* Check if drive provides explicit DMA cycle time */ - if ((id[ATA_ID_FIELD_VALID] & 2) && id[ATA_ID_EIDE_DMA_TIME]) - cycleTime = max_t(int, id[ATA_ID_EIDE_DMA_TIME], cycleTime); - - /* OHare limits according to some old Apple sources */ - if ((intf_type == controller_ohare) && (cycleTime < 150)) - cycleTime = 150; - /* Get the proper timing array for this controller */ - switch(intf_type) { - case controller_sh_ata6: - case controller_un_ata6: - case controller_k2_ata6: - break; - case controller_kl_ata4: - tm = mdma_timings_66; - break; - case controller_kl_ata3: - tm = mdma_timings_33k; - break; - default: - tm = mdma_timings_33; - break; - } - if (tm != NULL) { - /* Lookup matching access & recovery times */ - i = -1; - for (;;) { - if (tm[i+1].cycleTime < cycleTime) - break; - i++; - } - cycleTime = tm[i].cycleTime; - accessTime = tm[i].accessTime; - recTime = tm[i].recoveryTime; - -#ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "%s: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n", - drive->name, cycleTime, accessTime, recTime); -#endif - } - switch(intf_type) { - case controller_sh_ata6: { - /* 133Mhz cell */ - u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime); - *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr; - *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN; - } - case controller_un_ata6: - case controller_k2_ata6: { - /* 100Mhz cell */ - u32 tr = kauai_lookup_timing(kauai_mdma_timings, cycleTime); - *timings = ((*timings) & ~TR_100_PIOREG_MDMA_MASK) | tr; - *timings2 = (*timings2) & ~TR_100_UDMAREG_UDMA_EN; - } - break; - case controller_kl_ata4: - /* 66Mhz cell */ - accessTicks = SYSCLK_TICKS_66(accessTime); - accessTicks = min(accessTicks, 0x1fU); - accessTicks = max(accessTicks, 0x1U); - recTicks = SYSCLK_TICKS_66(recTime); - recTicks = min(recTicks, 0x1fU); - recTicks = max(recTicks, 0x3U); - /* Clear out mdma bits and disable udma */ - *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) | - (accessTicks << TR_66_MDMA_ACCESS_SHIFT) | - (recTicks << TR_66_MDMA_RECOVERY_SHIFT); - break; - case controller_kl_ata3: - /* 33Mhz cell on KeyLargo */ - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = max(accessTicks, 1U); - accessTicks = min(accessTicks, 0x1fU); - accessTime = accessTicks * IDE_SYSCLK_NS; - recTicks = SYSCLK_TICKS(recTime); - recTicks = max(recTicks, 1U); - recTicks = min(recTicks, 0x1fU); - *timings = ((*timings) & ~TR_33_MDMA_MASK) | - (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | - (recTicks << TR_33_MDMA_RECOVERY_SHIFT); - break; - default: { - /* 33Mhz cell on others */ - int halfTick = 0; - int origAccessTime = accessTime; - int origRecTime = recTime; - - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = max(accessTicks, 1U); - accessTicks = min(accessTicks, 0x1fU); - accessTime = accessTicks * IDE_SYSCLK_NS; - recTicks = SYSCLK_TICKS(recTime); - recTicks = max(recTicks, 2U) - 1; - recTicks = min(recTicks, 0x1fU); - recTime = (recTicks + 1) * IDE_SYSCLK_NS; - if ((accessTicks > 1) && - ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && - ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) { - halfTick = 1; - accessTicks--; - } - *timings = ((*timings) & ~TR_33_MDMA_MASK) | - (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | - (recTicks << TR_33_MDMA_RECOVERY_SHIFT); - if (halfTick) - *timings |= TR_33_MDMA_HALFTICK; - } - } -#ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "%s: Set MDMA timing for mode %d, reg: 0x%08x\n", - drive->name, speed & 0xf, *timings); -#endif -} -#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */ - -static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - int ret = 0; - u32 *timings, *timings2, tl[2]; - u8 unit = drive->dn & 1; - - timings = &pmif->timings[unit]; - timings2 = &pmif->timings[unit+2]; - - /* Copy timings to local image */ - tl[0] = *timings; - tl[1] = *timings2; - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - if (speed >= XFER_UDMA_0) { - if (pmif->kind == controller_kl_ata4) - ret = set_timings_udma_ata4(&tl[0], speed); - else if (pmif->kind == controller_un_ata6 - || pmif->kind == controller_k2_ata6) - ret = set_timings_udma_ata6(&tl[0], &tl[1], speed); - else if (pmif->kind == controller_sh_ata6) - ret = set_timings_udma_shasta(&tl[0], &tl[1], speed); - else - ret = -1; - } else - set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed); -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - if (ret) - return; - - /* Apply timings to controller */ - *timings = tl[0]; - *timings2 = tl[1]; - - pmac_ide_do_update_timings(drive); -} - -/* - * Blast some well known "safe" values to the timing registers at init or - * wakeup from sleep time, before we do real calculation - */ -static void -sanitize_timings(pmac_ide_hwif_t *pmif) -{ - unsigned int value, value2 = 0; - - switch(pmif->kind) { - case controller_sh_ata6: - value = 0x0a820c97; - value2 = 0x00033031; - break; - case controller_un_ata6: - case controller_k2_ata6: - value = 0x08618a92; - value2 = 0x00002921; - break; - case controller_kl_ata4: - value = 0x0008438c; - break; - case controller_kl_ata3: - value = 0x00084526; - break; - case controller_heathrow: - case controller_ohare: - default: - value = 0x00074526; - break; - } - pmif->timings[0] = pmif->timings[1] = value; - pmif->timings[2] = pmif->timings[3] = value2; -} - -/* Suspend call back, should be called after the child devices - * have actually been suspended - */ -static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif) -{ - /* We clear the timings */ - pmif->timings[0] = 0; - pmif->timings[1] = 0; - - disable_irq(pmif->irq); - - /* The media bay will handle itself just fine */ - if (pmif->mediabay) - return 0; - - /* Kauai has bus control FCRs directly here */ - if (pmif->kauai_fcr) { - u32 fcr = readl(pmif->kauai_fcr); - fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); - writel(fcr, pmif->kauai_fcr); - } - - /* Disable the bus on older machines and the cell on kauai */ - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, - 0); - - return 0; -} - -/* Resume call back, should be called before the child devices - * are resumed - */ -static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif) -{ - /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */ - if (!pmif->mediabay) { - ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1); - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1); - msleep(10); - ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0); - - /* Kauai has it different */ - if (pmif->kauai_fcr) { - u32 fcr = readl(pmif->kauai_fcr); - fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE; - writel(fcr, pmif->kauai_fcr); - } - - msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); - } - - /* Sanitize drive timings */ - sanitize_timings(pmif); - - enable_irq(pmif->irq); - - return 0; -} - -static u8 pmac_ide_cable_detect(ide_hwif_t *hwif) -{ - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - struct device_node *np = pmif->node; - const char *cable = of_get_property(np, "cable-type", NULL); - - /* Get cable type from device-tree. */ - if (cable && !strncmp(cable, "80-", 3)) - return ATA_CBL_PATA80; - - /* - * G5's seem to have incorrect cable type in device-tree. - * Let's assume they have a 80 conductor cable, this seem - * to be always the case unless the user mucked around. - */ - if (of_device_is_compatible(np, "K2-UATA") || - of_device_is_compatible(np, "shasta-ata")) - return ATA_CBL_PATA80; - - return ATA_CBL_PATA40; -} - -static void pmac_ide_init_dev(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - - if (pmif->mediabay) { -#ifdef CONFIG_PMAC_MEDIABAY - if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) { - drive->dev_flags &= ~IDE_DFLAG_NOPROBE; - return; - } -#endif - drive->dev_flags |= IDE_DFLAG_NOPROBE; - } -} - -static const struct ide_tp_ops pmac_tp_ops = { - .exec_command = pmac_exec_command, - .read_status = ide_read_status, - .read_altstatus = ide_read_altstatus, - .read_sff_dma_status = ide_read_sff_dma_status, - - .set_irq = pmac_set_irq, - - .tf_load = ide_tf_load, - .tf_read = ide_tf_read, - - .input_data = ide_input_data, - .output_data = ide_output_data, -}; - -static const struct ide_port_ops pmac_ide_ata6_port_ops = { - .init_dev = pmac_ide_init_dev, - .set_pio_mode = pmac_ide_set_pio_mode, - .set_dma_mode = pmac_ide_set_dma_mode, - .selectproc = pmac_ide_kauai_selectproc, - .cable_detect = pmac_ide_cable_detect, -}; - -static const struct ide_port_ops pmac_ide_ata4_port_ops = { - .init_dev = pmac_ide_init_dev, - .set_pio_mode = pmac_ide_set_pio_mode, - .set_dma_mode = pmac_ide_set_dma_mode, - .selectproc = pmac_ide_selectproc, - .cable_detect = pmac_ide_cable_detect, -}; - -static const struct ide_port_ops pmac_ide_port_ops = { - .init_dev = pmac_ide_init_dev, - .set_pio_mode = pmac_ide_set_pio_mode, - .set_dma_mode = pmac_ide_set_dma_mode, - .selectproc = pmac_ide_selectproc, -}; - -static const struct ide_dma_ops pmac_dma_ops; - -static const struct ide_port_info pmac_port_info = { - .name = DRV_NAME, - .init_dma = pmac_ide_init_dma, - .chipset = ide_pmac, - .tp_ops = &pmac_tp_ops, - .port_ops = &pmac_ide_port_ops, -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - .dma_ops = &pmac_dma_ops, -#endif - .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | - IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_MMIO | - IDE_HFLAG_UNMASK_IRQS, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, -}; - -/* - * Setup, register & probe an IDE channel driven by this driver, this is - * called by one of the 2 probe functions (macio or PCI). - */ -static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw) -{ - struct device_node *np = pmif->node; - const int *bidp; - struct ide_host *host; - ide_hwif_t *hwif; - hw_regs_t *hws[] = { hw, NULL, NULL, NULL }; - struct ide_port_info d = pmac_port_info; - int rc; - - pmif->broken_dma = pmif->broken_dma_warn = 0; - if (of_device_is_compatible(np, "shasta-ata")) { - pmif->kind = controller_sh_ata6; - d.port_ops = &pmac_ide_ata6_port_ops; - d.udma_mask = ATA_UDMA6; - } else if (of_device_is_compatible(np, "kauai-ata")) { - pmif->kind = controller_un_ata6; - d.port_ops = &pmac_ide_ata6_port_ops; - d.udma_mask = ATA_UDMA5; - } else if (of_device_is_compatible(np, "K2-UATA")) { - pmif->kind = controller_k2_ata6; - d.port_ops = &pmac_ide_ata6_port_ops; - d.udma_mask = ATA_UDMA5; - } else if (of_device_is_compatible(np, "keylargo-ata")) { - if (strcmp(np->name, "ata-4") == 0) { - pmif->kind = controller_kl_ata4; - d.port_ops = &pmac_ide_ata4_port_ops; - d.udma_mask = ATA_UDMA4; - } else - pmif->kind = controller_kl_ata3; - } else if (of_device_is_compatible(np, "heathrow-ata")) { - pmif->kind = controller_heathrow; - } else { - pmif->kind = controller_ohare; - pmif->broken_dma = 1; - } - - bidp = of_get_property(np, "AAPL,bus-id", NULL); - pmif->aapl_bus_id = bidp ? *bidp : 0; - - /* On Kauai-type controllers, we make sure the FCR is correct */ - if (pmif->kauai_fcr) - writel(KAUAI_FCR_UATA_MAGIC | - KAUAI_FCR_UATA_RESET_N | - KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr); - - pmif->mediabay = 0; - - /* Make sure we have sane timings */ - sanitize_timings(pmif); - - host = ide_host_alloc(&d, hws); - if (host == NULL) - return -ENOMEM; - hwif = host->ports[0]; - -#ifndef CONFIG_PPC64 - /* XXX FIXME: Media bay stuff need re-organizing */ - if (np->parent && np->parent->name - && strcasecmp(np->parent->name, "media-bay") == 0) { -#ifdef CONFIG_PMAC_MEDIABAY - media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, - hwif); -#endif /* CONFIG_PMAC_MEDIABAY */ - pmif->mediabay = 1; - if (!bidp) - pmif->aapl_bus_id = 1; - } else if (pmif->kind == controller_ohare) { - /* The code below is having trouble on some ohare machines - * (timing related ?). Until I can put my hand on one of these - * units, I keep the old way - */ - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); - } else -#endif - { - /* This is necessary to enable IDE when net-booting */ - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); - msleep(10); - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0); - msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); - } - - printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), " - "bus ID %d%s, irq %d\n", model_name[pmif->kind], - pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id, - pmif->mediabay ? " (mediabay)" : "", hw->irq); - - rc = ide_host_register(host, &d, hws); - if (rc) { - ide_host_free(host); - return rc; - } - - return 0; -} - -static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base) -{ - int i; - - for (i = 0; i < 8; ++i) - hw->io_ports_array[i] = base + i * 0x10; - - hw->io_ports.ctl_addr = base + 0x160; -} - -/* - * Attach to a macio probed interface - */ -static int __devinit -pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) -{ - void __iomem *base; - unsigned long regbase; - pmac_ide_hwif_t *pmif; - int irq, rc; - hw_regs_t hw; - - pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); - if (pmif == NULL) - return -ENOMEM; - - if (macio_resource_count(mdev) == 0) { - printk(KERN_WARNING "ide-pmac: no address for %s\n", - mdev->ofdev.node->full_name); - rc = -ENXIO; - goto out_free_pmif; - } - - /* Request memory resource for IO ports */ - if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) { - printk(KERN_ERR "ide-pmac: can't request MMIO resource for " - "%s!\n", mdev->ofdev.node->full_name); - rc = -EBUSY; - goto out_free_pmif; - } - - /* XXX This is bogus. Should be fixed in the registry by checking - * the kind of host interrupt controller, a bit like gatwick - * fixes in irq.c. That works well enough for the single case - * where that happens though... - */ - if (macio_irq_count(mdev) == 0) { - printk(KERN_WARNING "ide-pmac: no intrs for device %s, using " - "13\n", mdev->ofdev.node->full_name); - irq = irq_create_mapping(NULL, 13); - } else - irq = macio_irq(mdev, 0); - - base = ioremap(macio_resource_start(mdev, 0), 0x400); - regbase = (unsigned long) base; - - pmif->mdev = mdev; - pmif->node = mdev->ofdev.node; - pmif->regbase = regbase; - pmif->irq = irq; - pmif->kauai_fcr = NULL; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - if (macio_resource_count(mdev) >= 2) { - if (macio_request_resource(mdev, 1, "ide-pmac (dma)")) - printk(KERN_WARNING "ide-pmac: can't request DMA " - "resource for %s!\n", - mdev->ofdev.node->full_name); - else - pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000); - } else - pmif->dma_regs = NULL; -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - dev_set_drvdata(&mdev->ofdev.dev, pmif); - - memset(&hw, 0, sizeof(hw)); - pmac_ide_init_ports(&hw, pmif->regbase); - hw.irq = irq; - hw.dev = &mdev->bus->pdev->dev; - hw.parent = &mdev->ofdev.dev; - - rc = pmac_ide_setup_device(pmif, &hw); - if (rc != 0) { - /* The inteface is released to the common IDE layer */ - dev_set_drvdata(&mdev->ofdev.dev, NULL); - iounmap(base); - if (pmif->dma_regs) { - iounmap(pmif->dma_regs); - macio_release_resource(mdev, 1); - } - macio_release_resource(mdev, 0); - kfree(pmif); - } - - return rc; - -out_free_pmif: - kfree(pmif); - return rc; -} - -static int -pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg) -{ - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); - int rc = 0; - - if (mesg.event != mdev->ofdev.dev.power.power_state.event - && (mesg.event & PM_EVENT_SLEEP)) { - rc = pmac_ide_do_suspend(pmif); - if (rc == 0) - mdev->ofdev.dev.power.power_state = mesg; - } - - return rc; -} - -static int -pmac_ide_macio_resume(struct macio_dev *mdev) -{ - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); - int rc = 0; - - if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) { - rc = pmac_ide_do_resume(pmif); - if (rc == 0) - mdev->ofdev.dev.power.power_state = PMSG_ON; - } - - return rc; -} - -/* - * Attach to a PCI probed interface - */ -static int __devinit -pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct device_node *np; - pmac_ide_hwif_t *pmif; - void __iomem *base; - unsigned long rbase, rlen; - int rc; - hw_regs_t hw; - - np = pci_device_to_OF_node(pdev); - if (np == NULL) { - printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n"); - return -ENODEV; - } - - pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); - if (pmif == NULL) - return -ENOMEM; - - if (pci_enable_device(pdev)) { - printk(KERN_WARNING "ide-pmac: Can't enable PCI device for " - "%s\n", np->full_name); - rc = -ENXIO; - goto out_free_pmif; - } - pci_set_master(pdev); - - if (pci_request_regions(pdev, "Kauai ATA")) { - printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for " - "%s\n", np->full_name); - rc = -ENXIO; - goto out_free_pmif; - } - - pmif->mdev = NULL; - pmif->node = np; - - rbase = pci_resource_start(pdev, 0); - rlen = pci_resource_len(pdev, 0); - - base = ioremap(rbase, rlen); - pmif->regbase = (unsigned long) base + 0x2000; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - pmif->dma_regs = base + 0x1000; -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - pmif->kauai_fcr = base; - pmif->irq = pdev->irq; - - pci_set_drvdata(pdev, pmif); - - memset(&hw, 0, sizeof(hw)); - pmac_ide_init_ports(&hw, pmif->regbase); - hw.irq = pdev->irq; - hw.dev = &pdev->dev; - - rc = pmac_ide_setup_device(pmif, &hw); - if (rc != 0) { - /* The inteface is released to the common IDE layer */ - pci_set_drvdata(pdev, NULL); - iounmap(base); - pci_release_regions(pdev); - kfree(pmif); - } - - return rc; - -out_free_pmif: - kfree(pmif); - return rc; -} - -static int -pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) -{ - pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev); - int rc = 0; - - if (mesg.event != pdev->dev.power.power_state.event - && (mesg.event & PM_EVENT_SLEEP)) { - rc = pmac_ide_do_suspend(pmif); - if (rc == 0) - pdev->dev.power.power_state = mesg; - } - - return rc; -} - -static int -pmac_ide_pci_resume(struct pci_dev *pdev) -{ - pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev); - int rc = 0; - - if (pdev->dev.power.power_state.event != PM_EVENT_ON) { - rc = pmac_ide_do_resume(pmif); - if (rc == 0) - pdev->dev.power.power_state = PMSG_ON; - } - - return rc; -} - -static struct of_device_id pmac_ide_macio_match[] = -{ - { - .name = "IDE", - }, - { - .name = "ATA", - }, - { - .type = "ide", - }, - { - .type = "ata", - }, - {}, -}; - -static struct macio_driver pmac_ide_macio_driver = -{ - .name = "ide-pmac", - .match_table = pmac_ide_macio_match, - .probe = pmac_ide_macio_attach, - .suspend = pmac_ide_macio_suspend, - .resume = pmac_ide_macio_resume, -}; - -static const struct pci_device_id pmac_ide_pci_match[] = { - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA), 0 }, - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100), 0 }, - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100), 0 }, - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA), 0 }, - { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA), 0 }, - {}, -}; - -static struct pci_driver pmac_ide_pci_driver = { - .name = "ide-pmac", - .id_table = pmac_ide_pci_match, - .probe = pmac_ide_pci_attach, - .suspend = pmac_ide_pci_suspend, - .resume = pmac_ide_pci_resume, -}; -MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match); - -int __init pmac_ide_probe(void) -{ - int error; - - if (!machine_is(powermac)) - return -ENODEV; - -#ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST - error = pci_register_driver(&pmac_ide_pci_driver); - if (error) - goto out; - error = macio_register_driver(&pmac_ide_macio_driver); - if (error) { - pci_unregister_driver(&pmac_ide_pci_driver); - goto out; - } -#else - error = macio_register_driver(&pmac_ide_macio_driver); - if (error) - goto out; - error = pci_register_driver(&pmac_ide_pci_driver); - if (error) { - macio_unregister_driver(&pmac_ide_macio_driver); - goto out; - } -#endif -out: - return error; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -/* - * pmac_ide_build_dmatable builds the DBDMA command list - * for a transfer and sets the DBDMA channel to point to it. - */ -static int -pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - struct dbdma_cmd *table; - int i, count = 0; - volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; - struct scatterlist *sg; - int wr = (rq_data_dir(rq) == WRITE); - - /* DMA table is already aligned */ - table = (struct dbdma_cmd *) pmif->dma_table_cpu; - - /* Make sure DMA controller is stopped (necessary ?) */ - writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma->control); - while (readl(&dma->status) & RUN) - udelay(1); - - hwif->sg_nents = i = ide_build_sglist(drive, rq); - - if (!i) - return 0; - - /* Build DBDMA commands list */ - sg = hwif->sg_table; - while (i && sg_dma_len(sg)) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) { - if (pmif->broken_dma_warn == 0) { - printk(KERN_WARNING "%s: DMA on non aligned address, " - "switching to PIO on Ohare chipset\n", drive->name); - pmif->broken_dma_warn = 1; - } - goto use_pio_instead; - } - while (cur_len) { - unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; - - if (count++ >= MAX_DCMDS) { - printk(KERN_WARNING "%s: DMA table too small\n", - drive->name); - goto use_pio_instead; - } - st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); - st_le16(&table->req_count, tc); - st_le32(&table->phy_addr, cur_addr); - table->cmd_dep = 0; - table->xfer_status = 0; - table->res_count = 0; - cur_addr += tc; - cur_len -= tc; - ++table; - } - sg = sg_next(sg); - i--; - } - - /* convert the last command to an input/output last command */ - if (count) { - st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); - /* add the stop command to the end of the list */ - memset(table, 0, sizeof(struct dbdma_cmd)); - st_le16(&table->command, DBDMA_STOP); - mb(); - writel(hwif->dmatable_dma, &dma->cmdptr); - return 1; - } - - printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); - -use_pio_instead: - ide_destroy_dmatable(drive); - - return 0; /* revert to PIO for this request */ -} - -/* - * Prepare a DMA transfer. We build the DMA table, adjust the timings for - * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion - */ -static int -pmac_ide_dma_setup(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - struct request *rq = HWGROUP(drive)->rq; - u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4); - - if (!pmac_ide_build_dmatable(drive, rq)) { - ide_map_sg(drive, rq); - return 1; - } - - /* Apple adds 60ns to wrDataSetup on reads */ - if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { - writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0), - PMAC_IDE_REG(IDE_TIMING_CONFIG)); - (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); - } - - drive->waiting_for_dma = 1; - - return 0; -} - -static void -pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) -{ - /* issue cmd to drive */ - ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); -} - -/* - * Kick the DMA controller into life after the DMA command has been issued - * to the drive. - */ -static void -pmac_ide_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - volatile struct dbdma_regs __iomem *dma; - - dma = pmif->dma_regs; - - writel((RUN << 16) | RUN, &dma->control); - /* Make sure it gets to the controller right now */ - (void)readl(&dma->control); -} - -/* - * After a DMA transfer, make sure the controller is stopped - */ -static int -pmac_ide_dma_end (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; - u32 dstat; - - drive->waiting_for_dma = 0; - dstat = readl(&dma->status); - writel(((RUN|WAKE|DEAD) << 16), &dma->control); - - ide_destroy_dmatable(drive); - - /* verify good dma status. we don't check for ACTIVE beeing 0. We should... - * in theory, but with ATAPI decices doing buffer underruns, that would - * cause us to disable DMA, which isn't what we want - */ - return (dstat & (RUN|DEAD)) != RUN; -} - -/* - * Check out that the interrupt we got was for us. We can't always know this - * for sure with those Apple interfaces (well, we could on the recent ones but - * that's not implemented yet), on the other hand, we don't have shared interrupts - * so it's not really a problem - */ -static int -pmac_ide_dma_test_irq (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; - unsigned long status, timeout; - - /* We have to things to deal with here: - * - * - The dbdma won't stop if the command was started - * but completed with an error without transferring all - * datas. This happens when bad blocks are met during - * a multi-block transfer. - * - * - The dbdma fifo hasn't yet finished flushing to - * to system memory when the disk interrupt occurs. - * - */ - - /* If ACTIVE is cleared, the STOP command have passed and - * transfer is complete. - */ - status = readl(&dma->status); - if (!(status & ACTIVE)) - return 1; - - /* If dbdma didn't execute the STOP command yet, the - * active bit is still set. We consider that we aren't - * sharing interrupts (which is hopefully the case with - * those controllers) and so we just try to flush the - * channel for pending data in the fifo - */ - udelay(1); - writel((FLUSH << 16) | FLUSH, &dma->control); - timeout = 0; - for (;;) { - udelay(1); - status = readl(&dma->status); - if ((status & FLUSH) == 0) - break; - if (++timeout > 100) { - printk(KERN_WARNING "ide%d, ide_dma_test_irq \ - timeout flushing channel\n", HWIF(drive)->index); - break; - } - } - return 1; -} - -static void pmac_ide_dma_host_set(ide_drive_t *drive, int on) -{ -} - -static void -pmac_ide_dma_lost_irq (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; - unsigned long status = readl(&dma->status); - - printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status); -} - -static const struct ide_dma_ops pmac_dma_ops = { - .dma_host_set = pmac_ide_dma_host_set, - .dma_setup = pmac_ide_dma_setup, - .dma_exec_cmd = pmac_ide_dma_exec_cmd, - .dma_start = pmac_ide_dma_start, - .dma_end = pmac_ide_dma_end, - .dma_test_irq = pmac_ide_dma_test_irq, - .dma_timeout = ide_dma_timeout, - .dma_lost_irq = pmac_ide_dma_lost_irq, -}; - -/* - * Allocate the data structures needed for using DMA with an interface - * and fill the proper list of functions pointers - */ -static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, - const struct ide_port_info *d) -{ - pmac_ide_hwif_t *pmif = - (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - struct pci_dev *dev = to_pci_dev(hwif->dev); - - /* We won't need pci_dev if we switch to generic consistent - * DMA routines ... - */ - if (dev == NULL || pmif->dma_regs == 0) - return -ENODEV; - /* - * Allocate space for the DBDMA commands. - * The +2 is +1 for the stop command and +1 to allow for - * aligning the start address to a multiple of 16 bytes. - */ - pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent( - dev, - (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), - &hwif->dmatable_dma); - if (pmif->dma_table_cpu == NULL) { - printk(KERN_ERR "%s: unable to allocate DMA command list\n", - hwif->name); - return -ENOMEM; - } - - hwif->sg_max_nents = MAX_DCMDS; - - return 0; -} -#else -static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, - const struct ide_port_info *d) -{ - return -EOPNOTSUPP; -} -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - -module_init(pmac_ide_probe); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c new file mode 100644 index 0000000..4af4a8c --- /dev/null +++ b/drivers/ide/q40ide.c @@ -0,0 +1,165 @@ +/* + * Q40 I/O port IDE Driver + * + * (c) Richard Zidlicky + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * + */ + +#include +#include +#include +#include +#include + + /* + * Bases of the IDE interfaces + */ + +#define Q40IDE_NUM_HWIFS 2 + +#define PCIDE_BASE1 0x1f0 +#define PCIDE_BASE2 0x170 +#define PCIDE_BASE3 0x1e8 +#define PCIDE_BASE4 0x168 +#define PCIDE_BASE5 0x1e0 +#define PCIDE_BASE6 0x160 + +static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = { + PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5, + PCIDE_BASE6 */ +}; + +static int q40ide_default_irq(unsigned long base) +{ + switch (base) { + case 0x1f0: return 14; + case 0x170: return 15; + case 0x1e8: return 11; + default: + return 0; + } +} + + +/* + * Addresses are pretranslated for Q40 ISA access. + */ +static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, + ide_ack_intr_t *ack_intr, + int irq) +{ + memset(hw, 0, sizeof(hw_regs_t)); + /* BIG FAT WARNING: + assumption: only DATA port is ever used in 16 bit mode */ + hw->io_ports.data_addr = Q40_ISA_IO_W(base); + hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1); + hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2); + hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3); + hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4); + hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5); + hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6); + hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7); + hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206); + + hw->irq = irq; + hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; +} + +static void q40ide_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) + return insw(data_addr, buf, (len + 1) / 2); + + insw_swapw(data_addr, buf, (len + 1) / 2); +} + +static void q40ide_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) + return outsw(data_addr, buf, (len + 1) / 2); + + outsw_swapw(data_addr, buf, (len + 1) / 2); +} + +/* Q40 has a byte-swapped IDE interface */ +static const struct ide_tp_ops q40ide_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + .read_sff_dma_status = ide_read_sff_dma_status, + + .set_irq = ide_set_irq, + + .tf_load = ide_tf_load, + .tf_read = ide_tf_read, + + .input_data = q40ide_input_data, + .output_data = q40ide_output_data, +}; + +static const struct ide_port_info q40ide_port_info = { + .tp_ops = &q40ide_tp_ops, + .host_flags = IDE_HFLAG_NO_DMA, +}; + +/* + * the static array is needed to have the name reported in /proc/ioports, + * hwif->name unfortunately isn't available yet + */ +static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ + "ide0", "ide1" +}; + +/* + * Probe for Q40 IDE interfaces + */ + +static int __init q40ide_init(void) +{ + int i; + hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; + + if (!MACH_IS_Q40) + return -ENODEV; + + printk(KERN_INFO "ide: Q40 IDE controller\n"); + + for (i = 0; i < Q40IDE_NUM_HWIFS; i++) { + const char *name = q40_ide_names[i]; + + if (!request_region(pcide_bases[i], 8, name)) { + printk("could not reserve ports %lx-%lx for %s\n", + pcide_bases[i],pcide_bases[i]+8,name); + continue; + } + if (!request_region(pcide_bases[i]+0x206, 1, name)) { + printk("could not reserve port %lx for %s\n", + pcide_bases[i]+0x206,name); + release_region(pcide_bases[i], 8); + continue; + } + q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL, + q40ide_default_irq(pcide_bases[i])); + + hws[i] = &hw[i]; + } + + return ide_host_add(&q40ide_port_info, hws, NULL); +} + +module_init(q40ide_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c new file mode 100644 index 0000000..bc27c7a --- /dev/null +++ b/drivers/ide/qd65xx.c @@ -0,0 +1,429 @@ +/* + * Copyright (C) 1996-2001 Linus Torvalds & author (see below) + */ + +/* + * Version 0.03 Cleaned auto-tune, added probe + * Version 0.04 Added second channel tuning + * Version 0.05 Enhanced tuning ; added qd6500 support + * Version 0.06 Added dos driver's list + * Version 0.07 Second channel bug fix + * + * QDI QD6500/QD6580 EIDE controller fast support + * + * To activate controller support, use "ide0=qd65xx" + */ + +/* + * Rewritten from the work of Colten Edwards by + * Samuel Thibault + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "qd65xx" + +#include "qd65xx.h" + +/* + * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580) + * or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580) + * -- qd6500 is a single IDE interface + * -- qd6580 is a dual IDE interface + * + * More research on qd6580 being done by willmore@cig.mot.com (David) + * More Information given by Petr Soucek (petr@ryston.cz) + * http://www.ryston.cz/petr/vlb + */ + +/* + * base: Timer1 + * + * + * base+0x01: Config (R/O) + * + * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500) + * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30 + * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz + * bit 3: qd6500: 1 = disabled, 0 = enabled + * qd6580: 1 + * upper nibble: + * qd6500: 1100 + * qd6580: either 1010 or 0101 + * + * + * base+0x02: Timer2 (qd6580 only) + * + * + * base+0x03: Control (qd6580 only) + * + * bits 0-3 must always be set 1 + * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock + * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb + * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb + * channel 1 for hdc & hdd + * bit 1 : 1 = only disks on primary port + * 0 = disks & ATAPI devices on primary port + * bit 2-4 : always 0 + * bit 5 : status, but of what ? + * bit 6 : always set 1 by dos driver + * bit 7 : set 1 for non-ATAPI devices on primary port + * (maybe read-ahead and post-write buffer ?) + */ + +static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ + +/* + * qd65xx_select: + * + * This routine is invoked to prepare for access to a given drive. + */ + +static void qd65xx_select(ide_drive_t *drive) +{ + u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | + (QD_TIMREG(drive) & 0x02); + + if (timings[index] != QD_TIMING(drive)) + outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); +} + +/* + * qd6500_compute_timing + * + * computes the timing value where + * lower nibble represents active time, in count of VLB clocks + * upper nibble represents recovery time, in count of VLB clocks + */ + +static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time) +{ + int clk = ide_vlb_clk ? ide_vlb_clk : 50; + u8 act_cyc, rec_cyc; + + if (clk <= 33) { + act_cyc = 9 - IDE_IN(active_time * clk / 1000 + 1, 2, 9); + rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15); + } else { + act_cyc = 8 - IDE_IN(active_time * clk / 1000 + 1, 1, 8); + rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18); + } + + return (rec_cyc << 4) | 0x08 | act_cyc; +} + +/* + * qd6580_compute_timing + * + * idem for qd6580 + */ + +static u8 qd6580_compute_timing (int active_time, int recovery_time) +{ + int clk = ide_vlb_clk ? ide_vlb_clk : 50; + u8 act_cyc, rec_cyc; + + act_cyc = 17 - IDE_IN(active_time * clk / 1000 + 1, 2, 17); + rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15); + + return (rec_cyc << 4) | act_cyc; +} + +/* + * qd_find_disk_type + * + * tries to find timing from dos driver's table + */ + +static int qd_find_disk_type (ide_drive_t *drive, + int *active_time, int *recovery_time) +{ + struct qd65xx_timing_s *p; + char *m = (char *)&drive->id[ATA_ID_PROD]; + char model[ATA_ID_PROD_LEN]; + + if (*m == 0) + return 0; + + strncpy(model, m, ATA_ID_PROD_LEN); + ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */ + + for (p = qd65xx_timing ; p->offset != -1 ; p++) { + if (!strncmp(p->model, model+p->offset, 4)) { + printk(KERN_DEBUG "%s: listed !\n", drive->name); + *active_time = p->active; + *recovery_time = p->recovery; + return 1; + } + } + return 0; +} + +/* + * qd_set_timing: + * + * records the timing + */ + +static void qd_set_timing (ide_drive_t *drive, u8 timing) +{ + drive->drive_data &= 0xff00; + drive->drive_data |= timing; + + printk(KERN_DEBUG "%s: %#x\n", drive->name, timing); +} + +static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + u16 *id = drive->id; + int active_time = 175; + int recovery_time = 415; /* worst case values from the dos driver */ + + /* + * FIXME: use "pio" value + */ + if (!qd_find_disk_type(drive, &active_time, &recovery_time) && + (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) && + id[ATA_ID_EIDE_PIO] >= 240) { + printk(KERN_INFO "%s: PIO mode%d\n", drive->name, + id[ATA_ID_OLD_PIO_MODES] & 0xff); + active_time = 110; + recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120; + } + + qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time)); +} + +static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); + unsigned int cycle_time; + int active_time = 175; + int recovery_time = 415; /* worst case values from the dos driver */ + u8 base = (hwif->config_data & 0xff00) >> 8; + + if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) { + cycle_time = ide_pio_cycle_time(drive, pio); + + switch (pio) { + case 0: break; + case 3: + if (cycle_time >= 110) { + active_time = 86; + recovery_time = cycle_time - 102; + } else + printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); + break; + case 4: + if (cycle_time >= 69) { + active_time = 70; + recovery_time = cycle_time - 61; + } else + printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); + break; + default: + if (cycle_time >= 180) { + active_time = 110; + recovery_time = cycle_time - 120; + } else { + active_time = t->active; + recovery_time = cycle_time - active_time; + } + } + printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio); + } + + if (!HWIF(drive)->channel && drive->media != ide_disk) { + outb(0x5f, QD_CONTROL_PORT); + printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO " + "and post-write buffer on %s.\n", + drive->name, HWIF(drive)->name); + } + + qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time)); +} + +/* + * qd_testreg + * + * tests if the given port is a register + */ + +static int __init qd_testreg(int port) +{ + unsigned long flags; + u8 savereg, readreg; + + local_irq_save(flags); + savereg = inb_p(port); + outb_p(QD_TESTVAL, port); /* safe value */ + readreg = inb_p(port); + outb(savereg, port); + local_irq_restore(flags); + + if (savereg == QD_TESTVAL) { + printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); + printk(KERN_ERR "Please contact maintainers to tell about your hardware\n"); + printk(KERN_ERR "Assuming qd65xx is not present.\n"); + return 1; + } + + return (readreg != QD_TESTVAL); +} + +static void __init qd6500_init_dev(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 base = (hwif->config_data & 0xff00) >> 8; + u8 config = QD_CONFIG(hwif); + + drive->drive_data = QD6500_DEF_DATA; +} + +static void __init qd6580_init_dev(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u16 t1, t2; + u8 base = (hwif->config_data & 0xff00) >> 8; + u8 config = QD_CONFIG(hwif); + + if (hwif->host_flags & IDE_HFLAG_SINGLE) { + t1 = QD6580_DEF_DATA; + t2 = QD6580_DEF_DATA2; + } else + t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA; + + drive->drive_data = (drive->dn & 1) ? t2 : t1; +} + +static const struct ide_port_ops qd6500_port_ops = { + .init_dev = qd6500_init_dev, + .set_pio_mode = qd6500_set_pio_mode, + .selectproc = qd65xx_select, +}; + +static const struct ide_port_ops qd6580_port_ops = { + .init_dev = qd6580_init_dev, + .set_pio_mode = qd6580_set_pio_mode, + .selectproc = qd65xx_select, +}; + +static const struct ide_port_info qd65xx_port_info __initdata = { + .name = DRV_NAME, + .chipset = ide_qd65xx, + .host_flags = IDE_HFLAG_IO_32BIT | + IDE_HFLAG_NO_DMA, + .pio_mask = ATA_PIO4, +}; + +/* + * qd_probe: + * + * looks at the specified baseport, and if qd found, registers & initialises it + * return 1 if another qd may be probed + */ + +static int __init qd_probe(int base) +{ + int rc; + u8 config, unit, control; + struct ide_port_info d = qd65xx_port_info; + + config = inb(QD_CONFIG_PORT); + + if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) + return -ENODEV; + + unit = ! (config & QD_CONFIG_IDE_BASEPORT); + + if (unit) + d.host_flags |= IDE_HFLAG_QD_2ND_PORT; + + switch (config & 0xf0) { + case QD_CONFIG_QD6500: + if (qd_testreg(base)) + return -ENODEV; /* bad register */ + + if (config & QD_CONFIG_DISABLED) { + printk(KERN_WARNING "qd6500 is disabled !\n"); + return -ENODEV; + } + + printk(KERN_NOTICE "qd6500 at %#x\n", base); + printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", + config, QD_ID3); + + d.port_ops = &qd6500_port_ops; + d.host_flags |= IDE_HFLAG_SINGLE; + break; + case QD_CONFIG_QD6580_A: + case QD_CONFIG_QD6580_B: + if (qd_testreg(base) || qd_testreg(base + 0x02)) + return -ENODEV; /* bad registers */ + + control = inb(QD_CONTROL_PORT); + + printk(KERN_NOTICE "qd6580 at %#x\n", base); + printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", + config, control, QD_ID3); + + outb(QD_DEF_CONTR, QD_CONTROL_PORT); + + d.port_ops = &qd6580_port_ops; + if (control & QD_CONTR_SEC_DISABLED) + d.host_flags |= IDE_HFLAG_SINGLE; + + printk(KERN_INFO "qd6580: %s IDE board\n", + (control & QD_CONTR_SEC_DISABLED) ? "single" : "dual"); + break; + default: + return -ENODEV; + } + + rc = ide_legacy_device_add(&d, (base << 8) | config); + + if (d.host_flags & IDE_HFLAG_SINGLE) + return (rc == 0) ? 1 : rc; + + return rc; +} + +static int probe_qd65xx; + +module_param_named(probe, probe_qd65xx, bool, 0); +MODULE_PARM_DESC(probe, "probe for QD65xx chipsets"); + +static int __init qd65xx_init(void) +{ + int rc1, rc2 = -ENODEV; + + if (probe_qd65xx == 0) + return -ENODEV; + + rc1 = qd_probe(0x30); + if (rc1) + rc2 = qd_probe(0xb0); + + if (rc1 < 0 && rc2 < 0) + return -ENODEV; + + return 0; +} + +module_init(qd65xx_init); + +MODULE_AUTHOR("Samuel Thibault"); +MODULE_DESCRIPTION("support of qd65xx vlb ide chipset"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/qd65xx.h b/drivers/ide/qd65xx.h new file mode 100644 index 0000000..c83dea8 --- /dev/null +++ b/drivers/ide/qd65xx.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2000 Linus Torvalds & authors + */ + +/* + * Authors: Petr Soucek + * Samuel Thibault + */ + +/* truncates a in [b,c] */ +#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) + +#define IDE_IMPLY(a,b) ((!(a)) || (b)) + +#define QD_TIM1_PORT (base) +#define QD_CONFIG_PORT (base+0x01) +#define QD_TIM2_PORT (base+0x02) +#define QD_CONTROL_PORT (base+0x03) + +#define QD_CONFIG_IDE_BASEPORT 0x01 +#define QD_CONFIG_BASEPORT 0x02 +#define QD_CONFIG_ID3 0x04 +#define QD_CONFIG_DISABLED 0x08 +#define QD_CONFIG_QD6500 0xc0 +#define QD_CONFIG_QD6580_A 0xa0 +#define QD_CONFIG_QD6580_B 0x50 + +#define QD_CONTR_SEC_DISABLED 0x01 + +#define QD_ID3 ((config & QD_CONFIG_ID3)!=0) + +#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff) + +#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff) +#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8) + +#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08)) +#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) +#define QD6580_DEF_DATA2 ((QD_TIM2_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) +#define QD_DEF_CONTR (0x40 | ((control & 0x02) ? 0x9f : 0x1f)) + +#define QD_TESTVAL 0x19 /* safe value */ + +/* Drive specific timing taken from DOS driver v3.7 */ + +static struct qd65xx_timing_s { + s8 offset; /* ofset from the beginning of Model Number" */ + char model[4]; /* 4 chars from Model number, no conversion */ + s16 active; /* active time */ + s16 recovery; /* recovery time */ +} qd65xx_timing [] = { + { 30, "2040", 110, 225 }, /* Conner CP30204 */ + { 30, "2045", 135, 225 }, /* Conner CP30254 */ + { 30, "1040", 155, 325 }, /* Conner CP30104 */ + { 30, "1047", 135, 265 }, /* Conner CP30174 */ + { 30, "5344", 135, 225 }, /* Conner CP3544 */ + { 30, "01 4", 175, 405 }, /* Conner CP-3104 */ + { 27, "C030", 175, 375 }, /* Conner CP3000 */ + { 8, "PL42", 110, 295 }, /* Quantum LP240 */ + { 8, "PL21", 110, 315 }, /* Quantum LP120 */ + { 8, "PL25", 175, 385 }, /* Quantum LP52 */ + { 4, "PA24", 110, 285 }, /* WD Piranha SP4200 */ + { 6, "2200", 110, 260 }, /* WD Caviar AC2200 */ + { 6, "3204", 110, 235 }, /* WD Caviar AC2340 */ + { 6, "1202", 110, 265 }, /* WD Caviar AC2120 */ + { 0, "DS3-", 135, 315 }, /* Teac SD340 */ + { 8, "KM32", 175, 355 }, /* Toshiba MK234 */ + { 2, "53A1", 175, 355 }, /* Seagate ST351A */ + { 2, "4108", 175, 295 }, /* Seagate ST1480A */ + { 2, "1344", 175, 335 }, /* Seagate ST3144A */ + { 6, "7 12", 110, 225 }, /* Maxtor 7213A */ + { 30, "02F4", 145, 295 }, /* Conner 3204F */ + { 2, "1302", 175, 335 }, /* Seagate ST3120A */ + { 2, "2334", 145, 265 }, /* Seagate ST3243A */ + { 2, "2338", 145, 275 }, /* Seagate ST3283A */ + { 2, "3309", 145, 275 }, /* Seagate ST3390A */ + { 2, "5305", 145, 275 }, /* Seagate ST3550A */ + { 2, "4100", 175, 295 }, /* Seagate ST1400A */ + { 2, "4110", 175, 295 }, /* Seagate ST1401A */ + { 2, "6300", 135, 265 }, /* Seagate ST3600A */ + { 2, "5300", 135, 265 }, /* Seagate ST3500A */ + { 6, "7 31", 135, 225 }, /* Maxtor 7131 AT */ + { 6, "7 43", 115, 265 }, /* Maxtor 7345 AT */ + { 6, "7 42", 110, 255 }, /* Maxtor 7245 AT */ + { 6, "3 04", 135, 265 }, /* Maxtor 340 AT */ + { 6, "61 0", 135, 285 }, /* WD AC160 */ + { 6, "1107", 135, 235 }, /* WD AC1170 */ + { 6, "2101", 110, 220 }, /* WD AC1210 */ + { 6, "4202", 135, 245 }, /* WD AC2420 */ + { 6, "41 0", 175, 355 }, /* WD Caviar 140 */ + { 6, "82 0", 175, 355 }, /* WD Caviar 280 */ + { 8, "PL01", 175, 375 }, /* Quantum LP105 */ + { 8, "PL25", 110, 295 }, /* Quantum LP525 */ + { 10, "4S 2", 175, 385 }, /* Quantum ELS42 */ + { 10, "8S 5", 175, 385 }, /* Quantum ELS85 */ + { 10, "1S72", 175, 385 }, /* Quantum ELS127 */ + { 10, "1S07", 175, 385 }, /* Quantum ELS170 */ + { 8, "ZE42", 135, 295 }, /* Quantum EZ240 */ + { 8, "ZE21", 175, 385 }, /* Quantum EZ127 */ + { 8, "ZE58", 175, 385 }, /* Quantum EZ85 */ + { 8, "ZE24", 175, 385 }, /* Quantum EZ42 */ + { 27, "C036", 155, 325 }, /* Conner CP30064 */ + { 27, "C038", 155, 325 }, /* Conner CP30084 */ + { 6, "2205", 110, 255 }, /* WDC AC2250 */ + { 2, " CHA", 140, 415 }, /* WDC AH series; WDC AH260, WDC */ + { 2, " CLA", 140, 415 }, /* WDC AL series: WDC AL2120, 2170, */ + { 4, "UC41", 140, 415 }, /* WDC CU140 */ + { 6, "1207", 130, 275 }, /* WDC AC2170 */ + { 6, "2107", 130, 275 }, /* WDC AC1270 */ + { 6, "5204", 130, 275 }, /* WDC AC2540 */ + { 30, "3004", 110, 235 }, /* Conner CP30340 */ + { 30, "0345", 135, 255 }, /* Conner CP30544 */ + { 12, "12A3", 175, 320 }, /* MAXTOR LXT-213A */ + { 12, "43A0", 145, 240 }, /* MAXTOR LXT-340A */ + { 6, "7 21", 180, 290 }, /* Maxtor 7120 AT */ + { 6, "7 71", 135, 240 }, /* Maxtor 7170 AT */ + { 12, "45\0000", 110, 205 }, /* MAXTOR MXT-540 */ + { 8, "PL11", 180, 290 }, /* QUANTUM LP110A */ + { 8, "OG21", 150, 275 }, /* QUANTUM GO120 */ + { 12, "42A5", 175, 320 }, /* MAXTOR LXT-245A */ + { 2, "2309", 175, 295 }, /* ST3290A */ + { 2, "3358", 180, 310 }, /* ST3385A */ + { 2, "6355", 180, 310 }, /* ST3655A */ + { 2, "1900", 175, 270 }, /* ST9100A */ + { 2, "1954", 175, 270 }, /* ST9145A */ + { 2, "1909", 175, 270 }, /* ST9190AG */ + { 2, "2953", 175, 270 }, /* ST9235A */ + { 2, "1359", 175, 270 }, /* ST3195A */ + { 24, "3R11", 175, 290 }, /* ALPS ELECTRIC Co.,LTD, DR311C */ + { 0, "2M26", 175, 215 }, /* M262XT-0Ah */ + { 4, "2253", 175, 300 }, /* HP C2235A */ + { 4, "-32A", 145, 245 }, /* H3133-A2 */ + { 30, "0326", 150, 270 }, /* Samsung Electronics 120MB */ + { 30, "3044", 110, 195 }, /* Conner CFA340A */ + { 30, "43A0", 110, 195 }, /* Conner CFA340A */ + { -1, " ", 175, 415 } /* unknown disk name */ +}; diff --git a/drivers/ide/rapide.c b/drivers/ide/rapide.c new file mode 100644 index 0000000..78d27d9 --- /dev/null +++ b/drivers/ide/rapide.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 1996-2002 Russell King. + */ + +#include +#include +#include +#include +#include +#include + +#include + +static struct const ide_port_info rapide_port_info = { + .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, +}; + +static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base, + void __iomem *ctrl, unsigned int sz, int irq) +{ + unsigned long port = (unsigned long)base; + int i; + + for (i = 0; i <= 7; i++) { + hw->io_ports_array[i] = port; + port += sz; + } + hw->io_ports.ctl_addr = (unsigned long)ctrl; + hw->irq = irq; +} + +static int __devinit +rapide_probe(struct expansion_card *ec, const struct ecard_id *id) +{ + void __iomem *base; + struct ide_host *host; + int ret; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + + ret = ecard_request_resources(ec); + if (ret) + goto out; + + base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); + if (!base) { + ret = -ENOMEM; + goto release; + } + + memset(&hw, 0, sizeof(hw)); + rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq); + hw.chipset = ide_generic; + hw.dev = &ec->dev; + + ret = ide_host_add(&rapide_port_info, hws, &host); + if (ret) + goto release; + + ecard_set_drvdata(ec, host); + goto out; + + release: + ecard_release_resources(ec); + out: + return ret; +} + +static void __devexit rapide_remove(struct expansion_card *ec) +{ + struct ide_host *host = ecard_get_drvdata(ec); + + ecard_set_drvdata(ec, NULL); + + ide_host_remove(host); + + ecard_release_resources(ec); +} + +static struct ecard_id rapide_ids[] = { + { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, + { 0xffff, 0xffff } +}; + +static struct ecard_driver rapide_driver = { + .probe = rapide_probe, + .remove = __devexit_p(rapide_remove), + .id_table = rapide_ids, + .drv = { + .name = "rapide", + }, +}; + +static int __init rapide_init(void) +{ + return ecard_register_driver(&rapide_driver); +} + +static void __exit rapide_exit(void) +{ + ecard_unregister_driver(&rapide_driver); +} + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Yellowstone RAPIDE driver"); + +module_init(rapide_init); +module_exit(rapide_exit); diff --git a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c new file mode 100644 index 0000000..7daf013 --- /dev/null +++ b/drivers/ide/rz1000.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 1995-1998 Linus Torvalds & author (see below) + */ + +/* + * Principal Author: mlord@pobox.com (Mark Lord) + * + * See linux/MAINTAINERS for address of current maintainer. + * + * This file provides support for disabling the buggy read-ahead + * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards. + * + * Dunno if this fixes both ports, or only the primary port (?). + */ + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "rz1000" + +static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + u16 reg; + + if (!pci_read_config_word (dev, 0x40, ®) && + !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { + printk(KERN_INFO "%s: disabled chipset read-ahead " + "(buggy RZ1000/RZ1001)\n", hwif->name); + } else { + if (hwif->mate) + hwif->mate->serialized = hwif->serialized = 1; + hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS; + printk(KERN_INFO "%s: serialized, disabled unmasking " + "(buggy RZ1000/RZ1001)\n", hwif->name); + } +} + +static const struct ide_port_info rz1000_chipset __devinitdata = { + .name = DRV_NAME, + .init_hwif = init_hwif_rz1000, + .chipset = ide_rz1000, + .host_flags = IDE_HFLAG_NO_DMA, +}; + +static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + return ide_pci_init_one(dev, &rz1000_chipset, NULL); +} + +static const struct pci_device_id rz1000_pci_tbl[] = { + { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), 0 }, + { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl); + +static struct pci_driver rz1000_pci_driver = { + .name = "RZ1000_IDE", + .id_table = rz1000_pci_tbl, + .probe = rz1000_init_one, + .remove = ide_pci_remove, +}; + +static int __init rz1000_ide_init(void) +{ + return ide_pci_register_driver(&rz1000_pci_driver); +} + +static void __exit rz1000_ide_exit(void) +{ + pci_unregister_driver(&rz1000_pci_driver); +} + +module_init(rz1000_ide_init); +module_exit(rz1000_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c new file mode 100644 index 0000000..f1a8758 --- /dev/null +++ b/drivers/ide/sc1200.c @@ -0,0 +1,357 @@ +/* + * Copyright (C) 2000-2002 Mark Lord + * 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: + * Available from National Semiconductor + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "sc1200" + +#define SC1200_REV_A 0x00 +#define SC1200_REV_B1 0x01 +#define SC1200_REV_B3 0x02 +#define SC1200_REV_C1 0x03 +#define SC1200_REV_D1 0x04 + +#define PCI_CLK_33 0x00 +#define PCI_CLK_48 0x01 +#define PCI_CLK_66 0x02 +#define PCI_CLK_33A 0x03 + +static unsigned short sc1200_get_pci_clock (void) +{ + unsigned char chip_id, silicon_revision; + unsigned int pci_clock; + /* + * Check the silicon revision, as not all versions of the chip + * have the register with the fast PCI bus timings. + */ + chip_id = inb (0x903c); + silicon_revision = inb (0x903d); + + // Read the fast pci clock frequency + if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) { + pci_clock = PCI_CLK_33; + } else { + // check clock generator configuration (cfcc) + // the clock is in bits 8 and 9 of this word + + pci_clock = inw (0x901e); + pci_clock >>= 8; + pci_clock &= 0x03; + if (pci_clock == PCI_CLK_33A) + pci_clock = PCI_CLK_33; + } + return pci_clock; +} + +/* + * 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 const unsigned int sc1200_pio_timings[4][5] = + {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz + {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz + {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz + {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}}; // format1, 66Mhz + +/* + * After chip reset, the PIO timings are set to 0x00009172, which is not valid. + */ +//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) + +static void sc1200_tunepio(ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *pdev = to_pci_dev(hwif->dev); + unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0; + + pci_read_config_dword(pdev, basereg + 4, &format); + format = (format >> 31) & 1; + if (format) + format += sc1200_get_pci_clock(); + pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3), + sc1200_pio_timings[format][pio]); +} + +/* + * The SC1200 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. + */ +static u8 sc1200_udma_filter(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + ide_drive_t *mate = ide_get_pair_dev(drive); + u16 *mateid = mate->id; + u8 mask = hwif->ultra_mask; + + if (mate == NULL) + goto out; + + 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_FIELD_VALID] & 2) && + (mateid[ATA_ID_MWDMA_MODES] & 7)) + mask = 0; + } +out: + return mask; +} + +static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned int reg, timings; + unsigned short pci_clock; + unsigned int basereg = hwif->channel ? 0x50 : 0x40; + + static const u32 udma_timing[3][3] = { + { 0x00921250, 0x00911140, 0x00911030 }, + { 0x00932470, 0x00922260, 0x00922140 }, + { 0x009436a1, 0x00933481, 0x00923261 }, + }; + + static const u32 mwdma_timing[3][3] = { + { 0x00077771, 0x00012121, 0x00002020 }, + { 0x000bbbb2, 0x00024241, 0x00013131 }, + { 0x000ffff3, 0x00035352, 0x00015151 }, + }; + + pci_clock = sc1200_get_pci_clock(); + + /* + * Note that each DMA mode has several timings associated with it. + * The correct timing depends on the fast PCI clock freq. + */ + + if (mode >= XFER_UDMA_0) + timings = udma_timing[pci_clock][mode - XFER_UDMA_0]; + else + timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0]; + + if ((drive->dn & 1) == 0) { + pci_read_config_dword(dev, basereg + 4, ®); + timings |= reg & 0x80000000; /* preserve PIO format bit */ + pci_write_config_dword(dev, basereg + 4, timings); + } else + pci_write_config_dword(dev, basereg + 12, timings); +} + +/* Replacement for the standard ide_dma_end action in + * dma_proc. + * + * returns 1 on error, 0 otherwise + */ +static int sc1200_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte dma_stat; + + dma_stat = inb(dma_base+2); /* get DMA status */ + + if (!(dma_stat & 4)) + printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n", + dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2)); + + outb(dma_stat|0x1b, dma_base+2); /* clear the INTR & ERROR bits */ + outb(inb(dma_base)&~1, dma_base); /* !! DO THIS HERE !! stop DMA */ + + drive->waiting_for_dma = 0; + ide_destroy_dmatable(drive); /* purge DMA mappings */ + + return (dma_stat & 7) != 4; /* verify good DMA status */ +} + +/* + * sc1200_set_pio_mode() handles setting of PIO modes + * for both the chipset and drive. + * + * All existing BIOSs for this chipset guarantee that all drives + * will have valid default PIO timings set up before we get here. + */ + +static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + int mode = -1; + + /* + * bad abuse of ->set_pio_mode interface + */ + switch (pio) { + case 200: mode = XFER_UDMA_0; break; + case 201: mode = XFER_UDMA_1; break; + case 202: mode = XFER_UDMA_2; break; + case 100: mode = XFER_MW_DMA_0; break; + case 101: mode = XFER_MW_DMA_1; break; + case 102: mode = XFER_MW_DMA_2; break; + } + if (mode != -1) { + printk("SC1200: %s: changing (U)DMA mode\n", drive->name); + ide_dma_off_quietly(drive); + if (ide_set_dma_mode(drive, mode) == 0 && + (drive->dev_flags & IDE_DFLAG_USING_DMA)) + hwif->dma_ops->dma_host_set(drive, 1); + return; + } + + sc1200_tunepio(drive, pio); +} + +#ifdef CONFIG_PM +struct sc1200_saved_state { + u32 regs[8]; +}; + +static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) +{ + printk("SC1200: suspend(%u)\n", state.event); + + /* + * we only save state when going from full power to less + */ + if (state.event == PM_EVENT_ON) { + struct ide_host *host = pci_get_drvdata(dev); + struct sc1200_saved_state *ss = host->host_priv; + unsigned int r; + + /* + * save timing registers + * (this may be unnecessary if BIOS also does it) + */ + for (r = 0; r < 8; r++) + pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]); + } + + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + return 0; +} + +static int sc1200_resume (struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct sc1200_saved_state *ss = host->host_priv; + unsigned int r; + int i; + + i = pci_enable_device(dev); + if (i) + return i; + + /* + * restore timing registers + * (this may be unnecessary if BIOS also does it) + */ + for (r = 0; r < 8; r++) + pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]); + + return 0; +} +#endif + +static const struct ide_port_ops sc1200_port_ops = { + .set_pio_mode = sc1200_set_pio_mode, + .set_dma_mode = sc1200_set_dma_mode, + .udma_filter = sc1200_udma_filter, +}; + +static const struct ide_dma_ops sc1200_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = sc1200_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info sc1200_chipset __devinitdata = { + .name = DRV_NAME, + .port_ops = &sc1200_port_ops, + .dma_ops = &sc1200_dma_ops, + .host_flags = IDE_HFLAG_SERIALIZE | + IDE_HFLAG_POST_SET_MODE | + IDE_HFLAG_ABUSE_DMA_MODES, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, +}; + +static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct sc1200_saved_state *ss = NULL; + int rc; + +#ifdef CONFIG_PM + ss = kmalloc(sizeof(*ss), GFP_KERNEL); + if (ss == NULL) + return -ENOMEM; +#endif + rc = ide_pci_init_one(dev, &sc1200_chipset, ss); + if (rc) + kfree(ss); + + return rc; +} + +static const struct pci_device_id sc1200_pci_tbl[] = { + { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0}, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl); + +static struct pci_driver sc1200_pci_driver = { + .name = "SC1200_IDE", + .id_table = sc1200_pci_tbl, + .probe = sc1200_init_one, + .remove = ide_pci_remove, +#ifdef CONFIG_PM + .suspend = sc1200_suspend, + .resume = sc1200_resume, +#endif +}; + +static int __init sc1200_ide_init(void) +{ + return ide_pci_register_driver(&sc1200_pci_driver); +} + +static void __exit sc1200_ide_exit(void) +{ + pci_unregister_driver(&sc1200_pci_driver); +} + +module_init(sc1200_ide_init); +module_exit(sc1200_ide_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c new file mode 100644 index 0000000..49f163a --- /dev/null +++ b/drivers/ide/scc_pata.c @@ -0,0 +1,966 @@ +/* + * Support for IDE interfaces on Celleb platform + * + * (C) Copyright 2006 TOSHIBA CORPORATION + * + * This code is based on drivers/ide/pci/siimage.c: + * Copyright (C) 2001-2002 Andre Hedrick + * Copyright (C) 2003 Red Hat + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include + +#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4 + +#define SCC_PATA_NAME "scc IDE" + +#define TDVHSEL_MASTER 0x00000001 +#define TDVHSEL_SLAVE 0x00000004 + +#define MODE_JCUSFEN 0x00000080 + +#define CCKCTRL_ATARESET 0x00040000 +#define CCKCTRL_BUFCNT 0x00020000 +#define CCKCTRL_CRST 0x00010000 +#define CCKCTRL_OCLKEN 0x00000100 +#define CCKCTRL_ATACLKOEN 0x00000002 +#define CCKCTRL_LCLKEN 0x00000001 + +#define QCHCD_IOS_SS 0x00000001 + +#define QCHSD_STPDIAG 0x00020000 + +#define INTMASK_MSK 0xD1000012 +#define INTSTS_SERROR 0x80000000 +#define INTSTS_PRERR 0x40000000 +#define INTSTS_RERR 0x10000000 +#define INTSTS_ICERR 0x01000000 +#define INTSTS_BMSINT 0x00000010 +#define INTSTS_BMHE 0x00000008 +#define INTSTS_IOIRQS 0x00000004 +#define INTSTS_INTRQ 0x00000002 +#define INTSTS_ACTEINT 0x00000001 + +#define ECMODE_VALUE 0x01 + +static struct scc_ports { + unsigned long ctl, dma; + struct ide_host *host; /* for removing port from system */ +} scc_ports[MAX_HWIFS]; + +/* PIO transfer mode table */ +/* JCHST */ +static unsigned long JCHSTtbl[2][7] = { + {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00}, /* 100MHz */ + {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00} /* 133MHz */ +}; + +/* JCHHT */ +static unsigned long JCHHTtbl[2][7] = { + {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00}, /* 100MHz */ + {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00} /* 133MHz */ +}; + +/* JCHCT */ +static unsigned long JCHCTtbl[2][7] = { + {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00}, /* 100MHz */ + {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00} /* 133MHz */ +}; + + +/* DMA transfer mode table */ +/* JCHDCTM/JCHDCTS */ +static unsigned long JCHDCTxtbl[2][7] = { + {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00}, /* 100MHz */ + {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00} /* 133MHz */ +}; + +/* JCSTWTM/JCSTWTS */ +static unsigned long JCSTWTxtbl[2][7] = { + {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00}, /* 100MHz */ + {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02} /* 133MHz */ +}; + +/* JCTSS */ +static unsigned long JCTSStbl[2][7] = { + {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00}, /* 100MHz */ + {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05} /* 133MHz */ +}; + +/* JCENVT */ +static unsigned long JCENVTtbl[2][7] = { + {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}, /* 100MHz */ + {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} /* 133MHz */ +}; + +/* JCACTSELS/JCACTSELM */ +static unsigned long JCACTSELtbl[2][7] = { + {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00}, /* 100MHz */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} /* 133MHz */ +}; + + +static u8 scc_ide_inb(unsigned long port) +{ + u32 data = in_be32((void*)port); + return (u8)data; +} + +static void scc_exec_command(ide_hwif_t *hwif, u8 cmd) +{ + out_be32((void *)hwif->io_ports.command_addr, cmd); + eieio(); + in_be32((void *)(hwif->dma_base + 0x01c)); + eieio(); +} + +static u8 scc_read_status(ide_hwif_t *hwif) +{ + return (u8)in_be32((void *)hwif->io_ports.status_addr); +} + +static u8 scc_read_altstatus(ide_hwif_t *hwif) +{ + return (u8)in_be32((void *)hwif->io_ports.ctl_addr); +} + +static u8 scc_read_sff_dma_status(ide_hwif_t *hwif) +{ + return (u8)in_be32((void *)(hwif->dma_base + 4)); +} + +static void scc_set_irq(ide_hwif_t *hwif, int on) +{ + u8 ctl = ATA_DEVCTL_OBS; + + if (on == 4) { /* hack for SRST */ + ctl |= 4; + on &= ~4; + } + + ctl |= on ? 0 : 2; + + out_be32((void *)hwif->io_ports.ctl_addr, ctl); + eieio(); + in_be32((void *)(hwif->dma_base + 0x01c)); + eieio(); +} + +static void scc_ide_insw(unsigned long port, void *addr, u32 count) +{ + u16 *ptr = (u16 *)addr; + while (count--) { + *ptr++ = le16_to_cpu(in_be32((void*)port)); + } +} + +static void scc_ide_insl(unsigned long port, void *addr, u32 count) +{ + u16 *ptr = (u16 *)addr; + while (count--) { + *ptr++ = le16_to_cpu(in_be32((void*)port)); + *ptr++ = le16_to_cpu(in_be32((void*)port)); + } +} + +static void scc_ide_outb(u8 addr, unsigned long port) +{ + out_be32((void*)port, addr); +} + +static void +scc_ide_outsw(unsigned long port, void *addr, u32 count) +{ + u16 *ptr = (u16 *)addr; + while (count--) { + out_be32((void*)port, cpu_to_le16(*ptr++)); + } +} + +static void +scc_ide_outsl(unsigned long port, void *addr, u32 count) +{ + u16 *ptr = (u16 *)addr; + while (count--) { + out_be32((void*)port, cpu_to_le16(*ptr++)); + out_be32((void*)port, cpu_to_le16(*ptr++)); + } +} + +/** + * scc_set_pio_mode - set host controller for PIO mode + * @drive: drive + * @pio: PIO mode number + * + * Load the timing settings for this device mode into the + * controller. + */ + +static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct scc_ports *ports = ide_get_hwifdata(hwif); + unsigned long ctl_base = ports->ctl; + unsigned long cckctrl_port = ctl_base + 0xff0; + unsigned long piosht_port = ctl_base + 0x000; + unsigned long pioct_port = ctl_base + 0x004; + unsigned long reg; + int offset; + + reg = in_be32((void __iomem *)cckctrl_port); + if (reg & CCKCTRL_ATACLKOEN) { + offset = 1; /* 133MHz */ + } else { + offset = 0; /* 100MHz */ + } + reg = JCHSTtbl[offset][pio] << 16 | JCHHTtbl[offset][pio]; + out_be32((void __iomem *)piosht_port, reg); + reg = JCHCTtbl[offset][pio]; + out_be32((void __iomem *)pioct_port, reg); +} + +/** + * scc_set_dma_mode - set host controller for DMA mode + * @drive: drive + * @speed: DMA mode + * + * Load the timing settings for this device mode into the + * controller. + */ + +static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct scc_ports *ports = ide_get_hwifdata(hwif); + unsigned long ctl_base = ports->ctl; + unsigned long cckctrl_port = ctl_base + 0xff0; + unsigned long mdmact_port = ctl_base + 0x008; + unsigned long mcrcst_port = ctl_base + 0x00c; + unsigned long sdmact_port = ctl_base + 0x010; + unsigned long scrcst_port = ctl_base + 0x014; + unsigned long udenvt_port = ctl_base + 0x018; + unsigned long tdvhsel_port = ctl_base + 0x020; + int is_slave = (&hwif->drives[1] == drive); + int offset, idx; + unsigned long reg; + unsigned long jcactsel; + + reg = in_be32((void __iomem *)cckctrl_port); + if (reg & CCKCTRL_ATACLKOEN) { + offset = 1; /* 133MHz */ + } else { + offset = 0; /* 100MHz */ + } + + idx = speed - XFER_UDMA_0; + + jcactsel = JCACTSELtbl[offset][idx]; + if (is_slave) { + out_be32((void __iomem *)sdmact_port, JCHDCTxtbl[offset][idx]); + out_be32((void __iomem *)scrcst_port, JCSTWTxtbl[offset][idx]); + jcactsel = jcactsel << 2; + out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_SLAVE) | jcactsel); + } else { + out_be32((void __iomem *)mdmact_port, JCHDCTxtbl[offset][idx]); + out_be32((void __iomem *)mcrcst_port, JCSTWTxtbl[offset][idx]); + out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_MASTER) | jcactsel); + } + reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx]; + out_be32((void __iomem *)udenvt_port, reg); +} + +static void scc_dma_host_set(ide_drive_t *drive, int on) +{ + ide_hwif_t *hwif = drive->hwif; + u8 unit = drive->dn & 1; + u8 dma_stat = scc_ide_inb(hwif->dma_base + 4); + + if (on) + dma_stat |= (1 << (5 + unit)); + else + dma_stat &= ~(1 << (5 + unit)); + + scc_ide_outb(dma_stat, hwif->dma_base + 4); +} + +/** + * scc_ide_dma_setup - begin a DMA phase + * @drive: target device + * + * Build an IDE DMA PRD (IDE speak for scatter gather table) + * and then set up the DMA transfer registers. + * + * Returns 0 on success. If a PIO fallback is required then 1 + * is returned. + */ + +static int scc_dma_setup(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct request *rq = HWGROUP(drive)->rq; + unsigned int reading; + u8 dma_stat; + + if (rq_data_dir(rq)) + reading = 0; + else + reading = 1 << 3; + + /* fall back to pio! */ + if (!ide_build_dmatable(drive, rq)) { + ide_map_sg(drive, rq); + return 1; + } + + /* PRD table */ + out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma); + + /* specify r/w */ + out_be32((void __iomem *)hwif->dma_base, reading); + + /* read DMA status for INTR & ERROR flags */ + dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4)); + + /* clear INTR & ERROR flags */ + out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6); + drive->waiting_for_dma = 1; + return 0; +} + +static void scc_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 dma_cmd = scc_ide_inb(hwif->dma_base); + + /* start DMA */ + scc_ide_outb(dma_cmd | 1, hwif->dma_base); + wmb(); +} + +static int __scc_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 dma_stat, dma_cmd; + + drive->waiting_for_dma = 0; + /* get DMA command mode */ + dma_cmd = scc_ide_inb(hwif->dma_base); + /* stop DMA */ + scc_ide_outb(dma_cmd & ~1, hwif->dma_base); + /* get DMA status */ + dma_stat = scc_ide_inb(hwif->dma_base + 4); + /* clear the INTR & ERROR bits */ + scc_ide_outb(dma_stat | 6, hwif->dma_base + 4); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + wmb(); + return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; +} + +/** + * scc_dma_end - Stop DMA + * @drive: IDE drive + * + * Check and clear INT Status register. + * Then call __scc_dma_end(). + */ + +static int scc_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + void __iomem *dma_base = (void __iomem *)hwif->dma_base; + unsigned long intsts_port = hwif->dma_base + 0x014; + u32 reg; + int dma_stat, data_loss = 0; + static int retry = 0; + + /* errata A308 workaround: Step5 (check data loss) */ + /* We don't check non ide_disk because it is limited to UDMA4 */ + if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr) + & ATA_ERR) && + drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) { + reg = in_be32((void __iomem *)intsts_port); + if (!(reg & INTSTS_ACTEINT)) { + printk(KERN_WARNING "%s: operation failed (transfer data loss)\n", + drive->name); + data_loss = 1; + if (retry++) { + struct request *rq = HWGROUP(drive)->rq; + int unit; + /* ERROR_RESET and drive->crc_count are needed + * to reduce DMA transfer mode in retry process. + */ + if (rq) + rq->errors |= ERROR_RESET; + for (unit = 0; unit < MAX_DRIVES; unit++) { + ide_drive_t *drive = &hwif->drives[unit]; + drive->crc_count++; + } + } + } + } + + while (1) { + reg = in_be32((void __iomem *)intsts_port); + + if (reg & INTSTS_SERROR) { + printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME); + out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT); + + out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS); + continue; + } + + if (reg & INTSTS_PRERR) { + u32 maea0, maec0; + unsigned long ctl_base = hwif->config_data; + + maea0 = in_be32((void __iomem *)(ctl_base + 0xF50)); + maec0 = in_be32((void __iomem *)(ctl_base + 0xF54)); + + printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", SCC_PATA_NAME, maea0, maec0); + + out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT); + + out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS); + continue; + } + + if (reg & INTSTS_RERR) { + printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME); + out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT); + + out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS); + continue; + } + + if (reg & INTSTS_ICERR) { + out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS); + + printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME); + out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT); + continue; + } + + if (reg & INTSTS_BMSINT) { + printk(KERN_WARNING "%s: Internal Bus Error\n", SCC_PATA_NAME); + out_be32((void __iomem *)intsts_port, INTSTS_BMSINT); + + ide_do_reset(drive); + continue; + } + + if (reg & INTSTS_BMHE) { + out_be32((void __iomem *)intsts_port, INTSTS_BMHE); + continue; + } + + if (reg & INTSTS_ACTEINT) { + out_be32((void __iomem *)intsts_port, INTSTS_ACTEINT); + continue; + } + + if (reg & INTSTS_IOIRQS) { + out_be32((void __iomem *)intsts_port, INTSTS_IOIRQS); + continue; + } + break; + } + + dma_stat = __scc_dma_end(drive); + if (data_loss) + dma_stat |= 2; /* emulate DMA error (to retry command) */ + return dma_stat; +} + +/* returns 1 if dma irq issued, 0 otherwise */ +static int scc_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014); + + /* SCC errata A252,A308 workaround: Step4 */ + if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr) + & ATA_ERR) && + (int_stat & INTSTS_INTRQ)) + return 1; + + /* SCC errata A308 workaround: Step5 (polling IOIRQS) */ + if (int_stat & INTSTS_IOIRQS) + return 1; + + return 0; +} + +static u8 scc_udma_filter(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 mask = hwif->ultra_mask; + + /* errata A308 workaround: limit non ide_disk drive to UDMA4 */ + if ((drive->media != ide_disk) && (mask & 0xE0)) { + printk(KERN_INFO "%s: limit %s to UDMA4\n", + SCC_PATA_NAME, drive->name); + mask = ATA_UDMA4; + } + + return mask; +} + +/** + * setup_mmio_scc - map CTRL/BMID region + * @dev: PCI device we are configuring + * @name: device name + * + */ + +static int setup_mmio_scc (struct pci_dev *dev, const char *name) +{ + unsigned long ctl_base = pci_resource_start(dev, 0); + unsigned long dma_base = pci_resource_start(dev, 1); + unsigned long ctl_size = pci_resource_len(dev, 0); + unsigned long dma_size = pci_resource_len(dev, 1); + void __iomem *ctl_addr; + void __iomem *dma_addr; + int i, ret; + + for (i = 0; i < MAX_HWIFS; i++) { + if (scc_ports[i].ctl == 0) + break; + } + if (i >= MAX_HWIFS) + return -ENOMEM; + + ret = pci_request_selected_regions(dev, (1 << 2) - 1, name); + if (ret < 0) { + printk(KERN_ERR "%s: can't reserve resources\n", name); + return ret; + } + + if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL) + goto fail_0; + + if ((dma_addr = ioremap(dma_base, dma_size)) == NULL) + goto fail_1; + + pci_set_master(dev); + scc_ports[i].ctl = (unsigned long)ctl_addr; + scc_ports[i].dma = (unsigned long)dma_addr; + pci_set_drvdata(dev, (void *) &scc_ports[i]); + + return 1; + + fail_1: + iounmap(ctl_addr); + fail_0: + return -ENOMEM; +} + +static int scc_ide_setup_pci_device(struct pci_dev *dev, + const struct ide_port_info *d) +{ + struct scc_ports *ports = pci_get_drvdata(dev); + struct ide_host *host; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + int i, rc; + + memset(&hw, 0, sizeof(hw)); + for (i = 0; i <= 8; i++) + hw.io_ports_array[i] = ports->dma + 0x20 + i * 4; + hw.irq = dev->irq; + hw.dev = &dev->dev; + hw.chipset = ide_pci; + + rc = ide_host_add(d, hws, &host); + if (rc) + return rc; + + ports->host = host; + + return 0; +} + +/** + * init_setup_scc - set up an SCC PATA Controller + * @dev: PCI device + * @d: IDE port info + * + * Perform the initial set up for this device. + */ + +static int __devinit init_setup_scc(struct pci_dev *dev, + const struct ide_port_info *d) +{ + unsigned long ctl_base; + unsigned long dma_base; + unsigned long cckctrl_port; + unsigned long intmask_port; + unsigned long mode_port; + unsigned long ecmode_port; + u32 reg = 0; + struct scc_ports *ports; + int rc; + + rc = pci_enable_device(dev); + if (rc) + goto end; + + rc = setup_mmio_scc(dev, d->name); + if (rc < 0) + goto end; + + ports = pci_get_drvdata(dev); + ctl_base = ports->ctl; + dma_base = ports->dma; + cckctrl_port = ctl_base + 0xff0; + intmask_port = dma_base + 0x010; + mode_port = ctl_base + 0x024; + ecmode_port = ctl_base + 0xf00; + + /* controller initialization */ + reg = 0; + out_be32((void*)cckctrl_port, reg); + reg |= CCKCTRL_ATACLKOEN; + out_be32((void*)cckctrl_port, reg); + reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN; + out_be32((void*)cckctrl_port, reg); + reg |= CCKCTRL_CRST; + out_be32((void*)cckctrl_port, reg); + + for (;;) { + reg = in_be32((void*)cckctrl_port); + if (reg & CCKCTRL_CRST) + break; + udelay(5000); + } + + reg |= CCKCTRL_ATARESET; + out_be32((void*)cckctrl_port, reg); + + out_be32((void*)ecmode_port, ECMODE_VALUE); + out_be32((void*)mode_port, MODE_JCUSFEN); + out_be32((void*)intmask_port, INTMASK_MSK); + + rc = scc_ide_setup_pci_device(dev, d); + + end: + return rc; +} + +static void scc_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + struct ide_io_ports *io_ports = &drive->hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) + out_be32((void *)io_ports->data_addr, + (tf->hob_data << 8) | tf->data); + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + scc_ide_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + scc_ide_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + scc_ide_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + scc_ide_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + scc_ide_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + scc_ide_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + scc_ide_outb((tf->device & HIHI) | drive->select, + io_ports->device_addr); +} + +static void scc_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + struct ide_io_ports *io_ports = &drive->hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data = (u16)in_be32((void *)io_ports->data_addr); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_FEATURE) + tf->feature = scc_ide_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = scc_ide_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = scc_ide_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = scc_ide_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = scc_ide_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = scc_ide_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + scc_ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = scc_ide_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = scc_ide_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = scc_ide_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = scc_ide_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = scc_ide_inb(io_ports->lbah_addr); + } +} + +static void scc_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + len++; + + if (drive->io_32bit) { + scc_ide_insl(data_addr, buf, len / 4); + + if ((len & 3) >= 2) + scc_ide_insw(data_addr, (u8 *)buf + (len & ~3), 1); + } else + scc_ide_insw(data_addr, buf, len / 2); +} + +static void scc_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + len++; + + if (drive->io_32bit) { + scc_ide_outsl(data_addr, buf, len / 4); + + if ((len & 3) >= 2) + scc_ide_outsw(data_addr, (u8 *)buf + (len & ~3), 1); + } else + scc_ide_outsw(data_addr, buf, len / 2); +} + +/** + * init_mmio_iops_scc - set up the iops for MMIO + * @hwif: interface to set up + * + */ + +static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct scc_ports *ports = pci_get_drvdata(dev); + unsigned long dma_base = ports->dma; + + ide_set_hwifdata(hwif, ports); + + hwif->dma_base = dma_base; + hwif->config_data = ports->ctl; +} + +/** + * init_iops_scc - set up iops + * @hwif: interface to set up + * + * Do the basic setup for the SCC hardware interface + * and then do the MMIO setup. + */ + +static void __devinit init_iops_scc(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + + hwif->hwif_data = NULL; + if (pci_get_drvdata(dev) == NULL) + return; + init_mmio_iops_scc(hwif); +} + +static int __devinit scc_init_dma(ide_hwif_t *hwif, + const struct ide_port_info *d) +{ + return ide_allocate_dma_engine(hwif); +} + +static u8 scc_cable_detect(ide_hwif_t *hwif) +{ + return ATA_CBL_PATA80; +} + +/** + * init_hwif_scc - set up hwif + * @hwif: interface to set up + * + * We do the basic set up of the interface structure. The SCC + * requires several custom handlers so we override the default + * ide DMA handlers appropriately. + */ + +static void __devinit init_hwif_scc(ide_hwif_t *hwif) +{ + /* PTERADD */ + out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma); + + if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN) + hwif->ultra_mask = ATA_UDMA6; /* 133MHz */ + else + hwif->ultra_mask = ATA_UDMA5; /* 100MHz */ +} + +static const struct ide_tp_ops scc_tp_ops = { + .exec_command = scc_exec_command, + .read_status = scc_read_status, + .read_altstatus = scc_read_altstatus, + .read_sff_dma_status = scc_read_sff_dma_status, + + .set_irq = scc_set_irq, + + .tf_load = scc_tf_load, + .tf_read = scc_tf_read, + + .input_data = scc_input_data, + .output_data = scc_output_data, +}; + +static const struct ide_port_ops scc_port_ops = { + .set_pio_mode = scc_set_pio_mode, + .set_dma_mode = scc_set_dma_mode, + .udma_filter = scc_udma_filter, + .cable_detect = scc_cable_detect, +}; + +static const struct ide_dma_ops scc_dma_ops = { + .dma_host_set = scc_dma_host_set, + .dma_setup = scc_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = scc_dma_start, + .dma_end = scc_dma_end, + .dma_test_irq = scc_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +#define DECLARE_SCC_DEV(name_str) \ + { \ + .name = name_str, \ + .init_iops = init_iops_scc, \ + .init_dma = scc_init_dma, \ + .init_hwif = init_hwif_scc, \ + .tp_ops = &scc_tp_ops, \ + .port_ops = &scc_port_ops, \ + .dma_ops = &scc_dma_ops, \ + .host_flags = IDE_HFLAG_SINGLE, \ + .pio_mask = ATA_PIO4, \ + } + +static const struct ide_port_info scc_chipsets[] __devinitdata = { + /* 0 */ DECLARE_SCC_DEV("sccIDE"), +}; + +/** + * scc_init_one - pci layer discovery entry + * @dev: PCI device + * @id: ident table entry + * + * Called by the PCI code when it finds an SCC PATA controller. + * We then use the IDE PCI generic helper to do most of the work. + */ + +static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + return init_setup_scc(dev, &scc_chipsets[id->driver_data]); +} + +/** + * scc_remove - pci layer remove entry + * @dev: PCI device + * + * Called by the PCI code when it removes an SCC PATA controller. + */ + +static void __devexit scc_remove(struct pci_dev *dev) +{ + struct scc_ports *ports = pci_get_drvdata(dev); + struct ide_host *host = ports->host; + + ide_host_remove(host); + + iounmap((void*)ports->dma); + iounmap((void*)ports->ctl); + pci_release_selected_regions(dev, (1 << 2) - 1); + memset(ports, 0, sizeof(*ports)); +} + +static const struct pci_device_id scc_pci_tbl[] = { + { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, scc_pci_tbl); + +static struct pci_driver scc_pci_driver = { + .name = "SCC IDE", + .id_table = scc_pci_tbl, + .probe = scc_init_one, + .remove = __devexit_p(scc_remove), +}; + +static int scc_ide_init(void) +{ + return ide_pci_register_driver(&scc_pci_driver); +} + +module_init(scc_ide_init); +/* -- No exit code? +static void scc_ide_exit(void) +{ + ide_pci_unregister_driver(&scc_pci_driver); +} +module_exit(scc_ide_exit); + */ + + +MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c new file mode 100644 index 0000000..437bc91 --- /dev/null +++ b/drivers/ide/serverworks.c @@ -0,0 +1,470 @@ +/* + * Copyright (C) 1998-2000 Michel Aubry + * Copyright (C) 1998-2000 Andrzej Krzysztofowicz + * Copyright (C) 1998-2000 Andre Hedrick + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * Portions copyright (c) 2001 Sun Microsystems + * + * + * RCC/ServerWorks IDE driver for Linux + * + * OSB4: `Open South Bridge' IDE Interface (fn 1) + * supports UDMA mode 2 (33 MB/s) + * + * CSB5: `Champion South Bridge' IDE Interface (fn 1) + * all revisions support UDMA mode 4 (66 MB/s) + * revision A2.0 and up support UDMA mode 5 (100 MB/s) + * + * *** The CSB5 does not provide ANY register *** + * *** to detect 80-conductor cable presence. *** + * + * CSB6: `Champion South Bridge' IDE Interface (optional: third channel) + * + * HT1000: AKA BCM5785 - Hypertransport Southbridge for Opteron systems. IDE + * controller same as the CSB6. Single channel ATA100 only. + * + * Documentation: + * Available under NDA only. Errata info very hard to get. + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "serverworks" + +#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ +#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ + +/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 + * can overrun their FIFOs when used with the CSB5 */ +static const char *svwks_bad_ata100[] = { + "ST320011A", + "ST340016A", + "ST360021A", + "ST380021A", + NULL +}; + +static struct pci_dev *isa_dev; + +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + char *m = (char *)&drive->id[ATA_ID_PROD]; + + while (*list) + if (!strcmp(*list++, m)) + return 1; + return 0; +} + +static u8 svwks_udma_filter(ide_drive_t *drive) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u8 mask = 0; + + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) + return 0x1f; + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { + u32 reg = 0; + if (isa_dev) + pci_read_config_dword(isa_dev, 0x64, ®); + + /* + * Don't enable UDMA on disk devices for the moment + */ + if(drive->media == ide_disk) + return 0; + /* Check the OSB4 DMA33 enable bit */ + return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0; + } else if (dev->revision < SVWKS_CSB5_REVISION_NEW) { + return 0x07; + } else if (dev->revision >= SVWKS_CSB5_REVISION_NEW) { + u8 btr = 0, mode; + pci_read_config_byte(dev, 0x5A, &btr); + mode = btr & 0x3; + + /* If someone decides to do UDMA133 on CSB5 the same + issue will bite so be inclusive */ + if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100)) + mode = 2; + + switch(mode) { + case 3: mask = 0x3f; break; + case 2: mask = 0x1f; break; + case 1: mask = 0x07; break; + default: mask = 0x00; break; + } + } + if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && + (!(PCI_FUNC(dev->devfn) & 1))) + mask = 0x1f; + + return mask; +} + +static u8 svwks_csb_check (struct pci_dev *dev) +{ + switch (dev->device) { + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: + case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: + return 1; + default: + break; + } + return 0; +} + +static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; + static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 }; + + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + + pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]); + + if (svwks_csb_check(dev)) { + u16 csb_pio = 0; + + pci_read_config_word(dev, 0x4a, &csb_pio); + + csb_pio &= ~(0x0f << (4 * drive->dn)); + csb_pio |= (pio << (4 * drive->dn)); + + pci_write_config_word(dev, 0x4a, csb_pio); + } +} + +static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + static const u8 udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; + static const u8 dma_modes[] = { 0x77, 0x21, 0x20 }; + static const u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 }; + + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 unit = drive->dn & 1; + + u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0; + + pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); + pci_read_config_byte(dev, 0x54, &ultra_enable); + + ultra_timing &= ~(0x0F << (4*unit)); + ultra_enable &= ~(0x01 << drive->dn); + + if (speed >= XFER_UDMA_0) { + dma_timing |= dma_modes[2]; + ultra_timing |= (udma_modes[speed - XFER_UDMA_0] << (4 * unit)); + ultra_enable |= (0x01 << drive->dn); + } else if (speed >= XFER_MW_DMA_0) + dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; + + pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing); + pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing); + pci_write_config_byte(dev, 0x54, ultra_enable); +} + +static unsigned int init_chipset_svwks(struct pci_dev *dev) +{ + unsigned int reg; + u8 btr; + + /* force Master Latency Timer value to 64 PCICLKs */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); + + /* OSB4 : South Bridge and IDE */ + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { + isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); + if (isa_dev) { + pci_read_config_dword(isa_dev, 0x64, ®); + reg &= ~0x00002000; /* disable 600ns interrupt mask */ + if(!(reg & 0x00004000)) + printk(KERN_DEBUG DRV_NAME " %s: UDMA not BIOS " + "enabled.\n", pci_name(dev)); + reg |= 0x00004000; /* enable UDMA/33 support */ + pci_write_config_dword(isa_dev, 0x64, reg); + } + } + + /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ + else if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) { + + /* Third Channel Test */ + if (!(PCI_FUNC(dev->devfn) & 1)) { + struct pci_dev * findev = NULL; + u32 reg4c = 0; + findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); + if (findev) { + pci_read_config_dword(findev, 0x4C, ®4c); + reg4c &= ~0x000007FF; + reg4c |= 0x00000040; + reg4c |= 0x00000020; + pci_write_config_dword(findev, 0x4C, reg4c); + pci_dev_put(findev); + } + outb_p(0x06, 0x0c00); + dev->irq = inb_p(0x0c01); + } else { + struct pci_dev * findev = NULL; + u8 reg41 = 0; + + findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL); + if (findev) { + pci_read_config_byte(findev, 0x41, ®41); + reg41 &= ~0x40; + pci_write_config_byte(findev, 0x41, reg41); + pci_dev_put(findev); + } + /* + * This is a device pin issue on CSB6. + * Since there will be a future raid mode, + * early versions of the chipset require the + * interrupt pin to be set, and it is a compatibility + * mode issue. + */ + if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) + dev->irq = 0; + } +// pci_read_config_dword(dev, 0x40, &pioreg) +// pci_write_config_dword(dev, 0x40, 0x99999999); +// pci_read_config_dword(dev, 0x44, &dmareg); +// pci_write_config_dword(dev, 0x44, 0xFFFFFFFF); + /* setup the UDMA Control register + * + * 1. clear bit 6 to enable DMA + * 2. enable DMA modes with bits 0-1 + * 00 : legacy + * 01 : udma2 + * 10 : udma2/udma4 + * 11 : udma2/udma4/udma5 + */ + pci_read_config_byte(dev, 0x5A, &btr); + btr &= ~0x40; + if (!(PCI_FUNC(dev->devfn) & 1)) + btr |= 0x2; + else + btr |= (dev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; + pci_write_config_byte(dev, 0x5A, btr); + } + /* Setup HT1000 SouthBridge Controller - Single Channel Only */ + else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) { + pci_read_config_byte(dev, 0x5A, &btr); + btr &= ~0x40; + btr |= 0x3; + pci_write_config_byte(dev, 0x5A, btr); + } + + return dev->irq; +} + +static u8 ata66_svwks_svwks(ide_hwif_t *hwif) +{ + return ATA_CBL_PATA80; +} + +/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits + * of the subsystem device ID indicate presence of an 80-pin cable. + * Bit 15 clear = secondary IDE channel does not have 80-pin cable. + * Bit 15 set = secondary IDE channel has 80-pin cable. + * Bit 14 clear = primary IDE channel does not have 80-pin cable. + * Bit 14 set = primary IDE channel has 80-pin cable. + */ +static u8 ata66_svwks_dell(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + + if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && + dev->vendor == PCI_VENDOR_ID_SERVERWORKS && + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE || + dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) + return ((1 << (hwif->channel + 14)) & + dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; + return ATA_CBL_PATA40; +} + +/* Sun Cobalt Alpine hardware avoids the 80-pin cable + * detect issue by attaching the drives directly to the board. + * This check follows the Dell precedent (how scary is that?!) + * + * WARNING: this only works on Alpine hardware! + */ +static u8 ata66_svwks_cobalt(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + + if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && + dev->vendor == PCI_VENDOR_ID_SERVERWORKS && + dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) + return ((1 << (hwif->channel + 14)) & + dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; + return ATA_CBL_PATA40; +} + +static u8 svwks_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + + /* Server Works */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS) + return ata66_svwks_svwks (hwif); + + /* Dell PowerEdge */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) + return ata66_svwks_dell (hwif); + + /* Cobalt Alpine */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN) + return ata66_svwks_cobalt (hwif); + + /* Per Specified Design by OEM, and ASIC Architect */ + if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) + return ATA_CBL_PATA80; + + return ATA_CBL_PATA40; +} + +static const struct ide_port_ops osb4_port_ops = { + .set_pio_mode = svwks_set_pio_mode, + .set_dma_mode = svwks_set_dma_mode, + .udma_filter = svwks_udma_filter, +}; + +static const struct ide_port_ops svwks_port_ops = { + .set_pio_mode = svwks_set_pio_mode, + .set_dma_mode = svwks_set_dma_mode, + .udma_filter = svwks_udma_filter, + .cable_detect = svwks_cable_detect, +}; + +#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS + +static const struct ide_port_info serverworks_chipsets[] __devinitdata = { + { /* 0: OSB4 */ + .name = DRV_NAME, + .init_chipset = init_chipset_svwks, + .port_ops = &osb4_port_ops, + .host_flags = IDE_HFLAGS_SVWKS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = 0x00, /* UDMA is problematic on OSB4 */ + }, + { /* 1: CSB5 */ + .name = DRV_NAME, + .init_chipset = init_chipset_svwks, + .port_ops = &svwks_port_ops, + .host_flags = IDE_HFLAGS_SVWKS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, + }, + { /* 2: CSB6 */ + .name = DRV_NAME, + .init_chipset = init_chipset_svwks, + .port_ops = &svwks_port_ops, + .host_flags = IDE_HFLAGS_SVWKS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, + }, + { /* 3: CSB6-2 */ + .name = DRV_NAME, + .init_chipset = init_chipset_svwks, + .port_ops = &svwks_port_ops, + .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, + }, + { /* 4: HT1000 */ + .name = DRV_NAME, + .init_chipset = init_chipset_svwks, + .port_ops = &svwks_port_ops, + .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, + } +}; + +/** + * svwks_init_one - called when a OSB/CSB is found + * @dev: the svwks 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 __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct ide_port_info d; + u8 idx = id->driver_data; + + d = serverworks_chipsets[idx]; + + if (idx == 1) + d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX; + else if (idx == 2 || idx == 3) { + if ((PCI_FUNC(dev->devfn) & 1) == 0) { + if (pci_resource_start(dev, 0) != 0x01f1) + d.host_flags |= IDE_HFLAG_NON_BOOTABLE; + d.host_flags |= IDE_HFLAG_SINGLE; + } else + d.host_flags &= ~IDE_HFLAG_SINGLE; + } + + return ide_pci_init_one(dev, &d, NULL); +} + +static const struct pci_device_id svwks_pci_tbl[] = { + { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0 }, + { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 1 }, + { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2 }, + { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 3 }, + { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, svwks_pci_tbl); + +static struct pci_driver svwks_pci_driver = { + .name = "Serverworks_IDE", + .id_table = svwks_pci_tbl, + .probe = svwks_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init svwks_ide_init(void) +{ + return ide_pci_register_driver(&svwks_pci_driver); +} + +static void __exit svwks_ide_exit(void) +{ + pci_unregister_driver(&svwks_pci_driver); +} + +module_init(svwks_ide_init); +module_exit(svwks_ide_exit); + +MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c new file mode 100644 index 0000000..8af9b23 --- /dev/null +++ b/drivers/ide/sgiioc4.c @@ -0,0 +1,674 @@ +/* + * Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2008 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "SGIIOC4" + +/* IOC4 Specific Definitions */ +#define IOC4_CMD_OFFSET 0x100 +#define IOC4_CTRL_OFFSET 0x120 +#define IOC4_DMA_OFFSET 0x140 +#define IOC4_INTR_OFFSET 0x0 + +#define IOC4_TIMING 0x00 +#define IOC4_DMA_PTR_L 0x01 +#define IOC4_DMA_PTR_H 0x02 +#define IOC4_DMA_ADDR_L 0x03 +#define IOC4_DMA_ADDR_H 0x04 +#define IOC4_BC_DEV 0x05 +#define IOC4_BC_MEM 0x06 +#define IOC4_DMA_CTRL 0x07 +#define IOC4_DMA_END_ADDR 0x08 + +/* Bits in the IOC4 Control/Status Register */ +#define IOC4_S_DMA_START 0x01 +#define IOC4_S_DMA_STOP 0x02 +#define IOC4_S_DMA_DIR 0x04 +#define IOC4_S_DMA_ACTIVE 0x08 +#define IOC4_S_DMA_ERROR 0x10 +#define IOC4_ATA_MEMERR 0x02 + +/* Read/Write Directions */ +#define IOC4_DMA_WRITE 0x04 +#define IOC4_DMA_READ 0x00 + +/* Interrupt Register Offsets */ +#define IOC4_INTR_REG 0x03 +#define IOC4_INTR_SET 0x05 +#define IOC4_INTR_CLEAR 0x07 + +#define IOC4_IDE_CACHELINE_SIZE 128 +#define IOC4_CMD_CTL_BLK_SIZE 0x20 +#define IOC4_SUPPORTED_FIRMWARE_REV 46 + +typedef struct { + u32 timing_reg0; + u32 timing_reg1; + u32 low_mem_ptr; + u32 high_mem_ptr; + u32 low_mem_addr; + u32 high_mem_addr; + u32 dev_byte_count; + u32 mem_byte_count; + u32 status; +} ioc4_dma_regs_t; + +/* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */ +/* IOC4 has only 1 IDE channel */ +#define IOC4_PRD_BYTES 16 +#define IOC4_PRD_ENTRIES (PAGE_SIZE /(4*IOC4_PRD_BYTES)) + + +static void +sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, + unsigned long ctrl_port, unsigned long irq_port) +{ + unsigned long reg = data_port; + int i; + + /* Registers are word (32 bit) aligned */ + for (i = 0; i <= 7; i++) + hw->io_ports_array[i] = reg + i * 4; + + hw->io_ports.ctl_addr = ctrl_port; + hw->io_ports.irq_addr = irq_port; +} + +static int +sgiioc4_checkirq(ide_hwif_t * hwif) +{ + unsigned long intr_addr = + hwif->io_ports.irq_addr + IOC4_INTR_REG * 4; + + if ((u8)readl((void __iomem *)intr_addr) & 0x03) + return 1; + + return 0; +} + +static u8 sgiioc4_read_status(ide_hwif_t *); + +static int +sgiioc4_clearirq(ide_drive_t * drive) +{ + u32 intr_reg; + ide_hwif_t *hwif = HWIF(drive); + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2); + + /* Code to check for PCI error conditions */ + intr_reg = readl((void __iomem *)other_ir); + if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */ + /* + * Using sgiioc4_read_status to read the Status register has a + * side effect of clearing the interrupt. The first read should + * clear it if it is set. The second read should return + * a "clear" status if it got cleared. If not, then spin + * for a bit trying to clear it. + */ + u8 stat = sgiioc4_read_status(hwif); + int count = 0; + + stat = sgiioc4_read_status(hwif); + while ((stat & ATA_BUSY) && (count++ < 100)) { + udelay(1); + stat = sgiioc4_read_status(hwif); + } + + if (intr_reg & 0x02) { + struct pci_dev *dev = to_pci_dev(hwif->dev); + /* Error when transferring DMA data on PCI bus */ + u32 pci_err_addr_low, pci_err_addr_high, + pci_stat_cmd_reg; + + pci_err_addr_low = + readl((void __iomem *)io_ports->irq_addr); + pci_err_addr_high = + readl((void __iomem *)(io_ports->irq_addr + 4)); + pci_read_config_dword(dev, PCI_COMMAND, + &pci_stat_cmd_reg); + printk(KERN_ERR + "%s(%s) : PCI Bus Error when doing DMA:" + " status-cmd reg is 0x%x\n", + __func__, drive->name, pci_stat_cmd_reg); + printk(KERN_ERR + "%s(%s) : PCI Error Address is 0x%x%x\n", + __func__, drive->name, + pci_err_addr_high, pci_err_addr_low); + /* Clear the PCI Error indicator */ + pci_write_config_dword(dev, PCI_COMMAND, 0x00000146); + } + + /* Clear the Interrupt, Error bits on the IOC4 */ + writel(0x03, (void __iomem *)other_ir); + + intr_reg = readl((void __iomem *)other_ir); + } + + return intr_reg & 3; +} + +static void sgiioc4_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4; + unsigned int reg = readl((void __iomem *)ioc4_dma_addr); + unsigned int temp_reg = reg | IOC4_S_DMA_START; + + writel(temp_reg, (void __iomem *)ioc4_dma_addr); +} + +static u32 +sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base) +{ + unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4; + u32 ioc4_dma; + int count; + + count = 0; + ioc4_dma = readl((void __iomem *)ioc4_dma_addr); + while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) { + udelay(1); + ioc4_dma = readl((void __iomem *)ioc4_dma_addr); + } + return ioc4_dma; +} + +/* Stops the IOC4 DMA Engine */ +static int sgiioc4_dma_end(ide_drive_t *drive) +{ + u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0; + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + int dma_stat = 0; + unsigned long *ending_dma = ide_get_hwifdata(hwif); + + writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4)); + + ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); + + if (ioc4_dma & IOC4_S_DMA_STOP) { + printk(KERN_ERR + "%s(%s): IOC4 DMA STOP bit is still 1 :" + "ioc4_dma_reg 0x%x\n", + __func__, drive->name, ioc4_dma); + dma_stat = 1; + } + + /* + * The IOC4 will DMA 1's to the ending dma area to indicate that + * previous data DMA is complete. This is necessary because of relaxed + * ordering between register reads and DMA writes on the Altix. + */ + while ((cnt++ < 200) && (!valid)) { + for (num = 0; num < 16; num++) { + if (ending_dma[num]) { + valid = 1; + break; + } + } + udelay(1); + } + if (!valid) { + printk(KERN_ERR "%s(%s) : DMA incomplete\n", __func__, + drive->name); + dma_stat = 1; + } + + bc_dev = readl((void __iomem *)(dma_base + IOC4_BC_DEV * 4)); + bc_mem = readl((void __iomem *)(dma_base + IOC4_BC_MEM * 4)); + + if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) { + if (bc_dev > bc_mem + 8) { + printk(KERN_ERR + "%s(%s): WARNING!! byte_count_dev %d " + "!= byte_count_mem %d\n", + __func__, drive->name, bc_dev, bc_mem); + } + } + + drive->waiting_for_dma = 0; + ide_destroy_dmatable(drive); + + return dma_stat; +} + +static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ +} + +/* returns 1 if dma irq issued, 0 otherwise */ +static int sgiioc4_dma_test_irq(ide_drive_t *drive) +{ + return sgiioc4_checkirq(HWIF(drive)); +} + +static void sgiioc4_dma_host_set(ide_drive_t *drive, int on) +{ + if (!on) + sgiioc4_clearirq(drive); +} + +static void +sgiioc4_resetproc(ide_drive_t * drive) +{ + sgiioc4_dma_end(drive); + sgiioc4_clearirq(drive); +} + +static void +sgiioc4_dma_lost_irq(ide_drive_t * drive) +{ + sgiioc4_resetproc(drive); + + ide_dma_lost_irq(drive); +} + +static u8 sgiioc4_read_status(ide_hwif_t *hwif) +{ + unsigned long port = hwif->io_ports.status_addr; + u8 reg = (u8) readb((void __iomem *) port); + + if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */ + unsigned long other_ir = port - 0x110; + unsigned int intr_reg = (u32) readl((void __iomem *) other_ir); + + /* Clear the Interrupt, Error bits on the IOC4 */ + if (intr_reg & 0x03) { + writel(0x03, (void __iomem *) other_ir); + intr_reg = (u32) readl((void __iomem *) other_ir); + } + } + + return reg; +} + +/* Creates a dma map for the scatter-gather list entries */ +static int __devinit +ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET; + int num_ports = sizeof (ioc4_dma_regs_t); + void *pad; + + printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); + + if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) { + printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx " + "already in use\n", __func__, hwif->name, + dma_base, dma_base + num_ports - 1); + return -1; + } + + hwif->dma_base = (unsigned long)hwif->io_ports.irq_addr + + IOC4_DMA_OFFSET; + + hwif->sg_max_nents = IOC4_PRD_ENTRIES; + + hwif->prd_max_nents = IOC4_PRD_ENTRIES; + hwif->prd_ent_size = IOC4_PRD_BYTES; + + if (ide_allocate_dma_engine(hwif)) + goto dma_pci_alloc_failure; + + pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE, + (dma_addr_t *)&hwif->extra_base); + if (pad) { + ide_set_hwifdata(hwif, pad); + return 0; + } + + ide_release_dma_engine(hwif); + + printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n", + __func__, hwif->name); + printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name); + +dma_pci_alloc_failure: + release_mem_region(dma_base, num_ports); + + return -1; +} + +/* Initializes the IOC4 DMA Engine */ +static void +sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) +{ + u32 ioc4_dma; + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4; + u32 dma_addr, ending_dma_addr; + + ioc4_dma = readl((void __iomem *)ioc4_dma_addr); + + if (ioc4_dma & IOC4_S_DMA_ACTIVE) { + printk(KERN_WARNING + "%s(%s):Warning!! DMA from previous transfer was still active\n", + __func__, drive->name); + writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr); + ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); + + if (ioc4_dma & IOC4_S_DMA_STOP) + printk(KERN_ERR + "%s(%s) : IOC4 Dma STOP bit is still 1\n", + __func__, drive->name); + } + + ioc4_dma = readl((void __iomem *)ioc4_dma_addr); + if (ioc4_dma & IOC4_S_DMA_ERROR) { + printk(KERN_WARNING + "%s(%s) : Warning!! - DMA Error during Previous" + " transfer | status 0x%x\n", + __func__, drive->name, ioc4_dma); + writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr); + ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); + + if (ioc4_dma & IOC4_S_DMA_STOP) + printk(KERN_ERR + "%s(%s) : IOC4 DMA STOP bit is still 1\n", + __func__, drive->name); + } + + /* Address of the Scatter Gather List */ + dma_addr = cpu_to_le32(hwif->dmatable_dma); + writel(dma_addr, (void __iomem *)(dma_base + IOC4_DMA_PTR_L * 4)); + + /* Address of the Ending DMA */ + memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE); + ending_dma_addr = cpu_to_le32(hwif->extra_base); + writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4)); + + writel(dma_direction, (void __iomem *)ioc4_dma_addr); + drive->waiting_for_dma = 1; +} + +/* IOC4 Scatter Gather list Format */ +/* 128 Bit entries to support 64 bit addresses in the future */ +/* The Scatter Gather list Entry should be in the BIG-ENDIAN Format */ +/* --------------------------------------------------------------------- */ +/* | Upper 32 bits - Zero | Lower 32 bits- address | */ +/* --------------------------------------------------------------------- */ +/* | Upper 32 bits - Zero |EOL| 15 unused | 16 Bit Length| */ +/* --------------------------------------------------------------------- */ +/* Creates the scatter gather list, DMA Table */ +static unsigned int +sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int *table = hwif->dmatable_cpu; + unsigned int count = 0, i = 1; + struct scatterlist *sg; + + hwif->sg_nents = i = ide_build_sglist(drive, rq); + + if (!i) + return 0; /* sglist of length Zero */ + + sg = hwif->sg_table; + while (i && sg_dma_len(sg)) { + dma_addr_t cur_addr; + int cur_len; + cur_addr = sg_dma_address(sg); + cur_len = sg_dma_len(sg); + + while (cur_len) { + if (count++ >= IOC4_PRD_ENTRIES) { + printk(KERN_WARNING + "%s: DMA table too small\n", + drive->name); + goto use_pio_instead; + } else { + u32 bcount = + 0x10000 - (cur_addr & 0xffff); + + if (bcount > cur_len) + bcount = cur_len; + + /* put the addr, length in + * the IOC4 dma-table format */ + *table = 0x0; + table++; + *table = cpu_to_be32(cur_addr); + table++; + *table = 0x0; + table++; + + *table = cpu_to_be32(bcount); + table++; + + cur_addr += bcount; + cur_len -= bcount; + } + } + + sg = sg_next(sg); + i--; + } + + if (count) { + table--; + *table |= cpu_to_be32(0x80000000); + return count; + } + +use_pio_instead: + ide_destroy_dmatable(drive); + + return 0; /* revert to PIO for this request */ +} + +static int sgiioc4_dma_setup(ide_drive_t *drive) +{ + struct request *rq = HWGROUP(drive)->rq; + unsigned int count = 0; + int ddir; + + if (rq_data_dir(rq)) + ddir = PCI_DMA_TODEVICE; + else + ddir = PCI_DMA_FROMDEVICE; + + if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) { + /* try PIO instead of DMA */ + ide_map_sg(drive, rq); + return 1; + } + + if (rq_data_dir(rq)) + /* Writes TO the IOC4 FROM Main Memory */ + ddir = IOC4_DMA_READ; + else + /* Writes FROM the IOC4 TO Main Memory */ + ddir = IOC4_DMA_WRITE; + + sgiioc4_configure_for_dma(ddir, drive); + + return 0; +} + +static const struct ide_tp_ops sgiioc4_tp_ops = { + .exec_command = ide_exec_command, + .read_status = sgiioc4_read_status, + .read_altstatus = ide_read_altstatus, + .read_sff_dma_status = ide_read_sff_dma_status, + + .set_irq = ide_set_irq, + + .tf_load = ide_tf_load, + .tf_read = ide_tf_read, + + .input_data = ide_input_data, + .output_data = ide_output_data, +}; + +static const struct ide_port_ops sgiioc4_port_ops = { + .set_dma_mode = sgiioc4_set_dma_mode, + /* reset DMA engine, clear IRQs */ + .resetproc = sgiioc4_resetproc, +}; + +static const struct ide_dma_ops sgiioc4_dma_ops = { + .dma_host_set = sgiioc4_dma_host_set, + .dma_setup = sgiioc4_dma_setup, + .dma_start = sgiioc4_dma_start, + .dma_end = sgiioc4_dma_end, + .dma_test_irq = sgiioc4_dma_test_irq, + .dma_lost_irq = sgiioc4_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info sgiioc4_port_info __devinitdata = { + .name = DRV_NAME, + .chipset = ide_pci, + .init_dma = ide_dma_sgiioc4, + .tp_ops = &sgiioc4_tp_ops, + .port_ops = &sgiioc4_port_ops, + .dma_ops = &sgiioc4_dma_ops, + .host_flags = IDE_HFLAG_MMIO, + .mwdma_mask = ATA_MWDMA2_ONLY, +}; + +static int __devinit +sgiioc4_ide_setup_pci_device(struct pci_dev *dev) +{ + unsigned long cmd_base, irqport; + unsigned long bar0, cmd_phys_base, ctl; + void __iomem *virt_base; + struct ide_host *host; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; + struct ide_port_info d = sgiioc4_port_info; + int rc; + + /* Get the CmdBlk and CtrlBlk Base Registers */ + bar0 = pci_resource_start(dev, 0); + virt_base = ioremap(bar0, pci_resource_len(dev, 0)); + if (virt_base == NULL) { + printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n", + DRV_NAME, bar0); + return -ENOMEM; + } + cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET; + ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET; + irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET; + + cmd_phys_base = bar0 + IOC4_CMD_OFFSET; + if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE, + DRV_NAME) == NULL) { + printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx " + "already in use\n", DRV_NAME, pci_name(dev), + cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); + return -EBUSY; + } + + /* Initialize the IO registers */ + memset(&hw, 0, sizeof(hw)); + sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); + hw.irq = dev->irq; + hw.chipset = ide_pci; + hw.dev = &dev->dev; + + /* Initializing chipset IRQ Registers */ + writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); + + host = ide_host_alloc(&d, hws); + if (host == NULL) { + rc = -ENOMEM; + goto err; + } + + rc = ide_host_register(host, &d, hws); + if (rc) + goto err_free; + + return 0; +err_free: + ide_host_free(host); +err: + release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE); + iounmap(virt_base); + return rc; +} + +static unsigned int __devinit +pci_init_sgiioc4(struct pci_dev *dev) +{ + int ret; + + printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n", + DRV_NAME, pci_name(dev), dev->revision); + + if (dev->revision < IOC4_SUPPORTED_FIRMWARE_REV) { + printk(KERN_ERR "Skipping %s IDE controller in slot %s: " + "firmware is obsolete - please upgrade to " + "revision46 or higher\n", + DRV_NAME, pci_name(dev)); + ret = -EAGAIN; + goto out; + } + ret = sgiioc4_ide_setup_pci_device(dev); +out: + return ret; +} + +int +ioc4_ide_attach_one(struct ioc4_driver_data *idd) +{ + /* PCI-RT does not bring out IDE connection. + * Do not attach to this particular IOC4. + */ + if (idd->idd_variant == IOC4_VARIANT_PCI_RT) + return 0; + + return pci_init_sgiioc4(idd->idd_pdev); +} + +static struct ioc4_submodule ioc4_ide_submodule = { + .is_name = "IOC4_ide", + .is_owner = THIS_MODULE, + .is_probe = ioc4_ide_attach_one, +/* .is_remove = ioc4_ide_remove_one, */ +}; + +static int __init ioc4_ide_init(void) +{ + return ioc4_register_submodule(&ioc4_ide_submodule); +} + +late_initcall(ioc4_ide_init); /* Call only after IDE init is done */ + +MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon"); +MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c new file mode 100644 index 0000000..eb4faf9 --- /dev/null +++ b/drivers/ide/siimage.c @@ -0,0 +1,857 @@ +/* + * Copyright (C) 2001-2002 Andre Hedrick + * Copyright (C) 2003 Red Hat + * Copyright (C) 2007-2008 MontaVista Software, Inc. + * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz + * + * May be copied or modified under the terms of the GNU General Public License + * + * Documentation for CMD680: + * http://gkernel.sourceforge.net/specs/sii/sii-0680a-v1.31.pdf.bz2 + * + * Documentation for SiI 3112: + * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 + * + * Errata and other documentation only available under NDA. + * + * + * FAQ Items: + * If you are using Marvell SATA-IDE adapters with Maxtor drives + * ensure the system is set up for ATA100/UDMA5, not UDMA6. + * + * If you are using WD drives with SATA bridges you must set the + * drive to "Single". "Master" will hang. + * + * If you have strange problems with nVidia chipset systems please + * see the SI support documentation and update your system BIOS + * if necessary + * + * The Dell DRAC4 has some interesting features including effectively hot + * unplugging/replugging the virtual CD interface when the DRAC is reset. + * This often causes drivers/ide/siimage to panic but is ok with the rather + * smarter code in libata. + * + * TODO: + * - IORDY fixes + * - VDMA support + */ + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "siimage" + +/** + * pdev_is_sata - check if device is SATA + * @pdev: PCI device to check + * + * Returns true if this is a SATA controller + */ + +static int pdev_is_sata(struct pci_dev *pdev) +{ +#ifdef CONFIG_BLK_DEV_IDE_SATA + switch (pdev->device) { + case PCI_DEVICE_ID_SII_3112: + case PCI_DEVICE_ID_SII_1210SA: + return 1; + case PCI_DEVICE_ID_SII_680: + return 0; + } + BUG(); +#endif + return 0; +} + +/** + * is_sata - check if hwif is SATA + * @hwif: interface to check + * + * Returns true if this is a SATA controller + */ + +static inline int is_sata(ide_hwif_t *hwif) +{ + return pdev_is_sata(to_pci_dev(hwif->dev)); +} + +/** + * siimage_selreg - return register base + * @hwif: interface + * @r: config offset + * + * Turn a config register offset into the right address in either + * PCI space or MMIO space to access the control register in question + * Thankfully this is a configuration operation, so isn't performance + * critical. + */ + +static unsigned long siimage_selreg(ide_hwif_t *hwif, int r) +{ + unsigned long base = (unsigned long)hwif->hwif_data; + + base += 0xA0 + r; + if (hwif->host_flags & IDE_HFLAG_MMIO) + base += hwif->channel << 6; + else + base += hwif->channel << 4; + return base; +} + +/** + * siimage_seldev - return register base + * @hwif: interface + * @r: config offset + * + * Turn a config register offset into the right address in either + * PCI space or MMIO space to access the control register in question + * including accounting for the unit shift. + */ + +static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long base = (unsigned long)hwif->hwif_data; + u8 unit = drive->dn & 1; + + base += 0xA0 + r; + if (hwif->host_flags & IDE_HFLAG_MMIO) + base += hwif->channel << 6; + else + base += hwif->channel << 4; + base |= unit << unit; + return base; +} + +static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr) +{ + struct ide_host *host = pci_get_drvdata(dev); + u8 tmp = 0; + + if (host->host_priv) + tmp = readb((void __iomem *)addr); + else + pci_read_config_byte(dev, addr, &tmp); + + return tmp; +} + +static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr) +{ + struct ide_host *host = pci_get_drvdata(dev); + u16 tmp = 0; + + if (host->host_priv) + tmp = readw((void __iomem *)addr); + else + pci_read_config_word(dev, addr, &tmp); + + return tmp; +} + +static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr) +{ + struct ide_host *host = pci_get_drvdata(dev); + + if (host->host_priv) + writeb(val, (void __iomem *)addr); + else + pci_write_config_byte(dev, addr, val); +} + +static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr) +{ + struct ide_host *host = pci_get_drvdata(dev); + + if (host->host_priv) + writew(val, (void __iomem *)addr); + else + pci_write_config_word(dev, addr, val); +} + +static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr) +{ + struct ide_host *host = pci_get_drvdata(dev); + + if (host->host_priv) + writel(val, (void __iomem *)addr); + else + pci_write_config_dword(dev, addr, val); +} + +/** + * sil_udma_filter - compute UDMA mask + * @drive: IDE device + * + * Compute the available UDMA speeds for the device on the interface. + * + * For the CMD680 this depends on the clocking mode (scsc), for the + * SI3112 SATA controller life is a bit simpler. + */ + +static u8 sil_pata_udma_filter(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long base = (unsigned long)hwif->hwif_data; + u8 scsc, mask = 0; + + base += (hwif->host_flags & IDE_HFLAG_MMIO) ? 0x4A : 0x8A; + + scsc = sil_ioread8(dev, base); + + switch (scsc & 0x30) { + case 0x10: /* 133 */ + mask = ATA_UDMA6; + break; + case 0x20: /* 2xPCI */ + mask = ATA_UDMA6; + break; + case 0x00: /* 100 */ + mask = ATA_UDMA5; + break; + default: /* Disabled ? */ + BUG(); + } + + return mask; +} + +static u8 sil_sata_udma_filter(ide_drive_t *drive) +{ + char *m = (char *)&drive->id[ATA_ID_PROD]; + + return strstr(m, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6; +} + +/** + * sil_set_pio_mode - set host controller for PIO mode + * @drive: drive + * @pio: PIO mode number + * + * Load the timing settings for this device mode into the + * controller. If we are in PIO mode 3 or 4 turn on IORDY + * monitoring (bit 9). The TF timing is bits 31:16 + */ + +static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) +{ + static const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; + static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; + + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + ide_drive_t *pair = ide_get_pair_dev(drive); + u32 speedt = 0; + u16 speedp = 0; + unsigned long addr = siimage_seldev(drive, 0x04); + unsigned long tfaddr = siimage_selreg(hwif, 0x02); + unsigned long base = (unsigned long)hwif->hwif_data; + u8 tf_pio = pio; + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + u8 addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84) + : (mmio ? 0xB4 : 0x80); + u8 mode = 0; + u8 unit = drive->dn & 1; + + /* trim *taskfile* PIO to the slowest of the master/slave */ + if (pair) { + u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4); + + if (pair_pio < tf_pio) + tf_pio = pair_pio; + } + + /* cheat for now and use the docs */ + speedp = data_speed[pio]; + speedt = tf_speed[tf_pio]; + + sil_iowrite16(dev, speedp, addr); + sil_iowrite16(dev, speedt, tfaddr); + + /* now set up IORDY */ + speedp = sil_ioread16(dev, tfaddr - 2); + speedp &= ~0x200; + if (pio > 2) + speedp |= 0x200; + sil_iowrite16(dev, speedp, tfaddr - 2); + + mode = sil_ioread8(dev, base + addr_mask); + mode &= ~(unit ? 0x30 : 0x03); + mode |= unit ? 0x10 : 0x01; + sil_iowrite8(dev, mode, base + addr_mask); +} + +/** + * sil_set_dma_mode - set host controller for DMA mode + * @drive: drive + * @speed: DMA mode + * + * Tune the SiI chipset for the desired DMA mode. + */ + +static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }; + static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 }; + static const u16 dma[] = { 0x2208, 0x10C2, 0x10C1 }; + + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long base = (unsigned long)hwif->hwif_data; + u16 ultra = 0, multi = 0; + u8 mode = 0, unit = drive->dn & 1; + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + u8 scsc = 0, addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84) + : (mmio ? 0xB4 : 0x80); + unsigned long ma = siimage_seldev(drive, 0x08); + unsigned long ua = siimage_seldev(drive, 0x0C); + + scsc = sil_ioread8 (dev, base + (mmio ? 0x4A : 0x8A)); + mode = sil_ioread8 (dev, base + addr_mask); + multi = sil_ioread16(dev, ma); + ultra = sil_ioread16(dev, ua); + + mode &= ~(unit ? 0x30 : 0x03); + ultra &= ~0x3F; + scsc = ((scsc & 0x30) == 0x00) ? 0 : 1; + + scsc = is_sata(hwif) ? 1 : scsc; + + if (speed >= XFER_UDMA_0) { + multi = dma[2]; + ultra |= scsc ? ultra6[speed - XFER_UDMA_0] : + ultra5[speed - XFER_UDMA_0]; + mode |= unit ? 0x30 : 0x03; + } else { + multi = dma[speed - XFER_MW_DMA_0]; + mode |= unit ? 0x20 : 0x02; + } + + sil_iowrite8 (dev, mode, base + addr_mask); + sil_iowrite16(dev, multi, ma); + sil_iowrite16(dev, ultra, ua); +} + +/* returns 1 if dma irq issued, 0 otherwise */ +static int siimage_io_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 dma_altstat = 0; + unsigned long addr = siimage_selreg(hwif, 1); + + /* return 1 if INTR asserted */ + if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4) + return 1; + + /* return 1 if Device INTR asserted */ + pci_read_config_byte(dev, addr, &dma_altstat); + if (dma_altstat & 8) + return 0; /* return 1; */ + + return 0; +} + +/** + * siimage_mmio_dma_test_irq - check we caused an IRQ + * @drive: drive we are testing + * + * Check if we caused an IDE DMA interrupt. We may also have caused + * SATA status interrupts, if so we clean them up and continue. + */ + +static int siimage_mmio_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long addr = siimage_selreg(hwif, 0x1); + void __iomem *sata_error_addr + = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET]; + + if (sata_error_addr) { + unsigned long base = (unsigned long)hwif->hwif_data; + u32 ext_stat = readl((void __iomem *)(base + 0x10)); + u8 watchdog = 0; + + if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { + u32 sata_error = readl(sata_error_addr); + + writel(sata_error, sata_error_addr); + watchdog = (sata_error & 0x00680000) ? 1 : 0; + printk(KERN_WARNING "%s: sata_error = 0x%08x, " + "watchdog = %d, %s\n", + drive->name, sata_error, watchdog, __func__); + } else + watchdog = (ext_stat & 0x8000) ? 1 : 0; + + ext_stat >>= 16; + if (!(ext_stat & 0x0404) && !watchdog) + return 0; + } + + /* return 1 if INTR asserted */ + if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4) + return 1; + + /* return 1 if Device INTR asserted */ + if (readb((void __iomem *)addr) & 8) + return 0; /* return 1; */ + + return 0; +} + +static int siimage_dma_test_irq(ide_drive_t *drive) +{ + if (drive->hwif->host_flags & IDE_HFLAG_MMIO) + return siimage_mmio_dma_test_irq(drive); + else + return siimage_io_dma_test_irq(drive); +} + +/** + * sil_sata_reset_poll - wait for SATA reset + * @drive: drive we are resetting + * + * Poll the SATA phy and see whether it has come back from the dead + * yet. + */ + +static int sil_sata_reset_poll(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + void __iomem *sata_status_addr + = (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET]; + + if (sata_status_addr) { + /* SATA Status is available only when in MMIO mode */ + u32 sata_stat = readl(sata_status_addr); + + if ((sata_stat & 0x03) != 0x03) { + printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", + hwif->name, sata_stat); + return -ENXIO; + } + } + + return 0; +} + +/** + * sil_sata_pre_reset - reset hook + * @drive: IDE device being reset + * + * For the SATA devices we need to handle recalibration/geometry + * differently + */ + +static void sil_sata_pre_reset(ide_drive_t *drive) +{ + if (drive->media == ide_disk) { + drive->special.b.set_geometry = 0; + drive->special.b.recalibrate = 0; + } +} + +/** + * init_chipset_siimage - set up an SI device + * @dev: PCI device + * + * Perform the initial PCI set up for this device. Attempt to switch + * to 133 MHz clocking if the system isn't already set up to do it. + */ + +static unsigned int init_chipset_siimage(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + void __iomem *ioaddr = host->host_priv; + unsigned long base, scsc_addr; + u8 rev = dev->revision, tmp; + + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255); + + if (ioaddr) + pci_set_master(dev); + + base = (unsigned long)ioaddr; + + if (ioaddr && pdev_is_sata(dev)) { + u32 tmp32, irq_mask; + + /* make sure IDE0/1 interrupts are not masked */ + irq_mask = (1 << 22) | (1 << 23); + tmp32 = readl(ioaddr + 0x48); + if (tmp32 & irq_mask) { + tmp32 &= ~irq_mask; + writel(tmp32, ioaddr + 0x48); + readl(ioaddr + 0x48); /* flush */ + } + writel(0, ioaddr + 0x148); + writel(0, ioaddr + 0x1C8); + } + + sil_iowrite8(dev, 0, base ? (base + 0xB4) : 0x80); + sil_iowrite8(dev, 0, base ? (base + 0xF4) : 0x84); + + scsc_addr = base ? (base + 0x4A) : 0x8A; + tmp = sil_ioread8(dev, scsc_addr); + + switch (tmp & 0x30) { + case 0x00: + /* On 100 MHz clocking, try and switch to 133 MHz */ + sil_iowrite8(dev, tmp | 0x10, scsc_addr); + break; + case 0x30: + /* Clocking is disabled, attempt to force 133MHz clocking. */ + sil_iowrite8(dev, tmp & ~0x20, scsc_addr); + case 0x10: + /* On 133Mhz clocking. */ + break; + case 0x20: + /* On PCIx2 clocking. */ + break; + } + + tmp = sil_ioread8(dev, scsc_addr); + + sil_iowrite8 (dev, 0x72, base + 0xA1); + sil_iowrite16(dev, 0x328A, base + 0xA2); + sil_iowrite32(dev, 0x62DD62DD, base + 0xA4); + sil_iowrite32(dev, 0x43924392, base + 0xA8); + sil_iowrite32(dev, 0x40094009, base + 0xAC); + sil_iowrite8 (dev, 0x72, base ? (base + 0xE1) : 0xB1); + sil_iowrite16(dev, 0x328A, base ? (base + 0xE2) : 0xB2); + sil_iowrite32(dev, 0x62DD62DD, base ? (base + 0xE4) : 0xB4); + sil_iowrite32(dev, 0x43924392, base ? (base + 0xE8) : 0xB8); + sil_iowrite32(dev, 0x40094009, base ? (base + 0xEC) : 0xBC); + + if (base && pdev_is_sata(dev)) { + writel(0xFFFF0000, ioaddr + 0x108); + writel(0xFFFF0000, ioaddr + 0x188); + writel(0x00680000, ioaddr + 0x148); + writel(0x00680000, ioaddr + 0x1C8); + } + + /* report the clocking mode of the controller */ + if (!pdev_is_sata(dev)) { + static const char *clk_str[] = + { "== 100", "== 133", "== 2X PCI", "DISABLED!" }; + + tmp >>= 4; + printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s\n", + pci_name(dev), clk_str[tmp & 3]); + } + + return 0; +} + +/** + * init_mmio_iops_siimage - set up the iops for MMIO + * @hwif: interface to set up + * + * The basic setup here is fairly simple, we can use standard MMIO + * operations. However we do have to set the taskfile register offsets + * by hand as there isn't a standard defined layout for them this time. + * + * The hardware supports buffered taskfiles and also some rather nice + * extended PRD tables. For better SI3112 support use the libata driver + */ + +static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_host *host = pci_get_drvdata(dev); + void *addr = host->host_priv; + u8 ch = hwif->channel; + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long base; + + /* + * Fill in the basic hwif bits + */ + hwif->host_flags |= IDE_HFLAG_MMIO; + + hwif->hwif_data = addr; + + /* + * Now set up the hw. We have to do this ourselves as the + * MMIO layout isn't the same as the standard port based I/O. + */ + memset(io_ports, 0, sizeof(*io_ports)); + + base = (unsigned long)addr; + if (ch) + base += 0xC0; + else + base += 0x80; + + /* + * The buffered task file doesn't have status/control, so we + * can't currently use it sanely since we want to use LBA48 mode. + */ + io_ports->data_addr = base; + io_ports->error_addr = base + 1; + io_ports->nsect_addr = base + 2; + io_ports->lbal_addr = base + 3; + io_ports->lbam_addr = base + 4; + io_ports->lbah_addr = base + 5; + io_ports->device_addr = base + 6; + io_ports->status_addr = base + 7; + io_ports->ctl_addr = base + 10; + + if (pdev_is_sata(dev)) { + base = (unsigned long)addr; + if (ch) + base += 0x80; + hwif->sata_scr[SATA_STATUS_OFFSET] = base + 0x104; + hwif->sata_scr[SATA_ERROR_OFFSET] = base + 0x108; + hwif->sata_scr[SATA_CONTROL_OFFSET] = base + 0x100; + } + + hwif->irq = dev->irq; + + hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00); +} + +static int is_dev_seagate_sata(ide_drive_t *drive) +{ + const char *s = (const char *)&drive->id[ATA_ID_PROD]; + unsigned len = strnlen(s, ATA_ID_PROD_LEN); + + if ((len > 4) && (!memcmp(s, "ST", 2))) + if ((!memcmp(s + len - 2, "AS", 2)) || + (!memcmp(s + len - 3, "ASL", 3))) { + printk(KERN_INFO "%s: applying pessimistic Seagate " + "errata fix\n", drive->name); + return 1; + } + + return 0; +} + +/** + * sil_quirkproc - post probe fixups + * @drive: drive + * + * Called after drive probe we use this to decide whether the + * Seagate fixup must be applied. This used to be in init_iops but + * that can occur before we know what drives are present. + */ + +static void sil_quirkproc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + + /* Try and rise the rqsize */ + if (!is_sata(hwif) || !is_dev_seagate_sata(drive)) + hwif->rqsize = 128; +} + +/** + * init_iops_siimage - set up iops + * @hwif: interface to set up + * + * Do the basic setup for the SIIMAGE hardware interface + * and then do the MMIO setup if we can. This is the first + * look in we get for setting up the hwif so that we + * can get the iops right before using them. + */ + +static void __devinit init_iops_siimage(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_host *host = pci_get_drvdata(dev); + + hwif->hwif_data = NULL; + + /* Pessimal until we finish probing */ + hwif->rqsize = 15; + + if (host->host_priv) + init_mmio_iops_siimage(hwif); +} + +/** + * sil_cable_detect - cable detection + * @hwif: interface to check + * + * Check for the presence of an ATA66 capable cable on the interface. + */ + +static u8 sil_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long addr = siimage_selreg(hwif, 0); + u8 ata66 = sil_ioread8(dev, addr); + + return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; +} + +static const struct ide_port_ops sil_pata_port_ops = { + .set_pio_mode = sil_set_pio_mode, + .set_dma_mode = sil_set_dma_mode, + .quirkproc = sil_quirkproc, + .udma_filter = sil_pata_udma_filter, + .cable_detect = sil_cable_detect, +}; + +static const struct ide_port_ops sil_sata_port_ops = { + .set_pio_mode = sil_set_pio_mode, + .set_dma_mode = sil_set_dma_mode, + .reset_poll = sil_sata_reset_poll, + .pre_reset = sil_sata_pre_reset, + .quirkproc = sil_quirkproc, + .udma_filter = sil_sata_udma_filter, + .cable_detect = sil_cable_detect, +}; + +static const struct ide_dma_ops sil_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = ide_dma_end, + .dma_test_irq = siimage_dma_test_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = ide_dma_lost_irq, +}; + +#define DECLARE_SII_DEV(p_ops) \ + { \ + .name = DRV_NAME, \ + .init_chipset = init_chipset_siimage, \ + .init_iops = init_iops_siimage, \ + .port_ops = p_ops, \ + .dma_ops = &sil_dma_ops, \ + .pio_mask = ATA_PIO4, \ + .mwdma_mask = ATA_MWDMA2, \ + .udma_mask = ATA_UDMA6, \ + } + +static const struct ide_port_info siimage_chipsets[] __devinitdata = { + /* 0: SiI680 */ DECLARE_SII_DEV(&sil_pata_port_ops), + /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops) +}; + +/** + * siimage_init_one - PCI layer discovery entry + * @dev: PCI device + * @id: ident table entry + * + * Called by the PCI code when it finds an SiI680 or SiI3112 controller. + * We then use the IDE PCI generic helper to do most of the work. + */ + +static int __devinit siimage_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + void __iomem *ioaddr = NULL; + resource_size_t bar5 = pci_resource_start(dev, 5); + unsigned long barsize = pci_resource_len(dev, 5); + int rc; + struct ide_port_info d; + u8 idx = id->driver_data; + u8 BA5_EN; + + d = siimage_chipsets[idx]; + + if (idx) { + static int first = 1; + + if (first) { + printk(KERN_INFO DRV_NAME ": For full SATA support you " + "should use the libata sata_sil module.\n"); + first = 0; + } + + d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA; + } + + rc = pci_enable_device(dev); + if (rc) + return rc; + + pci_read_config_byte(dev, 0x8A, &BA5_EN); + if ((BA5_EN & 0x01) || bar5) { + /* + * Drop back to PIO if we can't map the MMIO. Some systems + * seem to get terminally confused in the PCI spaces. + */ + if (!request_mem_region(bar5, barsize, d.name)) { + printk(KERN_WARNING DRV_NAME " %s: MMIO ports not " + "available\n", pci_name(dev)); + } else { + ioaddr = ioremap(bar5, barsize); + if (ioaddr == NULL) + release_mem_region(bar5, barsize); + } + } + + rc = ide_pci_init_one(dev, &d, ioaddr); + if (rc) { + if (ioaddr) { + iounmap(ioaddr); + release_mem_region(bar5, barsize); + } + pci_disable_device(dev); + } + + return rc; +} + +static void __devexit siimage_remove(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + void __iomem *ioaddr = host->host_priv; + + ide_pci_remove(dev); + + if (ioaddr) { + resource_size_t bar5 = pci_resource_start(dev, 5); + unsigned long barsize = pci_resource_len(dev, 5); + + iounmap(ioaddr); + release_mem_region(bar5, barsize); + } + + pci_disable_device(dev); +} + +static const struct pci_device_id siimage_pci_tbl[] = { + { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), 0 }, +#ifdef CONFIG_BLK_DEV_IDE_SATA + { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112), 1 }, + { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 }, +#endif + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, siimage_pci_tbl); + +static struct pci_driver siimage_pci_driver = { + .name = "SiI_IDE", + .id_table = siimage_pci_tbl, + .probe = siimage_init_one, + .remove = __devexit_p(siimage_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init siimage_ide_init(void) +{ + return ide_pci_register_driver(&siimage_pci_driver); +} + +static void __exit siimage_ide_exit(void) +{ + pci_unregister_driver(&siimage_pci_driver); +} + +module_init(siimage_ide_init); +module_exit(siimage_ide_exit); + +MODULE_AUTHOR("Andre Hedrick, Alan Cox"); +MODULE_DESCRIPTION("PCI driver module for SiI IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c new file mode 100644 index 0000000..ad32e18 --- /dev/null +++ b/drivers/ide/sis5513.c @@ -0,0 +1,641 @@ +/* + * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 2002 Lionel Bouton , Maintainer + * Copyright (C) 2003 Vojtech Pavlik + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * + * May be copied or modified under the terms of the GNU General Public License + * + * + * Thanks : + * + * SiS Taiwan : for direct support and hardware. + * Daniela Engert : for initial ATA100 advices and numerous others. + * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt : + * for checking code correctness, providing patches. + * + * + * Original tests and design on the SiS620 chipset. + * ATA100 tests and design on the SiS735 chipset. + * ATA16/33 support from specs + * ATA133 support for SiS961/962 by L.C. Chang + * ATA133 961/962/963 fixes by Vojtech Pavlik + * + * Documentation: + * SiS chipset documentation available under NDA to companies only + * (not to individuals). + */ + +/* + * The original SiS5513 comes from a SiS5511/55112/5513 chipset. The original + * SiS5513 was also used in the SiS5596/5513 chipset. Thus if we see a SiS5511 + * or SiS5596, we can assume we see the first MWDMA-16 capable SiS5513 chip. + * + * Later SiS chipsets integrated the 5513 functionality into the NorthBridge, + * starting with SiS5571 and up to SiS745. The PCI ID didn't change, though. We + * can figure out that we have a more modern and more capable 5513 by looking + * for the respective NorthBridge IDs. + * + * Even later (96x family) SiS chipsets use the MuTIOL link and place the 5513 + * into the SouthBrige. Here we cannot rely on looking up the NorthBridge PCI + * ID, while the now ATA-133 capable 5513 still has the same PCI ID. + * Fortunately the 5513 can be 'unmasked' by fiddling with some config space + * bits, changing its device id to the true one - 5517 for 961 and 5518 for + * 962/963. + */ + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "sis5513" + +/* registers layout and init values are chipset family dependant */ + +#define ATA_16 0x01 +#define ATA_33 0x02 +#define ATA_66 0x03 +#define ATA_100a 0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */ +#define ATA_100 0x05 +#define ATA_133a 0x06 /* SiS961b with 133 support */ +#define ATA_133 0x07 /* SiS962/963 */ + +static u8 chipset_family; + +/* + * Devices supported + */ +static const struct { + const char *name; + u16 host_id; + u8 chipset_family; + u8 flags; +} SiSHostChipInfo[] = { + { "SiS968", PCI_DEVICE_ID_SI_968, ATA_133 }, + { "SiS966", PCI_DEVICE_ID_SI_966, ATA_133 }, + { "SiS965", PCI_DEVICE_ID_SI_965, ATA_133 }, + { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100 }, + { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100 }, + { "SiS733", PCI_DEVICE_ID_SI_733, ATA_100 }, + { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100 }, + { "SiS633", PCI_DEVICE_ID_SI_633, ATA_100 }, + + { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a }, + { "SiS550", PCI_DEVICE_ID_SI_550, ATA_100a }, + + { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66 }, + { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66 }, + { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66 }, + { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66 }, + { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66 }, + + { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33 }, + { "SiS5598", PCI_DEVICE_ID_SI_5598, ATA_33 }, + { "SiS5597", PCI_DEVICE_ID_SI_5597, ATA_33 }, + { "SiS5591/2", PCI_DEVICE_ID_SI_5591, ATA_33 }, + { "SiS5582", PCI_DEVICE_ID_SI_5582, ATA_33 }, + { "SiS5581", PCI_DEVICE_ID_SI_5581, ATA_33 }, + + { "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 }, + { "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 }, + { "SiS5517", PCI_DEVICE_ID_SI_5517, ATA_16 }, + { "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 }, +}; + +/* Cycle time bits and values vary across chip dma capabilities + These three arrays hold the register layout and the values to set. + Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ + +/* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */ +static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 }; +static u8 cycle_time_range[] = { 0, 0, 2, 3, 3, 4, 4 }; +static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { + { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ + { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ + { 3, 2, 1, 0, 0, 0, 0 }, /* ATA_33 */ + { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_66 */ + { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific), + different cycle_time range and offset */ + { 11, 7, 5, 4, 2, 1, 0 }, /* ATA_100 */ + { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */ + { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */ +}; +/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133 + See SiS962 data sheet for more detail */ +static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { + { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ + { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ + { 2, 1, 1, 0, 0, 0, 0 }, + { 4, 3, 2, 1, 0, 0, 0 }, + { 4, 3, 2, 1, 0, 0, 0 }, + { 6, 4, 3, 1, 1, 1, 0 }, + { 9, 6, 4, 2, 2, 2, 2 }, + { 9, 6, 4, 2, 2, 2, 2 }, +}; +/* Initialize time, Active time, Recovery time vary across + IDE clock settings. These 3 arrays hold the register value + for PIO0/1/2/3/4 and DMA0/1/2 mode in order */ +static u8 ini_time_value[][8] = { + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 2, 1, 0, 0, 0, 1, 0, 0 }, + { 4, 3, 1, 1, 1, 3, 1, 1 }, + { 4, 3, 1, 1, 1, 3, 1, 1 }, + { 6, 4, 2, 2, 2, 4, 2, 2 }, + { 9, 6, 3, 3, 3, 6, 3, 3 }, + { 9, 6, 3, 3, 3, 6, 3, 3 }, +}; +static u8 act_time_value[][8] = { + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 9, 9, 9, 2, 2, 7, 2, 2 }, + { 19, 19, 19, 5, 4, 14, 5, 4 }, + { 19, 19, 19, 5, 4, 14, 5, 4 }, + { 28, 28, 28, 7, 6, 21, 7, 6 }, + { 38, 38, 38, 10, 9, 28, 10, 9 }, + { 38, 38, 38, 10, 9, 28, 10, 9 }, +}; +static u8 rco_time_value[][8] = { + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 9, 2, 0, 2, 0, 7, 1, 1 }, + { 19, 5, 1, 5, 2, 16, 3, 2 }, + { 19, 5, 1, 5, 2, 16, 3, 2 }, + { 30, 9, 3, 9, 4, 25, 6, 4 }, + { 40, 12, 4, 12, 5, 34, 12, 5 }, + { 40, 12, 4, 12, 5, 34, 12, 5 }, +}; + +/* + * Printing configuration + */ +/* Used for chipset type printing at boot time */ +static char *chipset_capability[] = { + "ATA", "ATA 16", + "ATA 33", "ATA 66", + "ATA 100 (1st gen)", "ATA 100 (2nd gen)", + "ATA 133 (1st gen)", "ATA 133 (2nd gen)" +}; + +/* + * Configuration functions + */ + +static u8 sis_ata133_get_base(ide_drive_t *drive) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u32 reg54 = 0; + + pci_read_config_dword(dev, 0x54, ®54); + + return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4; +} + +static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u16 t1 = 0; + u8 drive_pci = 0x40 + drive->dn * 2; + + const u16 pio_timings[] = { 0x000, 0x607, 0x404, 0x303, 0x301 }; + const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 }; + + pci_read_config_word(dev, drive_pci, &t1); + + /* clear active/recovery timings */ + t1 &= ~0x070f; + if (mode >= XFER_MW_DMA_0) { + if (chipset_family > ATA_16) + t1 &= ~0x8000; /* disable UDMA */ + t1 |= mwdma_timings[mode - XFER_MW_DMA_0]; + } else + t1 |= pio_timings[mode - XFER_PIO_0]; + + pci_write_config_word(dev, drive_pci, t1); +} + +static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u8 t1, drive_pci = 0x40 + drive->dn * 2; + + /* timing bits: 7:4 active 3:0 recovery */ + const u8 pio_timings[] = { 0x00, 0x67, 0x44, 0x33, 0x31 }; + const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 }; + + if (mode >= XFER_MW_DMA_0) { + u8 t2 = 0; + + pci_read_config_byte(dev, drive_pci, &t2); + t2 &= ~0x80; /* disable UDMA */ + pci_write_config_byte(dev, drive_pci, t2); + + t1 = mwdma_timings[mode - XFER_MW_DMA_0]; + } else + t1 = pio_timings[mode - XFER_PIO_0]; + + pci_write_config_byte(dev, drive_pci + 1, t1); +} + +static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u32 t1 = 0; + u8 drive_pci = sis_ata133_get_base(drive), clk, idx; + + pci_read_config_dword(dev, drive_pci, &t1); + + t1 &= 0xc0c00fff; + clk = (t1 & 0x08) ? ATA_133 : ATA_100; + if (mode >= XFER_MW_DMA_0) { + t1 &= ~0x04; /* disable UDMA */ + idx = mode - XFER_MW_DMA_0 + 5; + } else + idx = mode - XFER_PIO_0; + t1 |= ini_time_value[clk][idx] << 12; + t1 |= act_time_value[clk][idx] << 16; + t1 |= rco_time_value[clk][idx] << 24; + + pci_write_config_dword(dev, drive_pci, t1); +} + +static void sis_program_timings(ide_drive_t *drive, const u8 mode) +{ + if (chipset_family < ATA_100) /* ATA_16/33/66/100a */ + sis_ata16_program_timings(drive, mode); + else if (chipset_family < ATA_133) /* ATA_100/133a */ + sis_ata100_program_timings(drive, mode); + else /* ATA_133 */ + sis_ata133_program_timings(drive, mode); +} + +static void config_drive_art_rwp(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 reg4bh = 0; + u8 rw_prefetch = 0; + + pci_read_config_byte(dev, 0x4b, ®4bh); + + if (drive->media == ide_disk) + rw_prefetch = 0x11 << drive->dn; + + if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch) + pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); +} + +static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + config_drive_art_rwp(drive); + sis_program_timings(drive, XFER_PIO_0 + pio); +} + +static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u32 regdw = 0; + u8 drive_pci = sis_ata133_get_base(drive), clk, idx; + + pci_read_config_dword(dev, drive_pci, ®dw); + + regdw |= 0x04; + regdw &= 0xfffff00f; + /* check if ATA133 enable */ + clk = (regdw & 0x08) ? ATA_133 : ATA_100; + idx = mode - XFER_UDMA_0; + regdw |= cycle_time_value[clk][idx] << 4; + regdw |= cvs_time_value[clk][idx] << 8; + + pci_write_config_dword(dev, drive_pci, regdw); +} + +static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family; + + pci_read_config_byte(dev, drive_pci + 1, ®); + + /* force the UDMA bit on if we want to use UDMA */ + reg |= 0x80; + /* clean reg cycle time bits */ + reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]); + /* set reg cycle time bits */ + reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i]; + + pci_write_config_byte(dev, drive_pci + 1, reg); +} + +static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode) +{ + if (chipset_family >= ATA_133) /* ATA_133 */ + sis_ata133_program_udma_timings(drive, mode); + else /* ATA_33/66/100a/100/133a */ + sis_ata33_program_udma_timings(drive, mode); +} + +static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + if (speed >= XFER_UDMA_0) + sis_program_udma_timings(drive, speed); + else + sis_program_timings(drive, speed); +} + +static u8 sis_ata133_udma_filter(ide_drive_t *drive) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u32 regdw = 0; + u8 drive_pci = sis_ata133_get_base(drive); + + pci_read_config_dword(dev, drive_pci, ®dw); + + /* if ATA133 disable, we should not set speed above UDMA5 */ + return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5; +} + +static int __devinit sis_find_family(struct pci_dev *dev) +{ + struct pci_dev *host; + int i = 0; + + chipset_family = 0; + + for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) { + + host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL); + + if (!host) + continue; + + chipset_family = SiSHostChipInfo[i].chipset_family; + + /* Special case for SiS630 : 630S/ET is ATA_100a */ + if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) { + if (host->revision >= 0x30) + chipset_family = ATA_100a; + } + pci_dev_put(host); + + printk(KERN_INFO DRV_NAME " %s: %s %s controller\n", + pci_name(dev), SiSHostChipInfo[i].name, + chipset_capability[chipset_family]); + } + + if (!chipset_family) { /* Belongs to pci-quirks */ + + u32 idemisc; + u16 trueid; + + /* Disable ID masking and register remapping */ + pci_read_config_dword(dev, 0x54, &idemisc); + pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff)); + pci_read_config_word(dev, PCI_DEVICE_ID, &trueid); + pci_write_config_dword(dev, 0x54, idemisc); + + if (trueid == 0x5518) { + printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n", + pci_name(dev)); + chipset_family = ATA_133; + + /* Check for 5513 compability mapping + * We must use this, else the port enabled code will fail, + * as it expects the enablebits at 0x4a. + */ + if ((idemisc & 0x40000000) == 0) { + pci_write_config_dword(dev, 0x54, idemisc | 0x40000000); + printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n", + pci_name(dev)); + } + } + } + + if (!chipset_family) { /* Belongs to pci-quirks */ + + struct pci_dev *lpc_bridge; + u16 trueid; + u8 prefctl; + u8 idecfg; + + pci_read_config_byte(dev, 0x4a, &idecfg); + pci_write_config_byte(dev, 0x4a, idecfg | 0x10); + pci_read_config_word(dev, PCI_DEVICE_ID, &trueid); + pci_write_config_byte(dev, 0x4a, idecfg); + + if (trueid == 0x5517) { /* SiS 961/961B */ + + lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */ + pci_read_config_byte(dev, 0x49, &prefctl); + pci_dev_put(lpc_bridge); + + if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) { + printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n", + pci_name(dev)); + chipset_family = ATA_133a; + } else { + printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n", + pci_name(dev)); + chipset_family = ATA_100; + } + } + } + + return chipset_family; +} + +static unsigned int init_chipset_sis5513(struct pci_dev *dev) +{ + /* Make general config ops here + 1/ tell IDE channels to operate in Compatibility mode only + 2/ tell old chips to allow per drive IDE timings */ + + u8 reg; + u16 regw; + + switch (chipset_family) { + case ATA_133: + /* SiS962 operation mode */ + pci_read_config_word(dev, 0x50, ®w); + if (regw & 0x08) + pci_write_config_word(dev, 0x50, regw&0xfff7); + pci_read_config_word(dev, 0x52, ®w); + if (regw & 0x08) + pci_write_config_word(dev, 0x52, regw&0xfff7); + break; + case ATA_133a: + case ATA_100: + /* Fixup latency */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); + /* Set compatibility bit */ + pci_read_config_byte(dev, 0x49, ®); + if (!(reg & 0x01)) + pci_write_config_byte(dev, 0x49, reg|0x01); + break; + case ATA_100a: + case ATA_66: + /* Fixup latency */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); + + /* On ATA_66 chips the bit was elsewhere */ + pci_read_config_byte(dev, 0x52, ®); + if (!(reg & 0x04)) + pci_write_config_byte(dev, 0x52, reg|0x04); + break; + case ATA_33: + /* On ATA_33 we didn't have a single bit to set */ + pci_read_config_byte(dev, 0x09, ®); + if ((reg & 0x0f) != 0x00) + pci_write_config_byte(dev, 0x09, reg&0xf0); + case ATA_16: + /* force per drive recovery and active timings + needed on ATA_33 and below chips */ + pci_read_config_byte(dev, 0x52, ®); + if (!(reg & 0x08)) + pci_write_config_byte(dev, 0x52, reg|0x08); + break; + } + + return 0; +} + +struct sis_laptop { + u16 device; + u16 subvendor; + u16 subdevice; +}; + +static const struct sis_laptop sis_laptop[] = { + /* devid, subvendor, subdev */ + { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ + { 0x5513, 0x1734, 0x105f }, /* FSC Amilo A1630 */ + { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ + /* end marker */ + { 0, } +}; + +static u8 sis_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *pdev = to_pci_dev(hwif->dev); + const struct sis_laptop *lap = &sis_laptop[0]; + u8 ata66 = 0; + + while (lap->device) { + if (lap->device == pdev->device && + lap->subvendor == pdev->subsystem_vendor && + lap->subdevice == pdev->subsystem_device) + return ATA_CBL_PATA40_SHORT; + lap++; + } + + if (chipset_family >= ATA_133) { + u16 regw = 0; + u16 reg_addr = hwif->channel ? 0x52: 0x50; + pci_read_config_word(pdev, reg_addr, ®w); + ata66 = (regw & 0x8000) ? 0 : 1; + } else if (chipset_family >= ATA_66) { + u8 reg48h = 0; + u8 mask = hwif->channel ? 0x20 : 0x10; + pci_read_config_byte(pdev, 0x48, ®48h); + ata66 = (reg48h & mask) ? 0 : 1; + } + + return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40; +} + +static const struct ide_port_ops sis_port_ops = { + .set_pio_mode = sis_set_pio_mode, + .set_dma_mode = sis_set_dma_mode, + .cable_detect = sis_cable_detect, +}; + +static const struct ide_port_ops sis_ata133_port_ops = { + .set_pio_mode = sis_set_pio_mode, + .set_dma_mode = sis_set_dma_mode, + .udma_filter = sis_ata133_udma_filter, + .cable_detect = sis_cable_detect, +}; + +static const struct ide_port_info sis5513_chipset __devinitdata = { + .name = DRV_NAME, + .init_chipset = init_chipset_sis5513, + .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} }, + .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, +}; + +static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct ide_port_info d = sis5513_chipset; + u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; + int rc; + + rc = pci_enable_device(dev); + if (rc) + return rc; + + if (sis_find_family(dev) == 0) + return -ENOTSUPP; + + if (chipset_family >= ATA_133) + d.port_ops = &sis_ata133_port_ops; + else + d.port_ops = &sis_port_ops; + + d.udma_mask = udma_rates[chipset_family]; + + return ide_pci_init_one(dev, &d, NULL); +} + +static void __devexit sis5513_remove(struct pci_dev *dev) +{ + ide_pci_remove(dev); + pci_disable_device(dev); +} + +static const struct pci_device_id sis5513_pci_tbl[] = { + { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 }, + { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 }, + { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl); + +static struct pci_driver sis5513_pci_driver = { + .name = "SIS_IDE", + .id_table = sis5513_pci_tbl, + .probe = sis5513_init_one, + .remove = __devexit_p(sis5513_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init sis5513_ide_init(void) +{ + return ide_pci_register_driver(&sis5513_pci_driver); +} + +static void __exit sis5513_ide_exit(void) +{ + pci_unregister_driver(&sis5513_pci_driver); +} + +module_init(sis5513_ide_init); +module_exit(sis5513_ide_exit); + +MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik"); +MODULE_DESCRIPTION("PCI driver module for SIS IDE"); +MODULE_LICENSE("GPL"); + +/* + * TODO: + * - CLEANUP + * - More checks in the config registers (force values instead of + * relying on the BIOS setting them correctly). + * - Further optimisations ? + * . for example ATA66+ regs 0x48 & 0x4A + */ diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c new file mode 100644 index 0000000..84dc336 --- /dev/null +++ b/drivers/ide/sl82c105.c @@ -0,0 +1,371 @@ +/* + * SL82C105/Winbond 553 IDE driver + * + * Maintainer unknown. + * + * Drive tuning added from Rebel.com's kernel sources + * -- Russell King (15/11/98) linux@arm.linux.org.uk + * + * Merge in Russell's HW workarounds, fix various problems + * with the timing registers setup. + * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org + * + * Copyright (C) 2006-2007 MontaVista Software, Inc. + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + */ + +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "sl82c105" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(arg) printk arg +#else +#define DBG(fmt,...) +#endif +/* + * SL82C105 PCI config register 0x40 bits. + */ +#define CTRL_IDE_IRQB (1 << 30) +#define CTRL_IDE_IRQA (1 << 28) +#define CTRL_LEGIRQ (1 << 11) +#define CTRL_P1F16 (1 << 5) +#define CTRL_P1EN (1 << 4) +#define CTRL_P0F16 (1 << 1) +#define CTRL_P0EN (1 << 0) + +/* + * Convert a PIO mode and cycle time to the required on/off times + * for the interface. This has protection against runaway timings. + */ +static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio) +{ + struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); + unsigned int cmd_on, cmd_off; + u8 iordy = 0; + + cmd_on = (t->active + 29) / 30; + cmd_off = (ide_pio_cycle_time(drive, pio) - 30 * cmd_on + 29) / 30; + + if (cmd_on == 0) + cmd_on = 1; + + if (cmd_off == 0) + cmd_off = 1; + + if (pio > 2 || ata_id_has_iordy(drive->id)) + iordy = 0x40; + + return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy; +} + +/* + * Configure the chipset for PIO mode. + */ +static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + int reg = 0x44 + drive->dn * 4; + u16 drv_ctrl; + + drv_ctrl = get_pio_timings(drive, pio); + + /* + * Store the PIO timings so that we can restore them + * in case DMA will be turned off... + */ + drive->drive_data &= 0xffff0000; + drive->drive_data |= drv_ctrl; + + pci_write_config_word(dev, reg, drv_ctrl); + pci_read_config_word (dev, reg, &drv_ctrl); + + printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name, + ide_xfer_verbose(pio + XFER_PIO_0), + ide_pio_cycle_time(drive, pio), drv_ctrl); +} + +/* + * Configure the chipset for DMA mode. + */ +static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200}; + u16 drv_ctrl; + + DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n", + drive->name, ide_xfer_verbose(speed))); + + drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0]; + + /* + * Store the DMA timings so that we can actually program + * them when DMA will be turned on... + */ + drive->drive_data &= 0x0000ffff; + drive->drive_data |= (unsigned long)drv_ctrl << 16; +} + +/* + * The SL82C105 holds off all IDE interrupts while in DMA mode until + * all DMA activity is completed. Sometimes this causes problems (eg, + * when the drive wants to report an error condition). + * + * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller + * state machine. We need to kick this to work around various bugs. + */ +static inline void sl82c105_reset_host(struct pci_dev *dev) +{ + u16 val; + + pci_read_config_word(dev, 0x7e, &val); + pci_write_config_word(dev, 0x7e, val | (1 << 2)); + pci_write_config_word(dev, 0x7e, val & ~(1 << 2)); +} + +/* + * If we get an IRQ timeout, it might be that the DMA state machine + * got confused. Fix from Todd Inglett. Details from Winbond. + * + * This function is called when the IDE timer expires, the drive + * indicates that it is READY, and we were waiting for DMA to complete. + */ +static void sl82c105_dma_lost_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; + u8 dma_cmd; + + printk("sl82c105: lost IRQ, resetting host\n"); + + /* + * Check the raw interrupt from the drive. + */ + pci_read_config_dword(dev, 0x40, &val); + if (val & mask) + printk("sl82c105: drive was requesting IRQ, but host lost it\n"); + + /* + * Was DMA enabled? If so, disable it - we're resetting the + * host. The IDE layer will be handling the drive for us. + */ + dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); + if (dma_cmd & 1) { + outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); + printk("sl82c105: DMA was enabled\n"); + } + + sl82c105_reset_host(dev); +} + +/* + * ATAPI devices can cause the SL82C105 DMA state machine to go gaga. + * Winbond recommend that the DMA state machine is reset prior to + * setting the bus master DMA enable bit. + * + * The generic IDE core will have disabled the BMEN bit before this + * function is called. + */ +static void sl82c105_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + int reg = 0x44 + drive->dn * 4; + + DBG(("%s(drive:%s)\n", __func__, drive->name)); + + pci_write_config_word(dev, reg, drive->drive_data >> 16); + + sl82c105_reset_host(dev); + ide_dma_start(drive); +} + +static void sl82c105_dma_timeout(ide_drive_t *drive) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + + DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name)); + + sl82c105_reset_host(dev); + ide_dma_timeout(drive); +} + +static int sl82c105_dma_end(ide_drive_t *drive) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + int reg = 0x44 + drive->dn * 4; + int ret; + + DBG(("%s(drive:%s)\n", __func__, drive->name)); + + ret = ide_dma_end(drive); + + pci_write_config_word(dev, reg, drive->drive_data); + + return ret; +} + +/* + * ATA reset will clear the 16 bits mode in the control + * register, we need to reprogram it + */ +static void sl82c105_resetproc(ide_drive_t *drive) +{ + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + u32 val; + + DBG(("sl82c105_resetproc(drive:%s)\n", drive->name)); + + pci_read_config_dword(dev, 0x40, &val); + val |= (CTRL_P1F16 | CTRL_P0F16); + pci_write_config_dword(dev, 0x40, val); +} + +/* + * Return the revision of the Winbond bridge + * which this function is part of. + */ +static u8 sl82c105_bridge_revision(struct pci_dev *dev) +{ + struct pci_dev *bridge; + + /* + * The bridge should be part of the same device, but function 0. + */ + bridge = pci_get_bus_and_slot(dev->bus->number, + PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); + if (!bridge) + return -1; + + /* + * Make sure it is a Winbond 553 and is an ISA bridge. + */ + if (bridge->vendor != PCI_VENDOR_ID_WINBOND || + bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || + bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) { + pci_dev_put(bridge); + return -1; + } + /* + * We need to find function 0's revision, not function 1 + */ + pci_dev_put(bridge); + + return bridge->revision; +} + +/* + * Enable the PCI device + * + * --BenH: It's arch fixup code that should enable channels that + * have not been enabled by firmware. I decided we can still enable + * channel 0 here at least, but channel 1 has to be enabled by + * firmware or arch code. We still set both to 16 bits mode. + */ +static unsigned int init_chipset_sl82c105(struct pci_dev *dev) +{ + u32 val; + + DBG(("init_chipset_sl82c105()\n")); + + pci_read_config_dword(dev, 0x40, &val); + val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; + pci_write_config_dword(dev, 0x40, val); + + return dev->irq; +} + +static const struct ide_port_ops sl82c105_port_ops = { + .set_pio_mode = sl82c105_set_pio_mode, + .set_dma_mode = sl82c105_set_dma_mode, + .resetproc = sl82c105_resetproc, +}; + +static const struct ide_dma_ops sl82c105_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = sl82c105_dma_start, + .dma_end = sl82c105_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = sl82c105_dma_lost_irq, + .dma_timeout = sl82c105_dma_timeout, +}; + +static const struct ide_port_info sl82c105_chipset __devinitdata = { + .name = DRV_NAME, + .init_chipset = init_chipset_sl82c105, + .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, + .port_ops = &sl82c105_port_ops, + .dma_ops = &sl82c105_dma_ops, + .host_flags = IDE_HFLAG_IO_32BIT | + IDE_HFLAG_UNMASK_IRQS | +/* FIXME: check for Compatibility mode in generic IDE PCI code */ +#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT) + IDE_HFLAG_FORCE_LEGACY_IRQS | +#endif + IDE_HFLAG_SERIALIZE_DMA | + IDE_HFLAG_NO_AUTODMA, + .pio_mask = ATA_PIO5, + .mwdma_mask = ATA_MWDMA2, +}; + +static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct ide_port_info d = sl82c105_chipset; + u8 rev = sl82c105_bridge_revision(dev); + + if (rev <= 5) { + /* + * Never ever EVER under any circumstances enable + * DMA when the bridge is this old. + */ + printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge " + "revision %d, BM-DMA disabled\n", rev); + d.dma_ops = NULL; + d.mwdma_mask = 0; + d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA; + } + + return ide_pci_init_one(dev, &d, NULL); +} + +static const struct pci_device_id sl82c105_pci_tbl[] = { + { PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl); + +static struct pci_driver sl82c105_pci_driver = { + .name = "W82C105_IDE", + .id_table = sl82c105_pci_tbl, + .probe = sl82c105_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init sl82c105_ide_init(void) +{ + return ide_pci_register_driver(&sl82c105_pci_driver); +} + +static void __exit sl82c105_ide_exit(void) +{ + pci_unregister_driver(&sl82c105_pci_driver); +} + +module_init(sl82c105_ide_init); +module_exit(sl82c105_ide_exit); + +MODULE_DESCRIPTION("PCI driver module for W82C105 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c new file mode 100644 index 0000000..0f759e4 --- /dev/null +++ b/drivers/ide/slc90e66.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2000-2002 Andre Hedrick + * Copyright (C) 2006-2007 MontaVista Software, Inc. + * + * This is a look-alike variation of the ICH0 PIIX4 Ultra-66, + * but this keeps the ISA-Bridge and slots alive. + * + */ + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "slc90e66" + +static DEFINE_SPINLOCK(slc90e66_lock); + +static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + int is_slave = drive->dn & 1; + int master_port = hwif->channel ? 0x42 : 0x40; + int slave_port = 0x44; + unsigned long flags; + u16 master_data; + u8 slave_data; + int control = 0; + /* ISP RTC */ + static const u8 timings[][2] = { + { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + spin_lock_irqsave(&slc90e66_lock, flags); + pci_read_config_word(dev, master_port, &master_data); + + if (pio > 1) + control |= 1; /* Programmable timing on */ + if (drive->media == ide_disk) + control |= 4; /* Prefetch, post write */ + if (pio > 2) + control |= 2; /* IORDY */ + if (is_slave) { + master_data |= 0x4000; + master_data &= ~0x0070; + if (pio > 1) { + /* Set PPE, IE and TIME */ + master_data |= control << 4; + } + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data &= hwif->channel ? 0x0f : 0xf0; + slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << + (hwif->channel ? 4 : 0); + } else { + master_data &= ~0x3307; + if (pio > 1) { + /* enable PPE, IE and TIME */ + master_data |= control; + } + master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); + } + pci_write_config_word(dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(dev, slave_port, slave_data); + spin_unlock_irqrestore(&slc90e66_lock, flags); +} + +static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 maslave = hwif->channel ? 0x42 : 0x40; + int sitre = 0, a_speed = 7 << (drive->dn * 4); + int u_speed = 0, u_flag = 1 << drive->dn; + u16 reg4042, reg44, reg48, reg4a; + + pci_read_config_word(dev, maslave, ®4042); + sitre = (reg4042 & 0x4000) ? 1 : 0; + pci_read_config_word(dev, 0x44, ®44); + pci_read_config_word(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + + if (speed >= XFER_UDMA_0) { + u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4); + + if (!(reg48 & u_flag)) + pci_write_config_word(dev, 0x48, reg48|u_flag); + /* FIXME: (reg4a & a_speed) ? */ + if ((reg4a & u_speed) != u_speed) { + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + pci_read_config_word(dev, 0x4a, ®4a); + pci_write_config_word(dev, 0x4a, reg4a|u_speed); + } + } else { + const u8 mwdma_to_pio[] = { 0, 3, 4 }; + u8 pio; + + if (reg48 & u_flag) + pci_write_config_word(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + + if (speed >= XFER_MW_DMA_0) + pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; + else + pio = 2; /* only SWDMA2 is allowed */ + + slc90e66_set_pio_mode(drive, pio); + } +} + +static u8 slc90e66_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02; + + pci_read_config_byte(dev, 0x47, ®47); + + /* bit[0(1)]: 0:80, 1:40 */ + return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + +static const struct ide_port_ops slc90e66_port_ops = { + .set_pio_mode = slc90e66_set_pio_mode, + .set_dma_mode = slc90e66_set_dma_mode, + .cable_detect = slc90e66_cable_detect, +}; + +static const struct ide_port_info slc90e66_chipset __devinitdata = { + .name = DRV_NAME, + .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} }, + .port_ops = &slc90e66_port_ops, + .host_flags = IDE_HFLAG_LEGACY_IRQS, + .pio_mask = ATA_PIO4, + .swdma_mask = ATA_SWDMA2_ONLY, + .mwdma_mask = ATA_MWDMA12_ONLY, + .udma_mask = ATA_UDMA4, +}; + +static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + return ide_pci_init_one(dev, &slc90e66_chipset, NULL); +} + +static const struct pci_device_id slc90e66_pci_tbl[] = { + { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl); + +static struct pci_driver slc90e66_pci_driver = { + .name = "SLC90e66_IDE", + .id_table = slc90e66_pci_tbl, + .probe = slc90e66_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init slc90e66_ide_init(void) +{ + return ide_pci_register_driver(&slc90e66_pci_driver); +} + +static void __exit slc90e66_ide_exit(void) +{ + pci_unregister_driver(&slc90e66_pci_driver); +} + +module_init(slc90e66_ide_init); +module_exit(slc90e66_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c new file mode 100644 index 0000000..93e2cce --- /dev/null +++ b/drivers/ide/tc86c001.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2002 Toshiba Corporation + * Copyright (C) 2005-2006 MontaVista Software, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include + +#define DRV_NAME "tc86c001" + +static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00); + u16 mode, scr = inw(scr_port); + + switch (speed) { + case XFER_UDMA_4: mode = 0x00c0; break; + case XFER_UDMA_3: mode = 0x00b0; break; + case XFER_UDMA_2: mode = 0x00a0; break; + case XFER_UDMA_1: mode = 0x0090; break; + case XFER_UDMA_0: mode = 0x0080; break; + case XFER_MW_DMA_2: mode = 0x0070; break; + case XFER_MW_DMA_1: mode = 0x0060; break; + case XFER_MW_DMA_0: mode = 0x0050; break; + case XFER_PIO_4: mode = 0x0400; break; + case XFER_PIO_3: mode = 0x0300; break; + case XFER_PIO_2: mode = 0x0200; break; + case XFER_PIO_1: mode = 0x0100; break; + case XFER_PIO_0: + default: mode = 0x0000; break; + } + + scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f; + scr |= mode; + outw(scr, scr_port); +} + +static void tc86c001_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + tc86c001_set_mode(drive, XFER_PIO_0 + pio); +} + +/* + * HACKITY HACK + * + * This is a workaround for the limitation 5 of the TC86C001 IDE controller: + * if a DMA transfer terminates prematurely, the controller leaves the device's + * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or + * set the interrupt bit in the DMA status register), thus no PCI interrupt + * will occur until a DMA transfer has been successfully completed. + * + * We work around this by initiating dummy, zero-length DMA transfer on + * a DMA timeout expiration. I found no better way to do this with the current + * IDE core than to temporarily replace a higher level driver's timer expiry + * handler with our own backing up to that handler in case our recovery fails. + */ +static int tc86c001_timer_expiry(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + ide_expiry_t *expiry = ide_get_hwifdata(hwif); + ide_hwgroup_t *hwgroup = HWGROUP(drive); + u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + + /* Restore a higher level driver's expiry handler first. */ + hwgroup->expiry = expiry; + + if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */ + unsigned long sc_base = hwif->config_data; + unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); + u8 dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); + + printk(KERN_WARNING "%s: DMA interrupt possibly stuck, " + "attempting recovery...\n", drive->name); + + /* Stop DMA */ + outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD); + + /* Setup the dummy DMA transfer */ + outw(0, sc_base + 0x0a); /* Sector Count */ + outw(0, twcr_port); /* Transfer Word Count 1 or 2 */ + + /* Start the dummy DMA transfer */ + + /* clear R_OR_WCTR for write */ + outb(0x00, hwif->dma_base + ATA_DMA_CMD); + /* set START_STOPBM */ + outb(0x01, hwif->dma_base + ATA_DMA_CMD); + + /* + * If an interrupt was pending, it should come thru shortly. + * If not, a higher level driver's expiry handler should + * eventually cause some kind of recovery from the DMA stall. + */ + return WAIT_MIN_SLEEP; + } + + /* Chain to the restored expiry handler if DMA wasn't active. */ + if (likely(expiry != NULL)) + return expiry(drive); + + /* If there was no handler, "emulate" that for ide_timer_expiry()... */ + return -1; +} + +static void tc86c001_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + ide_hwgroup_t *hwgroup = HWGROUP(drive); + unsigned long sc_base = hwif->config_data; + unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); + unsigned long nsectors = hwgroup->rq->nr_sectors; + + /* + * We have to manually load the sector count and size into + * the appropriate system control registers for DMA to work + * with LBA48 and ATAPI devices... + */ + outw(nsectors, sc_base + 0x0a); /* Sector Count */ + outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */ + + /* Install our timeout expiry hook, saving the current handler... */ + ide_set_hwifdata(hwif, hwgroup->expiry); + hwgroup->expiry = &tc86c001_timer_expiry; + + ide_dma_start(drive); +} + +static u8 tc86c001_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long sc_base = pci_resource_start(dev, 5); + u16 scr1 = inw(sc_base + 0x00); + + /* + * System Control 1 Register bit 13 (PDIAGN): + * 0=80-pin cable, 1=40-pin cable + */ + return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; +} + +static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long sc_base = pci_resource_start(dev, 5); + u16 scr1 = inw(sc_base + 0x00); + + /* System Control 1 Register bit 15 (Soft Reset) set */ + outw(scr1 | 0x8000, sc_base + 0x00); + + /* System Control 1 Register bit 14 (FIFO Reset) set */ + outw(scr1 | 0x4000, sc_base + 0x00); + + /* System Control 1 Register: reset clear */ + outw(scr1 & ~0xc000, sc_base + 0x00); + + /* Store the system control register base for convenience... */ + hwif->config_data = sc_base; + + if (!hwif->dma_base) + return; + + /* + * Sector Count Control Register bits 0 and 1 set: + * software sets Sector Count Register for master and slave device + */ + outw(0x0003, sc_base + 0x0c); + + /* Sector Count Register limit */ + hwif->rqsize = 0xffff; +} + +static const struct ide_port_ops tc86c001_port_ops = { + .set_pio_mode = tc86c001_set_pio_mode, + .set_dma_mode = tc86c001_set_mode, + .cable_detect = tc86c001_cable_detect, +}; + +static const struct ide_dma_ops tc86c001_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = tc86c001_dma_start, + .dma_end = ide_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info tc86c001_chipset __devinitdata = { + .name = DRV_NAME, + .init_hwif = init_hwif_tc86c001, + .port_ops = &tc86c001_port_ops, + .dma_ops = &tc86c001_dma_ops, + .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, +}; + +static int __devinit tc86c001_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + int rc; + + rc = pci_enable_device(dev); + if (rc) + goto out; + + rc = pci_request_region(dev, 5, DRV_NAME); + if (rc) { + printk(KERN_ERR DRV_NAME ": system control regs already in use"); + goto out_disable; + } + + rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL); + if (rc) + goto out_release; + + goto out; + +out_release: + pci_release_region(dev, 5); +out_disable: + pci_disable_device(dev); +out: + return rc; +} + +static void __devexit tc86c001_remove(struct pci_dev *dev) +{ + ide_pci_remove(dev); + pci_release_region(dev, 5); + pci_disable_device(dev); +} + +static const struct pci_device_id tc86c001_pci_tbl[] = { + { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl); + +static struct pci_driver tc86c001_pci_driver = { + .name = "TC86C001", + .id_table = tc86c001_pci_tbl, + .probe = tc86c001_init_one, + .remove = __devexit_p(tc86c001_remove), +}; + +static int __init tc86c001_ide_init(void) +{ + return ide_pci_register_driver(&tc86c001_pci_driver); +} + +static void __exit tc86c001_ide_exit(void) +{ + pci_unregister_driver(&tc86c001_pci_driver); +} + +module_init(tc86c001_ide_init); +module_exit(tc86c001_ide_exit); + +MODULE_AUTHOR("MontaVista Software, Inc. "); +MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/triflex.c b/drivers/ide/triflex.c new file mode 100644 index 0000000..b6ff403 --- /dev/null +++ b/drivers/ide/triflex.c @@ -0,0 +1,142 @@ +/* + * IDE Chipset driver for the Compaq TriFlex IDE controller. + * + * Known to work with the Compaq Workstation 5x00 series. + * + * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. + * Author: Torben Mathiasen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Loosely based on the piix & svwks drivers. + * + * Documentation: + * Not publically available. + */ + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "triflex" + +static void triflex_set_mode(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + u32 triflex_timings = 0; + u16 timing = 0; + u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1; + + pci_read_config_dword(dev, channel_offset, &triflex_timings); + + switch(speed) { + case XFER_MW_DMA_2: + timing = 0x0103; + break; + case XFER_MW_DMA_1: + timing = 0x0203; + break; + case XFER_MW_DMA_0: + timing = 0x0808; + break; + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + timing = 0x0f0f; + break; + case XFER_PIO_4: + timing = 0x0202; + break; + case XFER_PIO_3: + timing = 0x0204; + break; + case XFER_PIO_2: + timing = 0x0404; + break; + case XFER_PIO_1: + timing = 0x0508; + break; + case XFER_PIO_0: + timing = 0x0808; + break; + } + + triflex_timings &= ~(0xFFFF << (16 * unit)); + triflex_timings |= (timing << (16 * unit)); + + pci_write_config_dword(dev, channel_offset, triflex_timings); +} + +static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + triflex_set_mode(drive, XFER_PIO_0 + pio); +} + +static const struct ide_port_ops triflex_port_ops = { + .set_pio_mode = triflex_set_pio_mode, + .set_dma_mode = triflex_set_mode, +}; + +static const struct ide_port_info triflex_device __devinitdata = { + .name = DRV_NAME, + .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, + .port_ops = &triflex_port_ops, + .pio_mask = ATA_PIO4, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, +}; + +static int __devinit triflex_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return ide_pci_init_one(dev, &triflex_device, NULL); +} + +static const struct pci_device_id triflex_pci_tbl[] = { + { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, triflex_pci_tbl); + +static struct pci_driver triflex_pci_driver = { + .name = "TRIFLEX_IDE", + .id_table = triflex_pci_tbl, + .probe = triflex_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init triflex_ide_init(void) +{ + return ide_pci_register_driver(&triflex_pci_driver); +} + +static void __exit triflex_ide_exit(void) +{ + pci_unregister_driver(&triflex_pci_driver); +} + +module_init(triflex_ide_init); +module_exit(triflex_ide_exit); + +MODULE_AUTHOR("Torben Mathiasen"); +MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE"); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c new file mode 100644 index 0000000..75ea615 --- /dev/null +++ b/drivers/ide/trm290.c @@ -0,0 +1,375 @@ +/* + * Copyright (c) 1997-1998 Mark Lord + * Copyright (c) 2007 MontaVista Software, Inc. + * + * May be copied or modified under the terms of the GNU General Public License + * + * June 22, 2004 - get rid of check_region + * - Jesper Juhl + * + */ + +/* + * This module provides support for the bus-master IDE DMA function + * of the Tekram TRM290 chip, used on a variety of PCI IDE add-on boards, + * including a "Precision Instruments" board. The TRM290 pre-dates + * the sff-8038 standard (ide-dma.c) by a few months, and differs + * significantly enough to warrant separate routines for some functions, + * while re-using others from ide-dma.c. + * + * EXPERIMENTAL! It works for me (a sample of one). + * + * Works reliably for me in DMA mode (READs only), + * DMA WRITEs are disabled by default (see #define below); + * + * DMA is not enabled automatically for this chipset, + * but can be turned on manually (with "hdparm -d1") at run time. + * + * I need volunteers with "spare" drives for further testing + * and development, and maybe to help figure out the peculiarities. + * Even knowing the registers (below), some things behave strangely. + */ + +#define TRM290_NO_DMA_WRITES /* DMA writes seem unreliable sometimes */ + +/* + * TRM-290 PCI-IDE2 Bus Master Chip + * ================================ + * The configuration registers are addressed in normal I/O port space + * and are used as follows: + * + * trm290_base depends on jumper settings, and is probed for by ide-dma.c + * + * trm290_base+2 when WRITTEN: chiptest register (byte, write-only) + * bit7 must always be written as "1" + * bits6-2 undefined + * bit1 1=legacy_compatible_mode, 0=native_pci_mode + * bit0 1=test_mode, 0=normal(default) + * + * trm290_base+2 when READ: status register (byte, read-only) + * bits7-2 undefined + * bit1 channel0 busmaster interrupt status 0=none, 1=asserted + * bit0 channel0 interrupt status 0=none, 1=asserted + * + * trm290_base+3 Interrupt mask register + * bits7-5 undefined + * bit4 legacy_header: 1=present, 0=absent + * bit3 channel1 busmaster interrupt status 0=none, 1=asserted (read only) + * bit2 channel1 interrupt status 0=none, 1=asserted (read only) + * bit1 channel1 interrupt mask: 1=masked, 0=unmasked(default) + * bit0 channel0 interrupt mask: 1=masked, 0=unmasked(default) + * + * trm290_base+1 "CPR" Config Pointer Register (byte) + * bit7 1=autoincrement CPR bits 2-0 after each access of CDR + * bit6 1=min. 1 wait-state posted write cycle (default), 0=0 wait-state + * bit5 0=enabled master burst access (default), 1=disable (write only) + * bit4 PCI DEVSEL# timing select: 1=medium(default), 0=fast + * bit3 0=primary IDE channel, 1=secondary IDE channel + * bits2-0 register index for accesses through CDR port + * + * trm290_base+0 "CDR" Config Data Register (word) + * two sets of seven config registers, + * selected by CPR bit 3 (channel) and CPR bits 2-0 (index 0 to 6), + * each index defined below: + * + * Index-0 Base address register for command block (word) + * defaults: 0x1f0 for primary, 0x170 for secondary + * + * Index-1 general config register (byte) + * bit7 1=DMA enable, 0=DMA disable + * bit6 1=activate IDE_RESET, 0=no action (default) + * bit5 1=enable IORDY, 0=disable IORDY (default) + * bit4 0=16-bit data port(default), 1=8-bit (XT) data port + * bit3 interrupt polarity: 1=active_low, 0=active_high(default) + * bit2 power-saving-mode(?): 1=enable, 0=disable(default) (write only) + * bit1 bus_master_mode(?): 1=enable, 0=disable(default) + * bit0 enable_io_ports: 1=enable(default), 0=disable + * + * Index-2 read-ahead counter preload bits 0-7 (byte, write only) + * bits7-0 bits7-0 of readahead count + * + * Index-3 read-ahead config register (byte, write only) + * bit7 1=enable_readahead, 0=disable_readahead(default) + * bit6 1=clear_FIFO, 0=no_action + * bit5 undefined + * bit4 mode4 timing control: 1=enable, 0=disable(default) + * bit3 undefined + * bit2 undefined + * bits1-0 bits9-8 of read-ahead count + * + * Index-4 base address register for control block (word) + * defaults: 0x3f6 for primary, 0x376 for secondary + * + * Index-5 data port timings (shared by both drives) (byte) + * standard PCI "clk" (clock) counts, default value = 0xf5 + * + * bits7-6 setup time: 00=1clk, 01=2clk, 10=3clk, 11=4clk + * bits5-3 hold time: 000=1clk, 001=2clk, 010=3clk, + * 011=4clk, 100=5clk, 101=6clk, + * 110=8clk, 111=12clk + * bits2-0 active time: 000=2clk, 001=3clk, 010=4clk, + * 011=5clk, 100=6clk, 101=8clk, + * 110=12clk, 111=16clk + * + * Index-6 command/control port timings (shared by both drives) (byte) + * same layout as Index-5, default value = 0xde + * + * Suggested CDR programming for PIO mode0 (600ns): + * 0x01f0,0x21,0xff,0x80,0x03f6,0xf5,0xde ; primary + * 0x0170,0x21,0xff,0x80,0x0376,0xf5,0xde ; secondary + * + * Suggested CDR programming for PIO mode3 (180ns): + * 0x01f0,0x21,0xff,0x80,0x03f6,0x09,0xde ; primary + * 0x0170,0x21,0xff,0x80,0x0376,0x09,0xde ; secondary + * + * Suggested CDR programming for PIO mode4 (120ns): + * 0x01f0,0x21,0xff,0x80,0x03f6,0x00,0xde ; primary + * 0x0170,0x21,0xff,0x80,0x0376,0x00,0xde ; secondary + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "trm290" + +static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma) +{ + ide_hwif_t *hwif = HWIF(drive); + u16 reg = 0; + unsigned long flags; + + /* select PIO or DMA */ + reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82); + + local_irq_save(flags); + + if (reg != hwif->select_data) { + hwif->select_data = reg; + /* set PIO/DMA */ + outb(0x51 | (hwif->channel << 3), hwif->config_data + 1); + outw(reg & 0xff, hwif->config_data); + } + + /* enable IRQ if not probing */ + if (drive->dev_flags & IDE_DFLAG_PRESENT) { + reg = inw(hwif->config_data + 3); + reg &= 0x13; + reg &= ~(1 << hwif->channel); + outw(reg, hwif->config_data + 3); + } + + local_irq_restore(flags); +} + +static void trm290_selectproc (ide_drive_t *drive) +{ + trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA)); +} + +static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command) +{ + ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL); +} + +static int trm290_dma_setup(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct request *rq = hwif->hwgroup->rq; + unsigned int count, rw; + + if (rq_data_dir(rq)) { +#ifdef TRM290_NO_DMA_WRITES + /* always use PIO for writes */ + trm290_prepare_drive(drive, 0); /* select PIO xfer */ + return 1; +#endif + rw = 1; + } else + rw = 2; + + if (!(count = ide_build_dmatable(drive, rq))) { + /* try PIO instead of DMA */ + trm290_prepare_drive(drive, 0); /* select PIO xfer */ + return 1; + } + /* select DMA xfer */ + trm290_prepare_drive(drive, 1); + outl(hwif->dmatable_dma | rw, hwif->dma_base); + drive->waiting_for_dma = 1; + /* start DMA */ + outw(count * 2 - 1, hwif->dma_base + 2); + return 0; +} + +static void trm290_dma_start(ide_drive_t *drive) +{ +} + +static int trm290_dma_end(ide_drive_t *drive) +{ + u16 status; + + drive->waiting_for_dma = 0; + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + status = inw(HWIF(drive)->dma_base + 2); + return status != 0x00ff; +} + +static int trm290_dma_test_irq(ide_drive_t *drive) +{ + u16 status; + + status = inw(HWIF(drive)->dma_base + 2); + return status == 0x00ff; +} + +static void trm290_dma_host_set(ide_drive_t *drive, int on) +{ +} + +static void __devinit init_hwif_trm290(ide_hwif_t *hwif) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned int cfg_base = pci_resource_start(dev, 4); + unsigned long flags; + u8 reg = 0; + + if ((dev->class & 5) && cfg_base) + printk(KERN_INFO DRV_NAME " %s: chip", pci_name(dev)); + else { + cfg_base = 0x3df0; + printk(KERN_INFO DRV_NAME " %s: using default", pci_name(dev)); + } + printk(KERN_CONT " config base at 0x%04x\n", cfg_base); + hwif->config_data = cfg_base; + hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0); + + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", + hwif->name, hwif->dma_base, hwif->dma_base + 3); + + if (ide_allocate_dma_engine(hwif)) + return; + + local_irq_save(flags); + /* put config reg into first byte of hwif->select_data */ + outb(0x51 | (hwif->channel << 3), hwif->config_data + 1); + /* select PIO as default */ + hwif->select_data = 0x21; + outb(hwif->select_data, hwif->config_data); + /* get IRQ info */ + reg = inb(hwif->config_data + 3); + /* mask IRQs for both ports */ + reg = (reg & 0x10) | 0x03; + outb(reg, hwif->config_data + 3); + local_irq_restore(flags); + + if (reg & 0x10) + /* legacy mode */ + hwif->irq = hwif->channel ? 15 : 14; + else if (!hwif->irq && hwif->mate && hwif->mate->irq) + /* sharing IRQ with mate */ + hwif->irq = hwif->mate->irq; + +#if 1 + { + /* + * My trm290-based card doesn't seem to work with all possible values + * for the control basereg, so this kludge ensures that we use only + * values that are known to work. Ugh. -ml + */ + u16 new, old, compat = hwif->channel ? 0x374 : 0x3f4; + static u16 next_offset = 0; + u8 old_mask; + + outb(0x54 | (hwif->channel << 3), hwif->config_data + 1); + old = inw(hwif->config_data); + old &= ~1; + old_mask = inb(old + 2); + if (old != compat && old_mask == 0xff) { + /* leave lower 10 bits untouched */ + compat += (next_offset += 0x400); + hwif->io_ports.ctl_addr = compat + 2; + outw(compat | 1, hwif->config_data); + new = inw(hwif->config_data); + printk(KERN_INFO "%s: control basereg workaround: " + "old=0x%04x, new=0x%04x\n", + hwif->name, old, new & ~1); + } + } +#endif +} + +static const struct ide_port_ops trm290_port_ops = { + .selectproc = trm290_selectproc, +}; + +static struct ide_dma_ops trm290_dma_ops = { + .dma_host_set = trm290_dma_host_set, + .dma_setup = trm290_dma_setup, + .dma_exec_cmd = trm290_dma_exec_cmd, + .dma_start = trm290_dma_start, + .dma_end = trm290_dma_end, + .dma_test_irq = trm290_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info trm290_chipset __devinitdata = { + .name = DRV_NAME, + .init_hwif = init_hwif_trm290, + .chipset = ide_trm290, + .port_ops = &trm290_port_ops, + .dma_ops = &trm290_dma_ops, + .host_flags = IDE_HFLAG_NO_ATAPI_DMA | +#if 0 /* play it safe for now */ + IDE_HFLAG_TRUST_BIOS_FOR_DMA | +#endif + IDE_HFLAG_NO_AUTODMA | + IDE_HFLAG_NO_LBA48, +}; + +static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + return ide_pci_init_one(dev, &trm290_chipset, NULL); +} + +static const struct pci_device_id trm290_pci_tbl[] = { + { PCI_VDEVICE(TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290), 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, trm290_pci_tbl); + +static struct pci_driver trm290_pci_driver = { + .name = "TRM290_IDE", + .id_table = trm290_pci_tbl, + .probe = trm290_init_one, + .remove = ide_pci_remove, +}; + +static int __init trm290_ide_init(void) +{ + return ide_pci_register_driver(&trm290_pci_driver); +} + +static void __exit trm290_ide_exit(void) +{ + pci_unregister_driver(&trm290_pci_driver); +} + +module_init(trm290_ide_init); +module_exit(trm290_ide_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c new file mode 100644 index 0000000..1da076e --- /dev/null +++ b/drivers/ide/umc8672.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 1995-1996 Linus Torvalds & author (see below) + */ + +/* + * Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien) + * + * This file provides support for the advanced features + * of the UMC 8672 IDE interface. + * + * Version 0.01 Initial version, hacked out of ide.c, + * and #include'd rather than compiled separately. + * This will get cleaned up in a subsequent release. + * + * Version 0.02 now configs/compiles separate from ide.c -ml + * Version 0.03 enhanced auto-tune, fix display bug + * Version 0.05 replace sti() with restore_flags() -ml + * add detection of possible race condition -ml + */ + +/* + * VLB Controller Support from + * Wolfram Podien + * Rohoefe 3 + * D28832 Achim + * Germany + * + * To enable UMC8672 support there must a lilo line like + * append="ide0=umc8672"... + * To set the speed according to the abilities of the hardware there must be a + * line like + * #define UMC_DRIVE0 11 + * in the beginning of the driver, which sets the speed of drive 0 to 11 (there + * are some lines present). 0 - 11 are allowed speed values. These values are + * the results from the DOS speed test program supplied from UMC. 11 is the + * highest speed (about PIO mode 3) + */ +#define REALLY_SLOW_IO /* some systems can safely undef this */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "umc8672" + +/* + * Default speeds. These can be changed with "auto-tune" and/or hdparm. + */ +#define UMC_DRIVE0 1 /* DOS measured drive speeds */ +#define UMC_DRIVE1 1 /* 0 to 11 allowed */ +#define UMC_DRIVE2 1 /* 11 = Fastest Speed */ +#define UMC_DRIVE3 1 /* In case of crash reduce speed */ + +static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; +static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11}; /* rough guesses */ + +/* 0 1 2 3 4 5 6 7 8 9 10 11 */ +static const u8 speedtab [3][12] = { + {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1}, + {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1}, + {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0} +}; + +static void out_umc(char port, char wert) +{ + outb_p(port, 0x108); + outb_p(wert, 0x109); +} + +static inline u8 in_umc(char port) +{ + outb_p(port, 0x108); + return inb_p(0x109); +} + +static void umc_set_speeds(u8 speeds[]) +{ + int i, tmp; + + outb_p(0x5A, 0x108); /* enable umc */ + + out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); + out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); + tmp = 0; + for (i = 3; i >= 0; i--) + tmp = (tmp << 2) | speedtab[1][speeds[i]]; + out_umc(0xdc, tmp); + for (i = 0; i < 4; i++) { + out_umc(0xd0 + i, speedtab[2][speeds[i]]); + out_umc(0xd8 + i, speedtab[2][speeds[i]]); + } + outb_p(0xa5, 0x108); /* disable umc */ + + printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", + speeds[0], speeds[1], speeds[2], speeds[3]); +} + +static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + ide_hwif_t *hwif = drive->hwif; + unsigned long flags; + + printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", + drive->name, pio, pio_to_umc[pio]); + spin_lock_irqsave(&ide_lock, flags); + if (hwif->mate && hwif->mate->hwgroup->handler) { + printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); + } else { + current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; + umc_set_speeds(current_speeds); + } + spin_unlock_irqrestore(&ide_lock, flags); +} + +static const struct ide_port_ops umc8672_port_ops = { + .set_pio_mode = umc_set_pio_mode, +}; + +static const struct ide_port_info umc8672_port_info __initdata = { + .name = DRV_NAME, + .chipset = ide_umc8672, + .port_ops = &umc8672_port_ops, + .host_flags = IDE_HFLAG_NO_DMA, + .pio_mask = ATA_PIO4, +}; + +static int __init umc8672_probe(void) +{ + unsigned long flags; + + if (!request_region(0x108, 2, "umc8672")) { + printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n"); + return 1; + } + local_irq_save(flags); + outb_p(0x5A, 0x108); /* enable umc */ + if (in_umc (0xd5) != 0xa0) { + local_irq_restore(flags); + printk(KERN_ERR "umc8672: not found\n"); + release_region(0x108, 2); + return 1; + } + outb_p(0xa5, 0x108); /* disable umc */ + + umc_set_speeds(current_speeds); + local_irq_restore(flags); + + return ide_legacy_device_add(&umc8672_port_info, 0); +} + +static int probe_umc8672; + +module_param_named(probe, probe_umc8672, bool, 0); +MODULE_PARM_DESC(probe, "probe for UMC8672 chipset"); + +static int __init umc8672_init(void) +{ + if (probe_umc8672 == 0) + goto out; + + if (umc8672_probe() == 0) + return 0;; +out: + return -ENODEV;; +} + +module_init(umc8672_init); + +MODULE_AUTHOR("Wolfram Podien"); +MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c new file mode 100644 index 0000000..2a812d3 --- /dev/null +++ b/drivers/ide/via82cxxx.c @@ -0,0 +1,514 @@ +/* + * VIA IDE driver for Linux. Supported southbridges: + * + * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, + * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, + * vt8235, vt8237, vt8237a + * + * Copyright (c) 2000-2002 Vojtech Pavlik + * Copyright (c) 2007 Bartlomiej Zolnierkiewicz + * + * Based on the work of: + * Michel Aubry + * Jeff Garzik + * Andre Hedrick + * + * Documentation: + * Obsolete device documentation publically available from via.com.tw + * Current device documentation available under NDA only + */ + +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PPC_CHRP +#include +#endif + +#define DRV_NAME "via82cxxx" + +#define VIA_IDE_ENABLE 0x40 +#define VIA_IDE_CONFIG 0x41 +#define VIA_FIFO_CONFIG 0x43 +#define VIA_MISC_1 0x44 +#define VIA_MISC_2 0x45 +#define VIA_MISC_3 0x46 +#define VIA_DRIVE_TIMING 0x48 +#define VIA_8BIT_TIMING 0x4e +#define VIA_ADDRESS_SETUP 0x4c +#define VIA_UDMA_TIMING 0x50 + +#define VIA_BAD_PREQ 0x01 /* Crashes if PREQ# till DDACK# set */ +#define VIA_BAD_CLK66 0x02 /* 66 MHz clock doesn't work correctly */ +#define VIA_SET_FIFO 0x04 /* Needs to have FIFO split set */ +#define VIA_NO_UNMASK 0x08 /* Doesn't work with IRQ unmasking on */ +#define VIA_BAD_ID 0x10 /* Has wrong vendor ID (0x1107) */ +#define VIA_BAD_AST 0x20 /* Don't touch Address Setup Timing */ + +/* + * VIA SouthBridge chips. + */ + +static struct via_isa_bridge { + char *name; + u16 id; + u8 rev_min; + u8 rev_max; + u8 udma_mask; + u8 flags; +} via_isa_bridges[] = { + { "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, + { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, ATA_UDMA5, }, + { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, ATA_UDMA5, }, + { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, ATA_UDMA5, }, + { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, ATA_UDMA5, }, + { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, ATA_UDMA4, }, + { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 }, + { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, ATA_UDMA4, }, + { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO }, + { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO }, + { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, 0x00, VIA_SET_FIFO }, + { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK }, + { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, + { NULL } +}; + +static unsigned int via_clock; +static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" }; + +struct via82cxxx_dev +{ + struct via_isa_bridge *via_config; + unsigned int via_80w; +}; + +/** + * via_set_speed - write timing registers + * @dev: PCI device + * @dn: device + * @timing: IDE timing data to use + * + * via_set_speed writes timing values to the chipset registers + */ + +static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_host *host = pci_get_drvdata(dev); + struct via82cxxx_dev *vdev = host->host_priv; + u8 t; + + if (~vdev->via_config->flags & VIA_BAD_AST) { + pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); + t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); + pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); + } + + pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)), + ((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1)); + + pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn), + ((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1)); + + switch (vdev->via_config->udma_mask) { + case ATA_UDMA2: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break; + case ATA_UDMA4: t = timing->udma ? (0xe8 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x0f; break; + case ATA_UDMA5: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break; + case ATA_UDMA6: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break; + default: return; + } + + pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t); +} + +/** + * via_set_drive - configure transfer mode + * @drive: Drive to set up + * @speed: desired speed + * + * via_set_drive() computes timing values configures the chipset to + * a desired transfer mode. It also can be called by upper layers. + */ + +static void via_set_drive(ide_drive_t *drive, const u8 speed) +{ + ide_hwif_t *hwif = drive->hwif; + ide_drive_t *peer = ide_get_pair_dev(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct ide_host *host = pci_get_drvdata(dev); + struct via82cxxx_dev *vdev = host->host_priv; + struct ide_timing t, p; + unsigned int T, UT; + + T = 1000000000 / via_clock; + + switch (vdev->via_config->udma_mask) { + case ATA_UDMA2: UT = T; break; + case ATA_UDMA4: UT = T/2; break; + case ATA_UDMA5: UT = T/3; break; + case ATA_UDMA6: UT = T/4; break; + default: UT = T; + } + + ide_timing_compute(drive, speed, &t, T, UT); + + if (peer) { + ide_timing_compute(peer, peer->current_speed, &p, T, UT); + ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); + } + + via_set_speed(HWIF(drive), drive->dn, &t); +} + +/** + * via_set_pio_mode - set host controller for PIO mode + * @drive: drive + * @pio: PIO mode number + * + * A callback from the upper layers for PIO-only tuning. + */ + +static void via_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + via_set_drive(drive, XFER_PIO_0 + pio); +} + +static struct via_isa_bridge *via_config_find(struct pci_dev **isa) +{ + struct via_isa_bridge *via_config; + + for (via_config = via_isa_bridges; via_config->id; via_config++) + if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA + + !!(via_config->flags & VIA_BAD_ID), + via_config->id, NULL))) { + + if ((*isa)->revision >= via_config->rev_min && + (*isa)->revision <= via_config->rev_max) + break; + pci_dev_put(*isa); + } + + return via_config; +} + +/* + * Check and handle 80-wire cable presence + */ +static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u) +{ + int i; + + switch (vdev->via_config->udma_mask) { + case ATA_UDMA4: + for (i = 24; i >= 0; i -= 8) + if (((u >> (i & 16)) & 8) && + ((u >> i) & 0x20) && + (((u >> i) & 7) < 2)) { + /* + * 2x PCI clock and + * UDMA w/ < 3T/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; + + case ATA_UDMA5: + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 0x10) || + (((u >> i) & 0x20) && + (((u >> i) & 7) < 4))) { + /* BIOS 80-wire bit or + * UDMA w/ < 60ns/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; + + case ATA_UDMA6: + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 0x10) || + (((u >> i) & 0x20) && + (((u >> i) & 7) < 6))) { + /* BIOS 80-wire bit or + * UDMA w/ < 60ns/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; + } +} + +/** + * init_chipset_via82cxxx - initialization handler + * @dev: PCI device + * + * The initialization callback. Here we determine the IDE chip type + * and initialize its drive independent registers. + */ + +static unsigned int init_chipset_via82cxxx(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct via82cxxx_dev *vdev = host->host_priv; + struct via_isa_bridge *via_config = vdev->via_config; + u8 t, v; + u32 u; + + /* + * Detect cable and configure Clk66 + */ + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + + via_cable_detect(vdev, u); + + if (via_config->udma_mask == ATA_UDMA4) { + /* Enable Clk66 */ + pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008); + } else if (via_config->flags & VIA_BAD_CLK66) { + /* Would cause trouble on 596a and 686 */ + pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); + } + + /* + * Check whether interfaces are enabled. + */ + + pci_read_config_byte(dev, VIA_IDE_ENABLE, &v); + + /* + * Set up FIFO sizes and thresholds. + */ + + pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t); + + /* Disable PREQ# till DDACK# */ + if (via_config->flags & VIA_BAD_PREQ) { + /* Would crash on 586b rev 41 */ + t &= 0x7f; + } + + /* Fix FIFO split between channels */ + if (via_config->flags & VIA_SET_FIFO) { + t &= (t & 0x9f); + switch (v & 3) { + case 2: t |= 0x00; break; /* 16 on primary */ + case 1: t |= 0x60; break; /* 16 on secondary */ + case 3: t |= 0x20; break; /* 8 pri 8 sec */ + } + } + + pci_write_config_byte(dev, VIA_FIFO_CONFIG, t); + + return 0; +} + +/* + * Cable special cases + */ + +static const struct dmi_system_id cable_dmi_table[] = { + { + .ident = "Acer Ferrari 3400", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."), + DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"), + }, + }, + { } +}; + +static int via_cable_override(struct pci_dev *pdev) +{ + /* Systems by DMI */ + if (dmi_check_system(cable_dmi_table)) + return 1; + + /* Arima W730-K8/Targa Visionary 811/... */ + if (pdev->subsystem_vendor == 0x161F && + pdev->subsystem_device == 0x2032) + return 1; + + return 0; +} + +static u8 via82cxxx_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *pdev = to_pci_dev(hwif->dev); + struct ide_host *host = pci_get_drvdata(pdev); + struct via82cxxx_dev *vdev = host->host_priv; + + if (via_cable_override(pdev)) + return ATA_CBL_PATA40_SHORT; + + if ((vdev->via_80w >> hwif->channel) & 1) + return ATA_CBL_PATA80; + else + return ATA_CBL_PATA40; +} + +static const struct ide_port_ops via_port_ops = { + .set_pio_mode = via_set_pio_mode, + .set_dma_mode = via_set_drive, + .cable_detect = via82cxxx_cable_detect, +}; + +static const struct ide_port_info via82cxxx_chipset __devinitdata = { + .name = DRV_NAME, + .init_chipset = init_chipset_via82cxxx, + .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, + .port_ops = &via_port_ops, + .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | + IDE_HFLAG_POST_SET_MODE | + IDE_HFLAG_IO_32BIT, + .pio_mask = ATA_PIO5, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, +}; + +static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct pci_dev *isa = NULL; + struct via_isa_bridge *via_config; + struct via82cxxx_dev *vdev; + int rc; + u8 idx = id->driver_data; + struct ide_port_info d; + + d = via82cxxx_chipset; + + /* + * Find the ISA bridge and check we know what it is. + */ + via_config = via_config_find(&isa); + if (!via_config->id) { + printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n", + pci_name(dev)); + return -ENODEV; + } + + /* + * Print the boot message. + */ + printk(KERN_INFO DRV_NAME " %s: VIA %s (rev %02x) IDE %sDMA%s\n", + pci_name(dev), via_config->name, isa->revision, + via_config->udma_mask ? "U" : "MW", + via_dma[via_config->udma_mask ? + (fls(via_config->udma_mask) - 1) : 0]); + + pci_dev_put(isa); + + /* + * Determine system bus clock. + */ + via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000; + + switch (via_clock) { + case 33000: via_clock = 33333; break; + case 37000: via_clock = 37500; break; + case 41000: via_clock = 41666; break; + } + + if (via_clock < 20000 || via_clock > 50000) { + printk(KERN_WARNING DRV_NAME ": User given PCI clock speed " + "impossible (%d), using 33 MHz instead.\n", via_clock); + printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want " + "to assume 80-wire cable.\n"); + via_clock = 33333; + } + + if (idx == 0) + d.host_flags |= IDE_HFLAG_NO_AUTODMA; + else + d.enablebits[1].reg = d.enablebits[0].reg = 0; + + if ((via_config->flags & VIA_NO_UNMASK) == 0) + d.host_flags |= IDE_HFLAG_UNMASK_IRQS; + +#ifdef CONFIG_PPC_CHRP + if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos) + d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; +#endif + + d.udma_mask = via_config->udma_mask; + + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); + if (!vdev) { + printk(KERN_ERR DRV_NAME " %s: out of memory :(\n", + pci_name(dev)); + return -ENOMEM; + } + + vdev->via_config = via_config; + + rc = ide_pci_init_one(dev, &d, vdev); + if (rc) + kfree(vdev); + + return rc; +} + +static void __devexit via_remove(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct via82cxxx_dev *vdev = host->host_priv; + + ide_pci_remove(dev); + kfree(vdev); +} + +static const struct pci_device_id via_pci_tbl[] = { + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), 0 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), 0 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_CX700_IDE), 0 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), 1 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, via_pci_tbl); + +static struct pci_driver via_pci_driver = { + .name = "VIA_IDE", + .id_table = via_pci_tbl, + .probe = via_init_one, + .remove = __devexit_p(via_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init via_ide_init(void) +{ + return ide_pci_register_driver(&via_pci_driver); +} + +static void __exit via_ide_exit(void) +{ + pci_unregister_driver(&via_pci_driver); +} + +module_init(via_ide_init); +module_exit(via_ide_exit); + +MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for VIA IDE"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2