diff options
Diffstat (limited to 'drivers/ide/alim15x3.c')
| -rw-r--r-- | drivers/ide/alim15x3.c | 220 |
1 files changed, 110 insertions, 110 deletions
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 66f43083408..36f76e28a0b 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -8,7 +8,7 @@ * Copyright (C) 2002 Alan Cox * ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw> * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com> - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> + * Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz * * (U)DMA capable version of ali 1533/1543(C), 1535(D) * @@ -40,16 +40,6 @@ #define DRV_NAME "alim15x3" /* - * Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking - * (this is DANGEROUS and could result in data corruption). - */ -static int wdc_udma; - -module_param(wdc_udma, bool, 0); -MODULE_PARM_DESC(wdc_udma, - "allow UDMA on M1543C-E chipset for WDC disks (DANGEROUS)"); - -/* * ALi devices are not plug in. Otherwise these static values would * need to go. They ought to go away anyway */ @@ -58,61 +48,84 @@ static u8 m5229_revision; static u8 chip_is_1543c_e; static struct pci_dev *isa_dev; +static void ali_fifo_control(ide_hwif_t *hwif, ide_drive_t *drive, int on) +{ + struct pci_dev *pdev = to_pci_dev(hwif->dev); + int pio_fifo = 0x54 + hwif->channel; + u8 fifo; + int shift = 4 * (drive->dn & 1); + + pci_read_config_byte(pdev, pio_fifo, &fifo); + fifo &= ~(0x0F << shift); + fifo |= (on << shift); + pci_write_config_byte(pdev, pio_fifo, fifo); +} + +static void ali_program_timings(ide_hwif_t *hwif, ide_drive_t *drive, + struct ide_timing *t, u8 ultra) +{ + struct pci_dev *dev = to_pci_dev(hwif->dev); + int port = hwif->channel ? 0x5c : 0x58; + int udmat = 0x56 + hwif->channel; + u8 unit = drive->dn & 1, udma; + int shift = 4 * unit; + + /* Set up the UDMA */ + pci_read_config_byte(dev, udmat, &udma); + udma &= ~(0x0F << shift); + udma |= ultra << shift; + pci_write_config_byte(dev, udmat, udma); + + if (t == NULL) + return; + + t->setup = clamp_val(t->setup, 1, 8) & 7; + t->act8b = clamp_val(t->act8b, 1, 8) & 7; + t->rec8b = clamp_val(t->rec8b, 1, 16) & 15; + t->active = clamp_val(t->active, 1, 8) & 7; + t->recover = clamp_val(t->recover, 1, 16) & 15; + + pci_write_config_byte(dev, port, t->setup); + pci_write_config_byte(dev, port + 1, (t->act8b << 4) | t->rec8b); + pci_write_config_byte(dev, port + unit + 2, + (t->active << 4) | t->recover); +} + /** * ali_set_pio_mode - set host controller for PIO mode + * @hwif: port * @drive: drive - * @pio: PIO mode number * * Program the controller for the given PIO mode. */ -static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) +static void ali_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); - int s_time = t->setup, a_time = t->active, c_time = t->cycle; - u8 s_clc, a_clc, r_clc; - unsigned long flags; + ide_drive_t *pair = ide_get_pair_dev(drive); int bus_speed = ide_pci_clk ? ide_pci_clk : 33; - int port = hwif->channel ? 0x5c : 0x58; - int portFIFO = hwif->channel ? 0x55 : 0x54; - u8 cd_dma_fifo = 0, unit = drive->dn & 1; - - if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) - s_clc = 0; - if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) - a_clc = 0; - - if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { - r_clc = 1; - } else { - if (r_clc >= 16) - r_clc = 0; + unsigned long T = 1000000 / bus_speed; /* PCI clock based */ + struct ide_timing t; + + ide_timing_compute(drive, drive->pio_mode, &t, T, 1); + if (pair) { + struct ide_timing p; + + ide_timing_compute(pair, pair->pio_mode, &p, T, 1); + ide_timing_merge(&p, &t, &t, + IDE_TIMING_SETUP | IDE_TIMING_8BIT); + if (pair->dma_mode) { + ide_timing_compute(pair, pair->dma_mode, &p, T, 1); + ide_timing_merge(&p, &t, &t, + IDE_TIMING_SETUP | IDE_TIMING_8BIT); + } } - local_irq_save(flags); - + /* * PIO mode => ATA FIFO on, ATAPI FIFO off */ - pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); - if (drive->media==ide_disk) { - if (unit) { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); - } else { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); - } - } else { - if (unit) { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); - } else { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); - } - } - - pci_write_config_byte(dev, port, s_clc); - pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc); - local_irq_restore(flags); + ali_fifo_control(hwif, drive, (drive->media == ide_disk) ? 0x05 : 0x00); + + ali_program_timings(hwif, drive, &t, 0); } /** @@ -132,7 +145,7 @@ static u8 ali_udma_filter(ide_drive_t *drive) if (m5229_revision > 0x20 && m5229_revision < 0xC2) { if (drive->media != ide_disk) return 0; - if (wdc_udma == 0 && chip_is_1543c_e && + if (chip_is_1543c_e && strstr((char *)&drive->id[ATA_ID_PROD], "WDC ")) return 0; } @@ -142,44 +155,42 @@ static u8 ali_udma_filter(ide_drive_t *drive) /** * ali_set_dma_mode - set host controller for DMA mode + * @hwif: port * @drive: drive - * @speed: DMA mode * * Configure the hardware for the desired IDE transfer mode. */ -static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed) +static void ali_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD }; struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 speed1 = speed; - u8 unit = drive->dn & 1; + ide_drive_t *pair = ide_get_pair_dev(drive); + int bus_speed = ide_pci_clk ? ide_pci_clk : 33; + unsigned long T = 1000000 / bus_speed; /* PCI clock based */ + const u8 speed = drive->dma_mode; u8 tmpbyte = 0x00; - int m5229_udma = (hwif->channel) ? 0x57 : 0x56; - - if (speed == XFER_UDMA_6) - speed1 = 0x47; + struct ide_timing t; if (speed < XFER_UDMA_0) { - u8 ultra_enable = (unit) ? 0x7f : 0xf7; - /* - * clear "ultra enable" bit - */ - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= ultra_enable; - pci_write_config_byte(dev, m5229_udma, tmpbyte); - - /* - * FIXME: Oh, my... DMA timings are never set. - */ + ide_timing_compute(drive, drive->dma_mode, &t, T, 1); + if (pair) { + struct ide_timing p; + + ide_timing_compute(pair, pair->pio_mode, &p, T, 1); + ide_timing_merge(&p, &t, &t, + IDE_TIMING_SETUP | IDE_TIMING_8BIT); + if (pair->dma_mode) { + ide_timing_compute(pair, pair->dma_mode, + &p, T, 1); + ide_timing_merge(&p, &t, &t, + IDE_TIMING_SETUP | IDE_TIMING_8BIT); + } + } + ali_program_timings(hwif, drive, &t, 0); } else { - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= (0x0f << ((1-unit) << 2)); - /* - * enable ultra dma and set timing - */ - tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2)); - pci_write_config_byte(dev, m5229_udma, tmpbyte); + ali_program_timings(hwif, drive, NULL, + udma_timing[speed - XFER_UDMA_0]); if (speed >= XFER_UDMA_3) { pci_read_config_byte(dev, 0x4b, &tmpbyte); tmpbyte |= 1; @@ -189,19 +200,20 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed) } /** - * ali15x3_dma_setup - begin a DMA phase + * ali_dma_check - DMA check * @drive: target device + * @cmd: command * * Returns 1 if the DMA cannot be performed, zero on success. */ -static int ali15x3_dma_setup(ide_drive_t *drive) +static int ali_dma_check(ide_drive_t *drive, struct ide_cmd *cmd) { if (m5229_revision < 0xC2 && drive->media != ide_disk) { - if (rq_data_dir(drive->hwif->rq)) + if (cmd->tf_flags & IDE_TFLAG_WRITE) return 1; /* try PIO instead of DMA */ } - return ide_dma_setup(drive); + return 0; } /** @@ -212,7 +224,7 @@ static int ali15x3_dma_setup(ide_drive_t *drive) * appropriate also sets up the 1533 southbridge. */ -static unsigned int init_chipset_ali15x3(struct pci_dev *dev) +static int init_chipset_ali15x3(struct pci_dev *dev) { unsigned long flags; u8 tmpbyte; @@ -364,19 +376,13 @@ static int ali_cable_override(struct pci_dev *pdev) * * This checks if the controller and the cable are capable * of UDMA66 transfers. It doesn't check the drives. - * But see note 2 below! - * - * FIXME: frobs bits that are not defined on newer ALi devicea */ static u8 ali_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long flags; u8 cbl = ATA_CBL_PATA40, tmpbyte; - local_irq_save(flags); - if (m5229_revision >= 0xC2) { /* * m5229 80-pin cable detection (from Host View) @@ -396,32 +402,26 @@ static u8 ali_cable_detect(ide_hwif_t *hwif) } } - local_irq_restore(flags); - return cbl; } -#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) +#ifndef CONFIG_SPARC64 /** * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff * @hwif: interface to configure * * Obtain the IRQ tables for an ALi based IDE solution on the PC * class platforms. This part of the code isn't applicable to the - * Sparc and PowerPC systems. + * Sparc systems. */ -static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) +static void init_hwif_ali15x3(ide_hwif_t *hwif) { - struct pci_dev *dev = to_pci_dev(hwif->dev); u8 ideic, inmir; s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; int irq = -1; - if (dev->device == PCI_DEVICE_ID_AL_M5229) - hwif->irq = hwif->channel ? 15 : 14; - if (isa_dev) { /* * read IDE interface control @@ -454,7 +454,7 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) } #else #define init_hwif_ali15x3 NULL -#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */ +#endif /* CONFIG_SPARC64 */ /** * init_dma_ali15x3 - set up DMA on ALi15x3 @@ -464,8 +464,7 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) * Set up the DMA functionality on the ALi 15x3. */ -static int __devinit init_dma_ali15x3(ide_hwif_t *hwif, - const struct ide_port_info *d) +static int init_dma_ali15x3(ide_hwif_t *hwif, const struct ide_port_info *d) { struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long base = ide_pci_dma_base(hwif, d); @@ -502,17 +501,17 @@ static const struct ide_port_ops ali_port_ops = { static const struct ide_dma_ops ali_dma_ops = { .dma_host_set = ide_dma_host_set, - .dma_setup = ali15x3_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, + .dma_setup = ide_dma_setup, .dma_start = ide_dma_start, .dma_end = ide_dma_end, .dma_test_irq = ide_dma_test_irq, .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, + .dma_check = ali_dma_check, + .dma_timer_expiry = ide_dma_sff_timer_expiry, .dma_sff_read_status = ide_dma_sff_read_status, }; -static const struct ide_port_info ali15x3_chipset __devinitdata = { +static const struct ide_port_info ali15x3_chipset = { .name = DRV_NAME, .init_chipset = init_chipset_ali15x3, .init_hwif = init_hwif_ali15x3, @@ -532,7 +531,8 @@ static const struct ide_port_info ali15x3_chipset __devinitdata = { * hot plug layer. */ -static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) +static int alim15x3_init_one(struct pci_dev *dev, + const struct pci_device_id *id) { struct ide_port_info d = ali15x3_chipset; u8 rev = dev->revision, idx = id->driver_data; @@ -597,6 +597,6 @@ static void __exit ali15x3_ide_exit(void) module_init(ali15x3_ide_init); module_exit(ali15x3_ide_exit); -MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox"); +MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox, Bartlomiej Zolnierkiewicz"); MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE"); MODULE_LICENSE("GPL"); |
