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 + -
显示快捷键?