diff options
Diffstat (limited to 'drivers/isdn/hisax/avma1_cs.c')
-rw-r--r-- | drivers/isdn/hisax/avma1_cs.c | 182 |
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 | ||
70 | static void avma1cs_config(dev_link_t *link); | 70 | static int avma1cs_config(struct pcmcia_device *link); |
71 | static void avma1cs_release(dev_link_t *link); | 71 | static 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 | ||
119 | static int avma1cs_attach(struct pcmcia_device *p_dev) | 119 | static 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 | ||
179 | static void avma1cs_detach(struct pcmcia_device *p_dev) | 164 | static 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 | ||
200 | static int get_tuple(client_handle_t handle, tuple_t *tuple, | 179 | static 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 | ||
208 | static int first_tuple(client_handle_t handle, tuple_t *tuple, | 187 | static 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 | ||
216 | static int next_tuple(client_handle_t handle, tuple_t *tuple, | 195 | static 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 | ||
224 | static void avma1cs_config(dev_link_t *link) | 203 | static 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 | ||
304 | found_port: | 277 | found_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 | ||
374 | static void avma1cs_release(dev_link_t *link) | 347 | static 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 | ||
393 | static 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 | |||
404 | static 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 | ||
416 | static struct pcmcia_device_id avma1cs_ids[] = { | 360 | static 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 | ||
437 | static int __init init_avma1_cs(void) | 379 | static int __init init_avma1_cs(void) |