diff options
Diffstat (limited to 'drivers/isdn/hisax/teles_cs.c')
-rw-r--r-- | drivers/isdn/hisax/teles_cs.c | 121 |
1 files changed, 44 insertions, 77 deletions
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 4e5c14c7240e..afcc2aeadb34 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c | |||
@@ -75,8 +75,8 @@ module_param(protocol, int, 0); | |||
75 | handler. | 75 | handler. |
76 | */ | 76 | */ |
77 | 77 | ||
78 | static void teles_cs_config(dev_link_t *link); | 78 | static int teles_cs_config(struct pcmcia_device *link); |
79 | static void teles_cs_release(dev_link_t *link); | 79 | static void teles_cs_release(struct pcmcia_device *link); |
80 | 80 | ||
81 | /* | 81 | /* |
82 | The attach() and detach() entry points are used to create and destroy | 82 | The attach() and detach() entry points are used to create and destroy |
@@ -89,10 +89,10 @@ static void teles_detach(struct pcmcia_device *p_dev); | |||
89 | /* | 89 | /* |
90 | A linked list of "instances" of the teles_cs device. Each actual | 90 | A linked list of "instances" of the teles_cs device. Each actual |
91 | PCMCIA card corresponds to one device instance, and is described | 91 | PCMCIA card corresponds to one device instance, and is described |
92 | by one dev_link_t structure (defined in ds.h). | 92 | by one struct pcmcia_device structure (defined in ds.h). |
93 | 93 | ||
94 | You may not want to use a linked list for this -- for example, the | 94 | You may not want to use a linked list for this -- for example, the |
95 | memory card driver uses an array of dev_link_t pointers, where minor | 95 | memory card driver uses an array of struct pcmcia_device pointers, where minor |
96 | device numbers are used to derive the corresponding array index. | 96 | device numbers are used to derive the corresponding array index. |
97 | */ | 97 | */ |
98 | 98 | ||
@@ -102,7 +102,7 @@ static void teles_detach(struct pcmcia_device *p_dev); | |||
102 | example, ethernet cards, modems). In other cases, there may be | 102 | example, ethernet cards, modems). In other cases, there may be |
103 | many actual or logical devices (SCSI adapters, memory cards with | 103 | many actual or logical devices (SCSI adapters, memory cards with |
104 | multiple partitions). The dev_node_t structures need to be kept | 104 | multiple partitions). The dev_node_t structures need to be kept |
105 | in a linked list starting at the 'dev' field of a dev_link_t | 105 | in a linked list starting at the 'dev' field of a struct pcmcia_device |
106 | structure. We allocate them in the card's private data structure, | 106 | structure. We allocate them in the card's private data structure, |
107 | because they generally shouldn't be allocated dynamically. | 107 | because they generally shouldn't be allocated dynamically. |
108 | In this case, we also provide a flag to indicate if a device is | 108 | In this case, we also provide a flag to indicate if a device is |
@@ -112,7 +112,7 @@ static void teles_detach(struct pcmcia_device *p_dev); | |||
112 | */ | 112 | */ |
113 | 113 | ||
114 | typedef struct local_info_t { | 114 | typedef struct local_info_t { |
115 | dev_link_t link; | 115 | struct pcmcia_device *p_dev; |
116 | dev_node_t node; | 116 | dev_node_t node; |
117 | int busy; | 117 | int busy; |
118 | int cardnr; | 118 | int cardnr; |
@@ -130,9 +130,8 @@ typedef struct local_info_t { | |||
130 | 130 | ||
131 | ======================================================================*/ | 131 | ======================================================================*/ |
132 | 132 | ||
133 | static int teles_attach(struct pcmcia_device *p_dev) | 133 | static int teles_probe(struct pcmcia_device *link) |
134 | { | 134 | { |
135 | dev_link_t *link; | ||
136 | local_info_t *local; | 135 | local_info_t *local; |
137 | 136 | ||
138 | DEBUG(0, "teles_attach()\n"); | 137 | DEBUG(0, "teles_attach()\n"); |
@@ -142,7 +141,9 @@ static int teles_attach(struct pcmcia_device *p_dev) | |||
142 | if (!local) return -ENOMEM; | 141 | if (!local) return -ENOMEM; |
143 | memset(local, 0, sizeof(local_info_t)); | 142 | memset(local, 0, sizeof(local_info_t)); |
144 | local->cardnr = -1; | 143 | local->cardnr = -1; |
145 | link = &local->link; link->priv = local; | 144 | |
145 | local->p_dev = link; | ||
146 | link->priv = local; | ||
146 | 147 | ||
147 | /* Interrupt setup */ | 148 | /* Interrupt setup */ |
148 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | 149 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; |
@@ -161,16 +162,9 @@ static int teles_attach(struct pcmcia_device *p_dev) | |||
161 | link->io.IOAddrLines = 5; | 162 | link->io.IOAddrLines = 5; |
162 | 163 | ||
163 | link->conf.Attributes = CONF_ENABLE_IRQ; | 164 | link->conf.Attributes = CONF_ENABLE_IRQ; |
164 | link->conf.Vcc = 50; | ||
165 | link->conf.IntType = INT_MEMORY_AND_IO; | 165 | link->conf.IntType = INT_MEMORY_AND_IO; |
166 | 166 | ||
167 | link->handle = p_dev; | 167 | return teles_cs_config(link); |
168 | p_dev->instance = link; | ||
169 | |||
170 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
171 | teles_cs_config(link); | ||
172 | |||
173 | return 0; | ||
174 | } /* teles_attach */ | 168 | } /* teles_attach */ |
175 | 169 | ||
176 | /*====================================================================== | 170 | /*====================================================================== |
@@ -182,20 +176,16 @@ static int teles_attach(struct pcmcia_device *p_dev) | |||
182 | 176 | ||
183 | ======================================================================*/ | 177 | ======================================================================*/ |
184 | 178 | ||
185 | static void teles_detach(struct pcmcia_device *p_dev) | 179 | static void teles_detach(struct pcmcia_device *link) |
186 | { | 180 | { |
187 | dev_link_t *link = dev_to_instance(p_dev); | 181 | local_info_t *info = link->priv; |
188 | local_info_t *info = link->priv; | ||
189 | |||
190 | DEBUG(0, "teles_detach(0x%p)\n", link); | ||
191 | 182 | ||
192 | if (link->state & DEV_CONFIG) { | 183 | DEBUG(0, "teles_detach(0x%p)\n", link); |
193 | info->busy = 1; | ||
194 | teles_cs_release(link); | ||
195 | } | ||
196 | 184 | ||
197 | kfree(info); | 185 | info->busy = 1; |
186 | teles_cs_release(link); | ||
198 | 187 | ||
188 | kfree(info); | ||
199 | } /* teles_detach */ | 189 | } /* teles_detach */ |
200 | 190 | ||
201 | /*====================================================================== | 191 | /*====================================================================== |
@@ -205,7 +195,7 @@ static void teles_detach(struct pcmcia_device *p_dev) | |||
205 | device available to the system. | 195 | device available to the system. |
206 | 196 | ||
207 | ======================================================================*/ | 197 | ======================================================================*/ |
208 | static int get_tuple(client_handle_t handle, tuple_t *tuple, | 198 | static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, |
209 | cisparse_t *parse) | 199 | cisparse_t *parse) |
210 | { | 200 | { |
211 | int i = pcmcia_get_tuple_data(handle, tuple); | 201 | int i = pcmcia_get_tuple_data(handle, tuple); |
@@ -213,7 +203,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, | |||
213 | return pcmcia_parse_tuple(handle, tuple, parse); | 203 | return pcmcia_parse_tuple(handle, tuple, parse); |
214 | } | 204 | } |
215 | 205 | ||
216 | static int first_tuple(client_handle_t handle, tuple_t *tuple, | 206 | static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, |
217 | cisparse_t *parse) | 207 | cisparse_t *parse) |
218 | { | 208 | { |
219 | int i = pcmcia_get_first_tuple(handle, tuple); | 209 | int i = pcmcia_get_first_tuple(handle, tuple); |
@@ -221,7 +211,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, | |||
221 | return get_tuple(handle, tuple, parse); | 211 | return get_tuple(handle, tuple, parse); |
222 | } | 212 | } |
223 | 213 | ||
224 | static int next_tuple(client_handle_t handle, tuple_t *tuple, | 214 | static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, |
225 | cisparse_t *parse) | 215 | cisparse_t *parse) |
226 | { | 216 | { |
227 | int i = pcmcia_get_next_tuple(handle, tuple); | 217 | int i = pcmcia_get_next_tuple(handle, tuple); |
@@ -229,9 +219,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, | |||
229 | return get_tuple(handle, tuple, parse); | 219 | return get_tuple(handle, tuple, parse); |
230 | } | 220 | } |
231 | 221 | ||
232 | static void teles_cs_config(dev_link_t *link) | 222 | static int teles_cs_config(struct pcmcia_device *link) |
233 | { | 223 | { |
234 | client_handle_t handle; | ||
235 | tuple_t tuple; | 224 | tuple_t tuple; |
236 | cisparse_t parse; | 225 | cisparse_t parse; |
237 | local_info_t *dev; | 226 | local_info_t *dev; |
@@ -241,7 +230,6 @@ static void teles_cs_config(dev_link_t *link) | |||
241 | IsdnCard_t icard; | 230 | IsdnCard_t icard; |
242 | 231 | ||
243 | DEBUG(0, "teles_config(0x%p)\n", link); | 232 | DEBUG(0, "teles_config(0x%p)\n", link); |
244 | handle = link->handle; | ||
245 | dev = link->priv; | 233 | dev = link->priv; |
246 | 234 | ||
247 | /* | 235 | /* |
@@ -253,7 +241,7 @@ static void teles_cs_config(dev_link_t *link) | |||
253 | tuple.TupleDataMax = 255; | 241 | tuple.TupleDataMax = 255; |
254 | tuple.TupleOffset = 0; | 242 | tuple.TupleOffset = 0; |
255 | tuple.Attributes = 0; | 243 | tuple.Attributes = 0; |
256 | i = first_tuple(handle, &tuple, &parse); | 244 | i = first_tuple(link, &tuple, &parse); |
257 | if (i != CS_SUCCESS) { | 245 | if (i != CS_SUCCESS) { |
258 | last_fn = ParseTuple; | 246 | last_fn = ParseTuple; |
259 | goto cs_failed; | 247 | goto cs_failed; |
@@ -261,32 +249,29 @@ static void teles_cs_config(dev_link_t *link) | |||
261 | link->conf.ConfigBase = parse.config.base; | 249 | link->conf.ConfigBase = parse.config.base; |
262 | link->conf.Present = parse.config.rmask[0]; | 250 | link->conf.Present = parse.config.rmask[0]; |
263 | 251 | ||
264 | /* Configure card */ | ||
265 | link->state |= DEV_CONFIG; | ||
266 | |||
267 | tuple.TupleData = (cisdata_t *)buf; | 252 | tuple.TupleData = (cisdata_t *)buf; |
268 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; | 253 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; |
269 | tuple.Attributes = 0; | 254 | tuple.Attributes = 0; |
270 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 255 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
271 | i = first_tuple(handle, &tuple, &parse); | 256 | i = first_tuple(link, &tuple, &parse); |
272 | while (i == CS_SUCCESS) { | 257 | while (i == CS_SUCCESS) { |
273 | if ( (cf->io.nwin > 0) && cf->io.win[0].base) { | 258 | if ( (cf->io.nwin > 0) && cf->io.win[0].base) { |
274 | printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); | 259 | printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); |
275 | link->conf.ConfigIndex = cf->index; | 260 | link->conf.ConfigIndex = cf->index; |
276 | link->io.BasePort1 = cf->io.win[0].base; | 261 | link->io.BasePort1 = cf->io.win[0].base; |
277 | i = pcmcia_request_io(link->handle, &link->io); | 262 | i = pcmcia_request_io(link, &link->io); |
278 | if (i == CS_SUCCESS) break; | 263 | if (i == CS_SUCCESS) break; |
279 | } else { | 264 | } else { |
280 | printk(KERN_INFO "(teles_cs: looks like the 97 model)\n"); | 265 | printk(KERN_INFO "(teles_cs: looks like the 97 model)\n"); |
281 | link->conf.ConfigIndex = cf->index; | 266 | link->conf.ConfigIndex = cf->index; |
282 | for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { | 267 | for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { |
283 | link->io.BasePort1 = j; | 268 | link->io.BasePort1 = j; |
284 | i = pcmcia_request_io(link->handle, &link->io); | 269 | i = pcmcia_request_io(link, &link->io); |
285 | if (i == CS_SUCCESS) break; | 270 | if (i == CS_SUCCESS) break; |
286 | } | 271 | } |
287 | break; | 272 | break; |
288 | } | 273 | } |
289 | i = next_tuple(handle, &tuple, &parse); | 274 | i = next_tuple(link, &tuple, &parse); |
290 | } | 275 | } |
291 | 276 | ||
292 | if (i != CS_SUCCESS) { | 277 | if (i != CS_SUCCESS) { |
@@ -294,14 +279,14 @@ static void teles_cs_config(dev_link_t *link) | |||
294 | goto cs_failed; | 279 | goto cs_failed; |
295 | } | 280 | } |
296 | 281 | ||
297 | i = pcmcia_request_irq(link->handle, &link->irq); | 282 | i = pcmcia_request_irq(link, &link->irq); |
298 | if (i != CS_SUCCESS) { | 283 | if (i != CS_SUCCESS) { |
299 | link->irq.AssignedIRQ = 0; | 284 | link->irq.AssignedIRQ = 0; |
300 | last_fn = RequestIRQ; | 285 | last_fn = RequestIRQ; |
301 | goto cs_failed; | 286 | goto cs_failed; |
302 | } | 287 | } |
303 | 288 | ||
304 | i = pcmcia_request_configuration(link->handle, &link->conf); | 289 | i = pcmcia_request_configuration(link, &link->conf); |
305 | if (i != CS_SUCCESS) { | 290 | if (i != CS_SUCCESS) { |
306 | last_fn = RequestConfiguration; | 291 | last_fn = RequestConfiguration; |
307 | goto cs_failed; | 292 | goto cs_failed; |
@@ -312,14 +297,11 @@ static void teles_cs_config(dev_link_t *link) | |||
312 | sprintf(dev->node.dev_name, "teles"); | 297 | sprintf(dev->node.dev_name, "teles"); |
313 | dev->node.major = dev->node.minor = 0x0; | 298 | dev->node.major = dev->node.minor = 0x0; |
314 | 299 | ||
315 | link->dev = &dev->node; | 300 | link->dev_node = &dev->node; |
316 | 301 | ||
317 | /* Finally, report what we've done */ | 302 | /* Finally, report what we've done */ |
318 | printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", | 303 | printk(KERN_INFO "%s: index 0x%02x:", |
319 | dev->node.dev_name, link->conf.ConfigIndex, | 304 | dev->node.dev_name, link->conf.ConfigIndex); |
320 | link->conf.Vcc/10, link->conf.Vcc%10); | ||
321 | if (link->conf.Vpp1) | ||
322 | printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); | ||
323 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 305 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
324 | printk(", irq %d", link->irq.AssignedIRQ); | 306 | printk(", irq %d", link->irq.AssignedIRQ); |
325 | if (link->io.NumPorts1) | 307 | if (link->io.NumPorts1) |
@@ -330,8 +312,6 @@ static void teles_cs_config(dev_link_t *link) | |||
330 | link->io.BasePort2+link->io.NumPorts2-1); | 312 | link->io.BasePort2+link->io.NumPorts2-1); |
331 | printk("\n"); | 313 | printk("\n"); |
332 | 314 | ||
333 | link->state &= ~DEV_CONFIG_PENDING; | ||
334 | |||
335 | icard.para[0] = link->irq.AssignedIRQ; | 315 | icard.para[0] = link->irq.AssignedIRQ; |
336 | icard.para[1] = link->io.BasePort1; | 316 | icard.para[1] = link->io.BasePort1; |
337 | icard.protocol = protocol; | 317 | icard.protocol = protocol; |
@@ -342,13 +322,16 @@ static void teles_cs_config(dev_link_t *link) | |||
342 | printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n", | 322 | printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n", |
343 | i, link->io.BasePort1); | 323 | i, link->io.BasePort1); |
344 | teles_cs_release(link); | 324 | teles_cs_release(link); |
345 | } else | 325 | return -ENODEV; |
346 | ((local_info_t*)link->priv)->cardnr = i; | 326 | } |
327 | |||
328 | ((local_info_t*)link->priv)->cardnr = i; | ||
329 | return 0; | ||
347 | 330 | ||
348 | return; | ||
349 | cs_failed: | 331 | cs_failed: |
350 | cs_error(link->handle, last_fn, i); | 332 | cs_error(link, last_fn, i); |
351 | teles_cs_release(link); | 333 | teles_cs_release(link); |
334 | return -ENODEV; | ||
352 | } /* teles_cs_config */ | 335 | } /* teles_cs_config */ |
353 | 336 | ||
354 | /*====================================================================== | 337 | /*====================================================================== |
@@ -359,7 +342,7 @@ cs_failed: | |||
359 | 342 | ||
360 | ======================================================================*/ | 343 | ======================================================================*/ |
361 | 344 | ||
362 | static void teles_cs_release(dev_link_t *link) | 345 | static void teles_cs_release(struct pcmcia_device *link) |
363 | { | 346 | { |
364 | local_info_t *local = link->priv; | 347 | local_info_t *local = link->priv; |
365 | 348 | ||
@@ -371,39 +354,23 @@ static void teles_cs_release(dev_link_t *link) | |||
371 | HiSax_closecard(local->cardnr); | 354 | HiSax_closecard(local->cardnr); |
372 | } | 355 | } |
373 | } | 356 | } |
374 | /* Unlink the device chain */ | 357 | |
375 | link->dev = NULL; | 358 | pcmcia_disable_device(link); |
376 | |||
377 | /* Don't bother checking to see if these succeed or not */ | ||
378 | if (link->win) | ||
379 | pcmcia_release_window(link->win); | ||
380 | pcmcia_release_configuration(link->handle); | ||
381 | pcmcia_release_io(link->handle, &link->io); | ||
382 | pcmcia_release_irq(link->handle, &link->irq); | ||
383 | link->state &= ~DEV_CONFIG; | ||
384 | } /* teles_cs_release */ | 359 | } /* teles_cs_release */ |
385 | 360 | ||
386 | static int teles_suspend(struct pcmcia_device *p_dev) | 361 | static int teles_suspend(struct pcmcia_device *link) |
387 | { | 362 | { |
388 | dev_link_t *link = dev_to_instance(p_dev); | ||
389 | local_info_t *dev = link->priv; | 363 | local_info_t *dev = link->priv; |
390 | 364 | ||
391 | link->state |= DEV_SUSPEND; | ||
392 | dev->busy = 1; | 365 | dev->busy = 1; |
393 | if (link->state & DEV_CONFIG) | ||
394 | pcmcia_release_configuration(link->handle); | ||
395 | 366 | ||
396 | return 0; | 367 | return 0; |
397 | } | 368 | } |
398 | 369 | ||
399 | static int teles_resume(struct pcmcia_device *p_dev) | 370 | static int teles_resume(struct pcmcia_device *link) |
400 | { | 371 | { |
401 | dev_link_t *link = dev_to_instance(p_dev); | ||
402 | local_info_t *dev = link->priv; | 372 | local_info_t *dev = link->priv; |
403 | 373 | ||
404 | link->state &= ~DEV_SUSPEND; | ||
405 | if (link->state & DEV_CONFIG) | ||
406 | pcmcia_request_configuration(link->handle, &link->conf); | ||
407 | dev->busy = 0; | 374 | dev->busy = 0; |
408 | 375 | ||
409 | return 0; | 376 | return 0; |
@@ -421,7 +388,7 @@ static struct pcmcia_driver teles_cs_driver = { | |||
421 | .drv = { | 388 | .drv = { |
422 | .name = "teles_cs", | 389 | .name = "teles_cs", |
423 | }, | 390 | }, |
424 | .probe = teles_attach, | 391 | .probe = teles_probe, |
425 | .remove = teles_detach, | 392 | .remove = teles_detach, |
426 | .id_table = teles_ids, | 393 | .id_table = teles_ids, |
427 | .suspend = teles_suspend, | 394 | .suspend = teles_suspend, |