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

📄 cosa.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
		schedule_timeout(30);		current->state = TASK_RUNNING;		irq = probe_irq_off(irqs);		/* Disable all IRQs from the card */		cosa_putstatus(cosa, 0);		/* Empty the received data register */		cosa_getdata8(cosa);		if (irq < 0) {			printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n",				irq, cosa->datareg);			return -1;		}		if (irq == 0) {			printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n",				cosa->datareg);		/*	return -1; */		}	}	cosa->irq = irq;	cosa->num = nr_cards;	cosa->usage = 0;	cosa->nchannels = 2;	/* FIXME: how to determine this? */	request_region(base, is_8bit(cosa)?2:4, cosa->type);	if (request_irq(cosa->irq, cosa_interrupt, 0, cosa->type, cosa))		goto bad1;	if (request_dma(cosa->dma, cosa->type)) {		free_irq(cosa->irq, cosa);bad1:		release_region(cosa->datareg,is_8bit(cosa)?2:4);		printk(KERN_NOTICE "cosa%d: allocating resources failed\n",			cosa->num);		return -1;	}		cosa->bouncebuf = kmalloc(COSA_MTU, GFP_KERNEL|GFP_DMA);	sprintf(cosa->name, "cosa%d", cosa->num);	/* Initialize the per-channel data */	cosa->chan = kmalloc(sizeof(struct channel_data)*cosa->nchannels,		GFP_KERNEL);	memset(cosa->chan, 0, sizeof(struct channel_data)*cosa->nchannels);	for (i=0; i<cosa->nchannels; i++) {		cosa->chan[i].cosa = cosa;		cosa->chan[i].num = i;		channel_init(cosa->chan+i);	}	printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",		cosa->num, cosa->id_string, cosa->type,		cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);	return nr_cards++;}/*---------- SPPP/HDLC netdevice ---------- */static void sppp_channel_init(struct channel_data *chan){	struct net_device *d;	chan->if_ptr = &chan->pppdev;	chan->pppdev.dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);	memset(chan->pppdev.dev, 0, sizeof(struct net_device));	sppp_attach(&chan->pppdev);	d=chan->pppdev.dev;	strcpy(d->name, chan->name);	d->base_addr = chan->cosa->datareg;	d->irq = chan->cosa->irq;	d->dma = chan->cosa->dma;	d->priv = chan;	d->init = NULL;	d->open = cosa_sppp_open;	d->stop = cosa_sppp_close;	d->hard_start_xmit = cosa_sppp_tx;	d->do_ioctl = cosa_sppp_ioctl;	d->get_stats = cosa_net_stats;	d->tx_timeout = cosa_sppp_timeout;	d->watchdog_timeo = TX_TIMEOUT;	if (register_netdev(d) == -1) {		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);		sppp_detach(chan->pppdev.dev);		return;	}}static void sppp_channel_delete(struct channel_data *chan){	sppp_detach(chan->pppdev.dev);	unregister_netdev(chan->pppdev.dev);}static int cosa_sppp_open(struct net_device *d){	struct channel_data *chan = d->priv;	int err, flags;	if (!(chan->cosa->firmware_status & COSA_FW_START)) {		printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",			chan->cosa->name, chan->cosa->firmware_status);		return -EPERM;	}	spin_lock_irqsave(&chan->cosa->lock, flags);	if (chan->usage != 0) {		printk(KERN_WARNING "%s: sppp_open called with usage count %d\n",			chan->name, chan->usage);		spin_unlock_irqrestore(&chan->cosa->lock, flags);		return -EBUSY;	}	chan->setup_rx = sppp_setup_rx;	chan->tx_done = sppp_tx_done;	chan->rx_done = sppp_rx_done;	chan->usage=-1;	chan->cosa->usage++;	MOD_INC_USE_COUNT;	spin_unlock_irqrestore(&chan->cosa->lock, flags);	err = sppp_open(d);	if (err) {		spin_lock_irqsave(&chan->cosa->lock, flags);		chan->usage=0;		chan->cosa->usage--;		MOD_DEC_USE_COUNT;				spin_unlock_irqrestore(&chan->cosa->lock, flags);		return err;	}	netif_start_queue(d);	cosa_enable_rx(chan);	return 0;}static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev){	struct channel_data *chan = dev->priv;	netif_stop_queue(dev);	chan->tx_skb = skb;	cosa_start_tx(chan, skb->data, skb->len);	return 0;}static void cosa_sppp_timeout(struct net_device *dev){	struct channel_data *chan = dev->priv;	if (test_bit(RXBIT, &chan->cosa->rxtx)) {		chan->stats.rx_errors++;		chan->stats.rx_missed_errors++;	} else {		chan->stats.tx_errors++;		chan->stats.tx_aborted_errors++;	}	cosa_kick(chan->cosa);	if (chan->tx_skb) {		dev_kfree_skb(chan->tx_skb);		chan->tx_skb = 0;	}	netif_wake_queue(dev);}static int cosa_sppp_close(struct net_device *d){	struct channel_data *chan = d->priv;	int flags;	netif_stop_queue(d);	sppp_close(d);	cosa_disable_rx(chan);	spin_lock_irqsave(&chan->cosa->lock, flags);	if (chan->rx_skb) {		kfree_skb(chan->rx_skb);		chan->rx_skb = 0;	}	if (chan->tx_skb) {		kfree_skb(chan->tx_skb);		chan->tx_skb = 0;	}	chan->usage=0;	chan->cosa->usage--;	MOD_DEC_USE_COUNT;	spin_unlock_irqrestore(&chan->cosa->lock, flags);	return 0;}static char *sppp_setup_rx(struct channel_data *chan, int size){	/*	 * We can safely fall back to non-dma-able memory, because we have	 * the cosa->bouncebuf pre-allocated.	 */	if (chan->rx_skb)		kfree_skb(chan->rx_skb);	chan->rx_skb = dev_alloc_skb(size);	if (chan->rx_skb == NULL) {		printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n",			chan->name);		chan->stats.rx_dropped++;		return NULL;	}	chan->pppdev.dev->trans_start = jiffies;	return skb_put(chan->rx_skb, size);}static int sppp_rx_done(struct channel_data *chan){	if (!chan->rx_skb) {		printk(KERN_WARNING "%s: rx_done with empty skb!\n",			chan->name);		chan->stats.rx_errors++;		chan->stats.rx_frame_errors++;		return 0;	}	chan->rx_skb->protocol = htons(ETH_P_WAN_PPP);	chan->rx_skb->dev = chan->pppdev.dev;	chan->rx_skb->mac.raw = chan->rx_skb->data;	chan->stats.rx_packets++;	chan->stats.rx_bytes += chan->cosa->rxsize;	netif_rx(chan->rx_skb);	chan->rx_skb = 0;	chan->pppdev.dev->last_rx = jiffies;	return 0;}/* ARGSUSED */static int sppp_tx_done(struct channel_data *chan, int size){	if (!chan->tx_skb) {		printk(KERN_WARNING "%s: tx_done with empty skb!\n",			chan->name);		chan->stats.tx_errors++;		chan->stats.tx_aborted_errors++;		return 1;	}	dev_kfree_skb_irq(chan->tx_skb);	chan->tx_skb = 0;	chan->stats.tx_packets++;	chan->stats.tx_bytes += size;	netif_wake_queue(chan->pppdev.dev);	return 1;}static struct net_device_stats *cosa_net_stats(struct net_device *dev){	struct channel_data *chan = dev->priv;	return &chan->stats;}/*---------- Character device ---------- */static void chardev_channel_init(struct channel_data *chan){	init_MUTEX(&chan->rsem);	init_MUTEX(&chan->wsem);}static ssize_t cosa_read(struct file *file,	char *buf, size_t count, loff_t *ppos){	DECLARE_WAITQUEUE(wait, current);	int flags;	struct channel_data *chan = (struct channel_data *)file->private_data;	struct cosa_data *cosa = chan->cosa;	char *kbuf;	if (!(cosa->firmware_status & COSA_FW_START)) {		printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",			cosa->name, cosa->firmware_status);		return -EPERM;	}	if (down_interruptible(&chan->rsem))		return -ERESTARTSYS;		if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {		printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);		up(&chan->rsem);		return -ENOMEM;	}	chan->rx_status = 0;	cosa_enable_rx(chan);	spin_lock_irqsave(&cosa->lock, flags);	add_wait_queue(&chan->rxwaitq, &wait);	while(!chan->rx_status) {		current->state = TASK_INTERRUPTIBLE;		spin_unlock_irqrestore(&cosa->lock, flags);		schedule();		spin_lock_irqsave(&cosa->lock, flags);		if (signal_pending(current) && chan->rx_status == 0) {			chan->rx_status = 1;			remove_wait_queue(&chan->rxwaitq, &wait);			current->state = TASK_RUNNING;			spin_unlock_irqrestore(&cosa->lock, flags);			up(&chan->rsem);			return -ERESTARTSYS;		}	}	remove_wait_queue(&chan->rxwaitq, &wait);	current->state = TASK_RUNNING;	kbuf = chan->rxdata;	count = chan->rxsize;	spin_unlock_irqrestore(&cosa->lock, flags);	up(&chan->rsem);	if (copy_to_user(buf, kbuf, count)) {		kfree(kbuf);		return -EFAULT;	}	kfree(kbuf);	return count;}static char *chrdev_setup_rx(struct channel_data *chan, int size){	/* Expect size <= COSA_MTU */	chan->rxsize = size;	return chan->rxdata;}static int chrdev_rx_done(struct channel_data *chan){	if (chan->rx_status) { /* Reader has died */		kfree(chan->rxdata);		up(&chan->wsem);	}	chan->rx_status = 1;	wake_up_interruptible(&chan->rxwaitq);	return 1;}static ssize_t cosa_write(struct file *file,	const char *buf, size_t count, loff_t *ppos){	DECLARE_WAITQUEUE(wait, current);	struct channel_data *chan = (struct channel_data *)file->private_data;	struct cosa_data *cosa = chan->cosa;	unsigned int flags;	char *kbuf;	if (!(cosa->firmware_status & COSA_FW_START)) {		printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",			cosa->name, cosa->firmware_status);		return -EPERM;	}	if (down_interruptible(&chan->wsem))		return -ERESTARTSYS;	if (count > COSA_MTU)		count = COSA_MTU;		/* Allocate the buffer */	if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) {		printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n",			cosa->name);		up(&chan->wsem);		return -ENOMEM;	}	if (copy_from_user(kbuf, buf, count)) {		up(&chan->wsem);		kfree(kbuf);		return -EFAULT;	}	chan->tx_status=0;	cosa_start_tx(chan, kbuf, count);	spin_lock_irqsave(&cosa->lock, flags);	add_wait_queue(&chan->txwaitq, &wait);	while(!chan->tx_status) {		current->state = TASK_INTERRUPTIBLE;		spin_unlock_irqrestore(&cosa->lock, flags);		schedule();		spin_lock_irqsave(&cosa->lock, flags);		if (signal_pending(current) && chan->tx_status == 0) {			chan->tx_status = 1;			remove_wait_queue(&chan->txwaitq, &wait);			current->state = TASK_RUNNING;			chan->tx_status = 1;			spin_unlock_irqrestore(&cosa->lock, flags);			return -ERESTARTSYS;		}	}	remove_wait_queue(&chan->txwaitq, &wait);	current->state = TASK_RUNNING;	up(&chan->wsem);	spin_unlock_irqrestore(&cosa->lock, flags);	kfree(kbuf);	return count;}static int chrdev_tx_done(struct channel_data *chan, int size){	if (chan->tx_status) { /* Writer was interrupted */		kfree(chan->txbuf);		up(&chan->wsem);	}	chan->tx_status = 1;	wake_up_interruptible(&chan->txwaitq);	return 1;}static unsigned int cosa_poll(struct file *file, poll_table *poll){	printk(KERN_INFO "cosa_poll is here\n");	return 0;}static int cosa_open(struct inode *inode, struct file *file){	struct cosa_data *cosa;	struct channel_data *chan;	unsigned long flags;	int n;	if ((n=MINOR(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)		>= nr_cards)		return -ENODEV;	cosa = cosa_cards+n;	if ((n=MINOR(file->f_dentry->d_inode->i_rdev)		& ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)		return -ENODEV;	chan = cosa->chan + n;		file->private_data = chan;	spin_lock_irqsave(&cosa->lock, flags);	if (chan->usage < 0) { /* in netdev mode */		spin_unlock_irqrestore(&cosa->lock, flags);		return -EBUSY;	}	cosa->usage++;	chan->usage++;	chan->tx_done = chrdev_tx_done;	chan->setup_rx = chrdev_setup_rx;	chan->rx_done = chrdev_rx_done;	spin_unlock_irqrestore(&cosa->lock, flags);	return 0;}static int cosa_release(struct inode *inode, struct file *file){	struct channel_data *channel = (struct channel_data *)file->private_data;	struct cosa_data *cosa;	unsigned long flags;	lock_kernel();	cosa = channel->cosa;	spin_lock_irqsave(&cosa->lock, flags);	cosa->usage--;	channel->usage--;	spin_unlock_irqrestore(&cosa->lock, flags);	unlock_kernel();	return 0;}#ifdef COSA_FASYNC_WORKINGstatic struct fasync_struct *fasync[256] = { NULL, };/* To be done ... */static int cosa_fasync(struct inode *inode, struct file *file, int on){        int port = MINOR(inode->i_rdev);        int rv = fasync_helper(inode, file, on, &fasync[port]);        return rv < 0 ? rv : 0;}#endif/* ---------- Ioctls ---------- *//* * Ioctl subroutines can safely be made inline, because they are called * only from cosa_ioctl(). */static inline int cosa_reset(struct cosa_data *cosa){	char idstring[COSA_MAX_ID_STRING];	if (cosa->usage > 1)		printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",			cosa->num, cosa->usage);	cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_START);	if (cosa_reset_and_read_id(cosa, idstring) < 0) {		printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num);		return -EIO;	}	printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num,		idstring);	cosa->firmware_status |= COSA_FW_RESET;	return 0;}/* High-level function to download data into COSA memory. Calls download() */static inline int cosa_download(struct cosa_data *cosa, struct cosa_download *d){	int i;	int addr, len;	char *code;	if (cosa->usage > 1)		printk(KERN_INFO "%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",			cosa->name, cosa->usage);	if (!(cosa->firmware_status & COSA_FW_RESET)) {		printk(KERN_NOTICE "%s: reset the card first (status %d).\n",			cosa->name, cosa->firmware_status);		return -EPERM;	}	if (get_user(addr, &(d->addr)) ||	    __get_user(len, &(d->len)) ||	    __get_user(code, &(d->code)))

⌨️ 快捷键说明

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