mc_pcmcia_cs.c.svn-base

来自「canpie 一个can bus的协议栈 - CAN interface fo」· SVN-BASE 代码 · 共 633 行 · 第 1/2 页

SVN-BASE
633
字号
//****************************************************************************//// File:          mc_pcmcia_cs.c                                              //// Description:   CANpie hardware abstraction layer (HAL)                     //// Author:        Uwe Koppe                                                   //// e-mail:        koppe@microcontrol.net                                      ////                                                                            ////============================================================================//// This program is free software; you can redistribute it and/or modify       //// it under the terms of the GNU Lesser General Public License as published   //// by the Free Software Foundation; either version 2.1 of the License, or     //// (at your option) any later version.                                        ////============================================================================////                                                                            //// Date        History                                                        //// ----------  -------------------------------------------------------------- //// 29.07.2003  Initial version                                                ////                                                                            ////****************************************************************************////------------------------------------------------------------------------------// CVS version information:// $Id: mc_pcmcia_cs.c,v 1.3 2006/04/25 20:03:43 microcontrol Exp $//------------------------------------------------------------------------------/*----------------------------------------------------------------------------*\** Include files                                                              ****                                                                            **\*----------------------------------------------------------------------------*/#include <linux/kernel.h>#include <linux/module.h>           // must be included in every kernel module#include <linux/init.h>#include <linux/ioport.h>           // request_region() / release_region()#include <linux/interrupt.h>        // request_irq() / free_irq()#include <linux/sched.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/timer.h>#include <asm/io.h>#include <asm/system.h>#include "mc_pcmcia_cs.h"/*====================================================================*//* Parameters that can be set with 'insmod' */MODULE_AUTHOR("Uwe Koppe <koppe@microcontrol.net>");MODULE_DESCRIPTION("Driver for MicroControl PCMCIA CAN interface");MODULE_LICENSE("GPL");static unsigned short   auwMcPcmciaPortS[2] = {0, 1};static int              slMcPcmciaPortCntS = 2;module_param_array_named(port, auwMcPcmciaPortS, ushort, &slMcPcmciaPortCntS, 0);MODULE_PARM_DESC(port, " Port number");/*----------------------------------------------------------------------------*\** Debugging                                                                  ****                                                                            **\*----------------------------------------------------------------------------*/#ifdef  CP_DEBUGunsigned short    uwMcPcmciaDebugG = 2;module_param_named(debug, uwMcPcmciaDebugG, ushort, 0);MODULE_PARM_DESC(debug, " Set debug level, 0=quiet .. 5=noisy");#endif/*====================================================================*//*   The event() function is this driver's Card Services event handler.   It will be called by Card Services when an appropriate card status   event is received.  The config() and release() entry points are   used to configure or release a socket, in response to card   insertion and ejection events.  They are invoked from the dummy   event handler. */static void mc_pcmcia_config(dev_link_t *link);#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) static void mc_pcmcia_detach(struct pcmcia_device *p_dev);#elsestatic void mc_pcmcia_detach(dev_link_t *link);#endifstatic int  mc_pcmcia_event(event_t event, int priority, event_callback_args_t *args);static void mc_pcmcia_release(dev_link_t *link);//-------------------------------------------------------------------// The dev_info variable is the "key" that is used to match up this// device driver with appropriate cards, through the card // configuration database.//static dev_info_t dev_info = CP_DRV_NAME;//-------------------------------------------------------------------// A linked list of "instances" of the dummy device.  Each actual// PCMCIA card corresponds to one device instance, and is described// by one dev_link_t structure (defined in ds.h).//static dev_link_t *dev_list = NULL; //----------------------------------------------------------------------------//// cs_error()                                                                 //// Handle errors of the Card Service                                          ////----------------------------------------------------------------------------///*static void cs_error(client_handle_t handle, int func, int ret){    error_info_t err = { func, ret };    // CardServices(ReportError, handle, &err);}*///----------------------------------------------------------------------------//// canpie_attach()                                                            //// This function creates an "instance" of the driver, allocating local data   //// structures for one device.  The device is registered with Card Services.   //// The dev_link structure is initialized, but we don't actually configure the //// card at this point -- we wait until we receive a card insertion event.     ////----------------------------------------------------------------------------//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)static int mc_pcmcia_attach(struct pcmcia_device *p_dev)#elsestatic dev_link_t * mc_pcmcia_attach(void)#endif{   _TsMcPcmciaInfo * info;   dev_link_t *      link;   client_reg_t      client_reg;   int               ret;       PK_DBG("mc_pcmcia_attach()");   //-------------------------------------------   // Create new PCMCIA CAN device   //   info = kmalloc(sizeof(*info), GFP_KERNEL);   if (!info) return -ENOMEM;   memset(info, 0, sizeof(*info));   link = &info->link; link->priv = info;         link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;   link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;   link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;   link->irq.IRQInfo1   = 0;  // No IRQ supported for this card       link->conf.Attributes = 0;   link->conf.Vcc = 50;   link->conf.IntType = INT_MEMORY_AND_IO;       //----------------------------------------------------------------   // Register with Card Services    //   link->next = dev_list;   dev_list = link;   client_reg.dev_info = &dev_info;   client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;   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 = &mc_pcmcia_event;   client_reg.Version = 0x0210;   client_reg.event_callback_args.client_data = link;#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)   link->handle = p_dev;   p_dev->instance = link;   link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;   mc_pcmcia_config(link);   return 0;#else	   ret = pcmcia_register_client(&link->handle, &client_reg);   if (ret != CS_SUCCESS)    {      cs_error(link->handle, RegisterClient, ret);      mc_pcmcia_detach(link);      return NULL;   }   return link;#endif    }//----------------------------------------------------------------------------//// mc_pcmcia_detach()                                                         //// This deletes a driver "instance".  The device is de-registered with Card   //// Services.  If it has been released, all local data structures are freed.   //// Otherwise, the structures will be freed when the device is released.       ////                                                                            ////----------------------------------------------------------------------------//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)static void mc_pcmcia_detach(struct pcmcia_device *p_dev){   dev_link_t *link = dev_to_instance(p_dev);   link->state &= ~DEV_PRESENT;	   mc_pcmcia_release(link);}  #elsestatic void mc_pcmcia_detach(dev_link_t *link){   dev_link_t **linkp;   PK_DBG("mc_pcmcia_detach()");   if(link == NULL) return;   //----------------------------------------------------------------   // Locate device structure   //   for(linkp = &dev_list; *linkp; linkp = &(*linkp)->next)   {      if(*linkp == link) break;      if(*linkp == NULL) return;   }   //----------------------------------------------------------------   // If the device is currently configured and active, we won't   // actually delete it yet.  Instead, it is marked so that when   // the release() function is called, that will trigger a proper   //  detach().   //   if(link->state & DEV_CONFIG)   {      #ifdef PCMCIA_DEBUG      printk(KERN_DEBUG "canpie_cs() detach postponed, '%s' still locked\n",             link->dev->dev_name);      #endif      link->state |= DEV_STALE_LINK;      return;   }   //----------------------------------------------------------------   // Break the link with Card Services   //   if(link->handle)   {      pcmcia_deregister_client(link->handle);          //--- Unlink device structure, and free it ---------------      *linkp = link->next;      //--- This points to the mc_pcmcia_info_t struct ------      kfree(link->priv);   }}#endif#define CS_CHECK(fn, ret) \do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)//----------------------------------------------------------------------------//// mc_pcmcia_config()                                                         //// This function 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.                                                   ////                                                                            ////----------------------------------------------------------------------------//void mc_pcmcia_config(dev_link_t *link){   client_handle_t         handle = link->handle;   _TsMcPcmciaInfo *       dev = link->priv;   tuple_t                 tuple;   u_short                 buf[128];   cisparse_t              parse;   config_info_t           conf;   cistpl_cftable_entry_t *cfg = &parse.cftable_entry;   cistpl_cftable_entry_t  dflt = { 0 };   int last_ret, last_fn;          PK_DBG("mc_pcmcia_config");       tuple.TupleData      = (cisdata_t *)buf;   tuple.TupleOffset    = 0;    tuple.TupleDataMax   = 255;   tuple.Attributes     = 0;   tuple.DesiredTuple   = 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];       //----------------------------------------------------------------   // Configure card   //   link->state |= DEV_CONFIG;   //----------------------------------------------------------------   // Lookup the current Vcc   //   CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));

⌨️ 快捷键说明

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