das08_cs.c revision 2202a5a7490a9de282846ea8d4a56d0249e09033
1/* 2 comedi/drivers/das08_cs.c 3 DAS08 driver 4 5 COMEDI - Linux Control and Measurement Device Interface 6 Copyright (C) 2000 David A. Schleef <ds@schleef.org> 7 Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 23***************************************************************** 24 25*/ 26/* 27Driver: das08_cs 28Description: DAS-08 PCMCIA boards 29Author: Warren Jasper, ds, Frank Hess 30Devices: [ComputerBoards] PCM-DAS08 (pcm-das08) 31Status: works 32 33This is the PCMCIA-specific support split off from the 34das08 driver. 35 36Options (for pcm-das08): 37 NONE 38 39Command support does not exist, but could be added for this board. 40*/ 41 42#include "../comedidev.h" 43 44#include <linux/delay.h> 45#include <linux/pci.h> 46#include <linux/slab.h> 47 48#include "das08.h" 49 50/* pcmcia includes */ 51#include <pcmcia/cistpl.h> 52#include <pcmcia/ds.h> 53 54static struct pcmcia_device *cur_dev; 55 56#define thisboard ((const struct das08_board_struct *)dev->board_ptr) 57 58static int das08_cs_attach(struct comedi_device *dev, 59 struct comedi_devconfig *it); 60 61static struct comedi_driver driver_das08_cs = { 62 .driver_name = "das08_cs", 63 .module = THIS_MODULE, 64 .attach = das08_cs_attach, 65 .detach = das08_common_detach, 66 .board_name = &das08_cs_boards[0].name, 67 .num_names = ARRAY_SIZE(das08_cs_boards), 68 .offset = sizeof(struct das08_board_struct), 69}; 70 71static int das08_cs_attach(struct comedi_device *dev, 72 struct comedi_devconfig *it) 73{ 74 int ret; 75 unsigned long iobase; 76 struct pcmcia_device *link = cur_dev; /* XXX hack */ 77 78 ret = alloc_private(dev, sizeof(struct das08_private_struct)); 79 if (ret < 0) 80 return ret; 81 82 printk("comedi%d: das08_cs: ", dev->minor); 83 /* deal with a pci board */ 84 85 if (thisboard->bustype == pcmcia) { 86 if (link == NULL) { 87 printk(" no pcmcia cards found\n"); 88 return -EIO; 89 } 90 iobase = link->resource[0]->start; 91 } else { 92 printk(" bug! board does not have PCMCIA bustype\n"); 93 return -EINVAL; 94 } 95 96 printk("\n"); 97 98 return das08_common_attach(dev, iobase); 99} 100 101/*====================================================================== 102 103 The following pcmcia code for the pcm-das08 is adapted from the 104 dummy_cs.c driver of the Linux PCMCIA Card Services package. 105 106 The initial developer of the original code is David A. Hinds 107 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 108 are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 109 110======================================================================*/ 111 112static void das08_pcmcia_config(struct pcmcia_device *link); 113static void das08_pcmcia_release(struct pcmcia_device *link); 114static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); 115static int das08_pcmcia_resume(struct pcmcia_device *p_dev); 116 117static int das08_pcmcia_attach(struct pcmcia_device *); 118static void das08_pcmcia_detach(struct pcmcia_device *); 119 120struct local_info_t { 121 struct pcmcia_device *link; 122 int stop; 123 struct bus_operations *bus; 124}; 125 126static int das08_pcmcia_attach(struct pcmcia_device *link) 127{ 128 struct local_info_t *local; 129 130 dev_dbg(&link->dev, "das08_pcmcia_attach()\n"); 131 132 /* Allocate space for private device-specific data */ 133 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); 134 if (!local) 135 return -ENOMEM; 136 local->link = link; 137 link->priv = local; 138 139 cur_dev = link; 140 141 das08_pcmcia_config(link); 142 143 return 0; 144} /* das08_pcmcia_attach */ 145 146static void das08_pcmcia_detach(struct pcmcia_device *link) 147{ 148 149 dev_dbg(&link->dev, "das08_pcmcia_detach\n"); 150 151 ((struct local_info_t *)link->priv)->stop = 1; 152 das08_pcmcia_release(link); 153 154 /* This points to the parent struct local_info_t struct */ 155 kfree(link->priv); 156 157} /* das08_pcmcia_detach */ 158 159 160static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, 161 void *priv_data) 162{ 163 if (p_dev->config_index == 0) 164 return -EINVAL; 165 166 return pcmcia_request_io(p_dev); 167} 168 169static void das08_pcmcia_config(struct pcmcia_device *link) 170{ 171 int ret; 172 173 dev_dbg(&link->dev, "das08_pcmcia_config\n"); 174 175 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; 176 177 ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL); 178 if (ret) { 179 dev_warn(&link->dev, "no configuration found\n"); 180 goto failed; 181 } 182 183 if (!link->irq) 184 goto failed; 185 186 ret = pcmcia_enable_device(link); 187 if (ret) 188 goto failed; 189 190 return; 191 192failed: 193 das08_pcmcia_release(link); 194 195} /* das08_pcmcia_config */ 196 197static void das08_pcmcia_release(struct pcmcia_device *link) 198{ 199 dev_dbg(&link->dev, "das08_pcmcia_release\n"); 200 pcmcia_disable_device(link); 201} /* das08_pcmcia_release */ 202 203static int das08_pcmcia_suspend(struct pcmcia_device *link) 204{ 205 struct local_info_t *local = link->priv; 206 /* Mark the device as stopped, to block IO until later */ 207 local->stop = 1; 208 209 return 0; 210} /* das08_pcmcia_suspend */ 211 212static int das08_pcmcia_resume(struct pcmcia_device *link) 213{ 214 struct local_info_t *local = link->priv; 215 216 local->stop = 0; 217 return 0; 218} /* das08_pcmcia_resume */ 219 220/*====================================================================*/ 221 222static const struct pcmcia_device_id das08_cs_id_table[] = { 223 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4001), 224 PCMCIA_DEVICE_NULL 225}; 226 227MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table); 228MODULE_AUTHOR("David A. Schleef <ds@schleef.org>, " 229 "Frank Mori Hess <fmhess@users.sourceforge.net>"); 230MODULE_DESCRIPTION("Comedi driver for ComputerBoards DAS-08 PCMCIA boards"); 231MODULE_LICENSE("GPL"); 232 233struct pcmcia_driver das08_cs_driver = { 234 .probe = das08_pcmcia_attach, 235 .remove = das08_pcmcia_detach, 236 .suspend = das08_pcmcia_suspend, 237 .resume = das08_pcmcia_resume, 238 .id_table = das08_cs_id_table, 239 .owner = THIS_MODULE, 240 .name = "pcm-das08", 241}; 242 243static int __init init_das08_pcmcia_cs(void) 244{ 245 pcmcia_register_driver(&das08_cs_driver); 246 return 0; 247} 248 249static void __exit exit_das08_pcmcia_cs(void) 250{ 251 pr_debug("das08_pcmcia_cs: unloading\n"); 252 pcmcia_unregister_driver(&das08_cs_driver); 253} 254 255static int __init das08_cs_init_module(void) 256{ 257 int ret; 258 259 ret = init_das08_pcmcia_cs(); 260 if (ret < 0) 261 return ret; 262 263 return comedi_driver_register(&driver_das08_cs); 264} 265 266static void __exit das08_cs_exit_module(void) 267{ 268 exit_das08_pcmcia_cs(); 269 comedi_driver_unregister(&driver_das08_cs); 270} 271 272module_init(das08_cs_init_module); 273module_exit(das08_cs_exit_module); 274