linux/drivers/ide/pci/delkin_cb.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/ide/pci/delkin_cb.c
   3 *
   4 *  Created 20 Oct 2004 by Mark Lord
   5 *
   6 *  Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
   7 *
   8 *  Modeled after the 16-bit PCMCIA driver: ide-cs.c
   9 *
  10 *  This is slightly peculiar, in that it is a PCI driver,
  11 *  but is NOT an IDE PCI driver -- the IDE layer does not directly
  12 *  support hot insertion/removal of PCI interfaces, so this driver
  13 *  is unable to use the IDE PCI interfaces.  Instead, it uses the
  14 *  same interfaces as the ide-cs (PCMCIA) driver uses.
  15 *  On the plus side, the driver is also smaller/simpler this way.
  16 *
  17 *  This file is subject to the terms and conditions of the GNU General Public
  18 *  License.  See the file COPYING in the main directory of this archive for
  19 *  more details.
  20 */
  21#include <linux/autoconf.h>
  22#include <linux/types.h>
  23#include <linux/module.h>
  24#include <linux/mm.h>
  25#include <linux/blkdev.h>
  26#include <linux/hdreg.h>
  27#include <linux/ide.h>
  28#include <linux/init.h>
  29#include <linux/pci.h>
  30#include <asm/io.h>
  31
  32/*
  33 * No chip documentation has yet been found,
  34 * so these configuration values were pulled from
  35 * a running Win98 system using "debug".
  36 * This gives around 3MByte/second read performance,
  37 * which is about 2/3 of what the chip is capable of.
  38 *
  39 * There is also a 4KByte mmio region on the card,
  40 * but its purpose has yet to be reverse-engineered.
  41 */
  42static const u8 setup[] = {
  43        0x00, 0x05, 0xbe, 0x01, 0x20, 0x8f, 0x00, 0x00,
  44        0xa4, 0x1f, 0xb3, 0x1b, 0x00, 0x00, 0x00, 0x80,
  45        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  46        0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13,
  47};
  48
  49static int __devinit
  50delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
  51{
  52        unsigned long base;
  53        hw_regs_t hw;
  54        ide_hwif_t *hwif = NULL;
  55        ide_drive_t *drive;
  56        int i, rc;
  57
  58        rc = pci_enable_device(dev);
  59        if (rc) {
  60                printk(KERN_ERR "delkin_cb: pci_enable_device failed (%d)\n", rc);
  61                return rc;
  62        }
  63        rc = pci_request_regions(dev, "delkin_cb");
  64        if (rc) {
  65                printk(KERN_ERR "delkin_cb: pci_request_regions failed (%d)\n", rc);
  66                pci_disable_device(dev);
  67                return rc;
  68        }
  69        base = pci_resource_start(dev, 0);
  70        outb(0x02, base + 0x1e);        /* set nIEN to block interrupts */
  71        inb(base + 0x17);               /* read status to clear interrupts */
  72        for (i = 0; i < sizeof(setup); ++i) {
  73                if (setup[i])
  74                        outb(setup[i], base + i);
  75        }
  76        pci_release_regions(dev);       /* IDE layer handles regions itself */
  77
  78        memset(&hw, 0, sizeof(hw));
  79        ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
  80        hw.irq = dev->irq;
  81        hw.chipset = ide_pci;           /* this enables IRQ sharing */
  82
  83        rc = ide_register_hw(&hw, &ide_undecoded_slave, 0, &hwif);
  84        if (rc < 0) {
  85                printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc);
  86                pci_disable_device(dev);
  87                return -ENODEV;
  88        }
  89        pci_set_drvdata(dev, hwif);
  90        hwif->pci_dev = dev;
  91        drive = &hwif->drives[0];
  92        if (drive->present) {
  93                drive->io_32bit = 1;
  94                drive->unmask   = 1;
  95        }
  96        return 0;
  97}
  98
  99static void
 100delkin_cb_remove (struct pci_dev *dev)
 101{
 102        ide_hwif_t *hwif = pci_get_drvdata(dev);
 103
 104        if (hwif)
 105                ide_unregister(hwif->index);
 106        pci_disable_device(dev);
 107}
 108
 109static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
 110        { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 111        { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 112        { 0, },
 113};
 114MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
 115
 116static struct pci_driver driver = {
 117        .name           = "Delkin-ASKA-Workbit Cardbus IDE",
 118        .id_table       = delkin_cb_pci_tbl,
 119        .probe          = delkin_cb_probe,
 120        .remove         = delkin_cb_remove,
 121};
 122
 123static int
 124delkin_cb_init (void)
 125{
 126        return pci_register_driver(&driver);
 127}
 128
 129static void
 130delkin_cb_exit (void)
 131{
 132        pci_unregister_driver(&driver);
 133}
 134
 135module_init(delkin_cb_init);
 136module_exit(delkin_cb_exit);
 137
 138MODULE_AUTHOR("Mark Lord");
 139MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE");
 140MODULE_LICENSE("GPL");
 141
 142
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.