aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hisax/elsa_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/hisax/elsa_cs.c')
-rw-r--r--drivers/isdn/hisax/elsa_cs.c112
1 files changed, 39 insertions, 73 deletions
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 062fb8f0739f..e18e75be8ed3 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -94,8 +94,8 @@ module_param(protocol, int, 0);
94 handler. 94 handler.
95*/ 95*/
96 96
97static void elsa_cs_config(dev_link_t *link); 97static int elsa_cs_config(struct pcmcia_device *link);
98static void elsa_cs_release(dev_link_t *link); 98static void elsa_cs_release(struct pcmcia_device *link);
99 99
100/* 100/*
101 The attach() and detach() entry points are used to create and destroy 101 The attach() and detach() entry points are used to create and destroy
@@ -111,7 +111,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev);
111 example, ethernet cards, modems). In other cases, there may be 111 example, ethernet cards, modems). In other cases, there may be
112 many actual or logical devices (SCSI adapters, memory cards with 112 many actual or logical devices (SCSI adapters, memory cards with
113 multiple partitions). The dev_node_t structures need to be kept 113 multiple partitions). The dev_node_t structures need to be kept
114 in a linked list starting at the 'dev' field of a dev_link_t 114 in a linked list starting at the 'dev' field of a struct pcmcia_device
115 structure. We allocate them in the card's private data structure, 115 structure. We allocate them in the card's private data structure,
116 because they generally shouldn't be allocated dynamically. 116 because they generally shouldn't be allocated dynamically.
117 In this case, we also provide a flag to indicate if a device is 117 In this case, we also provide a flag to indicate if a device is
@@ -121,7 +121,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev);
121*/ 121*/
122 122
123typedef struct local_info_t { 123typedef struct local_info_t {
124 dev_link_t link; 124 struct pcmcia_device *p_dev;
125 dev_node_t node; 125 dev_node_t node;
126 int busy; 126 int busy;
127 int cardnr; 127 int cardnr;
@@ -139,9 +139,8 @@ typedef struct local_info_t {
139 139
140======================================================================*/ 140======================================================================*/
141 141
142static int elsa_cs_attach(struct pcmcia_device *p_dev) 142static int elsa_cs_probe(struct pcmcia_device *link)
143{ 143{
144 dev_link_t *link;
145 local_info_t *local; 144 local_info_t *local;
146 145
147 DEBUG(0, "elsa_cs_attach()\n"); 146 DEBUG(0, "elsa_cs_attach()\n");
@@ -150,8 +149,11 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
150 local = kmalloc(sizeof(local_info_t), GFP_KERNEL); 149 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
151 if (!local) return -ENOMEM; 150 if (!local) return -ENOMEM;
152 memset(local, 0, sizeof(local_info_t)); 151 memset(local, 0, sizeof(local_info_t));
152
153 local->p_dev = link;
154 link->priv = local;
155
153 local->cardnr = -1; 156 local->cardnr = -1;
154 link = &local->link; link->priv = local;
155 157
156 /* Interrupt setup */ 158 /* Interrupt setup */
157 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; 159 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -170,16 +172,9 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
170 link->io.IOAddrLines = 3; 172 link->io.IOAddrLines = 3;
171 173
172 link->conf.Attributes = CONF_ENABLE_IRQ; 174 link->conf.Attributes = CONF_ENABLE_IRQ;
173 link->conf.Vcc = 50;
174 link->conf.IntType = INT_MEMORY_AND_IO; 175 link->conf.IntType = INT_MEMORY_AND_IO;
175 176
176 link->handle = p_dev; 177 return elsa_cs_config(link);
177 p_dev->instance = link;
178
179 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
180 elsa_cs_config(link);
181
182 return 0;
183} /* elsa_cs_attach */ 178} /* elsa_cs_attach */
184 179
185/*====================================================================== 180/*======================================================================
@@ -191,20 +186,16 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
191 186
192======================================================================*/ 187======================================================================*/
193 188
194static void elsa_cs_detach(struct pcmcia_device *p_dev) 189static void elsa_cs_detach(struct pcmcia_device *link)
195{ 190{
196 dev_link_t *link = dev_to_instance(p_dev); 191 local_info_t *info = link->priv;
197 local_info_t *info = link->priv;
198 192
199 DEBUG(0, "elsa_cs_detach(0x%p)\n", link); 193 DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
200 194
201 if (link->state & DEV_CONFIG) { 195 info->busy = 1;
202 info->busy = 1; 196 elsa_cs_release(link);
203 elsa_cs_release(link);
204 }
205
206 kfree(info);
207 197
198 kfree(info);
208} /* elsa_cs_detach */ 199} /* elsa_cs_detach */
209 200
210/*====================================================================== 201/*======================================================================
@@ -214,7 +205,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev)
214 device available to the system. 205 device available to the system.
215 206
216======================================================================*/ 207======================================================================*/
217static int get_tuple(client_handle_t handle, tuple_t *tuple, 208static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
218 cisparse_t *parse) 209 cisparse_t *parse)
219{ 210{
220 int i = pcmcia_get_tuple_data(handle, tuple); 211 int i = pcmcia_get_tuple_data(handle, tuple);
@@ -222,7 +213,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
222 return pcmcia_parse_tuple(handle, tuple, parse); 213 return pcmcia_parse_tuple(handle, tuple, parse);
223} 214}
224 215
225static int first_tuple(client_handle_t handle, tuple_t *tuple, 216static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
226 cisparse_t *parse) 217 cisparse_t *parse)
227{ 218{
228 int i = pcmcia_get_first_tuple(handle, tuple); 219 int i = pcmcia_get_first_tuple(handle, tuple);
@@ -230,7 +221,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
230 return get_tuple(handle, tuple, parse); 221 return get_tuple(handle, tuple, parse);
231} 222}
232 223
233static int next_tuple(client_handle_t handle, tuple_t *tuple, 224static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
234 cisparse_t *parse) 225 cisparse_t *parse)
235{ 226{
236 int i = pcmcia_get_next_tuple(handle, tuple); 227 int i = pcmcia_get_next_tuple(handle, tuple);
@@ -238,9 +229,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
238 return get_tuple(handle, tuple, parse); 229 return get_tuple(handle, tuple, parse);
239} 230}
240 231
241static void elsa_cs_config(dev_link_t *link) 232static int elsa_cs_config(struct pcmcia_device *link)
242{ 233{
243 client_handle_t handle;
244 tuple_t tuple; 234 tuple_t tuple;
245 cisparse_t parse; 235 cisparse_t parse;
246 local_info_t *dev; 236 local_info_t *dev;
@@ -250,7 +240,6 @@ static void elsa_cs_config(dev_link_t *link)
250 IsdnCard_t icard; 240 IsdnCard_t icard;
251 241
252 DEBUG(0, "elsa_config(0x%p)\n", link); 242 DEBUG(0, "elsa_config(0x%p)\n", link);
253 handle = link->handle;
254 dev = link->priv; 243 dev = link->priv;
255 244
256 /* 245 /*
@@ -262,7 +251,7 @@ static void elsa_cs_config(dev_link_t *link)
262 tuple.TupleDataMax = 255; 251 tuple.TupleDataMax = 255;
263 tuple.TupleOffset = 0; 252 tuple.TupleOffset = 0;
264 tuple.Attributes = 0; 253 tuple.Attributes = 0;
265 i = first_tuple(handle, &tuple, &parse); 254 i = first_tuple(link, &tuple, &parse);
266 if (i != CS_SUCCESS) { 255 if (i != CS_SUCCESS) {
267 last_fn = ParseTuple; 256 last_fn = ParseTuple;
268 goto cs_failed; 257 goto cs_failed;
@@ -270,32 +259,29 @@ static void elsa_cs_config(dev_link_t *link)
270 link->conf.ConfigBase = parse.config.base; 259 link->conf.ConfigBase = parse.config.base;
271 link->conf.Present = parse.config.rmask[0]; 260 link->conf.Present = parse.config.rmask[0];
272 261
273 /* Configure card */
274 link->state |= DEV_CONFIG;
275
276 tuple.TupleData = (cisdata_t *)buf; 262 tuple.TupleData = (cisdata_t *)buf;
277 tuple.TupleOffset = 0; tuple.TupleDataMax = 255; 263 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
278 tuple.Attributes = 0; 264 tuple.Attributes = 0;
279 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 265 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
280 i = first_tuple(handle, &tuple, &parse); 266 i = first_tuple(link, &tuple, &parse);
281 while (i == CS_SUCCESS) { 267 while (i == CS_SUCCESS) {
282 if ( (cf->io.nwin > 0) && cf->io.win[0].base) { 268 if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
283 printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n"); 269 printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
284 link->conf.ConfigIndex = cf->index; 270 link->conf.ConfigIndex = cf->index;
285 link->io.BasePort1 = cf->io.win[0].base; 271 link->io.BasePort1 = cf->io.win[0].base;
286 i = pcmcia_request_io(link->handle, &link->io); 272 i = pcmcia_request_io(link, &link->io);
287 if (i == CS_SUCCESS) break; 273 if (i == CS_SUCCESS) break;
288 } else { 274 } else {
289 printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n"); 275 printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
290 link->conf.ConfigIndex = cf->index; 276 link->conf.ConfigIndex = cf->index;
291 for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { 277 for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
292 link->io.BasePort1 = j; 278 link->io.BasePort1 = j;
293 i = pcmcia_request_io(link->handle, &link->io); 279 i = pcmcia_request_io(link, &link->io);
294 if (i == CS_SUCCESS) break; 280 if (i == CS_SUCCESS) break;
295 } 281 }
296 break; 282 break;
297 } 283 }
298 i = next_tuple(handle, &tuple, &parse); 284 i = next_tuple(link, &tuple, &parse);
299 } 285 }
300 286
301 if (i != CS_SUCCESS) { 287 if (i != CS_SUCCESS) {
@@ -303,14 +289,14 @@ static void elsa_cs_config(dev_link_t *link)
303 goto cs_failed; 289 goto cs_failed;
304 } 290 }
305 291
306 i = pcmcia_request_irq(link->handle, &link->irq); 292 i = pcmcia_request_irq(link, &link->irq);
307 if (i != CS_SUCCESS) { 293 if (i != CS_SUCCESS) {
308 link->irq.AssignedIRQ = 0; 294 link->irq.AssignedIRQ = 0;
309 last_fn = RequestIRQ; 295 last_fn = RequestIRQ;
310 goto cs_failed; 296 goto cs_failed;
311 } 297 }
312 298
313 i = pcmcia_request_configuration(link->handle, &link->conf); 299 i = pcmcia_request_configuration(link, &link->conf);
314 if (i != CS_SUCCESS) { 300 if (i != CS_SUCCESS) {
315 last_fn = RequestConfiguration; 301 last_fn = RequestConfiguration;
316 goto cs_failed; 302 goto cs_failed;
@@ -321,14 +307,11 @@ static void elsa_cs_config(dev_link_t *link)
321 sprintf(dev->node.dev_name, "elsa"); 307 sprintf(dev->node.dev_name, "elsa");
322 dev->node.major = dev->node.minor = 0x0; 308 dev->node.major = dev->node.minor = 0x0;
323 309
324 link->dev = &dev->node; 310 link->dev_node = &dev->node;
325 311
326 /* Finally, report what we've done */ 312 /* Finally, report what we've done */
327 printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", 313 printk(KERN_INFO "%s: index 0x%02x: ",
328 dev->node.dev_name, link->conf.ConfigIndex, 314 dev->node.dev_name, link->conf.ConfigIndex);
329 link->conf.Vcc/10, link->conf.Vcc%10);
330 if (link->conf.Vpp1)
331 printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
332 if (link->conf.Attributes & CONF_ENABLE_IRQ) 315 if (link->conf.Attributes & CONF_ENABLE_IRQ)
333 printk(", irq %d", link->irq.AssignedIRQ); 316 printk(", irq %d", link->irq.AssignedIRQ);
334 if (link->io.NumPorts1) 317 if (link->io.NumPorts1)
@@ -339,8 +322,6 @@ static void elsa_cs_config(dev_link_t *link)
339 link->io.BasePort2+link->io.NumPorts2-1); 322 link->io.BasePort2+link->io.NumPorts2-1);
340 printk("\n"); 323 printk("\n");
341 324
342 link->state &= ~DEV_CONFIG_PENDING;
343
344 icard.para[0] = link->irq.AssignedIRQ; 325 icard.para[0] = link->irq.AssignedIRQ;
345 icard.para[1] = link->io.BasePort1; 326 icard.para[1] = link->io.BasePort1;
346 icard.protocol = protocol; 327 icard.protocol = protocol;
@@ -354,10 +335,11 @@ static void elsa_cs_config(dev_link_t *link)
354 } else 335 } else
355 ((local_info_t*)link->priv)->cardnr = i; 336 ((local_info_t*)link->priv)->cardnr = i;
356 337
357 return; 338 return 0;
358cs_failed: 339cs_failed:
359 cs_error(link->handle, last_fn, i); 340 cs_error(link, last_fn, i);
360 elsa_cs_release(link); 341 elsa_cs_release(link);
342 return -ENODEV;
361} /* elsa_cs_config */ 343} /* elsa_cs_config */
362 344
363/*====================================================================== 345/*======================================================================
@@ -368,7 +350,7 @@ cs_failed:
368 350
369======================================================================*/ 351======================================================================*/
370 352
371static void elsa_cs_release(dev_link_t *link) 353static void elsa_cs_release(struct pcmcia_device *link)
372{ 354{
373 local_info_t *local = link->priv; 355 local_info_t *local = link->priv;
374 356
@@ -380,39 +362,23 @@ static void elsa_cs_release(dev_link_t *link)
380 HiSax_closecard(local->cardnr); 362 HiSax_closecard(local->cardnr);
381 } 363 }
382 } 364 }
383 /* Unlink the device chain */ 365
384 link->dev = NULL; 366 pcmcia_disable_device(link);
385
386 /* Don't bother checking to see if these succeed or not */
387 if (link->win)
388 pcmcia_release_window(link->win);
389 pcmcia_release_configuration(link->handle);
390 pcmcia_release_io(link->handle, &link->io);
391 pcmcia_release_irq(link->handle, &link->irq);
392 link->state &= ~DEV_CONFIG;
393} /* elsa_cs_release */ 367} /* elsa_cs_release */
394 368
395static int elsa_suspend(struct pcmcia_device *p_dev) 369static int elsa_suspend(struct pcmcia_device *link)
396{ 370{
397 dev_link_t *link = dev_to_instance(p_dev);
398 local_info_t *dev = link->priv; 371 local_info_t *dev = link->priv;
399 372
400 link->state |= DEV_SUSPEND;
401 dev->busy = 1; 373 dev->busy = 1;
402 if (link->state & DEV_CONFIG)
403 pcmcia_release_configuration(link->handle);
404 374
405 return 0; 375 return 0;
406} 376}
407 377
408static int elsa_resume(struct pcmcia_device *p_dev) 378static int elsa_resume(struct pcmcia_device *link)
409{ 379{
410 dev_link_t *link = dev_to_instance(p_dev);
411 local_info_t *dev = link->priv; 380 local_info_t *dev = link->priv;
412 381
413 link->state &= ~DEV_SUSPEND;
414 if (link->state & DEV_CONFIG)
415 pcmcia_request_configuration(link->handle, &link->conf);
416 dev->busy = 0; 382 dev->busy = 0;
417 383
418 return 0; 384 return 0;
@@ -430,7 +396,7 @@ static struct pcmcia_driver elsa_cs_driver = {
430 .drv = { 396 .drv = {
431 .name = "elsa_cs", 397 .name = "elsa_cs",
432 }, 398 },
433 .probe = elsa_cs_attach, 399 .probe = elsa_cs_probe,
434 .remove = elsa_cs_detach, 400 .remove = elsa_cs_detach,
435 .id_table = elsa_ids, 401 .id_table = elsa_ids,
436 .suspend = elsa_suspend, 402 .suspend = elsa_suspend,