das08_cs.c revision 61a8d9550e620ab777ce25c2878e57f4e1a6acd3
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 dev_info(dev->hw_dev, "comedi%d: das08_cs:\n", dev->minor); 83 /* deal with a pci board */ 84 85 if (thisboard->bustype == pcmcia) { 86 if (link == NULL) { 87 dev_err(dev->hw_dev, "no pcmcia cards found\n"); 88 return -EIO; 89 } 90 iobase = link->resource[0]->start; 91 } else { 92 dev_err(dev->hw_dev, "bug! board does not have PCMCIA bustype\n"); 93 return -EINVAL; 94 } 95 96 return das08_common_attach(dev, iobase); 97} 98 99/*====================================================================== 100 101 The following pcmcia code for the pcm-das08 is adapted from the 102 dummy_cs.c driver of the Linux PCMCIA Card Services package. 103 104 The initial developer of the original code is David A. Hinds 105 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 106 are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 107 108======================================================================*/ 109 110static void das08_pcmcia_config(struct pcmcia_device *link); 111static void das08_pcmcia_release(struct pcmcia_device *link); 112static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); 113static int das08_pcmcia_resume(struct pcmcia_device *p_dev); 114 115static int das08_pcmcia_attach(struct pcmcia_device *); 116static void das08_pcmcia_detach(struct pcmcia_device *); 117 118struct local_info_t { 119 struct pcmcia_device *link; 120 int stop; 121 struct bus_operations *bus; 122}; 123 124static int das08_pcmcia_attach(struct pcmcia_device *link) 125{ 126 struct local_info_t *local; 127 128 dev_dbg(&link->dev, "das08_pcmcia_attach()\n"); 129 130 /* Allocate space for private device-specific data */ 131 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); 132 if (!local) 133 return -ENOMEM; 134 local->link = link; 135 link->priv = local; 136 137 cur_dev = link; 138 139 das08_pcmcia_config(link); 140 141 return 0; 142} /* das08_pcmcia_attach */ 143 144static void das08_pcmcia_detach(struct pcmcia_device *link) 145{ 146 147 dev_dbg(&link->dev, "das08_pcmcia_detach\n"); 148 149 ((struct local_info_t *)link->priv)->stop = 1; 150 das08_pcmcia_release(link); 151 152 /* This points to the parent struct local_info_t struct */ 153 kfree(link->priv); 154 155} /* das08_pcmcia_detach */ 156 157 158static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, 159 void *priv_data) 160{ 161 if (p_dev->config_index == 0) 162 return -EINVAL; 163 164 return pcmcia_request_io(p_dev); 165} 166 167static void das08_pcmcia_config(struct pcmcia_device *link) 168{ 169 int ret; 170 171 dev_dbg(&link->dev, "das08_pcmcia_config\n"); 172 173 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; 174 175 ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL); 176 if (ret) { 177 dev_warn(&link->dev, "no configuration found\n"); 178 goto failed; 179 } 180 181 if (!link->irq) 182 goto failed; 183 184 ret = pcmcia_enable_device(link); 185 if (ret) 186 goto failed; 187 188 return; 189 190failed: 191 das08_pcmcia_release(link); 192 193} /* das08_pcmcia_config */ 194 195static void das08_pcmcia_release(struct pcmcia_device *link) 196{ 197 dev_dbg(&link->dev, "das08_pcmcia_release\n"); 198 pcmcia_disable_device(link); 199} /* das08_pcmcia_release */ 200 201static int das08_pcmcia_suspend(struct pcmcia_device *link) 202{ 203 struct local_info_t *local = link->priv; 204 /* Mark the device as stopped, to block IO until later */ 205 local->stop = 1; 206 207 return 0; 208} /* das08_pcmcia_suspend */ 209 210static int das08_pcmcia_resume(struct pcmcia_device *link) 211{ 212 struct local_info_t *local = link->priv; 213 214 local->stop = 0; 215 return 0; 216} /* das08_pcmcia_resume */ 217 218/*====================================================================*/ 219 220static const struct pcmcia_device_id das08_cs_id_table[] = { 221 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4001), 222 PCMCIA_DEVICE_NULL 223}; 224 225MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table); 226MODULE_AUTHOR("David A. Schleef <ds@schleef.org>, " 227 "Frank Mori Hess <fmhess@users.sourceforge.net>"); 228MODULE_DESCRIPTION("Comedi driver for ComputerBoards DAS-08 PCMCIA boards"); 229MODULE_LICENSE("GPL"); 230 231struct pcmcia_driver das08_cs_driver = { 232 .probe = das08_pcmcia_attach, 233 .remove = das08_pcmcia_detach, 234 .suspend = das08_pcmcia_suspend, 235 .resume = das08_pcmcia_resume, 236 .id_table = das08_cs_id_table, 237 .owner = THIS_MODULE, 238 .name = "pcm-das08", 239}; 240 241static int __init init_das08_pcmcia_cs(void) 242{ 243 pcmcia_register_driver(&das08_cs_driver); 244 return 0; 245} 246 247static void __exit exit_das08_pcmcia_cs(void) 248{ 249 pr_debug("das08_pcmcia_cs: unloading\n"); 250 pcmcia_unregister_driver(&das08_cs_driver); 251} 252 253static int __init das08_cs_init_module(void) 254{ 255 int ret; 256 257 ret = init_das08_pcmcia_cs(); 258 if (ret < 0) 259 return ret; 260 261 return comedi_driver_register(&driver_das08_cs); 262} 263 264static void __exit das08_cs_exit_module(void) 265{ 266 exit_das08_pcmcia_cs(); 267 comedi_driver_unregister(&driver_das08_cs); 268} 269 270module_init(das08_cs_init_module); 271module_exit(das08_cs_exit_module); 272