root/drivers/ide/ide-cs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ide_probe
  2. ide_detach
  3. idecs_register
  4. pcmcia_check_one_config
  5. ide_config
  6. ide_release
  7. init_ide_cs
  8. exit_ide_cs

   1 /*======================================================================
   2 
   3     A driver for PCMCIA IDE/ATA disk cards
   4 
   5     The contents of this file are subject to the Mozilla Public
   6     License Version 1.1 (the "License"); you may not use this file
   7     except in compliance with the License. You may obtain a copy of
   8     the License at http://www.mozilla.org/MPL/
   9 
  10     Software distributed under the License is distributed on an "AS
  11     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  12     implied. See the License for the specific language governing
  13     rights and limitations under the License.
  14 
  15     The initial developer of the original code is David A. Hinds
  16     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  17     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  18 
  19     Alternatively, the contents of this file may be used under the
  20     terms of the GNU General Public License version 2 (the "GPL"), in
  21     which case the provisions of the GPL are applicable instead of the
  22     above.  If you wish to allow the use of your version of this file
  23     only under the terms of the GPL and not to allow others to use
  24     your version of this file under the MPL, indicate your decision
  25     by deleting the provisions above and replace them with the notice
  26     and other provisions required by the GPL.  If you do not delete
  27     the provisions above, a recipient may use your version of this
  28     file under either the MPL or the GPL.
  29 
  30 ======================================================================*/
  31 
  32 #include <linux/module.h>
  33 #include <linux/kernel.h>
  34 #include <linux/init.h>
  35 #include <linux/ptrace.h>
  36 #include <linux/slab.h>
  37 #include <linux/string.h>
  38 #include <linux/timer.h>
  39 #include <linux/ioport.h>
  40 #include <linux/ide.h>
  41 #include <linux/major.h>
  42 #include <linux/delay.h>
  43 #include <asm/io.h>
  44 
  45 #include <pcmcia/cistpl.h>
  46 #include <pcmcia/ds.h>
  47 #include <pcmcia/cisreg.h>
  48 #include <pcmcia/ciscode.h>
  49 
  50 #define DRV_NAME "ide-cs"
  51 
  52 /*====================================================================*/
  53 
  54 /* Module parameters */
  55 
  56 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
  57 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
  58 MODULE_LICENSE("Dual MPL/GPL");
  59 
  60 /*====================================================================*/
  61 
  62 typedef struct ide_info_t {
  63         struct pcmcia_device    *p_dev;
  64         struct ide_host         *host;
  65         int                     ndev;
  66 } ide_info_t;
  67 
  68 static void ide_release(struct pcmcia_device *);
  69 static int ide_config(struct pcmcia_device *);
  70 
  71 static void ide_detach(struct pcmcia_device *p_dev);
  72 
  73 static int ide_probe(struct pcmcia_device *link)
  74 {
  75     ide_info_t *info;
  76 
  77     dev_dbg(&link->dev, "ide_attach()\n");
  78 
  79     /* Create new ide device */
  80     info = kzalloc(sizeof(*info), GFP_KERNEL);
  81     if (!info)
  82         return -ENOMEM;
  83 
  84     info->p_dev = link;
  85     link->priv = info;
  86 
  87     link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
  88             CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
  89 
  90     return ide_config(link);
  91 } /* ide_attach */
  92 
  93 static void ide_detach(struct pcmcia_device *link)
  94 {
  95     ide_info_t *info = link->priv;
  96 
  97     dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
  98 
  99     ide_release(link);
 100 
 101     kfree(info);
 102 } /* ide_detach */
 103 
 104 static const struct ide_port_ops idecs_port_ops = {
 105         .quirkproc              = ide_undecoded_slave,
 106 };
 107 
 108 static const struct ide_port_info idecs_port_info = {
 109         .port_ops               = &idecs_port_ops,
 110         .host_flags             = IDE_HFLAG_NO_DMA,
 111         .irq_flags              = IRQF_SHARED,
 112         .chipset                = ide_pci,
 113 };
 114 
 115 static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
 116                                 unsigned long irq, struct pcmcia_device *handle)
 117 {
 118     struct ide_host *host;
 119     ide_hwif_t *hwif;
 120     int i, rc;
 121     struct ide_hw hw, *hws[] = { &hw };
 122 
 123     if (!request_region(io, 8, DRV_NAME)) {
 124         printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
 125                         DRV_NAME, io, io + 7);
 126         return NULL;
 127     }
 128 
 129     if (!request_region(ctl, 1, DRV_NAME)) {
 130         printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
 131                         DRV_NAME, ctl);
 132         release_region(io, 8);
 133         return NULL;
 134     }
 135 
 136     memset(&hw, 0, sizeof(hw));
 137     ide_std_init_ports(&hw, io, ctl);
 138     hw.irq = irq;
 139     hw.dev = &handle->dev;
 140 
 141     rc = ide_host_add(&idecs_port_info, hws, 1, &host);
 142     if (rc)
 143         goto out_release;
 144 
 145     hwif = host->ports[0];
 146 
 147     if (hwif->present)
 148         return host;
 149 
 150     /* retry registration in case device is still spinning up */
 151     for (i = 0; i < 10; i++) {
 152         msleep(100);
 153         ide_port_scan(hwif);
 154         if (hwif->present)
 155             return host;
 156     }
 157 
 158     return host;
 159 
 160 out_release:
 161     release_region(ctl, 1);
 162     release_region(io, 8);
 163     return NULL;
 164 }
 165 
 166 static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
 167 {
 168         int *is_kme = priv_data;
 169 
 170         if ((pdev->resource[0]->flags & IO_DATA_PATH_WIDTH)
 171             != IO_DATA_PATH_WIDTH_8) {
 172                 pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
 173                 pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 174         }
 175         pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
 176         pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 177 
 178         if (pdev->resource[1]->end) {
 179                 pdev->resource[0]->end = 8;
 180                 pdev->resource[1]->end = (*is_kme) ? 2 : 1;
 181         } else {
 182                 if (pdev->resource[0]->end < 16)
 183                         return -ENODEV;
 184         }
 185 
 186         return pcmcia_request_io(pdev);
 187 }
 188 
 189 static int ide_config(struct pcmcia_device *link)
 190 {
 191     ide_info_t *info = link->priv;
 192     int ret = 0, is_kme = 0;
 193     unsigned long io_base, ctl_base;
 194     struct ide_host *host;
 195 
 196     dev_dbg(&link->dev, "ide_config(0x%p)\n", link);
 197 
 198     is_kme = ((link->manf_id == MANFID_KME) &&
 199               ((link->card_id == PRODID_KME_KXLC005_A) ||
 200                (link->card_id == PRODID_KME_KXLC005_B)));
 201 
 202     if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
 203             link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 204             if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
 205                     goto failed; /* No suitable config found */
 206     }
 207     io_base = link->resource[0]->start;
 208     if (link->resource[1]->end)
 209             ctl_base = link->resource[1]->start;
 210     else
 211             ctl_base = link->resource[0]->start + 0x0e;
 212 
 213     if (!link->irq)
 214             goto failed;
 215 
 216     ret = pcmcia_enable_device(link);
 217     if (ret)
 218             goto failed;
 219 
 220     /* disable drive interrupts during IDE probe */
 221     outb(0x02, ctl_base);
 222 
 223     /* special setup for KXLC005 card */
 224     if (is_kme)
 225         outb(0x81, ctl_base+1);
 226 
 227      host = idecs_register(io_base, ctl_base, link->irq, link);
 228      if (host == NULL && resource_size(link->resource[0]) == 0x20) {
 229             outb(0x02, ctl_base + 0x10);
 230             host = idecs_register(io_base + 0x10, ctl_base + 0x10,
 231                                   link->irq, link);
 232     }
 233 
 234     if (host == NULL)
 235         goto failed;
 236 
 237     info->ndev = 1;
 238     info->host = host;
 239     dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n",
 240             'a' + host->ports[0]->index * 2,
 241             link->vpp / 10, link->vpp % 10);
 242 
 243     return 0;
 244 
 245 failed:
 246     ide_release(link);
 247     return -ENODEV;
 248 } /* ide_config */
 249 
 250 static void ide_release(struct pcmcia_device *link)
 251 {
 252     ide_info_t *info = link->priv;
 253     struct ide_host *host = info->host;
 254 
 255     dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
 256 
 257     if (info->ndev) {
 258         ide_hwif_t *hwif = host->ports[0];
 259         unsigned long data_addr, ctl_addr;
 260 
 261         data_addr = hwif->io_ports.data_addr;
 262         ctl_addr = hwif->io_ports.ctl_addr;
 263 
 264         ide_host_remove(host);
 265         info->ndev = 0;
 266 
 267         release_region(ctl_addr, 1);
 268         release_region(data_addr, 8);
 269     }
 270 
 271     pcmcia_disable_device(link);
 272 } /* ide_release */
 273 
 274 
 275 static const struct pcmcia_device_id ide_ids[] = {
 276         PCMCIA_DEVICE_FUNC_ID(4),
 277         PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
 278         PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
 279         PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
 280         PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
 281         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
 282         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
 283         PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
 284         PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
 285         PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
 286         PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
 287         PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
 288         PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
 289         PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
 290         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
 291         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
 292         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
 293         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
 294         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
 295         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
 296         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
 297         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
 298         PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
 299         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
 300         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
 301         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
 302         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
 303         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
 304         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
 305         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
 306         PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
 307         PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
 308         PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
 309         PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
 310         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
 311         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb),
 312         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),
 313         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
 314         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
 315         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
 316         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
 317         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
 318         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
 319         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
 320         PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
 321         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
 322         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
 323         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
 324         PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
 325         PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
 326         PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
 327         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
 328         PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
 329         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
 330         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
 331         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
 332         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
 333         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133),
 334         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),
 335         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
 336         PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
 337         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
 338         PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
 339         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
 340         PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
 341         PCMCIA_DEVICE_NULL,
 342 };
 343 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
 344 
 345 static struct pcmcia_driver ide_cs_driver = {
 346         .owner          = THIS_MODULE,
 347         .name           = "ide-cs",
 348         .probe          = ide_probe,
 349         .remove         = ide_detach,
 350         .id_table       = ide_ids,
 351 };
 352 
 353 static int __init init_ide_cs(void)
 354 {
 355         return pcmcia_register_driver(&ide_cs_driver);
 356 }
 357 
 358 static void __exit exit_ide_cs(void)
 359 {
 360         pcmcia_unregister_driver(&ide_cs_driver);
 361 }
 362 
 363 late_initcall(init_ide_cs);
 364 module_exit(exit_ide_cs);

/* [<][>][^][v][top][bottom][index][help] */