1/* 2 * Linux ARCnet driver - COM20020 PCMCIA support 3 * 4 * Written 1994-1999 by Avery Pennarun, 5 * based on an ISA version by David Woodhouse. 6 * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4) 7 * which was derived from pcnet_cs.c by David Hinds. 8 * Some additional portions derived from skeleton.c by Donald Becker. 9 * 10 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) 11 * for sponsoring the further development of this driver. 12 * 13 * ********************** 14 * 15 * The original copyright of skeleton.c was as follows: 16 * 17 * skeleton.c Written 1993 by Donald Becker. 18 * Copyright 1993 United States Government as represented by the 19 * Director, National Security Agency. This software may only be used 20 * and distributed according to the terms of the GNU General Public License as 21 * modified by SRC, incorporated herein by reference. 22 * 23 * ********************** 24 * Changes: 25 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000 26 * - reorganize kmallocs in com20020_attach, checking all for failure 27 * and releasing the previous allocations if one fails 28 * ********************** 29 * 30 * For more details, see drivers/net/arcnet.c 31 * 32 * ********************** 33 */ 34#include <linux/kernel.h> 35#include <linux/init.h> 36#include <linux/sched.h> 37#include <linux/ptrace.h> 38#include <linux/slab.h> 39#include <linux/string.h> 40#include <linux/timer.h> 41#include <linux/delay.h> 42#include <linux/module.h> 43#include <asm/io.h> 44#include <asm/system.h> 45 46#include <linux/netdevice.h> 47#include <linux/arcdevice.h> 48#include <linux/com20020.h> 49 50#include <pcmcia/version.h> 51#include <pcmcia/cs_types.h> 52#include <pcmcia/cs.h> 53#include <pcmcia/cistpl.h> 54#include <pcmcia/ds.h> 55 56#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" 57 58#ifdef PCMCIA_DEBUG 59 60static int pc_debug = PCMCIA_DEBUG; 61MODULE_PARM(pc_debug, "i"); 62#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) 63 64static void regdump(struct net_device *dev) 65{ 66 int ioaddr = dev->base_addr; 67 int count; 68 69 printk("com20020 register dump:\n"); 70 for (count = ioaddr; count < ioaddr + 16; count++) 71 { 72 if (!(count % 16)) 73 printk("\n%04X: ", count); 74 printk("%02X ", inb(count)); 75 } 76 printk("\n"); 77 78 printk("buffer0 dump:\n"); 79 /* set up the address register */ 80 count = 0; 81 outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); 82 outb(count & 0xff, _ADDR_LO); 83 84 for (count = 0; count < 256+32; count++) 85 { 86 if (!(count % 16)) 87 printk("\n%04X: ", count); 88 89 /* copy the data */ 90 printk("%02X ", inb(_MEMDATA)); 91 } 92 printk("\n"); 93} 94 95#else 96 97#define DEBUG(n, args...) do { } while (0) 98static inline void regdump(struct net_device *dev) { } 99 100#endif 101 102 103/*====================================================================*/ 104 105/* Parameters that can be set with 'insmod' */ 106 107static int node; 108static int timeout = 3; 109static int backplane; 110static int clockp; 111static int clockm; 112 113MODULE_PARM(node, "i"); 114MODULE_PARM(timeout, "i"); 115MODULE_PARM(backplane, "i"); 116MODULE_PARM(clockp, "i"); 117MODULE_PARM(clockm, "i"); 118 119/* Bit map of interrupts to choose from */ 120static u_int irq_mask = 0xdeb8; 121static int irq_list[4] = { -1 }; 122 123MODULE_PARM(irq_mask, "i"); 124MODULE_PARM(irq_list, "1-4i"); 125MODULE_LICENSE("GPL"); 126 127/*====================================================================*/ 128 129static void com20020_config(dev_link_t *link); 130static void com20020_release(u_long arg); 131static int com20020_event(event_t event, int priority, 132 event_callback_args_t *args); 133 134static dev_info_t dev_info = "com20020_cs"; 135 136static dev_link_t *com20020_attach(void); 137static void com20020_detach(dev_link_t *); 138 139static dev_link_t *dev_list; 140 141/*====================================================================*/ 142 143typedef struct com20020_dev_t { 144 struct net_device *dev; 145 int dev_configured; 146 dev_node_t node; 147} com20020_dev_t; 148 149/*====================================================================== 150 151 This bit of code is used to avoid unregistering network devices 152 at inappropriate times. 2.2 and later kernels are fairly picky 153 about when this can happen. 154 155======================================================================*/ 156 157static void flush_stale_links(void) 158{ 159 dev_link_t *link, *next; 160 for (link = dev_list; link; link = next) { 161 next = link->next; 162 if (link->state & DEV_STALE_LINK) 163 com20020_detach(link); 164 } 165} 166 167/*====================================================================*/ 168 169static void cs_error(client_handle_t handle, int func, int ret) 170{ 171 error_info_t err = { func, ret }; 172 CardServices(ReportError, handle, &err); 173} 174 175/*====================================================================== 176 177 com20020_attach() creates an "instance" of the driver, allocating 178 local data structures for one device. The device is registered 179 with Card Services. 180 181======================================================================*/ 182 183static void com20020cs_open_close(struct net_device *dev, bool open) 184{ 185 if (open) 186 MOD_INC_USE_COUNT; 187 else 188 MOD_DEC_USE_COUNT; 189} 190 191static dev_link_t *com20020_attach(void) 192{ 193 client_reg_t client_reg; 194 dev_link_t *link; 195 com20020_dev_t *info; 196 struct net_device *dev; 197 int i, ret; 198 struct arcnet_local *lp; 199 200 DEBUG(0, "com20020_attach()\n"); 201 flush_stale_links(); 202 203 /* Create new network device */ 204 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); 205 if (!link) 206 return NULL; 207 208 info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); 209 if (!info) 210 goto fail_alloc_info; 211 212 lp = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); 213 if (!lp) 214 goto fail_alloc_lp; 215 216 dev = dev_alloc("arc%d", &ret); 217 if (!dev) 218 goto fail_alloc_dev; 219 220 memset(info, 0, sizeof(struct com20020_dev_t)); 221 memset(lp, 0, sizeof(struct arcnet_local)); 222 memset(link, 0, sizeof(struct dev_link_t)); 223 dev->priv = lp; 224 225 link->release.function = &com20020_release; 226 link->release.data = (u_long)link; 227 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 228 link->io.NumPorts1 = 16; 229 link->io.IOAddrLines = 16; 230 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 231 link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; 232 if (irq_list[0] == -1) 233 link->irq.IRQInfo2 = irq_mask; 234 else 235 for (i = 0; i < 4; i++) 236 link->irq.IRQInfo2 |= 1 << irq_list[i]; 237 link->conf.Attributes = CONF_ENABLE_IRQ; 238 link->conf.Vcc = 50; 239 link->conf.IntType = INT_MEMORY_AND_IO; 240 link->conf.Present = PRESENT_OPTION; 241 242 /* fill in our module parameters as defaults */ 243 dev->dev_addr[0] = node; 244 lp->timeout = timeout; 245 lp->backplane = backplane; 246 lp->clockp = clockp; 247 lp->clockm = clockm & 3; 248 lp->hw.open_close_ll = com20020cs_open_close; 249 250 link->irq.Instance = info->dev = dev; 251 link->priv = info; 252 253 /* Register with Card Services */ 254 link->next = dev_list; 255 dev_list = link; 256 client_reg.dev_info = &dev_info; 257 client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; 258 client_reg.EventMask = 259 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | 260 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | 261 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; 262 client_reg.event_handler = &com20020_event; 263 client_reg.Version = 0x0210; 264 client_reg.event_callback_args.client_data = link; 265 ret = CardServices(RegisterClient, &link->handle, &client_reg); 266 if (ret != 0) { 267 cs_error(link->handle, RegisterClient, ret); 268 com20020_detach(link); 269 return NULL; 270 } 271 272 return link; 273 274fail_alloc_dev: 275 kfree(lp); 276fail_alloc_lp: 277 kfree(info); 278fail_alloc_info: 279 kfree(link); 280 return NULL; 281} /* com20020_attach */ 282 283/*====================================================================== 284 285 This deletes a driver "instance". The device is de-registered 286 with Card Services. If it has been released, all local data 287 structures are freed. Otherwise, the structures will be freed 288 when the device is released. 289 290======================================================================*/ 291 292static void com20020_detach(dev_link_t *link) 293{ 294 struct com20020_dev_t *info = link->priv; 295 dev_link_t **linkp; 296 struct net_device *dev; 297 298 DEBUG(1,"detach...\n"); 299 300 DEBUG(0, "com20020_detach(0x%p)\n", link); 301 302 /* Locate device structure */ 303 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) 304 if (*linkp == link) break; 305 if (*linkp == NULL) 306 return; 307 308 dev = info->dev; 309 310 if (link->state & DEV_CONFIG) { 311 com20020_release((u_long)link); 312 if (link->state & DEV_STALE_CONFIG) { 313 link->state |= DEV_STALE_LINK; 314 return; 315 } 316 } 317 318 if (link->handle) 319 CardServices(DeregisterClient, link->handle); 320 321 /* Unlink device structure, free bits */ 322 DEBUG(1,"unlinking...\n"); 323 *linkp = link->next; 324 if (link->priv) 325 { 326 dev = info->dev; 327 if (dev) 328 { 329 if (info->dev_configured) 330 { 331 DEBUG(1,"unregister...\n"); 332 333 if (netif_running(dev)) 334 dev->stop(dev); 335 336 /* 337 * this is necessary because we register our IRQ separately 338 * from card services. 339 */ 340 if (dev->irq) 341 free_irq(dev->irq, dev); 342 343 /* ...but I/O ports are done automatically by card services */ 344 345 unregister_netdev(dev); 346 MOD_DEC_USE_COUNT; 347 } 348 349 DEBUG(1,"kfree...\n"); 350 kfree(dev->priv); 351 kfree(dev); 352 } 353 DEBUG(1,"kfree2...\n"); 354 kfree(info); 355 } 356 DEBUG(1,"kfree3...\n"); 357 kfree(link); 358 359} /* com20020_detach */ 360 361/*====================================================================== 362 363 com20020_config() is scheduled to run after a CARD_INSERTION event 364 is received, to configure the PCMCIA socket, and to make the 365 device available to the system. 366 367======================================================================*/ 368 369#define CS_CHECK(fn, args...) \ 370while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed 371 372static void com20020_config(dev_link_t *link) 373{ 374 struct arcnet_local *lp; 375 client_handle_t handle; 376 tuple_t tuple; 377 cisparse_t parse; 378 com20020_dev_t *info; 379 struct net_device *dev; 380 int i, last_ret, last_fn; 381 u_char buf[64]; 382 int ioaddr; 383 384 handle = link->handle; 385 info = link->priv; 386 dev = info->dev; 387 388 DEBUG(1,"config...\n"); 389 390 DEBUG(0, "com20020_config(0x%p)\n", link); 391 392 tuple.Attributes = 0; 393 tuple.TupleData = buf; 394 tuple.TupleDataMax = 64; 395 tuple.TupleOffset = 0; 396 tuple.DesiredTuple = CISTPL_CONFIG; 397 CS_CHECK(GetFirstTuple, handle, &tuple); 398 CS_CHECK(GetTupleData, handle, &tuple); 399 CS_CHECK(ParseTuple, handle, &tuple, &parse); 400 link->conf.ConfigBase = parse.config.base; 401 402 /* Configure card */ 403 link->state |= DEV_CONFIG; 404 strcpy(info->node.dev_name, dev->name); 405 406 DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); 407 i = !CS_SUCCESS; 408 if (!link->io.BasePort1) 409 { 410 for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) 411 { 412 link->io.BasePort1 = ioaddr; 413 i = CardServices(RequestIO, link->handle, &link->io); 414 if (i == CS_SUCCESS) 415 break; 416 } 417 } 418 else 419 i = CardServices(RequestIO, link->handle, &link->io); 420 421 if (i != CS_SUCCESS) 422 { 423 DEBUG(1,"arcnet: requestIO failed totally!\n"); 424 goto failed; 425 } 426 427 ioaddr = dev->base_addr = link->io.BasePort1; 428 DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr); 429 430 DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n", 431 link->irq.AssignedIRQ, 432 link->irq.IRQInfo1, link->irq.IRQInfo2); 433 i = CardServices(RequestIRQ, link->handle, &link->irq); 434 if (i != CS_SUCCESS) 435 { 436 DEBUG(1,"arcnet: requestIRQ failed totally!\n"); 437 goto failed; 438 } 439 440 dev->irq = link->irq.AssignedIRQ; 441 442 CS_CHECK(RequestConfiguration, link->handle, &link->conf); 443 444 if (com20020_check(dev)) 445 { 446 regdump(dev); 447 goto failed; 448 } 449 450 MOD_INC_USE_COUNT; 451 452 lp = dev->priv; 453 lp->card_name = "PCMCIA COM20020"; 454 lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ 455 456 i = com20020_found(dev, 0); 457 458 if (i != 0) { 459 DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); 460 goto failed; 461 } 462 463 info->dev_configured = 1; 464 link->dev = &info->node; 465 link->state &= ~DEV_CONFIG_PENDING; 466 467 DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", 468 dev->name, dev->base_addr, dev->irq); 469 return; 470 471cs_failed: 472 cs_error(link->handle, last_fn, last_ret); 473failed: 474 DEBUG(1,"com20020_config failed...\n"); 475 com20020_release((u_long)link); 476} /* com20020_config */ 477 478/*====================================================================== 479 480 After a card is removed, com20020_release() will unregister the net 481 device, and release the PCMCIA configuration. If the device is 482 still open, this will be postponed until it is closed. 483 484======================================================================*/ 485 486static void com20020_release(u_long arg) 487{ 488 dev_link_t *link = (dev_link_t *)arg; 489 490 DEBUG(1,"release...\n"); 491 492 DEBUG(0, "com20020_release(0x%p)\n", link); 493 494 if (link->open) { 495 DEBUG(1,"postpone...\n"); 496 DEBUG(1, "com20020_cs: release postponed, device stll open\n"); 497 link->state |= DEV_STALE_CONFIG; 498 return; 499 } 500 501 CardServices(ReleaseConfiguration, link->handle); 502 CardServices(ReleaseIO, link->handle, &link->io); 503 CardServices(ReleaseIRQ, link->handle, &link->irq); 504 505 link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); 506 507} /* com20020_release */ 508 509/*====================================================================== 510 511 The card status event handler. Mostly, this schedules other 512 stuff to run after an event is received. A CARD_REMOVAL event 513 also sets some flags to discourage the net drivers from trying 514 to talk to the card any more. 515 516======================================================================*/ 517 518static int com20020_event(event_t event, int priority, 519 event_callback_args_t *args) 520{ 521 dev_link_t *link = args->client_data; 522 com20020_dev_t *info = link->priv; 523 struct net_device *dev = info->dev; 524 525 DEBUG(1, "com20020_event(0x%06x)\n", event); 526 527 switch (event) { 528 case CS_EVENT_CARD_REMOVAL: 529 link->state &= ~DEV_PRESENT; 530 if (link->state & DEV_CONFIG) { 531 netif_device_detach(dev); 532 link->release.expires = jiffies + HZ/20; 533 link->state |= DEV_RELEASE_PENDING; 534 add_timer(&link->release); 535 } 536 break; 537 case CS_EVENT_CARD_INSERTION: 538 link->state |= DEV_PRESENT; 539 com20020_config(link); 540 break; 541 case CS_EVENT_PM_SUSPEND: 542 link->state |= DEV_SUSPEND; 543 /* Fall through... */ 544 case CS_EVENT_RESET_PHYSICAL: 545 if (link->state & DEV_CONFIG) { 546 if (link->open) { 547 netif_device_detach(dev); 548 } 549 CardServices(ReleaseConfiguration, link->handle); 550 } 551 break; 552 case CS_EVENT_PM_RESUME: 553 link->state &= ~DEV_SUSPEND; 554 /* Fall through... */ 555 case CS_EVENT_CARD_RESET: 556 if (link->state & DEV_CONFIG) { 557 CardServices(RequestConfiguration, link->handle, &link->conf); 558 if (link->open) { 559 int ioaddr = dev->base_addr; 560 struct arcnet_local *lp = (struct arcnet_local *)dev->priv; 561 ARCRESET; 562 } 563 } 564 break; 565 } 566 return 0; 567} /* com20020_event */ 568 569 570/*====================================================================*/ 571 572static int __init init_com20020_cs(void) 573{ 574 servinfo_t serv; 575 576 DEBUG(0, "%s\n", VERSION); 577 CardServices(GetCardServicesInfo, &serv); 578 if (serv.Revision != CS_RELEASE_CODE) { 579 printk(KERN_NOTICE "com20020_cs: Card Services release " 580 "does not match!\n"); 581 return -1; 582 } 583 register_pccard_driver(&dev_info, &com20020_attach, &com20020_detach); 584 return 0; 585} 586 587static void __exit exit_com20020_cs(void) 588{ 589 DEBUG(0, "com20020_cs: unloading\n"); 590 unregister_pccard_driver(&dev_info); 591 while (dev_list != NULL) 592 com20020_detach(dev_list); 593} 594 595module_init(init_com20020_cs); 596module_exit(exit_com20020_cs); 597