linux/drivers/ata/pata_radisys.c
<<
>>
Prefs
   1/*
   2 *    pata_radisys.c - Intel PATA/SATA controllers
   3 *
   4 *      (C) 2006 Red Hat <alan@lxorguk.ukuu.org.uk>
   5 *
   6 *    Some parts based on ata_piix.c by Jeff Garzik and others.
   7 *
   8 *    A PIIX relative, this device has a single ATA channel and no
   9 *    slave timings, SITRE or PPE. In that sense it is a close relative
  10 *    of the original PIIX. It does however support UDMA 33/66 per channel
  11 *    although no other modes/timings. Also lacking is 32bit I/O on the ATA
  12 *    port.
  13 */
  14
  15#include <linux/kernel.h>
  16#include <linux/module.h>
  17#include <linux/pci.h>
  18#include <linux/init.h>
  19#include <linux/blkdev.h>
  20#include <linux/delay.h>
  21#include <linux/device.h>
  22#include <scsi/scsi_host.h>
  23#include <linux/libata.h>
  24#include <linux/ata.h>
  25
  26#define DRV_NAME        "pata_radisys"
  27#define DRV_VERSION     "0.4.4"
  28
  29/**
  30 *      radisys_set_piomode - Initialize host controller PATA PIO timings
  31 *      @ap: ATA port
  32 *      @adev: Device whose timings we are configuring
  33 *
  34 *      Set PIO mode for device, in host controller PCI config space.
  35 *
  36 *      LOCKING:
  37 *      None (inherited from caller).
  38 */
  39
  40static void radisys_set_piomode (struct ata_port *ap, struct ata_device *adev)
  41{
  42        unsigned int pio        = adev->pio_mode - XFER_PIO_0;
  43        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
  44        u16 idetm_data;
  45        int control = 0;
  46
  47        /*
  48         *      See Intel Document 298600-004 for the timing programing rules
  49         *      for PIIX/ICH. Note that the early PIIX does not have the slave
  50         *      timing port at 0x44. The Radisys is a relative of the PIIX
  51         *      but not the same so be careful.
  52         */
  53
  54        static const     /* ISP  RTC */
  55        u8 timings[][2] = { { 0, 0 },   /* Check me */
  56                            { 0, 0 },
  57                            { 1, 1 },
  58                            { 2, 2 },
  59                            { 3, 3 }, };
  60
  61        if (pio > 0)
  62                control |= 1;   /* TIME1 enable */
  63        if (ata_pio_need_iordy(adev))
  64                control |= 2;   /* IE IORDY */
  65
  66        pci_read_config_word(dev, 0x40, &idetm_data);
  67
  68        /* Enable IE and TIME as appropriate. Clear the other
  69           drive timing bits */
  70        idetm_data &= 0xCCCC;
  71        idetm_data |= (control << (4 * adev->devno));
  72        idetm_data |= (timings[pio][0] << 12) |
  73                        (timings[pio][1] << 8);
  74        pci_write_config_word(dev, 0x40, idetm_data);
  75
  76        /* Track which port is configured */
  77        ap->private_data = adev;
  78}
  79
  80/**
  81 *      radisys_set_dmamode - Initialize host controller PATA DMA timings
  82 *      @ap: Port whose timings we are configuring
  83 *      @adev: Device to program
  84 *
  85 *      Set MWDMA mode for device, in host controller PCI config space.
  86 *
  87 *      LOCKING:
  88 *      None (inherited from caller).
  89 */
  90
  91static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
  92{
  93        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
  94        u16 idetm_data;
  95        u8 udma_enable;
  96
  97        static const     /* ISP  RTC */
  98        u8 timings[][2] = { { 0, 0 },
  99                            { 0, 0 },
 100                            { 1, 1 },
 101                            { 2, 2 },
 102                            { 3, 3 }, };
 103
 104        /*
 105         * MWDMA is driven by the PIO timings. We must also enable
 106         * IORDY unconditionally.
 107         */
 108
 109        pci_read_config_word(dev, 0x40, &idetm_data);
 110        pci_read_config_byte(dev, 0x48, &udma_enable);
 111
 112        if (adev->dma_mode < XFER_UDMA_0) {
 113                unsigned int mwdma      = adev->dma_mode - XFER_MW_DMA_0;
 114                const unsigned int needed_pio[3] = {
 115                        XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
 116                };
 117                int pio = needed_pio[mwdma] - XFER_PIO_0;
 118                int control = 3;        /* IORDY|TIME0 */
 119
 120                /* If the drive MWDMA is faster than it can do PIO then
 121                   we must force PIO0 for PIO cycles. */
 122
 123                if (adev->pio_mode < needed_pio[mwdma])
 124                        control = 1;
 125
 126                /* Mask out the relevant control and timing bits we will load. Also
 127                   clear the other drive TIME register as a precaution */
 128
 129                idetm_data &= 0xCCCC;
 130                idetm_data |= control << (4 * adev->devno);
 131                idetm_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
 132
 133                udma_enable &= ~(1 << adev->devno);
 134        } else {
 135                u8 udma_mode;
 136
 137                /* UDMA66 on: UDMA 33 and 66 are switchable via register 0x4A */
 138
 139                pci_read_config_byte(dev, 0x4A, &udma_mode);
 140
 141                if (adev->xfer_mode == XFER_UDMA_2)
 142                        udma_mode &= ~(2 << (adev->devno * 4));
 143                else /* UDMA 4 */
 144                        udma_mode |= (2 << (adev->devno * 4));
 145
 146                pci_write_config_byte(dev, 0x4A, udma_mode);
 147
 148                udma_enable |= (1 << adev->devno);
 149        }
 150        pci_write_config_word(dev, 0x40, idetm_data);
 151        pci_write_config_byte(dev, 0x48, udma_enable);
 152
 153        /* Track which port is configured */
 154        ap->private_data = adev;
 155}
 156
 157/**
 158 *      radisys_qc_issue        -       command issue
 159 *      @qc: command pending
 160 *
 161 *      Called when the libata layer is about to issue a command. We wrap
 162 *      this interface so that we can load the correct ATA timings if
 163 *      necessary. Our logic also clears TIME0/TIME1 for the other device so
 164 *      that, even if we get this wrong, cycles to the other device will
 165 *      be made PIO0.
 166 */
 167
 168static unsigned int radisys_qc_issue(struct ata_queued_cmd *qc)
 169{
 170        struct ata_port *ap = qc->ap;
 171        struct ata_device *adev = qc->dev;
 172
 173        if (adev != ap->private_data) {
 174                /* UDMA timing is not shared */
 175                if (adev->dma_mode < XFER_UDMA_0) {
 176                        if (adev->dma_mode)
 177                                radisys_set_dmamode(ap, adev);
 178                        else if (adev->pio_mode)
 179                                radisys_set_piomode(ap, adev);
 180                }
 181        }
 182        return ata_bmdma_qc_issue(qc);
 183}
 184
 185
 186static struct scsi_host_template radisys_sht = {
 187        ATA_BMDMA_SHT(DRV_NAME),
 188};
 189
 190static struct ata_port_operations radisys_pata_ops = {
 191        .inherits               = &ata_bmdma_port_ops,
 192        .qc_issue               = radisys_qc_issue,
 193        .cable_detect           = ata_cable_unknown,
 194        .set_piomode            = radisys_set_piomode,
 195        .set_dmamode            = radisys_set_dmamode,
 196};
 197
 198
 199/**
 200 *      radisys_init_one - Register PIIX ATA PCI device with kernel services
 201 *      @pdev: PCI device to register
 202 *      @ent: Entry in radisys_pci_tbl matching with @pdev
 203 *
 204 *      Called from kernel PCI layer.  We probe for combined mode (sigh),
 205 *      and then hand over control to libata, for it to do the rest.
 206 *
 207 *      LOCKING:
 208 *      Inherited from PCI layer (may sleep).
 209 *
 210 *      RETURNS:
 211 *      Zero on success, or -ERRNO value.
 212 */
 213
 214static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 215{
 216        static const struct ata_port_info info = {
 217                .flags          = ATA_FLAG_SLAVE_POSS,
 218                .pio_mask       = ATA_PIO4,
 219                .mwdma_mask     = ATA_MWDMA12_ONLY,
 220                .udma_mask      = ATA_UDMA24_ONLY,
 221                .port_ops       = &radisys_pata_ops,
 222        };
 223        const struct ata_port_info *ppi[] = { &info, NULL };
 224
 225        ata_print_version_once(&pdev->dev, DRV_VERSION);
 226
 227        return ata_pci_bmdma_init_one(pdev, ppi, &radisys_sht, NULL, 0);
 228}
 229
 230static const struct pci_device_id radisys_pci_tbl[] = {
 231        { PCI_VDEVICE(RADISYS, 0x8201), },
 232
 233        { }     /* terminate list */
 234};
 235
 236static struct pci_driver radisys_pci_driver = {
 237        .name                   = DRV_NAME,
 238        .id_table               = radisys_pci_tbl,
 239        .probe                  = radisys_init_one,
 240        .remove                 = ata_pci_remove_one,
 241#ifdef CONFIG_PM
 242        .suspend                = ata_pci_device_suspend,
 243        .resume                 = ata_pci_device_resume,
 244#endif
 245};
 246
 247module_pci_driver(radisys_pci_driver);
 248
 249MODULE_AUTHOR("Alan Cox");
 250MODULE_DESCRIPTION("SCSI low-level driver for Radisys R82600 controllers");
 251MODULE_LICENSE("GPL");
 252MODULE_DEVICE_TABLE(pci, radisys_pci_tbl);
 253MODULE_VERSION(DRV_VERSION);
 254
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.