linux/drivers/scsi/pcmcia/fdomain_stub.c
<<
>>
Prefs
   1/*======================================================================
   2
   3    A driver for Future Domain-compatible PCMCIA SCSI cards
   4
   5    fdomain_cs.c 1.47 2001/10/13 00:08:52
   6
   7    The contents of this file are subject to the Mozilla Public
   8    License Version 1.1 (the "License"); you may not use this file
   9    except in compliance with the License. You may obtain a copy of
  10    the License at http://www.mozilla.org/MPL/
  11
  12    Software distributed under the License is distributed on an "AS
  13    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  14    implied. See the License for the specific language governing
  15    rights and limitations under the License.
  16
  17    The initial developer of the original code is David A. Hinds
  18    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  19    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  20
  21    Alternatively, the contents of this file may be used under the
  22    terms of the GNU General Public License version 2 (the "GPL"), in
  23    which case the provisions of the GPL are applicable instead of the
  24    above.  If you wish to allow the use of your version of this file
  25    only under the terms of the GPL and not to allow others to use
  26    your version of this file under the MPL, indicate your decision
  27    by deleting the provisions above and replace them with the notice
  28    and other provisions required by the GPL.  If you do not delete
  29    the provisions above, a recipient may use your version of this
  30    file under either the MPL or the GPL.
  31    
  32======================================================================*/
  33
  34#include <linux/module.h>
  35#include <linux/init.h>
  36#include <linux/kernel.h>
  37#include <linux/slab.h>
  38#include <linux/string.h>
  39#include <linux/ioport.h>
  40#include <scsi/scsi.h>
  41#include <linux/major.h>
  42#include <linux/blkdev.h>
  43#include <scsi/scsi_ioctl.h>
  44
  45#include "scsi.h"
  46#include <scsi/scsi_host.h>
  47#include "fdomain.h"
  48
  49#include <pcmcia/cs_types.h>
  50#include <pcmcia/cs.h>
  51#include <pcmcia/cistpl.h>
  52#include <pcmcia/ds.h>
  53
  54/*====================================================================*/
  55
  56/* Module parameters */
  57
  58MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
  59MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");
  60MODULE_LICENSE("Dual MPL/GPL");
  61
  62#ifdef PCMCIA_DEBUG
  63static int pc_debug = PCMCIA_DEBUG;
  64module_param(pc_debug, int, 0);
  65#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
  66static char *version =
  67"fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)";
  68#else
  69#define DEBUG(n, args...)
  70#endif
  71
  72/*====================================================================*/
  73
  74typedef struct scsi_info_t {
  75        struct pcmcia_device    *p_dev;
  76    dev_node_t          node;
  77    struct Scsi_Host    *host;
  78} scsi_info_t;
  79
  80
  81static void fdomain_release(struct pcmcia_device *link);
  82static void fdomain_detach(struct pcmcia_device *p_dev);
  83static int fdomain_config(struct pcmcia_device *link);
  84
  85static int fdomain_probe(struct pcmcia_device *link)
  86{
  87        scsi_info_t *info;
  88
  89        DEBUG(0, "fdomain_attach()\n");
  90
  91        /* Create new SCSI device */
  92        info = kzalloc(sizeof(*info), GFP_KERNEL);
  93        if (!info)
  94                return -ENOMEM;
  95
  96        info->p_dev = link;
  97        link->priv = info;
  98        link->io.NumPorts1 = 0x10;
  99        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
 100        link->io.IOAddrLines = 10;
 101        link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
 102        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 103        link->conf.Attributes = CONF_ENABLE_IRQ;
 104        link->conf.IntType = INT_MEMORY_AND_IO;
 105        link->conf.Present = PRESENT_OPTION;
 106
 107        return fdomain_config(link);
 108} /* fdomain_attach */
 109
 110/*====================================================================*/
 111
 112static void fdomain_detach(struct pcmcia_device *link)
 113{
 114        DEBUG(0, "fdomain_detach(0x%p)\n", link);
 115
 116        fdomain_release(link);
 117
 118        kfree(link->priv);
 119} /* fdomain_detach */
 120
 121/*====================================================================*/
 122
 123#define CS_CHECK(fn, ret) \
 124do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 125
 126static int fdomain_config_check(struct pcmcia_device *p_dev,
 127                                cistpl_cftable_entry_t *cfg,
 128                                cistpl_cftable_entry_t *dflt,
 129                                unsigned int vcc,
 130                                void *priv_data)
 131{
 132        p_dev->io.BasePort1 = cfg->io.win[0].base;
 133        return pcmcia_request_io(p_dev, &p_dev->io);
 134}
 135
 136
 137static int fdomain_config(struct pcmcia_device *link)
 138{
 139    scsi_info_t *info = link->priv;
 140    int last_ret, last_fn;
 141    char str[22];
 142    struct Scsi_Host *host;
 143
 144    DEBUG(0, "fdomain_config(0x%p)\n", link);
 145
 146    last_ret = pcmcia_loop_config(link, fdomain_config_check, NULL);
 147    if (last_ret) {
 148            cs_error(link, RequestIO, last_ret);
 149            goto failed;
 150    }
 151
 152    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 153    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 154
 155    /* A bad hack... */
 156    release_region(link->io.BasePort1, link->io.NumPorts1);
 157
 158    /* Set configuration options for the fdomain driver */
 159    sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
 160    fdomain_setup(str);
 161
 162    host = __fdomain_16x0_detect(&fdomain_driver_template);
 163    if (!host) {
 164        printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
 165        goto cs_failed;
 166    }
 167
 168    if (scsi_add_host(host, NULL))
 169            goto cs_failed;
 170    scsi_scan_host(host);
 171
 172    sprintf(info->node.dev_name, "scsi%d", host->host_no);
 173    link->dev_node = &info->node;
 174    info->host = host;
 175
 176    return 0;
 177
 178cs_failed:
 179    cs_error(link, last_fn, last_ret);
 180failed:
 181    fdomain_release(link);
 182    return -ENODEV;
 183} /* fdomain_config */
 184
 185/*====================================================================*/
 186
 187static void fdomain_release(struct pcmcia_device *link)
 188{
 189        scsi_info_t *info = link->priv;
 190
 191        DEBUG(0, "fdomain_release(0x%p)\n", link);
 192
 193        scsi_remove_host(info->host);
 194        pcmcia_disable_device(link);
 195        scsi_unregister(info->host);
 196}
 197
 198/*====================================================================*/
 199
 200static int fdomain_resume(struct pcmcia_device *link)
 201{
 202        fdomain_16x0_bus_reset(NULL);
 203
 204        return 0;
 205}
 206
 207static struct pcmcia_device_id fdomain_ids[] = {
 208        PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, 0x859cad20),
 209        PCMCIA_DEVICE_PROD_ID1("SCSI PCMCIA Adapter Card", 0x8dacb57e),
 210        PCMCIA_DEVICE_PROD_ID12(" SIMPLE TECHNOLOGY Corporation", "SCSI PCMCIA Credit Card Controller", 0x182bdafe, 0xc80d106f),
 211        PCMCIA_DEVICE_NULL,
 212};
 213MODULE_DEVICE_TABLE(pcmcia, fdomain_ids);
 214
 215static struct pcmcia_driver fdomain_cs_driver = {
 216        .owner          = THIS_MODULE,
 217        .drv            = {
 218                .name   = "fdomain_cs",
 219        },
 220        .probe          = fdomain_probe,
 221        .remove         = fdomain_detach,
 222        .id_table       = fdomain_ids,
 223        .resume         = fdomain_resume,
 224};
 225
 226static int __init init_fdomain_cs(void)
 227{
 228        return pcmcia_register_driver(&fdomain_cs_driver);
 229}
 230
 231static void __exit exit_fdomain_cs(void)
 232{
 233        pcmcia_unregister_driver(&fdomain_cs_driver);
 234}
 235
 236module_init(init_fdomain_cs);
 237module_exit(exit_fdomain_cs);
 238