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

📄 sja1000.c

📁 socket can driver, for s3c2440 using sja100, enjoy it!
💻 C
📖 第 1 页 / 共 2 页
字号:
static void sja1000_rx(struct net_device *dev){	struct sja1000_priv *priv = netdev_priv(dev);	struct net_device_stats *stats = dev->get_stats(dev);	struct can_frame *cf;	struct sk_buff *skb;	uint8_t fi;	uint8_t dreg;	canid_t id;	uint8_t dlc;	int i;	skb = dev_alloc_skb(sizeof(struct can_frame));	if (skb == NULL)		return;	skb->dev = dev;	skb->protocol = htons(ETH_P_CAN);	fi = priv->read_reg(dev, REG_FI);	dlc = fi & 0x0F;	if (fi & FI_FF) {		/* extended frame format (EFF) */		dreg = EFF_BUF;		id = (priv->read_reg(dev, REG_ID1) << (5 + 16))		    | (priv->read_reg(dev, REG_ID2) << (5 + 8))		    | (priv->read_reg(dev, REG_ID3) << 5)		    | (priv->read_reg(dev, REG_ID4) >> 3);		id |= CAN_EFF_FLAG;	} else {		/* standard frame format (SFF) */		dreg = SFF_BUF;		id = (priv->read_reg(dev, REG_ID1) << 3)		    | (priv->read_reg(dev, REG_ID2) >> 5);	}	if (fi & FI_RTR)		id |= CAN_RTR_FLAG;	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));	memset(cf, 0, sizeof(struct can_frame));	cf->can_id = id;	cf->can_dlc = dlc;	for (i = 0; i < dlc; i++)		cf->data[i] = priv->read_reg(dev, dreg++);	while (i < 8)		cf->data[i++] = 0;	/* release receive buffer */	priv->write_reg(dev, REG_CMR, CMD_RRB);	netif_rx(skb);	dev->last_rx = jiffies;	stats->rx_packets++;	stats->rx_bytes += dlc;}static int sja1000_err(struct net_device *dev,		       uint8_t isrc, uint8_t status, int n){	struct sja1000_priv *priv = netdev_priv(dev);	struct net_device_stats *stats = dev->get_stats(dev);	struct can_frame *cf;	struct sk_buff *skb;	enum can_state state = priv->can.state;	uint8_t ecc, alc;	skb = dev_alloc_skb(sizeof(struct can_frame));	if (skb == NULL)		return -ENOMEM;	skb->dev = dev;	skb->protocol = htons(ETH_P_CAN);	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));	memset(cf, 0, sizeof(struct can_frame));	cf->can_id = CAN_ERR_FLAG;	cf->can_dlc = CAN_ERR_DLC;	if (isrc & IRQ_DOI) {		/* data overrun interrupt */		iiDBG(KERN_INFO "%s: data overrun isrc=0x%02X "		      "status=0x%02X\n", dev->name, isrc, status);		iDBG(KERN_INFO "%s: DOI #%d#\n", dev->name, n);		cf->can_id |= CAN_ERR_CRTL;		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;		priv->can.can_stats.data_overrun++;		priv->write_reg(dev, REG_CMR, CMD_CDO);	/* clear bit */	}	if (isrc & IRQ_EI) {		/* error warning interrupt */		iiDBG(KERN_INFO "%s: error warning isrc=0x%02X "		      "status=0x%02X\n", dev->name, isrc, status);		iDBG(KERN_INFO "%s: EI #%d#\n", dev->name, n);		priv->can.can_stats.error_warning++;		if (status & SR_BS) {			state = CAN_STATE_BUS_OFF;			cf->can_id |= CAN_ERR_BUSOFF;			can_bus_off(dev);			iDBG(KERN_INFO "%s: BUS OFF\n", dev->name);		} else if (status & SR_ES) {			state = CAN_STATE_BUS_WARNING;			iDBG(KERN_INFO "%s: error\n", dev->name);		} else			state = CAN_STATE_ACTIVE;	}	if (isrc & IRQ_BEI) {		/* bus error interrupt */		iiDBG(KERN_INFO "%s: bus error isrc=0x%02X "		      "status=0x%02X\n", dev->name, isrc, status);		iDBG(KERN_INFO "%s: BEI #%d# [%d]\n", dev->name, n,		     priv->can.can_stats.bus_error);		priv->can.can_stats.bus_error++;		ecc = priv->read_reg(dev, REG_ECC);		iDBG(KERN_INFO "%s: ECC = 0x%02X (%s, %s, %s)\n",		     dev->name, ecc,		     (ecc & ECC_DIR) ? "RX" : "TX",		     ecc_types[ecc >> ECC_ERR],		     ecc_errors[ecc & ECC_SEG]);		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;		switch (ecc & ECC_MASK) {		case ECC_BIT:			cf->data[2] |= CAN_ERR_PROT_BIT;			break;		case ECC_FORM:			cf->data[2] |= CAN_ERR_PROT_FORM;			break;		case ECC_STUFF:			cf->data[2] |= CAN_ERR_PROT_STUFF;			break;		default:			cf->data[2] |= CAN_ERR_PROT_UNSPEC;			cf->data[3] = ecc & ECC_SEG;			break;		}		/* Error occured during transmission? */		if ((ecc & ECC_DIR) == 0)			cf->data[2] |= CAN_ERR_PROT_TX;	}	if (isrc & IRQ_EPI) {		/* error passive interrupt */		iiDBG(KERN_INFO "%s: error passive isrc=0x%02X"		      " status=0x%02X\n", dev->name, isrc, status);		iDBG(KERN_INFO "%s: EPI #%d#\n", dev->name, n);		priv->can.can_stats.error_passive++;		if (status & SR_ES) {			iDBG(KERN_INFO "%s: ERROR PASSIVE\n", dev->name);			state = CAN_STATE_BUS_PASSIVE;		} else {			iDBG(KERN_INFO "%s: ERROR ACTIVE\n", dev->name);			state = CAN_STATE_ACTIVE;		}	}	if (isrc & IRQ_ALI) {		/* arbitration lost interrupt */		iiDBG(KERN_INFO "%s: error arbitration lost "		      "isrc=0x%02X status=0x%02X\n",		      dev->name, isrc, status);		iDBG(KERN_INFO "%s: ALI #%d#\n", dev->name, n);		alc = priv->read_reg(dev, REG_ALC);		iDBG(KERN_INFO "%s: ALC = 0x%02X\n", dev->name, alc);		priv->can.can_stats.arbitration_lost++;		cf->can_id |= CAN_ERR_LOSTARB;		cf->data[0] = alc & 0x1f;	}	if (state != priv->can.state && (state == CAN_STATE_BUS_WARNING ||					 state == CAN_STATE_BUS_PASSIVE)) {		uint8_t rxerr = priv->read_reg(dev, REG_RXERR);		uint8_t txerr = priv->read_reg(dev, REG_TXERR);		cf->can_id |= CAN_ERR_CRTL;		if (state == CAN_STATE_BUS_WARNING)			cf->data[1] = (txerr > rxerr) ?				CAN_ERR_CRTL_TX_WARNING :				CAN_ERR_CRTL_RX_WARNING;		else			cf->data[1] = (txerr > rxerr) ?				CAN_ERR_CRTL_TX_PASSIVE :				CAN_ERR_CRTL_RX_PASSIVE;	}	priv->can.state = state;	netif_rx(skb);	dev->last_rx = jiffies;	stats->rx_packets++;	stats->rx_bytes += cf->can_dlc;	return 0;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)irqreturn_t sja1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)#elseirqreturn_t sja1000_interrupt(int irq, void *dev_id)#endif{	struct net_device *dev = (struct net_device *)dev_id;	struct sja1000_priv *priv = netdev_priv(dev);	struct net_device_stats *stats = dev->get_stats(dev);	uint8_t isrc, status;	int n = 0;	if (priv->pre_irq)		priv->pre_irq(dev);	iiDBG(KERN_INFO "%s: interrupt\n", dev->name);	if (priv->can.state == CAN_STATE_STOPPED) {		iiDBG(KERN_ERR "%s: %s: controller is in reset mode! "		      "MOD=0x%02X IER=0x%02X IR=0x%02X SR=0x%02X!\n",		      dev->name, __func__, priv->read_reg(dev, REG_MOD),		      priv->read_reg(dev, REG_IER), priv->read_reg(dev, REG_IR),		      priv->read_reg(dev, REG_SR));		goto out;	}	while ((isrc = priv->read_reg(dev, REG_IR)) && (n < 20)) {		n++;		status = priv->read_reg(dev, REG_SR);		if (isrc & IRQ_WUI) {			/* wake-up interrupt */			priv->can.can_stats.wakeup++;		}		if (isrc & IRQ_TI) {			/* transmission complete interrupt */			stats->tx_packets++;			can_get_echo_skb(dev, 0);			netif_wake_queue(dev);		}		if (isrc & IRQ_RI) {			/* receive interrupt */			while (status & SR_RBS) {				sja1000_rx(dev);				status = priv->read_reg(dev, REG_SR);			}		}		if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {			/* error interrupt */			if (sja1000_err(dev, isrc, status, n))				break;		}	}	if (n > 1)		iDBG(KERN_INFO "%s: handled %d IRQs\n", dev->name, n);out:	if (priv->post_irq)		priv->post_irq(dev);	return (n) ? IRQ_HANDLED : IRQ_NONE;}EXPORT_SYMBOL_GPL(sja1000_interrupt);static int sja1000_open(struct net_device *dev){	struct sja1000_priv *priv = netdev_priv(dev);	int err;	/* set chip into reset mode */	set_reset_mode(dev);	/* determine and set bittime */	err = can_set_bittiming(dev);	if (err){		iiDBG("%s: can_set_bittiming ERROR: %x\n", __func__, err);		return err;		}	/* register interrupt handler, if not done by the device driver */	if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)		err = request_irq(dev->irq, &sja1000_interrupt, SA_SHIRQ,				  dev->name, (void *)dev);#else		err = request_irq(dev->irq, &sja1000_interrupt, IRQF_SHARED,				  dev->name, (void *)dev);#endif		if (err)			return -EAGAIN;	}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)	/* clear statistics */	memset(&priv->can.net_stats, 0, sizeof(priv->can.net_stats));#endif	/* init and start chi */	sja1000_start(dev);	priv->open_time = jiffies;	netif_start_queue(dev);	return 0;}static int sja1000_close(struct net_device *dev){	struct sja1000_priv *priv = netdev_priv(dev);	set_reset_mode(dev);	netif_stop_queue(dev);	priv->open_time = 0;	can_close_cleanup(dev);	if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER))		free_irq(dev->irq, (void *)dev);	return 0;}struct net_device *alloc_sja1000dev(int sizeof_priv){	struct net_device *dev;	struct sja1000_priv *priv;	dev = alloc_candev(sizeof(struct sja1000_priv) + sizeof_priv);	if (!dev)		return NULL;	priv = netdev_priv(dev);	priv->dev = dev;	if (sizeof_priv)		priv->priv = (void *)priv + sizeof(struct sja1000_priv);	return dev;}EXPORT_SYMBOL_GPL(alloc_sja1000dev);void free_sja1000dev(struct net_device *dev){	free_candev(dev);}EXPORT_SYMBOL(free_sja1000dev);int register_sja1000dev(struct net_device *dev){	struct sja1000_priv *priv = netdev_priv(dev);	int err;	if (!sja1000_probe_chip(dev))		return -ENODEV;	dev->flags |= IFF_ECHO;	/* we support local echo */	dev->open = sja1000_open;	dev->stop = sja1000_close;	dev->hard_start_xmit = sja1000_start_xmit;	priv->can.bittiming_const = &sja1000_bittiming_const;	priv->can.do_set_bittiming = sja1000_set_bittiming;	priv->can.do_get_state = sja1000_get_state;	priv->can.do_set_mode = sja1000_set_mode;	priv->dev = dev;	err = register_netdev(dev);	if (err) {		printk(KERN_INFO		       "%s: registering netdev failed\n", DRV_NAME);		free_netdev(dev);		return err;	}	set_reset_mode(dev);	chipset_init(dev);	return 0;}EXPORT_SYMBOL(register_sja1000dev);void unregister_sja1000dev(struct net_device *dev){	set_reset_mode(dev);	unregister_netdev(dev);}EXPORT_SYMBOL(unregister_sja1000dev);static __init int sja1000_init(void){	printk(KERN_INFO "%s CAN netdevice driver\n", DRV_NAME);	if (debug)		printk(KERN_INFO "%s: debug level set to %d.\n",		       DRV_NAME, debug);	return 0;}module_init(sja1000_init);static __exit void sja1000_exit(void){	printk(KERN_INFO "%s: driver removed\n", DRV_NAME);}module_exit(sja1000_exit);

⌨️ 快捷键说明

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