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

📄 farsync.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		return -EINVAL;	}	switch (sync.clock_type) {	case CLOCK_EXT:		FST_WRB(card, portConfig[i].internalClock, EXTCLK);		break;	case CLOCK_INT:		FST_WRB(card, portConfig[i].internalClock, INTCLK);		break;	default:		return -EINVAL;	}	FST_WRL(card, portConfig[i].lineSpeed, sync.clock_rate);	return 0;}static intfst_get_iface(struct fst_card_info *card, struct fst_port_info *port,	      struct ifreq *ifr){	sync_serial_settings sync;	int i;	/* First check what line type is set, we'll default to reporting X.21	 * if nothing is set as IF_IFACE_SYNC_SERIAL implies it can't be	 * changed	 */	switch (port->hwif) {	case E1:		ifr->ifr_settings.type = IF_IFACE_E1;		break;	case T1:		ifr->ifr_settings.type = IF_IFACE_T1;		break;	case V35:		ifr->ifr_settings.type = IF_IFACE_V35;		break;	case V24:		ifr->ifr_settings.type = IF_IFACE_V24;		break;	case X21D:		ifr->ifr_settings.type = IF_IFACE_X21D;		break;	case X21:	default:		ifr->ifr_settings.type = IF_IFACE_X21;		break;	}	if (ifr->ifr_settings.size == 0) {		return 0;	/* only type requested */	}	if (ifr->ifr_settings.size < sizeof (sync)) {		return -ENOMEM;	}	i = port->index;	sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed);	/* Lucky card and linux use same encoding here */	sync.clock_type = FST_RDB(card, portConfig[i].internalClock) ==	    INTCLK ? CLOCK_INT : CLOCK_EXT;	sync.loopback = 0;	if (copy_to_user(ifr->ifr_settings.ifs_ifsu.sync, &sync, sizeof (sync))) {		return -EFAULT;	}	ifr->ifr_settings.size = sizeof (sync);	return 0;}static intfst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	struct fst_card_info *card;	struct fst_port_info *port;	struct fstioc_write wrthdr;	struct fstioc_info info;	unsigned long flags;	dbg(DBG_IOCTL, "ioctl: %x, %p\n", cmd, ifr->ifr_data);	port = dev_to_port(dev);	card = port->card;	if (!capable(CAP_NET_ADMIN))		return -EPERM;	switch (cmd) {	case FSTCPURESET:		fst_cpureset(card);		card->state = FST_RESET;		return 0;	case FSTCPURELEASE:		fst_cpurelease(card);		card->state = FST_STARTING;		return 0;	case FSTWRITE:		/* Code write (download) */		/* First copy in the header with the length and offset of data		 * to write		 */		if (ifr->ifr_data == NULL) {			return -EINVAL;		}		if (copy_from_user(&wrthdr, ifr->ifr_data,				   sizeof (struct fstioc_write))) {			return -EFAULT;		}		/* Sanity check the parameters. We don't support partial writes		 * when going over the top		 */		if (wrthdr.size > FST_MEMSIZE || wrthdr.offset > FST_MEMSIZE		    || wrthdr.size + wrthdr.offset > FST_MEMSIZE) {			return -ENXIO;		}		/* Now copy the data to the card.		 * This will probably break on some architectures.		 * I'll fix it when I have something to test on.		 */		if (copy_from_user(card->mem + wrthdr.offset,				   ifr->ifr_data + sizeof (struct fstioc_write),				   wrthdr.size)) {			return -EFAULT;		}		/* Writes to the memory of a card in the reset state constitute		 * a download		 */		if (card->state == FST_RESET) {			card->state = FST_DOWNLOAD;		}		return 0;	case FSTGETCONF:		/* If card has just been started check the shared memory config		 * version and marker		 */		if (card->state == FST_STARTING) {			check_started_ok(card);			/* If everything checked out enable card interrupts */			if (card->state == FST_RUNNING) {				spin_lock_irqsave(&card->card_lock, flags);				fst_enable_intr(card);				FST_WRB(card, interruptHandshake, 0xEE);				spin_unlock_irqrestore(&card->card_lock, flags);			}		}		if (ifr->ifr_data == NULL) {			return -EINVAL;		}		gather_conf_info(card, port, &info);		if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) {			return -EFAULT;		}		return 0;	case FSTSETCONF:		/*		 * Most of the settings have been moved to the generic ioctls		 * this just covers debug and board ident now		 */		if (card->state != FST_RUNNING) {			printk_err			    ("Attempt to configure card %d in non-running state (%d)\n",			     card->card_no, card->state);			return -EIO;		}		if (copy_from_user(&info, ifr->ifr_data, sizeof (info))) {			return -EFAULT;		}		return set_conf_from_info(card, port, &info);	case SIOCWANDEV:		switch (ifr->ifr_settings.type) {		case IF_GET_IFACE:			return fst_get_iface(card, port, ifr);		case IF_IFACE_SYNC_SERIAL:		case IF_IFACE_V35:		case IF_IFACE_V24:		case IF_IFACE_X21:		case IF_IFACE_X21D:		case IF_IFACE_T1:		case IF_IFACE_E1:			return fst_set_iface(card, port, ifr);		case IF_PROTO_RAW:			port->mode = FST_RAW;			return 0;		case IF_GET_PROTO:			if (port->mode == FST_RAW) {				ifr->ifr_settings.type = IF_PROTO_RAW;				return 0;			}			return hdlc_ioctl(dev, ifr, cmd);		default:			port->mode = FST_GEN_HDLC;			dbg(DBG_IOCTL, "Passing this type to hdlc %x\n",			    ifr->ifr_settings.type);			return hdlc_ioctl(dev, ifr, cmd);		}	default:		/* Not one of ours. Pass through to HDLC package */		return hdlc_ioctl(dev, ifr, cmd);	}}static voidfst_openport(struct fst_port_info *port){	int signals;	int txq_length;	/* Only init things if card is actually running. This allows open to	 * succeed for downloads etc.	 */	if (port->card->state == FST_RUNNING) {		if (port->run) {			dbg(DBG_OPEN, "open: found port already running\n");			fst_issue_cmd(port, STOPPORT);			port->run = 0;		}		fst_rx_config(port);		fst_tx_config(port);		fst_op_raise(port, OPSTS_RTS | OPSTS_DTR);		fst_issue_cmd(port, STARTPORT);		port->run = 1;		signals = FST_RDL(port->card, v24DebouncedSts[port->index]);		if (signals & (((port->hwif == X21) || (port->hwif == X21D))			       ? IPSTS_INDICATE : IPSTS_DCD))			netif_carrier_on(port_to_dev(port));		else			netif_carrier_off(port_to_dev(port));		txq_length = port->txqe - port->txqs;		port->txqe = 0;		port->txqs = 0;	}}static voidfst_closeport(struct fst_port_info *port){	if (port->card->state == FST_RUNNING) {		if (port->run) {			port->run = 0;			fst_op_lower(port, OPSTS_RTS | OPSTS_DTR);			fst_issue_cmd(port, STOPPORT);		} else {			dbg(DBG_OPEN, "close: port not running\n");		}	}}static intfst_open(struct net_device *dev){	int err;	struct fst_port_info *port;	port = dev_to_port(dev);	if (!try_module_get(THIS_MODULE))          return -EBUSY;	if (port->mode != FST_RAW) {		err = hdlc_open(dev);		if (err)			return err;	}	fst_openport(port);	netif_wake_queue(dev);	return 0;}static intfst_close(struct net_device *dev){	struct fst_port_info *port;	struct fst_card_info *card;	unsigned char tx_dma_done;	unsigned char rx_dma_done;	port = dev_to_port(dev);	card = port->card;	tx_dma_done = inb(card->pci_conf + DMACSR1);	rx_dma_done = inb(card->pci_conf + DMACSR0);	dbg(DBG_OPEN,	    "Port Close: tx_dma_in_progress = %d (%x) rx_dma_in_progress = %d (%x)\n",	    card->dmatx_in_progress, tx_dma_done, card->dmarx_in_progress,	    rx_dma_done);	netif_stop_queue(dev);	fst_closeport(dev_to_port(dev));	if (port->mode != FST_RAW) {		hdlc_close(dev);	}	module_put(THIS_MODULE);	return 0;}static intfst_attach(struct net_device *dev, unsigned short encoding, unsigned short parity){	/*	 * Setting currently fixed in FarSync card so we check and forget	 */	if (encoding != ENCODING_NRZ || parity != PARITY_CRC16_PR1_CCITT)		return -EINVAL;	return 0;}static voidfst_tx_timeout(struct net_device *dev){	struct fst_port_info *port;	struct fst_card_info *card;	struct net_device_stats *stats = hdlc_stats(dev);	port = dev_to_port(dev);	card = port->card;	stats->tx_errors++;	stats->tx_aborted_errors++;	dbg(DBG_ASS, "Tx timeout card %d port %d\n",	    card->card_no, port->index);	fst_issue_cmd(port, ABORTTX);	dev->trans_start = jiffies;	netif_wake_queue(dev);	port->start = 0;}static intfst_start_xmit(struct sk_buff *skb, struct net_device *dev){	struct fst_card_info *card;	struct fst_port_info *port;	struct net_device_stats *stats = hdlc_stats(dev);	unsigned long flags;	int txq_length;	port = dev_to_port(dev);	card = port->card;	dbg(DBG_TX, "fst_start_xmit: length = %d\n", skb->len);	/* Drop packet with error if we don't have carrier */	if (!netif_carrier_ok(dev)) {		dev_kfree_skb(skb);		stats->tx_errors++;		stats->tx_carrier_errors++;		dbg(DBG_ASS,		    "Tried to transmit but no carrier on card %d port %d\n",		    card->card_no, port->index);		return 0;	}	/* Drop it if it's too big! MTU failure ? */	if (skb->len > LEN_TX_BUFFER) {		dbg(DBG_ASS, "Packet too large %d vs %d\n", skb->len,		    LEN_TX_BUFFER);		dev_kfree_skb(skb);		stats->tx_errors++;		return 0;	}	/*	 * We are always going to queue the packet	 * so that the bottom half is the only place we tx from	 * Check there is room in the port txq	 */	spin_lock_irqsave(&card->card_lock, flags);	if ((txq_length = port->txqe - port->txqs) < 0) {		/*		 * This is the case where the next free has wrapped but the		 * last used hasn't		 */		txq_length = txq_length + FST_TXQ_DEPTH;	}	spin_unlock_irqrestore(&card->card_lock, flags);	if (txq_length > fst_txq_high) {		/*		 * We have got enough buffers in the pipeline.  Ask the network		 * layer to stop sending frames down		 */		netif_stop_queue(dev);		port->start = 1;	/* I'm using this to signal stop sent up */	}	if (txq_length == FST_TXQ_DEPTH - 1) {		/*		 * This shouldn't have happened but such is life		 */		dev_kfree_skb(skb);		stats->tx_errors++;		dbg(DBG_ASS, "Tx queue overflow card %d port %d\n",		    card->card_no, port->index);		return 0;	}	/*	 * queue the buffer	 */	spin_lock_irqsave(&card->card_lock, flags);	port->txq[port->txqe] = skb;	port->txqe++;	if (port->txqe == FST_TXQ_DEPTH)		port->txqe = 0;	spin_unlock_irqrestore(&card->card_lock, flags);	/* Scehdule the bottom half which now does transmit processing */	fst_q_work_item(&fst_work_txq, card->card_no);	tasklet_schedule(&fst_tx_task);	return 0;}/* *      Card setup having checked hardware resources. *      Should be pretty bizarre if we get an error here (kernel memory *      exhaustion is one possibility). If we do see a problem we report it *      via a printk and leave the corresponding interface and all that follow *      disabled. */static char *type_strings[] __devinitdata = {	"no hardware",		/* Should never be seen */	"FarSync T2P",	"FarSync T4P",	"FarSync T1U",	"FarSync T2U",	"FarSync T4U",	"FarSync TE1"};static void __devinitfst_init_card(struct fst_card_info *card){	int i;	int err;	/* We're working on a number of ports based on the card ID. If the	 * firmware detects something different later (should never happen)	 * we'll have to revise it in some way then.	 */	for (i = 0; i < card->nports; i++) {                err = register_hdlc_device(card->ports[i].dev);                if (err < 0) {			int j;                        printk_err ("Cannot register HDLC device for port %d"                                    " (errno %d)\n", i, -err );			for (j = i; j < card->nports; j++) {				free_netdev(card->ports[j].dev);				card->ports[j].dev = NULL;			}                        card->nports = i;                        break;                }	}	printk_info("

⌨️ 快捷键说明

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