diff options
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/hardware/avm/avm_cs.c | 185 | ||||
-rw-r--r-- | drivers/isdn/hisax/avma1_cs.c | 182 | ||||
-rw-r--r-- | drivers/isdn/hisax/elsa_cs.c | 112 | ||||
-rw-r--r-- | drivers/isdn/hisax/sedlbauer_cs.c | 143 | ||||
-rw-r--r-- | drivers/isdn/hisax/teles_cs.c | 121 |
5 files changed, 250 insertions, 493 deletions
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 2a2b03ff096b..7bbfd85ab793 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c | |||
@@ -51,8 +51,8 @@ MODULE_LICENSE("GPL"); | |||
51 | handler. | 51 | handler. |
52 | */ | 52 | */ |
53 | 53 | ||
54 | static void avmcs_config(dev_link_t *link); | 54 | static int avmcs_config(struct pcmcia_device *link); |
55 | static void avmcs_release(dev_link_t *link); | 55 | static void avmcs_release(struct pcmcia_device *link); |
56 | 56 | ||
57 | /* | 57 | /* |
58 | The attach() and detach() entry points are used to create and destroy | 58 | The attach() and detach() entry points are used to create and destroy |
@@ -65,10 +65,10 @@ static void avmcs_detach(struct pcmcia_device *p_dev); | |||
65 | /* | 65 | /* |
66 | A linked list of "instances" of the skeleton device. Each actual | 66 | A linked list of "instances" of the skeleton device. Each actual |
67 | PCMCIA card corresponds to one device instance, and is described | 67 | PCMCIA card corresponds to one device instance, and is described |
68 | by one dev_link_t structure (defined in ds.h). | 68 | by one struct pcmcia_device structure (defined in ds.h). |
69 | 69 | ||
70 | You may not want to use a linked list for this -- for example, the | 70 | You may not want to use a linked list for this -- for example, the |
71 | memory card driver uses an array of dev_link_t pointers, where minor | 71 | memory card driver uses an array of struct pcmcia_device pointers, where minor |
72 | device numbers are used to derive the corresponding array index. | 72 | device numbers are used to derive the corresponding array index. |
73 | */ | 73 | */ |
74 | 74 | ||
@@ -78,7 +78,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev); | |||
78 | example, ethernet cards, modems). In other cases, there may be | 78 | example, ethernet cards, modems). In other cases, there may be |
79 | many actual or logical devices (SCSI adapters, memory cards with | 79 | many actual or logical devices (SCSI adapters, memory cards with |
80 | multiple partitions). The dev_node_t structures need to be kept | 80 | multiple partitions). The dev_node_t structures need to be kept |
81 | in a linked list starting at the 'dev' field of a dev_link_t | 81 | in a linked list starting at the 'dev' field of a struct pcmcia_device |
82 | structure. We allocate them in the card's private data structure, | 82 | structure. We allocate them in the card's private data structure, |
83 | because they generally can't be allocated dynamically. | 83 | because they generally can't be allocated dynamically. |
84 | */ | 84 | */ |
@@ -99,54 +99,38 @@ typedef struct local_info_t { | |||
99 | 99 | ||
100 | ======================================================================*/ | 100 | ======================================================================*/ |
101 | 101 | ||
102 | static int avmcs_attach(struct pcmcia_device *p_dev) | 102 | static int avmcs_probe(struct pcmcia_device *p_dev) |
103 | { | 103 | { |
104 | dev_link_t *link; | ||
105 | local_info_t *local; | 104 | local_info_t *local; |
106 | 105 | ||
107 | /* Initialize the dev_link_t structure */ | ||
108 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
109 | if (!link) | ||
110 | goto err; | ||
111 | memset(link, 0, sizeof(struct dev_link_t)); | ||
112 | |||
113 | /* The io structure describes IO port mapping */ | 106 | /* The io structure describes IO port mapping */ |
114 | link->io.NumPorts1 = 16; | 107 | p_dev->io.NumPorts1 = 16; |
115 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 108 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
116 | link->io.NumPorts2 = 0; | 109 | p_dev->io.NumPorts2 = 0; |
117 | 110 | ||
118 | /* Interrupt setup */ | 111 | /* Interrupt setup */ |
119 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 112 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
120 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | 113 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; |
114 | |||
115 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
121 | 116 | ||
122 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
123 | |||
124 | /* General socket configuration */ | 117 | /* General socket configuration */ |
125 | link->conf.Attributes = CONF_ENABLE_IRQ; | 118 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
126 | link->conf.Vcc = 50; | 119 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
127 | link->conf.IntType = INT_MEMORY_AND_IO; | 120 | p_dev->conf.ConfigIndex = 1; |
128 | link->conf.ConfigIndex = 1; | 121 | p_dev->conf.Present = PRESENT_OPTION; |
129 | link->conf.Present = PRESENT_OPTION; | ||
130 | 122 | ||
131 | /* Allocate space for private device-specific data */ | 123 | /* Allocate space for private device-specific data */ |
132 | local = kmalloc(sizeof(local_info_t), GFP_KERNEL); | 124 | local = kmalloc(sizeof(local_info_t), GFP_KERNEL); |
133 | if (!local) | 125 | if (!local) |
134 | goto err_kfree; | 126 | goto err; |
135 | memset(local, 0, sizeof(local_info_t)); | 127 | memset(local, 0, sizeof(local_info_t)); |
136 | link->priv = local; | 128 | p_dev->priv = local; |
137 | 129 | ||
138 | link->handle = p_dev; | 130 | return avmcs_config(p_dev); |
139 | p_dev->instance = link; | ||
140 | 131 | ||
141 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
142 | avmcs_config(link); | ||
143 | |||
144 | return 0; | ||
145 | |||
146 | err_kfree: | ||
147 | kfree(link); | ||
148 | err: | 132 | err: |
149 | return -EINVAL; | 133 | return -ENOMEM; |
150 | } /* avmcs_attach */ | 134 | } /* avmcs_attach */ |
151 | 135 | ||
152 | /*====================================================================== | 136 | /*====================================================================== |
@@ -158,15 +142,10 @@ static int avmcs_attach(struct pcmcia_device *p_dev) | |||
158 | 142 | ||
159 | ======================================================================*/ | 143 | ======================================================================*/ |
160 | 144 | ||
161 | static void avmcs_detach(struct pcmcia_device *p_dev) | 145 | static void avmcs_detach(struct pcmcia_device *link) |
162 | { | 146 | { |
163 | dev_link_t *link = dev_to_instance(p_dev); | ||
164 | |||
165 | if (link->state & DEV_CONFIG) | ||
166 | avmcs_release(link); | 147 | avmcs_release(link); |
167 | 148 | kfree(link->priv); | |
168 | kfree(link->priv); | ||
169 | kfree(link); | ||
170 | } /* avmcs_detach */ | 149 | } /* avmcs_detach */ |
171 | 150 | ||
172 | /*====================================================================== | 151 | /*====================================================================== |
@@ -177,7 +156,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev) | |||
177 | 156 | ||
178 | ======================================================================*/ | 157 | ======================================================================*/ |
179 | 158 | ||
180 | static int get_tuple(client_handle_t handle, tuple_t *tuple, | 159 | static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, |
181 | cisparse_t *parse) | 160 | cisparse_t *parse) |
182 | { | 161 | { |
183 | int i = pcmcia_get_tuple_data(handle, tuple); | 162 | int i = pcmcia_get_tuple_data(handle, tuple); |
@@ -185,7 +164,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, | |||
185 | return pcmcia_parse_tuple(handle, tuple, parse); | 164 | return pcmcia_parse_tuple(handle, tuple, parse); |
186 | } | 165 | } |
187 | 166 | ||
188 | static int first_tuple(client_handle_t handle, tuple_t *tuple, | 167 | static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, |
189 | cisparse_t *parse) | 168 | cisparse_t *parse) |
190 | { | 169 | { |
191 | int i = pcmcia_get_first_tuple(handle, tuple); | 170 | int i = pcmcia_get_first_tuple(handle, tuple); |
@@ -193,7 +172,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, | |||
193 | return get_tuple(handle, tuple, parse); | 172 | return get_tuple(handle, tuple, parse); |
194 | } | 173 | } |
195 | 174 | ||
196 | static int next_tuple(client_handle_t handle, tuple_t *tuple, | 175 | static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, |
197 | cisparse_t *parse) | 176 | cisparse_t *parse) |
198 | { | 177 | { |
199 | int i = pcmcia_get_next_tuple(handle, tuple); | 178 | int i = pcmcia_get_next_tuple(handle, tuple); |
@@ -201,9 +180,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, | |||
201 | return get_tuple(handle, tuple, parse); | 180 | return get_tuple(handle, tuple, parse); |
202 | } | 181 | } |
203 | 182 | ||
204 | static void avmcs_config(dev_link_t *link) | 183 | static int avmcs_config(struct pcmcia_device *link) |
205 | { | 184 | { |
206 | client_handle_t handle; | ||
207 | tuple_t tuple; | 185 | tuple_t tuple; |
208 | cisparse_t parse; | 186 | cisparse_t parse; |
209 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | 187 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; |
@@ -213,8 +191,7 @@ static void avmcs_config(dev_link_t *link) | |||
213 | char devname[128]; | 191 | char devname[128]; |
214 | int cardtype; | 192 | int cardtype; |
215 | int (*addcard)(unsigned int port, unsigned irq); | 193 | int (*addcard)(unsigned int port, unsigned irq); |
216 | 194 | ||
217 | handle = link->handle; | ||
218 | dev = link->priv; | 195 | dev = link->priv; |
219 | 196 | ||
220 | /* | 197 | /* |
@@ -223,25 +200,21 @@ static void avmcs_config(dev_link_t *link) | |||
223 | */ | 200 | */ |
224 | do { | 201 | do { |
225 | tuple.DesiredTuple = CISTPL_CONFIG; | 202 | tuple.DesiredTuple = CISTPL_CONFIG; |
226 | i = pcmcia_get_first_tuple(handle, &tuple); | 203 | i = pcmcia_get_first_tuple(link, &tuple); |
227 | if (i != CS_SUCCESS) break; | 204 | if (i != CS_SUCCESS) break; |
228 | tuple.TupleData = buf; | 205 | tuple.TupleData = buf; |
229 | tuple.TupleDataMax = 64; | 206 | tuple.TupleDataMax = 64; |
230 | tuple.TupleOffset = 0; | 207 | tuple.TupleOffset = 0; |
231 | i = pcmcia_get_tuple_data(handle, &tuple); | 208 | i = pcmcia_get_tuple_data(link, &tuple); |
232 | if (i != CS_SUCCESS) break; | 209 | if (i != CS_SUCCESS) break; |
233 | i = pcmcia_parse_tuple(handle, &tuple, &parse); | 210 | i = pcmcia_parse_tuple(link, &tuple, &parse); |
234 | if (i != CS_SUCCESS) break; | 211 | if (i != CS_SUCCESS) break; |
235 | link->conf.ConfigBase = parse.config.base; | 212 | link->conf.ConfigBase = parse.config.base; |
236 | } while (0); | 213 | } while (0); |
237 | if (i != CS_SUCCESS) { | 214 | if (i != CS_SUCCESS) { |
238 | cs_error(link->handle, ParseTuple, i); | 215 | cs_error(link, ParseTuple, i); |
239 | link->state &= ~DEV_CONFIG_PENDING; | 216 | return -ENODEV; |
240 | return; | ||
241 | } | 217 | } |
242 | |||
243 | /* Configure card */ | ||
244 | link->state |= DEV_CONFIG; | ||
245 | 218 | ||
246 | do { | 219 | do { |
247 | 220 | ||
@@ -252,7 +225,7 @@ static void avmcs_config(dev_link_t *link) | |||
252 | tuple.DesiredTuple = CISTPL_VERS_1; | 225 | tuple.DesiredTuple = CISTPL_VERS_1; |
253 | 226 | ||
254 | devname[0] = 0; | 227 | devname[0] = 0; |
255 | if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { | 228 | if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { |
256 | strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], | 229 | strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], |
257 | sizeof(devname)); | 230 | sizeof(devname)); |
258 | } | 231 | } |
@@ -263,7 +236,7 @@ static void avmcs_config(dev_link_t *link) | |||
263 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; | 236 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; |
264 | tuple.Attributes = 0; | 237 | tuple.Attributes = 0; |
265 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 238 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
266 | i = first_tuple(handle, &tuple, &parse); | 239 | i = first_tuple(link, &tuple, &parse); |
267 | while (i == CS_SUCCESS) { | 240 | while (i == CS_SUCCESS) { |
268 | if (cf->io.nwin > 0) { | 241 | if (cf->io.nwin > 0) { |
269 | link->conf.ConfigIndex = cf->index; | 242 | link->conf.ConfigIndex = cf->index; |
@@ -273,36 +246,36 @@ static void avmcs_config(dev_link_t *link) | |||
273 | printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", | 246 | printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", |
274 | link->io.BasePort1, | 247 | link->io.BasePort1, |
275 | link->io.BasePort1+link->io.NumPorts1-1); | 248 | link->io.BasePort1+link->io.NumPorts1-1); |
276 | i = pcmcia_request_io(link->handle, &link->io); | 249 | i = pcmcia_request_io(link, &link->io); |
277 | if (i == CS_SUCCESS) goto found_port; | 250 | if (i == CS_SUCCESS) goto found_port; |
278 | } | 251 | } |
279 | i = next_tuple(handle, &tuple, &parse); | 252 | i = next_tuple(link, &tuple, &parse); |
280 | } | 253 | } |
281 | 254 | ||
282 | found_port: | 255 | found_port: |
283 | if (i != CS_SUCCESS) { | 256 | if (i != CS_SUCCESS) { |
284 | cs_error(link->handle, RequestIO, i); | 257 | cs_error(link, RequestIO, i); |
285 | break; | 258 | break; |
286 | } | 259 | } |
287 | 260 | ||
288 | /* | 261 | /* |
289 | * allocate an interrupt line | 262 | * allocate an interrupt line |
290 | */ | 263 | */ |
291 | i = pcmcia_request_irq(link->handle, &link->irq); | 264 | i = pcmcia_request_irq(link, &link->irq); |
292 | if (i != CS_SUCCESS) { | 265 | if (i != CS_SUCCESS) { |
293 | cs_error(link->handle, RequestIRQ, i); | 266 | cs_error(link, RequestIRQ, i); |
294 | pcmcia_release_io(link->handle, &link->io); | 267 | /* undo */ |
268 | pcmcia_disable_device(link); | ||
295 | break; | 269 | break; |
296 | } | 270 | } |
297 | 271 | ||
298 | /* | 272 | /* |
299 | * configure the PCMCIA socket | 273 | * configure the PCMCIA socket |
300 | */ | 274 | */ |
301 | i = pcmcia_request_configuration(link->handle, &link->conf); | 275 | i = pcmcia_request_configuration(link, &link->conf); |
302 | if (i != CS_SUCCESS) { | 276 | if (i != CS_SUCCESS) { |
303 | cs_error(link->handle, RequestConfiguration, i); | 277 | cs_error(link, RequestConfiguration, i); |
304 | pcmcia_release_io(link->handle, &link->io); | 278 | pcmcia_disable_device(link); |
305 | pcmcia_release_irq(link->handle, &link->irq); | ||
306 | break; | 279 | break; |
307 | } | 280 | } |
308 | 281 | ||
@@ -331,13 +304,12 @@ found_port: | |||
331 | 304 | ||
332 | dev->node.major = 64; | 305 | dev->node.major = 64; |
333 | dev->node.minor = 0; | 306 | dev->node.minor = 0; |
334 | link->dev = &dev->node; | 307 | link->dev_node = &dev->node; |
335 | 308 | ||
336 | link->state &= ~DEV_CONFIG_PENDING; | ||
337 | /* If any step failed, release any partially configured state */ | 309 | /* If any step failed, release any partially configured state */ |
338 | if (i != 0) { | 310 | if (i != 0) { |
339 | avmcs_release(link); | 311 | avmcs_release(link); |
340 | return; | 312 | return -ENODEV; |
341 | } | 313 | } |
342 | 314 | ||
343 | 315 | ||
@@ -351,9 +323,10 @@ found_port: | |||
351 | printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n", | 323 | printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n", |
352 | dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ); | 324 | dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ); |
353 | avmcs_release(link); | 325 | avmcs_release(link); |
354 | return; | 326 | return -ENODEV; |
355 | } | 327 | } |
356 | dev->node.minor = i; | 328 | dev->node.minor = i; |
329 | return 0; | ||
357 | 330 | ||
358 | } /* avmcs_config */ | 331 | } /* avmcs_config */ |
359 | 332 | ||
@@ -365,56 +338,12 @@ found_port: | |||
365 | 338 | ||
366 | ======================================================================*/ | 339 | ======================================================================*/ |
367 | 340 | ||
368 | static void avmcs_release(dev_link_t *link) | 341 | static void avmcs_release(struct pcmcia_device *link) |
369 | { | 342 | { |
370 | b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); | 343 | b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); |
371 | 344 | pcmcia_disable_device(link); | |
372 | /* Unlink the device chain */ | ||
373 | link->dev = NULL; | ||
374 | |||
375 | /* Don't bother checking to see if these succeed or not */ | ||
376 | pcmcia_release_configuration(link->handle); | ||
377 | pcmcia_release_io(link->handle, &link->io); | ||
378 | pcmcia_release_irq(link->handle, &link->irq); | ||
379 | link->state &= ~DEV_CONFIG; | ||
380 | } /* avmcs_release */ | 345 | } /* avmcs_release */ |
381 | 346 | ||
382 | static int avmcs_suspend(struct pcmcia_device *dev) | ||
383 | { | ||
384 | dev_link_t *link = dev_to_instance(dev); | ||
385 | |||
386 | link->state |= DEV_SUSPEND; | ||
387 | if (link->state & DEV_CONFIG) | ||
388 | pcmcia_release_configuration(link->handle); | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static int avmcs_resume(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_request_configuration(link->handle, &link->conf); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | /*====================================================================== | ||
405 | |||
406 | The card status event handler. Mostly, this schedules other | ||
407 | stuff to run after an event is received. A CARD_REMOVAL event | ||
408 | also sets some flags to discourage the net drivers from trying | ||
409 | to talk to the card any more. | ||
410 | |||
411 | When a CARD_REMOVAL event is received, we immediately set a flag | ||
412 | to block future accesses to this device. All the functions that | ||
413 | actually access the device should check this flag to make sure | ||
414 | the card is still present. | ||
415 | |||
416 | ======================================================================*/ | ||
417 | |||
418 | 347 | ||
419 | static struct pcmcia_device_id avmcs_ids[] = { | 348 | static struct pcmcia_device_id avmcs_ids[] = { |
420 | PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), | 349 | PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), |
@@ -429,11 +358,9 @@ static struct pcmcia_driver avmcs_driver = { | |||
429 | .drv = { | 358 | .drv = { |
430 | .name = "avm_cs", | 359 | .name = "avm_cs", |
431 | }, | 360 | }, |
432 | .probe = avmcs_attach, | 361 | .probe = avmcs_probe, |
433 | .remove = avmcs_detach, | 362 | .remove = avmcs_detach, |
434 | .id_table = avmcs_ids, | 363 | .id_table = avmcs_ids, |
435 | .suspend= avmcs_suspend, | ||
436 | .resume = avmcs_resume, | ||
437 | }; | 364 | }; |
438 | 365 | ||
439 | static int __init avmcs_init(void) | 366 | static int __init avmcs_init(void) |
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) |
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, |
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 6f5213a18a8d..9bb18f3f7829 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -95,8 +95,8 @@ module_param(protocol, int, 0); | |||
95 | event handler. | 95 | event handler. |
96 | */ | 96 | */ |
97 | 97 | ||
98 | static void sedlbauer_config(dev_link_t *link); | 98 | static int sedlbauer_config(struct pcmcia_device *link); |
99 | static void sedlbauer_release(dev_link_t *link); | 99 | static void sedlbauer_release(struct pcmcia_device *link); |
100 | 100 | ||
101 | /* | 101 | /* |
102 | The attach() and detach() entry points are used to create and destroy | 102 | The attach() and detach() entry points are used to create and destroy |
@@ -119,7 +119,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev); | |||
119 | example, ethernet cards, modems). In other cases, there may be | 119 | example, ethernet cards, modems). In other cases, there may be |
120 | many actual or logical devices (SCSI adapters, memory cards with | 120 | many actual or logical devices (SCSI adapters, memory cards with |
121 | multiple partitions). The dev_node_t structures need to be kept | 121 | multiple partitions). The dev_node_t structures need to be kept |
122 | in a linked list starting at the 'dev' field of a dev_link_t | 122 | in a linked list starting at the 'dev' field of a struct pcmcia_device |
123 | structure. We allocate them in the card's private data structure, | 123 | structure. We allocate them in the card's private data structure, |
124 | because they generally shouldn't be allocated dynamically. | 124 | because they generally shouldn't be allocated dynamically. |
125 | 125 | ||
@@ -130,7 +130,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev); | |||
130 | */ | 130 | */ |
131 | 131 | ||
132 | typedef struct local_info_t { | 132 | typedef struct local_info_t { |
133 | dev_link_t link; | 133 | struct pcmcia_device *p_dev; |
134 | dev_node_t node; | 134 | dev_node_t node; |
135 | int stop; | 135 | int stop; |
136 | int cardnr; | 136 | int cardnr; |
@@ -148,11 +148,10 @@ typedef struct local_info_t { | |||
148 | 148 | ||
149 | ======================================================================*/ | 149 | ======================================================================*/ |
150 | 150 | ||
151 | static int sedlbauer_attach(struct pcmcia_device *p_dev) | 151 | static int sedlbauer_probe(struct pcmcia_device *link) |
152 | { | 152 | { |
153 | local_info_t *local; | 153 | local_info_t *local; |
154 | dev_link_t *link; | 154 | |
155 | |||
156 | DEBUG(0, "sedlbauer_attach()\n"); | 155 | DEBUG(0, "sedlbauer_attach()\n"); |
157 | 156 | ||
158 | /* Allocate space for private device-specific data */ | 157 | /* Allocate space for private device-specific data */ |
@@ -160,8 +159,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) | |||
160 | if (!local) return -ENOMEM; | 159 | if (!local) return -ENOMEM; |
161 | memset(local, 0, sizeof(local_info_t)); | 160 | memset(local, 0, sizeof(local_info_t)); |
162 | local->cardnr = -1; | 161 | local->cardnr = -1; |
163 | link = &local->link; link->priv = local; | 162 | |
164 | 163 | local->p_dev = link; | |
164 | link->priv = local; | ||
165 | |||
165 | /* Interrupt setup */ | 166 | /* Interrupt setup */ |
166 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 167 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
167 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 168 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
@@ -182,18 +183,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) | |||
182 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 183 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
183 | link->io.IOAddrLines = 3; | 184 | link->io.IOAddrLines = 3; |
184 | 185 | ||
185 | |||
186 | link->conf.Attributes = 0; | 186 | link->conf.Attributes = 0; |
187 | link->conf.Vcc = 50; | ||
188 | link->conf.IntType = INT_MEMORY_AND_IO; | 187 | link->conf.IntType = INT_MEMORY_AND_IO; |
189 | 188 | ||
190 | link->handle = p_dev; | 189 | return sedlbauer_config(link); |
191 | p_dev->instance = link; | ||
192 | |||
193 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
194 | sedlbauer_config(link); | ||
195 | |||
196 | return 0; | ||
197 | } /* sedlbauer_attach */ | 190 | } /* sedlbauer_attach */ |
198 | 191 | ||
199 | /*====================================================================== | 192 | /*====================================================================== |
@@ -205,19 +198,15 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) | |||
205 | 198 | ||
206 | ======================================================================*/ | 199 | ======================================================================*/ |
207 | 200 | ||
208 | static void sedlbauer_detach(struct pcmcia_device *p_dev) | 201 | static void sedlbauer_detach(struct pcmcia_device *link) |
209 | { | 202 | { |
210 | dev_link_t *link = dev_to_instance(p_dev); | 203 | DEBUG(0, "sedlbauer_detach(0x%p)\n", link); |
211 | |||
212 | DEBUG(0, "sedlbauer_detach(0x%p)\n", link); | ||
213 | 204 | ||
214 | if (link->state & DEV_CONFIG) { | 205 | ((local_info_t *)link->priv)->stop = 1; |
215 | ((local_info_t *)link->priv)->stop = 1; | 206 | sedlbauer_release(link); |
216 | sedlbauer_release(link); | ||
217 | } | ||
218 | 207 | ||
219 | /* This points to the parent local_info_t struct */ | 208 | /* This points to the parent local_info_t struct */ |
220 | kfree(link->priv); | 209 | kfree(link->priv); |
221 | } /* sedlbauer_detach */ | 210 | } /* sedlbauer_detach */ |
222 | 211 | ||
223 | /*====================================================================== | 212 | /*====================================================================== |
@@ -230,9 +219,8 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev) | |||
230 | #define CS_CHECK(fn, ret) \ | 219 | #define CS_CHECK(fn, ret) \ |
231 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 220 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
232 | 221 | ||
233 | static void sedlbauer_config(dev_link_t *link) | 222 | static int sedlbauer_config(struct pcmcia_device *link) |
234 | { | 223 | { |
235 | client_handle_t handle = link->handle; | ||
236 | local_info_t *dev = link->priv; | 224 | local_info_t *dev = link->priv; |
237 | tuple_t tuple; | 225 | tuple_t tuple; |
238 | cisparse_t parse; | 226 | cisparse_t parse; |
@@ -254,18 +242,13 @@ static void sedlbauer_config(dev_link_t *link) | |||
254 | tuple.TupleData = buf; | 242 | tuple.TupleData = buf; |
255 | tuple.TupleDataMax = sizeof(buf); | 243 | tuple.TupleDataMax = sizeof(buf); |
256 | tuple.TupleOffset = 0; | 244 | tuple.TupleOffset = 0; |
257 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 245 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
258 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 246 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
259 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 247 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
260 | link->conf.ConfigBase = parse.config.base; | 248 | link->conf.ConfigBase = parse.config.base; |
261 | link->conf.Present = parse.config.rmask[0]; | 249 | link->conf.Present = parse.config.rmask[0]; |
262 | |||
263 | /* Configure card */ | ||
264 | link->state |= DEV_CONFIG; | ||
265 | 250 | ||
266 | /* Look up the current Vcc */ | 251 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); |
267 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); | ||
268 | link->conf.Vcc = conf.Vcc; | ||
269 | 252 | ||
270 | /* | 253 | /* |
271 | In this loop, we scan the CIS for configuration table entries, | 254 | In this loop, we scan the CIS for configuration table entries, |
@@ -280,12 +263,12 @@ static void sedlbauer_config(dev_link_t *link) | |||
280 | will only use the CIS to fill in implementation-defined details. | 263 | will only use the CIS to fill in implementation-defined details. |
281 | */ | 264 | */ |
282 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 265 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
283 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 266 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
284 | while (1) { | 267 | while (1) { |
285 | cistpl_cftable_entry_t dflt = { 0 }; | 268 | cistpl_cftable_entry_t dflt = { 0 }; |
286 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 269 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
287 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 270 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
288 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0) | 271 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) |
289 | goto next_entry; | 272 | goto next_entry; |
290 | 273 | ||
291 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; | 274 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; |
@@ -309,10 +292,10 @@ static void sedlbauer_config(dev_link_t *link) | |||
309 | } | 292 | } |
310 | 293 | ||
311 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | 294 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) |
312 | link->conf.Vpp1 = link->conf.Vpp2 = | 295 | link->conf.Vpp = |
313 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | 296 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; |
314 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) | 297 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) |
315 | link->conf.Vpp1 = link->conf.Vpp2 = | 298 | link->conf.Vpp = |
316 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; | 299 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; |
317 | 300 | ||
318 | /* Do we need to allocate an interrupt? */ | 301 | /* Do we need to allocate an interrupt? */ |
@@ -339,13 +322,13 @@ static void sedlbauer_config(dev_link_t *link) | |||
339 | link->io.NumPorts2 = io->win[1].len; | 322 | link->io.NumPorts2 = io->win[1].len; |
340 | } | 323 | } |
341 | /* This reserves IO space but doesn't actually enable it */ | 324 | /* This reserves IO space but doesn't actually enable it */ |
342 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 325 | if (pcmcia_request_io(link, &link->io) != 0) |
343 | goto next_entry; | 326 | goto next_entry; |
344 | } | 327 | } |
345 | 328 | ||
346 | /* | 329 | /* |
347 | Now set up a common memory window, if needed. There is room | 330 | Now set up a common memory window, if needed. There is room |
348 | in the dev_link_t structure for one memory window handle, | 331 | in the struct pcmcia_device structure for one memory window handle, |
349 | but if the base addresses need to be saved, or if multiple | 332 | but if the base addresses need to be saved, or if multiple |
350 | windows are needed, the info should go in the private data | 333 | windows are needed, the info should go in the private data |
351 | structure for this device. | 334 | structure for this device. |
@@ -366,7 +349,7 @@ static void sedlbauer_config(dev_link_t *link) | |||
366 | req.Size = 0x1000; | 349 | req.Size = 0x1000; |
367 | */ | 350 | */ |
368 | req.AccessSpeed = 0; | 351 | req.AccessSpeed = 0; |
369 | if (pcmcia_request_window(&link->handle, &req, &link->win) != 0) | 352 | if (pcmcia_request_window(&link, &req, &link->win) != 0) |
370 | goto next_entry; | 353 | goto next_entry; |
371 | map.Page = 0; map.CardOffset = mem->win[0].card_addr; | 354 | map.Page = 0; map.CardOffset = mem->win[0].card_addr; |
372 | if (pcmcia_map_mem_page(link->win, &map) != 0) | 355 | if (pcmcia_map_mem_page(link->win, &map) != 0) |
@@ -374,29 +357,25 @@ static void sedlbauer_config(dev_link_t *link) | |||
374 | } | 357 | } |
375 | /* If we got this far, we're cool! */ | 358 | /* If we got this far, we're cool! */ |
376 | break; | 359 | break; |
377 | 360 | ||
378 | next_entry: | 361 | next_entry: |
379 | /* new in dummy.cs 2001/01/28 MN | 362 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
380 | if (link->io.NumPorts1) | ||
381 | pcmcia_release_io(link->handle, &link->io); | ||
382 | */ | ||
383 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | ||
384 | } | 363 | } |
385 | 364 | ||
386 | /* | 365 | /* |
387 | Allocate an interrupt line. Note that this does not assign a | 366 | Allocate an interrupt line. Note that this does not assign a |
388 | handler to the interrupt, unless the 'Handler' member of the | 367 | handler to the interrupt, unless the 'Handler' member of the |
389 | irq structure is initialized. | 368 | irq structure is initialized. |
390 | */ | 369 | */ |
391 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 370 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
392 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 371 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
393 | 372 | ||
394 | /* | 373 | /* |
395 | This actually configures the PCMCIA socket -- setting up | 374 | This actually configures the PCMCIA socket -- setting up |
396 | the I/O windows and the interrupt mapping, and putting the | 375 | the I/O windows and the interrupt mapping, and putting the |
397 | card and host interface into "Memory and IO" mode. | 376 | card and host interface into "Memory and IO" mode. |
398 | */ | 377 | */ |
399 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 378 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
400 | 379 | ||
401 | /* | 380 | /* |
402 | At this point, the dev_node_t structure(s) need to be | 381 | At this point, the dev_node_t structure(s) need to be |
@@ -404,14 +383,13 @@ static void sedlbauer_config(dev_link_t *link) | |||
404 | */ | 383 | */ |
405 | sprintf(dev->node.dev_name, "sedlbauer"); | 384 | sprintf(dev->node.dev_name, "sedlbauer"); |
406 | dev->node.major = dev->node.minor = 0; | 385 | dev->node.major = dev->node.minor = 0; |
407 | link->dev = &dev->node; | 386 | link->dev_node = &dev->node; |
408 | 387 | ||
409 | /* Finally, report what we've done */ | 388 | /* Finally, report what we've done */ |
410 | printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", | 389 | printk(KERN_INFO "%s: index 0x%02x:", |
411 | dev->node.dev_name, link->conf.ConfigIndex, | 390 | dev->node.dev_name, link->conf.ConfigIndex); |
412 | link->conf.Vcc/10, link->conf.Vcc%10); | 391 | if (link->conf.Vpp) |
413 | if (link->conf.Vpp1) | 392 | printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); |
414 | printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); | ||
415 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 393 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
416 | printk(", irq %d", link->irq.AssignedIRQ); | 394 | printk(", irq %d", link->irq.AssignedIRQ); |
417 | if (link->io.NumPorts1) | 395 | if (link->io.NumPorts1) |
@@ -424,8 +402,6 @@ static void sedlbauer_config(dev_link_t *link) | |||
424 | printk(", mem 0x%06lx-0x%06lx", req.Base, | 402 | printk(", mem 0x%06lx-0x%06lx", req.Base, |
425 | req.Base+req.Size-1); | 403 | req.Base+req.Size-1); |
426 | printk("\n"); | 404 | printk("\n"); |
427 | |||
428 | link->state &= ~DEV_CONFIG_PENDING; | ||
429 | 405 | ||
430 | icard.para[0] = link->irq.AssignedIRQ; | 406 | icard.para[0] = link->irq.AssignedIRQ; |
431 | icard.para[1] = link->io.BasePort1; | 407 | icard.para[1] = link->io.BasePort1; |
@@ -437,14 +413,16 @@ static void sedlbauer_config(dev_link_t *link) | |||
437 | printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", | 413 | printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", |
438 | last_ret, link->io.BasePort1); | 414 | last_ret, link->io.BasePort1); |
439 | sedlbauer_release(link); | 415 | sedlbauer_release(link); |
416 | return -ENODEV; | ||
440 | } else | 417 | } else |
441 | ((local_info_t*)link->priv)->cardnr = last_ret; | 418 | ((local_info_t*)link->priv)->cardnr = last_ret; |
442 | 419 | ||
443 | return; | 420 | return 0; |
444 | 421 | ||
445 | cs_failed: | 422 | cs_failed: |
446 | cs_error(link->handle, last_fn, last_ret); | 423 | cs_error(link, last_fn, last_ret); |
447 | sedlbauer_release(link); | 424 | sedlbauer_release(link); |
425 | return -ENODEV; | ||
448 | 426 | ||
449 | } /* sedlbauer_config */ | 427 | } /* sedlbauer_config */ |
450 | 428 | ||
@@ -456,7 +434,7 @@ cs_failed: | |||
456 | 434 | ||
457 | ======================================================================*/ | 435 | ======================================================================*/ |
458 | 436 | ||
459 | static void sedlbauer_release(dev_link_t *link) | 437 | static void sedlbauer_release(struct pcmcia_device *link) |
460 | { | 438 | { |
461 | local_info_t *local = link->priv; | 439 | local_info_t *local = link->priv; |
462 | DEBUG(0, "sedlbauer_release(0x%p)\n", link); | 440 | DEBUG(0, "sedlbauer_release(0x%p)\n", link); |
@@ -467,46 +445,23 @@ static void sedlbauer_release(dev_link_t *link) | |||
467 | HiSax_closecard(local->cardnr); | 445 | HiSax_closecard(local->cardnr); |
468 | } | 446 | } |
469 | } | 447 | } |
470 | /* Unlink the device chain */ | ||
471 | link->dev = NULL; | ||
472 | 448 | ||
473 | /* | 449 | pcmcia_disable_device(link); |
474 | In a normal driver, additional code may be needed to release | ||
475 | other kernel data structures associated with this device. | ||
476 | */ | ||
477 | |||
478 | /* Don't bother checking to see if these succeed or not */ | ||
479 | if (link->win) | ||
480 | pcmcia_release_window(link->win); | ||
481 | pcmcia_release_configuration(link->handle); | ||
482 | if (link->io.NumPorts1) | ||
483 | pcmcia_release_io(link->handle, &link->io); | ||
484 | if (link->irq.AssignedIRQ) | ||
485 | pcmcia_release_irq(link->handle, &link->irq); | ||
486 | link->state &= ~DEV_CONFIG; | ||
487 | } /* sedlbauer_release */ | 450 | } /* sedlbauer_release */ |
488 | 451 | ||
489 | static int sedlbauer_suspend(struct pcmcia_device *p_dev) | 452 | static int sedlbauer_suspend(struct pcmcia_device *link) |
490 | { | 453 | { |
491 | dev_link_t *link = dev_to_instance(p_dev); | ||
492 | local_info_t *dev = link->priv; | 454 | local_info_t *dev = link->priv; |
493 | 455 | ||
494 | link->state |= DEV_SUSPEND; | ||
495 | dev->stop = 1; | 456 | dev->stop = 1; |
496 | if (link->state & DEV_CONFIG) | ||
497 | pcmcia_release_configuration(link->handle); | ||
498 | 457 | ||
499 | return 0; | 458 | return 0; |
500 | } | 459 | } |
501 | 460 | ||
502 | static int sedlbauer_resume(struct pcmcia_device *p_dev) | 461 | static int sedlbauer_resume(struct pcmcia_device *link) |
503 | { | 462 | { |
504 | dev_link_t *link = dev_to_instance(p_dev); | ||
505 | local_info_t *dev = link->priv; | 463 | local_info_t *dev = link->priv; |
506 | 464 | ||
507 | link->state &= ~DEV_SUSPEND; | ||
508 | if (link->state & DEV_CONFIG) | ||
509 | pcmcia_request_configuration(link->handle, &link->conf); | ||
510 | dev->stop = 0; | 465 | dev->stop = 0; |
511 | 466 | ||
512 | return 0; | 467 | return 0; |
@@ -530,7 +485,7 @@ static struct pcmcia_driver sedlbauer_driver = { | |||
530 | .drv = { | 485 | .drv = { |
531 | .name = "sedlbauer_cs", | 486 | .name = "sedlbauer_cs", |
532 | }, | 487 | }, |
533 | .probe = sedlbauer_attach, | 488 | .probe = sedlbauer_probe, |
534 | .remove = sedlbauer_detach, | 489 | .remove = sedlbauer_detach, |
535 | .id_table = sedlbauer_ids, | 490 | .id_table = sedlbauer_ids, |
536 | .suspend = sedlbauer_suspend, | 491 | .suspend = sedlbauer_suspend, |
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, |