linux/drivers/ata/pata_sch.c
<<
>>
Prefs
   1/*
   2 *  pata_sch.c - Intel SCH PATA controllers
   3 *
   4 *  Copyright (c) 2008 Alek Du <alek.du@intel.com>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License 2 as published
   8 *  by the Free Software Foundation.
   9 *
  10 *  This program is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 *  GNU General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU General Public License
  16 *  along with this program; see the file COPYING.  If not, write to
  17 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18 *
  19 */
  20
  21/*
  22 *  Supports:
  23 *    Intel SCH (AF82US15W, AF82US15L, AF82UL11L) chipsets -- see spec at:
  24 *    http://download.intel.com/design/chipsets/embedded/datashts/319537.pdf
  25 */
  26
  27#include <linux/kernel.h>
  28#include <linux/module.h>
  29#include <linux/pci.h>
  30#include <linux/init.h>
  31#include <linux/blkdev.h>
  32#include <linux/delay.h>
  33#include <linux/device.h>
  34#include <scsi/scsi_host.h>
  35#include <linux/libata.h>
  36#include <linux/dmi.h>
  37
  38#define DRV_NAME        "pata_sch"
  39#define DRV_VERSION     "0.2"
  40
  41/* see SCH datasheet page 351 */
  42enum {
  43        D0TIM   = 0x80,         /* Device 0 Timing Register */
  44        D1TIM   = 0x84,         /* Device 1 Timing Register */
  45        PM      = 0x07,         /* PIO Mode Bit Mask */
  46        MDM     = (0x03 << 8),  /* Multi-word DMA Mode Bit Mask */
  47        UDM     = (0x07 << 16), /* Ultra DMA Mode Bit Mask */
  48        PPE     = (1 << 30),    /* Prefetch/Post Enable */
  49        USD     = (1 << 31),    /* Use Synchronous DMA */
  50};
  51
  52static int sch_init_one(struct pci_dev *pdev,
  53                         const struct pci_device_id *ent);
  54static void sch_set_piomode(struct ata_port *ap, struct ata_device *adev);
  55static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev);
  56
  57static const struct pci_device_id sch_pci_tbl[] = {
  58        /* Intel SCH PATA Controller */
  59        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SCH_IDE), 0 },
  60        { }     /* terminate list */
  61};
  62
  63static struct pci_driver sch_pci_driver = {
  64        .name                   = DRV_NAME,
  65        .id_table               = sch_pci_tbl,
  66        .probe                  = sch_init_one,
  67        .remove                 = ata_pci_remove_one,
  68#ifdef CONFIG_PM
  69        .suspend                = ata_pci_device_suspend,
  70        .resume                 = ata_pci_device_resume,
  71#endif
  72};
  73
  74static struct scsi_host_template sch_sht = {
  75        ATA_BMDMA_SHT(DRV_NAME),
  76};
  77
  78static struct ata_port_operations sch_pata_ops = {
  79        .inherits               = &ata_bmdma_port_ops,
  80        .cable_detect           = ata_cable_unknown,
  81        .set_piomode            = sch_set_piomode,
  82        .set_dmamode            = sch_set_dmamode,
  83};
  84
  85static struct ata_port_info sch_port_info = {
  86        .flags          = ATA_FLAG_SLAVE_POSS,
  87        .pio_mask       = ATA_PIO4,
  88        .mwdma_mask     = ATA_MWDMA2,
  89        .udma_mask      = ATA_UDMA5,
  90        .port_ops       = &sch_pata_ops,
  91};
  92
  93MODULE_AUTHOR("Alek Du <alek.du@intel.com>");
  94MODULE_DESCRIPTION("SCSI low-level driver for Intel SCH PATA controllers");
  95MODULE_LICENSE("GPL");
  96MODULE_DEVICE_TABLE(pci, sch_pci_tbl);
  97MODULE_VERSION(DRV_VERSION);
  98
  99/**
 100 *      sch_set_piomode - Initialize host controller PATA PIO timings
 101 *      @ap: Port whose timings we are configuring
 102 *      @adev: ATA device
 103 *
 104 *      Set PIO mode for device, in host controller PCI config space.
 105 *
 106 *      LOCKING:
 107 *      None (inherited from caller).
 108 */
 109
 110static void sch_set_piomode(struct ata_port *ap, struct ata_device *adev)
 111{
 112        unsigned int pio        = adev->pio_mode - XFER_PIO_0;
 113        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
 114        unsigned int port       = adev->devno ? D1TIM : D0TIM;
 115        unsigned int data;
 116
 117        pci_read_config_dword(dev, port, &data);
 118        /* see SCH datasheet page 351 */
 119        /* set PIO mode */
 120        data &= ~(PM | PPE);
 121        data |= pio;
 122        /* enable PPE for block device */
 123        if (adev->class == ATA_DEV_ATA)
 124                data |= PPE;
 125        pci_write_config_dword(dev, port, data);
 126}
 127
 128/**
 129 *      sch_set_dmamode - Initialize host controller PATA DMA timings
 130 *      @ap: Port whose timings we are configuring
 131 *      @adev: ATA device
 132 *
 133 *      Set MW/UDMA mode for device, in host controller PCI config space.
 134 *
 135 *      LOCKING:
 136 *      None (inherited from caller).
 137 */
 138
 139static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 140{
 141        unsigned int dma_mode   = adev->dma_mode;
 142        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
 143        unsigned int port       = adev->devno ? D1TIM : D0TIM;
 144        unsigned int data;
 145
 146        pci_read_config_dword(dev, port, &data);
 147        /* see SCH datasheet page 351 */
 148        if (dma_mode >= XFER_UDMA_0) {
 149                /* enable Synchronous DMA mode */
 150                data |= USD;
 151                data &= ~UDM;
 152                data |= (dma_mode - XFER_UDMA_0) << 16;
 153        } else { /* must be MWDMA mode, since we masked SWDMA already */
 154                data &= ~(USD | MDM);
 155                data |= (dma_mode - XFER_MW_DMA_0) << 8;
 156        }
 157        pci_write_config_dword(dev, port, data);
 158}
 159
 160/**
 161 *      sch_init_one - Register SCH ATA PCI device with kernel services
 162 *      @pdev: PCI device to register
 163 *      @ent: Entry in sch_pci_tbl matching with @pdev
 164 *
 165 *      LOCKING:
 166 *      Inherited from PCI layer (may sleep).
 167 *
 168 *      RETURNS:
 169 *      Zero on success, or -ERRNO value.
 170 */
 171
 172static int sch_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 173{
 174        const struct ata_port_info *ppi[] = { &sch_port_info, NULL };
 175
 176        ata_print_version_once(&pdev->dev, DRV_VERSION);
 177
 178        return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0);
 179}
 180
 181module_pci_driver(sch_pci_driver);
 182
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.