diff options
Diffstat (limited to 'drivers/net/wireless/atmel_cs.c')
-rw-r--r-- | drivers/net/wireless/atmel_cs.c | 162 |
1 files changed, 56 insertions, 106 deletions
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index d6f4a5a3e55a..26bf1127524d 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
@@ -91,8 +91,8 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); | |||
91 | event handler. | 91 | event handler. |
92 | */ | 92 | */ |
93 | 93 | ||
94 | static void atmel_config(dev_link_t *link); | 94 | static int atmel_config(struct pcmcia_device *link); |
95 | static void atmel_release(dev_link_t *link); | 95 | static void atmel_release(struct pcmcia_device *link); |
96 | 96 | ||
97 | /* | 97 | /* |
98 | The attach() and detach() entry points are used to create and destroy | 98 | The attach() and detach() entry points are used to create and destroy |
@@ -112,10 +112,10 @@ static void atmel_detach(struct pcmcia_device *p_dev); | |||
112 | /* | 112 | /* |
113 | A linked list of "instances" of the atmelnet device. Each actual | 113 | A linked list of "instances" of the atmelnet device. Each actual |
114 | PCMCIA card corresponds to one device instance, and is described | 114 | PCMCIA card corresponds to one device instance, and is described |
115 | by one dev_link_t structure (defined in ds.h). | 115 | by one struct pcmcia_device structure (defined in ds.h). |
116 | 116 | ||
117 | You may not want to use a linked list for this -- for example, the | 117 | You may not want to use a linked list for this -- for example, the |
118 | memory card driver uses an array of dev_link_t pointers, where minor | 118 | memory card driver uses an array of struct pcmcia_device pointers, where minor |
119 | device numbers are used to derive the corresponding array index. | 119 | device numbers are used to derive the corresponding array index. |
120 | */ | 120 | */ |
121 | 121 | ||
@@ -125,7 +125,7 @@ static void atmel_detach(struct pcmcia_device *p_dev); | |||
125 | example, ethernet cards, modems). In other cases, there may be | 125 | example, ethernet cards, modems). In other cases, there may be |
126 | many actual or logical devices (SCSI adapters, memory cards with | 126 | many actual or logical devices (SCSI adapters, memory cards with |
127 | multiple partitions). The dev_node_t structures need to be kept | 127 | multiple partitions). The dev_node_t structures need to be kept |
128 | in a linked list starting at the 'dev' field of a dev_link_t | 128 | in a linked list starting at the 'dev' field of a struct pcmcia_device |
129 | structure. We allocate them in the card's private data structure, | 129 | structure. We allocate them in the card's private data structure, |
130 | because they generally shouldn't be allocated dynamically. | 130 | because they generally shouldn't be allocated dynamically. |
131 | 131 | ||
@@ -152,24 +152,16 @@ typedef struct local_info_t { | |||
152 | 152 | ||
153 | ======================================================================*/ | 153 | ======================================================================*/ |
154 | 154 | ||
155 | static int atmel_attach(struct pcmcia_device *p_dev) | 155 | static int atmel_probe(struct pcmcia_device *p_dev) |
156 | { | 156 | { |
157 | dev_link_t *link; | ||
158 | local_info_t *local; | 157 | local_info_t *local; |
159 | 158 | ||
160 | DEBUG(0, "atmel_attach()\n"); | 159 | DEBUG(0, "atmel_attach()\n"); |
161 | 160 | ||
162 | /* Initialize the dev_link_t structure */ | ||
163 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
164 | if (!link) { | ||
165 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | |||
169 | /* Interrupt setup */ | 161 | /* Interrupt setup */ |
170 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 162 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
171 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 163 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
172 | link->irq.Handler = NULL; | 164 | p_dev->irq.Handler = NULL; |
173 | 165 | ||
174 | /* | 166 | /* |
175 | General socket configuration defaults can go here. In this | 167 | General socket configuration defaults can go here. In this |
@@ -178,26 +170,18 @@ static int atmel_attach(struct pcmcia_device *p_dev) | |||
178 | and attributes of IO windows) are fixed by the nature of the | 170 | and attributes of IO windows) are fixed by the nature of the |
179 | device, and can be hard-wired here. | 171 | device, and can be hard-wired here. |
180 | */ | 172 | */ |
181 | link->conf.Attributes = 0; | 173 | p_dev->conf.Attributes = 0; |
182 | link->conf.Vcc = 50; | 174 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
183 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
184 | 175 | ||
185 | /* Allocate space for private device-specific data */ | 176 | /* Allocate space for private device-specific data */ |
186 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 177 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
187 | if (!local) { | 178 | if (!local) { |
188 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); | 179 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); |
189 | kfree (link); | ||
190 | return -ENOMEM; | 180 | return -ENOMEM; |
191 | } | 181 | } |
192 | link->priv = local; | 182 | p_dev->priv = local; |
193 | 183 | ||
194 | link->handle = p_dev; | 184 | return atmel_config(p_dev); |
195 | p_dev->instance = link; | ||
196 | |||
197 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
198 | atmel_config(link); | ||
199 | |||
200 | return 0; | ||
201 | } /* atmel_attach */ | 185 | } /* atmel_attach */ |
202 | 186 | ||
203 | /*====================================================================== | 187 | /*====================================================================== |
@@ -209,17 +193,13 @@ static int atmel_attach(struct pcmcia_device *p_dev) | |||
209 | 193 | ||
210 | ======================================================================*/ | 194 | ======================================================================*/ |
211 | 195 | ||
212 | static void atmel_detach(struct pcmcia_device *p_dev) | 196 | static void atmel_detach(struct pcmcia_device *link) |
213 | { | 197 | { |
214 | dev_link_t *link = dev_to_instance(p_dev); | ||
215 | |||
216 | DEBUG(0, "atmel_detach(0x%p)\n", link); | 198 | DEBUG(0, "atmel_detach(0x%p)\n", link); |
217 | 199 | ||
218 | if (link->state & DEV_CONFIG) | 200 | atmel_release(link); |
219 | atmel_release(link); | ||
220 | 201 | ||
221 | kfree(link->priv); | 202 | kfree(link->priv); |
222 | kfree(link); | ||
223 | } | 203 | } |
224 | 204 | ||
225 | /*====================================================================== | 205 | /*====================================================================== |
@@ -236,19 +216,17 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
236 | /* Call-back function to interrogate PCMCIA-specific information | 216 | /* Call-back function to interrogate PCMCIA-specific information |
237 | about the current existance of the card */ | 217 | about the current existance of the card */ |
238 | static int card_present(void *arg) | 218 | static int card_present(void *arg) |
239 | { | 219 | { |
240 | dev_link_t *link = (dev_link_t *)arg; | 220 | struct pcmcia_device *link = (struct pcmcia_device *)arg; |
241 | if (link->state & DEV_SUSPEND) | 221 | |
242 | return 0; | 222 | if (pcmcia_dev_present(link)) |
243 | else if (link->state & DEV_PRESENT) | ||
244 | return 1; | 223 | return 1; |
245 | 224 | ||
246 | return 0; | 225 | return 0; |
247 | } | 226 | } |
248 | 227 | ||
249 | static void atmel_config(dev_link_t *link) | 228 | static int atmel_config(struct pcmcia_device *link) |
250 | { | 229 | { |
251 | client_handle_t handle; | ||
252 | tuple_t tuple; | 230 | tuple_t tuple; |
253 | cisparse_t parse; | 231 | cisparse_t parse; |
254 | local_info_t *dev; | 232 | local_info_t *dev; |
@@ -256,9 +234,8 @@ static void atmel_config(dev_link_t *link) | |||
256 | u_char buf[64]; | 234 | u_char buf[64]; |
257 | struct pcmcia_device_id *did; | 235 | struct pcmcia_device_id *did; |
258 | 236 | ||
259 | handle = link->handle; | ||
260 | dev = link->priv; | 237 | dev = link->priv; |
261 | did = handle_to_dev(handle).driver_data; | 238 | did = handle_to_dev(link).driver_data; |
262 | 239 | ||
263 | DEBUG(0, "atmel_config(0x%p)\n", link); | 240 | DEBUG(0, "atmel_config(0x%p)\n", link); |
264 | 241 | ||
@@ -272,15 +249,12 @@ static void atmel_config(dev_link_t *link) | |||
272 | registers. | 249 | registers. |
273 | */ | 250 | */ |
274 | tuple.DesiredTuple = CISTPL_CONFIG; | 251 | tuple.DesiredTuple = CISTPL_CONFIG; |
275 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 252 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
276 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 253 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
277 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 254 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
278 | link->conf.ConfigBase = parse.config.base; | 255 | link->conf.ConfigBase = parse.config.base; |
279 | link->conf.Present = parse.config.rmask[0]; | 256 | link->conf.Present = parse.config.rmask[0]; |
280 | 257 | ||
281 | /* Configure card */ | ||
282 | link->state |= DEV_CONFIG; | ||
283 | |||
284 | /* | 258 | /* |
285 | In this loop, we scan the CIS for configuration table entries, | 259 | In this loop, we scan the CIS for configuration table entries, |
286 | each of which describes a valid card configuration, including | 260 | each of which describes a valid card configuration, including |
@@ -294,12 +268,12 @@ static void atmel_config(dev_link_t *link) | |||
294 | will only use the CIS to fill in implementation-defined details. | 268 | will only use the CIS to fill in implementation-defined details. |
295 | */ | 269 | */ |
296 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 270 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
297 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 271 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
298 | while (1) { | 272 | while (1) { |
299 | cistpl_cftable_entry_t dflt = { 0 }; | 273 | cistpl_cftable_entry_t dflt = { 0 }; |
300 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 274 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
301 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 275 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
302 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0) | 276 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) |
303 | goto next_entry; | 277 | goto next_entry; |
304 | 278 | ||
305 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; | 279 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; |
@@ -314,16 +288,11 @@ static void atmel_config(dev_link_t *link) | |||
314 | 288 | ||
315 | /* Use power settings for Vcc and Vpp if present */ | 289 | /* Use power settings for Vcc and Vpp if present */ |
316 | /* Note that the CIS values need to be rescaled */ | 290 | /* Note that the CIS values need to be rescaled */ |
317 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) | ||
318 | link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; | ||
319 | else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) | ||
320 | link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; | ||
321 | |||
322 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | 291 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) |
323 | link->conf.Vpp1 = link->conf.Vpp2 = | 292 | link->conf.Vpp = |
324 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | 293 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; |
325 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) | 294 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) |
326 | link->conf.Vpp1 = link->conf.Vpp2 = | 295 | link->conf.Vpp = |
327 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; | 296 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; |
328 | 297 | ||
329 | /* Do we need to allocate an interrupt? */ | 298 | /* Do we need to allocate an interrupt? */ |
@@ -349,14 +318,14 @@ static void atmel_config(dev_link_t *link) | |||
349 | } | 318 | } |
350 | 319 | ||
351 | /* This reserves IO space but doesn't actually enable it */ | 320 | /* This reserves IO space but doesn't actually enable it */ |
352 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 321 | if (pcmcia_request_io(link, &link->io) != 0) |
353 | goto next_entry; | 322 | goto next_entry; |
354 | 323 | ||
355 | /* If we got this far, we're cool! */ | 324 | /* If we got this far, we're cool! */ |
356 | break; | 325 | break; |
357 | 326 | ||
358 | next_entry: | 327 | next_entry: |
359 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | 328 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
360 | } | 329 | } |
361 | 330 | ||
362 | /* | 331 | /* |
@@ -365,14 +334,14 @@ static void atmel_config(dev_link_t *link) | |||
365 | irq structure is initialized. | 334 | irq structure is initialized. |
366 | */ | 335 | */ |
367 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 336 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
368 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 337 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
369 | 338 | ||
370 | /* | 339 | /* |
371 | This actually configures the PCMCIA socket -- setting up | 340 | This actually configures the PCMCIA socket -- setting up |
372 | the I/O windows and the interrupt mapping, and putting the | 341 | the I/O windows and the interrupt mapping, and putting the |
373 | card and host interface into "Memory and IO" mode. | 342 | card and host interface into "Memory and IO" mode. |
374 | */ | 343 | */ |
375 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 344 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
376 | 345 | ||
377 | if (link->irq.AssignedIRQ == 0) { | 346 | if (link->irq.AssignedIRQ == 0) { |
378 | printk(KERN_ALERT | 347 | printk(KERN_ALERT |
@@ -384,7 +353,7 @@ static void atmel_config(dev_link_t *link) | |||
384 | init_atmel_card(link->irq.AssignedIRQ, | 353 | init_atmel_card(link->irq.AssignedIRQ, |
385 | link->io.BasePort1, | 354 | link->io.BasePort1, |
386 | did ? did->driver_info : ATMEL_FW_TYPE_NONE, | 355 | did ? did->driver_info : ATMEL_FW_TYPE_NONE, |
387 | &handle_to_dev(handle), | 356 | &handle_to_dev(link), |
388 | card_present, | 357 | card_present, |
389 | link); | 358 | link); |
390 | if (!((local_info_t*)link->priv)->eth_dev) | 359 | if (!((local_info_t*)link->priv)->eth_dev) |
@@ -393,18 +362,18 @@ static void atmel_config(dev_link_t *link) | |||
393 | 362 | ||
394 | /* | 363 | /* |
395 | At this point, the dev_node_t structure(s) need to be | 364 | At this point, the dev_node_t structure(s) need to be |
396 | initialized and arranged in a linked list at link->dev. | 365 | initialized and arranged in a linked list at link->dev_node. |
397 | */ | 366 | */ |
398 | strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); | 367 | strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); |
399 | dev->node.major = dev->node.minor = 0; | 368 | dev->node.major = dev->node.minor = 0; |
400 | link->dev = &dev->node; | 369 | link->dev_node = &dev->node; |
401 | 370 | ||
402 | link->state &= ~DEV_CONFIG_PENDING; | 371 | return 0; |
403 | return; | 372 | |
404 | |||
405 | cs_failed: | 373 | cs_failed: |
406 | cs_error(link->handle, last_fn, last_ret); | 374 | cs_error(link, last_fn, last_ret); |
407 | atmel_release(link); | 375 | atmel_release(link); |
376 | return -ENODEV; | ||
408 | } | 377 | } |
409 | 378 | ||
410 | /*====================================================================== | 379 | /*====================================================================== |
@@ -415,53 +384,34 @@ static void atmel_config(dev_link_t *link) | |||
415 | 384 | ||
416 | ======================================================================*/ | 385 | ======================================================================*/ |
417 | 386 | ||
418 | static void atmel_release(dev_link_t *link) | 387 | static void atmel_release(struct pcmcia_device *link) |
419 | { | 388 | { |
420 | struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; | 389 | struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; |
421 | 390 | ||
422 | DEBUG(0, "atmel_release(0x%p)\n", link); | 391 | DEBUG(0, "atmel_release(0x%p)\n", link); |
423 | 392 | ||
424 | /* Unlink the device chain */ | 393 | if (dev) |
425 | link->dev = NULL; | ||
426 | |||
427 | if (dev) | ||
428 | stop_atmel_card(dev); | 394 | stop_atmel_card(dev); |
429 | ((local_info_t*)link->priv)->eth_dev = NULL; | 395 | ((local_info_t*)link->priv)->eth_dev = NULL; |
430 | 396 | ||
431 | /* Don't bother checking to see if these succeed or not */ | 397 | pcmcia_disable_device(link); |
432 | pcmcia_release_configuration(link->handle); | ||
433 | if (link->io.NumPorts1) | ||
434 | pcmcia_release_io(link->handle, &link->io); | ||
435 | if (link->irq.AssignedIRQ) | ||
436 | pcmcia_release_irq(link->handle, &link->irq); | ||
437 | link->state &= ~DEV_CONFIG; | ||
438 | } | 398 | } |
439 | 399 | ||
440 | static int atmel_suspend(struct pcmcia_device *dev) | 400 | static int atmel_suspend(struct pcmcia_device *link) |
441 | { | 401 | { |
442 | dev_link_t *link = dev_to_instance(dev); | ||
443 | local_info_t *local = link->priv; | 402 | local_info_t *local = link->priv; |
444 | 403 | ||
445 | link->state |= DEV_SUSPEND; | 404 | netif_device_detach(local->eth_dev); |
446 | if (link->state & DEV_CONFIG) { | ||
447 | netif_device_detach(local->eth_dev); | ||
448 | pcmcia_release_configuration(link->handle); | ||
449 | } | ||
450 | 405 | ||
451 | return 0; | 406 | return 0; |
452 | } | 407 | } |
453 | 408 | ||
454 | static int atmel_resume(struct pcmcia_device *dev) | 409 | static int atmel_resume(struct pcmcia_device *link) |
455 | { | 410 | { |
456 | dev_link_t *link = dev_to_instance(dev); | ||
457 | local_info_t *local = link->priv; | 411 | local_info_t *local = link->priv; |
458 | 412 | ||
459 | link->state &= ~DEV_SUSPEND; | 413 | atmel_open(local->eth_dev); |
460 | if (link->state & DEV_CONFIG) { | 414 | netif_device_attach(local->eth_dev); |
461 | pcmcia_request_configuration(link->handle, &link->conf); | ||
462 | atmel_open(local->eth_dev); | ||
463 | netif_device_attach(local->eth_dev); | ||
464 | } | ||
465 | 415 | ||
466 | return 0; | 416 | return 0; |
467 | } | 417 | } |
@@ -515,7 +465,7 @@ static struct pcmcia_driver atmel_driver = { | |||
515 | .drv = { | 465 | .drv = { |
516 | .name = "atmel_cs", | 466 | .name = "atmel_cs", |
517 | }, | 467 | }, |
518 | .probe = atmel_attach, | 468 | .probe = atmel_probe, |
519 | .remove = atmel_detach, | 469 | .remove = atmel_detach, |
520 | .id_table = atmel_ids, | 470 | .id_table = atmel_ids, |
521 | .suspend = atmel_suspend, | 471 | .suspend = atmel_suspend, |