macmace.c

来自「linux 内核源代码」· C语言 代码 · 共 818 行 · 第 1/2 页

C
818
字号
	psc_write_word(PSC_ENETWR_CTL, 0x9000);	psc_write_word(PSC_ENETRD_CTL, 0x9000);	psc_write_word(PSC_ENETWR_CTL, 0x0400);	psc_write_word(PSC_ENETRD_CTL, 0x0400);	mace_rxdma_reset(dev);	mace_txdma_reset(dev);	/* turn it on! */	mb->maccc = ENXMT | ENRCV;	/* enable all interrupts except receive interrupts */	mb->imr = RCVINT;	return 0;out2:	dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,	                  mp->tx_ring, mp->tx_ring_phys);out1:	free_irq(dev->irq, dev);	free_irq(mp->dma_intr, dev);	return -ENOMEM;}/* * Shut down the mace and its interrupt channel */static int mace_close(struct net_device *dev){	struct mace_data *mp = netdev_priv(dev);	volatile struct mace *mb = mp->mace;	mb->maccc = 0;		/* disable rx and tx	 */	mb->imr = 0xFF;		/* disable all irqs	 */	mace_dma_off(dev);	/* disable rx and tx dma */	return 0;}/* * Transmit a frame */static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev){	struct mace_data *mp = netdev_priv(dev);	unsigned long flags;	/* Stop the queue since there's only the one buffer */	local_irq_save(flags);	netif_stop_queue(dev);	if (!mp->tx_count) {		printk(KERN_ERR "macmace: tx queue running but no free buffers.\n");		local_irq_restore(flags);		return NETDEV_TX_BUSY;	}	mp->tx_count--;	local_irq_restore(flags);	dev->stats.tx_packets++;	dev->stats.tx_bytes += skb->len;	/* We need to copy into our xmit buffer to take care of alignment and caching issues */	skb_copy_from_linear_data(skb, mp->tx_ring, skb->len);	/* load the Tx DMA and fire it off */	psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, (u32)  mp->tx_ring_phys);	psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len);	psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800);	mp->tx_slot ^= 0x10;	dev_kfree_skb(skb);	dev->trans_start = jiffies;	return NETDEV_TX_OK;}static void mace_set_multicast(struct net_device *dev){	struct mace_data *mp = netdev_priv(dev);	volatile struct mace *mb = mp->mace;	int i, j;	u32 crc;	u8 maccc;	unsigned long flags;	local_irq_save(flags);	maccc = mb->maccc;	mb->maccc &= ~PROM;	if (dev->flags & IFF_PROMISC) {		mb->maccc |= PROM;	} else {		unsigned char multicast_filter[8];		struct dev_mc_list *dmi = dev->mc_list;		if (dev->flags & IFF_ALLMULTI) {			for (i = 0; i < 8; i++) {				multicast_filter[i] = 0xFF;			}		} else {			for (i = 0; i < 8; i++)				multicast_filter[i] = 0;			for (i = 0; i < dev->mc_count; i++) {				crc = ether_crc_le(6, dmi->dmi_addr);				j = crc >> 26;	/* bit number in multicast_filter */				multicast_filter[j >> 3] |= 1 << (j & 7);				dmi = dmi->next;			}		}		if (mp->chipid == BROKEN_ADDRCHG_REV)			mb->iac = LOGADDR;		else {			mb->iac = ADDRCHG | LOGADDR;			while ((mb->iac & ADDRCHG) != 0)				;		}		for (i = 0; i < 8; ++i)			mb->ladrf = multicast_filter[i];		if (mp->chipid != BROKEN_ADDRCHG_REV)			mb->iac = 0;	}	mb->maccc = maccc;	local_irq_restore(flags);}static void mace_handle_misc_intrs(struct net_device *dev, int intr){	struct mace_data *mp = netdev_priv(dev);	volatile struct mace *mb = mp->mace;	static int mace_babbles, mace_jabbers;	if (intr & MPCO)		dev->stats.rx_missed_errors += 256;	dev->stats.rx_missed_errors += mb->mpc;   /* reading clears it */	if (intr & RNTPCO)		dev->stats.rx_length_errors += 256;	dev->stats.rx_length_errors += mb->rntpc; /* reading clears it */	if (intr & CERR)		++dev->stats.tx_heartbeat_errors;	if (intr & BABBLE)		if (mace_babbles++ < 4)			printk(KERN_DEBUG "macmace: babbling transmitter\n");	if (intr & JABBER)		if (mace_jabbers++ < 4)			printk(KERN_DEBUG "macmace: jabbering transceiver\n");}static irqreturn_t mace_interrupt(int irq, void *dev_id){	struct net_device *dev = (struct net_device *) dev_id;	struct mace_data *mp = netdev_priv(dev);	volatile struct mace *mb = mp->mace;	int intr, fs;	unsigned long flags;	/* don't want the dma interrupt handler to fire */	local_irq_save(flags);	intr = mb->ir; /* read interrupt register */	mace_handle_misc_intrs(dev, intr);	if (intr & XMTINT) {		fs = mb->xmtfs;		if ((fs & XMTSV) == 0) {			printk(KERN_ERR "macmace: xmtfs not valid! (fs=%x)\n", fs);			mace_reset(dev);			/*			 * XXX mace likes to hang the machine after a xmtfs error.			 * This is hard to reproduce, reseting *may* help			 */		}		/* dma should have finished */		if (!mp->tx_count) {			printk(KERN_DEBUG "macmace: tx ring ran out? (fs=%x)\n", fs);		}		/* Update stats */		if (fs & (UFLO|LCOL|LCAR|RTRY)) {			++dev->stats.tx_errors;			if (fs & LCAR)				++dev->stats.tx_carrier_errors;			else if (fs & (UFLO|LCOL|RTRY)) {				++dev->stats.tx_aborted_errors;				if (mb->xmtfs & UFLO) {					printk(KERN_ERR "%s: DMA underrun.\n", dev->name);					dev->stats.tx_fifo_errors++;					mace_txdma_reset(dev);				}			}		}	}	if (mp->tx_count)		netif_wake_queue(dev);	local_irq_restore(flags);	return IRQ_HANDLED;}static void mace_tx_timeout(struct net_device *dev){	struct mace_data *mp = netdev_priv(dev);	volatile struct mace *mb = mp->mace;	unsigned long flags;	local_irq_save(flags);	/* turn off both tx and rx and reset the chip */	mb->maccc = 0;	printk(KERN_ERR "macmace: transmit timeout - resetting\n");	mace_txdma_reset(dev);	mace_reset(dev);	/* restart rx dma */	mace_rxdma_reset(dev);	mp->tx_count = N_TX_RING;	netif_wake_queue(dev);	/* turn it on! */	mb->maccc = ENXMT | ENRCV;	/* enable all interrupts except receive interrupts */	mb->imr = RCVINT;	local_irq_restore(flags);}/* * Handle a newly arrived frame */static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf){	struct sk_buff *skb;	unsigned int frame_status = mf->rcvsts;	if (frame_status & (RS_OFLO | RS_CLSN | RS_FRAMERR | RS_FCSERR)) {		dev->stats.rx_errors++;		if (frame_status & RS_OFLO) {			printk(KERN_DEBUG "%s: fifo overflow.\n", dev->name);			dev->stats.rx_fifo_errors++;		}		if (frame_status & RS_CLSN)			dev->stats.collisions++;		if (frame_status & RS_FRAMERR)			dev->stats.rx_frame_errors++;		if (frame_status & RS_FCSERR)			dev->stats.rx_crc_errors++;	} else {		unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 );		skb = dev_alloc_skb(frame_length + 2);		if (!skb) {			dev->stats.rx_dropped++;			return;		}		skb_reserve(skb, 2);		memcpy(skb_put(skb, frame_length), mf->data, frame_length);		skb->protocol = eth_type_trans(skb, dev);		netif_rx(skb);		dev->last_rx = jiffies;		dev->stats.rx_packets++;		dev->stats.rx_bytes += frame_length;	}}/* * The PSC has passed us a DMA interrupt event. */static irqreturn_t mace_dma_intr(int irq, void *dev_id){	struct net_device *dev = (struct net_device *) dev_id;	struct mace_data *mp = netdev_priv(dev);	int left, head;	u16 status;	u32 baka;	/* Not sure what this does */	while ((baka = psc_read_long(PSC_MYSTERY)) != psc_read_long(PSC_MYSTERY));	if (!(baka & 0x60000000)) return IRQ_NONE;	/*	 * Process the read queue	 */	status = psc_read_word(PSC_ENETRD_CTL);	if (status & 0x2000) {		mace_rxdma_reset(dev);	} else if (status & 0x0100) {		psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100);		left = psc_read_long(PSC_ENETRD_LEN + mp->rx_slot);		head = N_RX_RING - left;		/* Loop through the ring buffer and process new packages */		while (mp->rx_tail < head) {			mace_dma_rx_frame(dev, (struct mace_frame*) (mp->rx_ring				+ (mp->rx_tail * MACE_BUFF_SIZE)));			mp->rx_tail++;		}		/* If we're out of buffers in this ring then switch to */		/* the other set, otherwise just reactivate this one.  */		if (!left) {			mace_load_rxdma_base(dev, mp->rx_slot);			mp->rx_slot ^= 0x10;		} else {			psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x9800);		}	}	/*	 * Process the write queue	 */	status = psc_read_word(PSC_ENETWR_CTL);	if (status & 0x2000) {		mace_txdma_reset(dev);	} else if (status & 0x0100) {		psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100);		mp->tx_sloti ^= 0x10;		mp->tx_count++;	}	return IRQ_HANDLED;}MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Macintosh MACE ethernet driver");static int __devexit mac_mace_device_remove (struct platform_device *pdev){	struct net_device *dev = platform_get_drvdata(pdev);	struct mace_data *mp = netdev_priv(dev);	unregister_netdev(dev);	free_irq(dev->irq, dev);	free_irq(IRQ_MAC_MACE_DMA, dev);	dma_free_coherent(mp->device, N_RX_RING * MACE_BUFF_SIZE,	                  mp->rx_ring, mp->rx_ring_phys);	dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,	                  mp->tx_ring, mp->tx_ring_phys);	free_netdev(dev);	return 0;}static struct platform_driver mac_mace_driver = {	.probe  = mace_probe,	.remove = __devexit_p(mac_mace_device_remove),	.driver	= {		.name = mac_mace_string,	},};static int __init mac_mace_init_module(void){	int err;	if ((err = platform_driver_register(&mac_mace_driver))) {		printk(KERN_ERR "Driver registration failed\n");		return err;	}	mac_mace_device = platform_device_alloc(mac_mace_string, 0);	if (!mac_mace_device)		goto out_unregister;	if (platform_device_add(mac_mace_device)) {		platform_device_put(mac_mace_device);		mac_mace_device = NULL;	}	return 0;out_unregister:	platform_driver_unregister(&mac_mace_driver);	return -ENOMEM;}static void __exit mac_mace_cleanup_module(void){	platform_driver_unregister(&mac_mace_driver);	if (mac_mace_device) {		platform_device_unregister(mac_mace_device);		mac_mace_device = NULL;	}}module_init(mac_mace_init_module);module_exit(mac_mace_cleanup_module);

⌨️ 快捷键说明

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