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

📄 synclink_cs.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	return mgslpc_get_text_ptr;}/** * line discipline callback wrappers * * The wrappers maintain line discipline references * while calling into the line discipline. * * ldisc_flush_buffer - flush line discipline receive buffers * ldisc_receive_buf  - pass receive data to line discipline */static void ldisc_flush_buffer(struct tty_struct *tty){	struct tty_ldisc *ld = tty_ldisc_ref(tty);	if (ld) {		if (ld->flush_buffer)			ld->flush_buffer(tty);		tty_ldisc_deref(ld);	}}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 int mgslpc_probe(struct pcmcia_device *link){    MGSLPC_INFO *info;    int ret;    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 -ENOMEM;    }    memset(info, 0, sizeof(MGSLPC_INFO));    info->magic = MGSLPC_MAGIC;    INIT_WORK(&info->task, bh_handler, 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;    info->p_dev = link;    link->priv = info;    /* Initialize the struct pcmcia_device structure */    /* Interrupt setup */    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;    link->irq.IRQInfo1   = IRQ_LEVEL_ID;    link->irq.Handler = NULL;    link->conf.Attributes = 0;    link->conf.IntType = INT_MEMORY_AND_IO;    ret = mgslpc_config(link);    if (ret)	    return ret;    mgslpc_add_device(info);    return 0;}/* Card has been inserted. */#define CS_CHECK(fn, ret) \do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)static int mgslpc_config(struct pcmcia_device *link){    MGSLPC_INFO *info = link->priv;    tuple_t tuple;    cisparse_t parse;    int last_fn, last_ret;    u_char buf[64];    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, pcmcia_get_first_tuple(link, &tuple));    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));    link->conf.ConfigBase = parse.config.base;    link->conf.Present = parse.config.rmask[0];    /* get CIS configuration entry */    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));    cfg = &(parse.cftable_entry);    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &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, pcmcia_request_io(link, &link->io));    }    link->conf.Attributes = CONF_ENABLE_IRQ;    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, pcmcia_request_irq(link, &link->irq));    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &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_node = &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");    return 0;cs_failed:    cs_error(link, last_fn, last_ret);    mgslpc_release((u_long)link);    return -ENODEV;}/* 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){	struct pcmcia_device *link = (struct pcmcia_device *)arg;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("mgslpc_release(0x%p)\n", link);	pcmcia_disable_device(link);}static void mgslpc_detach(struct pcmcia_device *link){	if (debug_level >= DEBUG_LEVEL_INFO)		printk("mgslpc_detach(0x%p)\n", link);	((MGSLPC_INFO *)link->priv)->stop = 1;	mgslpc_release((u_long)link);	mgslpc_remove_device((MGSLPC_INFO *)link->priv);}static int mgslpc_suspend(struct pcmcia_device *link){	MGSLPC_INFO *info = link->priv;	info->stop = 1;	return 0;}static int mgslpc_resume(struct pcmcia_device *link){	MGSLPC_INFO *info = link->priv;	info->stop = 0;	return 0;}static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,					char *name, 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, name, routine);		return 1;	}	if (info->magic != MGSLPC_MAGIC) {		printk(badmagic, name, 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;	/* wait for command completion */ 	while (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->name, "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->name, "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. */static 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) {		info->pending_bh &= ~BH_STATUS;		rc = BH_STATUS;	}	if (!rc) {		/* Mark BH routine as complete */		info->bh_running   = 0;		info->bh_requested = 0;	}		spin_unlock_irqrestore(&info->lock,flags);		return rc;}void bh_handler(void* Context){	MGSLPC_INFO *info = (MGSLPC_INFO*)Context;	int action;	if (!info)		return;			if (debug_level >= DEBUG_LEVEL_BH)		printk( "%s(%d):bh_handler(%s) entry\n",			__FILE__,__LINE__,info->device_name);		info->bh_running = 1;	while((action = bh_action(info)) != 0) {			/* Process work item */		if ( debug_level >= DEBUG_LEVEL_BH )			printk( "%s(%d):bh_handler() work item action=%d\n",				__FILE__,__LINE__,action);		switch (action) {				case BH_RECEIVE:			while(rx_get_frame(info));			break;		case BH_TRANSMIT:			bh_transmit(info);			break;		case BH_STATUS:			bh_status(info);			break;		default:			/* unknown work item ID */			printk("Unknown work item ID=%08X!\n", action);			break;		}	}	if (debug_level >= DEBUG_LEVEL_BH)		printk( "%s(%d):bh_handler(%s) exit\n",			__FILE__,__LINE__,info->device_name);}void bh_transmit(MGSLPC_INFO *info){	struct tty_struct *tty = info->tty;	if (debug_level >= DEBUG_LEVEL_BH)		printk("bh_transmit() entry on %s\n", info->device_name);	if (tty) {		tty_wakeup(tty);		wake_up_interruptible(&tty->write_wait);	}}void bh_status(MGSLPC_INFO *info){	info->ri_chkcount = 0;	info->dsr_chkcount = 0;	info->dcd_chkcount = 0;	info->cts_chkcount = 0;}/* eom: non-zero = end of frame */ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom){	unsigned char data[2];	unsigned char fifo_count, read_count, i;	RXBUF *buf = (RXBUF*)(info->rx_buf + (info->rx_put * info->rx_buf_size));	if (debug_level >= DEBUG_LEVEL_ISR)		printk("%s(%d):rx_ready_hdlc(eom=%d)\n",__FILE__,__LINE__,eom);		if (!info->rx_enabled)		return;	if (info->rx_frame_count >= info->rx_buf_count) {		/* no more free buffers */		issue_command(info, CHA, CMD_RXRESET);		info->pending_bh |= BH_RECEIVE;		info->rx_overflow = 1;		info->icount.buf_overrun++;		return;	}	if (eom) {		/* end of frame, get FIFO count from RBCL register */ 		if (!(fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f)))			fifo_count = 32;	} else		fifo_count = 32;		do {		if (fifo_count == 1) {			read_count = 1;			data[0] = read_reg(info, CHA + RXFIFO);		} else {			read_count = 2;			*((unsigned short *) data) = read_reg16(info, CHA + RXFIFO);		}		fifo_count -= read_count;		if (!fifo_count && eom)			buf->status = data[--read_count];		for (i = 0; i < read_count; i++) {			if (buf->count >= info->max_frame_size) {				/* frame too large, reset receiver and reset current buffer */				issue_command(info, CHA, CMD_RXRESET);				buf->count = 0;				return;			}			*(buf->data + buf->count) = data[i];			buf->count++;		}	} while (fifo_count);	if (eom) {		info->pending_bh |= BH_RECEIVE;		info->rx_frame_count++;		info->rx_put++;		if (info->rx_put >= info->rx_buf_count)			info->rx_put = 0;	}	issue_command(info, CHA, CMD_RXFIFO);}static void rx_ready_async(MGSLPC_INFO *info, int tcd){	unsigned char data, status, flag;	int fifo_count;	int work = 0; 	struct tty_struct *tty = info->tty; 	struct mgsl_icount *icount = &info->icount;	if (tcd) {		/* early termination, get FIFO count from RBCL register */ 		fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f);		/* Zero fifo count could mean 0 or 32 bytes available.		 * If BIT5 of STAR is set then at least 1 byte is available.		 */		if (!fifo_count && (read_reg(info,CHA+STAR) & BIT5))			fifo_count = 32;	} else		fifo_count = 32;	tty_buffer_request_room(tty, fifo_count);	/* Flush received async data to receive data buffer. */ 	while (fifo_count) {

⌨️ 快捷键说明

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