⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcan_pccard-2.6.16.c

📁 linux下的CAN BUS驱动代码。适合在arm平台使用。
💻 C
字号:
//****************************************************************************// Copyright (C) 2006-2007  PEAK System-Technik GmbH//// linux@peak-system.com// www.peak-system.com//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)//// Major contributions by://                Edouard Tisserant (edouard.tisserant@lolitech.fr) XENOMAI//                Laurent Bessard   (laurent.bessard@lolitech.fr)   XENOMAI//                Oliver Hartkopp   (oliver.hartkopp@volkswagen.de) socketCAN//                     //****************************************************************************//***************************************************************************//// system dependend parts to handle pcan-pccard// special code for kernels less and equal than 2.6.16//// $Id: pcan_pccard-2.6.16.c 465 2007-02-23 21:41:18Z ohartkopp $////****************************************************************************  //****************************************************************************// LOCALS#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)static dev_link_t *pccard_card_list = NULL;static dev_info_t  pccard_info      = DEVICE_NAME;#endif//****************************************************************************// CODE#ifdef LINUX_24static void cs_error(client_handle_t handle, int func, int ret){  error_info_t err = { func, ret };  CardServices(ReportError, handle, &err);}#endif//****************************************************************************// is called at CARD_REMOVALstatic int pccard_plugout(dev_link_t *link){  PCAN_PCCARD *card = link->priv;      DPRINTK(KERN_DEBUG "%s: pccard_plugout()\n", DEVICE_NAME);    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)  if (link->open)   {    int i;        printk(KERN_INFO "%s: release postponed since device is still used!\n", DEVICE_NAME);    link->state |= DEV_STALE_CONFIG;        // mark all associated channels as plugged out    for (i = 0; i < PCCARD_CHANNELS; i++)      if (card->dev[i])        card->dev[i]->ucPhysicallyInstalled = 0;             return -EBUSY;  }  #endif  link->state &= ~DEV_PRESENT;    if (link->state & DEV_CONFIG)  {        pccard_release_all_devices(card);            // release pcmcia driver part    link->dev  = NULL;    pcmcia_release_configuration(link->handle);    pcmcia_release_io(link->handle, &link->io);    pcmcia_release_irq(link->handle, &link->irq);        link->state &= ~DEV_CONFIG;  }    DPRINTK(KERN_DEBUG "%s: pccard_plugout() is OK\n", DEVICE_NAME);  return 0;}//****************************************************************************// is called at CARD_INSERTION or startup with already inserted cardstatic int pccard_plugin(dev_link_t *link){  client_handle_t handle = link->handle;  tuple_t   tuple;  cisdata_t buf[CISTPL_END + 1];  cisparse_t parse;  config_info_t conf;  cistpl_vers_1_t *cv;  int last_ret;  int last_fn;  PCAN_PCCARD *card = NULL;    DPRINTK(KERN_DEBUG "%s: pccard_plugin()\n", DEVICE_NAME);    // show manufacturer string in log  CS_PREPARE(CISTPL_VERS_1);  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));  CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));  cv = &parse.version_1;  printk(KERN_INFO "%s: %s %s %s %s\n", DEVICE_NAME, &cv->str[cv->ofs[0]], &cv->str[cv->ofs[1]],                                                      &cv->str[cv->ofs[2]], &cv->str[cv->ofs[3]]);  // specify what to request  CS_PREPARE(CISTPL_CONFIG);  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));  CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));    link->conf.ConfigBase = parse.config.base;  link->conf.Present    = parse.config.rmask[0];    link->state |= DEV_CONFIG;  CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;  tuple.Attributes   = 0;  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));  while (1)   {    cistpl_cftable_entry_t *cfg = &parse.cftable_entry;      if (pcmcia_get_tuple_data(handle, &tuple) != 0 || pcmcia_parse_tuple(handle, &tuple, &parse) != 0)      goto next_entry;    card = link->priv;    if (cfg->io.nwin > 0)     {      cistpl_io_t *io = &cfg->io;            link->conf.Attributes  = CONF_ENABLE_IRQ;      link->conf.IntType     = INT_MEMORY_AND_IO;      link->conf.Vcc         = cfg->vcc.param[CISTPL_POWER_VNOM] / 10000;      link->conf.Vpp1        = 0;       link->conf.Vpp2        = 0;       link->conf.ConfigIndex = cfg->index;      link->conf.Present     = PRESENT_OPTION | PRESENT_STATUS;            link->irq.Attributes   = IRQ_TYPE_EXCLUSIVE;      link->irq.IRQInfo1     = cfg->irq.IRQInfo1;      link->irq.IRQInfo2     = cfg->irq.IRQInfo2;      link->irq.Handler      = NULL; // we use our own handler            link->io.BasePort1     = io->win[0].base;      link->io.NumPorts1     = io->win[0].len;      link->io.Attributes1   = IO_DATA_PATH_WIDTH_8; // only this kind of access is yet supported      link->io.IOAddrLines   = io->flags &  CISTPL_IO_LINES_MASK;                   if (pcmcia_request_io(link->handle, &link->io) == 0)        break;    }    next_entry:    CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));  }    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));  CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));  DPRINTK(KERN_DEBUG "%s: pccard found: base1=0x%04x, size=%d, irq=%d\n", DEVICE_NAME, link->io.BasePort1, link->io.NumPorts1, link->irq.AssignedIRQ);  // init (cardmgr) devices associated with that card (is that necessary?)  card->node.major = pcan_drv.nMajor;  card->node.minor = PCCARD_MINOR_BASE;  strcpy(card->node.dev_name, DEVICE_NAME);  link->dev = &card->node;    // create device descriptors associated with the card - get relevant parts to get independend from dev_link_t  card->basePort  = link->io.BasePort1;   card->commonIrq = link->irq.AssignedIRQ;  last_ret = pccard_create_all_devices(card);  if (last_ret)    goto fail;    link->state &= ~DEV_CONFIG_PENDING;  return 0;      cs_failed:  cs_error(link->handle, last_fn, last_ret);    fail:  // remove card virtually  pccard_plugout(link);    link->state &= ~DEV_CONFIG_PENDING;    DPRINTK(KERN_DEBUG "%s: pccard_plugin() failed!\n", DEVICE_NAME);  return -ENODEV;} // pccard_plugin()//****************************************************************************// detach entry#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)static void pccard_detach(dev_link_t *link){  dev_link_t **plink;    DPRINTK(KERN_DEBUG "%s: pccard_detach()\n", DEVICE_NAME);    // test if the link is part of the linked list of pccard devices  for (plink = &pccard_card_list; *plink; plink = &(*plink)->next)    if (*plink == link)      break;  if (*plink == NULL)    return;      // do not finish stale config  if (link->state & DEV_STALE_CONFIG)     return;    // un-register  if (link->handle)  {    int ret;        ret = pcmcia_deregister_client(link->handle);    if (ret != CS_SUCCESS)      cs_error(link->handle, DeregisterClient, ret);    else      link->handle = NULL;  }    // unlink from list  *plink = link->next;  if (link->priv)  {    DPRINTK(KERN_DEBUG "%s: kfree(PCAN_PCCARD=0x%p)\n", DEVICE_NAME, link->priv);    kfree(link->priv);    link->priv = NULL;  }}#else static void pccard_detach(struct pcmcia_device *pcmcia_dev){  dev_link_t *link = dev_to_instance(pcmcia_dev);    DPRINTK(KERN_DEBUG "%s: pccard_detach()\n", DEVICE_NAME);    // finish pending work  if (link->priv)  {    pccard_plugout(link);        DPRINTK(KERN_DEBUG "%s: kfree(PCAN_PCCARD=0x%p)\n", DEVICE_NAME, link->priv);    kfree(link->priv);    link->priv = NULL;  }}#endif//****************************************************************************// attach entry#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)static int pccard_event(event_t event, int priority, event_callback_args_t *args);static dev_link_t *pccard_attach(void)#elsestatic int pccard_probe(struct pcmcia_device *pcmcia_dev)#endif{  PCAN_PCCARD *card;  dev_link_t     *link = NULL;  int ret = 0;  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)  client_reg_t   client_reg;  #endif    DPRINTK(KERN_DEBUG "%s: pccard_probe or .._attach()\n", DEVICE_NAME);    // allocate a device structure  card = (PCAN_PCCARD *)kmalloc(sizeof(PCAN_PCCARD), GFP_KERNEL);  DPRINTK(KERN_DEBUG "%s: kmalloc() = 0x%p\n", DEVICE_NAME, card);  if (card == NULL)  {    DPRINTK(KERN_DEBUG "%s: can't allocate card memory\n", DEVICE_NAME);    ret = -ENOMEM;    goto fail;  }    memset(card, 0, sizeof(*card));      // init pcmcia card specific parts  link          = &card->link;  link->priv    = card;  link->state   = 0;    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)  // insert into linked list of pccard devices - current lonly element  link->next        = pccard_card_list;  pccard_card_list  = link;    // register client to card services  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)  client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |                   CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |                   CS_EVENT_PM_SUSPEND     | CS_EVENT_PM_RESUME;  client_reg.event_handler = &pccard_event;  #endif  client_reg.dev_info   = &pccard_info;  client_reg.Version    = 0x0210; // version 2.1  client_reg.event_callback_args.client_data = link;   ret = pcmcia_register_client(&link->handle, &client_reg);  if ((ret != CS_SUCCESS) || ((card->dev[0] == NULL) && (card->dev[1] == NULL)))  {    cs_error(link->handle, RegisterClient, ret);    pccard_detach(link);    link = NULL;    goto fail;  }    fail:  if (link != NULL)  {    DPRINTK(KERN_DEBUG "%s: pccard_attach() is OK\n", DEVICE_NAME);  }    return link;  #else  link->handle = pcmcia_dev;  pcmcia_dev->instance = link;    pccard_plugin(link);    fail:  DPRINTK(KERN_DEBUG "%s: pccard_probe() = %d\n", DEVICE_NAME, ret);  return ret;  #endif}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)//****************************************************************************// is called at each card state changestatic int pccard_event(event_t event, int priority, event_callback_args_t *args){  dev_link_t     *link = (dev_link_t *)args->client_data;  DPRINTK(KERN_DEBUG "%s: pccard_event(%d)\n", DEVICE_NAME, event);    switch (event)  {    case CS_EVENT_EJECTION_REQUEST:    break;        case CS_EVENT_CARD_INSERTION:    pccard_plugin(link);    break;        case CS_EVENT_CARD_REMOVAL:    pccard_plugout(link);    break;        case CS_EVENT_PM_SUSPEND:    case CS_EVENT_PM_RESUME:    break;        case CS_EVENT_RESET_PHYSICAL:    break;        case CS_EVENT_CARD_RESET:    break;      default:    break;  }     return 0;}static void pcan_unlink_pccard(void){  dev_link_t *link;  DPRINTK(KERN_DEBUG "%s: pcan_unlink_pccard()\n", DEVICE_NAME);  // remove rest of linked (stale) devices   for (link = pccard_card_list; link; )  {    dev_link_t *tmp_link = link;    link = link->next;    pccard_plugout(tmp_link);    if (tmp_link->handle)      pcmcia_deregister_client(tmp_link->handle);    // free and remove from list    if (tmp_link->priv)    {      DPRINTK(KERN_DEBUG "%s: kfree(PCAN_PCCARD=0x%p)\n", DEVICE_NAME, tmp_link->priv);      kfree(tmp_link->priv);      tmp_link->priv = NULL;    }  }}#elsestatic int pccard_suspend(struct pcmcia_device *pcmcia_dev){  DPRINTK(KERN_DEBUG "%s: pccard_suspend()\n", DEVICE_NAME);  return 0;}static int pccard_resume(struct pcmcia_device *pcmcia_dev){  DPRINTK(KERN_DEBUG "%s: pccard_resume()\n", DEVICE_NAME);  return 0;}#endif// fin

⌨️ 快捷键说明

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