diff options
Diffstat (limited to 'drivers/net/pcmcia/smc91c92_cs.c')
-rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 195 |
1 files changed, 73 insertions, 122 deletions
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index c7cca842e5ee..0122415dfeef 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -102,10 +102,6 @@ static const char *version = | |||
102 | currently have room for another Tx packet. */ | 102 | currently have room for another Tx packet. */ |
103 | #define MEMORY_WAIT_TIME 8 | 103 | #define MEMORY_WAIT_TIME 8 |
104 | 104 | ||
105 | static dev_info_t dev_info = "smc91c92_cs"; | ||
106 | |||
107 | static dev_link_t *dev_list; | ||
108 | |||
109 | struct smc_private { | 105 | struct smc_private { |
110 | dev_link_t link; | 106 | dev_link_t link; |
111 | spinlock_t lock; | 107 | spinlock_t lock; |
@@ -281,12 +277,9 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, | |||
281 | 277 | ||
282 | /*====================================================================*/ | 278 | /*====================================================================*/ |
283 | 279 | ||
284 | static dev_link_t *smc91c92_attach(void); | 280 | static void smc91c92_detach(struct pcmcia_device *p_dev); |
285 | static void smc91c92_detach(dev_link_t *); | ||
286 | static void smc91c92_config(dev_link_t *link); | 281 | static void smc91c92_config(dev_link_t *link); |
287 | static void smc91c92_release(dev_link_t *link); | 282 | static void smc91c92_release(dev_link_t *link); |
288 | static int smc91c92_event(event_t event, int priority, | ||
289 | event_callback_args_t *args); | ||
290 | 283 | ||
291 | static int smc_open(struct net_device *dev); | 284 | static int smc_open(struct net_device *dev); |
292 | static int smc_close(struct net_device *dev); | 285 | static int smc_close(struct net_device *dev); |
@@ -315,20 +308,18 @@ static struct ethtool_ops ethtool_ops; | |||
315 | 308 | ||
316 | ======================================================================*/ | 309 | ======================================================================*/ |
317 | 310 | ||
318 | static dev_link_t *smc91c92_attach(void) | 311 | static int smc91c92_attach(struct pcmcia_device *p_dev) |
319 | { | 312 | { |
320 | client_reg_t client_reg; | ||
321 | struct smc_private *smc; | 313 | struct smc_private *smc; |
322 | dev_link_t *link; | 314 | dev_link_t *link; |
323 | struct net_device *dev; | 315 | struct net_device *dev; |
324 | int ret; | ||
325 | 316 | ||
326 | DEBUG(0, "smc91c92_attach()\n"); | 317 | DEBUG(0, "smc91c92_attach()\n"); |
327 | 318 | ||
328 | /* Create new ethernet device */ | 319 | /* Create new ethernet device */ |
329 | dev = alloc_etherdev(sizeof(struct smc_private)); | 320 | dev = alloc_etherdev(sizeof(struct smc_private)); |
330 | if (!dev) | 321 | if (!dev) |
331 | return NULL; | 322 | return -ENOMEM; |
332 | smc = netdev_priv(dev); | 323 | smc = netdev_priv(dev); |
333 | link = &smc->link; | 324 | link = &smc->link; |
334 | link->priv = dev; | 325 | link->priv = dev; |
@@ -366,20 +357,13 @@ static dev_link_t *smc91c92_attach(void) | |||
366 | smc->mii_if.phy_id_mask = 0x1f; | 357 | smc->mii_if.phy_id_mask = 0x1f; |
367 | smc->mii_if.reg_num_mask = 0x1f; | 358 | smc->mii_if.reg_num_mask = 0x1f; |
368 | 359 | ||
369 | /* Register with Card Services */ | 360 | link->handle = p_dev; |
370 | link->next = dev_list; | 361 | p_dev->instance = link; |
371 | dev_list = link; | 362 | |
372 | client_reg.dev_info = &dev_info; | 363 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
373 | client_reg.Version = 0x0210; | 364 | smc91c92_config(link); |
374 | client_reg.event_callback_args.client_data = link; | ||
375 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
376 | if (ret != 0) { | ||
377 | cs_error(link->handle, RegisterClient, ret); | ||
378 | smc91c92_detach(link); | ||
379 | return NULL; | ||
380 | } | ||
381 | 365 | ||
382 | return link; | 366 | return 0; |
383 | } /* smc91c92_attach */ | 367 | } /* smc91c92_attach */ |
384 | 368 | ||
385 | /*====================================================================== | 369 | /*====================================================================== |
@@ -391,30 +375,19 @@ static dev_link_t *smc91c92_attach(void) | |||
391 | 375 | ||
392 | ======================================================================*/ | 376 | ======================================================================*/ |
393 | 377 | ||
394 | static void smc91c92_detach(dev_link_t *link) | 378 | static void smc91c92_detach(struct pcmcia_device *p_dev) |
395 | { | 379 | { |
380 | dev_link_t *link = dev_to_instance(p_dev); | ||
396 | struct net_device *dev = link->priv; | 381 | struct net_device *dev = link->priv; |
397 | dev_link_t **linkp; | ||
398 | 382 | ||
399 | DEBUG(0, "smc91c92_detach(0x%p)\n", link); | 383 | DEBUG(0, "smc91c92_detach(0x%p)\n", link); |
400 | 384 | ||
401 | /* Locate device structure */ | ||
402 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
403 | if (*linkp == link) break; | ||
404 | if (*linkp == NULL) | ||
405 | return; | ||
406 | |||
407 | if (link->dev) | 385 | if (link->dev) |
408 | unregister_netdev(dev); | 386 | unregister_netdev(dev); |
409 | 387 | ||
410 | if (link->state & DEV_CONFIG) | 388 | if (link->state & DEV_CONFIG) |
411 | smc91c92_release(link); | 389 | smc91c92_release(link); |
412 | 390 | ||
413 | if (link->handle) | ||
414 | pcmcia_deregister_client(link->handle); | ||
415 | |||
416 | /* Unlink device structure, free bits */ | ||
417 | *linkp = link->next; | ||
418 | free_netdev(dev); | 391 | free_netdev(dev); |
419 | } /* smc91c92_detach */ | 392 | } /* smc91c92_detach */ |
420 | 393 | ||
@@ -895,6 +868,62 @@ free_cfg_mem: | |||
895 | return rc; | 868 | return rc; |
896 | } | 869 | } |
897 | 870 | ||
871 | static int smc91c92_suspend(struct pcmcia_device *p_dev) | ||
872 | { | ||
873 | dev_link_t *link = dev_to_instance(p_dev); | ||
874 | struct net_device *dev = link->priv; | ||
875 | |||
876 | link->state |= DEV_SUSPEND; | ||
877 | if (link->state & DEV_CONFIG) { | ||
878 | if (link->open) | ||
879 | netif_device_detach(dev); | ||
880 | pcmcia_release_configuration(link->handle); | ||
881 | } | ||
882 | |||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | static int smc91c92_resume(struct pcmcia_device *p_dev) | ||
887 | { | ||
888 | dev_link_t *link = dev_to_instance(p_dev); | ||
889 | struct net_device *dev = link->priv; | ||
890 | struct smc_private *smc = netdev_priv(dev); | ||
891 | int i; | ||
892 | |||
893 | link->state &= ~DEV_SUSPEND; | ||
894 | if (link->state & DEV_CONFIG) { | ||
895 | if ((smc->manfid == MANFID_MEGAHERTZ) && | ||
896 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | ||
897 | mhz_3288_power(link); | ||
898 | pcmcia_request_configuration(link->handle, &link->conf); | ||
899 | if (smc->manfid == MANFID_MOTOROLA) | ||
900 | mot_config(link); | ||
901 | if ((smc->manfid == MANFID_OSITECH) && | ||
902 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
903 | /* Power up the card and enable interrupts */ | ||
904 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); | ||
905 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); | ||
906 | } | ||
907 | if (((smc->manfid == MANFID_OSITECH) && | ||
908 | (smc->cardid == PRODID_OSITECH_SEVEN)) || | ||
909 | ((smc->manfid == MANFID_PSION) && | ||
910 | (smc->cardid == PRODID_PSION_NET100))) { | ||
911 | /* Download the Seven of Diamonds firmware */ | ||
912 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
913 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
914 | udelay(50); | ||
915 | } | ||
916 | } | ||
917 | if (link->open) { | ||
918 | smc_reset(dev); | ||
919 | netif_device_attach(dev); | ||
920 | } | ||
921 | } | ||
922 | |||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | |||
898 | /*====================================================================== | 927 | /*====================================================================== |
899 | 928 | ||
900 | This verifies that the chip is some SMC91cXX variant, and returns | 929 | This verifies that the chip is some SMC91cXX variant, and returns |
@@ -935,14 +964,12 @@ static int check_sig(dev_link_t *link) | |||
935 | } | 964 | } |
936 | 965 | ||
937 | if (width) { | 966 | if (width) { |
938 | event_callback_args_t args; | ||
939 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); | 967 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); |
940 | args.client_data = link; | 968 | smc91c92_suspend(link->handle); |
941 | smc91c92_event(CS_EVENT_RESET_PHYSICAL, 0, &args); | ||
942 | pcmcia_release_io(link->handle, &link->io); | 969 | pcmcia_release_io(link->handle, &link->io); |
943 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 970 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
944 | pcmcia_request_io(link->handle, &link->io); | 971 | pcmcia_request_io(link->handle, &link->io); |
945 | smc91c92_event(CS_EVENT_CARD_RESET, 0, &args); | 972 | smc91c92_resume(link->handle); |
946 | return check_sig(link); | 973 | return check_sig(link); |
947 | } | 974 | } |
948 | return -ENODEV; | 975 | return -ENODEV; |
@@ -1172,82 +1199,6 @@ static void smc91c92_release(dev_link_t *link) | |||
1172 | 1199 | ||
1173 | /*====================================================================== | 1200 | /*====================================================================== |
1174 | 1201 | ||
1175 | The card status event handler. Mostly, this schedules other | ||
1176 | stuff to run after an event is received. A CARD_REMOVAL event | ||
1177 | also sets some flags to discourage the net drivers from trying | ||
1178 | to talk to the card any more. | ||
1179 | |||
1180 | ======================================================================*/ | ||
1181 | |||
1182 | static int smc91c92_event(event_t event, int priority, | ||
1183 | event_callback_args_t *args) | ||
1184 | { | ||
1185 | dev_link_t *link = args->client_data; | ||
1186 | struct net_device *dev = link->priv; | ||
1187 | struct smc_private *smc = netdev_priv(dev); | ||
1188 | int i; | ||
1189 | |||
1190 | DEBUG(1, "smc91c92_event(0x%06x)\n", event); | ||
1191 | |||
1192 | switch (event) { | ||
1193 | case CS_EVENT_CARD_REMOVAL: | ||
1194 | link->state &= ~DEV_PRESENT; | ||
1195 | if (link->state & DEV_CONFIG) | ||
1196 | netif_device_detach(dev); | ||
1197 | break; | ||
1198 | case CS_EVENT_CARD_INSERTION: | ||
1199 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1200 | smc91c92_config(link); | ||
1201 | break; | ||
1202 | case CS_EVENT_PM_SUSPEND: | ||
1203 | link->state |= DEV_SUSPEND; | ||
1204 | /* Fall through... */ | ||
1205 | case CS_EVENT_RESET_PHYSICAL: | ||
1206 | if (link->state & DEV_CONFIG) { | ||
1207 | if (link->open) | ||
1208 | netif_device_detach(dev); | ||
1209 | pcmcia_release_configuration(link->handle); | ||
1210 | } | ||
1211 | break; | ||
1212 | case CS_EVENT_PM_RESUME: | ||
1213 | link->state &= ~DEV_SUSPEND; | ||
1214 | /* Fall through... */ | ||
1215 | case CS_EVENT_CARD_RESET: | ||
1216 | if (link->state & DEV_CONFIG) { | ||
1217 | if ((smc->manfid == MANFID_MEGAHERTZ) && | ||
1218 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | ||
1219 | mhz_3288_power(link); | ||
1220 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1221 | if (smc->manfid == MANFID_MOTOROLA) | ||
1222 | mot_config(link); | ||
1223 | if ((smc->manfid == MANFID_OSITECH) && | ||
1224 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
1225 | /* Power up the card and enable interrupts */ | ||
1226 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); | ||
1227 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); | ||
1228 | } | ||
1229 | if (((smc->manfid == MANFID_OSITECH) && | ||
1230 | (smc->cardid == PRODID_OSITECH_SEVEN)) || | ||
1231 | ((smc->manfid == MANFID_PSION) && | ||
1232 | (smc->cardid == PRODID_PSION_NET100))) { | ||
1233 | /* Download the Seven of Diamonds firmware */ | ||
1234 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
1235 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
1236 | udelay(50); | ||
1237 | } | ||
1238 | } | ||
1239 | if (link->open) { | ||
1240 | smc_reset(dev); | ||
1241 | netif_device_attach(dev); | ||
1242 | } | ||
1243 | } | ||
1244 | break; | ||
1245 | } | ||
1246 | return 0; | ||
1247 | } /* smc91c92_event */ | ||
1248 | |||
1249 | /*====================================================================== | ||
1250 | |||
1251 | MII interface support for SMC91cXX based cards | 1202 | MII interface support for SMC91cXX based cards |
1252 | ======================================================================*/ | 1203 | ======================================================================*/ |
1253 | 1204 | ||
@@ -2360,10 +2311,11 @@ static struct pcmcia_driver smc91c92_cs_driver = { | |||
2360 | .drv = { | 2311 | .drv = { |
2361 | .name = "smc91c92_cs", | 2312 | .name = "smc91c92_cs", |
2362 | }, | 2313 | }, |
2363 | .attach = smc91c92_attach, | 2314 | .probe = smc91c92_attach, |
2364 | .event = smc91c92_event, | 2315 | .remove = smc91c92_detach, |
2365 | .detach = smc91c92_detach, | ||
2366 | .id_table = smc91c92_ids, | 2316 | .id_table = smc91c92_ids, |
2317 | .suspend = smc91c92_suspend, | ||
2318 | .resume = smc91c92_resume, | ||
2367 | }; | 2319 | }; |
2368 | 2320 | ||
2369 | static int __init init_smc91c92_cs(void) | 2321 | static int __init init_smc91c92_cs(void) |
@@ -2374,7 +2326,6 @@ static int __init init_smc91c92_cs(void) | |||
2374 | static void __exit exit_smc91c92_cs(void) | 2326 | static void __exit exit_smc91c92_cs(void) |
2375 | { | 2327 | { |
2376 | pcmcia_unregister_driver(&smc91c92_cs_driver); | 2328 | pcmcia_unregister_driver(&smc91c92_cs_driver); |
2377 | BUG_ON(dev_list != NULL); | ||
2378 | } | 2329 | } |
2379 | 2330 | ||
2380 | module_init(init_smc91c92_cs); | 2331 | module_init(init_smc91c92_cs); |