diff options
Diffstat (limited to 'drivers/isdn/hisax/elsa_cs.c')
-rw-r--r-- | drivers/isdn/hisax/elsa_cs.c | 112 |
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 | ||
97 | static void elsa_cs_config(dev_link_t *link); | 97 | static int elsa_cs_config(struct pcmcia_device *link); |
98 | static void elsa_cs_release(dev_link_t *link); | 98 | static 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 | ||
123 | typedef struct local_info_t { | 123 | typedef 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 | ||
142 | static int elsa_cs_attach(struct pcmcia_device *p_dev) | 142 | static 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 | ||
194 | static void elsa_cs_detach(struct pcmcia_device *p_dev) | 189 | static 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 | ======================================================================*/ |
217 | static int get_tuple(client_handle_t handle, tuple_t *tuple, | 208 | static 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 | ||
225 | static int first_tuple(client_handle_t handle, tuple_t *tuple, | 216 | static 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 | ||
233 | static int next_tuple(client_handle_t handle, tuple_t *tuple, | 224 | static 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 | ||
241 | static void elsa_cs_config(dev_link_t *link) | 232 | static 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; |
358 | cs_failed: | 339 | cs_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 | ||
371 | static void elsa_cs_release(dev_link_t *link) | 353 | static 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 | ||
395 | static int elsa_suspend(struct pcmcia_device *p_dev) | 369 | static 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 | ||
408 | static int elsa_resume(struct pcmcia_device *p_dev) | 378 | static 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, |