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

📄 synclink_cs.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
MODULE_PARM(irq_mask, "i");MODULE_PARM(irq_list, "1-4i");MODULE_PARM(break_on_load,"i");MODULE_PARM(ttymajor,"i");MODULE_PARM(cuamajor,"i");MODULE_PARM(debug_level,"i");MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifstatic char *driver_name = "SyncLink PC Card driver";static char *driver_version = "$Revision: 3.10 $";static struct tty_driver serial_driver, callout_driver;static int serial_refcount;/* number of characters left in xmit buffer before we ask for more */#define WAKEUP_CHARS 256static void mgslpc_change_params(MGSLPC_INFO *info);static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);static struct tty_struct *serial_table[MAX_DEVICE_COUNT];static struct termios *serial_termios[MAX_DEVICE_COUNT];static struct termios *serial_termios_locked[MAX_DEVICE_COUNT];#ifndef MIN#define MIN(a,b)	((a) < (b) ? (a) : (b))#endif/* PCMCIA prototypes */static void mgslpc_config(dev_link_t *link);static void mgslpc_release(u_long arg);static int  mgslpc_event(event_t event, int priority,			 event_callback_args_t *args);static dev_link_t *mgslpc_attach(void);static void mgslpc_detach(dev_link_t *);static dev_info_t dev_info = "synclink_cs";static dev_link_t *dev_list = NULL;static void cs_error(client_handle_t handle, int func, int ret){    error_info_t err = { func, ret };    CardServices(ReportError, handle, &err);}/* * 1st function defined in .text section. Calling this function in * init_module() followed by a breakpoint allows a remote debugger * (gdb) to get the .text address for the add-symbol-file command. * This allows remote debugging of dynamically loadable modules. */static void* mgslpc_get_text_ptr(void);static void* mgslpc_get_text_ptr() {return mgslpc_get_text_ptr;}/** * line discipline callback wrappers * * The wrappers maintain line discipline references * while calling into the line discipline. * * ldisc_receive_buf  - pass receive data to line discipline */static void ldisc_receive_buf(struct tty_struct *tty,			      const __u8 *data, char *flags, int count){	struct tty_ldisc *ld;	if (!tty)		return;	ld = tty_ldisc_ref(tty);	if (ld) {		if (ld->receive_buf)			ld->receive_buf(tty, data, flags, count);		tty_ldisc_deref(ld);	}}static dev_link_t *mgslpc_attach(void){    MGSLPC_INFO *info;    dev_link_t *link;    client_reg_t client_reg;    int ret, i;        if (debug_level >= DEBUG_LEVEL_INFO)	    printk("mgslpc_attach\n");	    info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);    if (!info) {	    printk("Error can't allocate device instance data\n");	    return NULL;    }    memset(info, 0, sizeof(MGSLPC_INFO));    info->magic = MGSLPC_MAGIC;    info->task.sync = 0;    info->task.routine = bh_handler;    info->task.data    = info;    info->max_frame_size = 4096;    info->close_delay = 5*HZ/10;    info->closing_wait = 30*HZ;    init_waitqueue_head(&info->open_wait);    init_waitqueue_head(&info->close_wait);    init_waitqueue_head(&info->status_event_wait_q);    init_waitqueue_head(&info->event_wait_q);    spin_lock_init(&info->lock);    spin_lock_init(&info->netlock);    memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));    info->idle_mode = HDLC_TXIDLE_FLAGS;		    info->imra_value = 0xffff;    info->imrb_value = 0xffff;    info->pim_value = 0xff;    link = &info->link;    link->priv = info;        /* Initialize the dev_link_t structure */    link->release.function = &mgslpc_release;    link->release.data = (u_long)link;    /* Interrupt setup */    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;    link->irq.IRQInfo1   = IRQ_INFO2_VALID | IRQ_LEVEL_ID;    if (irq_list[0] == -1)	    link->irq.IRQInfo2 = irq_mask;    else	    for (i = 0; i < 4; i++)		    link->irq.IRQInfo2 |= 1 << irq_list[i];    link->irq.Handler = NULL;        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 = &mgslpc_event;    client_reg.Version = 0x0210;    client_reg.event_callback_args.client_data = link;    ret = CardServices(RegisterClient, &link->handle, &client_reg);    if (ret != CS_SUCCESS) {	    cs_error(link->handle, RegisterClient, ret);	    mgslpc_detach(link);	    return NULL;    }    mgslpc_add_device(info);    memset(serial_table,0,sizeof(struct tty_struct*)*MAX_DEVICE_COUNT);    memset(serial_termios,0,sizeof(struct termios*)*MAX_DEVICE_COUNT);    memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_DEVICE_COUNT);		    info->callout_termios = callout_driver.init_termios;    info->normal_termios  = serial_driver.init_termios;    return link;}/* Card has been inserted. */#define CS_CHECK(fn, args...) \while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failedstatic void mgslpc_config(dev_link_t *link){    client_handle_t handle = link->handle;    MGSLPC_INFO *info = link->priv;    tuple_t tuple;    cisparse_t parse;    int last_fn, last_ret;    u_char buf[64];    config_info_t conf;    cistpl_cftable_entry_t dflt = { 0 };    cistpl_cftable_entry_t *cfg;        if (debug_level >= DEBUG_LEVEL_INFO)	    printk("mgslpc_config(0x%p)\n", link);    /* read CONFIG tuple to find its configuration registers */    tuple.DesiredTuple = CISTPL_CONFIG;    tuple.Attributes = 0;    tuple.TupleData = buf;    tuple.TupleDataMax = sizeof(buf);    tuple.TupleOffset = 0;    CS_CHECK(GetFirstTuple, handle, &tuple);    CS_CHECK(GetTupleData, handle, &tuple);    CS_CHECK(ParseTuple, handle, &tuple, &parse);    link->conf.ConfigBase = parse.config.base;    link->conf.Present = parse.config.rmask[0];        /* Configure card */    link->state |= DEV_CONFIG;    /* Look up the current Vcc */    CS_CHECK(GetConfigurationInfo, handle, &conf);    link->conf.Vcc = conf.Vcc;    /* get CIS configuration entry */    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;    CS_CHECK(GetFirstTuple, handle, &tuple);    cfg = &(parse.cftable_entry);    CS_CHECK(GetTupleData, handle, &tuple);    CS_CHECK(ParseTuple, handle, &tuple, &parse);    if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;    if (cfg->index == 0)	    goto cs_failed;    link->conf.ConfigIndex = cfg->index;    link->conf.Attributes |= CONF_ENABLE_IRQ;	    /* IO window settings */    link->io.NumPorts1 = 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;	    CS_CHECK(RequestIO, link->handle, &link->io);    }    link->conf.Attributes = CONF_ENABLE_IRQ;    link->conf.Vcc = 50;    link->conf.IntType = INT_MEMORY_AND_IO;    link->conf.ConfigIndex = 8;    link->conf.Present = PRESENT_OPTION;        link->irq.Attributes |= IRQ_HANDLE_PRESENT;    link->irq.Handler     = mgslpc_isr;    link->irq.Instance    = info;    CS_CHECK(RequestIRQ, link->handle, &link->irq);    CS_CHECK(RequestConfiguration, link->handle, &link->conf);    info->io_base = link->io.BasePort1;    info->irq_level = link->irq.AssignedIRQ;    /* add to linked list of devices */    sprintf(info->node.dev_name, "mgslpc0");    info->node.major = info->node.minor = 0;    link->dev = &info->node;    printk(KERN_INFO "%s: index 0x%02x:",	   info->node.dev_name, link->conf.ConfigIndex);    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);    printk("\n");        link->state &= ~DEV_CONFIG_PENDING;    return;cs_failed:    cs_error(link->handle, last_fn, last_ret);    mgslpc_release((u_long)link);}/* Card has been removed. * Unregister device and release PCMCIA configuration. * If device is open, postpone until it is closed. */static void mgslpc_release(u_long arg){    dev_link_t *link = (dev_link_t *)arg;    if (debug_level >= DEBUG_LEVEL_INFO)	    printk("mgslpc_release(0x%p)\n", link);    if (link->open) {	    if (debug_level >= DEBUG_LEVEL_INFO)		    printk("synclink_cs: release postponed, '%s' still open\n",			   link->dev->dev_name);	    link->state |= DEV_STALE_CONFIG;	    return;    }    /* Unlink the device chain */    link->dev = NULL;    link->state &= ~DEV_CONFIG;    CardServices(ReleaseConfiguration, link->handle);    if (link->io.NumPorts1)	    CardServices(ReleaseIO, link->handle, &link->io);    if (link->irq.AssignedIRQ)	    CardServices(ReleaseIRQ, link->handle, &link->irq);    if (link->state & DEV_STALE_LINK)	    mgslpc_detach(link);}static void mgslpc_detach(dev_link_t *link){    dev_link_t **linkp;    if (debug_level >= DEBUG_LEVEL_INFO)	    printk("mgslpc_detach(0x%p)\n", link);        /* find device */    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)	    if (*linkp == link) break;    if (*linkp == NULL)	    return;    if (link->state & DEV_CONFIG) {	    /* device is configured/active, mark it so when	     * release() is called a proper detach() occurs.	     */	    if (debug_level >= DEBUG_LEVEL_INFO)		    printk(KERN_DEBUG "synclinkpc: detach postponed, '%s' "			   "still locked\n", link->dev->dev_name);	    link->state |= DEV_STALE_LINK;	    return;    }    /* Break the link with Card Services */    if (link->handle)	    CardServices(DeregisterClient, link->handle);        /* Unlink device structure, and free it */    *linkp = link->next;    mgslpc_remove_device((MGSLPC_INFO *)link->priv);}static int mgslpc_event(event_t event, int priority,			event_callback_args_t *args){    dev_link_t *link = args->client_data;    MGSLPC_INFO *info = link->priv;        if (debug_level >= DEBUG_LEVEL_INFO)	    printk("mgslpc_event(0x%06x)\n", event);        switch (event) {    case CS_EVENT_CARD_REMOVAL:	    link->state &= ~DEV_PRESENT;	    if (link->state & DEV_CONFIG) {		    ((MGSLPC_INFO *)link->priv)->stop = 1;		    mod_timer(&link->release, jiffies + HZ/20);	    }	    break;    case CS_EVENT_CARD_INSERTION:	    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;	    info->bus = args->bus;	    mgslpc_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 */	    info->stop = 1;	    if (link->state & DEV_CONFIG)		    CardServices(ReleaseConfiguration, link->handle);	    break;    case CS_EVENT_PM_RESUME:	    link->state &= ~DEV_SUSPEND;	    /* Fall through... */    case CS_EVENT_CARD_RESET:	    if (link->state & DEV_CONFIG)		    CardServices(RequestConfiguration, link->handle, &link->conf);	    info->stop = 0;	    break;    }    return 0;}static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,					kdev_t device, const char *routine){#ifdef MGSLPC_PARANOIA_CHECK	static const char *badmagic =		"Warning: bad magic number for mgsl struct (%s) in %s\n";	static const char *badinfo =		"Warning: null mgslpc_info for (%s) in %s\n";	if (!info) {		printk(badinfo, kdevname(device), routine);		return 1;	}	if (info->magic != MGSLPC_MAGIC) {		printk(badmagic, kdevname(device), routine);		return 1;	}#else	if (!info)		return 1;#endif	return 0;}#define CMD_RXFIFO      BIT7	// release current rx FIFO#define CMD_RXRESET     BIT6	// receiver reset#define CMD_RXFIFO_READ BIT5#define CMD_START_TIMER BIT4#define CMD_TXFIFO      BIT3	// release current tx FIFO#define CMD_TXEOM       BIT1	// transmit end message#define CMD_TXRESET     BIT0	// transmit resetstatic BOOLEAN wait_command_complete(MGSLPC_INFO *info, unsigned char channel) {	int i = 0;	unsigned char status;	/* wait for command completion */ 	while ((status = read_reg(info, (unsigned char)(channel+STAR)) & BIT2)) {		udelay(1);		if (i++ == 1000)			return FALSE;	}	return TRUE;}static void issue_command(MGSLPC_INFO *info, unsigned char channel, unsigned char cmd) {	wait_command_complete(info, channel);	write_reg(info, (unsigned char) (channel + CMDR), cmd);}static void tx_pause(struct tty_struct *tty){	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;	unsigned long flags;		if (mgslpc_paranoia_check(info, tty->device, "tx_pause"))		return;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("tx_pause(%s)\n",info->device_name);				spin_lock_irqsave(&info->lock,flags);	if (info->tx_enabled)	 	tx_stop(info);	spin_unlock_irqrestore(&info->lock,flags);}static void tx_release(struct tty_struct *tty){	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;	unsigned long flags;		if (mgslpc_paranoia_check(info, tty->device, "tx_release"))		return;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("tx_release(%s)\n",info->device_name);				spin_lock_irqsave(&info->lock,flags);	if (!info->tx_enabled)	 	tx_start(info);	spin_unlock_irqrestore(&info->lock,flags);}/* Return next bottom half action to perform. * or 0 if nothing to do. */int bh_action(MGSLPC_INFO *info){	unsigned long flags;	int rc = 0;		spin_lock_irqsave(&info->lock,flags);	if (info->pending_bh & BH_RECEIVE) {		info->pending_bh &= ~BH_RECEIVE;		rc = BH_RECEIVE;	} else if (info->pending_bh & BH_TRANSMIT) {		info->pending_bh &= ~BH_TRANSMIT;		rc = BH_TRANSMIT;	} else if (info->pending_bh & BH_STATUS) {

⌨️ 快捷键说明

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