elsa_cs.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 552 行 · 第 1/2 页

C
552
字号
	if (ret != CS_SUCCESS)	    cs_error(link->handle, DeregisterClient, ret);    }    /* Unlink device structure and free it */    *linkp = link->next;    kfree(info);} /* elsa_cs_detach *//*======================================================================    elsa_cs_config() is scheduled to run after a CARD_INSERTION event    is received, to configure the PCMCIA socket, and to make the    device available to the system.======================================================================*/static int get_tuple(client_handle_t handle, tuple_t *tuple,                     cisparse_t *parse){    int i = pcmcia_get_tuple_data(handle, tuple);    if (i != CS_SUCCESS) return i;    return pcmcia_parse_tuple(handle, tuple, parse);}static int first_tuple(client_handle_t handle, tuple_t *tuple,                     cisparse_t *parse){    int i = pcmcia_get_first_tuple(handle, tuple);    if (i != CS_SUCCESS) return i;    return get_tuple(handle, tuple, parse);}static int next_tuple(client_handle_t handle, tuple_t *tuple,                     cisparse_t *parse){    int i = pcmcia_get_next_tuple(handle, tuple);    if (i != CS_SUCCESS) return i;    return get_tuple(handle, tuple, parse);}static void elsa_cs_config(dev_link_t *link){    client_handle_t handle;    tuple_t tuple;    cisparse_t parse;    local_info_t *dev;    int i, j, last_fn;    u_short buf[128];    cistpl_cftable_entry_t *cf = &parse.cftable_entry;    IsdnCard_t icard;    DEBUG(0, "elsa_config(0x%p)\n", link);    handle = link->handle;    dev = link->priv;    /*       This reads the card's CONFIG tuple to find its configuration       registers.    */    tuple.DesiredTuple = CISTPL_CONFIG;    tuple.TupleData = (cisdata_t *)buf;    tuple.TupleDataMax = 255;    tuple.TupleOffset = 0;    tuple.Attributes = 0;    i = first_tuple(handle, &tuple, &parse);    if (i != CS_SUCCESS) {        last_fn = ParseTuple;	goto cs_failed;    }    link->conf.ConfigBase = parse.config.base;    link->conf.Present = parse.config.rmask[0];    /* Configure card */    link->state |= DEV_CONFIG;    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) && cf->io.win[0].base) {            printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");            link->conf.ConfigIndex = cf->index;            link->io.BasePort1 = cf->io.win[0].base;            i = pcmcia_request_io(link->handle, &link->io);            if (i == CS_SUCCESS) break;        } else {          printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");          link->conf.ConfigIndex = cf->index;          for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {            link->io.BasePort1 = j;            i = pcmcia_request_io(link->handle, &link->io);            if (i == CS_SUCCESS) break;          }          break;        }        i = next_tuple(handle, &tuple, &parse);    }    if (i != CS_SUCCESS) {	last_fn = RequestIO;	goto cs_failed;    }    i = pcmcia_request_irq(link->handle, &link->irq);    if (i != CS_SUCCESS) {        link->irq.AssignedIRQ = 0;	last_fn = RequestIRQ;        goto cs_failed;    }    i = pcmcia_request_configuration(link->handle, &link->conf);    if (i != CS_SUCCESS) {      last_fn = RequestConfiguration;      goto cs_failed;    }    /* At this point, the dev_node_t structure(s) should be       initialized and arranged in a linked list at link->dev. *//*  */    sprintf(dev->node.dev_name, "elsa");    dev->node.major = dev->node.minor = 0x0;    link->dev = &dev->node;    /* Finally, report what we've done */    printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",           dev->node.dev_name, link->conf.ConfigIndex,           link->conf.Vcc/10, link->conf.Vcc%10);    if (link->conf.Vpp1)        printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);    if (link->conf.Attributes & CONF_ENABLE_IRQ)        printk(", irq %d", link->irq.AssignedIRQ);    if (link->io.NumPorts1)        printk(", io 0x%04x-0x%04x", link->io.BasePort1,               link->io.BasePort1+link->io.NumPorts1-1);    if (link->io.NumPorts2)        printk(" & 0x%04x-0x%04x", link->io.BasePort2,               link->io.BasePort2+link->io.NumPorts2-1);    printk("\n");    link->state &= ~DEV_CONFIG_PENDING;    icard.para[0] = link->irq.AssignedIRQ;    icard.para[1] = link->io.BasePort1;    icard.protocol = protocol;    icard.typ = ISDN_CTYPE_ELSA_PCMCIA;        i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);    if (i < 0) {    	printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n",    		i, link->io.BasePort1);    	elsa_cs_release(link);    } else    	((local_info_t*)link->priv)->cardnr = i;    return;cs_failed:    cs_error(link->handle, last_fn, i);    elsa_cs_release(link);} /* elsa_cs_config *//*======================================================================    After a card is removed, elsa_cs_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 elsa_cs_release(dev_link_t *link){    local_info_t *local = link->priv;    DEBUG(0, "elsa_cs_release(0x%p)\n", link);    if (local) {    	if (local->cardnr >= 0) {    	    /* no unregister function with hisax */	    HiSax_closecard(local->cardnr);	}    }    /* Unlink the device chain */    link->dev = NULL;    /* Don't bother checking to see if these succeed or not */    if (link->win)        pcmcia_release_window(link->win);    pcmcia_release_configuration(link->handle);    pcmcia_release_io(link->handle, &link->io);    pcmcia_release_irq(link->handle, &link->irq);    link->state &= ~DEV_CONFIG;} /* elsa_cs_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 elsa_cs_event(event_t event, int priority,                          event_callback_args_t *args){    dev_link_t *link = args->client_data;    local_info_t *dev = link->priv;    DEBUG(1, "elsa_cs_event(%d)\n", event);    switch (event) {    case CS_EVENT_CARD_REMOVAL:        link->state &= ~DEV_PRESENT;        if (link->state & DEV_CONFIG) {            ((local_info_t*)link->priv)->busy = 1;	    elsa_cs_release(link);        }        break;    case CS_EVENT_CARD_INSERTION:        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;        elsa_cs_config(link);        break;    case CS_EVENT_PM_SUSPEND:        link->state |= DEV_SUSPEND;        /* Fall through... */    case CS_EVENT_RESET_PHYSICAL:        /* Mark the device as stopped, to block IO until later */        dev->busy = 1;        if (link->state & DEV_CONFIG)            pcmcia_release_configuration(link->handle);        break;    case CS_EVENT_PM_RESUME:        link->state &= ~DEV_SUSPEND;        /* Fall through... */    case CS_EVENT_CARD_RESET:        if (link->state & DEV_CONFIG)            pcmcia_request_configuration(link->handle, &link->conf);        dev->busy = 0;        break;    }    return 0;} /* elsa_cs_event */static struct pcmcia_driver elsa_cs_driver = {	.owner		= THIS_MODULE,	.drv		= {		.name	= "elsa_cs",	},	.attach		= elsa_cs_attach,	.detach		= elsa_cs_detach,};static int __init init_elsa_cs(void){	return pcmcia_register_driver(&elsa_cs_driver);}static void __exit exit_elsa_cs(void){	pcmcia_unregister_driver(&elsa_cs_driver);	/* XXX: this really needs to move into generic code.. */	while (dev_list != NULL)		elsa_cs_detach(dev_list);}module_init(init_elsa_cs);module_exit(exit_elsa_cs);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?