mc_pcmcia_cs.c
来自「canpie 一个can bus的协议栈 - CAN interface fo」· C语言 代码 · 共 633 行 · 第 1/2 页
C
633 行
link->conf.Vcc = conf.Vcc; //---------------------------------------------------------------- // In this loop, we scan the CIS for configuration table entries, // each of which describes a valid card configuration, including // voltage, IO window, memory window, and interrupt settings. // tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if( pcmcia_get_tuple_data(handle, &tuple) != 0 || pcmcia_parse_tuple(handle, &tuple, &parse) != 0) { goto next_entry; } //-------------------------------------------------------- // IRQ settings // /* if(cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) { link->conf.Attributes |= CONF_ENABLE_IRQ; } */ //-------------------------------------------------------- // I/O window settings // link->io.NumPorts1 = 0; link->io.NumPorts2 = 0; if( (cfg->io.nwin > 0) || (dflt.io.nwin > 0) ) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; if( !(io->flags & CISTPL_IO_8BIT) ) { link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; } if( !(io->flags & CISTPL_IO_16BIT)) { link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; } link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; link->io.BasePort1 = io->win[0].base; link->io.NumPorts1 = io->win[0].len; if(io->nwin > 1) { link->io.Attributes2 = link->io.Attributes1; link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = io->win[1].len; } //------------------------------------------------ // This reserves IO space but doesn't actually // enable it // if(pcmcia_request_io(link->handle, &link->io) != 0) { goto next_entry; } } //----------------------------------------------- // If we've got this far, we're done // break; next_entry: if(cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } // link->irq.Attributes = IRQ_FORCED_PULSE; //CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); PK_DBG("Conf. I/O-Base=%04X I/O-Num=%02d IRQ=%02d Attributes=%X", link->io.BasePort1, link->io.NumPorts1, link->irq.AssignedIRQ, link->irq.Attributes); request_region(link->io.BasePort1, link->io.NumPorts1, CP_DRV_NAME); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); sprintf(dev->node.dev_name, CP_DRV_NAME); dev->node.major = 0; dev->node.minor = 0; dev->irg = 0; dev->port = link->io.BasePort1; link->dev = &dev->node; //---------------------------------------------------------------- // reset the PCMCIA card // mc_pcmcia_set_info(link->priv); mc_pcmcia_reset(); mc_pcmcia_task_start(); link->state &= ~DEV_CONFIG_PENDING; return; cs_failed: cs_error(link->handle, last_fn, last_ret);// failed: mc_pcmcia_release(link); link->state &= ~DEV_CONFIG_PENDING;}//----------------------------------------------------------------------------//// mc_pcmcia_release() //// After a card is removed, mc_pcmcia_release() will unregister the device, //// and release the PCMCIA configuration. If the device is still open, //// this will be postponed until it is closed. //// ////----------------------------------------------------------------------------//void mc_pcmcia_release(dev_link_t *link){ PK_DBG("mc_pcmcia_release(0x%p)\n", link); mc_pcmcia_task_stop(); if(link->open) { PK_DBG("release postponed, still open"); link->state |= DEV_STALE_CONFIG; return; } if(link->win) { pcmcia_release_window(link->win); } //---------------------------------------------------------------- // release the open ports // release_region(link->io.BasePort1, link->io.NumPorts1); free_irq(link->irq.AssignedIRQ, link->priv); pcmcia_release_configuration(link->handle); if(link->io.NumPorts1) { pcmcia_release_io(link->handle, &link->io); } link->state &= ~DEV_CONFIG; }//----------------------------------------------------------------------------//// mc_pcmcia_event() //// The card status event handler. Mostly, this schedules other stuff to run //// after an event is received. When a CARD_REMOVAL event is received, we //// immediately set a private 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 mc_pcmcia_event(event_t event, int priority, event_callback_args_t *args){ dev_link_t * link = args->client_data; _TsMcPcmciaInfo * dev = link->priv; PK_DBG("mc_pcmcia_event()"); switch (event) { case CS_EVENT_CARD_REMOVAL: PK_DBG("CS_EVENT_CARD_REMOVAL"); link->state &= ~DEV_PRESENT; if(link->state & DEV_CONFIG) { mc_pcmcia_release(link); } break; case CS_EVENT_CARD_INSERTION: PK_DBG("CS_EVENT_CARD_INSERTION"); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; mc_pcmcia_config(link); break; case CS_EVENT_PM_SUSPEND: PK_DBG("CS_EVENT_PM_SUSPEND"); link->state |= DEV_SUSPEND; //--- Fall through... -------- case CS_EVENT_RESET_PHYSICAL: PK_DBG("CS_EVENT_RESET_PHYSICAL"); // Mark the device as stopped, to block IO until later dev->stop = 1; if(link->state & DEV_CONFIG) { pcmcia_release_configuration(link->handle); } break; case CS_EVENT_PM_RESUME: PK_DBG("CS_EVENT_PM_RESUME"); link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: PK_DBG("CS_EVENT_CARD_RESET"); if(link->state & DEV_CONFIG) { pcmcia_request_configuration(link->handle, &link->conf); } dev->stop = 0; /* In a normal driver, additional code may go here to restore the device state and restart IO. */ break; } return 0;}#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)static struct pcmcia_device_id mc_pcmcia_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0000, 0xe386), /* CAN */ PCMCIA_DEVICE_NULL,};MODULE_DEVICE_TABLE(pcmcia, mc_pcmcia_cs_ids);#endif/*----------------------------------------------------------------------------*\** Initialization structures / functions **** **\*----------------------------------------------------------------------------*/static struct pcmcia_driver mc_pcmcia_driver = { .owner = THIS_MODULE, .drv = { .name = "can_mc_pcmcia", },#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) .probe = mc_pcmcia_attach, .remove = mc_pcmcia_detach, .id_table = mc_pcmcia_cs_ids,#else .attach = mc_pcmcia_attach, .detach = mc_pcmcia_detach,#endif};//----------------------------------------------------------------------------//// init_mc_pcmcia_cs() //// ////----------------------------------------------------------------------------//static int __init init_mc_pcmcia_cs(void){ int slStatusT; PK_INF("Init driver for MicroControl PCMCIA CAN card .."); //---------------------------------------------------------------- // register PCMCIA driver / services and assign // the resources for the PCMCIA CAN interface // slStatusT = pcmcia_register_driver(&mc_pcmcia_driver); //---------------------------------------------------------------- // start the CANpie driver for the CAN interface // mc_pcmcia_can_register(&auwMcPcmciaPortS[0]); return(slStatusT);}//----------------------------------------------------------------------------//// exit_mc_pcmcia_cs() //// ////----------------------------------------------------------------------------//static void __exit exit_mc_pcmcia_cs(void){ PK_INF("Remove driver for MicroControl PCMCIA CAN card .."); mc_pcmcia_can_unregister(); pcmcia_unregister_driver(&mc_pcmcia_driver);}//----------------------------------------------------------------------------//// module_init() //// ////----------------------------------------------------------------------------//module_init(init_mc_pcmcia_cs);//----------------------------------------------------------------------------//// module_exit() //// ////----------------------------------------------------------------------------//module_exit(exit_mc_pcmcia_cs);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?