📄 avma1_cs.c
字号:
static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse){ int i; i = CardServices(fn, handle, tuple); if (i != CS_SUCCESS) return i; i = CardServices(GetTupleData, handle, tuple); if (i != CS_SUCCESS) return i; return CardServices(ParseTuple, handle, tuple, parse);}#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)static void avma1cs_config(dev_link_t *link){ client_handle_t handle; tuple_t tuple; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; local_info_t *dev; int i; u_char buf[64]; char devname[128]; int busy = 0; handle = link->handle; dev = link->priv; DEBUG(0, "avma1cs_config(0x%p)\n", link); /* This reads the card's CONFIG tuple to find its configuration registers. */ do { tuple.DesiredTuple = CISTPL_CONFIG; i = CardServices(GetFirstTuple, handle, &tuple); if (i != CS_SUCCESS) break; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; i = CardServices(GetTupleData, handle, &tuple); if (i != CS_SUCCESS) break; i = CardServices(ParseTuple, handle, &tuple, &parse); if (i != CS_SUCCESS) break; link->conf.ConfigBase = parse.config.base; } while (0); if (i != CS_SUCCESS) { cs_error(link->handle, ParseTuple, i); link->state &= ~DEV_CONFIG_PENDING; return; } /* Configure card */ link->state |= DEV_CONFIG; do { tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = 254; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_VERS_1; devname[0] = 0; if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { strncpy(devname,parse.version_1.str + parse.version_1.ofs[1], sizeof(devname)); } /* * find IO port */ tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; i = first_tuple(handle, &tuple, &parse); while (i == CS_SUCCESS) { if (cf->io.nwin > 0) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.NumPorts1 = cf->io.win[0].len; link->io.NumPorts2 = 0; printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1 - 1); i = CardServices(RequestIO, link->handle, &link->io); if (i == CS_SUCCESS) goto found_port; } i = next_tuple(handle, &tuple, &parse); }found_port: if (i != CS_SUCCESS) { cs_error(link->handle, RequestIO, i); break; } /* * allocate an interrupt line */ i = CardServices(RequestIRQ, link->handle, &link->irq); if (i != CS_SUCCESS) { cs_error(link->handle, RequestIRQ, i); CardServices(ReleaseIO, link->handle, &link->io); break; } /* * configure the PCMCIA socket */ i = CardServices(RequestConfiguration, link->handle, &link->conf); if (i != CS_SUCCESS) { cs_error(link->handle, RequestConfiguration, i); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); break; } } while (0); /* At this point, the dev_node_t structure(s) should be initialized and arranged in a linked list at link->dev. */ strcpy(dev->node.dev_name, "A1"); dev->node.major = 45; dev->node.minor = 0; link->dev = &dev->node; link->state &= ~DEV_CONFIG_PENDING; /* If any step failed, release any partially configured state */ if (i != 0) { avma1cs_release((u_long)link); return; } printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", link->io.BasePort1, link->irq.AssignedIRQ); if (avm_a1_init_pcmcia((void *)(int)link->io.BasePort1, link->irq.AssignedIRQ, &busy, isdnprot) != 0) { printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); return; } i = 0; /* no returncode for cardnr :-( */ dev->node.minor = i;} /* avma1cs_config *//*====================================================================== After a card is removed, avma1cs_release() will unregister the net device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. ======================================================================*/static void avma1cs_release(u_long arg){ dev_link_t *link = (dev_link_t *)arg; local_info_t *local = link->priv; DEBUG(0, "avma1cs_release(0x%p)\n", link); /* If the device is currently in use, we won't release until it is actually closed. */ if (link->open) { DEBUG(1, "avma1_cs: release postponed, '%s' still open\n", link->dev->dev_name); link->state |= DEV_STALE_CONFIG; return; } /* no unregister function with hisax */ HiSax_closecard(local->node.minor); /* Unlink the device chain */ link->dev = NULL; /* Don't bother checking to see if these succeed or not */ CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; if (link->state & DEV_STALE_LINK) avma1cs_detach(link); } /* avma1cs_release *//*====================================================================== The card status event handler. Mostly, this schedules other stuff to run after an event is received. A CARD_REMOVAL event also sets some flags to discourage the net drivers from trying to talk to the card any more. When a CARD_REMOVAL event is received, we immediately set a flag to block future accesses to this device. All the functions that actually access the device should check this flag to make sure the card is still present. ======================================================================*/static int avma1cs_event(event_t event, int priority, event_callback_args_t *args){ dev_link_t *link = args->client_data; DEBUG(1, "avma1cs_event(0x%06x)\n", event); switch (event) { case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { link->release.expires = jiffies + HZ/20; add_timer(&link->release); } break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; avma1cs_config(link); break; case CS_EVENT_PM_SUSPEND: link->state |= DEV_SUSPEND; /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) CardServices(ReleaseConfiguration, link->handle); break; case CS_EVENT_PM_RESUME: link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) CardServices(RequestConfiguration, link->handle, &link->conf); break; } return 0;} /* avma1cs_event *//*====================================================================*/static int __init init_avma1_cs(void){ servinfo_t serv; DEBUG(0, "%s\n", version); CardServices(GetCardServicesInfo, &serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE "avma1_cs: Card Services release " "does not match!\n"); return -1; } register_pccard_driver(&dev_info, &avma1cs_attach, &avma1cs_detach); return 0;}static void __exit exit_avma1_cs(void){ DEBUG(0, "avma1_cs: unloading\n"); unregister_pccard_driver(&dev_info); while (dev_list != NULL) if (dev_list->state & DEV_CONFIG) avma1cs_release((u_long)dev_list); avma1cs_detach(dev_list);}module_init(init_avma1_cs);module_exit(exit_avma1_cs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -