1/* 2 * Aironet 4500 Pcmcia driver 3 * 4 * Elmer Joandi, Januar 1999 5 * Copyright Elmer Joandi, all rights restricted 6 * 7 * 8 * Revision 0.1 ,started 30.12.1998 9 * 10 * 11 */ 12 13#define DRV_NAME "aironet4500_cs" 14#define DRV_VERSION "0.1" 15 16static const char *awc_version = 17DRV_NAME ".c v" DRV_VERSION " 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n"; 18 19 20#include <linux/module.h> 21#include <linux/init.h> 22#include <linux/kernel.h> 23#include <linux/sched.h> 24#include <linux/ptrace.h> 25#include <linux/slab.h> 26#include <linux/string.h> 27#include <linux/timer.h> 28#include <linux/interrupt.h> 29#include <linux/in.h> 30#include <linux/ethtool.h> 31 32#include <asm/uaccess.h> 33#include <asm/io.h> 34#include <asm/system.h> 35#include <asm/bitops.h> 36 37#include <linux/netdevice.h> 38#include <linux/etherdevice.h> 39#include <linux/skbuff.h> 40#include <linux/if_arp.h> 41#include <linux/ioport.h> 42 43 44#include <pcmcia/version.h> 45#include <pcmcia/cs_types.h> 46#include <pcmcia/cs.h> 47#include <pcmcia/cistpl.h> 48#include <pcmcia/cisreg.h> 49#include <pcmcia/ciscode.h> 50#if LINUX_VERSION_CODE < 0x20300 51#ifdef MODULE 52#include <pcmcia/k_compat.h> 53#endif 54#endif 55#include <pcmcia/ds.h> 56 57#include "../aironet4500.h" 58 59 60static u_int irq_mask = 0x5eF8; 61static int awc_ports[] = {0x140,0x100,0xc0, 0x80 }; 62#if LINUX_VERSION_CODE > 0x20100 63MODULE_PARM(irq_mask, "i"); 64 65#endif 66 67 68#define RUN_AT(x) (jiffies+(x)) 69 70#ifdef PCMCIA_DEBUG 71static int pc_debug = PCMCIA_DEBUG; 72MODULE_PARM(pc_debug, "i"); 73#define PC_DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) 74static char *version = 75"aironet4500_cs.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n"; 76#else 77#define PC_DEBUG(n, args...) 78#endif 79 80/* Index of functions. */ 81 82static dev_info_t dev_info = "aironet4500_cs"; 83 84static dev_link_t *awc_attach(void); 85static void awc_detach(dev_link_t *); 86static void awc_release(u_long arg); 87static int awc_event(event_t event, int priority, 88 event_callback_args_t *args); 89 90static dev_link_t *dev_list; 91 92static void cs_error(client_handle_t handle, int func, int ret) 93{ 94#if CS_RELEASE_CODE < 0x2911 95 CardServices(ReportError, dev_info, (void *)func, (void *)ret); 96#else 97 error_info_t err = { func, ret }; 98 CardServices(ReportError, handle, &err); 99#endif 100} 101 102#define CFG_CHECK(fn, args...) if (CardServices(fn, args) != 0) goto next_entry 103 104static void flush_stale_links(void) 105{ 106 dev_link_t *link, *next; 107 for (link = dev_list; link; link = next) { 108 next = link->next; 109 if (link->state & DEV_STALE_LINK) 110 awc_detach(link); 111 } 112} 113 114 115/* 116 We never need to do anything when a awc device is "initialized" 117 by the net software, because we only register already-found cards. 118*/ 119 120static int awc_pcmcia_init(struct net_device *dev) 121{ 122 return awc_init(dev); 123 124} 125 126static int awc_pcmcia_open(struct net_device *dev) 127{ 128 dev_link_t *link; 129 int status; 130 131 for (link = dev_list; link; link = link->next) 132 if (link->priv == dev) break; 133 if (!DEV_OK(link)) 134 return -ENODEV; 135 136 status = awc_open(dev); 137 138 if (!status ) 139 link->open++; 140 141 return status; 142} 143 144static int awc_pcmcia_close(struct net_device *dev) 145{ 146// int ioaddr = dev->base_addr; 147 dev_link_t *link; 148 int ret; 149 150 for (link = dev_list; link; link = link->next) 151 if (link->priv == dev) break; 152 if (link == NULL) 153 return -ENODEV; 154 155 PC_DEBUG(2, "%s: closing device.\n", dev->name); 156 157 link->open--; 158 ret = awc_close(dev); 159 160 if (link->state & DEV_STALE_CONFIG) { 161 link->release.expires = RUN_AT( HZ/20 ); 162 link->state |= DEV_RELEASE_PENDING; 163 add_timer(&link->release); 164 } 165 return ret; 166} 167 168static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) 169{ 170 u32 ethcmd; 171 172 /* dev_ioctl() in ../../net/core/dev.c has already checked 173 capable(CAP_NET_ADMIN), so don't bother with that here. */ 174 175 if (get_user(ethcmd, (u32 *)useraddr)) 176 return -EFAULT; 177 178 switch (ethcmd) { 179 180 case ETHTOOL_GDRVINFO: { 181 struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; 182 strcpy (info.driver, DRV_NAME); 183 strcpy (info.version, DRV_VERSION); 184 sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr); 185 if (copy_to_user (useraddr, &info, sizeof (info))) 186 return -EFAULT; 187 return 0; 188 } 189 190#ifdef PCMCIA_DEBUG 191 /* get message-level */ 192 case ETHTOOL_GMSGLVL: { 193 struct ethtool_value edata = {ETHTOOL_GMSGLVL}; 194 edata.data = pc_debug; 195 if (copy_to_user(useraddr, &edata, sizeof(edata))) 196 return -EFAULT; 197 return 0; 198 } 199 /* set message-level */ 200 case ETHTOOL_SMSGLVL: { 201 struct ethtool_value edata; 202 if (copy_from_user(&edata, useraddr, sizeof(edata))) 203 return -EFAULT; 204 pc_debug = edata.data; 205 return 0; 206 } 207#endif 208 209 default: 210 break; 211 } 212 213 return -EOPNOTSUPP; 214} 215 216static int awc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 217{ 218 switch (cmd) { 219 case SIOCETHTOOL: 220 return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); 221 222 default: 223 return -EOPNOTSUPP; 224 } 225 return 0; 226} 227 228/* 229 awc_attach() creates an "instance" of the driver, allocating 230 local data structures for one device. The device is registered 231 with Card Services. 232*/ 233 234static dev_link_t *awc_attach(void) 235{ 236 client_reg_t client_reg; 237 dev_link_t *link = NULL; 238 struct net_device *dev = NULL; 239 int ret; 240 241 PC_DEBUG(0, "awc_attach()\n"); 242 flush_stale_links(); 243 244 /* Create the PC card device object. */ 245 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); 246 if (!link) 247 return NULL; 248 memset(link, 0, sizeof(struct dev_link_t)); 249 250 link->dev = kmalloc(sizeof(struct dev_node_t), GFP_KERNEL); 251 if (!link->dev) { 252 kfree(link); 253 return NULL; 254 } 255 256 memset(link->dev, 0, sizeof(struct dev_node_t)); 257 258 link->release.function = &awc_release; 259 link->release.data = (u_long)link; 260// link->io.NumPorts1 = 32; 261 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; 262// link->io.IOAddrLines = 5; 263 link->irq.Attributes = IRQ_HANDLE_PRESENT ; // |IRQ_TYPE_EXCLUSIVE ; 264 link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; 265 link->irq.IRQInfo2 = irq_mask; 266 link->irq.Handler = &awc_interrupt; 267 link->conf.Attributes = CONF_ENABLE_IRQ; 268 link->conf.Vcc = 50; 269 link->conf.IntType = INT_MEMORY_AND_IO; 270 link->conf.ConfigIndex = 1; 271 link->conf.Present = PRESENT_OPTION; 272 273 /* Create the network device object. */ 274 275 dev = kmalloc(sizeof(struct net_device ), GFP_KERNEL); 276// dev = init_etherdev(0, sizeof(struct awc_private) ); 277 if (!dev ) { 278 printk(KERN_CRIT "out of mem on dev alloc \n"); 279 kfree(link->dev); 280 kfree(link); 281 return NULL; 282 }; 283 memset(dev,0,sizeof(struct net_device)); 284 dev->priv = kmalloc(sizeof(struct awc_private), GFP_KERNEL); 285 if (!dev->priv ) {printk(KERN_CRIT "out of mem on dev priv alloc \n"); return NULL;}; 286 memset(dev->priv,0,sizeof(struct awc_private)); 287 288// link->dev->minor = dev->minor; 289// link->dev->major = dev->major; 290 291 /* The 4500-specific entries in the device structure. */ 292 293// dev->tx_queue_len = tx_queue_len; 294 295 dev->hard_start_xmit = &awc_start_xmit; 296// dev->set_config = &awc_config_misiganes,aga mitte awc_config; 297 dev->get_stats = &awc_get_stats; 298// dev->set_multicast_list = &awc_set_multicast_list; 299 dev->do_ioctl = &awc_ioctl; 300 301 strcpy(dev->name, ((struct awc_private *)dev->priv)->node.dev_name); 302 303 ether_setup(dev); 304 305 dev->init = &awc_pcmcia_init; 306 dev->open = &awc_pcmcia_open; 307 dev->stop = &awc_pcmcia_close; 308 309 link->priv = dev; 310#if CS_RELEASE_CODE > 0x2911 311 link->irq.Instance = dev; 312#endif 313 314 /* Register with Card Services */ 315 link->next = dev_list; 316 dev_list = link; 317 318 319 client_reg.dev_info = &dev_info; 320 client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; 321 client_reg.EventMask = 322 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | 323 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | 324 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; 325 client_reg.event_handler = &awc_event; 326 client_reg.Version = 0x0210; 327 client_reg.event_callback_args.client_data = link; 328 ret = CardServices(RegisterClient, &link->handle, &client_reg); 329 if (ret != 0) { 330 cs_error(link->handle, RegisterClient, ret); 331 awc_detach(link); 332 return NULL; 333 } 334 335 return link; 336} /* awc_attach */ 337 338/* 339 340 This deletes a driver "instance". The device is de-registered 341 with Card Services. If it has been released, all local data 342 structures are freed. Otherwise, the structures will be freed 343 when the device is released. 344 345*/ 346 347static void awc_detach(dev_link_t *link) 348{ 349 dev_link_t **linkp; 350 unsigned long flags; 351 int i=0; 352 353 DEBUG(0, "awc_detach(0x%p)\n", link); 354 355 /* Locate device structure */ 356 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) 357 if (*linkp == link) break; 358 if (*linkp == NULL) 359 return; 360 361 save_flags(flags); 362 cli(); 363 if (link->state & DEV_RELEASE_PENDING) { 364 del_timer(&link->release); 365 link->state &= ~DEV_RELEASE_PENDING; 366 } 367 restore_flags(flags); 368 369 if (link->state & DEV_CONFIG) { 370 awc_release((u_long)link); 371 if (link->state & DEV_STALE_CONFIG) { 372 link->state |= DEV_STALE_LINK; 373 return; 374 } 375 } 376 377 if (link->handle) 378 CardServices(DeregisterClient, link->handle); 379 380 /* Unlink device structure, free bits */ 381 *linkp = link->next; 382 383 i=0; 384 while ( i < MAX_AWCS) { 385 if (!aironet4500_devices[i]) 386 {i++; continue;} 387 if (aironet4500_devices[i] == link->priv){ 388 if (awc_proc_unset_fun) 389 awc_proc_unset_fun(i); 390 391 aironet4500_devices[i]=0; 392 } 393 i++; 394 } 395 396 if (link->priv) { 397 //struct net_device *dev = link->priv; 398 // dam dam damn mif (dev->priv) 399 // kfree(dev->priv); 400 kfree(link->priv); 401 } 402 kfree(link->dev); 403 kfree(link); 404 405} /* awc_detach */ 406 407/* 408 409 awc_pcmcia_config() is scheduled to run after a CARD_INSERTION event 410 is received, to configure the PCMCIA socket, and to make the 411 ethernet device available to the system. 412 413*/ 414 415#define CS_CHECK(fn, args...) \ 416while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed 417 418static void awc_pcmcia_config(dev_link_t *link) 419{ 420 client_handle_t handle; 421 struct net_device *dev; 422 struct awc_private *lp; 423 tuple_t tuple; 424 int ii; 425 cisparse_t parse; 426 u_short buf[64]; 427 int last_fn, last_ret, i = 0; 428// int ioaddr; 429 u16 *phys_addr; 430 int retval; 431 432 handle = link->handle; 433 dev = link->priv; 434 phys_addr = (u16 *)dev->dev_addr; 435 436 PC_DEBUG(0, "awc_pcmcia_config(0x%p)\n", link); 437 438 tuple.Attributes = 0; 439 tuple.DesiredTuple = CISTPL_CONFIG; 440 CS_CHECK(GetFirstTuple, handle, &tuple); 441 tuple.TupleData = (cisdata_t *)buf; 442 tuple.TupleDataMax = 64; 443 tuple.TupleOffset = 0; 444 CS_CHECK(GetTupleData, handle, &tuple); 445 CS_CHECK(ParseTuple, handle, &tuple, &parse); 446 link->conf.ConfigBase = parse.config.base; 447 link->conf.Present = parse.config.rmask[0]; 448 449 450 /* Configure card */ 451 link->state |= DEV_CONFIG; 452 453 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 454 CS_CHECK(GetFirstTuple, handle, &tuple); 455 456 while (1) { 457 cistpl_cftable_entry_t dflt = { 0 }; 458 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 459 CFG_CHECK(GetTupleData, handle, &tuple); 460 CFG_CHECK(ParseTuple, handle, &tuple, &parse); 461 462 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; 463 if (cfg->index == 0) goto next_entry; 464 link->conf.ConfigIndex = cfg->index; 465 466 /* Use power settings for Vcc and Vpp if present */ 467 /* Note that the CIS values need to be rescaled */ 468 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) 469 link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; 470 else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) 471 link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; 472 473 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) 474 link->conf.Vpp1 = link->conf.Vpp2 = 475 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; 476 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) 477 link->conf.Vpp1 = link->conf.Vpp2 = 478 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; 479 480 /* Do we need to allocate an interrupt? */ 481 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) 482 link->conf.Attributes |= CONF_ENABLE_IRQ; 483 484 /* IO window settings */ 485 link->io.NumPorts1 = link->io.NumPorts2 = 0; 486 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { 487 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; 488 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 489 if (!(io->flags & CISTPL_IO_8BIT)) 490 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; 491 if (!(io->flags & CISTPL_IO_16BIT)) { 492 493 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 494 printk(KERN_CRIT "8-bit IO not supported on this aironet 4500 driver \n"); 495 } 496 link->io.BasePort1 = io->win[0].base; 497 498 link->io.NumPorts1 = io->win[0].len; 499 if (io->nwin > 1) { 500 link->io.Attributes2 = link->io.Attributes1; 501 link->io.BasePort2 = io->win[1].base; 502 link->io.NumPorts2 = io->win[1].len; 503 } 504 } 505 ii = 0; 506 last_fn = RequestIO; 507 while ((last_ret = CardServices(RequestIO, link->handle, &link->io)) ){ 508 509 if (ii > 4) 510 goto cs_failed; 511 link->io.BasePort1 = awc_ports[ii]; 512 ii++; 513 }; 514 515 516 break; 517 518 next_entry: 519 if (CardServices(GetNextTuple, handle, &tuple)) 520 break; 521 } 522 523 if (link->conf.Attributes & CONF_ENABLE_IRQ){ 524 525 ii = 0; last_fn = RequestIRQ; 526 while ((last_ret = CardServices(RequestIRQ, link->handle, &link->irq)) ){ 527 528 ii++; 529 while (!(irq_mask & (1 << ii) ) && ii < 15) 530 ii++; 531 link->irq.IRQInfo2 = 1 << ii; 532 533 if(ii > 15) 534 goto cs_failed; 535 printk("trying irq %d , mask %x \n",ii, link->irq.IRQInfo2); 536 537 }; 538 } 539 540 CS_CHECK(RequestConfiguration, link->handle, &link->conf); 541 542 543 dev->irq = link->irq.AssignedIRQ; 544 dev->base_addr = link->io.BasePort1; 545 546 547 awc_private_init( dev); 548 549 550 551 retval = register_netdev(dev); 552 if (retval != 0) { 553 printk(KERN_NOTICE "awc_cs: register_netdev() failed for dev %x retval %x\n",(unsigned int)dev,retval); 554 goto failed; 555 } 556 557 if(awc_pcmcia_init(dev)) goto failed; 558 559 i=0; 560 while (aironet4500_devices[i] && i < MAX_AWCS-1) i++; 561 if (!aironet4500_devices[i]){ 562 aironet4500_devices[i]=dev; 563 if (awc_proc_set_fun) 564 awc_proc_set_fun(i); 565 } 566 567 568 link->state &= ~DEV_CONFIG_PENDING; 569 570 lp = (struct awc_private *)dev->priv; 571 572 DEBUG(1,"pcmcia config complete on port %x \n",(unsigned int)dev->base_addr); 573 574 return; 575 576cs_failed: 577 cs_error(link->handle, last_fn, last_ret); 578 link->dev=NULL; 579failed: 580 581 awc_release((u_long)link); 582 return; 583 584} /* awc_pcmcia_config */ 585 586/* 587 After a card is removed, awc_release() will unregister the net 588 device, and release the PCMCIA configuration. If the device is 589 still open, this will be postponed until it is closed. 590 591*/ 592 593static void awc_release(u_long arg) 594{ 595 dev_link_t *link = (dev_link_t *)arg; 596 struct net_device *dev = link->priv; 597 598 DEBUG(0, "awc_release(0x%p)\n", link); 599 600 if (link->open) { 601 DEBUG(1, "awc_cs: release postponed, '%s' still open\n", 602 link->dev->dev_name); 603 link->state |= DEV_STALE_CONFIG; 604 return; 605 } 606 607 CardServices(ReleaseConfiguration, link->handle); 608 CardServices(ReleaseIO, link->handle, &link->io); 609 CardServices(ReleaseIRQ, link->handle, &link->irq); 610 611 CardServices(ReleaseWindow, link->win); 612 if (link->dev) 613 unregister_netdev(dev); 614 // link->dev = NULL; 615 616 link->state &= ~DEV_CONFIG; 617 if (link->state & DEV_STALE_LINK) 618 awc_detach(link); 619 620} /* awc_release */ 621 622/* 623 624 The card status event handler. Mostly, this schedules other 625 stuff to run after an event is received. A CARD_REMOVAL event 626 also sets some flags to discourage the net drivers from trying 627 to talk to the card any more. 628*/ 629 630static int awc_event(event_t event, int priority, 631 event_callback_args_t *args) 632{ 633 dev_link_t *link = args->client_data; 634 struct net_device *dev = link->priv; 635 636 PC_DEBUG(1, "awc_event(0x%06x)\n", event); 637 638 switch (event) { 639 case CS_EVENT_CARD_REMOVAL: 640 link->state &= ~DEV_PRESENT; 641 if (link->state & DEV_CONFIG) { 642 netif_device_detach(dev); 643 link->release.expires = RUN_AT( HZ/20 ); 644 add_timer(&link->release); 645 } 646 break; 647 case CS_EVENT_CARD_INSERTION: 648 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 649 awc_pcmcia_config(link); 650 break; 651 case CS_EVENT_PM_SUSPEND: 652 link->state |= DEV_SUSPEND; 653 /* Fall through... */ 654 case CS_EVENT_RESET_PHYSICAL: 655 if (link->state & DEV_CONFIG) { 656 if (link->open) 657 netif_device_detach(dev); 658 659 CardServices(ReleaseConfiguration, link->handle); 660 } 661 break; 662 case CS_EVENT_PM_RESUME: 663 link->state &= ~DEV_SUSPEND; 664 /* Fall through... */ 665 case CS_EVENT_CARD_RESET: 666 if (link->state & DEV_CONFIG) { 667 CardServices(RequestConfiguration, link->handle, &link->conf); 668 if (link->open) { 669 // awc_reset(dev); 670 netif_device_attach(dev); 671 } 672 } 673 break; 674 } 675 return 0; 676} /* awc_event */ 677 678 679 680static int __init aironet_cs_init(void) 681{ 682 servinfo_t serv; 683 684 /* Always emit the version, before any failure. */ 685 printk(KERN_INFO"%s", awc_version); 686 PC_DEBUG(0, "%s\n", version); 687 CardServices(GetCardServicesInfo, &serv); 688 if (serv.Revision != CS_RELEASE_CODE) { 689 printk(KERN_NOTICE "awc_cs: Card Services release " 690 "does not match!\n"); 691 return -1; 692 } 693 register_pcmcia_driver(&dev_info, &awc_attach, &awc_detach); 694 return 0; 695} 696 697static void __exit aironet_cs_exit(void) 698{ 699 DEBUG(0, "awc_cs: unloading %c ",'\n'); 700 unregister_pcmcia_driver(&dev_info); 701 702 while (dev_list != NULL) { 703 if (dev_list->state & DEV_CONFIG) 704 awc_release((u_long)dev_list); 705 awc_detach(dev_list); 706 } 707 708// while (dev_list != NULL) 709// awc_detach(dev_list); 710} 711 712module_init(aironet_cs_init); 713module_exit(aironet_cs_exit); 714MODULE_LICENSE("GPL"); 715