linux/drivers/ide/jmicron.c
<<
>>
Prefs
   1
   2/*
   3 * Copyright (C) 2006           Red Hat
   4 *
   5 *  May be copied or modified under the terms of the GNU General Public License
   6 */
   7
   8#include <linux/types.h>
   9#include <linux/module.h>
  10#include <linux/pci.h>
  11#include <linux/ide.h>
  12#include <linux/init.h>
  13
  14#define DRV_NAME "jmicron"
  15
  16typedef enum {
  17        PORT_PATA0 = 0,
  18        PORT_PATA1 = 1,
  19        PORT_SATA = 2,
  20} port_type;
  21
  22/**
  23 *      jmicron_cable_detect    -       cable detection
  24 *      @hwif: IDE port
  25 *
  26 *      Returns the cable type.
  27 */
  28
  29static u8 jmicron_cable_detect(ide_hwif_t *hwif)
  30{
  31        struct pci_dev *pdev = to_pci_dev(hwif->dev);
  32
  33        u32 control;
  34        u32 control5;
  35
  36        int port = hwif->channel;
  37        port_type port_map[2];
  38
  39        pci_read_config_dword(pdev, 0x40, &control);
  40
  41        /* There are two basic mappings. One has the two SATA ports merged
  42           as master/slave and the secondary as PATA, the other has only the
  43           SATA port mapped */
  44        if (control & (1 << 23)) {
  45                port_map[0] = PORT_SATA;
  46                port_map[1] = PORT_PATA0;
  47        } else {
  48                port_map[0] = PORT_SATA;
  49                port_map[1] = PORT_SATA;
  50        }
  51
  52        /* The 365/366 may have this bit set to map the second PATA port
  53           as the internal primary channel */
  54        pci_read_config_dword(pdev, 0x80, &control5);
  55        if (control5 & (1<<24))
  56                port_map[0] = PORT_PATA1;
  57
  58        /* The two ports may then be logically swapped by the firmware */
  59        if (control & (1 << 22))
  60                port = port ^ 1;
  61
  62        /*
  63         *      Now we know which physical port we are talking about we can
  64         *      actually do our cable checking etc. Thankfully we don't need
  65         *      to do the plumbing for other cases.
  66         */
  67        switch (port_map[port]) {
  68        case PORT_PATA0:
  69                if (control & (1 << 3)) /* 40/80 pin primary */
  70                        return ATA_CBL_PATA40;
  71                return ATA_CBL_PATA80;
  72        case PORT_PATA1:
  73                if (control5 & (1 << 19))       /* 40/80 pin secondary */
  74                        return ATA_CBL_PATA40;
  75                return ATA_CBL_PATA80;
  76        case PORT_SATA:
  77                break;
  78        }
  79        /* Avoid bogus "control reaches end of non-void function" */
  80        return ATA_CBL_PATA80;
  81}
  82
  83static void jmicron_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
  84{
  85}
  86
  87/**
  88 *      jmicron_set_dma_mode    -       set host controller for DMA mode
  89 *      @hwif: port
  90 *      @drive: drive
  91 *
  92 *      As the JMicron snoops for timings we don't need to do anything here.
  93 */
  94
  95static void jmicron_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
  96{
  97}
  98
  99static const struct ide_port_ops jmicron_port_ops = {
 100        .set_pio_mode           = jmicron_set_pio_mode,
 101        .set_dma_mode           = jmicron_set_dma_mode,
 102        .cable_detect           = jmicron_cable_detect,
 103};
 104
 105static const struct ide_port_info jmicron_chipset = {
 106        .name           = DRV_NAME,
 107        .enablebits     = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
 108        .port_ops       = &jmicron_port_ops,
 109        .pio_mask       = ATA_PIO5,
 110        .mwdma_mask     = ATA_MWDMA2,
 111        .udma_mask      = ATA_UDMA6,
 112};
 113
 114/**
 115 *      jmicron_init_one        -       pci layer discovery entry
 116 *      @dev: PCI device
 117 *      @id: ident table entry
 118 *
 119 *      Called by the PCI code when it finds a Jmicron controller.
 120 *      We then use the IDE PCI generic helper to do most of the work.
 121 */
 122
 123static int jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 124{
 125        return ide_pci_init_one(dev, &jmicron_chipset, NULL);
 126}
 127
 128/* All JMB PATA controllers have and will continue to have the same
 129 * interface.  Matching vendor and device class is enough for all
 130 * current and future controllers if the controller is programmed
 131 * properly.
 132 *
 133 * If libata is configured, jmicron PCI quirk programs the controller
 134 * into the correct mode.  If libata isn't configured, match known
 135 * device IDs too to maintain backward compatibility.
 136 */
 137static struct pci_device_id jmicron_pci_tbl[] = {
 138#if !defined(CONFIG_ATA) && !defined(CONFIG_ATA_MODULE)
 139        { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361) },
 140        { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363) },
 141        { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365) },
 142        { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366) },
 143        { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368) },
 144#endif
 145        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 146          PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
 147        { 0, },
 148};
 149
 150MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
 151
 152static struct pci_driver jmicron_pci_driver = {
 153        .name           = "JMicron IDE",
 154        .id_table       = jmicron_pci_tbl,
 155        .probe          = jmicron_init_one,
 156        .remove         = ide_pci_remove,
 157        .suspend        = ide_pci_suspend,
 158        .resume         = ide_pci_resume,
 159};
 160
 161static int __init jmicron_ide_init(void)
 162{
 163        return ide_pci_register_driver(&jmicron_pci_driver);
 164}
 165
 166static void __exit jmicron_ide_exit(void)
 167{
 168        pci_unregister_driver(&jmicron_pci_driver);
 169}
 170
 171module_init(jmicron_ide_init);
 172module_exit(jmicron_ide_exit);
 173
 174MODULE_AUTHOR("Alan Cox");
 175MODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes");
 176MODULE_LICENSE("GPL");
 177