aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hisax/avma1_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/hisax/avma1_cs.c')
-rw-r--r--drivers/isdn/hisax/avma1_cs.c182
1 files changed, 62 insertions, 120 deletions
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 969da40c4248..ac28e3278ad9 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -67,8 +67,8 @@ module_param(isdnprot, int, 0);
67 handler. 67 handler.
68*/ 68*/
69 69
70static void avma1cs_config(dev_link_t *link); 70static int avma1cs_config(struct pcmcia_device *link);
71static void avma1cs_release(dev_link_t *link); 71static void avma1cs_release(struct pcmcia_device *link);
72 72
73/* 73/*
74 The attach() and detach() entry points are used to create and destroy 74 The attach() and detach() entry points are used to create and destroy
@@ -82,10 +82,10 @@ static void avma1cs_detach(struct pcmcia_device *p_dev);
82/* 82/*
83 A linked list of "instances" of the skeleton device. Each actual 83 A linked list of "instances" of the skeleton device. Each actual
84 PCMCIA card corresponds to one device instance, and is described 84 PCMCIA card corresponds to one device instance, and is described
85 by one dev_link_t structure (defined in ds.h). 85 by one struct pcmcia_device structure (defined in ds.h).
86 86
87 You may not want to use a linked list for this -- for example, the 87 You may not want to use a linked list for this -- for example, the
88 memory card driver uses an array of dev_link_t pointers, where minor 88 memory card driver uses an array of struct pcmcia_device pointers, where minor
89 device numbers are used to derive the corresponding array index. 89 device numbers are used to derive the corresponding array index.
90*/ 90*/
91 91
@@ -95,7 +95,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev);
95 example, ethernet cards, modems). In other cases, there may be 95 example, ethernet cards, modems). In other cases, there may be
96 many actual or logical devices (SCSI adapters, memory cards with 96 many actual or logical devices (SCSI adapters, memory cards with
97 multiple partitions). The dev_node_t structures need to be kept 97 multiple partitions). The dev_node_t structures need to be kept
98 in a linked list starting at the 'dev' field of a dev_link_t 98 in a linked list starting at the 'dev' field of a struct pcmcia_device
99 structure. We allocate them in the card's private data structure, 99 structure. We allocate them in the card's private data structure,
100 because they generally can't be allocated dynamically. 100 because they generally can't be allocated dynamically.
101*/ 101*/
@@ -116,55 +116,40 @@ typedef struct local_info_t {
116 116
117======================================================================*/ 117======================================================================*/
118 118
119static int avma1cs_attach(struct pcmcia_device *p_dev) 119static int avma1cs_probe(struct pcmcia_device *p_dev)
120{ 120{
121 dev_link_t *link;
122 local_info_t *local; 121 local_info_t *local;
123 122
124 DEBUG(0, "avma1cs_attach()\n"); 123 DEBUG(0, "avma1cs_attach()\n");
125 124
126 /* Initialize the dev_link_t structure */
127 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
128 if (!link)
129 return -ENOMEM;
130 memset(link, 0, sizeof(struct dev_link_t));
131
132 /* Allocate space for private device-specific data */ 125 /* Allocate space for private device-specific data */
133 local = kmalloc(sizeof(local_info_t), GFP_KERNEL); 126 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
134 if (!local) { 127 if (!local)
135 kfree(link);
136 return -ENOMEM; 128 return -ENOMEM;
137 } 129
138 memset(local, 0, sizeof(local_info_t)); 130 memset(local, 0, sizeof(local_info_t));
139 link->priv = local; 131 p_dev->priv = local;
140 132
141 /* The io structure describes IO port mapping */ 133 /* The io structure describes IO port mapping */
142 link->io.NumPorts1 = 16; 134 p_dev->io.NumPorts1 = 16;
143 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 135 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
144 link->io.NumPorts2 = 16; 136 p_dev->io.NumPorts2 = 16;
145 link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; 137 p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
146 link->io.IOAddrLines = 5; 138 p_dev->io.IOAddrLines = 5;
147 139
148 /* Interrupt setup */ 140 /* Interrupt setup */
149 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 141 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
150 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; 142 p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
151 143
152 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 144 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
153 145
154 /* General socket configuration */ 146 /* General socket configuration */
155 link->conf.Attributes = CONF_ENABLE_IRQ; 147 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
156 link->conf.Vcc = 50; 148 p_dev->conf.IntType = INT_MEMORY_AND_IO;
157 link->conf.IntType = INT_MEMORY_AND_IO; 149 p_dev->conf.ConfigIndex = 1;
158 link->conf.ConfigIndex = 1; 150 p_dev->conf.Present = PRESENT_OPTION;
159 link->conf.Present = PRESENT_OPTION;
160 151
161 link->handle = p_dev; 152 return avma1cs_config(p_dev);
162 p_dev->instance = link;
163
164 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
165 avma1cs_config(link);
166
167 return 0;
168} /* avma1cs_attach */ 153} /* avma1cs_attach */
169 154
170/*====================================================================== 155/*======================================================================
@@ -176,17 +161,11 @@ static int avma1cs_attach(struct pcmcia_device *p_dev)
176 161
177======================================================================*/ 162======================================================================*/
178 163
179static void avma1cs_detach(struct pcmcia_device *p_dev) 164static void avma1cs_detach(struct pcmcia_device *link)
180{ 165{
181 dev_link_t *link = dev_to_instance(p_dev); 166 DEBUG(0, "avma1cs_detach(0x%p)\n", link);
182 167 avma1cs_release(link);
183 DEBUG(0, "avma1cs_detach(0x%p)\n", link); 168 kfree(link->priv);
184
185 if (link->state & DEV_CONFIG)
186 avma1cs_release(link);
187
188 kfree(link->priv);
189 kfree(link);
190} /* avma1cs_detach */ 169} /* avma1cs_detach */
191 170
192/*====================================================================== 171/*======================================================================
@@ -197,7 +176,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev)
197 176
198======================================================================*/ 177======================================================================*/
199 178
200static int get_tuple(client_handle_t handle, tuple_t *tuple, 179static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
201 cisparse_t *parse) 180 cisparse_t *parse)
202{ 181{
203 int i = pcmcia_get_tuple_data(handle, tuple); 182 int i = pcmcia_get_tuple_data(handle, tuple);
@@ -205,7 +184,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
205 return pcmcia_parse_tuple(handle, tuple, parse); 184 return pcmcia_parse_tuple(handle, tuple, parse);
206} 185}
207 186
208static int first_tuple(client_handle_t handle, tuple_t *tuple, 187static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
209 cisparse_t *parse) 188 cisparse_t *parse)
210{ 189{
211 int i = pcmcia_get_first_tuple(handle, tuple); 190 int i = pcmcia_get_first_tuple(handle, tuple);
@@ -213,7 +192,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
213 return get_tuple(handle, tuple, parse); 192 return get_tuple(handle, tuple, parse);
214} 193}
215 194
216static int next_tuple(client_handle_t handle, tuple_t *tuple, 195static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
217 cisparse_t *parse) 196 cisparse_t *parse)
218{ 197{
219 int i = pcmcia_get_next_tuple(handle, tuple); 198 int i = pcmcia_get_next_tuple(handle, tuple);
@@ -221,9 +200,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
221 return get_tuple(handle, tuple, parse); 200 return get_tuple(handle, tuple, parse);
222} 201}
223 202
224static void avma1cs_config(dev_link_t *link) 203static int avma1cs_config(struct pcmcia_device *link)
225{ 204{
226 client_handle_t handle;
227 tuple_t tuple; 205 tuple_t tuple;
228 cisparse_t parse; 206 cisparse_t parse;
229 cistpl_cftable_entry_t *cf = &parse.cftable_entry; 207 cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -233,8 +211,7 @@ static void avma1cs_config(dev_link_t *link)
233 char devname[128]; 211 char devname[128];
234 IsdnCard_t icard; 212 IsdnCard_t icard;
235 int busy = 0; 213 int busy = 0;
236 214
237 handle = link->handle;
238 dev = link->priv; 215 dev = link->priv;
239 216
240 DEBUG(0, "avma1cs_config(0x%p)\n", link); 217 DEBUG(0, "avma1cs_config(0x%p)\n", link);
@@ -245,25 +222,21 @@ static void avma1cs_config(dev_link_t *link)
245 */ 222 */
246 do { 223 do {
247 tuple.DesiredTuple = CISTPL_CONFIG; 224 tuple.DesiredTuple = CISTPL_CONFIG;
248 i = pcmcia_get_first_tuple(handle, &tuple); 225 i = pcmcia_get_first_tuple(link, &tuple);
249 if (i != CS_SUCCESS) break; 226 if (i != CS_SUCCESS) break;
250 tuple.TupleData = buf; 227 tuple.TupleData = buf;
251 tuple.TupleDataMax = 64; 228 tuple.TupleDataMax = 64;
252 tuple.TupleOffset = 0; 229 tuple.TupleOffset = 0;
253 i = pcmcia_get_tuple_data(handle, &tuple); 230 i = pcmcia_get_tuple_data(link, &tuple);
254 if (i != CS_SUCCESS) break; 231 if (i != CS_SUCCESS) break;
255 i = pcmcia_parse_tuple(handle, &tuple, &parse); 232 i = pcmcia_parse_tuple(link, &tuple, &parse);
256 if (i != CS_SUCCESS) break; 233 if (i != CS_SUCCESS) break;
257 link->conf.ConfigBase = parse.config.base; 234 link->conf.ConfigBase = parse.config.base;
258 } while (0); 235 } while (0);
259 if (i != CS_SUCCESS) { 236 if (i != CS_SUCCESS) {
260 cs_error(link->handle, ParseTuple, i); 237 cs_error(link, ParseTuple, i);
261 link->state &= ~DEV_CONFIG_PENDING; 238 return -ENODEV;
262 return;
263 } 239 }
264
265 /* Configure card */
266 link->state |= DEV_CONFIG;
267 240
268 do { 241 do {
269 242
@@ -274,7 +247,7 @@ static void avma1cs_config(dev_link_t *link)
274 tuple.DesiredTuple = CISTPL_VERS_1; 247 tuple.DesiredTuple = CISTPL_VERS_1;
275 248
276 devname[0] = 0; 249 devname[0] = 0;
277 if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { 250 if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
278 strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], 251 strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
279 sizeof(devname)); 252 sizeof(devname));
280 } 253 }
@@ -285,7 +258,7 @@ static void avma1cs_config(dev_link_t *link)
285 tuple.TupleOffset = 0; tuple.TupleDataMax = 255; 258 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
286 tuple.Attributes = 0; 259 tuple.Attributes = 0;
287 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 260 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
288 i = first_tuple(handle, &tuple, &parse); 261 i = first_tuple(link, &tuple, &parse);
289 while (i == CS_SUCCESS) { 262 while (i == CS_SUCCESS) {
290 if (cf->io.nwin > 0) { 263 if (cf->io.nwin > 0) {
291 link->conf.ConfigIndex = cf->index; 264 link->conf.ConfigIndex = cf->index;
@@ -295,36 +268,36 @@ static void avma1cs_config(dev_link_t *link)
295 printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", 268 printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
296 link->io.BasePort1, 269 link->io.BasePort1,
297 link->io.BasePort1+link->io.NumPorts1 - 1); 270 link->io.BasePort1+link->io.NumPorts1 - 1);
298 i = pcmcia_request_io(link->handle, &link->io); 271 i = pcmcia_request_io(link, &link->io);
299 if (i == CS_SUCCESS) goto found_port; 272 if (i == CS_SUCCESS) goto found_port;
300 } 273 }
301 i = next_tuple(handle, &tuple, &parse); 274 i = next_tuple(link, &tuple, &parse);
302 } 275 }
303 276
304found_port: 277found_port:
305 if (i != CS_SUCCESS) { 278 if (i != CS_SUCCESS) {
306 cs_error(link->handle, RequestIO, i); 279 cs_error(link, RequestIO, i);
307 break; 280 break;
308 } 281 }
309 282
310 /* 283 /*
311 * allocate an interrupt line 284 * allocate an interrupt line
312 */ 285 */
313 i = pcmcia_request_irq(link->handle, &link->irq); 286 i = pcmcia_request_irq(link, &link->irq);
314 if (i != CS_SUCCESS) { 287 if (i != CS_SUCCESS) {
315 cs_error(link->handle, RequestIRQ, i); 288 cs_error(link, RequestIRQ, i);
316 pcmcia_release_io(link->handle, &link->io); 289 /* undo */
290 pcmcia_disable_device(link);
317 break; 291 break;
318 } 292 }
319 293
320 /* 294 /*
321 * configure the PCMCIA socket 295 * configure the PCMCIA socket
322 */ 296 */
323 i = pcmcia_request_configuration(link->handle, &link->conf); 297 i = pcmcia_request_configuration(link, &link->conf);
324 if (i != CS_SUCCESS) { 298 if (i != CS_SUCCESS) {
325 cs_error(link->handle, RequestConfiguration, i); 299 cs_error(link, RequestConfiguration, i);
326 pcmcia_release_io(link->handle, &link->io); 300 pcmcia_disable_device(link);
327 pcmcia_release_irq(link->handle, &link->irq);
328 break; 301 break;
329 } 302 }
330 303
@@ -336,13 +309,12 @@ found_port:
336 strcpy(dev->node.dev_name, "A1"); 309 strcpy(dev->node.dev_name, "A1");
337 dev->node.major = 45; 310 dev->node.major = 45;
338 dev->node.minor = 0; 311 dev->node.minor = 0;
339 link->dev = &dev->node; 312 link->dev_node = &dev->node;
340 313
341 link->state &= ~DEV_CONFIG_PENDING;
342 /* If any step failed, release any partially configured state */ 314 /* If any step failed, release any partially configured state */
343 if (i != 0) { 315 if (i != 0) {
344 avma1cs_release(link); 316 avma1cs_release(link);
345 return; 317 return -ENODEV;
346 } 318 }
347 319
348 printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", 320 printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
@@ -357,10 +329,11 @@ found_port:
357 if (i < 0) { 329 if (i < 0) {
358 printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); 330 printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
359 avma1cs_release(link); 331 avma1cs_release(link);
360 return; 332 return -ENODEV;
361 } 333 }
362 dev->node.minor = i; 334 dev->node.minor = i;
363 335
336 return 0;
364} /* avma1cs_config */ 337} /* avma1cs_config */
365 338
366/*====================================================================== 339/*======================================================================
@@ -371,47 +344,18 @@ found_port:
371 344
372======================================================================*/ 345======================================================================*/
373 346
374static void avma1cs_release(dev_link_t *link) 347static void avma1cs_release(struct pcmcia_device *link)
375{ 348{
376 local_info_t *local = link->priv; 349 local_info_t *local = link->priv;
377 350
378 DEBUG(0, "avma1cs_release(0x%p)\n", link); 351 DEBUG(0, "avma1cs_release(0x%p)\n", link);
379 352
380 /* no unregister function with hisax */ 353 /* now unregister function with hisax */
381 HiSax_closecard(local->node.minor); 354 HiSax_closecard(local->node.minor);
382 355
383 /* Unlink the device chain */ 356 pcmcia_disable_device(link);
384 link->dev = NULL;
385
386 /* Don't bother checking to see if these succeed or not */
387 pcmcia_release_configuration(link->handle);
388 pcmcia_release_io(link->handle, &link->io);
389 pcmcia_release_irq(link->handle, &link->irq);
390 link->state &= ~DEV_CONFIG;
391} /* avma1cs_release */ 357} /* avma1cs_release */
392 358
393static int avma1cs_suspend(struct pcmcia_device *dev)
394{
395 dev_link_t *link = dev_to_instance(dev);
396
397 link->state |= DEV_SUSPEND;
398 if (link->state & DEV_CONFIG)
399 pcmcia_release_configuration(link->handle);
400
401 return 0;
402}
403
404static int avma1cs_resume(struct pcmcia_device *dev)
405{
406 dev_link_t *link = dev_to_instance(dev);
407
408 link->state &= ~DEV_SUSPEND;
409 if (link->state & DEV_CONFIG)
410 pcmcia_request_configuration(link->handle, &link->conf);
411
412 return 0;
413}
414
415 359
416static struct pcmcia_device_id avma1cs_ids[] = { 360static struct pcmcia_device_id avma1cs_ids[] = {
417 PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), 361 PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
@@ -425,13 +369,11 @@ static struct pcmcia_driver avma1cs_driver = {
425 .drv = { 369 .drv = {
426 .name = "avma1_cs", 370 .name = "avma1_cs",
427 }, 371 },
428 .probe = avma1cs_attach, 372 .probe = avma1cs_probe,
429 .remove = avma1cs_detach, 373 .remove = avma1cs_detach,
430 .id_table = avma1cs_ids, 374 .id_table = avma1cs_ids,
431 .suspend = avma1cs_suspend,
432 .resume = avma1cs_resume,
433}; 375};
434 376
435/*====================================================================*/ 377/*====================================================================*/
436 378
437static int __init init_avma1_cs(void) 379static int __init init_avma1_cs(void)