aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pcmcia/smc91c92_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/pcmcia/smc91c92_cs.c')
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c195
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
105static dev_info_t dev_info = "smc91c92_cs";
106
107static dev_link_t *dev_list;
108
109struct smc_private { 105struct 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
284static dev_link_t *smc91c92_attach(void); 280static void smc91c92_detach(struct pcmcia_device *p_dev);
285static void smc91c92_detach(dev_link_t *);
286static void smc91c92_config(dev_link_t *link); 281static void smc91c92_config(dev_link_t *link);
287static void smc91c92_release(dev_link_t *link); 282static void smc91c92_release(dev_link_t *link);
288static int smc91c92_event(event_t event, int priority,
289 event_callback_args_t *args);
290 283
291static int smc_open(struct net_device *dev); 284static int smc_open(struct net_device *dev);
292static int smc_close(struct net_device *dev); 285static int smc_close(struct net_device *dev);
@@ -315,20 +308,18 @@ static struct ethtool_ops ethtool_ops;
315 308
316======================================================================*/ 309======================================================================*/
317 310
318static dev_link_t *smc91c92_attach(void) 311static 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
394static void smc91c92_detach(dev_link_t *link) 378static 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
871static 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
886static 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
1182static 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
2369static int __init init_smc91c92_cs(void) 2321static int __init init_smc91c92_cs(void)
@@ -2374,7 +2326,6 @@ static int __init init_smc91c92_cs(void)
2374static void __exit exit_smc91c92_cs(void) 2326static 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
2380module_init(init_smc91c92_cs); 2331module_init(init_smc91c92_cs);