pcmcia: move config_{base,index,regs} to struct pcmcia_device
[deliverable/linux.git] / drivers / isdn / hisax / avma1_cs.c
CommitLineData
1da177e4
LT
1/*
2 * PCMCIA client driver for AVM A1 / Fritz!PCMCIA
3 *
4 * Author Carsten Paeth
5 * Copyright 1998-2001 by Carsten Paeth <calle@calle.in-berlin.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13
14
15#include <linux/kernel.h>
16#include <linux/init.h>
1da177e4
LT
17#include <linux/ptrace.h>
18#include <linux/slab.h>
19#include <linux/string.h>
20#include <asm/io.h>
21#include <asm/system.h>
22
1da177e4
LT
23#include <pcmcia/cs.h>
24#include <pcmcia/cistpl.h>
25#include <pcmcia/ds.h>
26#include "hisax_cfg.h"
27
28MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards");
29MODULE_AUTHOR("Carsten Paeth");
30MODULE_LICENSE("GPL");
31
1da177e4
LT
32
33/*====================================================================*/
34
35/* Parameters that can be set with 'insmod' */
36
37static int isdnprot = 2;
38
39module_param(isdnprot, int, 0);
40
41/*====================================================================*/
42
43/*
44 The event() function is this driver's Card Services event handler.
45 It will be called by Card Services when an appropriate card status
46 event is received. The config() and release() entry points are
47 used to configure or release a socket, in response to card insertion
48 and ejection events. They are invoked from the skeleton event
49 handler.
50*/
51
a465870a 52static int avma1cs_config(struct pcmcia_device *link) __devinit ;
fba395ee 53static void avma1cs_release(struct pcmcia_device *link);
1da177e4
LT
54
55/*
56 The attach() and detach() entry points are used to create and destroy
57 "instances" of the driver, where each instance represents everything
58 needed to manage one actual PCMCIA card.
59*/
60
a465870a 61static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ;
1da177e4 62
1da177e4 63
1da177e4
LT
64/*======================================================================
65
66 avma1cs_attach() creates an "instance" of the driver, allocating
67 local data structures for one device. The device is registered
68 with Card Services.
69
70 The dev_link structure is initialized, but we don't actually
71 configure the card at this point -- we wait until we receive a
72 card insertion event.
73
74======================================================================*/
75
a465870a 76static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
1da177e4 77{
e773cfe1 78 dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
1da177e4 79
1da177e4 80 /* The io structure describes IO port mapping */
90abdc3b
DB
81 p_dev->resource[0]->end = 16;
82 p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
83 p_dev->resource[1]->end = 16;
84 p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
1da177e4 85
1da177e4 86 /* General socket configuration */
fd238232 87 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
7feabb64
DB
88 p_dev->config_index = 1;
89 p_dev->config_regs = PRESENT_OPTION;
f8cfa618 90
15b99ac1 91 return avma1cs_config(p_dev);
1da177e4
LT
92} /* avma1cs_attach */
93
94/*======================================================================
95
96 This deletes a driver "instance". The device is de-registered
97 with Card Services. If it has been released, all local data
98 structures are freed. Otherwise, the structures will be freed
99 when the device is released.
100
101======================================================================*/
102
a465870a 103static void __devexit avma1cs_detach(struct pcmcia_device *link)
1da177e4 104{
e773cfe1 105 dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link);
e2d40963
DB
106 avma1cs_release(link);
107 kfree(link->priv);
1da177e4
LT
108} /* avma1cs_detach */
109
110/*======================================================================
111
112 avma1cs_config() is scheduled to run after a CARD_INSERTION event
113 is received, to configure the PCMCIA socket, and to make the
114 ethernet device available to the system.
115
116======================================================================*/
117
5fcd4da0 118static int avma1cs_configcheck(struct pcmcia_device *p_dev,
8e2fc39d
DB
119 cistpl_cftable_entry_t *cf,
120 cistpl_cftable_entry_t *dflt,
ad913c11 121 unsigned int vcc,
8e2fc39d 122 void *priv_data)
1da177e4 123{
5fcd4da0
DB
124 if (cf->io.nwin <= 0)
125 return -ENODEV;
126
90abdc3b
DB
127 p_dev->resource[0]->start = cf->io.win[0].base;
128 p_dev->resource[0]->end = cf->io.win[0].len;
129 p_dev->io_lines = 5;
130 return pcmcia_request_io(p_dev);
1da177e4
LT
131}
132
1da177e4 133
a465870a 134static int __devinit avma1cs_config(struct pcmcia_device *link)
1da177e4 135{
eb14120f 136 int i = -1;
1da177e4
LT
137 char devname[128];
138 IsdnCard_t icard;
139 int busy = 0;
fba395ee 140
e773cfe1 141 dev_dbg(&link->dev, "avma1cs_config(0x%p)\n", link);
1da177e4 142
5fcd4da0
DB
143 devname[0] = 0;
144 if (link->prod_id[1])
145 strlcpy(devname, link->prod_id[1], sizeof(devname));
a9606fd3 146
5fcd4da0
DB
147 if (pcmcia_loop_config(link, avma1cs_configcheck, NULL))
148 return -ENODEV;
1da177e4 149
5fcd4da0 150 do {
1da177e4
LT
151 /*
152 * allocate an interrupt line
153 */
eb14120f 154 if (!link->irq) {
50db3fdb 155 /* undo */
fba395ee 156 pcmcia_disable_device(link);
1da177e4
LT
157 break;
158 }
50db3fdb 159
1da177e4
LT
160 /*
161 * configure the PCMCIA socket
162 */
fba395ee 163 i = pcmcia_request_configuration(link, &link->conf);
4c89e88b 164 if (i != 0) {
fba395ee 165 pcmcia_disable_device(link);
1da177e4
LT
166 break;
167 }
168
169 } while (0);
170
1da177e4
LT
171 /* If any step failed, release any partially configured state */
172 if (i != 0) {
173 avma1cs_release(link);
15b99ac1 174 return -ENODEV;
1da177e4
LT
175 }
176
177 printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
9a017a91 178 (unsigned int) link->resource[0]->start, link->irq);
1da177e4 179
eb14120f 180 icard.para[0] = link->irq;
9a017a91 181 icard.para[1] = link->resource[0]->start;
1da177e4
LT
182 icard.protocol = isdnprot;
183 icard.typ = ISDN_CTYPE_A1_PCMCIA;
184
185 i = hisax_init_pcmcia(link, &busy, &icard);
186 if (i < 0) {
9a017a91
DB
187 printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 "
188 "PCMCIA %d at i/o %#x\n", i,
189 (unsigned int) link->resource[0]->start);
1da177e4 190 avma1cs_release(link);
15b99ac1 191 return -ENODEV;
1da177e4 192 }
b498ada6 193 link->priv = (void *) (unsigned long) i;
1da177e4 194
15b99ac1 195 return 0;
1da177e4
LT
196} /* avma1cs_config */
197
198/*======================================================================
199
200 After a card is removed, avma1cs_release() will unregister the net
201 device, and release the PCMCIA configuration. If the device is
202 still open, this will be postponed until it is closed.
203
204======================================================================*/
205
fba395ee 206static void avma1cs_release(struct pcmcia_device *link)
1da177e4 207{
b498ada6 208 unsigned long minor = (unsigned long) link->priv;
1da177e4 209
e773cfe1 210 dev_dbg(&link->dev, "avma1cs_release(0x%p)\n", link);
1da177e4 211
5f2a71fc 212 /* now unregister function with hisax */
b498ada6 213 HiSax_closecard(minor);
1da177e4 214
fba395ee 215 pcmcia_disable_device(link);
1da177e4
LT
216} /* avma1cs_release */
217
1da177e4 218
c594c12c
DB
219static struct pcmcia_device_id avma1cs_ids[] = {
220 PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
221 PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b),
222 PCMCIA_DEVICE_NULL
223};
224MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids);
225
1da177e4
LT
226static struct pcmcia_driver avma1cs_driver = {
227 .owner = THIS_MODULE,
228 .drv = {
229 .name = "avma1_cs",
230 },
15b99ac1 231 .probe = avma1cs_probe,
a465870a 232 .remove = __devexit_p(avma1cs_detach),
c594c12c 233 .id_table = avma1cs_ids,
1da177e4 234};
8661bb5b 235
1da177e4
LT
236/*====================================================================*/
237
238static int __init init_avma1_cs(void)
239{
240 return(pcmcia_register_driver(&avma1cs_driver));
241}
242
243static void __exit exit_avma1_cs(void)
244{
245 pcmcia_unregister_driver(&avma1cs_driver);
1da177e4
LT
246}
247
248module_init(init_avma1_cs);
249module_exit(exit_avma1_cs);
This page took 0.538154 seconds and 5 git commands to generate.