diff options
Diffstat (limited to 'drivers/ide')
62 files changed, 3935 insertions, 1829 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 3f828052f8d2..49234e32fd16 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -167,6 +167,13 @@ config BLK_DEV_IDECS Support for Compact Flash cards, outboard IDE disks, tape drives, and CD-ROM drives connected through a PCMCIA card. +config BLK_DEV_DELKIN + tristate "Cardbus IDE support (Delkin/ASKA/Workbit)" + depends on CARDBUS && PCI + help + Support for Delkin, ASKA, and Workbit Cardbus CompactFlash + Adapters. This may also work for similar SD and XD adapters. + config BLK_DEV_IDECD tristate "Include IDE/ATAPI CDROM support" ---help--- @@ -264,6 +271,13 @@ config BLK_DEV_IDESCSI If both this SCSI emulation and native ATAPI support are compiled into the kernel, the native support will be used. +config BLK_DEV_IDEACPI + bool "IDE ACPI support" + depends on ACPI + ---help--- + Implement ACPI support for generic IDE devices. On modern + machines ACPI support is required to properly handle ACPI S3 states. + config IDE_TASK_IOCTL bool "IDE Taskfile Access" help @@ -369,6 +383,9 @@ config BLK_DEV_OFFBOARD config BLK_DEV_GENERIC tristate "Generic PCI IDE Chipset Support" depends on BLK_DEV_IDEPCI + help + This option provides generic support for various PCI IDE Chipsets + which otherwise might not be supported. config BLK_DEV_OPTI621 tristate "OPTi 82C621 chipset enhanced support (EXPERIMENTAL)" @@ -606,6 +623,11 @@ config BLK_DEV_PIIX the kernel to change PIO, DMA and UDMA speeds and to configure the chip to optimum performance. +config BLK_DEV_IT8213 + tristate "IT8213 IDE support" + help + This driver adds support for the ITE 8213 IDE controller. + config BLK_DEV_IT821X tristate "IT821X IDE support" help @@ -742,6 +764,11 @@ config BLK_DEV_VIA82CXXX This allows the kernel to change PIO, DMA and UDMA speeds and to configure the chip to optimum performance. +config BLK_DEV_TC86C001 + tristate "Toshiba TC86C001 support" + help + This driver adds support for Toshiba TC86C001 GOKU-S chip. + endif config BLK_DEV_IDE_PMAC @@ -773,6 +800,14 @@ config BLK_DEV_IDEDMA_PMAC to transfer data to and from memory. Saying Y is safe and improves performance. +config BLK_DEV_IDE_CELLEB + bool "Toshiba's Cell Reference Set IDE support" + depends on PPC_CELLEB + help + This driver provides support for the built-in IDE controller on + Toshiba Cell Reference Board. + If unsure, say Y. + config BLK_DEV_IDE_SWARM tristate "IDE for Sibyte evaluation boards" depends on SIBYTE_SB1xxx_SOC diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 569fae717503..28feedfbd21d 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -22,6 +22,7 @@ ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o ide-core-$(CONFIG_PROC_FS) += ide-proc.o ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o +ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o # built-in only drivers from arm/ ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o @@ -36,6 +37,7 @@ ide-core-$(CONFIG_BLK_DEV_Q40IDE) += legacy/q40ide.o # built-in only drivers from ppc/ ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o +ide-core-$(CONFIG_BLK_DEV_IDE_CELLEB) += ppc/scc_pata.o # built-in only drivers from h8300/ ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 8a1c27f28692..40e5c66b81ce 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -307,26 +307,24 @@ static int icside_set_speed(ide_drive_t *drive, u8 xfer_mode) return on; } -static int icside_dma_host_off(ide_drive_t *drive) +static void icside_dma_host_off(ide_drive_t *drive) { - return 0; } -static int icside_dma_off_quietly(ide_drive_t *drive) +static void icside_dma_off_quietly(ide_drive_t *drive) { drive->using_dma = 0; - return icside_dma_host_off(drive); } -static int icside_dma_host_on(ide_drive_t *drive) +static void icside_dma_host_on(ide_drive_t *drive) { - return 0; } static int icside_dma_on(ide_drive_t *drive) { drive->using_dma = 1; - return icside_dma_host_on(drive); + + return 0; } static int icside_dma_check(ide_drive_t *drive) @@ -365,10 +363,7 @@ static int icside_dma_check(ide_drive_t *drive) out: on = icside_set_speed(drive, xfer_mode); - if (on) - return icside_dma_on(drive); - else - return icside_dma_off_quietly(drive); + return on ? 0 : -1; } static int icside_dma_end(ide_drive_t *drive) @@ -497,9 +492,9 @@ static void icside_dma_init(ide_hwif_t *hwif) hwif->autodma = autodma; hwif->ide_dma_check = icside_dma_check; - hwif->ide_dma_host_off = icside_dma_host_off; - hwif->ide_dma_off_quietly = icside_dma_off_quietly; - hwif->ide_dma_host_on = icside_dma_host_on; + hwif->dma_host_off = icside_dma_host_off; + hwif->dma_off_quietly = icside_dma_off_quietly; + hwif->dma_host_on = icside_dma_host_on; hwif->ide_dma_on = icside_dma_on; hwif->dma_setup = icside_dma_setup; hwif->dma_exec_cmd = icside_dma_exec_cmd; @@ -556,7 +551,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e * Ensure we're using MMIO */ default_hwif_mmiops(hwif); - hwif->mmio = 2; + hwif->mmio = 1; for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { hwif->hw.io_ports[i] = port; diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c index 3058217767d6..9c6c49fdd2b1 100644 --- a/drivers/ide/arm/rapide.c +++ b/drivers/ide/arm/rapide.c @@ -46,7 +46,7 @@ rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; hwif->hw.irq = hwif->irq = irq; - hwif->mmio = 2; + hwif->mmio = 1; default_hwif_mmiops(hwif); return hwif; diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index 5797e0b5a132..6b2d152351b3 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -682,9 +682,12 @@ static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int); static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int); static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int); static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int); -static int cris_dma_off (ide_drive_t *drive); static int cris_dma_on (ide_drive_t *drive); +static void cris_dma_off(ide_drive_t *drive) +{ +} + static void tune_cris_ide(ide_drive_t *drive, u8 pio) { int setup, strobe, hold; @@ -795,7 +798,7 @@ init_e100_ide (void) 0, 0, cris_ide_ack_intr, ide_default_irq(0)); ide_register_hw(&hw, &hwif); - hwif->mmio = 2; + hwif->mmio = 1; hwif->chipset = ide_etrax100; hwif->tuneproc = &tune_cris_ide; hwif->speedproc = &speed_cris_ide; @@ -814,13 +817,16 @@ init_e100_ide (void) hwif->OUTBSYNC = &cris_ide_outbsync; hwif->INB = &cris_ide_inb; hwif->INW = &cris_ide_inw; - hwif->ide_dma_host_off = &cris_dma_off; - hwif->ide_dma_host_on = &cris_dma_on; - hwif->ide_dma_off_quietly = &cris_dma_off; + hwif->dma_host_off = &cris_dma_off; + hwif->dma_host_on = &cris_dma_on; + hwif->dma_off_quietly = &cris_dma_off; hwif->udma_four = 0; hwif->ultra_mask = cris_ultra_mask; hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */ hwif->swdma_mask = 0x07; /* Singleword DMA 0-2 */ + hwif->autodma = 1; + hwif->drives[0].autodma = 1; + hwif->drives[1].autodma = 1; } /* Reset pulse */ @@ -835,11 +841,6 @@ init_e100_ide (void) cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0); } -static int cris_dma_off (ide_drive_t *drive) -{ - return 0; -} - static int cris_dma_on (ide_drive_t *drive) { return 0; @@ -1045,17 +1046,10 @@ static ide_startstop_t cris_dma_intr (ide_drive_t *drive) static int cris_dma_check(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct hd_driveid* id = drive->id; - - if (id && (id->capability & 1)) { - if (ide_use_dma(drive)) { - if (cris_config_drive_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - } + if (ide_use_dma(drive) && cris_config_drive_for_dma(drive)) + return 0; - return hwif->ide_dma_off_quietly(drive); + return -1; } static int cris_dma_end(ide_drive_t *drive) diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c index 608ca871744b..88750a300337 100644 --- a/drivers/ide/h8300/ide-h8300.c +++ b/drivers/ide/h8300/ide-h8300.c @@ -76,13 +76,11 @@ static inline void hwif_setup(ide_hwif_t *hwif) { default_hwif_iops(hwif); - hwif->mmio = 2; + hwif->mmio = 1; hwif->OUTW = mm_outw; hwif->OUTSW = mm_outsw; hwif->INW = mm_inw; hwif->INSW = mm_insw; - hwif->OUTL = NULL; - hwif->INL = NULL; hwif->OUTSL = NULL; hwif->INSL = NULL; } diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c new file mode 100644 index 000000000000..17aea65d7dd2 --- /dev/null +++ b/drivers/ide/ide-acpi.c @@ -0,0 +1,697 @@ +/* + * ide-acpi.c + * Provides ACPI support for IDE drives. + * + * Copyright (C) 2005 Intel Corp. + * Copyright (C) 2005 Randy Dunlap + * Copyright (C) 2006 SUSE Linux Products GmbH + * Copyright (C) 2006 Hannes Reinecke + */ + +#include <linux/ata.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <acpi/acpi.h> +#include <linux/ide.h> +#include <linux/pci.h> + +#include <acpi/acpi_bus.h> +#include <acpi/acnames.h> +#include <acpi/acnamesp.h> +#include <acpi/acparser.h> +#include <acpi/acexcep.h> +#include <acpi/acmacros.h> +#include <acpi/actypes.h> + +#define REGS_PER_GTF 7 +struct taskfile_array { + u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ +}; + +struct GTM_buffer { + u32 PIO_speed0; + u32 DMA_speed0; + u32 PIO_speed1; + u32 DMA_speed1; + u32 GTM_flags; +}; + +struct ide_acpi_drive_link { + ide_drive_t *drive; + acpi_handle obj_handle; + u8 idbuff[512]; +}; + +struct ide_acpi_hwif_link { + ide_hwif_t *hwif; + acpi_handle obj_handle; + struct GTM_buffer gtm; + struct ide_acpi_drive_link master; + struct ide_acpi_drive_link slave; +}; + +#undef DEBUGGING +/* note: adds function name and KERN_DEBUG */ +#ifdef DEBUGGING +#define DEBPRINT(fmt, args...) \ + printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args) +#else +#define DEBPRINT(fmt, args...) do {} while (0) +#endif /* DEBUGGING */ + +extern int ide_noacpi; +extern int ide_noacpitfs; +extern int ide_noacpionboot; + +/** + * ide_get_dev_handle - finds acpi_handle and PCI device.function + * @dev: device to locate + * @handle: returned acpi_handle for @dev + * @pcidevfn: return PCI device.func for @dev + * + * Returns the ACPI object handle to the corresponding PCI device. + * + * Returns 0 on success, <0 on error. + */ +static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, + acpi_integer *pcidevfn) +{ + struct pci_dev *pdev = to_pci_dev(dev); + unsigned int bus, devnum, func; + acpi_integer addr; + acpi_handle dev_handle; + struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER, + .pointer = NULL}; + acpi_status status; + struct acpi_device_info *dinfo = NULL; + int ret = -ENODEV; + + bus = pdev->bus->number; + devnum = PCI_SLOT(pdev->devfn); + func = PCI_FUNC(pdev->devfn); + /* ACPI _ADR encoding for PCI bus: */ + addr = (acpi_integer)(devnum << 16 | func); + + DEBPRINT("ENTER: pci %02x:%02x.%01x\n", bus, devnum, func); + + dev_handle = DEVICE_ACPI_HANDLE(dev); + if (!dev_handle) { + DEBPRINT("no acpi handle for device\n"); + goto err; + } + + status = acpi_get_object_info(dev_handle, &buffer); + if (ACPI_FAILURE(status)) { + DEBPRINT("get_object_info for device failed\n"); + goto err; + } + dinfo = buffer.pointer; + if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && + dinfo->address == addr) { + *pcidevfn = addr; + *handle = dev_handle; + } else { + DEBPRINT("get_object_info for device has wrong " + " address: %llu, should be %u\n", + dinfo ? (unsigned long long)dinfo->address : -1ULL, + (unsigned int)addr); + goto err; + } + + DEBPRINT("for dev=0x%x.%x, addr=0x%llx, *handle=0x%p\n", + devnum, func, (unsigned long long)addr, *handle); + ret = 0; +err: + kfree(dinfo); + return ret; +} + +/** + * ide_acpi_hwif_get_handle - Get ACPI object handle for a given hwif + * @hwif: device to locate + * + * Retrieves the object handle for a given hwif. + * + * Returns handle on success, 0 on error. + */ +static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) +{ + struct device *dev = hwif->gendev.parent; + acpi_handle dev_handle; + acpi_integer pcidevfn; + acpi_handle chan_handle; + int err; + + DEBPRINT("ENTER: device %s\n", hwif->name); + + if (!dev) { + DEBPRINT("no PCI device for %s\n", hwif->name); + return NULL; + } + + err = ide_get_dev_handle(dev, &dev_handle, &pcidevfn); + if (err < 0) { + DEBPRINT("ide_get_dev_handle failed (%d)\n", err); + return NULL; + } + + /* get child objects of dev_handle == channel objects, + * + _their_ children == drive objects */ + /* channel is hwif->channel */ + chan_handle = acpi_get_child(dev_handle, hwif->channel); + DEBPRINT("chan adr=%d: handle=0x%p\n", + hwif->channel, chan_handle); + + return chan_handle; +} + +/** + * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive + * @drive: device to locate + * + * Retrieves the object handle of a given drive. According to the ACPI + * spec the drive is a child of the hwif. + * + * Returns handle on success, 0 on error. + */ +static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + int port; + acpi_handle drive_handle; + + if (!hwif->acpidata) + return NULL; + + if (!hwif->acpidata->obj_handle) + return NULL; + + port = hwif->channel ? drive->dn - 2: drive->dn; + + DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", + drive->name, hwif->channel, port); + + + /* TBD: could also check ACPI object VALID bits */ + drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port); + DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle); + + return drive_handle; +} + +/** + * do_drive_get_GTF - get the drive bootup default taskfile settings + * @drive: the drive for which the taskfile settings should be retrieved + * @gtf_length: number of bytes of _GTF data returned at @gtf_address + * @gtf_address: buffer containing _GTF taskfile arrays + * + * The _GTF method has no input parameters. + * It returns a variable number of register set values (registers + * hex 1F1..1F7, taskfiles). + * The <variable number> is not known in advance, so have ACPI-CA + * allocate the buffer as needed and return it, then free it later. + * + * The returned @gtf_length and @gtf_address are only valid if the + * function return value is 0. + */ +static int do_drive_get_GTF(ide_drive_t *drive, + unsigned int *gtf_length, unsigned long *gtf_address, + unsigned long *obj_loc) +{ + acpi_status status; + struct acpi_buffer output; + union acpi_object *out_obj; + ide_hwif_t *hwif = HWIF(drive); + struct device *dev = hwif->gendev.parent; + int err = -ENODEV; + int port; + + *gtf_length = 0; + *gtf_address = 0UL; + *obj_loc = 0UL; + + if (ide_noacpi) + return 0; + + if (!dev) { + DEBPRINT("no PCI device for %s\n", hwif->name); + goto out; + } + + if (!hwif->acpidata) { + DEBPRINT("no ACPI data for %s\n", hwif->name); + goto out; + } + + port = hwif->channel ? drive->dn - 2: drive->dn; + + if (!drive->acpidata) { + if (port == 0) { + drive->acpidata = &hwif->acpidata->master; + hwif->acpidata->master.drive = drive; + } else { + drive->acpidata = &hwif->acpidata->slave; + hwif->acpidata->slave.drive = drive; + } + } + + DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", + hwif->name, dev->bus_id, port, hwif->channel); + + if (!drive->present) { + DEBPRINT("%s drive %d:%d not present\n", + hwif->name, hwif->channel, port); + goto out; + } + + /* Get this drive's _ADR info. if not already known. */ + if (!drive->acpidata->obj_handle) { + drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); + if (!drive->acpidata->obj_handle) { + DEBPRINT("No ACPI object found for %s\n", + drive->name); + goto out; + } + } + + /* Setting up output buffer */ + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ + + /* _GTF has no input parameters */ + err = -EIO; + status = acpi_evaluate_object(drive->acpidata->obj_handle, "_GTF", + NULL, &output); + if (ACPI_FAILURE(status)) { + printk(KERN_DEBUG + "%s: Run _GTF error: status = 0x%x\n", + __FUNCTION__, status); + goto out; + } + + if (!output.length || !output.pointer) { + DEBPRINT("Run _GTF: " + "length or ptr is NULL (0x%llx, 0x%p)\n", + (unsigned long long)output.length, + output.pointer); + goto out; + } + + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + DEBPRINT("Run _GTF: error: " + "expected object type of ACPI_TYPE_BUFFER, " + "got 0x%x\n", out_obj->type); + err = -ENOENT; + kfree(output.pointer); + goto out; + } + + if (!out_obj->buffer.length || !out_obj->buffer.pointer || + out_obj->buffer.length % REGS_PER_GTF) { + printk(KERN_ERR + "%s: unexpected GTF length (%d) or addr (0x%p)\n", + __FUNCTION__, out_obj->buffer.length, + out_obj->buffer.pointer); + err = -ENOENT; + kfree(output.pointer); + goto out; + } + + *gtf_length = out_obj->buffer.length; + *gtf_address = (unsigned long)out_obj->buffer.pointer; + *obj_loc = (unsigned long)out_obj; + DEBPRINT("returning gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n", + *gtf_length, *gtf_address, *obj_loc); + err = 0; +out: + return err; +} + +/** + * taskfile_load_raw - send taskfile registers to drive + * @drive: drive to which output is sent + * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) + * + * Outputs IDE taskfile to the drive. + */ +static int taskfile_load_raw(ide_drive_t *drive, + const struct taskfile_array *gtf) +{ + ide_task_t args; + int err = 0; + + DEBPRINT("(0x1f1-1f7): hex: " + "%02x %02x %02x %02x %02x %02x %02x\n", + gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], + gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); + + memset(&args, 0, sizeof(ide_task_t)); + args.command_type = IDE_DRIVE_TASK_NO_DATA; + args.data_phase = TASKFILE_IN; + args.handler = &task_no_data_intr; + + /* convert gtf to IDE Taskfile */ + args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */ + args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */ + args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */ + args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */ + args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */ + args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */ + args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */ + + if (ide_noacpitfs) { + DEBPRINT("_GTF execution disabled\n"); + return err; + } + + err = ide_raw_taskfile(drive, &args, NULL); + if (err) + printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n", + __FUNCTION__, err); + + return err; +} + +/** + * do_drive_set_taskfiles - write the drive taskfile settings from _GTF + * @drive: the drive to which the taskfile command should be sent + * @gtf_length: total number of bytes of _GTF taskfiles + * @gtf_address: location of _GTF taskfile arrays + * + * Write {gtf_address, length gtf_length} in groups of + * REGS_PER_GTF bytes. + */ +static int do_drive_set_taskfiles(ide_drive_t *drive, + unsigned int gtf_length, + unsigned long gtf_address) +{ + int rc = -ENODEV, err; + int gtf_count = gtf_length / REGS_PER_GTF; + int ix; + struct taskfile_array *gtf; + + if (ide_noacpi) + return 0; + + DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn); + + if (!drive->present) + goto out; + if (!gtf_count) /* shouldn't be here */ + goto out; + + DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", + gtf_length, gtf_length, gtf_count, gtf_address); + + if (gtf_length % REGS_PER_GTF) { + printk(KERN_ERR "%s: unexpected GTF length (%d)\n", + __FUNCTION__, gtf_length); + goto out; + } + + rc = 0; + for (ix = 0; ix < gtf_count; ix++) { + gtf = (struct taskfile_array *) + (gtf_address + ix * REGS_PER_GTF); + + /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ + err = taskfile_load_raw(drive, gtf); + if (err) + rc = err; + } + +out: + return rc; +} + +/** + * ide_acpi_exec_tfs - get then write drive taskfile settings + * @drive: the drive for which the taskfile settings should be + * written. + * + * According to the ACPI spec this should be called after _STM + * has been evaluated for the interface. Some ACPI vendors interpret + * that as a hard requirement and modify the taskfile according + * to the Identify Drive information passed down with _STM. + * So one should really make sure to call this only after _STM has + * been executed. + */ +int ide_acpi_exec_tfs(ide_drive_t *drive) +{ + int ret; + unsigned int gtf_length; + unsigned long gtf_address; + unsigned long obj_loc; + + if (ide_noacpi) + return 0; + + DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn); + + ret = do_drive_get_GTF(drive, >f_length, >f_address, &obj_loc); + if (ret < 0) { + DEBPRINT("get_GTF error (%d)\n", ret); + return ret; + } + + DEBPRINT("call set_taskfiles, drive=%s\n", drive->name); + + ret = do_drive_set_taskfiles(drive, gtf_length, gtf_address); + kfree((void *)obj_loc); + if (ret < 0) { + DEBPRINT("set_taskfiles error (%d)\n", ret); + } + + DEBPRINT("ret=%d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs); + +/** + * ide_acpi_get_timing - get the channel (controller) timings + * @hwif: target IDE interface (channel) + * + * This function executes the _GTM ACPI method for the target channel. + * + */ +void ide_acpi_get_timing(ide_hwif_t *hwif) +{ + acpi_status status; + struct acpi_buffer output; + union acpi_object *out_obj; + + if (ide_noacpi) + return; + + DEBPRINT("ENTER:\n"); + + if (!hwif->acpidata) { + DEBPRINT("no ACPI data for %s\n", hwif->name); + return; + } + + /* Setting up output buffer for _GTM */ + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ + + /* _GTM has no input parameters */ + status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_GTM", + NULL, &output); + + DEBPRINT("_GTM status: %d, outptr: 0x%p, outlen: 0x%llx\n", + status, output.pointer, + (unsigned long long)output.length); + + if (ACPI_FAILURE(status)) { + DEBPRINT("Run _GTM error: status = 0x%x\n", status); + return; + } + + if (!output.length || !output.pointer) { + DEBPRINT("Run _GTM: length or ptr is NULL (0x%llx, 0x%p)\n", + (unsigned long long)output.length, + output.pointer); + kfree(output.pointer); + return; + } + + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + kfree(output.pointer); + DEBPRINT("Run _GTM: error: " + "expected object type of ACPI_TYPE_BUFFER, " + "got 0x%x\n", out_obj->type); + return; + } + + if (!out_obj->buffer.length || !out_obj->buffer.pointer || + out_obj->buffer.length != sizeof(struct GTM_buffer)) { + kfree(output.pointer); + printk(KERN_ERR + "%s: unexpected _GTM length (0x%x)[should be 0x%zx] or " + "addr (0x%p)\n", + __FUNCTION__, out_obj->buffer.length, + sizeof(struct GTM_buffer), out_obj->buffer.pointer); + return; + } + + memcpy(&hwif->acpidata->gtm, out_obj->buffer.pointer, + sizeof(struct GTM_buffer)); + + DEBPRINT("_GTM info: ptr: 0x%p, len: 0x%x, exp.len: 0x%Zx\n", + out_obj->buffer.pointer, out_obj->buffer.length, + sizeof(struct GTM_buffer)); + + DEBPRINT("_GTM fields: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + hwif->acpidata->gtm.PIO_speed0, + hwif->acpidata->gtm.DMA_speed0, + hwif->acpidata->gtm.PIO_speed1, + hwif->acpidata->gtm.DMA_speed1, + hwif->acpidata->gtm.GTM_flags); + + kfree(output.pointer); +} +EXPORT_SYMBOL_GPL(ide_acpi_get_timing); + +/** + * ide_acpi_push_timing - set the channel (controller) timings + * @hwif: target IDE interface (channel) + * + * This function executes the _STM ACPI method for the target channel. + * + * _STM requires Identify Drive data, which has to passed as an argument. + * Unfortunately hd_driveid is a mangled version which we can't readily + * use; hence we'll get the information afresh. + */ +void ide_acpi_push_timing(ide_hwif_t *hwif) +{ + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[3]; + struct ide_acpi_drive_link *master = &hwif->acpidata->master; + struct ide_acpi_drive_link *slave = &hwif->acpidata->slave; + + if (ide_noacpi) + return; + + DEBPRINT("ENTER:\n"); + + if (!hwif->acpidata) { + DEBPRINT("no ACPI data for %s\n", hwif->name); + return; + } + + /* Give the GTM buffer + drive Identify data to the channel via the + * _STM method: */ + /* setup input parameters buffer for _STM */ + input.count = 3; + input.pointer = in_params; + in_params[0].type = ACPI_TYPE_BUFFER; + in_params[0].buffer.length = sizeof(struct GTM_buffer); + in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm; + in_params[1].type = ACPI_TYPE_BUFFER; + in_params[1].buffer.length = sizeof(struct hd_driveid); + in_params[1].buffer.pointer = (u8 *)&master->idbuff; + in_params[2].type = ACPI_TYPE_BUFFER; + in_params[2].buffer.length = sizeof(struct hd_driveid); + in_params[2].buffer.pointer = (u8 *)&slave->idbuff; + /* Output buffer: _STM has no output */ + + status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_STM", + &input, NULL); + + if (ACPI_FAILURE(status)) { + DEBPRINT("Run _STM error: status = 0x%x\n", status); + } + DEBPRINT("_STM status: %d\n", status); +} +EXPORT_SYMBOL_GPL(ide_acpi_push_timing); + +/** + * ide_acpi_init - initialize the ACPI link for an IDE interface + * @hwif: target IDE interface (channel) + * + * The ACPI spec is not quite clear when the drive identify buffer + * should be obtained. Calling IDENTIFY DEVICE during shutdown + * is not the best of ideas as the drive might already being put to + * sleep. And obviously we can't call it during resume. + * So we get the information during startup; but this means that + * any changes during run-time will be lost after resume. + */ +void ide_acpi_init(ide_hwif_t *hwif) +{ + int unit; + int err; + struct ide_acpi_drive_link *master; + struct ide_acpi_drive_link *slave; + + hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); + if (!hwif->acpidata) + return; + + hwif->acpidata->obj_handle = ide_acpi_hwif_get_handle(hwif); + if (!hwif->acpidata->obj_handle) { + DEBPRINT("no ACPI object for %s found\n", hwif->name); + kfree(hwif->acpidata); + hwif->acpidata = NULL; + return; + } + + /* + * The ACPI spec mandates that we send information + * for both drives, regardless whether they are connected + * or not. + */ + hwif->acpidata->master.drive = &hwif->drives[0]; + hwif->drives[0].acpidata = &hwif->acpidata->master; + master = &hwif->acpidata->master; + + hwif->acpidata->slave.drive = &hwif->drives[1]; + hwif->drives[1].acpidata = &hwif->acpidata->slave; + slave = &hwif->acpidata->slave; + + + /* + * Send IDENTIFY for each drive + */ + if (master->drive->present) { + err = taskfile_lib_get_identify(master->drive, master->idbuff); + if (err) { + DEBPRINT("identify device %s failed (%d)\n", + master->drive->name, err); + } + } + + if (slave->drive->present) { + err = taskfile_lib_get_identify(slave->drive, slave->idbuff); + if (err) { + DEBPRINT("identify device %s failed (%d)\n", + slave->drive->name, err); + } + } + + if (ide_noacpionboot) { + DEBPRINT("ACPI methods disabled on boot\n"); + return; + } + + /* + * ACPI requires us to call _STM on startup + */ + ide_acpi_get_timing(hwif); + ide_acpi_push_timing(hwif); + + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + + if (drive->present) { + /* Execute ACPI startup code */ + ide_acpi_exec_tfs(drive); + } + } +} +EXPORT_SYMBOL_GPL(ide_acpi_init); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 5969cec58dc1..45a928c058cf 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -687,15 +687,8 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) { struct request *rq = HWGROUP(drive)->rq; - ide_hwif_t *hwif = HWIF(drive); int stat, err, sense_key; - /* We may have bogus DMA interrupts in PIO state here */ - if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) { - stat = hwif->INB(hwif->dma_status); - /* Should we force the bit as well ? */ - hwif->OUTB(stat, hwif->dma_status); - } /* Check for errors. */ stat = HWIF(drive)->INB(IDE_STATUS_REG); if (stat_ret) @@ -930,6 +923,10 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { + /* waiting for CDB interrupt, not DMA yet. */ + if (info->dma) + drive->waiting_for_dma = 0; + /* packet command */ ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); return ide_started; @@ -972,6 +969,10 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, /* Check for errors. */ if (cdrom_decode_status(drive, DRQ_STAT, NULL)) return ide_stopped; + + /* Ok, next interrupt will be DMA interrupt. */ + if (info->dma) + drive->waiting_for_dma = 1; } else { /* Otherwise, we must wait for DRQ to get set. */ if (ide_wait_stat(&startstop, drive, DRQ_STAT, @@ -1103,7 +1104,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) if (dma) { info->dma = 0; if ((dma_error = HWIF(drive)->ide_dma_end(drive))) - __ide_dma_off(drive); + ide_dma_off(drive); } if (cdrom_decode_status(drive, 0, &stat)) @@ -1699,7 +1700,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (dma) { if (dma_error) { printk(KERN_ERR "ide-cd: dma error\n"); - __ide_dma_off(drive); + ide_dma_off(drive); return ide_error(drive, "dma error", stat); } @@ -1825,7 +1826,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) info->dma = 0; if ((dma_error = HWIF(drive)->ide_dma_end(drive))) { printk(KERN_ERR "ide-cd: write dma error\n"); - __ide_dma_off(drive); + ide_dma_off(drive); } } @@ -3254,14 +3255,6 @@ int ide_cdrom_setup (ide_drive_t *drive) if (drive->autotune == IDE_TUNE_DEFAULT || drive->autotune == IDE_TUNE_AUTO) drive->dsc_overlap = (drive->next != drive); -#if 0 - drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1; - if (HWIF(drive)->no_dsc) { - printk(KERN_INFO "ide-cd: %s: disabling DSC overlap\n", - drive->name); - drive->dsc_overlap = 0; - } -#endif if (ide_cdrom_register(drive, nslots)) { printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); @@ -3360,21 +3353,16 @@ static int idecd_open(struct inode * inode, struct file * file) { struct gendisk *disk = inode->i_bdev->bd_disk; struct cdrom_info *info; - ide_drive_t *drive; int rc = -ENOMEM; if (!(info = ide_cd_get(disk))) return -ENXIO; - drive = info->drive; - - drive->usage++; - if (!info->buffer) - info->buffer = kmalloc(SECTOR_BUFFER_SIZE, - GFP_KERNEL|__GFP_REPEAT); - if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file))) - drive->usage--; + info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT); + + if (info->buffer) + rc = cdrom_open(&info->devinfo, inode, file); if (rc < 0) ide_cd_put(info); @@ -3386,10 +3374,8 @@ static int idecd_release(struct inode * inode, struct file * file) { struct gendisk *disk = inode->i_bdev->bd_disk; struct cdrom_info *info = ide_cd_g(disk); - ide_drive_t *drive = info->drive; cdrom_release (&info->devinfo, file); - drive->usage--; ide_cd_put(info); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 0a05a377d66a..e2cea1889c4d 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -77,6 +77,7 @@ struct ide_disk_obj { ide_driver_t *driver; struct gendisk *disk; struct kref kref; + unsigned int openers; /* protected by BKL for now */ }; static DEFINE_MUTEX(idedisk_ref_mutex); @@ -1081,8 +1082,9 @@ static int idedisk_open(struct inode *inode, struct file *filp) drive = idkp->drive; - drive->usage++; - if (drive->removable && drive->usage == 1) { + idkp->openers++; + + if (drive->removable && idkp->openers == 1) { ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK; @@ -1106,9 +1108,10 @@ static int idedisk_release(struct inode *inode, struct file *filp) struct ide_disk_obj *idkp = ide_disk_g(disk); ide_drive_t *drive = idkp->drive; - if (drive->usage == 1) + if (idkp->openers == 1) ide_cacheflush_p(drive); - if (drive->removable && drive->usage == 1) { + + if (drive->removable && idkp->openers == 1) { ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK; @@ -1117,7 +1120,8 @@ static int idedisk_release(struct inode *inode, struct file *filp) if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } - drive->usage--; + + idkp->openers--; ide_disk_put(idkp); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 56efed6742d4..08e7cd043bcc 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -348,15 +348,14 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable); static int config_drive_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - if ((id->capability & 1) && hwif->autodma) { + if ((id->capability & 1) && drive->hwif->autodma) { /* * Enable DMA on any drive that has * UltraDMA (mode 0/1/2/3/4/5/6) enabled */ if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f)) - return hwif->ide_dma_on(drive); + return 0; /* * Enable DMA on any drive that has mode2 DMA * (multi or single) enabled @@ -364,14 +363,14 @@ static int config_drive_for_dma (ide_drive_t *drive) if (id->field_valid & 2) /* regular DMA */ if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) - return hwif->ide_dma_on(drive); + return 0; /* Consult the list of known "good" drives */ if (__ide_dma_good_drive(drive)) - return hwif->ide_dma_on(drive); + return 0; } -// if (hwif->tuneproc != NULL) hwif->tuneproc(drive, 255); - return hwif->ide_dma_off_quietly(drive); + + return -1; } /** @@ -415,72 +414,68 @@ static int dma_timer_expiry (ide_drive_t *drive) } /** - * __ide_dma_host_off - Generic DMA kill + * ide_dma_host_off - Generic DMA kill * @drive: drive to control * * Perform the generic IDE controller DMA off operation. This * works for most IDE bus mastering controllers */ -int __ide_dma_host_off (ide_drive_t *drive) +void ide_dma_host_off(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 unit = (drive->select.b.unit & 0x01); u8 dma_stat = hwif->INB(hwif->dma_status); hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status); - return 0; } -EXPORT_SYMBOL(__ide_dma_host_off); +EXPORT_SYMBOL(ide_dma_host_off); /** - * __ide_dma_host_off_quietly - Generic DMA kill + * ide_dma_off_quietly - Generic DMA kill * @drive: drive to control * * Turn off the current DMA on this IDE controller. */ -int __ide_dma_off_quietly (ide_drive_t *drive) +void ide_dma_off_quietly(ide_drive_t *drive) { drive->using_dma = 0; ide_toggle_bounce(drive, 0); - if (HWIF(drive)->ide_dma_host_off(drive)) - return 1; - - return 0; + drive->hwif->dma_host_off(drive); } -EXPORT_SYMBOL(__ide_dma_off_quietly); +EXPORT_SYMBOL(ide_dma_off_quietly); #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ /** - * __ide_dma_off - disable DMA on a device + * ide_dma_off - disable DMA on a device * @drive: drive to disable DMA on * * Disable IDE DMA for a device on this IDE controller. * Inform the user that DMA has been disabled. */ -int __ide_dma_off (ide_drive_t *drive) +void ide_dma_off(ide_drive_t *drive) { printk(KERN_INFO "%s: DMA disabled\n", drive->name); - return HWIF(drive)->ide_dma_off_quietly(drive); + drive->hwif->dma_off_quietly(drive); } -EXPORT_SYMBOL(__ide_dma_off); +EXPORT_SYMBOL(ide_dma_off); #ifdef CONFIG_BLK_DEV_IDEDMA_PCI /** - * __ide_dma_host_on - Enable DMA on a host + * ide_dma_host_on - Enable DMA on a host * @drive: drive to enable for DMA * * Enable DMA on an IDE controller following generic bus mastering * IDE controller behaviour */ - -int __ide_dma_host_on (ide_drive_t *drive) + +void ide_dma_host_on(ide_drive_t *drive) { if (drive->using_dma) { ide_hwif_t *hwif = HWIF(drive); @@ -488,12 +483,10 @@ int __ide_dma_host_on (ide_drive_t *drive) u8 dma_stat = hwif->INB(hwif->dma_status); hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status); - return 0; } - return 1; } -EXPORT_SYMBOL(__ide_dma_host_on); +EXPORT_SYMBOL(ide_dma_host_on); /** * __ide_dma_on - Enable DMA on a device @@ -511,8 +504,7 @@ int __ide_dma_on (ide_drive_t *drive) drive->using_dma = 1; ide_toggle_bounce(drive, 1); - if (HWIF(drive)->ide_dma_host_on(drive)) - return 1; + drive->hwif->dma_host_on(drive); return 0; } @@ -565,7 +557,10 @@ int ide_dma_setup(ide_drive_t *drive) } /* PRD table */ - hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable); + if (hwif->mmio) + writel(hwif->dmatable_dma, (void __iomem *)hwif->dma_prdtable); + else + outl(hwif->dmatable_dma, hwif->dma_prdtable); /* specify r/w */ hwif->OUTB(reading, hwif->dma_command); @@ -680,6 +675,9 @@ int ide_use_dma(ide_drive_t *drive) struct hd_driveid *id = drive->id; ide_hwif_t *hwif = drive->hwif; + if ((id->capability & 1) == 0 || drive->autodma == 0) + return 0; + /* consult the list of known "bad" drives */ if (__ide_dma_bad_drive(drive)) return 0; @@ -753,12 +751,37 @@ void ide_dma_verbose(ide_drive_t *drive) return; bug_dma_off: printk(", BUG DMA OFF"); - hwif->ide_dma_off_quietly(drive); + hwif->dma_off_quietly(drive); return; } EXPORT_SYMBOL(ide_dma_verbose); +int ide_set_dma(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + int rc; + + rc = hwif->ide_dma_check(drive); + + switch(rc) { + case -1: /* DMA needs to be disabled */ + hwif->dma_off_quietly(drive); + return 0; + case 0: /* DMA needs to be enabled */ + return hwif->ide_dma_on(drive); + case 1: /* DMA setting cannot be changed */ + break; + default: + BUG(); + break; + } + + return rc; +} + +EXPORT_SYMBOL_GPL(ide_set_dma); + #ifdef CONFIG_BLK_DEV_IDEDMA_PCI int __ide_dma_lostirq (ide_drive_t *drive) { @@ -809,7 +832,7 @@ int ide_release_dma(ide_hwif_t *hwif) { ide_release_dma_engine(hwif); - if (hwif->mmio == 2) + if (hwif->mmio) return 1; else return ide_release_iomio_dma(hwif); @@ -878,9 +901,9 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports) { - if (hwif->mmio == 2) + if (hwif->mmio) return ide_mapped_mmio_dma(hwif, base,ports); - BUG_ON(hwif->mmio == 1); + return ide_iomio_dma(hwif, base, ports); } @@ -908,14 +931,14 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p if (!(hwif->dma_prdtable)) hwif->dma_prdtable = (hwif->dma_base + 4); - if (!hwif->ide_dma_off_quietly) - hwif->ide_dma_off_quietly = &__ide_dma_off_quietly; - if (!hwif->ide_dma_host_off) - hwif->ide_dma_host_off = &__ide_dma_host_off; + if (!hwif->dma_off_quietly) + hwif->dma_off_quietly = &ide_dma_off_quietly; + if (!hwif->dma_host_off) + hwif->dma_host_off = &ide_dma_host_off; if (!hwif->ide_dma_on) hwif->ide_dma_on = &__ide_dma_on; - if (!hwif->ide_dma_host_on) - hwif->ide_dma_host_on = &__ide_dma_host_on; + if (!hwif->dma_host_on) + hwif->dma_host_on = &ide_dma_host_on; if (!hwif->ide_dma_check) hwif->ide_dma_check = &__ide_dma_check; if (!hwif->dma_setup) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index d33717c8afd4..57cd21c5b2c1 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -279,6 +279,7 @@ typedef struct ide_floppy_obj { ide_driver_t *driver; struct gendisk *disk; struct kref kref; + unsigned int openers; /* protected by BKL for now */ /* Current packet command */ idefloppy_pc_t *pc; @@ -866,7 +867,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { printk(KERN_ERR "ide-floppy: The floppy wants to issue " "more interrupts in DMA mode\n"); - (void)__ide_dma_off(drive); + ide_dma_off(drive); return ide_do_reset(drive); } @@ -1096,9 +1097,9 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p pc->current_position = pc->buffer; bcount.all = min(pc->request_transfer, 63 * 1024); - if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { - (void)__ide_dma_off(drive); - } + if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) + ide_dma_off(drive); + feature.all = 0; if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) @@ -1433,7 +1434,8 @@ static int idefloppy_get_capacity (ide_drive_t *drive) drive->bios_cyl = 0; drive->bios_head = drive->bios_sect = 0; - floppy->blocks = floppy->bs_factor = 0; + floppy->blocks = 0; + floppy->bs_factor = 1; set_capacity(floppy->disk, 0); idefloppy_create_read_capacity_cmd(&pc); @@ -1949,9 +1951,9 @@ static int idefloppy_open(struct inode *inode, struct file *filp) drive = floppy->drive; - drive->usage++; + floppy->openers++; - if (drive->usage == 1) { + if (floppy->openers == 1) { clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); /* Just in case */ @@ -1969,13 +1971,11 @@ static int idefloppy_open(struct inode *inode, struct file *filp) ** capacity of the drive or begin the format - Sam */ ) { - drive->usage--; ret = -EIO; goto out_put_floppy; } if (floppy->wp && (filp->f_mode & 2)) { - drive->usage--; ret = -EROFS; goto out_put_floppy; } @@ -1987,13 +1987,13 @@ static int idefloppy_open(struct inode *inode, struct file *filp) } check_disk_change(inode->i_bdev); } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) { - drive->usage--; ret = -EBUSY; goto out_put_floppy; } return 0; out_put_floppy: + floppy->openers--; ide_floppy_put(floppy); return ret; } @@ -2007,7 +2007,7 @@ static int idefloppy_release(struct inode *inode, struct file *filp) debug_log(KERN_INFO "Reached idefloppy_release\n"); - if (drive->usage == 1) { + if (floppy->openers == 1) { /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd(&pc, 0); @@ -2016,7 +2016,8 @@ static int idefloppy_release(struct inode *inode, struct file *filp) clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); } - drive->usage--; + + floppy->openers--; ide_floppy_put(floppy); @@ -2050,7 +2051,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file, prevent = 0; /* fall through */ case CDROM_LOCKDOOR: - if (drive->usage > 1) + if (floppy->openers > 1) return -EBUSY; /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */ @@ -2072,7 +2073,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file, if (!(file->f_mode & 2)) return -EPERM; - if (drive->usage > 1) { + if (floppy->openers > 1) { /* Don't format if someone is using the disk */ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 2614f41b5074..c193553f6fe7 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -226,7 +226,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * break; if (drive->hwif->ide_dma_check == NULL) break; - drive->hwif->ide_dma_check(drive); + ide_set_dma(drive); break; } pm->pm_step = ide_pm_state_completed; @@ -1351,7 +1351,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) */ drive->retry_pio++; drive->state = DMA_PIO_RETRY; - (void) hwif->ide_dma_off_quietly(drive); + hwif->dma_off_quietly(drive); /* * un-busy drive etc (hwgroup->busy is cleared on return) and @@ -1646,6 +1646,17 @@ irqreturn_t ide_intr (int irq, void *dev_id) del_timer(&hwgroup->timer); spin_unlock(&ide_lock); + /* Some controllers might set DMA INTR no matter DMA or PIO; + * bmdma status might need to be cleared even for + * PIO interrupts to prevent spurious/lost irq. + */ + if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma)) + /* 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. + */ + hwif->ide_dma_clear_irq(drive); + if (drive->unmask) local_irq_enable_in_hardirq(); /* service this interrupt, may set handler for next interrupt */ diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index badde6331775..c67b3b1e6f4c 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -49,11 +49,6 @@ static void ide_insw (unsigned long port, void *addr, u32 count) insw(port, addr, count); } -static u32 ide_inl (unsigned long port) -{ - return (u32) inl(port); -} - static void ide_insl (unsigned long port, void *addr, u32 count) { insl(port, addr, count); @@ -79,11 +74,6 @@ static void ide_outsw (unsigned long port, void *addr, u32 count) outsw(port, addr, count); } -static void ide_outl (u32 val, unsigned long port) -{ - outl(val, port); -} - static void ide_outsl (unsigned long port, void *addr, u32 count) { outsl(port, addr, count); @@ -94,12 +84,10 @@ void default_hwif_iops (ide_hwif_t *hwif) hwif->OUTB = ide_outb; hwif->OUTBSYNC = ide_outbsync; hwif->OUTW = ide_outw; - hwif->OUTL = ide_outl; hwif->OUTSW = ide_outsw; hwif->OUTSL = ide_outsl; hwif->INB = ide_inb; hwif->INW = ide_inw; - hwif->INL = ide_inl; hwif->INSW = ide_insw; hwif->INSL = ide_insl; } @@ -123,11 +111,6 @@ static void ide_mm_insw (unsigned long port, void *addr, u32 count) __ide_mm_insw((void __iomem *) port, addr, count); } -static u32 ide_mm_inl (unsigned long port) -{ - return (u32) readl((void __iomem *) port); -} - static void ide_mm_insl (unsigned long port, void *addr, u32 count) { __ide_mm_insl((void __iomem *) port, addr, count); @@ -153,11 +136,6 @@ static void ide_mm_outsw (unsigned long port, void *addr, u32 count) __ide_mm_outsw((void __iomem *) port, addr, count); } -static void ide_mm_outl (u32 value, unsigned long port) -{ - writel(value, (void __iomem *) port); -} - static void ide_mm_outsl (unsigned long port, void *addr, u32 count) { __ide_mm_outsl((void __iomem *) port, addr, count); @@ -170,12 +148,10 @@ void default_hwif_mmiops (ide_hwif_t *hwif) this one is controller specific! */ hwif->OUTBSYNC = ide_mm_outbsync; hwif->OUTW = ide_mm_outw; - hwif->OUTL = ide_mm_outl; hwif->OUTSW = ide_mm_outsw; hwif->OUTSL = ide_mm_outsl; hwif->INB = ide_mm_inb; hwif->INW = ide_mm_inw; - hwif->INL = ide_mm_inl; hwif->INSW = ide_mm_insw; hwif->INSL = ide_mm_insl; } @@ -777,7 +753,7 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed) #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->ide_dma_check) /* check if host supports DMA */ - hwif->ide_dma_host_off(drive); + hwif->dma_host_off(drive); #endif /* @@ -854,9 +830,9 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed) #ifdef CONFIG_BLK_DEV_IDEDMA if (speed >= XFER_SW_DMA_0) - hwif->ide_dma_host_on(drive); + hwif->dma_host_on(drive); else if (hwif->ide_dma_check) /* check if host supports DMA */ - hwif->ide_dma_off_quietly(drive); + hwif->dma_off_quietly(drive); #endif switch(speed) { @@ -1066,12 +1042,12 @@ static void check_dma_crc(ide_drive_t *drive) { #ifdef CONFIG_BLK_DEV_IDEDMA if (drive->crc_count) { - (void) HWIF(drive)->ide_dma_off_quietly(drive); + drive->hwif->dma_off_quietly(drive); ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive)); if (drive->current_speed >= XFER_SW_DMA_0) (void) HWIF(drive)->ide_dma_on(drive); } else - (void)__ide_dma_off(drive); + ide_dma_off(drive); #endif } diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 8237d89eec6e..8afce4ceea31 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -205,6 +205,21 @@ int ide_dma_enable (ide_drive_t *drive) EXPORT_SYMBOL(ide_dma_enable); +int ide_use_fast_pio(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + + if ((id->capability & 1) && drive->autodma) + return 1; + + if ((id->capability & 8) || (id->field_valid & 2)) + return 1; + + return 0; +} + +EXPORT_SYMBOL_GPL(ide_use_fast_pio); + /* * Standard (generic) timings for PIO modes, from ATA2 specification. * These timings are for access to the IDE data port register *only*. @@ -349,7 +364,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p int use_iordy = 0; struct hd_driveid* id = drive->id; int overridden = 0; - int blacklisted = 0; if (mode_wanted != 255) { pio_mode = mode_wanted; @@ -357,7 +371,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p pio_mode = 0; } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { overridden = 1; - blacklisted = 1; use_iordy = (pio_mode > 2); } else { pio_mode = id->tPIO; @@ -409,7 +422,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; d->use_iordy = use_iordy; d->overridden = overridden; - d->blacklisted = blacklisted; } return pio_mode; } @@ -462,8 +474,6 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) return -1; } -EXPORT_SYMBOL_GPL(ide_set_xfer_rate); - static void ide_dump_opcode(ide_drive_t *drive) { struct request *rq; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5a5c565a32a8..8afbd6cb94be 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -853,11 +853,11 @@ static void probe_hwif(ide_hwif_t *hwif) * things, if not checked and cleared. * PARANOIA!!! */ - hwif->ide_dma_off_quietly(drive); + hwif->dma_off_quietly(drive); #ifdef CONFIG_IDEDMA_ONLYDISK if (drive->media == ide_disk) #endif - hwif->ide_dma_check(drive); + ide_set_dma(drive); } } } @@ -1384,6 +1384,9 @@ static int hwif_init(ide_hwif_t *hwif) done: init_gendisk(hwif); + + ide_acpi_init(hwif); + hwif->present = 1; /* success */ return 1; diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index aa049dab3d95..afb71c66b6f3 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -26,7 +26,6 @@ #include <asm/uaccess.h> #include <linux/errno.h> -#include <linux/sched.h> #include <linux/proc_fs.h> #include <linux/stat.h> #include <linux/mm.h> @@ -413,7 +412,6 @@ void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void while (p->name != NULL) { ent = create_proc_entry(p->name, p->mode, dir); if (!ent) return; - ent->nlink = 1; ent->data = data; ent->read_proc = p->read_proc; ent->write_proc = p->write_proc; @@ -549,7 +547,7 @@ static int ide_drivers_open(struct inode *inode, struct file *file) return single_open(file, &ide_drivers_show, NULL); } -static struct file_operations ide_drivers_operations = { +static const struct file_operations ide_drivers_operations = { .open = ide_drivers_open, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index b3bcd1d7315e..4e59239fef75 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1970,7 +1970,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) printk(KERN_ERR "ide-tape: The tape wants to issue more " "interrupts in DMA mode\n"); printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); - (void)__ide_dma_off(drive); + ide_dma_off(drive); return ide_do_reset(drive); } /* Get the number of bytes to transfer on this interrupt. */ @@ -2176,7 +2176,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { printk(KERN_WARNING "ide-tape: DMA disabled, " "reverting to PIO\n"); - (void)__ide_dma_off(drive); + ide_dma_off(drive); } if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) dma_ok = !hwif->dma_setup(drive); @@ -4779,7 +4779,7 @@ static ide_driver_t idetape_driver = { /* * Our character device supporting functions, passed to register_chrdev. */ -static struct file_operations idetape_fops = { +static const struct file_operations idetape_fops = { .owner = THIS_MODULE, .read = idetape_chrdev_read, .write = idetape_chrdev_write, @@ -4792,15 +4792,10 @@ static int idetape_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; struct ide_tape_obj *tape; - ide_drive_t *drive; if (!(tape = ide_tape_get(disk))) return -ENXIO; - drive = tape->drive; - - drive->usage++; - return 0; } @@ -4808,9 +4803,6 @@ static int idetape_release(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; struct ide_tape_obj *tape = ide_tape_g(disk); - ide_drive_t *drive = tape->drive; - - drive->usage--; ide_tape_put(tape); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 6c9bd5165bdb..b3c0818c5c6c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -187,6 +187,12 @@ int noautodma = 1; EXPORT_SYMBOL(noautodma); +#ifdef CONFIG_BLK_DEV_IDEACPI +int ide_noacpi = 0; +int ide_noacpitfs = 1; +int ide_noacpionboot = 1; +#endif + /* * This is declared extern in ide.h, for access by other IDE modules: */ @@ -383,9 +389,8 @@ int ide_hwif_request_regions(ide_hwif_t *hwif) unsigned long addr; unsigned int i; - if (hwif->mmio == 2) + if (hwif->mmio) return 0; - BUG_ON(hwif->mmio == 1); addr = hwif->io_ports[IDE_CONTROL_OFFSET]; if (addr && !hwif_request_region(hwif, addr, 1)) goto control_region_busy; @@ -432,7 +437,7 @@ void ide_hwif_release_regions(ide_hwif_t *hwif) { u32 i = 0; - if (hwif->mmio == 2) + if (hwif->mmio) return; if (hwif->io_ports[IDE_CONTROL_OFFSET]) release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); @@ -501,23 +506,22 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->ide_dma_end = tmp_hwif->ide_dma_end; hwif->ide_dma_check = tmp_hwif->ide_dma_check; hwif->ide_dma_on = tmp_hwif->ide_dma_on; - hwif->ide_dma_off_quietly = tmp_hwif->ide_dma_off_quietly; + hwif->dma_off_quietly = tmp_hwif->dma_off_quietly; hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq; - hwif->ide_dma_host_on = tmp_hwif->ide_dma_host_on; - hwif->ide_dma_host_off = tmp_hwif->ide_dma_host_off; + hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq; + hwif->dma_host_on = tmp_hwif->dma_host_on; + hwif->dma_host_off = tmp_hwif->dma_host_off; hwif->ide_dma_lostirq = tmp_hwif->ide_dma_lostirq; hwif->ide_dma_timeout = tmp_hwif->ide_dma_timeout; hwif->OUTB = tmp_hwif->OUTB; hwif->OUTBSYNC = tmp_hwif->OUTBSYNC; hwif->OUTW = tmp_hwif->OUTW; - hwif->OUTL = tmp_hwif->OUTL; hwif->OUTSW = tmp_hwif->OUTSW; hwif->OUTSL = tmp_hwif->OUTSL; hwif->INB = tmp_hwif->INB; hwif->INW = tmp_hwif->INW; - hwif->INL = tmp_hwif->INL; hwif->INSW = tmp_hwif->INSW; hwif->INSL = tmp_hwif->INSL; @@ -545,7 +549,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->extra_ports = tmp_hwif->extra_ports; hwif->autodma = tmp_hwif->autodma; hwif->udma_four = tmp_hwif->udma_four; - hwif->no_dsc = tmp_hwif->no_dsc; hwif->hwif_data = tmp_hwif->hwif_data; } @@ -1132,12 +1135,11 @@ static int set_using_dma (ide_drive_t *drive, int arg) if (HWIF(drive)->ide_dma_check == NULL) return -EPERM; if (arg) { - if (HWIF(drive)->ide_dma_check(drive)) return -EIO; - if (HWIF(drive)->ide_dma_on(drive)) return -EIO; - } else { - if (__ide_dma_off(drive)) + if (ide_set_dma(drive)) return -EIO; - } + if (HWIF(drive)->ide_dma_on(drive)) return -EIO; + } else + ide_dma_off(drive); return 0; #else return -EPERM; @@ -1214,10 +1216,15 @@ EXPORT_SYMBOL(system_bus_clock); static int generic_ide_suspend(struct device *dev, pm_message_t mesg) { ide_drive_t *drive = dev->driver_data; + ide_hwif_t *hwif = HWIF(drive); struct request rq; struct request_pm_state rqpm; ide_task_t args; + /* Call ACPI _GTM only once */ + if (!(drive->dn % 2)) + ide_acpi_get_timing(hwif); + memset(&rq, 0, sizeof(rq)); memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); @@ -1235,10 +1242,17 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg) static int generic_ide_resume(struct device *dev) { ide_drive_t *drive = dev->driver_data; + ide_hwif_t *hwif = HWIF(drive); struct request rq; struct request_pm_state rqpm; ide_task_t args; + /* Call ACPI _STM only once */ + if (!(drive->dn % 2)) + ide_acpi_push_timing(hwif); + + ide_acpi_exec_tfs(drive); + memset(&rq, 0, sizeof(rq)); memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); @@ -1543,6 +1557,24 @@ static int __init ide_setup(char *s) } #endif /* CONFIG_BLK_DEV_IDEPCI */ +#ifdef CONFIG_BLK_DEV_IDEACPI + if (!strcmp(s, "ide=noacpi")) { + //printk(" : Disable IDE ACPI support.\n"); + ide_noacpi = 1; + return 1; + } + if (!strcmp(s, "ide=acpigtf")) { + //printk(" : Enable IDE ACPI _GTF support.\n"); + ide_noacpitfs = 0; + return 1; + } + if (!strcmp(s, "ide=acpionboot")) { + //printk(" : Call IDE ACPI methods on boot.\n"); + ide_noacpionboot = 0; + return 1; + } +#endif /* CONFIG_BLK_DEV_IDEACPI */ + /* * Look for drive options: "hdx=" */ diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c index 0391a3122878..1ed224a01f79 100644 --- a/drivers/ide/legacy/buddha.c +++ b/drivers/ide/legacy/buddha.c @@ -215,7 +215,7 @@ fail_base2: index = ide_register_hw(&hw, &hwif); if (index != -1) { - hwif->mmio = 2; + hwif->mmio = 1; printk("ide%d: ", index); switch(type) { case BOARD_BUDDHA: diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c index 64d42619ab06..dcfadbbf55d8 100644 --- a/drivers/ide/legacy/gayle.c +++ b/drivers/ide/legacy/gayle.c @@ -167,7 +167,7 @@ found: index = ide_register_hw(&hw, &hwif); if (index != -1) { - hwif->mmio = 2; + hwif->mmio = 1; switch (i) { case 0: printk("ide%d: Gayle IDE interface (A%d style)\n", index, diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index c48e87e512d3..19ccd006f205 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -143,16 +143,16 @@ static void ht6560b_selectproc (ide_drive_t *drive) current_timing = timing; if (drive->media != ide_disk || !drive->present) select |= HT_PREFETCH_MODE; - (void) HWIF(drive)->INB(HT_CONFIG_PORT); - (void) HWIF(drive)->INB(HT_CONFIG_PORT); - (void) HWIF(drive)->INB(HT_CONFIG_PORT); - (void) HWIF(drive)->INB(HT_CONFIG_PORT); - HWIF(drive)->OUTB(select, HT_CONFIG_PORT); + (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: */ - HWIF(drive)->OUTB(timing, IDE_SELECT_REG); - (void) HWIF(drive)->INB(IDE_STATUS_REG); + outb(timing, IDE_SELECT_REG); + (void)inb(IDE_STATUS_REG); #ifdef DEBUG printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, select, timing); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 7efd28ac21ed..a5023cdbdc58 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -34,7 +34,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/sched.h> #include <linux/ptrace.h> #include <linux/slab.h> #include <linux/string.h> diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index b1730d7e414c..4c0079ad52ac 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -141,7 +141,7 @@ void macide_init(void) } if (index != -1) { - hwif->mmio = 2; + hwif->mmio = 1; if (macintosh_config->ide_type == MAC_IDE_QUADRA) printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index); else if (macintosh_config->ide_type == MAC_IDE_PB) diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index 434a94faa3b7..74f08124eabb 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -145,7 +145,7 @@ void q40ide_init(void) index = ide_register_hw(&hw, &hwif); // **FIXME** if (index != -1) - hwif->mmio = 2; + hwif->mmio = 1; } } diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index c7854ea57b52..0a59d5ef1599 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -181,12 +181,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed) { int mem_sttime; int mem_stcfg; - unsigned long mode; - -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - if (ide_use_dma(drive)) - mode = ide_dma_speed(drive, 0); -#endif mem_sttime = 0; mem_stcfg = au_readl(MEM_STCFG2); @@ -195,7 +189,7 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed) auide_tune_drive(drive, speed - XFER_PIO_0); return 0; } - + switch(speed) { #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA case XFER_MW_DMA_2: @@ -207,7 +201,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed) mem_stcfg &= ~TOECS_MASK; mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS; - mode = XFER_MW_DMA_2; break; case XFER_MW_DMA_1: mem_sttime = SBC_IDE_TIMING(MDMA1); @@ -218,7 +211,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed) mem_stcfg &= ~TOECS_MASK; mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS; - mode = XFER_MW_DMA_1; break; case XFER_MW_DMA_0: mem_sttime = SBC_IDE_TIMING(MDMA0); @@ -229,14 +221,13 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed) mem_stcfg &= ~TOECS_MASK; mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS; - mode = XFER_MW_DMA_0; break; #endif default: return 1; } - - if (ide_config_drive_speed(drive, mode)) + + if (ide_config_drive_speed(drive, speed)) return 1; au_writel(mem_sttime,MEM_STTIME2); @@ -423,9 +414,9 @@ static int auide_dma_check(ide_drive_t *drive) speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA); if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) - return HWIF(drive)->ide_dma_on(drive); + return 0; - return HWIF(drive)->ide_dma_off_quietly(drive); + return -1; } static int auide_dma_test_irq(ide_drive_t *drive) @@ -447,27 +438,24 @@ static int auide_dma_test_irq(ide_drive_t *drive) return 0; } -static int auide_dma_host_on(ide_drive_t *drive) +static void auide_dma_host_on(ide_drive_t *drive) { - return 0; } static int auide_dma_on(ide_drive_t *drive) { drive->using_dma = 1; - return auide_dma_host_on(drive); -} + return 0; +} -static int auide_dma_host_off(ide_drive_t *drive) +static void auide_dma_host_off(ide_drive_t *drive) { - return 0; } -static int auide_dma_off_quietly(ide_drive_t *drive) +static void auide_dma_off_quietly(ide_drive_t *drive) { drive->using_dma = 0; - return auide_dma_host_off(drive); } static int auide_dma_lostirq(ide_drive_t *drive) @@ -717,7 +705,8 @@ static int au_ide_probe(struct device *dev) /* hold should be on in all cases */ hwif->hold = 1; - hwif->mmio = 2; + + hwif->mmio = 1; /* If the user has selected DDMA assisted copies, then set up a few local I/O function entry points @@ -732,7 +721,7 @@ static int au_ide_probe(struct device *dev) hwif->speedproc = &auide_tune_chipset; #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - hwif->ide_dma_off_quietly = &auide_dma_off_quietly; + hwif->dma_off_quietly = &auide_dma_off_quietly; hwif->ide_dma_timeout = &auide_dma_timeout; hwif->ide_dma_check = &auide_dma_check; @@ -741,8 +730,8 @@ static int au_ide_probe(struct device *dev) hwif->ide_dma_end = &auide_dma_end; hwif->dma_setup = &auide_dma_setup; hwif->ide_dma_test_irq = &auide_dma_test_irq; - hwif->ide_dma_host_off = &auide_dma_host_off; - hwif->ide_dma_host_on = &auide_dma_host_on; + hwif->dma_host_off = &auide_dma_host_off; + hwif->dma_host_on = &auide_dma_host_on; hwif->ide_dma_lostirq = &auide_dma_lostirq; hwif->ide_dma_on = &auide_dma_on; diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c index 09c9e7936b0d..81fa06851b27 100644 --- a/drivers/ide/mips/swarm.c +++ b/drivers/ide/mips/swarm.c @@ -115,7 +115,7 @@ static int __devinit swarm_ide_probe(struct device *dev) /* Setup MMIO ops. */ default_hwif_mmiops(hwif); /* Prevent resource map manipulation. */ - hwif->mmio = 2; + hwif->mmio = 1; hwif->noprobe = 0; for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile index fef08960aa4c..6591ff4753cb 100644 --- a/drivers/ide/pci/Makefile +++ b/drivers/ide/pci/Makefile @@ -9,9 +9,10 @@ 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_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o -#obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.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 @@ -26,6 +27,7 @@ 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 diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index d261bfbad222..990eafe5ea11 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -94,9 +94,9 @@ static u8 aec62xx_ratemask (ide_drive_t *drive) switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_ARTOP_ATP865: case PCI_DEVICE_ID_ARTOP_ATP865R: - mode = (hwif->INB(((hwif->channel) ? - hwif->mate->dma_status : - hwif->dma_status)) & 0x10) ? 4 : 3; + mode = (inb(hwif->channel ? + hwif->mate->dma_status : + hwif->dma_status) & 0x10) ? 4 : 3; break; case PCI_DEVICE_ID_ARTOP_ATP860: case PCI_DEVICE_ID_ARTOP_ATP860R: @@ -209,25 +209,13 @@ static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - - if ((id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - - goto fast_ata_pio; + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) aec62xx_tune_drive(drive, 5); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + + return -1; } static int aec62xx_irq_timeout (ide_drive_t *drive) @@ -286,10 +274,8 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) hwif->tuneproc = &aec62xx_tune_drive; hwif->speedproc = &aec62xx_tune_chipset; - if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) hwif->serialized = hwif->channel; - hwif->no_dsc = 1; - } if (hwif->mate) hwif->mate->serialized = hwif->serialized; diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 68df77ec502b..4debd18d52f8 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -507,17 +507,15 @@ static int config_chipset_for_dma (ide_drive_t *drive) * * Configure a drive for DMA operation. If DMA is not possible we * drop the drive into PIO mode instead. - * - * FIXME: exactly what are we trying to return here */ - + static int ali15x3_config_drive_for_dma(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) - return hwif->ide_dma_off_quietly(drive); + goto no_dma_set; drive->init_speed = 0; @@ -552,9 +550,10 @@ try_dma_modes: ata_pio: hwif->tuneproc(drive, 255); no_dma_set: - return hwif->ide_dma_off_quietly(drive); + return -1; } - return hwif->ide_dma_on(drive); + + return 0; } /** @@ -852,8 +851,8 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) { if (m5229_revision < 0x20) return; - if (!(hwif->channel)) - hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2); + if (!hwif->channel) + outb(inb(dmabase + 2) & 0x60, dmabase + 2); ide_setup_dma(hwif, dmabase, 8); } diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index a4336995a410..7989bdd842a2 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -304,8 +304,9 @@ static int amd74xx_ide_dma_check(ide_drive_t *drive) amd_set_drive(drive, speed); if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) - return HWIF(drive)->ide_dma_on(drive); - return HWIF(drive)->ide_dma_off_quietly(drive); + return 0; + + return -1; } /* diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 982ac31fa995..2d48af32e3f4 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -101,7 +101,7 @@ static u8 atiixp_dma_2_pio(u8 xfer_rate) { } } -static int atiixp_ide_dma_host_on(ide_drive_t *drive) +static void atiixp_dma_host_on(ide_drive_t *drive) { struct pci_dev *dev = drive->hwif->pci_dev; unsigned long flags; @@ -118,10 +118,10 @@ static int atiixp_ide_dma_host_on(ide_drive_t *drive) spin_unlock_irqrestore(&atiixp_lock, flags); - return __ide_dma_host_on(drive); + ide_dma_host_on(drive); } -static int atiixp_ide_dma_host_off(ide_drive_t *drive) +static void atiixp_dma_host_off(ide_drive_t *drive) { struct pci_dev *dev = drive->hwif->pci_dev; unsigned long flags; @@ -135,7 +135,7 @@ static int atiixp_ide_dma_host_off(ide_drive_t *drive) spin_unlock_irqrestore(&atiixp_lock, flags); - return __ide_dma_host_off(drive); + ide_dma_host_off(drive); } /** @@ -235,11 +235,8 @@ static int atiixp_config_drive_for_dma(ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive)); - /* If no DMA speed was available then disable DMA and use PIO. */ - if (!speed) { - u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); - speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0; - } + if (!speed) + return 0; (void) atiixp_speedproc(drive, speed); return ide_dma_enable(drive); @@ -255,30 +252,20 @@ static int atiixp_config_drive_for_dma(ide_drive_t *drive) static int atiixp_dma_check(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; u8 tspeed, speed; drive->init_speed = 0; - if ((id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (atiixp_config_drive_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - - goto fast_ata_pio; + if (ide_use_dma(drive) && atiixp_config_drive_for_dma(drive)) + return 0; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) { tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0; - hwif->speedproc(drive, speed); - return hwif->ide_dma_off_quietly(drive); + atiixp_speedproc(drive, speed); } - /* IORDY not supported */ - return 0; + + return -1; } /** @@ -318,8 +305,8 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) else hwif->udma_four = 0; - hwif->ide_dma_host_on = &atiixp_ide_dma_host_on; - hwif->ide_dma_host_off = &atiixp_ide_dma_host_off; + hwif->dma_host_on = &atiixp_dma_host_on; + hwif->dma_host_off = &atiixp_dma_host_off; hwif->ide_dma_check = &atiixp_dma_check; if (!noautodma) hwif->autodma = 1; diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index aee947e8fc38..49df27513da7 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -466,36 +466,21 @@ static int config_chipset_for_dma (ide_drive_t *drive) if (!speed) return 0; - if(ide_set_xfer_rate(drive, speed)) - return 0; - - if (!drive->init_speed) - drive->init_speed = speed; + if (cmd64x_tune_chipset(drive, speed)) + return 0; return ide_dma_enable(drive); } static int cmd64x_config_drive_for_dma (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - - if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - - goto fast_ata_pio; + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) config_chipset_for_pio(drive, 1); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + + return -1; } static int cmd64x_alt_dma_status (struct pci_dev *dev) @@ -518,13 +503,13 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive) drive->waiting_for_dma = 0; /* read DMA command state */ - dma_cmd = hwif->INB(hwif->dma_command); + dma_cmd = inb(hwif->dma_command); /* stop DMA */ - hwif->OUTB((dma_cmd & ~1), hwif->dma_command); + outb(dma_cmd & ~1, hwif->dma_command); /* get DMA status */ - dma_stat = hwif->INB(hwif->dma_status); + dma_stat = inb(hwif->dma_status); /* clear the INTR & ERROR bits */ - hwif->OUTB(dma_stat|6, hwif->dma_status); + outb(dma_stat | 6, hwif->dma_status); if (cmd64x_alt_dma_status(dev)) { u8 dma_intr = 0; u8 dma_mask = (hwif->channel) ? ARTTIM23_INTR_CH1 : @@ -546,7 +531,7 @@ static int cmd64x_ide_dma_test_irq (ide_drive_t *drive) struct pci_dev *dev = hwif->pci_dev; u8 dma_alt_stat = 0, mask = (hwif->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; - u8 dma_stat = hwif->INB(hwif->dma_status); + u8 dma_stat = inb(hwif->dma_status); (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat); #ifdef DEBUG @@ -576,13 +561,13 @@ static int cmd646_1_ide_dma_end (ide_drive_t *drive) drive->waiting_for_dma = 0; /* get DMA status */ - dma_stat = hwif->INB(hwif->dma_status); + dma_stat = inb(hwif->dma_status); /* read DMA command state */ - dma_cmd = hwif->INB(hwif->dma_command); + dma_cmd = inb(hwif->dma_command); /* stop DMA */ - hwif->OUTB((dma_cmd & ~1), hwif->dma_command); + outb(dma_cmd & ~1, hwif->dma_command); /* clear the INTR & ERROR bits */ - hwif->OUTB(dma_stat|6, hwif->dma_status); + outb(dma_stat | 6, hwif->dma_status); /* and free any DMA resources */ ide_destroy_dmatable(drive); /* verify good DMA status */ diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index ba6786aabf3b..400859a839f7 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -132,12 +132,11 @@ static void cs5520_tune_drive(ide_drive_t *drive, u8 pio) static int cs5520_config_drive_xfer_rate(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - /* Tune the drive for PIO modes up to PIO 4 */ cs5520_tune_drive(drive, 4); + /* Then tell the core to use DMA operations */ - return hwif->ide_dma_on(drive); + return 0; } /* diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index 9bf5fdfc5b1f..b2d7c132ef4b 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -81,8 +81,8 @@ static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autot pio = ide_get_best_pio_mode(drive, pio, 4, NULL); if (!cs5530_set_xfer_mode(drive, modes[pio])) { - format = (hwif->INL(basereg+4) >> 31) & 1; - hwif->OUTL(cs5530_pio_timings[format][pio], + format = (inl(basereg + 4) >> 31) & 1; + outl(cs5530_pio_timings[format][pio], basereg+(drive->select.b.unit<<3)); } } @@ -103,16 +103,13 @@ static int cs5530_config_dma (ide_drive_t *drive) int unit = drive->select.b.unit; ide_drive_t *mate = &hwif->drives[unit^1]; struct hd_driveid *id = drive->id; - unsigned int reg, timings; + unsigned int reg, timings = 0; unsigned long basereg; /* * Default to DMA-off in case we run into trouble here. */ - hwif->ide_dma_off_quietly(drive); - /* turn off DMA while we fiddle */ - hwif->ide_dma_host_off(drive); - /* clear DMA_capable bit */ + hwif->dma_off_quietly(drive); /* * The CS5530 specifies that two drives sharing a cable cannot @@ -182,30 +179,24 @@ static int cs5530_config_dma (ide_drive_t *drive) case XFER_MW_DMA_1: timings = 0x00012121; break; case XFER_MW_DMA_2: timings = 0x00002020; break; default: - printk(KERN_ERR "%s: cs5530_config_dma: huh? mode=%02x\n", - drive->name, mode); - return 1; /* failure */ + BUG(); + break; } basereg = CS5530_BASEREG(hwif); - reg = hwif->INL(basereg+4); /* get drive0 config register */ + reg = inl(basereg + 4); /* get drive0 config register */ timings |= reg & 0x80000000; /* preserve PIO format bit */ if (unit == 0) { /* are we configuring drive0? */ - hwif->OUTL(timings, basereg+4); /* write drive0 config register */ + 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 */ - hwif->OUTL(reg, basereg+4); /* write drive0 config register */ - hwif->OUTL(timings, basereg+12); /* write drive1 config register */ + outl(reg, basereg + 4); /* write drive0 config register */ + outl(timings, basereg + 12); /* write drive1 config register */ } - (void) hwif->ide_dma_host_on(drive); - /* set DMA_capable bit */ - /* - * Finally, turn DMA on in software, and exit. - */ - return hwif->ide_dma_on(drive); /* success */ + return 0; /* success */ } /** @@ -321,17 +312,17 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) hwif->tuneproc = &cs5530_tuneproc; basereg = CS5530_BASEREG(hwif); - d0_timings = hwif->INL(basereg+0); + d0_timings = inl(basereg + 0); if (CS5530_BAD_PIO(d0_timings)) { /* PIO timings not initialized? */ - hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); + outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0); if (!hwif->drives[0].autotune) hwif->drives[0].autotune = 1; /* needs autotuning later */ } - if (CS5530_BAD_PIO(hwif->INL(basereg+8))) { - /* PIO timings not initialized? */ - hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); + if (CS5530_BAD_PIO(inl(basereg + 8))) { + /* PIO timings not initialized? */ + outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8); if (!hwif->drives[1].autotune) hwif->drives[1].autotune = 1; /* needs autotuning later */ diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c index 5c5aec28e671..45f43efbf92c 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -195,28 +195,19 @@ static int cs5535_config_drive_for_dma(ide_drive_t *drive) static int cs5535_dma_check(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct hd_driveid *id = drive->id; u8 speed; drive->init_speed = 0; - if ((id->capability & 1) && drive->autodma) { - if (ide_use_dma(drive)) { - if (cs5535_config_drive_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - - goto fast_ata_pio; + if (ide_use_dma(drive) && cs5535_config_drive_for_dma(drive)) + return 0; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) { speed = ide_get_best_pio_mode(drive, 255, 4, NULL); cs5535_set_drive(drive, speed); - return hwif->ide_dma_off_quietly(drive); } - /* IORDY not supported */ - return 0; + + return -1; } static u8 __devinit cs5535_cable_detect(struct pci_dev *dev) diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index 9eafcbf444f4..103b9db97853 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -197,8 +197,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) #if CY82C693_DEBUG_LOGS /* for debug let's show the previous values */ - HWIF(drive)->OUTB(index, CY82_INDEX_PORT); - data = HWIF(drive)->INB(CY82_DATA_PORT); + outb(index, CY82_INDEX_PORT); + data = inb(CY82_DATA_PORT); printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, @@ -207,8 +207,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) data = (u8)mode|(u8)(single<<2); - HWIF(drive)->OUTB(index, CY82_INDEX_PORT); - HWIF(drive)->OUTB(data, CY82_DATA_PORT); + 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", @@ -227,8 +227,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) */ data = BUSMASTER_TIMEOUT; - HWIF(drive)->OUTB(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); - HWIF(drive)->OUTB(data, CY82_DATA_PORT); + 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", @@ -478,21 +478,18 @@ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) } } -static ide_pci_device_t cy82c693_chipsets[] __devinitdata = { - { /* 0 */ - .name = "CY82C693", - .init_chipset = init_chipset_cy82c693, - .init_iops = init_iops_cy82c693, - .init_hwif = init_hwif_cy82c693, - .channels = 1, - .autodma = AUTODMA, - .bootable = ON_BOARD, - } +static ide_pci_device_t cy82c693_chipset __devinitdata = { + .name = "CY82C693", + .init_chipset = init_chipset_cy82c693, + .init_iops = init_iops_cy82c693, + .init_hwif = init_hwif_cy82c693, + .channels = 1, + .autodma = AUTODMA, + .bootable = ON_BOARD, }; static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d = &cy82c693_chipsets[id->driver_data]; struct pci_dev *dev2; int ret = -ENODEV; @@ -501,7 +498,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && PCI_FUNC(dev->devfn) == 1) { dev2 = pci_get_slot(dev->bus, dev->devfn + 1); - ret = ide_setup_pci_devices(dev, dev2, d); + ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset); /* We leak pci refs here but thats ok - we can't be unloaded */ } return ret; diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c new file mode 100644 index 000000000000..e2672fc65d30 --- /dev/null +++ b/drivers/ide/pci/delkin_cb.c @@ -0,0 +1,140 @@ +/* + * linux/drivers/ide/pci/delkin_cb.c + * + * Created 20 Oct 2004 by Mark Lord + * + * Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter + * + * Modeled after the 16-bit PCMCIA driver: ide-cs.c + * + * This is slightly peculiar, in that it is a PCI driver, + * but is NOT an IDE PCI driver -- the IDE layer does not directly + * support hot insertion/removal of PCI interfaces, so this driver + * is unable to use the IDE PCI interfaces. Instead, it uses the + * same interfaces as the ide-cs (PCMCIA) driver uses. + * On the plus side, the driver is also smaller/simpler this way. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ +#include <linux/autoconf.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/blkdev.h> +#include <linux/hdreg.h> +#include <linux/ide.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <asm/io.h> + +/* + * 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 int __devinit +delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + unsigned long base; + hw_regs_t hw; + ide_hwif_t *hwif = NULL; + ide_drive_t *drive; + int i, rc; + + 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); + 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); + } + pci_release_regions(dev); /* IDE layer handles regions itself */ + + memset(&hw, 0, sizeof(hw)); + ide_std_init_ports(&hw, base + 0x10, base + 0x1e); + hw.irq = dev->irq; + hw.chipset = ide_pci; /* this enables IRQ sharing */ + + rc = ide_register_hw_with_fixup(&hw, &hwif, ide_undecoded_slave); + if (rc < 0) { + printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); + pci_disable_device(dev); + return -ENODEV; + } + pci_set_drvdata(dev, hwif); + hwif->pci_dev = dev; + drive = &hwif->drives[0]; + if (drive->present) { + drive->io_32bit = 1; + drive->unmask = 1; + } + return 0; +} + +static void +delkin_cb_remove (struct pci_dev *dev) +{ + ide_hwif_t *hwif = pci_get_drvdata(dev); + + if (hwif) + ide_unregister(hwif->index); + pci_disable_device(dev); +} + +static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = { + { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl); + +static struct pci_driver driver = { + .name = "Delkin-ASKA-Workbit Cardbus IDE", + .id_table = delkin_cb_pci_tbl, + .probe = delkin_cb_probe, + .remove = delkin_cb_remove, +}; + +static int +delkin_cb_init (void) +{ + return pci_module_init(&driver); +} + +static void +delkin_cb_exit (void) +{ + pci_unregister_driver(&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/hpt34x.c b/drivers/ide/pci/hpt34x.c index ce7b08f08a09..924eaa3a5708 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -48,19 +48,6 @@ static u8 hpt34x_ratemask (ide_drive_t *drive) return 1; } -static void hpt34x_clear_chipset (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - u32 reg1 = 0, tmp1 = 0, reg2 = 0, tmp2 = 0; - - pci_read_config_dword(dev, 0x44, ®1); - pci_read_config_dword(dev, 0x48, ®2); - tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); - tmp2 = (reg2 & ~(0x11 << drive->dn)); - pci_write_config_dword(dev, 0x44, tmp1); - pci_write_config_dword(dev, 0x48, tmp2); -} - static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed) { struct pci_dev *dev = HWIF(drive)->pci_dev; @@ -81,7 +68,7 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed) pci_read_config_dword(dev, 0x44, ®1); pci_read_config_dword(dev, 0x48, ®2); tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); - tmp2 = ((hi_speed << drive->dn) | reg2); + tmp2 = ((hi_speed << drive->dn) | (reg2 & ~(0x11 << drive->dn))); pci_write_config_dword(dev, 0x44, tmp1); pci_write_config_dword(dev, 0x48, tmp2); @@ -99,7 +86,6 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed) static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - hpt34x_clear_chipset(drive); (void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio)); } @@ -117,38 +103,25 @@ static int config_chipset_for_dma (ide_drive_t *drive) if (!(speed)) return 0; - hpt34x_clear_chipset(drive); (void) hpt34x_tune_chipset(drive, speed); return ide_dma_enable(drive); } static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) #ifndef CONFIG_HPT34X_AUTODMA - return hwif->ide_dma_off_quietly(drive); + return -1; #else - return hwif->ide_dma_on(drive); + return 0; #endif - } - - goto fast_ata_pio; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) hpt34x_tune_drive(drive, 255); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + + return -1; } /* @@ -209,7 +182,6 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif) hwif->tuneproc = &hpt34x_tune_drive; hwif->speedproc = &hpt34x_tune_chipset; - hwif->no_dsc = 1; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index b486442dd5d7..60ecdc258c7c 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 + * linux/drivers/ide/pci/hpt366.c Version 1.01 Dec 23, 2006 * * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -60,13 +60,10 @@ * 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 - * - avoid calibrating PLL twice as the second time results in a wrong PCI - * frequency and thus in the wrong timings for the secondary channel - * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not - * allow for this speed anyway) - * - add support for HPT302N and HPT371N clocking (the same as for HPT372N) - * - HPT371/N are single channel chips, so avoid touching the primary channel - * which exists only virtually (there's no pins for it) + * - 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 @@ -76,11 +73,47 @@ * 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 - * <source@mvista.com> - * + * - 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 rate masking/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 two HPT37x speedproc handlers, fix the 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 + * supported DMA 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 + * - 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 + * Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com> */ - #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> @@ -332,93 +365,159 @@ static u32 sixty_six_base_hpt37x[] = { }; #define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT374_ALLOW_ATA133_6 0 -#define HPT371_ALLOW_ATA133_6 0 -#define HPT302_ALLOW_ATA133_6 0 -#define HPT372_ALLOW_ATA133_6 0 -#define HPT370_ALLOW_ATA100_5 1 +#define HPT374_ALLOW_ATA133_6 1 +#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 -#define F_LOW_PCI_33 0x23 -#define F_LOW_PCI_40 0x29 -#define F_LOW_PCI_50 0x2d -#define F_LOW_PCI_66 0x42 +/* 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 +}; /* - * Hold all the highpoint quirks and revision information in one - * place. + * Hold all the HighPoint chip information in one place. */ -struct hpt_info -{ +struct hpt_info { + u8 chip_type; /* Chip type */ u8 max_mode; /* Speeds allowed */ - int revision; /* Chipset revision */ - int flags; /* Chipset properties */ -#define PLL_MODE 1 -#define IS_3xxN 2 -#define PCI_66MHZ 4 - /* Speed table */ - u32 *speed; + u8 dpll_clk; /* DPLL clock in MHz */ + u8 pci_clk; /* PCI clock in MHz */ + u32 **settings; /* Chipset settings table */ }; -/* - * This wants fixing so that we do everything not by classrev - * (which breaks on the newest chips) but by creating an - * enumeration of chip variants and using that - */ +/* Supported HighPoint chips */ +enum { + HPT36x, + HPT370, + HPT370A, + HPT374, + HPT372, + HPT372A, + HPT302, + HPT371, + HPT372N, + HPT302N, + HPT371N +}; + +static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = { + twenty_five_base_hpt36x, + thirty_three_base_hpt36x, + forty_base_hpt36x, + NULL, + NULL +}; + +static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = { + NULL, + thirty_three_base_hpt37x, + NULL, + fifty_base_hpt37x, + sixty_six_base_hpt37x +}; + +static struct hpt_info hpt36x __devinitdata = { + .chip_type = HPT36x, + .max_mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1, + .dpll_clk = 0, /* no DPLL */ + .settings = hpt36x_settings +}; + +static struct hpt_info hpt370 __devinitdata = { + .chip_type = HPT370, + .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2, + .dpll_clk = 48, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt370a __devinitdata = { + .chip_type = HPT370A, + .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2, + .dpll_clk = 48, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt374 __devinitdata = { + .chip_type = HPT374, + .max_mode = HPT374_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 48, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt372 __devinitdata = { + .chip_type = HPT372, + .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 55, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt372a __devinitdata = { + .chip_type = HPT372A, + .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 66, + .settings = hpt37x_settings +}; -static __devinit u32 hpt_revision (struct pci_dev *dev) +static struct hpt_info hpt302 __devinitdata = { + .chip_type = HPT302, + .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 66, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt371 __devinitdata = { + .chip_type = HPT371, + .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 66, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt372n __devinitdata = { + .chip_type = HPT372N, + .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 77, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt302n __devinitdata = { + .chip_type = HPT302N, + .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 77, +}; + +static struct hpt_info hpt371n __devinitdata = { + .chip_type = HPT371N, + .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 77, + .settings = hpt37x_settings +}; + +static int check_in_drive_list(ide_drive_t *drive, const char **list) { - u32 class_rev; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - switch(dev->device) { - /* Remap new 372N onto 372 */ - case PCI_DEVICE_ID_TTI_HPT372N: - class_rev = PCI_DEVICE_ID_TTI_HPT372; break; - case PCI_DEVICE_ID_TTI_HPT374: - class_rev = PCI_DEVICE_ID_TTI_HPT374; break; - case PCI_DEVICE_ID_TTI_HPT371: - class_rev = PCI_DEVICE_ID_TTI_HPT371; break; - case PCI_DEVICE_ID_TTI_HPT302: - class_rev = PCI_DEVICE_ID_TTI_HPT302; break; - case PCI_DEVICE_ID_TTI_HPT372: - class_rev = PCI_DEVICE_ID_TTI_HPT372; break; - default: - break; - } - return class_rev; -} + struct hd_driveid *id = drive->id; -static int check_in_drive_lists(ide_drive_t *drive, const char **list); + while (*list) + if (!strcmp(*list++,id->model)) + return 1; + return 0; +} -static u8 hpt3xx_ratemask (ide_drive_t *drive) +static u8 hpt3xx_ratemask(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 mode = 0; - - /* FIXME: TODO - move this to set info->mode once at boot */ - - if (info->revision >= 8) { /* HPT374 */ - mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 7) { /* HPT371 */ - mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 6) { /* HPT302 */ - mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 5) { /* HPT372 */ - mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 4) { /* HPT370A */ - mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; - } else if (info->revision >= 3) { /* HPT370 */ - mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; - mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode; - } else { /* HPT366 and HPT368 */ - mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2; - } + struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); + u8 mode = info->max_mode; + if (!eighty_ninty_three(drive) && mode) mode = min(mode, (u8)1); return mode; @@ -429,75 +528,61 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive) * either PIO or UDMA modes 0,4,5 */ -static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) +static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); + u8 chip_type = info->chip_type; u8 mode = hpt3xx_ratemask(drive); if (drive->media != ide_disk) return min(speed, (u8)XFER_PIO_4); - switch(mode) { + switch (mode) { case 0x04: - speed = min(speed, (u8)XFER_UDMA_6); + speed = min_t(u8, speed, XFER_UDMA_6); break; case 0x03: - speed = min(speed, (u8)XFER_UDMA_5); - if (info->revision >= 5) + speed = min_t(u8, speed, XFER_UDMA_5); + if (chip_type >= HPT374) break; - if (check_in_drive_lists(drive, bad_ata100_5)) - speed = min(speed, (u8)XFER_UDMA_4); - break; + if (!check_in_drive_list(drive, bad_ata100_5)) + goto check_bad_ata33; + /* fall thru */ case 0x02: - speed = min(speed, (u8)XFER_UDMA_4); - /* - * CHECK ME, Does this need to be set to 5 ?? - */ - if (info->revision >= 3) - break; - if ((check_in_drive_lists(drive, bad_ata66_4)) || - (!(HPT366_ALLOW_ATA66_4))) - speed = min(speed, (u8)XFER_UDMA_3); - if ((check_in_drive_lists(drive, bad_ata66_3)) || - (!(HPT366_ALLOW_ATA66_3))) - speed = min(speed, (u8)XFER_UDMA_2); - break; + speed = min_t(u8, speed, XFER_UDMA_4); + + /* + * CHECK ME, Does this need to be changed to HPT374 ?? + */ + if (chip_type >= HPT370) + goto check_bad_ata33; + if (HPT366_ALLOW_ATA66_4 && + !check_in_drive_list(drive, bad_ata66_4)) + goto check_bad_ata33; + + speed = min_t(u8, speed, XFER_UDMA_3); + if (HPT366_ALLOW_ATA66_3 && + !check_in_drive_list(drive, bad_ata66_3)) + goto check_bad_ata33; + /* fall thru */ case 0x01: - speed = min(speed, (u8)XFER_UDMA_2); - /* - * CHECK ME, Does this need to be set to 5 ?? - */ - if (info->revision >= 3) + speed = min_t(u8, speed, XFER_UDMA_2); + + check_bad_ata33: + if (chip_type >= HPT370A) break; - if (check_in_drive_lists(drive, bad_ata33)) - speed = min(speed, (u8)XFER_MW_DMA_2); - break; + if (!check_in_drive_list(drive, bad_ata33)) + break; + /* fall thru */ case 0x00: default: - speed = min(speed, (u8)XFER_MW_DMA_2); + speed = min_t(u8, speed, XFER_MW_DMA_2); break; } return speed; } -static int check_in_drive_lists (ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (quirk_drives == list) { - while (*list) - if (strstr(id->model, *list++)) - return 1; - } else { - while (*list) - if (!strcmp(*list++,id->model)) - return 1; - } - return 0; -} - -static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) +static u32 get_speed_setting(u8 speed, struct hpt_info *info) { int i; @@ -510,260 +595,201 @@ static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) if (xfer_speeds[i] == speed) break; - return chipset_table[i]; + /* + * NOTE: info->settings only points to the pointer + * to the list of the actual register values + */ + return (*info->settings)[i]; } static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; - u8 regfast = (hwif->channel) ? 0x55 : 0x51; - u8 drive_fast = 0; - u32 reg1 = 0, reg2 = 0; - - /* - * Disable the "fast interrupt" prediction. - */ - pci_read_config_byte(dev, regfast, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, regfast, drive_fast & ~0x80); - - reg2 = pci_bus_clock_list(speed, info->speed); + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = pci_get_drvdata(dev); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 itr_addr = drive->dn ? 0x44 : 0x40; + u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : + (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); + u32 new_itr = get_speed_setting(speed, info); + u32 old_itr = 0; /* - * Disable on-chip PIO FIFO/buffer - * (to avoid problems handling I/O errors later) + * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) + * to avoid problems handling I/O errors later */ - pci_read_config_dword(dev, regtime, ®1); - if (speed >= XFER_MW_DMA_0) { - reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); - } else { - reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000); - } - reg2 &= ~0x80000000; + pci_read_config_dword(dev, itr_addr, &old_itr); + new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); + new_itr &= ~0xc0000000; - pci_write_config_dword(dev, regtime, reg2); + pci_write_config_dword(dev, itr_addr, new_itr); return ide_config_drive_speed(drive, speed); } -static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) +static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; - u8 drive_pci = 0x40 + (drive->dn * 4); - u8 new_fast = 0, drive_fast = 0; - u32 list_conf = 0, drive_conf = 0; - u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; - - /* - * Disable the "fast interrupt" prediction. - * don't holdoff on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, regfast, &drive_fast); - new_fast = drive_fast; - if (new_fast & 0x02) - new_fast &= ~0x02; - -#ifdef HPT_DELAY_INTERRUPT - if (new_fast & 0x01) - new_fast &= ~0x01; -#else - if ((new_fast & 0x01) == 0) - new_fast |= 0x01; -#endif - if (new_fast != drive_fast) - pci_write_config_byte(dev, regfast, new_fast); - - list_conf = pci_bus_clock_list(speed, info->speed); - - pci_read_config_dword(dev, drive_pci, &drive_conf); - list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = pci_get_drvdata(dev); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 itr_addr = 0x40 + (drive->dn * 4); + u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : + (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); + u32 new_itr = get_speed_setting(speed, info); + u32 old_itr = 0; + + pci_read_config_dword(dev, itr_addr, &old_itr); + new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); if (speed < XFER_MW_DMA_0) - list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, drive_pci, list_conf); + new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + pci_write_config_dword(dev, itr_addr, new_itr); return ide_config_drive_speed(drive, speed); } -static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) +static int hpt3xx_tune_chipset(ide_drive_t *drive, u8 speed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; - u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4); - u32 list_conf = 0, drive_conf = 0; - u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; - - /* - * Disable the "fast interrupt" prediction. - * don't holdoff on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, regfast, &drive_fast); - drive_fast &= ~0x07; - pci_write_config_byte(dev, regfast, drive_fast); - - list_conf = pci_bus_clock_list(speed, info->speed); - pci_read_config_dword(dev, drive_pci, &drive_conf); - list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); - if (speed < XFER_MW_DMA_0) - list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, drive_pci, list_conf); - - return ide_config_drive_speed(drive, speed); -} + ide_hwif_t *hwif = HWIF(drive); + struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); -static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); - - if (info->revision >= 8) - return hpt372_tune_chipset(drive, speed); /* not a typo */ - else if (info->revision >= 5) - return hpt372_tune_chipset(drive, speed); - else if (info->revision >= 3) - return hpt370_tune_chipset(drive, speed); + if (info->chip_type >= HPT370) + return hpt37x_tune_chipset(drive, speed); else /* hpt368: hpt_minimum_revision(dev, 2) */ return hpt36x_tune_chipset(drive, speed); } -static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio) +static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio) { - pio = ide_get_best_pio_mode(drive, 255, pio, NULL); - (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio)); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio); } /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initially for designed for + * after the drive is reported by the OS. Initially designed for * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. * - * check_in_drive_lists(drive, bad_ata66_4) - * check_in_drive_lists(drive, bad_ata66_3) - * check_in_drive_lists(drive, bad_ata33) - * */ -static int config_chipset_for_dma (ide_drive_t *drive) +static int config_chipset_for_dma(ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); if (!speed) return 0; - /* If we don't have any timings we can't do a lot */ - if (info->speed == NULL) - return 0; - (void) hpt3xx_tune_chipset(drive, speed); return ide_dma_enable(drive); } -static int hpt3xx_quirkproc (ide_drive_t *drive) +static int hpt3xx_quirkproc(ide_drive_t *drive) { - return ((int) check_in_drive_lists(drive, quirk_drives)); + struct hd_driveid *id = drive->id; + const char **list = quirk_drives; + + while (*list) + if (strstr(id->model, *list++)) + return 1; + return 0; } -static void hpt3xx_intrproc (ide_drive_t *drive) +static void hpt3xx_intrproc(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); if (drive->quirk_list) return; /* drives in the quirk_list may not like intr setups/cleanups */ - hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); + hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); } -static void hpt3xx_maskproc (ide_drive_t *drive, int mask) +static void hpt3xx_maskproc(ide_drive_t *drive, int mask) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); - struct pci_dev *dev = hwif->pci_dev; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = pci_get_drvdata(dev); if (drive->quirk_list) { - if (info->revision >= 3) { - u8 reg5a = 0; - pci_read_config_byte(dev, 0x5a, ®5a); - if (((reg5a & 0x10) >> 4) != mask) - pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); + 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) { + if (mask) disable_irq(hwif->irq); - } else { - enable_irq(hwif->irq); - } + else + enable_irq (hwif->irq); } - } else { - if (IDE_CONTROL_REG) - hwif->OUTB(mask ? (drive->ctl | 2) : - (drive->ctl & ~2), - IDE_CONTROL_REG); - } + } else + hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2), + IDE_CONTROL_REG); } -static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) +static int hpt366_config_drive_xfer_rate(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct hd_driveid *id = drive->id; - drive->init_speed = 0; - if ((id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - goto fast_ata_pio; + if (ide_use_fast_pio(drive)) + hpt3xx_tune_drive(drive, 255); - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - hpt3xx_tune_drive(drive, 5); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + return -1; } /* - * This is specific to the HPT366 UDMA bios chipset + * This is specific to the HPT366 UDMA chipset * by HighPoint|Triones Technologies, Inc. */ -static int hpt366_ide_dma_lostirq (ide_drive_t *drive) +static int hpt366_ide_dma_lostirq(ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 reg50h = 0, reg52h = 0, reg5ah = 0; - - pci_read_config_byte(dev, 0x50, ®50h); - pci_read_config_byte(dev, 0x52, ®52h); - pci_read_config_byte(dev, 0x5a, ®5ah); - printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", - drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); - if (reg5ah & 0x10) - pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); + struct pci_dev *dev = HWIF(drive)->pci_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, __FUNCTION__, mcr1, mcr3, scr1); + if (scr1 & 0x10) + pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); return __ide_dma_lostirq(drive); } -static void hpt370_clear_engine (ide_drive_t *drive) +static void hpt370_clear_engine(ide_drive_t *drive) { - u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50; - pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37); + ide_hwif_t *hwif = HWIF(drive); + + pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37); udelay(10); } +static void hpt370_irq_timeout(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u16 bfifo = 0; + u8 dma_cmd; + + pci_read_config_word(hwif->pci_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 = hwif->INB(hwif->dma_command); + /* stop DMA */ + hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command); + hpt370_clear_engine(drive); +} + static void hpt370_ide_dma_start(ide_drive_t *drive) { #ifdef HPT_RESET_STATE_ENGINE @@ -772,72 +798,43 @@ static void hpt370_ide_dma_start(ide_drive_t *drive) ide_dma_start(drive); } -static int hpt370_ide_dma_end (ide_drive_t *drive) +static int hpt370_ide_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - u8 dma_stat = hwif->INB(hwif->dma_status); + u8 dma_stat = hwif->INB(hwif->dma_status); if (dma_stat & 0x01) { /* wait a little */ udelay(20); dma_stat = hwif->INB(hwif->dma_status); + if (dma_stat & 0x01) + hpt370_irq_timeout(drive); } - if ((dma_stat & 0x01) != 0) - /* fallthrough */ - (void) HWIF(drive)->ide_dma_timeout(drive); - return __ide_dma_end(drive); } -static void hpt370_lostirq_timeout (ide_drive_t *drive) +static int hpt370_ide_dma_timeout(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52; - u8 dma_stat = 0, dma_cmd = 0; - - pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo); - printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo); - hpt370_clear_engine(drive); - /* get dma command mode */ - dma_cmd = hwif->INB(hwif->dma_command); - /* stop dma */ - hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command); - dma_stat = hwif->INB(hwif->dma_status); - /* clear errors */ - hwif->OUTB(dma_stat | 0x6, hwif->dma_status); -} - -static int hpt370_ide_dma_timeout (ide_drive_t *drive) -{ - hpt370_lostirq_timeout(drive); - hpt370_clear_engine(drive); + hpt370_irq_timeout(drive); return __ide_dma_timeout(drive); } -static int hpt370_ide_dma_lostirq (ide_drive_t *drive) -{ - hpt370_lostirq_timeout(drive); - hpt370_clear_engine(drive); - return __ide_dma_lostirq(drive); -} - /* returns 1 if DMA IRQ issued, 0 otherwise */ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u16 bfifo = 0; - u8 reginfo = hwif->channel ? 0x56 : 0x52; - u8 dma_stat; + u8 dma_stat; - pci_read_config_word(hwif->pci_dev, reginfo, &bfifo); + pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); if (bfifo & 0x1FF) { // printk("%s: %d bytes in FIFO\n", drive->name, bfifo); return 0; } - dma_stat = hwif->INB(hwif->dma_status); + dma_stat = inb(hwif->dma_status); /* return 1 if INTR asserted */ - if ((dma_stat & 4) == 4) + if (dma_stat & 4) return 1; if (!drive->waiting_for_dma) @@ -846,17 +843,17 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) return 0; } -static int hpt374_ide_dma_end (ide_drive_t *drive) +static int hpt374_ide_dma_end(ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; ide_hwif_t *hwif = HWIF(drive); - u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50; - u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01; - - pci_read_config_byte(dev, 0x6a, &bwsr_stat); - pci_read_config_byte(dev, mscreg, &msc_stat); - if ((bwsr_stat & bwsr_mask) == bwsr_mask) - pci_write_config_byte(dev, mscreg, msc_stat|0x30); + struct pci_dev *dev = hwif->pci_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); } @@ -866,40 +863,37 @@ static int hpt374_ide_dma_end (ide_drive_t *drive) * @mode: clocking mode (0x21 for write, 0x23 otherwise) * * Switch the DPLL clock on the HPT3xxN devices. This is a right mess. - * NOTE: avoid touching the disabled primary channel on HPT371N -- it - * doesn't physically exist anyway... */ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) { - u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b); + u8 scr2 = hwif->INB(hwif->dma_master + 0x7b); if ((scr2 & 0x7f) == mode) return; - /* MISC. control register 1 has the channel enable bit... */ - mcr1 = hwif->INB(hwif->dma_master + 0x70); - /* Tristate the bus */ - if (mcr1 & 0x04) - hwif->OUTB(0x80, hwif->dma_master + 0x73); + hwif->OUTB(0x80, hwif->dma_master + 0x73); hwif->OUTB(0x80, hwif->dma_master + 0x77); /* Switch clock and reset channels */ hwif->OUTB(mode, hwif->dma_master + 0x7b); hwif->OUTB(0xc0, hwif->dma_master + 0x79); - /* Reset state machines */ - if (mcr1 & 0x04) - hwif->OUTB(0x37, hwif->dma_master + 0x70); - hwif->OUTB(0x37, hwif->dma_master + 0x74); + /* + * Reset the state machines. + * NOTE: avoid accidentally enabling the disabled channels. + */ + hwif->OUTB(hwif->INB(hwif->dma_master + 0x70) | 0x32, + hwif->dma_master + 0x70); + hwif->OUTB(hwif->INB(hwif->dma_master + 0x74) | 0x32, + hwif->dma_master + 0x74); /* Complete reset */ hwif->OUTB(0x00, hwif->dma_master + 0x79); /* Reconnect channels to bus */ - if (mcr1 & 0x04) - hwif->OUTB(0x00, hwif->dma_master + 0x73); + hwif->OUTB(0x00, hwif->dma_master + 0x73); hwif->OUTB(0x00, hwif->dma_master + 0x77); } @@ -914,14 +908,12 @@ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) { - ide_hwif_t *hwif = HWIF(drive); - u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21; - - hpt3xxn_set_clock(hwif, wantclock); + hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21); } /* * Set/get power state for a drive. + * NOTE: affects both drives on each channel. * * When we turn the power back on, we need to re-initialize things. */ @@ -929,26 +921,18 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) static int hpt3xx_busproc(ide_drive_t *drive, int state) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 tristate, resetmask, bus_reg = 0; - u16 tri_reg = 0; + u8 mcr_addr = hwif->select_data + 2; + u8 resetmask = hwif->channel ? 0x80 : 0x40; + u8 bsr2 = 0; + u16 mcr = 0; hwif->bus_state = state; - if (hwif->channel) { - /* secondary channel */ - tristate = 0x56; - resetmask = 0x80; - } else { - /* primary channel */ - tristate = 0x52; - resetmask = 0x40; - } - /* Grab the status. */ - pci_read_config_word(dev, tristate, &tri_reg); - pci_read_config_byte(dev, 0x59, &bus_reg); + pci_read_config_word(dev, mcr_addr, &mcr); + pci_read_config_byte(dev, 0x59, &bsr2); /* * Set the state. We don't set it if we don't need to do so. @@ -956,22 +940,22 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) */ switch (state) { case BUSSTATE_ON: - if (!(bus_reg & resetmask)) + if (!(bsr2 & resetmask)) return 0; hwif->drives[0].failures = hwif->drives[1].failures = 0; - pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask); - pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT); + pci_write_config_byte(dev, 0x59, bsr2 & ~resetmask); + pci_write_config_word(dev, mcr_addr, mcr & ~TRISTATE_BIT); return 0; case BUSSTATE_OFF: - if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT)) + if ((bsr2 & resetmask) && !(mcr & TRISTATE_BIT)) return 0; - tri_reg &= ~TRISTATE_BIT; + mcr &= ~TRISTATE_BIT; break; case BUSSTATE_TRISTATE: - if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT)) + if ((bsr2 & resetmask) && (mcr & TRISTATE_BIT)) return 0; - tri_reg |= TRISTATE_BIT; + mcr |= TRISTATE_BIT; break; default: return -EINVAL; @@ -980,268 +964,320 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - pci_write_config_word(dev, tristate, tri_reg); - pci_write_config_byte(dev, 0x59, bus_reg | resetmask); + pci_write_config_word(dev, mcr_addr, mcr); + pci_write_config_byte(dev, 0x59, bsr2 | resetmask); return 0; } -static void __devinit hpt366_clocking(ide_hwif_t *hwif) +/** + * hpt37x_calibrate_dpll - calibrate the DPLL + * @dev: PCI device + * + * Perform a calibration cycle on the DPLL. + * Returns 1 if this succeeds + */ +static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) { - u32 reg1 = 0; - struct hpt_info *info = ide_get_hwifdata(hwif); + u32 dpll = (f_high << 16) | f_low | 0x100; + u8 scr2; + int i; - pci_read_config_dword(hwif->pci_dev, 0x40, ®1); + pci_write_config_dword(dev, 0x5c, dpll); - /* detect bus speed by looking at control reg timing: */ - switch((reg1 >> 8) & 7) { - case 5: - info->speed = forty_base_hpt36x; - break; - case 9: - info->speed = twenty_five_base_hpt36x; - break; - case 7: - default: - info->speed = thirty_three_base_hpt36x; + /* 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 __devinit hpt37x_clocking(ide_hwif_t *hwif) +static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) { - struct hpt_info *info = ide_get_hwifdata(hwif); - struct pci_dev *dev = hwif->pci_dev; - int adjust, i; - u16 freq = 0; - u32 pll, temp = 0; - u8 reg5bh = 0, mcr1 = 0; - + struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); + unsigned long io_base = pci_resource_start(dev, 4); + u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ + enum ata_clock clock; + + if (info == NULL) { + printk(KERN_ERR "%s: out of memory!\n", name); + return -ENOMEM; + } + /* - * default to pci clock. make sure MA15/16 are set to output - * to prevent drives having problems with 40-pin cables. Needed - * for some drives such as IBM-DTLA which will not enter ready - * state on reset when PDIAG is a input. - * - * ToDo: should we set 0x21 when using PLL mode ? + * Copy everything from a static "template" structure + * to just allocated per-chip hpt_info structure. */ - pci_write_config_byte(dev, 0x5b, 0x23); + *info = *(struct hpt_info *)pci_get_drvdata(dev); /* - * 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. - * - * 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... + * FIXME: Not portable. Also, why do we enable the ROM in the first place? + * We don't seem to be using it. */ - temp = inl(pci_resource_start(dev, 4) + 0x90); - if ((temp & 0xFFFFF000) != 0xABCDE000) { - printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n"); - - /* Calculate the average value of f_CNT */ - for (temp = i = 0; i < 128; i++) { - pci_read_config_word(dev, 0x78, &freq); - temp += freq & 0x1ff; - mdelay(1); - } - freq = temp / 128; - } else - freq = temp & 0x1ff; + if (dev->resource[PCI_ROM_RESOURCE].start) + pci_write_config_dword(dev, PCI_ROM_ADDRESS, + dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + + 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); /* - * HPT3xxN chips use different PCI clock information. - * Currently we always set up the PLL for them. + * First, try to estimate the PCI clock frequency... */ + if (info->chip_type >= HPT370) { + u8 scr1 = 0; + u16 f_cnt = 0; + u32 temp = 0; - if (info->flags & IS_3xxN) { - if(freq < 0x55) - pll = F_LOW_PCI_33; - else if(freq < 0x70) - pll = F_LOW_PCI_40; - else if(freq < 0x7F) - pll = F_LOW_PCI_50; - else - pll = F_LOW_PCI_66; + /* Interrupt force enable. */ + pci_read_config_byte(dev, 0x5a, &scr1); + if (scr1 & 0x10) + pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); - printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll); - } - else - { - if(freq < 0x9C) - pll = F_LOW_PCI_33; - else if(freq < 0xb0) - pll = F_LOW_PCI_40; - else if(freq <0xc8) - pll = F_LOW_PCI_50; + /* + * HighPoint does this for HPT372A. + * NOTE: This register is only writeable via I/O space. + */ + if (info->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. + * + * 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... + */ + temp = inl(io_base + 0x90); + if ((temp & 0xFFFFF000) != 0xABCDE000) { + int i; + + printk(KERN_WARNING "%s: no clock data saved by BIOS\n", + name); + + /* 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 - pll = F_LOW_PCI_66; - - if (pll == F_LOW_PCI_33) { - info->speed = thirty_three_base_hpt37x; - printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n"); - } else if (pll == F_LOW_PCI_40) { - /* Unsupported */ - } else if (pll == F_LOW_PCI_50) { - info->speed = fifty_base_hpt37x; - printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); - } else { - info->speed = sixty_six_base_hpt37x; - printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); + pci_clk = 66; + + printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, " + "assuming %d MHz PCI\n", name, 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; } } - if (pll == F_LOW_PCI_66) - info->flags |= PCI_66MHZ; + /* 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 pll if we don't have a table for the clock - * speed that we're running at. NOTE: the internal PLL will - * result in slow reads when using a 33MHz PCI clock. we also - * don't like to use the PLL because it will cause glitches - * on PRST/SRST when the HPT state engine gets reset. + * 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... * - * ToDo: Use 66MHz PLL when ATA133 devices are present on a - * 372 device so we can get ATA133 support + * 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 (info->speed) - goto init_hpt37X_done; + if (info->chip_type >= HPT374 || info->settings[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->max_mode == 0x04) { + dpll_clk = 66; + clock = ATA_CLOCK_66MHZ; + } else if (dpll_clk) { /* HPT36x chips don't have DPLL */ + dpll_clk = 50; + clock = ATA_CLOCK_50MHZ; + } - info->flags |= PLL_MODE; - - /* - * Adjust the PLL based upon the PCI clock, enable it, and - * wait for stabilization... - */ - adjust = 0; - freq = (pll < F_LOW_PCI_50) ? 2 : 4; - while (adjust++ < 6) { - pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 | - pll | 0x100); - - /* wait for clock stabilization */ - for (i = 0; i < 0x50000; i++) { - pci_read_config_byte(dev, 0x5b, ®5bh); - if (reg5bh & 0x80) { - /* spin looking for the clock to destabilize */ - for (i = 0; i < 0x1000; ++i) { - pci_read_config_byte(dev, 0x5b, - ®5bh); - if ((reg5bh & 0x80) == 0) - goto pll_recal; - } - pci_read_config_dword(dev, 0x5c, &pll); - pci_write_config_dword(dev, 0x5c, - pll & ~0x100); - pci_write_config_byte(dev, 0x5b, 0x21); - - info->speed = fifty_base_hpt37x; - printk("HPT37X: using 50MHz internal PLL\n"); - goto init_hpt37X_done; - } + if (info->settings[clock] == NULL) { + printk(KERN_ERR "%s: unknown bus timing!\n", name); + kfree(info); + return -EIO; } -pll_recal: - if (adjust & 1) - pll -= (adjust >> 1); - else - pll += (adjust >> 1); - } -init_hpt37X_done: - if (!info->speed) - printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n", - (info->flags & IS_3xxN) ? "N" : "", pll, freq); - /* - * Reset the state engines. - * NOTE: avoid accidentally enabling the primary channel on HPT371N. - */ - pci_read_config_byte(dev, 0x50, &mcr1); - if (mcr1 & 0x04) - pci_write_config_byte(dev, 0x50, 0x37); - pci_write_config_byte(dev, 0x54, 0x37); - udelay(100); -} + /* Select the DPLL clock. */ + pci_write_config_byte(dev, 0x5b, 0x21); -static int __devinit init_hpt37x(struct pci_dev *dev) -{ - u8 reg5ah; + /* + * Adjust the DPLL based upon PCI clock, enable it, + * and wait for stabilization... + */ + f_low = (pci_clk * 48) / dpll_clk; - pci_read_config_byte(dev, 0x5a, ®5ah); - /* interrupt force enable */ - pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); - return 0; -} + for (adjust = 0; adjust < 8; adjust++) { + if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta)) + break; -static int __devinit init_hpt366(struct pci_dev *dev) -{ - u32 reg1 = 0; - u8 drive_fast = 0; + /* + * 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: DPLL did not stabilize!\n", name); + kfree(info); + return -EIO; + } - /* - * Disable the "fast interrupt" prediction. - */ - pci_read_config_byte(dev, 0x51, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); - pci_read_config_dword(dev, 0x40, ®1); - - return 0; -} + printk("%s: using %d MHz DPLL clock\n", name, dpll_clk); + } else { + /* Mark the fact that we're not using the DPLL. */ + dpll_clk = 0; -static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) -{ - int ret = 0; + printk("%s: using %d MHz PCI clock\n", name, pci_clk); + } /* - * FIXME: Not portable. Also, why do we enable the ROM in the first place? - * We don't seem to be using it. + * Advance the table pointer to a slot which points to the list + * of the register values settings matching the clock being used. */ - if (dev->resource[PCI_ROM_RESOURCE].start) - pci_write_config_dword(dev, PCI_ROM_ADDRESS, - dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + info->settings += clock; - 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); + /* Store the clock frequencies. */ + info->dpll_clk = dpll_clk; + info->pci_clk = pci_clk; - if (hpt_revision(dev) >= 3) - ret = init_hpt37x(dev); - else - ret = init_hpt366(dev); + /* Point to this chip's own instance of the hpt_info structure. */ + pci_set_drvdata(dev, info); - if (ret) - return ret; + if (info->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 (info->chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) + + outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); return dev->irq; } static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = pci_get_drvdata(dev); int serialize = HPT_SERIALIZE_IO; - + u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02; + u8 chip_type = info->chip_type; + u8 new_mcr, old_mcr = 0; + + /* Cache the channel's MISC. control registers' offset */ + hwif->select_data = hwif->channel ? 0x54 : 0x50; + hwif->tuneproc = &hpt3xx_tune_drive; hwif->speedproc = &hpt3xx_tune_chipset; hwif->quirkproc = &hpt3xx_quirkproc; hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; - + hwif->busproc = &hpt3xx_busproc; + /* * 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 ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) { + if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) { /* * Clock is shared between the channels, * so we'll have to serialize them... :-( @@ -1250,200 +1286,168 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->rw_disk = &hpt3xxn_rw_disk; } + /* Serialize access to this device if needed */ + if (serialize && hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; + + /* + * Disable the "fast interrupt" prediction. Don't hold off + * on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr); + + if (info->chip_type >= HPT374) + new_mcr = old_mcr & ~0x07; + else if (info->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, hwif->select_data + 1, new_mcr); + + if (!hwif->dma_base) { + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + return; + } + + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + /* * The HPT37x uses the CBLID pins as outputs for MA15/MA16 - * address lines to access an external eeprom. To read valid + * address lines to access an external EEPROM. To read valid * cable detect state the pins must be enabled as inputs. */ - if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) { + 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 */ - u16 mcr3, mcr6; - pci_read_config_word(dev, 0x52, &mcr3); - pci_read_config_word(dev, 0x56, &mcr6); - pci_write_config_word(dev, 0x52, mcr3 | 0x8000); - pci_write_config_word(dev, 0x56, mcr6 | 0x8000); + 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, &ata66); - pci_write_config_word(dev, 0x52, mcr3); - pci_write_config_word(dev, 0x56, mcr6); - } else if (info->revision >= 3) { + 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 0x5b to enable P/SCBLID as inputs + * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs */ - u8 scr2; - 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, &ata66); - pci_write_config_byte(dev, 0x5b, scr2); - } else { - pci_read_config_byte(dev, 0x5a, &ata66); - } - -#ifdef DEBUG - printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", - ata66, (ata66 & regmask) ? "33" : "66", - PCI_FUNC(hwif->pci_dev->devfn)); -#endif /* DEBUG */ - - /* Serialize access to this device */ - if (serialize && hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; + u8 scr2 = 0; - /* - * Set up ioctl for power status. - * NOTE: power affects both drives on each channel. - */ - hwif->busproc = &hpt3xx_busproc; + pci_read_config_byte (dev, 0x5b, &scr2); + pci_write_config_byte(dev, 0x5b, (scr2 & ~1)); + /* now read cable id register */ + pci_read_config_byte (dev, 0x5a, &scr1); + pci_write_config_byte(dev, 0x5b, scr2); + } else + pci_read_config_byte (dev, 0x5a, &scr1); - if (!hwif->dma_base) { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - return; - } + if (!hwif->udma_four) + hwif->udma_four = (scr1 & ata66) ? 0 : 1; - hwif->ultra_mask = 0x7f; - hwif->mwdma_mask = 0x07; + hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; - if (!(hwif->udma_four)) - hwif->udma_four = ((ata66 & regmask) ? 0 : 1); - hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; - - if (info->revision >= 8) { - hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; - hwif->ide_dma_end = &hpt374_ide_dma_end; - } else if (info->revision >= 5) { - hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; - hwif->ide_dma_end = &hpt374_ide_dma_end; - } else if (info->revision >= 3) { - hwif->dma_start = &hpt370_ide_dma_start; - hwif->ide_dma_end = &hpt370_ide_dma_end; - hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; - hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; - } else if (info->revision >= 2) - hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; - else - hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; + if (chip_type >= HPT374) { + hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; + hwif->ide_dma_end = &hpt374_ide_dma_end; + } else if (chip_type >= HPT370) { + hwif->dma_start = &hpt370_ide_dma_start; + hwif->ide_dma_end = &hpt370_ide_dma_end; + hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; + } else + hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; if (!noautodma) hwif->autodma = 1; - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) { - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 masterdma = 0, slavedma = 0; - u8 dma_new = 0, dma_old = 0; - u8 primary = hwif->channel ? 0x4b : 0x43; - u8 secondary = hwif->channel ? 0x4f : 0x47; + struct pci_dev *dev = hwif->pci_dev; + u8 masterdma = 0, slavedma = 0; + u8 dma_new = 0, dma_old = 0; unsigned long flags; - if (!dmabase) - return; - - if(info->speed == NULL) { - printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n"); - return; - } - - dma_old = hwif->INB(dmabase+2); + dma_old = hwif->INB(dmabase + 2); local_irq_save(flags); dma_new = dma_old; - pci_read_config_byte(hwif->pci_dev, primary, &masterdma); - pci_read_config_byte(hwif->pci_dev, secondary, &slavedma); + 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 ( slavedma & 0x30) dma_new |= 0x40; if (dma_new != dma_old) - hwif->OUTB(dma_new, dmabase+2); + hwif->OUTB(dma_new, dmabase + 2); local_irq_restore(flags); ide_setup_dma(hwif, dmabase, 8); } -/* - * We "borrow" this hook in order to set the data structures - * up early enough before dma or init_hwif calls are made. - */ - -static void __devinit init_iops_hpt366(ide_hwif_t *hwif) -{ - struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); - struct pci_dev *dev = hwif->pci_dev; - u16 did = dev->device; - u8 rid = 0; - - if(info == NULL) { - printk(KERN_WARNING "hpt366: out of memory.\n"); - return; - } - ide_set_hwifdata(hwif, info); - - /* Avoid doing the same thing twice. */ - if (hwif->channel && hwif->mate) { - memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info)); - return; - } - - pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid); - - if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) || - ((did == PCI_DEVICE_ID_TTI_HPT372 || - did == PCI_DEVICE_ID_TTI_HPT302 || - did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) || - did == PCI_DEVICE_ID_TTI_HPT372N) - info->flags |= IS_3xxN; - - info->revision = hpt_revision(dev); - - if (info->revision >= 3) - hpt37x_clocking(hwif); - else - hpt366_clocking(hwif); -} - static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) { - struct pci_dev *findev = NULL; + struct pci_dev *dev2; if (PCI_FUNC(dev->devfn) & 1) return -ENODEV; - while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - if (findev->irq != dev->irq) { - /* FIXME: we need a core pci_set_interrupt() */ - findev->irq = dev->irq; - printk(KERN_WARNING "%s: pci-config space interrupt " - "fixed.\n", d->name); - } - return ide_setup_pci_devices(dev, findev, d); + pci_set_drvdata(dev, &hpt374); + + if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) { + int ret; + + pci_set_drvdata(dev2, &hpt374); + + if (dev2->irq != dev->irq) { + /* FIXME: we need a core pci_set_interrupt() */ + dev2->irq = dev->irq; + printk(KERN_WARNING "%s: PCI config space interrupt " + "fixed.\n", d->name); } + ret = ide_setup_pci_devices(dev, dev2, d); + if (ret < 0) + pci_dev_put(dev2); + return ret; } return ide_setup_pci_device(dev, d); } -static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d) +static int __devinit init_setup_hpt372n(struct pci_dev *dev, ide_pci_device_t *d) { + pci_set_drvdata(dev, &hpt372n); + return ide_setup_pci_device(dev, d); } static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) { - u8 mcr1 = 0; + struct hpt_info *info; + u8 rev = 0, mcr1 = 0; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + + if (rev > 1) { + d->name = "HPT371N"; + + info = &hpt371n; + } else + info = &hpt371; /* * HPT371 chips physically have only one channel, the secondary one, @@ -1453,59 +1457,94 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) */ pci_read_config_byte(dev, 0x50, &mcr1); if (mcr1 & 0x04) - pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04)); + pci_write_config_byte(dev, 0x50, mcr1 & ~0x04); + + pci_set_drvdata(dev, info); + + return ide_setup_pci_device(dev, d); +} + +static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d) +{ + struct hpt_info *info; + u8 rev = 0; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + + if (rev > 1) { + d->name = "HPT372N"; + + info = &hpt372n; + } else + info = &hpt372a; + pci_set_drvdata(dev, info); + + return ide_setup_pci_device(dev, d); +} + +static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d) +{ + struct hpt_info *info; + u8 rev = 0; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + + if (rev > 1) { + d->name = "HPT302N"; + + info = &hpt302n; + } else + info = &hpt302; + pci_set_drvdata(dev, info); return ide_setup_pci_device(dev, d); } static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) { - struct pci_dev *findev = NULL; - u8 pin1 = 0, pin2 = 0; - unsigned int class_rev; - char *chipset_names[] = {"HPT366", "HPT366", "HPT368", - "HPT370", "HPT370A", "HPT372", - "HPT372N" }; + struct pci_dev *dev2; + u8 rev = 0; + static char *chipset_names[] = { "HPT366", "HPT366", "HPT368", + "HPT370", "HPT370A", "HPT372", + "HPT372N" }; + static struct hpt_info *info[] = { &hpt36x, &hpt36x, &hpt36x, + &hpt370, &hpt370a, &hpt372, + &hpt372n }; if (PCI_FUNC(dev->devfn) & 1) return -ENODEV; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - if(dev->device == PCI_DEVICE_ID_TTI_HPT372N) - class_rev = 6; + if (rev > 6) + rev = 6; - if(class_rev <= 6) - d->name = chipset_names[class_rev]; - - switch(class_rev) { - case 6: - case 5: - case 4: - case 3: - goto init_single; - default: - break; - } + d->name = chipset_names[rev]; + + pci_set_drvdata(dev, info[rev]); + + if (rev > 2) + goto init_single; d->channels = 1; - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - pci_read_config_byte(findev, PCI_INTERRUPT_PIN, &pin2); - if ((pin1 != pin2) && (dev->irq == findev->irq)) { - d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, " - "pin1=%d pin2=%d\n", d->name, - pin1, pin2); - } - return ide_setup_pci_devices(dev, findev, d); + if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) { + u8 pin1 = 0, pin2 = 0; + int ret; + + pci_set_drvdata(dev2, info[rev]); + + 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) { + d->bootable = ON_BOARD; + printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", + d->name, pin1, pin2); } + ret = ide_setup_pci_devices(dev, dev2, d); + if (ret < 0) + pci_dev_put(dev2); + return ret; } init_single: return ide_setup_pci_device(dev, d); @@ -1516,64 +1555,68 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT366", .init_setup = init_setup_hpt366, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, .extra = 240 },{ /* 1 */ .name = "HPT372A", - .init_setup = init_setup_hpt37x, + .init_setup = init_setup_hpt372a, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, + .extra = 240 },{ /* 2 */ .name = "HPT302", - .init_setup = init_setup_hpt37x, + .init_setup = init_setup_hpt302, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, + .extra = 240 },{ /* 3 */ .name = "HPT371", .init_setup = init_setup_hpt371, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, + .extra = 240 },{ /* 4 */ .name = "HPT374", .init_setup = init_setup_hpt374, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, /* 4 */ .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, + .extra = 240 },{ /* 5 */ .name = "HPT372N", - .init_setup = init_setup_hpt37x, + .init_setup = init_setup_hpt372n, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, /* 4 */ .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, + .extra = 240 } }; diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c new file mode 100644 index 000000000000..424f00bb160d --- /dev/null +++ b/drivers/ide/pci/it8213.c @@ -0,0 +1,360 @@ +/* + * ITE 8213 IDE driver + * + * Copyright (C) 2006 Jack Lee + * Copyright (C) 2006 Alan Cox + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/hdreg.h> +#include <linux/ide.h> +#include <linux/init.h> + +#include <asm/io.h> + +/* + * it8213_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. This + * is all modes to ATA133 clipped by drive cable setup. + */ + +static u8 it8213_ratemask (ide_drive_t *drive) +{ + u8 mode = 4; + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + return mode; +} + +/** + * it8213_dma_2_pio - return the PIO mode matching DMA + * @xfer_rate: transfer speed + * + * Returns the nearest equivalent PIO timing for the PIO or DMA + * mode requested by the controller. + */ + +static u8 it8213_dma_2_pio (u8 xfer_rate) { + switch(xfer_rate) { + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + case XFER_PIO_4: + return 4; + case XFER_MW_DMA_1: + case XFER_PIO_3: + return 3; + case XFER_SW_DMA_2: + case XFER_PIO_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + case XFER_PIO_1: + case XFER_PIO_0: + case XFER_PIO_SLOW: + default: + return 0; + } +} + +/* + * it8213_tuneproc - tune a drive + * @drive: drive to tune + * @pio: desired PIO mode + * + * Set the interface PIO mode. + */ + +static void it8213_tuneproc (ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_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 }, }; + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + + 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_tune_chipset - set controller timings + * @drive: Drive to set up + * @xferspeed: speed we want to achieve + * + * Tune the ITE chipset for the desired mode. If we can't achieve + * the desired mode then tune for a lower one, but ultimately + * make the thing work. + */ + +static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 maslave = 0x40; + u8 speed = ide_rate_filter(it8213_ratemask(drive), xferspeed); + 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); + + switch(speed) { + case XFER_UDMA_6: + case XFER_UDMA_4: + case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; + break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_SW_DMA_2: + break; + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + break; + default: + return -1; + } + + if (speed >= XFER_UDMA_0) { + 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 { + 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); + } + it8213_tuneproc(drive, it8213_dma_2_pio(speed)); + return ide_config_drive_speed(drive, speed); +} + +/* + * config_chipset_for_dma - configure for DMA + * @drive: drive to configure + * + * Called by the IDE layer when it wants the timings set up. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, it8213_ratemask(drive)); + + if (!speed) + return 0; + + it8213_tune_chipset(drive, speed); + + return ide_dma_enable(drive); +} + +/** + * it8213_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * Set up the drive for DMA, tune the controller and drive as + * required. If the drive isn't suitable for DMA or we hit + * other problems then we will drop down to PIO and set up + * PIO appropriately + */ + +static int it8213_config_drive_for_dma (ide_drive_t *drive) +{ + u8 pio; + + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; + + pio = ide_get_best_pio_mode(drive, 255, 4, NULL); + it8213_tune_chipset(drive, XFER_PIO_0 + pio); + + return -1; +} + +/** + * init_hwif_it8213 - 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_it8213(ide_hwif_t *hwif) +{ + u8 reg42h = 0, ata66 = 0; + + hwif->speedproc = &it8213_tune_chipset; + hwif->tuneproc = &it8213_tuneproc; + + hwif->autodma = 0; + + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + + if (!hwif->dma_base) + return; + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x06; + hwif->swdma_mask = 0x04; + + pci_read_config_byte(hwif->pci_dev, 0x42, ®42h); + ata66 = (reg42h & 0x02) ? 0 : 1; + + hwif->ide_dma_check = &it8213_config_drive_for_dma; + if (!(hwif->udma_four)) + hwif->udma_four = ata66; + + /* + * The BIOS often doesn't set up DMA on this controller + * so we always do it. + */ + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + + +#define DECLARE_ITE_DEV(name_str) \ + { \ + .name = name_str, \ + .init_hwif = init_hwif_it8213, \ + .channels = 1, \ + .autodma = AUTODMA, \ + .enablebits = {{0x41,0x80,0x80}}, \ + .bootable = ON_BOARD, \ + } + +static ide_pci_device_t it8213_chipsets[] __devinitdata = { + /* 0 */ DECLARE_ITE_DEV("IT8213"), +}; + + +/** + * 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) +{ + ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]); + return 0; +} + + +static struct pci_device_id it8213_pci_tbl[] = { + { PCI_VENDOR_ID_ITE, 0x8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0, }, +}; + +MODULE_DEVICE_TABLE(pci, it8213_pci_tbl); + +static struct pci_driver driver = { + .name = "ITE8213_IDE", + .id_table = it8213_pci_tbl, + .probe = it8213_init_one, +}; + +static int __init it8213_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +module_init(it8213_ide_init); + +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 index e9bad185968a..a132767f7d90 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -520,14 +520,12 @@ static int config_chipset_for_dma (ide_drive_t *drive) static int it821x_config_drive_for_dma (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } config_it821x_chipset_for_pio(drive, 1); - return hwif->ide_dma_off_quietly(drive); + + return -1; } /** @@ -608,11 +606,11 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif) printk(".\n"); /* Now the core code will have wrongly decided no DMA so we need to fix this */ - hwif->ide_dma_off_quietly(drive); + hwif->dma_off_quietly(drive); #ifdef CONFIG_IDEDMA_ONLYDISK if (drive->media == ide_disk) #endif - hwif->ide_dma_check(drive); + ide_set_dma(drive); } else { /* Non RAID volume. Fixups to stop the core code doing unsupported things */ diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index f07bbbed1778..53f25500c22b 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -147,7 +147,9 @@ static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, jmicron_ratemask(drive)); - config_jmicron_chipset_for_pio(drive, !speed); + if (!speed) + return 0; + jmicron_tune_chipset(drive, speed); return ide_dma_enable(drive); } @@ -162,14 +164,12 @@ static int config_chipset_for_dma (ide_drive_t *drive) static int jmicron_config_drive_for_dma (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } config_jmicron_chipset_for_pio(drive, 1); - return hwif->ide_dma_off_quietly(drive); + + return -1; } /** diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index 8aaea4ea5549..b310c4f51077 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -166,10 +166,10 @@ static int ns87415_ide_dma_end (ide_drive_t *drive) /* get dma command mode */ dma_cmd = hwif->INB(hwif->dma_command); /* stop DMA */ - hwif->OUTB(dma_cmd & ~1, hwif->dma_command); + outb(dma_cmd & ~1, hwif->dma_command); /* from ERRATA: clear the INTR & ERROR bits */ dma_cmd = hwif->INB(hwif->dma_command); - hwif->OUTB(dma_cmd|6, hwif->dma_command); + outb(dma_cmd | 6, hwif->dma_command); /* and free any DMA resources */ ide_destroy_dmatable(drive); /* verify good DMA status */ @@ -190,7 +190,8 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive) static int ns87415_ide_dma_check (ide_drive_t *drive) { if (drive->media != ide_disk) - return HWIF(drive)->ide_dma_off_quietly(drive); + return -1; + return __ide_dma_check(drive); } @@ -243,9 +244,9 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) * to SELECT_DRIVE() properly during first probe_hwif(). */ timeout = 10000; - hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]); + outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]); udelay(10); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]); do { udelay(50); stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); @@ -263,7 +264,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) if (!hwif->dma_base) return; - hwif->OUTB(0x60, hwif->dma_status); + outb(0x60, hwif->dma_status); hwif->dma_setup = &ns87415_ide_dma_setup; hwif->ide_dma_check = &ns87415_ide_dma_check; hwif->ide_dma_end = &ns87415_ide_dma_end; diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 22bbf613f948..9ca60dd2185e 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -176,34 +176,35 @@ static int cmpt_clk(int time, int bus_speed) return ((time*bus_speed+999)/1000); } -static void write_reg(ide_hwif_t *hwif, u8 value, int reg) /* Write value to register reg, base of register * is at reg_base (0x1f0 primary, 0x170 secondary, * if not changed by PCI configuration). * This is from setupvic.exe program. */ +static void write_reg(u8 value, int reg) { - hwif->INW(reg_base+1); - hwif->INW(reg_base+1); - hwif->OUTB(3, reg_base+2); - hwif->OUTB(value, reg_base+reg); - hwif->OUTB(0x83, reg_base+2); + inw(reg_base + 1); + inw(reg_base + 1); + outb(3, reg_base + 2); + outb(value, reg_base + reg); + outb(0x83, reg_base + 2); } -static u8 read_reg(ide_hwif_t *hwif, int reg) /* Read value from register reg, base of register * is at reg_base (0x1f0 primary, 0x170 secondary, * if not changed by PCI configuration). * This is from setupvic.exe program. */ +static u8 read_reg(int reg) { u8 ret = 0; - hwif->INW(reg_base+1); - hwif->INW(reg_base+1); - hwif->OUTB(3, reg_base+2); - ret = hwif->INB(reg_base+reg); - hwif->OUTB(0x83, reg_base+2); + 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; } @@ -286,39 +287,39 @@ static void opti621_tune_drive (ide_drive_t *drive, u8 pio) reg_base = hwif->io_ports[IDE_DATA_OFFSET]; /* allow Register-B */ - hwif->OUTB(0xc0, reg_base+CNTRL_REG); + outb(0xc0, reg_base + CNTRL_REG); /* hmm, setupvic.exe does this ;-) */ - hwif->OUTB(0xff, reg_base+5); + outb(0xff, reg_base + 5); /* if reads 0xff, adapter not exist? */ - (void) hwif->INB(reg_base+CNTRL_REG); + (void)inb(reg_base + CNTRL_REG); /* if reads 0xc0, no interface exist? */ - read_reg(hwif, CNTRL_REG); + read_reg(CNTRL_REG); /* read version, probably 0 */ - read_reg(hwif, STRAP_REG); + read_reg(STRAP_REG); /* program primary drive */ - /* select Index-0 for Register-A */ - write_reg(hwif, 0, MISC_REG); - /* set read cycle timings */ - write_reg(hwif, cycle1, READ_REG); - /* set write cycle timings */ - write_reg(hwif, cycle1, WRITE_REG); + /* select Index-0 for Register-A */ + write_reg(0, MISC_REG); + /* set read cycle timings */ + write_reg(cycle1, READ_REG); + /* set write cycle timings */ + write_reg(cycle1, WRITE_REG); /* program secondary drive */ - /* select Index-1 for Register-B */ - write_reg(hwif, 1, MISC_REG); - /* set read cycle timings */ - write_reg(hwif, cycle2, READ_REG); - /* set write cycle timings */ - write_reg(hwif, cycle2, WRITE_REG); + /* select Index-1 for Register-B */ + write_reg(1, MISC_REG); + /* set read cycle timings */ + write_reg(cycle2, READ_REG); + /* set write cycle timings */ + write_reg(cycle2, WRITE_REG); /* use Register-A for drive 0 */ /* use Register-B for drive 1 */ - write_reg(hwif, 0x85, CNTRL_REG); + write_reg(0x85, CNTRL_REG); /* set address setup, DRDY timings, */ /* and read prefetch for both drives */ - write_reg(hwif, misc, MISC_REG); + write_reg(misc, MISC_REG); spin_unlock_irqrestore(&ide_lock, flags); } diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 77a9aaa7dab9..6ceb25bc5a7b 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -92,26 +92,6 @@ static u8 pdcnew_ratemask(ide_drive_t *drive) return mode; } -static int check_in_drive_lists(ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (pdc_quirk_drives == list) { - while (*list) { - if (strstr(id->model, *list++)) { - return 2; - } - } - } else { - while (*list) { - if (!strcmp(*list++,id->model)) { - return 1; - } - } - } - return 0; -} - /** * get_indexed_reg - Get indexed register * @hwif: for the port address @@ -121,8 +101,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) { u8 value; - hwif->OUTB(index, hwif->dma_vendor1); - value = hwif->INB(hwif->dma_vendor3); + outb(index, hwif->dma_vendor1); + value = inb(hwif->dma_vendor3); DBG("index[%02X] value[%02X]\n", index, value); return value; @@ -135,8 +115,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) */ static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value) { - hwif->OUTB(index, hwif->dma_vendor1); - hwif->OUTB(value, hwif->dma_vendor3); + outb(index, hwif->dma_vendor1); + outb(value, hwif->dma_vendor3); DBG("index[%02X] value[%02X]\n", index, value); } @@ -249,13 +229,6 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) return err; } -/* 0 1 2 3 4 5 6 7 8 - * 960, 480, 390, 300, 240, 180, 120, 90, 60 - * 180, 150, 120, 90, 60 - * DMA_Speed - * 180, 120, 90, 90, 90, 60, 30 - * 11, 5, 4, 3, 2, 1, 0 - */ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 4, NULL); @@ -308,46 +281,25 @@ static int config_chipset_for_dma(ide_drive_t *drive) static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - goto fast_ata_pio; + if (ide_use_fast_pio(drive)) + pdcnew_tune_drive(drive, 255); - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - hwif->tuneproc(drive, 255); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + return -1; } static int pdcnew_quirkproc(ide_drive_t *drive) { - return check_in_drive_lists(drive, pdc_quirk_drives); -} - -static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) -{ - if (HWIF(drive)->resetproc != NULL) - HWIF(drive)->resetproc(drive); - return __ide_dma_lostirq(drive); -} + const char **list, *model = drive->id->model; -static int pdcnew_ide_dma_timeout(ide_drive_t *drive) -{ - if (HWIF(drive)->resetproc != NULL) - HWIF(drive)->resetproc(drive); - return __ide_dma_timeout(drive); + for (list = pdc_quirk_drives; *list != NULL; list++) + if (strstr(model, *list) != NULL) + return 2; + return 0; } static void pdcnew_reset(ide_drive_t *drive) @@ -599,8 +551,6 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->err_stops_fifo = 1; hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; - hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; - hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; if (!hwif->udma_four) hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1; diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 143239c093d5..a7a639fe1eaf 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -2,6 +2,7 @@ * linux/drivers/ide/pci/pdc202xx_old.c Version 0.36 Sept 11, 2002 * * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> + * Copyright (C) 2006-2007 MontaVista Software, Inc. * * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this * compiled into the kernel if you have more than one card installed. @@ -123,26 +124,6 @@ static u8 pdc202xx_ratemask (ide_drive_t *drive) return mode; } -static int check_in_drive_lists (ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (pdc_quirk_drives == list) { - while (*list) { - if (strstr(id->model, *list++)) { - return 2; - } - } - } else { - while (*list) { - if (!strcmp(*list++,id->model)) { - return 1; - } - } - } - return 0; -} - static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); @@ -236,21 +217,10 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) } -/* 0 1 2 3 4 5 6 7 8 - * 960, 480, 390, 300, 240, 180, 120, 90, 60 - * 180, 150, 120, 90, 60 - * DMA_Speed - * 180, 120, 90, 90, 90, 60, 30 - * 11, 5, 4, 3, 2, 1, 0 - */ -static void config_chipset_for_pio (ide_drive_t *drive, u8 pio) +static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio) { - u8 speed = 0; - - if (pio == 5) pio = 4; - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); - - pdc202xx_tune_chipset(drive, speed); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + pdc202xx_tune_chipset(drive, XFER_PIO_0 + pio); } static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) @@ -270,17 +240,17 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif) { unsigned long clock_reg = hwif->dma_master + 0x11; - u8 clock = hwif->INB(clock_reg); + u8 clock = inb(clock_reg); - hwif->OUTB(clock | (hwif->channel ? 0x08 : 0x02), 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->dma_master + 0x11; - u8 clock = hwif->INB(clock_reg); + u8 clock = inb(clock_reg); - hwif->OUTB(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); + outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); } static int config_chipset_for_dma (ide_drive_t *drive) @@ -352,32 +322,25 @@ chipset_is_set: static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - goto fast_ata_pio; + if (ide_use_fast_pio(drive)) + pdc202xx_tune_drive(drive, 255); - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - hwif->tuneproc(drive, 5); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + return -1; } static int pdc202xx_quirkproc (ide_drive_t *drive) { - return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); + const char **list, *model = drive->id->model; + + for (list = pdc_quirk_drives; *list != NULL; list++) + if (strstr(model, *list) != NULL) + return 2; + return 0; } static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) @@ -390,14 +353,14 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) unsigned long high_16 = hwif->dma_master; unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); u32 word_count = 0; - u8 clock = hwif->INB(high_16 + 0x11); + u8 clock = inb(high_16 + 0x11); - hwif->OUTB(clock|(hwif->channel ? 0x08 : 0x02), 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; - hwif->OUTL(word_count, atapi_reg); + outl(word_count, atapi_reg); } ide_dma_start(drive); } @@ -410,9 +373,9 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive) unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); u8 clock = 0; - hwif->OUTL(0, atapi_reg); /* zero out extra */ - clock = hwif->INB(high_16 + 0x11); - hwif->OUTB(clock & ~(hwif->channel ? 0x08:0x02), high_16+0x11); + 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); @@ -423,8 +386,8 @@ static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long high_16 = hwif->dma_master; - u8 dma_stat = hwif->INB(hwif->dma_status); - u8 sc1d = hwif->INB((high_16 + 0x001d)); + u8 dma_stat = inb(hwif->dma_status); + u8 sc1d = inb(high_16 + 0x001d); if (hwif->channel) { /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */ @@ -460,11 +423,11 @@ static int pdc202xx_ide_dma_timeout(ide_drive_t *drive) static void pdc202xx_reset_host (ide_hwif_t *hwif) { unsigned long high_16 = hwif->dma_master; - u8 udma_speed_flag = hwif->INB(high_16|0x001f); + u8 udma_speed_flag = inb(high_16 | 0x001f); - hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f)); + outb(udma_speed_flag | 0x10, high_16 | 0x001f); mdelay(100); - hwif->OUTB((udma_speed_flag & ~0x10), (high_16|0x001f)); + outb(udma_speed_flag & ~0x10, high_16 | 0x001f); mdelay(2000); /* 2 seconds ?! */ printk(KERN_WARNING "PDC202XX: %s channel reset.\n", @@ -478,7 +441,7 @@ static void pdc202xx_reset (ide_drive_t *drive) pdc202xx_reset_host(hwif); pdc202xx_reset_host(mate); - hwif->tuneproc(drive, 5); + pdc202xx_tune_drive(drive, 255); } static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, @@ -505,7 +468,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) hwif->rqsize = 256; hwif->autodma = 0; - hwif->tuneproc = &config_chipset_for_pio; + hwif->tuneproc = &pdc202xx_tune_drive; hwif->quirkproc = &pdc202xx_quirkproc; if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) @@ -552,9 +515,9 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) return; } - udma_speed_flag = hwif->INB((dmabase|0x1f)); - primary_mode = hwif->INB((dmabase|0x1a)); - secondary_mode = hwif->INB((dmabase|0x1b)); + 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", hwif->cds->name, @@ -567,30 +530,10 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ", hwif->cds->name, udma_speed_flag, (udma_speed_flag|1)); - hwif->OUTB(udma_speed_flag|1,(dmabase|0x1f)); - printk("%sACTIVE\n", - (hwif->INB(dmabase|0x1f)&1) ? "":"IN"); + outb(udma_speed_flag | 1, dmabase | 0x1f); + printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN"); } #endif /* CONFIG_PDC202XX_BURST */ -#ifdef CONFIG_PDC202XX_MASTER - if (!(primary_mode & 1)) { - printk(KERN_INFO "%s: FORCING PRIMARY MODE BIT " - "0x%02x -> 0x%02x ", hwif->cds->name, - primary_mode, (primary_mode|1)); - hwif->OUTB(primary_mode|1, (dmabase|0x1a)); - printk("%s\n", - (hwif->INB((dmabase|0x1a)) & 1) ? "MASTER" : "PCI"); - } - - if (!(secondary_mode & 1)) { - printk(KERN_INFO "%s: FORCING SECONDARY MODE BIT " - "0x%02x -> 0x%02x ", hwif->cds->name, - secondary_mode, (secondary_mode|1)); - hwif->OUTB(secondary_mode|1, (dmabase|0x1b)); - printk("%s\n", - (hwif->INB((dmabase|0x1b)) & 1) ? "MASTER" : "PCI"); - } -#endif /* CONFIG_PDC202XX_MASTER */ ide_setup_dma(hwif, dmabase, 8); } diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index edb37f3d558d..569822f4cf55 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/piix.c Version 0.45 May 12, 2006 + * linux/drivers/ide/pci/piix.c Version 0.46 December 3, 2006 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> @@ -163,7 +163,7 @@ static u8 piix_ratemask (ide_drive_t *drive) * if the drive cannot see an 80pin cable. */ if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); + mode = min_t(u8, mode, 1); return mode; } @@ -216,7 +216,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int is_slave = (&hwif->drives[1] == drive); + int is_slave = drive->dn & 1; int master_port = hwif->channel ? 0x42 : 0x40; int slave_port = 0x44; unsigned long flags; @@ -225,7 +225,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) static DEFINE_SPINLOCK(tune_lock); int control = 0; - /* ISP RTC */ + /* ISP RTC */ static const u8 timings[][2]= { { 0, 0 }, { 0, 0 }, @@ -233,7 +233,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) { 2, 1 }, { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); /* * Master vs slave is synchronized above us but the slave register is @@ -243,25 +243,24 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) spin_lock_irqsave(&tune_lock, flags); pci_read_config_word(dev, master_port, &master_data); - if (pio >= 2) + if (pio > 1) control |= 1; /* Programmable timing on */ if (drive->media == ide_disk) control |= 4; /* Prefetch, post write */ - if (pio >= 3) + if (pio > 2) control |= 2; /* IORDY */ if (is_slave) { - master_data = master_data | 0x4000; + master_data |= 0x4000; + master_data &= ~0x0070; if (pio > 1) { /* enable PPE, IE and TIME */ master_data = master_data | (control << 4); - } else { - master_data &= ~0x0070; } pci_read_config_byte(dev, slave_port, &slave_data); slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); } else { - master_data = master_data & 0xccf8; + master_data &= ~0x3307; if (pio > 1) { /* enable PPE, IE and TIME */ master_data = master_data | control; @@ -370,7 +369,7 @@ static int piix_config_drive_for_dma (ide_drive_t *drive) * If no DMA speed was available or the chipset has DMA bugs * then disable DMA and use PIO */ - if (!speed || no_piix_dma) + if (!speed) return 0; (void) piix_tune_chipset(drive, speed); @@ -387,41 +386,28 @@ static int piix_config_drive_for_dma (ide_drive_t *drive) static int piix_config_drive_xfer_rate (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - drive->init_speed = 0; - if ((id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive) && piix_config_drive_for_dma(drive)) - return hwif->ide_dma_on(drive); - - goto fast_ata_pio; + if (ide_use_dma(drive) && piix_config_drive_for_dma(drive)) + return 0; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) /* Find best PIO mode. */ - (void) hwif->speedproc(drive, XFER_PIO_0 + - ide_get_best_pio_mode(drive, 255, 4, NULL)); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + piix_tune_chipset(drive, XFER_PIO_0 + + ide_get_best_pio_mode(drive, 255, 4, NULL)); + + return -1; } /** - * init_chipset_piix - set up the PIIX chipset - * @dev: PCI device to set up - * @name: Name of the device + * piix_is_ichx - check if ICHx + * @dev: PCI device to check * - * Initialize the PCI device as required. For the PIIX this turns - * out to be nice and simple + * returns 1 if ICHx, 0 otherwise. */ - -static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name) +static int piix_is_ichx(struct pci_dev *dev) { - switch(dev->device) { + switch (dev->device) { case PCI_DEVICE_ID_INTEL_82801EB_1: case PCI_DEVICE_ID_INTEL_82801AA_1: case PCI_DEVICE_ID_INTEL_82801AB_1: @@ -439,19 +425,61 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char case PCI_DEVICE_ID_INTEL_ICH7_21: case PCI_DEVICE_ID_INTEL_ESB2_18: case PCI_DEVICE_ID_INTEL_ICH8_6: - { - unsigned int extra = 0; - pci_read_config_dword(dev, 0x54, &extra); - pci_write_config_dword(dev, 0x54, extra|0x400); - } - default: - break; + return 1; + } + + return 0; +} + +/** + * init_chipset_piix - set up the PIIX chipset + * @dev: PCI device to set up + * @name: Name of the device + * + * Initialize the PCI device as required. For the PIIX this turns + * out to be nice and simple + */ + +static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name) +{ + if (piix_is_ichx(dev)) { + unsigned int extra = 0; + pci_read_config_dword(dev, 0x54, &extra); + pci_write_config_dword(dev, 0x54, extra|0x400); } return 0; } /** + * piix_dma_clear_irq - clear BMDMA status + * @drive: IDE drive to clear + * + * Called from ide_intr() for PIO interrupts + * to clear BMDMA status as needed by ICHx + */ +static void piix_dma_clear_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat; + + /* clear the INTR & ERROR bits */ + dma_stat = hwif->INB(hwif->dma_status); + /* Should we force the bit as well ? */ + hwif->OUTB(dma_stat, hwif->dma_status); +} + +static int __devinit piix_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30; + + pci_read_config_byte(dev, 0x54, ®54h); + + return (reg54h & mask) ? 1 : 0; +} + +/** * init_hwif_piix - fill in the hwif for the PIIX * @hwif: IDE interface * @@ -461,9 +489,6 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char static void __devinit init_hwif_piix(ide_hwif_t *hwif) { - u8 reg54h = 0, reg55h = 0, ata66 = 0; - u8 mask = hwif->channel ? 0xc0 : 0x30; - #ifndef CONFIG_IA64 if (!hwif->irq) hwif->irq = hwif->channel ? 15 : 14; @@ -473,10 +498,6 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) /* This is a painful system best to let it self tune for now */ return; } - /* ESB2 appears to generate spurious DMA interrupts in PIO mode - when in native mode */ - if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18) - hwif->atapi_irq_bogon = 1; hwif->autodma = 0; hwif->tuneproc = &piix_tune_drive; @@ -487,15 +508,16 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) if (!hwif->dma_base) return; + /* ICHx need to clear the bmdma status for all interrupts */ + if (piix_is_ichx(hwif->pci_dev)) + hwif->ide_dma_clear_irq = &piix_dma_clear_irq; + hwif->atapi_dma = 1; hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_INTEL_82371MX: - hwif->mwdma_mask = 0x80; - hwif->swdma_mask = 0x80; case PCI_DEVICE_ID_INTEL_82371FB_0: case PCI_DEVICE_ID_INTEL_82371FB_1: case PCI_DEVICE_ID_INTEL_82371SB_1: @@ -508,14 +530,14 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) hwif->ultra_mask = 0x07; break; default: - pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); - pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); - ata66 = (reg54h & mask) ? 1 : 0; + if (!hwif->udma_four) + hwif->udma_four = piix_cable_detect(hwif); break; } - if (!(hwif->udma_four)) - hwif->udma_four = ata66; + if (no_piix_dma) + hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0; + hwif->ide_dma_check = &piix_config_drive_xfer_rate; if (!noautodma) hwif->autodma = 1; @@ -539,13 +561,19 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { /* 0 */ DECLARE_PIIX_DEV("PIIXa"), /* 1 */ DECLARE_PIIX_DEV("PIIXb"), - { /* 2 */ + /* 2 */ + { /* + * 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 = "MPIIX", .init_hwif = init_hwif_piix, .channels = 2, .autodma = NODMA, - .enablebits = {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, + .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}}, .bootable = ON_BOARD, + .flags = IDEPCI_FLAG_ISA_PORTS }, /* 3 */ DECLARE_PIIX_DEV("PIIX3"), diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 8d762d323f8b..b5ae0c50e216 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -161,7 +161,7 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) /* * Default to DMA-off in case we run into trouble here. */ - hwif->ide_dma_off_quietly(drive); /* turn off DMA while we fiddle */ + hwif->dma_off_quietly(drive); /* turn off DMA while we fiddle */ outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */ /* @@ -241,10 +241,7 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */ - /* - * Finally, turn DMA on in software, and exit. - */ - return hwif->ide_dma_on(drive); /* success */ + return 0; /* success */ } /* @@ -442,10 +439,10 @@ static int sc1200_resume (struct pci_dev *dev) ide_drive_t *drive = &(hwif->drives[d]); if (drive->present && !__ide_dma_bad_drive(drive)) { int was_using_dma = drive->using_dma; - hwif->ide_dma_off_quietly(drive); + hwif->dma_off_quietly(drive); sc1200_config_dma(drive); if (!was_using_dma && drive->using_dma) { - hwif->ide_dma_off_quietly(drive); + hwif->dma_off_quietly(drive); } } } diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index ea9a28a45853..dbcd37a0c652 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -160,7 +160,7 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) { if (!drive->init_speed) { - u8 dma_stat = hwif->INB(hwif->dma_status); + u8 dma_stat = inb(hwif->dma_status); dma_pio: if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) && @@ -315,35 +315,15 @@ static int config_chipset_for_dma (ide_drive_t *drive) static int svwks_config_drive_xfer_rate (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - drive->init_speed = 0; - if ((id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - - goto fast_ata_pio; + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) config_chipset_for_pio(drive); - // hwif->tuneproc(drive, 5); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; -} - -/* This can go soon */ -static int svwks_ide_dma_end (ide_drive_t *drive) -{ - return __ide_dma_end(drive); + return -1; } static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name) @@ -537,35 +517,20 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif) } hwif->ide_dma_check = &svwks_config_drive_xfer_rate; - if (hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) - hwif->ide_dma_end = &svwks_ide_dma_end; - else if (!(hwif->udma_four)) - hwif->udma_four = ata66_svwks(hwif); + if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { + if (!hwif->udma_four) + hwif->udma_four = ata66_svwks(hwif); + } if (!noautodma) hwif->autodma = 1; - dma_stat = hwif->INB(hwif->dma_status); + dma_stat = inb(hwif->dma_status); hwif->drives[0].autodma = (dma_stat & 0x20); hwif->drives[1].autodma = (dma_stat & 0x40); hwif->drives[0].autotune = (!(dma_stat & 0x20)); hwif->drives[1].autotune = (!(dma_stat & 0x40)); } -/* - * We allow the BM-DMA driver to only work on enabled interfaces. - */ -static void __devinit init_dma_svwks (ide_hwif_t *hwif, unsigned long dmabase) -{ - struct pci_dev *dev = hwif->pci_dev; - - if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || - (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && - (!(PCI_FUNC(dev->devfn) & 1)) && (hwif->channel)) - return; - - ide_setup_dma(hwif, dmabase, 8); -} - static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d) { return ide_setup_pci_device(dev, d); @@ -600,7 +565,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = { .init_setup = init_setup_svwks, .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .init_dma = init_dma_svwks, .channels = 2, .autodma = AUTODMA, .bootable = ON_BOARD, @@ -609,7 +573,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = { .init_setup = init_setup_csb6, .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .init_dma = init_dma_svwks, .channels = 2, .autodma = AUTODMA, .bootable = ON_BOARD, @@ -618,7 +581,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = { .init_setup = init_setup_csb6, .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .init_dma = init_dma_svwks, .channels = 1, /* 2 */ .autodma = AUTODMA, .bootable = ON_BOARD, @@ -627,7 +589,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = { .init_setup = init_setup_svwks, .init_chipset = init_chipset_svwks, .init_hwif = init_hwif_svwks, - .init_dma = init_dma_svwks, .channels = 1, /* 2 */ .autodma = AUTODMA, .bootable = ON_BOARD, diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index b0bf01809279..fd09b295a69d 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -110,24 +110,24 @@ sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, static void sgiioc4_maskproc(ide_drive_t * drive, int mask) { - ide_hwif_t *hwif = HWIF(drive); - hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2), - IDE_CONTROL_REG); + writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2), + (void __iomem *)IDE_CONTROL_REG); } static int sgiioc4_checkirq(ide_hwif_t * hwif) { - u8 intr_reg = - hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4); + unsigned long intr_addr = + hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4; - if (intr_reg & 0x03) + if ((u8)readl((void __iomem *)intr_addr) & 0x03) return 1; return 0; } +static u8 sgiioc4_INB(unsigned long); static int sgiioc4_clearirq(ide_drive_t * drive) @@ -138,21 +138,21 @@ sgiioc4_clearirq(ide_drive_t * drive) hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2); /* Code to check for PCI error conditions */ - intr_reg = hwif->INL(other_ir); + intr_reg = readl((void __iomem *)other_ir); if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */ /* - * Using hwif->INB to read the IDE_STATUS_REG has a side effect + * Using sgiioc4_INB to read the IDE_STATUS_REG 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 = hwif->INB(IDE_STATUS_REG); + u8 stat = sgiioc4_INB(IDE_STATUS_REG); int count = 0; - stat = hwif->INB(IDE_STATUS_REG); + stat = sgiioc4_INB(IDE_STATUS_REG); while ((stat & 0x80) && (count++ < 100)) { udelay(1); - stat = hwif->INB(IDE_STATUS_REG); + stat = sgiioc4_INB(IDE_STATUS_REG); } if (intr_reg & 0x02) { @@ -161,9 +161,9 @@ sgiioc4_clearirq(ide_drive_t * drive) pci_stat_cmd_reg; pci_err_addr_low = - hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET]); + readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]); pci_err_addr_high = - hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + 4); + readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4)); pci_read_config_dword(hwif->pci_dev, PCI_COMMAND, &pci_stat_cmd_reg); printk(KERN_ERR @@ -180,9 +180,9 @@ sgiioc4_clearirq(ide_drive_t * drive) } /* Clear the Interrupt, Error bits on the IOC4 */ - hwif->OUTL(0x03, other_ir); + writel(0x03, (void __iomem *)other_ir); - intr_reg = hwif->INL(other_ir); + intr_reg = readl((void __iomem *)other_ir); } return intr_reg & 3; @@ -191,23 +191,25 @@ sgiioc4_clearirq(ide_drive_t * drive) static void sgiioc4_ide_dma_start(ide_drive_t * drive) { ide_hwif_t *hwif = HWIF(drive); - unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4); + 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; - hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4); + 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 = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + ioc4_dma = readl((void __iomem *)ioc4_dma_addr); while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) { udelay(1); - ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + ioc4_dma = readl((void __iomem *)ioc4_dma_addr); } return ioc4_dma; } @@ -218,11 +220,11 @@ sgiioc4_ide_dma_end(ide_drive_t * drive) { u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0; ide_hwif_t *hwif = HWIF(drive); - u64 dma_base = hwif->dma_base; + unsigned long dma_base = hwif->dma_base; int dma_stat = 0; unsigned long *ending_dma = ide_get_hwifdata(hwif); - hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4); + writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4)); ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); @@ -254,8 +256,8 @@ sgiioc4_ide_dma_end(ide_drive_t * drive) dma_stat = 1; } - bc_dev = hwif->INL(dma_base + IOC4_BC_DEV * 4); - bc_mem = hwif->INL(dma_base + IOC4_BC_MEM * 4); + 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) { @@ -273,34 +275,29 @@ sgiioc4_ide_dma_end(ide_drive_t * drive) } static int -sgiioc4_ide_dma_check(ide_drive_t * drive) +sgiioc4_ide_dma_on(ide_drive_t * drive) { - if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) { - printk(KERN_INFO - "Couldnot set %s in Multimode-2 DMA mode | " - "Drive %s using PIO instead\n", - drive->name, drive->name); - drive->using_dma = 0; - } else - drive->using_dma = 1; + drive->using_dma = 1; return 0; } -static int -sgiioc4_ide_dma_on(ide_drive_t * drive) +static void sgiioc4_dma_off_quietly(ide_drive_t *drive) { - drive->using_dma = 1; + drive->using_dma = 0; - return HWIF(drive)->ide_dma_host_on(drive); + drive->hwif->dma_host_off(drive); } -static int -sgiioc4_ide_dma_off_quietly(ide_drive_t * drive) +static int sgiioc4_ide_dma_check(ide_drive_t *drive) { - drive->using_dma = 0; - - return HWIF(drive)->ide_dma_host_off(drive); + /* FIXME: check for available DMA modes */ + if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) { + printk(KERN_WARNING "%s: couldn't set MWDMA2 mode, " + "using PIO instead\n", drive->name); + return -1; + } else + return 0; } /* returns 1 if dma irq issued, 0 otherwise */ @@ -310,21 +307,13 @@ sgiioc4_ide_dma_test_irq(ide_drive_t * drive) return sgiioc4_checkirq(HWIF(drive)); } -static int -sgiioc4_ide_dma_host_on(ide_drive_t * drive) +static void sgiioc4_dma_host_on(ide_drive_t * drive) { - if (drive->using_dma) - return 0; - - return 1; } -static int -sgiioc4_ide_dma_host_off(ide_drive_t * drive) +static void sgiioc4_dma_host_off(ide_drive_t * drive) { sgiioc4_clearirq(drive); - - return 0; } static int @@ -436,16 +425,17 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) { u32 ioc4_dma; ide_hwif_t *hwif = HWIF(drive); - u64 dma_base = hwif->dma_base; + 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 = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + 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", __FUNCTION__, drive->name); - hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4); + 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) @@ -454,13 +444,13 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) __FUNCTION__, drive->name); } - ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + 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", __FUNCTION__, drive->name, ioc4_dma); - hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4); + 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) @@ -471,14 +461,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) /* Address of the Scatter Gather List */ dma_addr = cpu_to_le32(hwif->dmatable_dma); - hwif->OUTL(dma_addr, dma_base + IOC4_DMA_PTR_L * 4); + 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->dma_status); - hwif->OUTL(ending_dma_addr, dma_base + IOC4_DMA_END_ADDR * 4); + writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4)); - hwif->OUTL(dma_direction, dma_base + IOC4_DMA_CTRL * 4); + writel(dma_direction, (void __iomem *)ioc4_dma_addr); drive->waiting_for_dma = 1; } @@ -590,7 +580,7 @@ static int sgiioc4_ide_dma_setup(ide_drive_t *drive) static void __devinit ide_init_sgiioc4(ide_hwif_t * hwif) { - hwif->mmio = 2; + hwif->mmio = 1; hwif->autodma = 1; hwif->atapi_dma = 1; hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ @@ -613,10 +603,10 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->ide_dma_end = &sgiioc4_ide_dma_end; hwif->ide_dma_check = &sgiioc4_ide_dma_check; hwif->ide_dma_on = &sgiioc4_ide_dma_on; - hwif->ide_dma_off_quietly = &sgiioc4_ide_dma_off_quietly; + hwif->dma_off_quietly = &sgiioc4_dma_off_quietly; hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq; - hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on; - hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off; + hwif->dma_host_on = &sgiioc4_dma_host_on; + hwif->dma_host_off = &sgiioc4_dma_host_off; hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq; hwif->ide_dma_timeout = &__ide_dma_timeout; @@ -688,7 +678,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) default_hwif_mmiops(hwif); /* Initializing chipset IRQ Registers */ - hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4); + writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); ide_init_sgiioc4(hwif); @@ -729,8 +719,7 @@ out: return ret; } -static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = { - { +static ide_pci_device_t sgiioc4_chipset __devinitdata = { /* Channel 0 */ .name = "SGIIOC4", .init_hwif = ide_init_sgiioc4, @@ -739,7 +728,6 @@ static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = { .autodma = AUTODMA, /* SGI IOC4 doesn't have enablebits. */ .bootable = ON_BOARD, - } }; int @@ -751,8 +739,7 @@ ioc4_ide_attach_one(struct ioc4_driver_data *idd) if (idd->idd_variant == IOC4_VARIANT_PCI_RT) return 0; - return pci_init_sgiioc4(idd->idd_pdev, - &sgiioc4_chipsets[idd->idd_pci_id->driver_data]); + return pci_init_sgiioc4(idd->idd_pdev, &sgiioc4_chipset); } static struct ioc4_submodule ioc4_ide_submodule = { diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 4ff89c7d990a..7b4c189a9d99 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -1,8 +1,9 @@ /* - * linux/drivers/ide/pci/siimage.c Version 1.07 Nov 30, 2003 + * linux/drivers/ide/pci/siimage.c Version 1.11 Jan 27, 2007 * * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> + * Copyright (C) 2007 MontaVista Software, Inc. * * May be copied or modified under the terms of the GNU General Public License * @@ -205,41 +206,39 @@ static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted) unsigned long tfaddr = siimage_selreg(hwif, 0x02); /* cheat for now and use the docs */ - switch(mode_wanted) { - case 4: - speedp = 0x10c1; - speedt = 0x10c1; - break; - case 3: - speedp = 0x10C3; - speedt = 0x10C3; - break; - case 2: - speedp = 0x1104; - speedt = 0x1281; - break; - case 1: - speedp = 0x2283; - speedt = 0x1281; - break; - case 0: - default: - speedp = 0x328A; - speedt = 0x328A; - break; + switch (mode_wanted) { + case 4: + speedp = 0x10c1; + speedt = 0x10c1; + break; + case 3: + speedp = 0x10c3; + speedt = 0x10c3; + break; + case 2: + speedp = 0x1104; + speedt = 0x1281; + break; + case 1: + speedp = 0x2283; + speedt = 0x2283; + break; + case 0: + default: + speedp = 0x328a; + speedt = 0x328a; + break; } - if (hwif->mmio) - { - hwif->OUTW(speedt, addr); - hwif->OUTW(speedp, tfaddr); + + if (hwif->mmio) { + hwif->OUTW(speedp, addr); + hwif->OUTW(speedt, tfaddr); /* Now set up IORDY */ if(mode_wanted == 3 || mode_wanted == 4) hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); else hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); - } - else - { + } else { pci_write_config_word(hwif->pci_dev, addr, speedp); pci_write_config_word(hwif->pci_dev, tfaddr, speedt); pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); @@ -397,12 +396,9 @@ static int config_chipset_for_dma (ide_drive_t *drive) if (!speed) return 0; - if (ide_set_xfer_rate(drive, speed)) + if (siimage_tune_chipset(drive, speed)) return 0; - if (!drive->init_speed) - drive->init_speed = speed; - return ide_dma_enable(drive); } @@ -418,25 +414,13 @@ static int config_chipset_for_dma (ide_drive_t *drive) static int siimage_config_drive_for_dma (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - - if ((id->capability & 1) != 0 && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - - goto fast_ata_pio; + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) config_chipset_for_pio(drive, 1); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + + return -1; } /* returns 1 if dma irq issued, 0 otherwise */ @@ -472,11 +456,11 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) unsigned long addr = siimage_selreg(hwif, 0x1); if (SATA_ERROR_REG) { - u32 ext_stat = hwif->INL(base + 0x10); + u32 ext_stat = readl((void __iomem *)(base + 0x10)); u8 watchdog = 0; if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { - u32 sata_error = hwif->INL(SATA_ERROR_REG); - hwif->OUTL(sata_error, SATA_ERROR_REG); + u32 sata_error = readl((void __iomem *)SATA_ERROR_REG); + writel(sata_error, (void __iomem *)SATA_ERROR_REG); watchdog = (sata_error & 0x00680000) ? 1 : 0; printk(KERN_WARNING "%s: sata_error = 0x%08x, " "watchdog = %d, %s\n", @@ -493,11 +477,11 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) } /* return 1 if INTR asserted */ - if ((hwif->INB(hwif->dma_status) & 0x04) == 0x04) + if ((readb((void __iomem *)hwif->dma_status) & 0x04) == 0x04) return 1; /* return 1 if Device INTR asserted */ - if ((hwif->INB(addr) & 8) == 8) + if ((readb((void __iomem *)addr) & 8) == 8) return 0; //return 1; return 0; @@ -519,9 +503,9 @@ static int siimage_busproc (ide_drive_t * drive, int state) u32 stat_config = 0; unsigned long addr = siimage_selreg(hwif, 0); - if (hwif->mmio) { - stat_config = hwif->INL(addr); - } else + if (hwif->mmio) + stat_config = readl((void __iomem *)addr); + else pci_read_config_dword(hwif->pci_dev, addr, &stat_config); switch (state) { @@ -557,9 +541,10 @@ static int siimage_reset_poll (ide_drive_t *drive) if (SATA_STATUS_REG) { ide_hwif_t *hwif = HWIF(drive); - if ((hwif->INL(SATA_STATUS_REG) & 0x03) != 0x03) { + /* SATA_STATUS_REG is valid only when in MMIO mode */ + if ((readl((void __iomem *)SATA_STATUS_REG) & 0x03) != 0x03) { printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", - hwif->name, hwif->INL(SATA_STATUS_REG)); + hwif->name, readl((void __iomem *)SATA_STATUS_REG)); HWGROUP(drive)->polling = 0; return ide_started; } @@ -619,7 +604,8 @@ static void siimage_reset (ide_drive_t *drive) } if (SATA_STATUS_REG) { - u32 sata_stat = hwif->INL(SATA_STATUS_REG); + /* SATA_STATUS_REG is valid only when in MMIO mode */ + u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG); printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n", hwif->name, sata_stat, __FUNCTION__); if (!(sata_stat)) { @@ -898,7 +884,8 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) base = (unsigned long) addr; hwif->dma_base = base + (ch ? 0x08 : 0x00); - hwif->mmio = 2; + + hwif->mmio = 1; } static int is_dev_seagate_sata(ide_drive_t *drive) diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 1afff659ab55..2ba0669f36a1 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -667,67 +667,20 @@ static int config_chipset_for_dma (ide_drive_t *drive) return ide_dma_enable(drive); } -static int sis5513_config_drive_xfer_rate (ide_drive_t *drive) +static int sis5513_config_xfer_rate(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; + config_art_rwp_pio(drive, 5); drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - - goto fast_ata_pio; + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + if (ide_use_fast_pio(drive)) sis5513_tune_drive(drive, 5); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; -} - -/* initiates/aborts (U)DMA read/write operations on a drive. */ -static int sis5513_config_xfer_rate (ide_drive_t *drive) -{ - config_drive_art_rwp(drive); - config_art_rwp_pio(drive, 5); - return sis5513_config_drive_xfer_rate(drive); -} - -/* - Future simpler config_xfer_rate : - When ide_find_best_mode is made bad-drive aware - - remove config_drive_xfer_rate and config_chipset_for_dma, - - replace config_xfer_rate with the following - -static int sis5513_config_xfer_rate (ide_drive_t *drive) -{ - u16 w80 = HWIF(drive)->udma_four; - u16 speed; - - config_drive_art_rwp(drive); - config_art_rwp_pio(drive, 5); - - speed = ide_find_best_mode(drive, - XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA | - (chipset_family >= ATA_33 ? XFER_UDMA : 0) | - (w80 && chipset_family >= ATA_66 ? XFER_UDMA_66 : 0) | - (w80 && chipset_family >= ATA_100a ? XFER_UDMA_100 : 0) | - (w80 && chipset_family >= ATA_133a ? XFER_UDMA_133 : 0)); - - sis5513_tune_chipset(drive, speed); - if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) - return HWIF(drive)->ide_dma_on(drive); - return HWIF(drive)->ide_dma_off_quietly(drive); + return -1; } -*/ /* Chip detection and general config */ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name) diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 170a26199050..3a8a76fc78c7 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -161,14 +161,14 @@ static int sl82c105_check_drive (ide_drive_t *drive) if (id->field_valid & 2) { if ((id->dma_mword & hwif->mwdma_mask) || (id->dma_1word & hwif->swdma_mask)) - return hwif->ide_dma_on(drive); + return 0; } - if (__ide_dma_good_drive(drive)) - return hwif->ide_dma_on(drive); + if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150) + return 0; } while (0); - return hwif->ide_dma_off_quietly(drive); + return -1; } /* @@ -215,7 +215,7 @@ static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive) * Was DMA enabled? If so, disable it - we're resetting the * host. The IDE layer will be handling the drive for us. */ - val = hwif->INB(dma_base); + val = inb(dma_base); if (val & 1) { outb(val & ~1, dma_base); printk("sl82c105: DMA was enabled\n"); @@ -259,28 +259,22 @@ static int sl82c105_ide_dma_on (ide_drive_t *drive) { DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name)); - if (config_for_dma(drive)) { - config_for_pio(drive, 4, 0, 0); - return HWIF(drive)->ide_dma_off_quietly(drive); - } + if (config_for_dma(drive)) + return 1; printk(KERN_INFO "%s: DMA enabled\n", drive->name); return __ide_dma_on(drive); } -static int sl82c105_ide_dma_off_quietly (ide_drive_t *drive) +static void sl82c105_dma_off_quietly(ide_drive_t *drive) { u8 speed = XFER_PIO_0; - int rc; - - DBG(("sl82c105_ide_dma_off_quietly(drive:%s)\n", drive->name)); - rc = __ide_dma_off_quietly(drive); + DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name)); + + ide_dma_off_quietly(drive); if (drive->pio_speed) speed = drive->pio_speed - XFER_PIO_0; config_for_pio(drive, speed, 0, 1); - drive->current_speed = drive->pio_speed; - - return rc; } /* @@ -401,11 +395,9 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c /* * Initialise the chip */ - static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) { unsigned int rev; - u8 dma_state; DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); @@ -431,7 +423,6 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) if (!hwif->dma_base) return; - dma_state = hwif->INB(hwif->dma_base + 2) & ~0x60; rev = sl82c105_bridge_revision(hwif->pci_dev); if (rev <= 5) { /* @@ -441,15 +432,12 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", hwif->name, rev); } else { - dma_state |= 0x60; - hwif->atapi_dma = 1; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; + hwif->mwdma_mask = 0x04; hwif->ide_dma_check = &sl82c105_check_drive; hwif->ide_dma_on = &sl82c105_ide_dma_on; - hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; + hwif->dma_off_quietly = &sl82c105_dma_off_quietly; hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; hwif->dma_start = &sl82c105_ide_dma_start; hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; @@ -462,7 +450,6 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) if (hwif->mate) hwif->serialized = hwif->mate->serialized = 1; } - hwif->OUTB(dma_state, hwif->dma_base + 2); } static ide_pci_device_t sl82c105_chipset __devinitdata = { diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 90e79c0844d2..ae7eb58d961c 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/slc90e66.c Version 0.12 May 12, 2006 + * linux/drivers/ide/pci/slc90e66.c Version 0.13 December 30, 2006 * * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com> @@ -26,7 +26,7 @@ static u8 slc90e66_ratemask (ide_drive_t *drive) u8 mode = 2; if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); + mode = min_t(u8, mode, 1); return mode; } @@ -65,36 +65,47 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int is_slave = (&hwif->drives[1] == drive); + 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; - /* ISP RTC */ + int control = 0; + /* ISP RTC */ static const u8 timings[][2]= { - { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; + { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); spin_lock_irqsave(&ide_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 = master_data | 0x4000; - if (pio > 1) + master_data |= 0x4000; + master_data &= ~0x0070; + if (pio > 1) { /* enable PPE, IE and TIME */ - master_data = master_data | 0x0070; + master_data = master_data | (control << 4); + } pci_read_config_byte(dev, slave_port, &slave_data); slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); } else { - master_data = master_data & 0xccf8; - if (pio > 1) + master_data &= ~0x3307; + if (pio > 1) { /* enable PPE, IE and TIME */ - master_data = master_data | 0x0007; + 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); @@ -168,26 +179,16 @@ static int slc90e66_config_drive_for_dma (ide_drive_t *drive) static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) - return hwif->ide_dma_on(drive); + if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) + return 0; - goto fast_ata_pio; + if (ide_use_fast_pio(drive)) + (void)slc90e66_tune_chipset(drive, XFER_PIO_0 + + ide_get_best_pio_mode(drive, 255, 4, NULL)); - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - (void) hwif->speedproc(drive, XFER_PIO_0 + - ide_get_best_pio_mode(drive, 255, 4, NULL)); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; + return -1; } static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) @@ -201,7 +202,7 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) hwif->irq = hwif->channel ? 15 : 14; hwif->speedproc = &slc90e66_tune_chipset; - hwif->tuneproc = &slc90e66_tune_drive; + hwif->tuneproc = &slc90e66_tune_drive; pci_read_config_byte(hwif->pci_dev, 0x47, ®47); @@ -213,14 +214,16 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) hwif->atapi_dma = 1; hwif->ultra_mask = 0x1f; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; + hwif->mwdma_mask = 0x06; + hwif->swdma_mask = 0x04; - if (!(hwif->udma_four)) + if (!hwif->udma_four) { /* bit[0(1)]: 0:80, 1:40 */ hwif->udma_four = (reg47 & mask) ? 0 : 1; + } hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate; + if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c new file mode 100644 index 000000000000..0b6d81d6ce48 --- /dev/null +++ b/drivers/ide/pci/tc86c001.c @@ -0,0 +1,299 @@ +/* + * drivers/ide/pci/tc86c001.c Version 1.00 Dec 12, 2006 + * + * Copyright (C) 2002 Toshiba Corporation + * Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com> + * + * 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 <linux/types.h> +#include <linux/pci.h> +#include <linux/ide.h> + +static inline u8 tc86c001_ratemask(ide_drive_t *drive) +{ + return eighty_ninty_three(drive) ? 2 : 1; +} + +static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00); + u16 mode, scr = hwif->INW(scr_port); + + speed = ide_rate_filter(tc86c001_ratemask(drive), speed); + + 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); + + return ide_config_drive_speed(drive, speed); +} + +static void tc86c001_tune_drive(ide_drive_t *drive, u8 pio) +{ + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void) tc86c001_tune_chipset(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 = hwif->INB(hwif->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 = hwif->INB(hwif->dma_command); + + printk(KERN_WARNING "%s: DMA interrupt possibly stuck, " + "attempting recovery...\n", drive->name); + + /* Stop DMA */ + outb(dma_cmd & ~0x01, hwif->dma_command); + + /* 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 */ + outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */ + outb(0x01, hwif->dma_command); /* set START_STOPBM */ + + /* + * 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 int tc86c001_busproc(ide_drive_t *drive, int state) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long sc_base = hwif->config_data; + u16 scr1; + + /* System Control 1 Register bit 11 (ATA Hard Reset) read */ + scr1 = hwif->INW(sc_base + 0x00); + + switch (state) { + case BUSSTATE_ON: + if (!(scr1 & 0x0800)) + return 0; + scr1 &= ~0x0800; + + hwif->drives[0].failures = hwif->drives[1].failures = 0; + break; + case BUSSTATE_OFF: + if (scr1 & 0x0800) + return 0; + scr1 |= 0x0800; + + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + break; + default: + return -EINVAL; + } + + /* System Control 1 Register bit 11 (ATA Hard Reset) write */ + outw(scr1, sc_base + 0x00); + return 0; +} + +static int config_chipset_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, tc86c001_ratemask(drive)); + + if (!speed) + return 0; + + (void) tc86c001_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive) +{ + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + tc86c001_tune_drive(drive, 255); + + return -1; +} + +static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) +{ + unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5); + u16 scr1 = hwif->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; + + hwif->tuneproc = &tc86c001_tune_drive; + hwif->speedproc = &tc86c001_tune_chipset; + hwif->busproc = &tc86c001_busproc; + + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + + 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; + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x1f; + hwif->mwdma_mask = 0x07; + + hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate; + hwif->dma_start = &tc86c001_dma_start; + + if (!hwif->udma_four) { + /* + * System Control 1 Register bit 13 (PDIAGN): + * 0=80-pin cable, 1=40-pin cable + */ + scr1 = hwif->INW(sc_base + 0x00); + hwif->udma_four = (scr1 & 0x2000) ? 0 : 1; + } + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; +} + +static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev, + const char *name) +{ + int err = pci_request_region(dev, 5, name); + + if (err) + printk(KERN_ERR "%s: system control regs already in use", name); + return err; +} + +static ide_pci_device_t tc86c001_chipset __devinitdata = { + .name = "TC86C001", + .init_chipset = init_chipset_tc86c001, + .init_hwif = init_hwif_tc86c001, + .channels = 1, + .autodma = AUTODMA, + .bootable = OFF_BOARD +}; + +static int __devinit tc86c001_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return ide_setup_pci_device(dev, &tc86c001_chipset); +} + +static struct pci_device_id tc86c001_pci_tbl[] = { + { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl); + +static struct pci_driver driver = { + .name = "TC86C001", + .id_table = tc86c001_pci_tbl, + .probe = tc86c001_init_one +}; + +static int __init tc86c001_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} +module_init(tc86c001_ide_init); + +MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); +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 index b13cce1fd1a6..5e06179c3469 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -104,29 +104,21 @@ static int triflex_config_drive_for_dma(ide_drive_t *drive) { int speed = ide_dma_speed(drive, 0); /* No ultra speeds */ - if (!speed) { - u8 pspeed = ide_get_best_pio_mode(drive, 255, 4, NULL); - speed = XFER_PIO_0 + pspeed; - } - + if (!speed) + return 0; + (void) triflex_tune_chipset(drive, speed); return ide_dma_enable(drive); } static int triflex_config_drive_xfer_rate(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - - if ((id->capability & 1) && drive->autodma) { - if (ide_use_dma(drive)) { - if (triflex_config_drive_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - } + if (ide_use_dma(drive) && triflex_config_drive_for_dma(drive)) + return 0; + + triflex_tune_drive(drive, 255); - hwif->tuneproc(drive, 255); - return hwif->ide_dma_off_quietly(drive); + return -1; } static void __devinit init_hwif_triflex(ide_hwif_t *hwif) diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index 174b88c4780e..cbb1b11119a5 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -157,16 +157,16 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma) if (reg != hwif->select_data) { hwif->select_data = reg; /* set PIO/DMA */ - hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1); - hwif->OUTW(reg & 0xff, hwif->config_data); + outb(0x51 | (hwif->channel << 3), hwif->config_data + 1); + outw(reg & 0xff, hwif->config_data); } /* enable IRQ if not probing */ if (drive->present) { - reg = hwif->INW(hwif->config_data + 3); + reg = inw(hwif->config_data + 3); reg &= 0x13; reg &= ~(1 << hwif->channel); - hwif->OUTW(reg, hwif->config_data+3); + outw(reg, hwif->config_data + 3); } local_irq_restore(flags); @@ -177,15 +177,12 @@ static void trm290_selectproc (ide_drive_t *drive) trm290_prepare_drive(drive, drive->using_dma); } -#ifdef CONFIG_BLK_DEV_IDEDMA static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { - ide_hwif_t *hwif = HWIF(drive); - BUG_ON(HWGROUP(drive)->handler != NULL); /* paranoia check */ ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - hwif->OUTB(command, IDE_COMMAND_REG); + outb(command, IDE_COMMAND_REG); } static int trm290_ide_dma_setup(ide_drive_t *drive) @@ -211,10 +208,10 @@ static int trm290_ide_dma_setup(ide_drive_t *drive) } /* select DMA xfer */ trm290_prepare_drive(drive, 1); - hwif->OUTL(hwif->dmatable_dma|rw, hwif->dma_command); + outl(hwif->dmatable_dma | rw, hwif->dma_command); drive->waiting_for_dma = 1; /* start DMA */ - hwif->OUTW((count * 2) - 1, hwif->dma_status); + outw((count * 2) - 1, hwif->dma_status); return 0; } @@ -230,7 +227,7 @@ static int trm290_ide_dma_end (ide_drive_t *drive) drive->waiting_for_dma = 0; /* purge DMA mappings */ ide_destroy_dmatable(drive); - status = hwif->INW(hwif->dma_status); + status = inw(hwif->dma_status); return (status != 0x00ff); } @@ -239,10 +236,9 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive) ide_hwif_t *hwif = HWIF(drive); u16 status = 0; - status = hwif->INW(hwif->dma_status); + status = inw(hwif->dma_status); return (status == 0x00ff); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * Invoked from ide-dma.c at boot time. @@ -269,15 +265,15 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) local_irq_save(flags); /* put config reg into first byte of hwif->select_data */ - hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1); + outb(0x51 | (hwif->channel << 3), hwif->config_data + 1); /* select PIO as default */ hwif->select_data = 0x21; - hwif->OUTB(hwif->select_data, hwif->config_data); + outb(hwif->select_data, hwif->config_data); /* get IRQ info */ - reg = hwif->INB(hwif->config_data+3); + reg = inb(hwif->config_data + 3); /* mask IRQs for both ports */ reg = (reg & 0x10) | 0x03; - hwif->OUTB(reg, hwif->config_data+3); + outb(reg, hwif->config_data + 3); local_irq_restore(flags); if ((reg & 0x10)) @@ -289,13 +285,11 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->dma_setup = &trm290_ide_dma_setup; hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd; hwif->dma_start = &trm290_ide_dma_start; hwif->ide_dma_end = &trm290_ide_dma_end; hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; -#endif /* CONFIG_BLK_DEV_IDEDMA */ hwif->selectproc = &trm290_selectproc; hwif->autodma = 0; /* play it safe for now */ @@ -312,16 +306,16 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) static u16 next_offset = 0; u8 old_mask; - hwif->OUTB(0x54|(hwif->channel<<3), hwif->config_data+1); - old = hwif->INW(hwif->config_data); + outb(0x54 | (hwif->channel << 3), hwif->config_data + 1); + old = inw(hwif->config_data); old &= ~1; - old_mask = hwif->INB(old+2); + old_mask = inb(old + 2); if (old != compat && old_mask == 0xff) { /* leave lower 10 bits untouched */ compat += (next_offset += 0x400); hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2; - hwif->OUTW(compat|1, hwif->config_data); - new = hwif->INW(hwif->config_data); + 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); diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 6fb6e50b8231..a508550c4095 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -240,8 +240,9 @@ static int via82cxxx_ide_dma_check (ide_drive_t *drive) via_set_drive(drive, speed); if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) - return hwif->ide_dma_on(drive); - return hwif->ide_dma_off_quietly(drive); + return 0; + + return -1; } static struct via_isa_bridge *via_config_find(struct pci_dev **isa) diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c index 0ac9da3a7378..82de2d781f2e 100644 --- a/drivers/ide/ppc/mpc8xx.c +++ b/drivers/ide/ppc/mpc8xx.c @@ -12,7 +12,6 @@ */ #include <linux/errno.h> -#include <linux/sched.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/stddef.h> diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 91c5344a945d..395d35253d5d 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -24,7 +24,6 @@ */ #include <linux/types.h> #include <linux/kernel.h> -#include <linux/sched.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/ide.h> @@ -1238,7 +1237,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->OUTBSYNC = pmac_outbsync; /* Tell common code _not_ to mess with resources */ - hwif->mmio = 2; + hwif->mmio = 1; hwif->hwif_data = pmif; pmac_ide_init_hwif_ports(&hwif->hw, pmif->regbase, 0, &hwif->irq); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); @@ -1980,16 +1979,12 @@ pmac_ide_dma_test_irq (ide_drive_t *drive) return 1; } -static int -pmac_ide_dma_host_off (ide_drive_t *drive) +static void pmac_ide_dma_host_off(ide_drive_t *drive) { - return 0; } -static int -pmac_ide_dma_host_on (ide_drive_t *drive) +static int pmac_ide_dma_host_on(ide_drive_t *drive) { - return 0; } static int @@ -2035,7 +2030,7 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) return; } - hwif->ide_dma_off_quietly = &__ide_dma_off_quietly; + hwif->dma_off_quietly = &ide_dma_off_quietly; hwif->ide_dma_on = &__ide_dma_on; hwif->ide_dma_check = &pmac_ide_dma_check; hwif->dma_setup = &pmac_ide_dma_setup; @@ -2043,8 +2038,8 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->dma_start = &pmac_ide_dma_start; hwif->ide_dma_end = &pmac_ide_dma_end; hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq; - hwif->ide_dma_host_off = &pmac_ide_dma_host_off; - hwif->ide_dma_host_on = &pmac_ide_dma_host_on; + hwif->dma_host_off = &pmac_ide_dma_host_off; + hwif->dma_host_on = &pmac_ide_dma_host_on; hwif->ide_dma_timeout = &__ide_dma_timeout; hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq; diff --git a/drivers/ide/ppc/scc_pata.c b/drivers/ide/ppc/scc_pata.c new file mode 100644 index 000000000000..de64b022478b --- /dev/null +++ b/drivers/ide/ppc/scc_pata.c @@ -0,0 +1,831 @@ +/* + * 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 <andre@linux-ide.org> + * Copyright (C) 2003 Red Hat <alan@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This 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 <linux/types.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/hdreg.h> +#include <linux/ide.h> +#include <linux/init.h> + +#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; + unsigned char hwif_id; /* for removing hwif 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 u16 scc_ide_inw(unsigned long port) +{ + u32 data = in_be32((void*)port); + return (u16)data; +} + +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_outw(u16 addr, unsigned long port) +{ + out_be32((void*)port, addr); +} + +static void +scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port) +{ + ide_hwif_t *hwif = HWIF(drive); + + out_be32((void*)port, addr); + __asm__ __volatile__("eieio":::"memory"); + in_be32((void*)(hwif->dma_base + 0x01c)); + __asm__ __volatile__("eieio":::"memory"); +} + +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_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. + * Enforce UDMA33 as a limit if there is no 80pin cable present. + */ + +static u8 scc_ratemask(ide_drive_t *drive) +{ + u8 mode = 4; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +/** + * scc_tuneproc - tune a drive PIO mode + * @drive: drive to tune + * @mode_wanted: the target operating mode + * + * Load the timing settings for this device mode into the + * controller. + */ + +static void scc_tuneproc(ide_drive_t *drive, byte mode_wanted) +{ + 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; + unsigned char speed = XFER_PIO_0; + int offset; + + mode_wanted = ide_get_best_pio_mode(drive, mode_wanted, 4, NULL); + switch (mode_wanted) { + case 4: + speed = XFER_PIO_4; + break; + case 3: + speed = XFER_PIO_3; + break; + case 2: + speed = XFER_PIO_2; + break; + case 1: + speed = XFER_PIO_1; + break; + case 0: + default: + speed = XFER_PIO_0; + break; + } + + reg = in_be32((void __iomem *)cckctrl_port); + if (reg & CCKCTRL_ATACLKOEN) { + offset = 1; /* 133MHz */ + } else { + offset = 0; /* 100MHz */ + } + reg = JCHSTtbl[offset][mode_wanted] << 16 | JCHHTtbl[offset][mode_wanted]; + out_be32((void __iomem *)piosht_port, reg); + reg = JCHCTtbl[offset][mode_wanted]; + out_be32((void __iomem *)pioct_port, reg); + + ide_config_drive_speed(drive, speed); +} + +/** + * scc_tune_chipset - tune a drive DMA mode + * @drive: Drive to set up + * @xferspeed: speed we want to achieve + * + * Load the timing settings for this device mode into the + * controller. + */ + +static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 speed = ide_rate_filter(scc_ratemask(drive), xferspeed); + 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 */ + } + + switch (speed) { + case XFER_UDMA_6: + idx = 6; + break; + case XFER_UDMA_5: + idx = 5; + break; + case XFER_UDMA_4: + idx = 4; + break; + case XFER_UDMA_3: + idx = 3; + break; + case XFER_UDMA_2: + idx = 2; + break; + case XFER_UDMA_1: + idx = 1; + break; + case XFER_UDMA_0: + idx = 0; + break; + default: + return 1; + } + + 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); + + return ide_config_drive_speed(drive, speed); +} + +/** + * scc_config_chipset_for_dma - configure for DMA + * @drive: drive to configure + * + * Called by scc_config_drive_for_dma(). + */ + +static int scc_config_chipset_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, scc_ratemask(drive)); + + if (!speed) + return 0; + + if (scc_tune_chipset(drive, speed)) + return 0; + + return ide_dma_enable(drive); +} + +/** + * scc_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * Set up the drive for DMA, tune the controller and drive as + * required. + * If the drive isn't suitable for DMA or we hit other problems + * then we will drop down to PIO and set up PIO appropriately. + * (return 1) + */ + +static int scc_config_drive_for_dma(ide_drive_t *drive) +{ + if (ide_use_dma(drive) && scc_config_chipset_for_dma(drive)) + return 0; + + if (ide_use_fast_pio(drive)) + scc_tuneproc(drive, 4); + + return -1; +} + +/** + * 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_prdtable, hwif->dmatable_dma); + + /* specify r/w */ + out_be32((void __iomem *)hwif->dma_command, reading); + + /* read dma_status for INTR & ERROR flags */ + dma_stat = in_be32((void __iomem *)hwif->dma_status); + + /* clear INTR & ERROR flags */ + out_be32((void __iomem *)hwif->dma_status, dma_stat|6); + drive->waiting_for_dma = 1; + return 0; +} + + +/** + * scc_ide_dma_end - Stop DMA + * @drive: IDE drive + * + * Check and clear INT Status register. + * Then call __ide_dma_end(). + */ + +static int scc_ide_dma_end(ide_drive_t * drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long intsts_port = hwif->dma_base + 0x014; + u32 reg; + + 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((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~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((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~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((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS); + continue; + } + + if (reg & INTSTS_ICERR) { + out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~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; + } + + return __ide_dma_end(drive); +} + +/** + * 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 *ctl_addr; + void *dma_addr; + int i; + + for (i = 0; i < MAX_HWIFS; i++) { + if (scc_ports[i].ctl == 0) + break; + } + if (i >= MAX_HWIFS) + return -ENOMEM; + + if (!request_mem_region(ctl_base, ctl_size, name)) { + printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME); + goto fail_0; + } + + if (!request_mem_region(dma_base, dma_size, name)) { + printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME); + goto fail_1; + } + + if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL) + goto fail_2; + + if ((dma_addr = ioremap(dma_base, dma_size)) == NULL) + goto fail_3; + + 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_3: + iounmap(ctl_addr); + fail_2: + release_mem_region(dma_base, dma_size); + fail_1: + release_mem_region(ctl_base, ctl_size); + fail_0: + return -ENOMEM; +} + +/** + * init_setup_scc - set up an SCC PATA Controller + * @dev: PCI device + * @d: IDE PCI device + * + * Perform the initial set up for this device. + */ + +static int __devinit init_setup_scc(struct pci_dev *dev, ide_pci_device_t *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; + unsigned long dma_status_port; + u32 reg = 0; + struct scc_ports *ports; + int rc; + + rc = setup_mmio_scc(dev, d->name); + if (rc < 0) { + return rc; + } + + 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; + dma_status_port = dma_base + 0x004; + + /* 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); + + return ide_setup_pci_device(dev, d); +} + +/** + * 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 = hwif->pci_dev; + struct scc_ports *ports = pci_get_drvdata(dev); + unsigned long dma_base = ports->dma; + + ide_set_hwifdata(hwif, ports); + + hwif->INB = scc_ide_inb; + hwif->INW = scc_ide_inw; + hwif->INSW = scc_ide_insw; + hwif->INSL = scc_ide_insl; + hwif->OUTB = scc_ide_outb; + hwif->OUTBSYNC = scc_ide_outbsync; + hwif->OUTW = scc_ide_outw; + hwif->OUTSW = scc_ide_outsw; + hwif->OUTSL = scc_ide_outsl; + + hwif->io_ports[IDE_DATA_OFFSET] = dma_base + 0x20; + hwif->io_ports[IDE_ERROR_OFFSET] = dma_base + 0x24; + hwif->io_ports[IDE_NSECTOR_OFFSET] = dma_base + 0x28; + hwif->io_ports[IDE_SECTOR_OFFSET] = dma_base + 0x2c; + hwif->io_ports[IDE_LCYL_OFFSET] = dma_base + 0x30; + hwif->io_ports[IDE_HCYL_OFFSET] = dma_base + 0x34; + hwif->io_ports[IDE_SELECT_OFFSET] = dma_base + 0x38; + hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c; + hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40; + + hwif->irq = hwif->pci_dev->irq; + hwif->dma_base = dma_base; + hwif->config_data = ports->ctl; + hwif->mmio = 1; +} + +/** + * 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 = hwif->pci_dev; + hwif->hwif_data = NULL; + if (pci_get_drvdata(dev) == NULL) + return; + init_mmio_iops_scc(hwif); +} + +/** + * 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) +{ + struct scc_ports *ports = ide_get_hwifdata(hwif); + + ports->hwif_id = hwif->index; + + hwif->dma_command = hwif->dma_base; + hwif->dma_status = hwif->dma_base + 0x04; + hwif->dma_prdtable = hwif->dma_base + 0x08; + + /* PTERADD */ + out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma); + + hwif->dma_setup = scc_dma_setup; + hwif->ide_dma_end = scc_ide_dma_end; + hwif->speedproc = scc_tune_chipset; + hwif->tuneproc = scc_tuneproc; + hwif->ide_dma_check = scc_config_drive_for_dma; + + hwif->drives[0].autotune = IDE_TUNE_AUTO; + hwif->drives[1].autotune = IDE_TUNE_AUTO; + + if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN) { + hwif->ultra_mask = 0x7f; /* 133MHz */ + } else { + hwif->ultra_mask = 0x3f; /* 100MHz */ + } + hwif->mwdma_mask = 0x00; + hwif->swdma_mask = 0x00; + hwif->atapi_dma = 1; + + /* we support 80c cable only. */ + hwif->udma_four = 1; + + hwif->autodma = 0; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +#define DECLARE_SCC_DEV(name_str) \ + { \ + .name = name_str, \ + .init_setup = init_setup_scc, \ + .init_iops = init_iops_scc, \ + .init_hwif = init_hwif_scc, \ + .channels = 1, \ + .autodma = AUTODMA, \ + .bootable = ON_BOARD, \ + } + +static ide_pci_device_t 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) +{ + ide_pci_device_t *d = &scc_chipsets[id->driver_data]; + return d->init_setup(dev, d); +} + +/** + * 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); + ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id]; + 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); + + if (hwif->dmatable_cpu) { + pci_free_consistent(hwif->pci_dev, + PRD_ENTRIES * PRD_BYTES, + hwif->dmatable_cpu, + hwif->dmatable_dma); + hwif->dmatable_cpu = NULL; + } + + ide_unregister(hwif->index); + + hwif->chipset = ide_unknown; + iounmap((void*)ports->dma); + iounmap((void*)ports->ctl); + release_mem_region(dma_base, dma_size); + release_mem_region(ctl_base, ctl_size); + memset(ports, 0, sizeof(*ports)); +} + +static struct pci_device_id scc_pci_tbl[] = { + { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, scc_pci_tbl); + +static struct pci_driver driver = { + .name = "SCC IDE", + .id_table = scc_pci_tbl, + .probe = scc_init_one, + .remove = scc_remove, +}; + +static int scc_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +module_init(scc_ide_init); +/* -- No exit code? +static void scc_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} +module_exit(scc_ide_exit); + */ + + +MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 695e23904d30..a52c80fe7d3e 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -783,10 +783,11 @@ static LIST_HEAD(ide_pci_drivers); * Returns are the same as for pci_register_driver */ -int __ide_pci_register_driver(struct pci_driver *driver, struct module *module) +int __ide_pci_register_driver(struct pci_driver *driver, struct module *module, + const char *mod_name) { if(!pre_init) - return __pci_register_driver(driver, module); + return __pci_register_driver(driver, module, mod_name); driver->driver.owner = module; list_add_tail(&driver->node, &ide_pci_drivers); return 0; @@ -862,6 +863,6 @@ void __init ide_scan_pcibus (int scan_direction) { list_del(l); d = list_entry(l, struct pci_driver, node); - __pci_register_driver(d, d->driver.owner); + __pci_register_driver(d, d->driver.owner, d->driver.mod_name); } } |