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        .irq_flags              = IRQF_SHARED,
 158        .chipset                = ide_pci,
 159};
 160
 161static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
 162                                unsigned long irq, struct pcmcia_device *handle)
 163{
 164    struct ide_host *host;
 165    ide_hwif_t *hwif;
 166    int i, rc;
 167    struct ide_hw hw, *hws[] = { &hw };
 168
 169    if (!request_region(io, 8, DRV_NAME)) {
 170        printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
 171                        DRV_NAME, io, io + 7);
 172        return NULL;
 173    }
 174
 175    if (!request_region(ctl, 1, DRV_NAME)) {
 176        printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
 177                        DRV_NAME, ctl);
 178        release_region(io, 8);
 179        return NULL;
 180    }
 181
 182    memset(&hw, 0, sizeof(hw));
 183    ide_std_init_ports(&hw, io, ctl);
 184    hw.irq = irq;
 185    hw.dev = &handle->dev;
 186
 187    rc = ide_host_add(&idecs_port_info, hws, 1, &host);
 188    if (rc)
 189        goto out_release;
 190
 191    hwif = host->ports[0];
 192
 193    if (hwif->present)
 194        return host;
 195
 196    /* retry registration in case device is still spinning up */
 197    for (i = 0; i < 10; i++) {
 198        msleep(100);
 199        ide_port_scan(hwif);
 200        if (hwif->present)
 201            return host;
 202    }
 203
 204    return host;
 205
 206out_release:
 207    release_region(ctl, 1);
 208    release_region(io, 8);
 209    return NULL;
 210}
 211
 212/*======================================================================
 213
 214    ide_config() is scheduled to run after a CARD_INSERTION event
 215    is received, to configure the PCMCIA socket, and to make the
 216    ide device available to the system.
 217
 218======================================================================*/
 219
 220#define CS_CHECK(fn, ret) \
 221do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 222
 223struct pcmcia_config_check {
 224        unsigned long ctl_base;
 225        int skip_vcc;
 226        int is_kme;
 227};
 228
 229static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 230                                   cistpl_cftable_entry_t *cfg,
 231                                   cistpl_cftable_entry_t *dflt,
 232                                   unsigned int vcc,
 233                                   void *priv_data)
 234{
 235        struct pcmcia_config_check *stk = priv_data;
 236
 237        /* Check for matching Vcc, unless we're desperate */
 238        if (!stk->skip_vcc) {
 239                if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
 240                        if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
 241                                return -ENODEV;
 242                } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
 243                        if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
 244                                return -ENODEV;
 245                }
 246        }
 247
 248        if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
 249                pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 250        else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
 251                pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 252
 253        if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 254                cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
 255                pdev->conf.ConfigIndex = cfg->index;
 256                pdev->io.BasePort1 = io->win[0].base;
 257                pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
 258                if (!(io->flags & CISTPL_IO_16BIT))
 259                        pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 260                if (io->nwin == 2) {
 261                        pdev->io.NumPorts1 = 8;
 262                        pdev->io.BasePort2 = io->win[1].base;
 263                        pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
 264                        if (pcmcia_request_io(pdev, &pdev->io) != 0)
 265                                return -ENODEV;
 266                        stk->ctl_base = pdev->io.BasePort2;
 267                } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
 268                        pdev->io.NumPorts1 = io->win[0].len;
 269                        pdev->io.NumPorts2 = 0;
 270                        if (pcmcia_request_io(pdev, &pdev->io) != 0)
 271                                return -ENODEV;
 272                        stk->ctl_base = pdev->io.BasePort1 + 0x0e;
 273                } else
 274                        return -ENODEV;
 275                /* If we've got this far, we're done */
 276                return 0;
 277        }
 278        return -ENODEV;
 279}
 280
 281static int ide_config(struct pcmcia_device *link)
 282{
 283    ide_info_t *info = link->priv;
 284    struct pcmcia_config_check *stk = NULL;
 285    int last_ret = 0, last_fn = 0, is_kme = 0;
 286    unsigned long io_base, ctl_base;
 287    struct ide_host *host;
 288
 289    DEBUG(0, "ide_config(0x%p)\n", link);
 290
 291    is_kme = ((link->manf_id == MANFID_KME) &&
 292              ((link->card_id == PRODID_KME_KXLC005_A) ||
 293               (link->card_id == PRODID_KME_KXLC005_B)));
 294
 295    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
 296    if (!stk)
 297            goto err_mem;
 298    stk->is_kme = is_kme;
 299    stk->skip_vcc = io_base = ctl_base = 0;
 300
 301    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
 302            stk->skip_vcc = 1;
 303            if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
 304                    goto failed; /* No suitable config found */
 305    }
 306    io_base = link->io.BasePort1;
 307    ctl_base = stk->ctl_base;
 308
 309    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 310    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 311
 312    /* disable drive interrupts during IDE probe */
 313    outb(0x02, ctl_base);
 314
 315    /* special setup for KXLC005 card */
 316    if (is_kme)
 317        outb(0x81, ctl_base+1);
 318
 319     host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
 320     if (host == NULL && link->io.NumPorts1 == 0x20) {
 321            outb(0x02, ctl_base + 0x10);
 322            host = idecs_register(io_base + 0x10, ctl_base + 0x10,
 323                                  link->irq.AssignedIRQ, link);
 324    }
 325
 326    if (host == NULL)
 327        goto failed;
 328
 329    info->ndev = 1;
 330    sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
 331    info->node.major = host->ports[0]->major;
 332    info->node.minor = 0;
 333    info->host = host;
 334    link->dev_node = &info->node;
 335    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
 336           info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
 337
 338    kfree(stk);
 339    return 0;
 340
 341err_mem:
 342    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
 343    goto failed;
 344
 345cs_failed:
 346    cs_error(link, last_fn, last_ret);
 347failed:
 348    kfree(stk);
 349    ide_release(link);
 350    return -ENODEV;
 351} /* ide_config */
 352
 353/*======================================================================
 354
 355    After a card is removed, ide_release() will unregister the net
 356    device, and release the PCMCIA configuration.  If the device is
 357    still open, this will be postponed until it is closed.
 358
 359======================================================================*/
 360
 361static void ide_release(struct pcmcia_device *link)
 362{
 363    ide_info_t *info = link->priv;
 364    struct ide_host *host = info->host;
 365
 366    DEBUG(0, "ide_release(0x%p)\n", link);
 367
 368    if (info->ndev)
 369        /* FIXME: if this fails we need to queue the cleanup somehow
 370           -- need to investigate the required PCMCIA magic */
 371        ide_host_remove(host);
 372
 373    info->ndev = 0;
 374
 375    pcmcia_disable_device(link);
 376} /* ide_release */
 377
 378
 379/*======================================================================
 380
 381    The card status event handler.  Mostly, this schedules other
 382    stuff to run after an event is received.  A CARD_REMOVAL event
 383    also sets some flags to discourage the ide drivers from
 384    talking to the ports.
 385
 386======================================================================*/
 387
 388static struct pcmcia_device_id ide_ids[] = {
 389        PCMCIA_DEVICE_FUNC_ID(4),
 390        PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
 391        PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
 392        PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
 393        PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
 394        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
 395        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
 396        PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
 397        PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
 398        PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
 399        PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
 400        PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
 401        PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
 402        PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
 403        PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
 404        PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
 405        PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
 406        PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
 407        PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
 408        PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
 409        PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
 410        PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
 411        PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
 412        PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
 413        PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
 414        PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
 415        PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
 416        PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
 417        PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
 418        PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
 419        PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
 420        PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
 421        PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
 422        PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
 423        PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
 424        PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
 425        PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
 426        PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
 427        PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
 428        PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
 429        PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
 430        PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
 431        PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
 432        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
 433        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
 434        PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
 435        PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
 436        PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
 437        PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
 438        PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
 439        PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
 440        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
 441        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
 442        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
 443        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
 444        PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
 445        PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
 446        PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
 447        PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
 448        PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
 449        PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
 450        PCMCIA_DEVICE_NULL,
 451};
 452MODULE_DEVICE_TABLE(pcmcia, ide_ids);
 453
 454static struct pcmcia_driver ide_cs_driver = {
 455        .owner          = THIS_MODULE,
 456        .drv            = {
 457                .name   = "ide-cs",
 458        },
 459        .probe          = ide_probe,
 460        .remove         = ide_detach,
 461        .id_table       = ide_ids,
 462};
 463
 464static int __init init_ide_cs(void)
 465{
 466        return pcmcia_register_driver(&ide_cs_driver);
 467}
 468
 469static void __exit exit_ide_cs(void)
 470{
 471        pcmcia_unregister_driver(&ide_cs_driver);
 472}
 473
 474late_initcall(init_ide_cs);
 475module_exit(exit_ide_cs);
 476