linux/drivers/ide/pci/slc90e66.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/ide/pci/slc90e66.c    Version 0.19    Sep 24, 2007
   3 *
   4 *  Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
   5 *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
   6 *
   7 * This is a look-alike variation of the ICH0 PIIX4 Ultra-66,
   8 * but this keeps the ISA-Bridge and slots alive.
   9 *
  10 */
  11
  12#include <linux/types.h>
  13#include <linux/module.h>
  14#include <linux/kernel.h>
  15#include <linux/ioport.h>
  16#include <linux/pci.h>
  17#include <linux/hdreg.h>
  18#include <linux/ide.h>
  19#include <linux/delay.h>
  20#include <linux/init.h>
  21
  22#include <asm/io.h>
  23
  24static DEFINE_SPINLOCK(slc90e66_lock);
  25
  26static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
  27{
  28        ide_hwif_t *hwif        = HWIF(drive);
  29        struct pci_dev *dev     = hwif->pci_dev;
  30        int is_slave            = drive->dn & 1;
  31        int master_port         = hwif->channel ? 0x42 : 0x40;
  32        int slave_port          = 0x44;
  33        unsigned long flags;
  34        u16 master_data;
  35        u8 slave_data;
  36        int control = 0;
  37                                     /* ISP  RTC */
  38        static const u8 timings[][2]= {
  39                                        { 0, 0 },
  40                                        { 0, 0 },
  41                                        { 1, 0 },
  42                                        { 2, 1 },
  43                                        { 2, 3 }, };
  44
  45        spin_lock_irqsave(&slc90e66_lock, flags);
  46        pci_read_config_word(dev, master_port, &master_data);
  47
  48        if (pio > 1)
  49                control |= 1;   /* Programmable timing on */
  50        if (drive->media == ide_disk)
  51                control |= 4;   /* Prefetch, post write */
  52        if (pio > 2)
  53                control |= 2;   /* IORDY */
  54        if (is_slave) {
  55                master_data |=  0x4000;
  56                master_data &= ~0x0070;
  57                if (pio > 1) {
  58                        /* Set PPE, IE and TIME */
  59                        master_data |= control << 4;
  60                }
  61                pci_read_config_byte(dev, slave_port, &slave_data);
  62                slave_data &= hwif->channel ? 0x0f : 0xf0;
  63                slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) <<
  64                               (hwif->channel ? 4 : 0);
  65        } else {
  66                master_data &= ~0x3307;
  67                if (pio > 1) {
  68                        /* enable PPE, IE and TIME */
  69                        master_data |= control;
  70                }
  71                master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
  72        }
  73        pci_write_config_word(dev, master_port, master_data);
  74        if (is_slave)
  75                pci_write_config_byte(dev, slave_port, slave_data);
  76        spin_unlock_irqrestore(&slc90e66_lock, flags);
  77}
  78
  79static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
  80{
  81        ide_hwif_t *hwif        = HWIF(drive);
  82        struct pci_dev *dev     = hwif->pci_dev;
  83        u8 maslave              = hwif->channel ? 0x42 : 0x40;
  84        int sitre = 0, a_speed  = 7 << (drive->dn * 4);
  85        int u_speed = 0, u_flag = 1 << drive->dn;
  86        u16                     reg4042, reg44, reg48, reg4a;
  87
  88        pci_read_config_word(dev, maslave, &reg4042);
  89        sitre = (reg4042 & 0x4000) ? 1 : 0;
  90        pci_read_config_word(dev, 0x44, &reg44);
  91        pci_read_config_word(dev, 0x48, &reg48);
  92        pci_read_config_word(dev, 0x4a, &reg4a);
  93
  94        switch(speed) {
  95                case XFER_UDMA_4:       u_speed = 4 << (drive->dn * 4); break;
  96                case XFER_UDMA_3:       u_speed = 3 << (drive->dn * 4); break;
  97                case XFER_UDMA_2:       u_speed = 2 << (drive->dn * 4); break;
  98                case XFER_UDMA_1:       u_speed = 1 << (drive->dn * 4); break;
  99                case XFER_UDMA_0:       u_speed = 0 << (drive->dn * 4); break;
 100                case XFER_MW_DMA_2:
 101                case XFER_MW_DMA_1:
 102                case XFER_SW_DMA_2:     break;
 103                default:                return;
 104        }
 105
 106        if (speed >= XFER_UDMA_0) {
 107                if (!(reg48 & u_flag))
 108                        pci_write_config_word(dev, 0x48, reg48|u_flag);
 109                /* FIXME: (reg4a & a_speed) ? */
 110                if ((reg4a & u_speed) != u_speed) {
 111                        pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
 112                        pci_read_config_word(dev, 0x4a, &reg4a);
 113                        pci_write_config_word(dev, 0x4a, reg4a|u_speed);
 114                }
 115        } else {
 116                const u8 mwdma_to_pio[] = { 0, 3, 4 };
 117                u8 pio;
 118
 119                if (reg48 & u_flag)
 120                        pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
 121                if (reg4a & a_speed)
 122                        pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
 123
 124                if (speed >= XFER_MW_DMA_0)
 125                        pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
 126                else
 127                        pio = 2; /* only SWDMA2 is allowed */
 128
 129                slc90e66_set_pio_mode(drive, pio);
 130        }
 131}
 132
 133static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
 134{
 135        u8 reg47 = 0;
 136        u8 mask = hwif->channel ? 0x01 : 0x02;  /* bit0:Primary */
 137
 138        hwif->set_pio_mode = &slc90e66_set_pio_mode;
 139        hwif->set_dma_mode = &slc90e66_set_dma_mode;
 140
 141        pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
 142
 143        if (hwif->dma_base == 0)
 144                return;
 145
 146        if (hwif->cbl != ATA_CBL_PATA40_SHORT)
 147                /* bit[0(1)]: 0:80, 1:40 */
 148                hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 149}
 150
 151static const struct ide_port_info slc90e66_chipset __devinitdata = {
 152        .name           = "SLC90E66",
 153        .init_hwif      = init_hwif_slc90e66,
 154        .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
 155        .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
 156        .pio_mask       = ATA_PIO4,
 157        .swdma_mask     = ATA_SWDMA2_ONLY,
 158        .mwdma_mask     = ATA_MWDMA12_ONLY,
 159        .udma_mask      = ATA_UDMA4,
 160};
 161
 162static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 163{
 164        return ide_setup_pci_device(dev, &slc90e66_chipset);
 165}
 166
 167static const struct pci_device_id slc90e66_pci_tbl[] = {
 168        { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0 },
 169        { 0, },
 170};
 171MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
 172
 173static struct pci_driver driver = {
 174        .name           = "SLC90e66_IDE",
 175        .id_table       = slc90e66_pci_tbl,
 176        .probe          = slc90e66_init_one,
 177};
 178
 179static int __init slc90e66_ide_init(void)
 180{
 181        return ide_pci_register_driver(&driver);
 182}
 183
 184module_init(slc90e66_ide_init);
 185
 186MODULE_AUTHOR("Andre Hedrick");
 187MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE");
 188MODULE_LICENSE("GPL");
 189
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.