linux/drivers/ide/ide-cs.c
<<
>>
Prefs
   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#include <asm/system.h>
  45
  46#include <pcmcia/cs_types.h>
  47#include <pcmcia/cs.h>
  48#include <pcmcia/cistpl.h>
  49#include <pcmcia/ds.h>
  50#include <pcmcia/cisreg.h>
  51#include <pcmcia/ciscode.h>
  52
  53#define DRV_NAME "ide-cs"
  54
  55/*====================================================================*/
  56
  57/* Module parameters */
  58
  59MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
  60MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
  61MODULE_LICENSE("Dual MPL/GPL");
  62
  63#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
  64
  65#ifdef CONFIG_PCMCIA_DEBUG
  66INT_MODULE_PARM(pc_debug, 0);
  67#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
  68#else
  69#define DEBUG(n, args...)
  70#endif
  71
  72/*====================================================================*/
  73
  74typedef struct ide_info_t {
  75        struct pcmcia_device    *p_dev;
  76        struct ide_host         *host;
  77    int         ndev;
  78    dev_node_t  node;
  79} ide_info_t;
  80
  81static void ide_release(struct pcmcia_device *);
  82static int ide_config(struct pcmcia_device *);
  83
  84static void ide_detach(struct pcmcia_device *p_dev);
  85
  86
  87
  88
  89/*======================================================================
  90
  91    ide_attach() creates an "instance" of the driver, allocating
  92    local data structures for one device.  The device is registered
  93    with Card Services.
  94
  95======================================================================*/
  96
  97static int ide_probe(struct pcmcia_device *link)
  98{
  99    ide_info_t *info;
 100
 101    DEBUG(0, "ide_attach()\n");
 102
 103    /* Create new ide device */
 104    info = kzalloc(sizeof(*info), GFP_KERNEL);
 105    if (!info)
 106        return -ENOMEM;
 107
 108    info->p_dev = link;
 109    link->priv = info;
 110
 111    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
 112    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
 113    link->io.IOAddrLines = 3;
 114    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 115    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 116    link->conf.Attributes = CONF_ENABLE_IRQ;
 117    link->conf.IntType = INT_MEMORY_AND_IO;
 118
 119    return ide_config(link);
 120} /* ide_attach */
 121
 122/*======================================================================
 123
 124    This deletes a driver "instance".  The device is de-registered
 125    with Card Services.  If it has been released, all local data
 126    structures are freed.  Otherwise, the structures will be freed
 127    when the device is released.
 128
 129======================================================================*/
 130
 131static void ide_detach(struct pcmcia_device *link)
 132{
 133    ide_info_t *info = link->priv;
 134    ide_hwif_t *hwif = info->host->ports[0];
 135    unsigned long data_addr, ctl_addr;
 136
 137    DEBUG(0, "ide_detach(0x%p)\n", link);
 138
 139    data_addr = hwif->io_ports.data_addr;
 140    ctl_addr  = hwif->io_ports.ctl_addr;
 141
 142    ide_release(link);
 143
 144    release_region(ctl_addr, 1);
 145    release_region(data_addr, 8);
 146
 147    kfree(info);
 148} /* ide_detach */
 149
 150static const struct ide_port_ops idecs_port_ops = {
 151        .quirkproc              = ide_undecoded_slave,
 152};
 153
 154static const struct ide_port_info idecs_port_info = {
 155        .port_ops               = &idecs_port_ops,
 156        .host_flags             = IDE_HFLAG_NO_DMA,
 157};
 158
 159static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
 160                                unsigned long irq, struct pcmcia_device *handle)
 161{
 162    struct ide_host *host;
 163    ide_hwif_t *hwif;
 164    int i, rc;
 165    hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 166
 167    if (!request_region(io, 8, DRV_NAME)) {
 168        printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
 169                        DRV_NAME, io, io + 7);
 170        return NULL;
 171    }
 172
 173    if (!request_region(ctl, 1, DRV_NAME)) {
 174        printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
 175                        DRV_NAME, ctl);
 176        release_region(io, 8);
 177        return NULL;
 178    }
 179
 180    memset(&hw, 0, sizeof(hw));
 181    ide_std_init_ports(&hw, io, ctl);
 182    hw.irq = irq;
 183    hw.chipset = ide_pci;
 184    hw.dev = &handle->dev;
 185
 186    rc = ide_host_add(&idecs_port_info, hws, &host);
 187    if (rc)
 188        goto out_release;
 189
 190    hwif = host->ports[0];
 191
 192    if (hwif->present)
 193        return host;
 194
 195    /* retry registration in case device is still spinning up */
 196    for (i = 0; i < 10; i++) {
 197        msleep(100);
 198        ide_port_scan(hwif);
 199        if (hwif->present)
 200            return host;
 201    }
 202
 203    return host;
 204
 205out_release:
 206    release_region(ctl, 1);
 207    release_region(io, 8);
 208    return NULL;
 209}
 210
 211/*======================================================================
 212
 213    ide_config() is scheduled to run after a CARD_INSERTION event
 214    is received, to configure the PCMCIA socket, and to make the
 215    ide device available to the system.
 216
 217======================================================================*/
 218
 219#define CS_CHECK(fn, ret) \
 220do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 221
 222struct pcmcia_config_check {
 223        unsigned long ctl_base;
 224        int skip_vcc;
 225        int is_kme;
 226};
 227
 228static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 229                                   cistpl_cftable_entry_t *cfg,
 230                                   cistpl_cftable_entry_t *dflt,
 231                                   unsigned int vcc,
 232                                   void *priv_data)
 233{
 234        struct pcmcia_config_check *stk = priv_data;
 235
 236        /* Check for matching Vcc, unless we're desperate */
 237        if (!stk->skip_vcc) {
 238                if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
 239                        if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
 240                                return -ENODEV;
 241                } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
 242                        if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
 243                                return -ENODEV;
 244                }
 245        }
 246
 247        if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
 248                pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 249        else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
 250                pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 251
 252        if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 253                cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
 254                pdev->conf.ConfigIndex = cfg->index;
 255                pdev->io.BasePort1 = io->win[0].base;
 256                pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
 257                if (!(io->flags & CISTPL_IO_16BIT))
 258                        pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 259                if (io->nwin == 2) {
 260                        pdev->io.NumPorts1 = 8;
 261                        pdev->io.BasePort2 = io->win[1].base;
 262                        pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
 263                        if (pcmcia_request_io(pdev, &pdev->io) != 0)
 264                                return -ENODEV;
 265                        stk->ctl_base = pdev->io.BasePort2;
 266                } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
 267                        pdev->io.NumPorts1 = io->win[0].len;
 268                        pdev->io.NumPorts2 = 0;
 269                        if (pcmcia_request_io(pdev, &pdev->io) != 0)
 270                                return -ENODEV;
 271                        stk->ctl_base = pdev->io.BasePort1 + 0x0e;
 272                } else
 273                        return -ENODEV;
 274                /* If we've got this far, we're done */
 275                return 0;
 276        }
 277        return -ENODEV;
 278}
 279
 280static int ide_config(struct pcmcia_device *link)
 281{
 282    ide_info_t *info = link->priv;
 283    struct pcmcia_config_check *stk = NULL;
 284    int last_ret = 0, last_fn = 0, is_kme = 0;
 285    unsigned long io_base, ctl_base;
 286    struct ide_host *host;
 287
 288    DEBUG(0, "ide_config(0x%p)\n", link);
 289
 290    is_kme = ((link->manf_id == MANFID_KME) &&
 291              ((link->card_id == PRODID_KME_KXLC005_A) ||
 292               (link->card_id == PRODID_KME_KXLC005_B)));
 293
 294    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
 295    if (!stk)
 296            goto err_mem;
 297    stk->is_kme = is_kme;
 298    stk->skip_vcc = io_base = ctl_base = 0;
 299
 300    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
 301            stk->skip_vcc = 1;
 302            if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
 303                    goto failed; /* No suitable config found */
 304    }
 305    io_base = link->io.BasePort1;
 306    ctl_base = stk->ctl_base;
 307
 308    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 309    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 310
 311    /* disable drive interrupts during IDE probe */
 312    outb(0x02, ctl_base);
 313
 314    /* special setup for KXLC005 card */
 315    if (is_kme)
 316        outb(0x81, ctl_base+1);
 317
 318     host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
 319     if (host == NULL && link->io.NumPorts1 == 0x20) {
 320            outb(0x02, ctl_base + 0x10);
 321            host = idecs_register(io_base + 0x10, ctl_base + 0x10,
 322                                  link->irq.AssignedIRQ, link);
 323    }
 324
 325    if (host == NULL)
 326        goto failed;
 327
 328    info->ndev = 1;
 329    sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
 330    info->node.major = host->ports[0]->major;
 331    info->node.minor = 0;
 332    info->host = host;
 333    link->dev_node = &info->node;
 334    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
 335           info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
 336
 337    kfree(stk);
 338    return 0;
 339
 340err_mem:
 341    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
 342    goto failed;
 343
 344cs_failed:
 345    cs_error(link, last_fn, last_ret);
 346failed:
 347    kfree(stk);
 348    ide_release(link);
 349    return -ENODEV;
 350} /* ide_config */
 351
 352/*======================================================================
 353
 354    After a card is removed, ide_release() will unregister the net
 355    device, and release the PCMCIA configuration.  If the device is
 356    still open, this will be postponed until it is closed.
 357
 358======================================================================*/
 359
 360static void ide_release(struct pcmcia_device *link)
 361{
 362    ide_info_t *info = link->priv;
 363    struct ide_host *host = info->host;
 364
 365    DEBUG(0, "ide_release(0x%p)\n", link);
 366
 367    if (info->ndev)
 368        /* FIXME: if this fails we need to queue the cleanup somehow
 369           -- need to investigate the required PCMCIA magic */
 370        ide_host_remove(host);
 371
 372    info->ndev = 0;
 373
 374    pcmcia_disable_device(link);
 375} /* ide_release */
 376
 377
 378/*======================================================================
 379
 380    The card status event handler.  Mostly, this schedules other
 381    stuff to run after an event is received.  A CARD_REMOVAL event
 382    also sets some flags to discourage the ide drivers from
 383    talking to the ports.
 384
 385======================================================================*/
 386
 387static struct pcmcia_device_id ide_ids[] = {
 388        PCMCIA_DEVICE_FUNC_ID(4),
 389        PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
 390        PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
 391        PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
 392        PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
 393        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
 394        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
 395        PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
 396        PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
 397        PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
 398        PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
 399        PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
 400        PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
 401        PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
 402        PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
 403        PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
 404        PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
 405        PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
 406        PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
 407        PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
 408        PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
 409        PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
 410        PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
 411        PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
 412        PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
 413        PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
 414        PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
 415        PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
 416        PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
 417        PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
 418        PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
 419        PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
 420        PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
 421        PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
 422        PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
 423        PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
 424        PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
 425        PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
 426        PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
 427        PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
 428        PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
 429        PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
 430        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
 431        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
 432        PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
 433        PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
 434        PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
 435        PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
 436        PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
 437        PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
 438        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
 439        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
 440        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
 441        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
 442        PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
 443        PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
 444        PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
 445        PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
 446        PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
 447        PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
 448        PCMCIA_DEVICE_NULL,
 449};
 450MODULE_DEVICE_TABLE(pcmcia, ide_ids);
 451
 452static struct pcmcia_driver ide_cs_driver = {
 453        .owner          = THIS_MODULE,
 454        .drv            = {
 455                .name   = "ide-cs",
 456        },
 457        .probe          = ide_probe,
 458        .remove         = ide_detach,
 459        .id_table       = ide_ids,
 460};
 461
 462static int __init init_ide_cs(void)
 463{
 464        return pcmcia_register_driver(&ide_cs_driver);
 465}
 466
 467static void __exit exit_ide_cs(void)
 468{
 469        pcmcia_unregister_driver(&ide_cs_driver);
 470}
 471
 472late_initcall(init_ide_cs);
 473module_exit(exit_ide_cs);
 474