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

📄 atarilance.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	long	flags;	long	*vbr, save_berr;	save_flags(flags);	cli();	__asm__ __volatile__ ( "movec	%/vbr,%0" : "=r" (vbr) : );	save_berr = vbr[2];	__asm__ __volatile__	(	"movel	%/sp,%/d1\n\t"		"movel	#Lberr,%2@\n\t"		"moveq	#0,%0\n\t"		"tstl   %3\n\t"		"bne	1f\n\t"		"moveb	%1@,%/d0\n\t"		"nop	\n\t"		"bra	2f\n""1:		 movew	%1@,%/d0\n\t"		"nop	\n""2:		 tstl   %4\n\t"		"beq	2f\n\t"		"tstl	%3\n\t"		"bne	1f\n\t"		"clrb	%1@\n\t"		"nop	\n\t"		"moveb	%/d0,%1@\n\t"		"nop	\n\t"		"bra	2f\n""1:		 clrw	%1@\n\t"		"nop	\n\t"		"movew	%/d0,%1@\n\t"		"nop	\n""2:		 moveq	#1,%0\n""Lberr:	 movel	%/d1,%/sp"		: "=&d" (ret)		: "a" (regp), "a" (&vbr[2]), "rm" (wordflag), "rm" (writeflag)		: "d0", "d1", "memory"	);	vbr[2] = save_berr;	restore_flags(flags);	return( ret );}__initfunc(static unsigned long lance_probe1( struct device *dev,								   struct lance_addr *init_rec )){	volatile unsigned short *memaddr =		(volatile unsigned short *)init_rec->memaddr;	volatile unsigned short *ioaddr =		(volatile unsigned short *)init_rec->ioaddr;	struct lance_private	*lp;	struct lance_ioreg		*IO;	int 					i;	static int 				did_version = 0;	unsigned short			save1, save2;	PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",				  (long)memaddr, (long)ioaddr ));	/* Test whether memory readable and writable */	PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" ));	if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail;	/* Written values should come back... */	PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" ));	save1 = *memaddr;	*memaddr = 0x0001;	if (*memaddr != 0x0001) goto probe_fail;	PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" ));	*memaddr = 0x0000;	if (*memaddr != 0x0000) goto probe_fail;	*memaddr = save1;	/* First port should be readable and writable */	PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" ));	if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail;	/* and written values should be readable */	PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" ));	save2 = ioaddr[1];	ioaddr[1] = 0x0001;	if (ioaddr[1] != 0x0001) goto probe_fail;	/* The CSR0_INIT bit should not be readable */	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" ));	save1 = ioaddr[0];	ioaddr[1] = CSR0;	ioaddr[0] = CSR0_INIT | CSR0_STOP;	if (ioaddr[0] != CSR0_STOP) {		ioaddr[0] = save1;		ioaddr[1] = save2;		goto probe_fail;	}	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" ));	ioaddr[0] = CSR0_STOP;	if (ioaddr[0] != CSR0_STOP) {		ioaddr[0] = save1;		ioaddr[1] = save2;		goto probe_fail;	}	/* Now ok... */	PROBE_PRINT(( "lance_probe1: Lance card detected\n" ));	goto probe_ok;  probe_fail:	return( 0 );  probe_ok:	init_etherdev( dev, sizeof(struct lance_private) );	if (!dev->priv)		dev->priv = kmalloc( sizeof(struct lance_private), GFP_KERNEL );	lp = (struct lance_private *)dev->priv;	MEM = (struct lance_memory *)memaddr;	IO = lp->iobase = (struct lance_ioreg *)ioaddr;	dev->base_addr = (unsigned long)ioaddr; /* informational only */	lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy;	REGA( CSR0 ) = CSR0_STOP;	/* Now test for type: If the eeprom I/O port is readable, it is a	 * PAM card */	if (addr_accessible( &(IO->eeprom), 0, 0 )) {		/* Switch back to Ram */		i = IO->mem;		lp->cardtype = PAM_CARD;	}	else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {		lp->cardtype = NEW_RIEBL;	}	else		lp->cardtype = OLD_RIEBL;	if (lp->cardtype == PAM_CARD ||		memaddr == (unsigned short *)0xffe00000) {		/* PAMs card and Riebl on ST use level 5 autovector */		request_irq(IRQ_AUTO_5, lance_interrupt, IRQ_TYPE_PRIO,		            "PAM/Riebl-ST Ethernet", dev);		dev->irq = (unsigned short)IRQ_AUTO_5;	}	else {		/* For VME-RieblCards, request a free VME int;		 * (This must be unsigned long, since dev->irq is short and the		 * IRQ_MACHSPEC bit would be cut off...)		 */		unsigned long irq = atari_register_vme_int();		if (!irq) {			printk( "Lance: request for VME interrupt failed\n" );			return( 0 );		}		request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,		            "Riebl-VME Ethernet", dev);		dev->irq = irq;	}	printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ",		   dev->name, lance_names[lp->cardtype],		   (unsigned long)ioaddr,		   (unsigned long)memaddr,		   dev->irq,		   init_rec->slow_flag ? " (slow memcpy)" : "" );	/* Get the ethernet address */	switch( lp->cardtype ) {	  case OLD_RIEBL:		/* No ethernet address! (Set some default address) */		memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 );		break;	  case NEW_RIEBL:		lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 );		break;	  case PAM_CARD:		i = IO->eeprom;		for( i = 0; i < 6; ++i )			dev->dev_addr[i] =				((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |				((((unsigned short *)MEM)[i*2+1] & 0x0f));		i = IO->mem;		break;	}	for( i = 0; i < 6; ++i )		printk( "%02x%s", dev->dev_addr[i], (i < 5) ? ":" : "\n" );	if (lp->cardtype == OLD_RIEBL) {		printk( "%s: Warning: This is a default ethernet address!\n",				dev->name );		printk( "      Use \"ifconfig hw ether ...\" to set the address.\n" );	}	MEM->init.mode = 0x0000;		/* Disable Rx and Tx. */	for( i = 0; i < 6; i++ )		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */	MEM->init.filter[0] = 0x00000000;	MEM->init.filter[1] = 0x00000000;	MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );	MEM->init.rx_ring.adr_hi = 0;	MEM->init.rx_ring.len    = RX_RING_LEN_BITS;	MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );	MEM->init.tx_ring.adr_hi = 0;	MEM->init.tx_ring.len    = TX_RING_LEN_BITS;	if (lp->cardtype == PAM_CARD)		IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq);	else		*RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq);	if (did_version++ == 0)		DPRINTK( 1, ( version ));	/* The LANCE-specific entries in the device structure. */	dev->open = &lance_open;	dev->hard_start_xmit = &lance_start_xmit;	dev->stop = &lance_close;	dev->get_stats = &lance_get_stats;	dev->set_multicast_list = &set_multicast_list;	dev->set_mac_address = &lance_set_mac_address;	dev->start = 0;	memset( &lp->stats, 0, sizeof(lp->stats) );	return( 1 );}static int lance_open( struct device *dev ){	struct lance_private *lp = (struct lance_private *)dev->priv;	struct lance_ioreg	 *IO = lp->iobase;	int i;	DPRINTK( 2, ( "%s: lance_open()\n", dev->name ));	lance_init_ring(dev);	/* Re-initialize the LANCE, and start it when done. */	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);	REGA( CSR2 ) = 0;	REGA( CSR1 ) = 0;	REGA( CSR0 ) = CSR0_INIT;	/* From now on, AREG is kept to point to CSR0 */	i = 1000000;	while (--i > 0)		if (DREG & CSR0_IDON)			break;	if (i < 0 || (DREG & CSR0_ERR)) {		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",					  dev->name, i, DREG ));		DREG = CSR0_STOP;		return( -EIO );	}	DREG = CSR0_IDON;	DREG = CSR0_STRT;	DREG = CSR0_INEA;	dev->tbusy = 0;	dev->interrupt = 0;	dev->start = 1;	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));	MOD_INC_USE_COUNT;	return( 0 );}/* Initialize the LANCE Rx and Tx rings. */static void lance_init_ring( struct device *dev ){	struct lance_private *lp = (struct lance_private *)dev->priv;	int i;	unsigned offset;	lp->lock = 0;	lp->tx_full = 0;	lp->cur_rx = lp->cur_tx = 0;	lp->dirty_tx = 0;	offset = offsetof( struct lance_memory, packet_area );/* If the packet buffer at offset 'o' would conflict with the reserved area * of RieblCards, advance it */#define	CHECK_OFFSET(o)														 \	do {																	 \		if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) {		 \			if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \										 : (o) < RIEBL_RSVD_END)			 \				(o) = RIEBL_RSVD_END;										 \		}																	 \	} while(0)	for( i = 0; i < TX_RING_SIZE; i++ ) {		CHECK_OFFSET(offset);		MEM->tx_head[i].base = offset;		MEM->tx_head[i].flag = TMD1_OWN_HOST; 		MEM->tx_head[i].base_hi = 0;		MEM->tx_head[i].length = 0;		MEM->tx_head[i].misc = 0;		offset += PKT_BUF_SZ;	}	for( i = 0; i < RX_RING_SIZE; i++ ) {		CHECK_OFFSET(offset);		MEM->rx_head[i].base = offset;		MEM->rx_head[i].flag = TMD1_OWN_CHIP;		MEM->rx_head[i].base_hi = 0;		MEM->rx_head[i].buf_length = -PKT_BUF_SZ;		MEM->rx_head[i].msg_length = 0;		offset += PKT_BUF_SZ;	}}static int lance_start_xmit( struct sk_buff *skb, struct device *dev ){	struct lance_private *lp = (struct lance_private *)dev->priv;	struct lance_ioreg	 *IO = lp->iobase;	int entry, len;	struct lance_tx_head *head;	unsigned long flags;	/* Transmitter timeout, serious problems. */	if (dev->tbusy) {		int tickssofar = jiffies - dev->trans_start;		if (tickssofar < 20)			return( 1 );		AREG = CSR0;		DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",					  dev->name, DREG ));		DREG = CSR0_STOP;		/*		 * Always set BSWP after a STOP as STOP puts it back into		 * little endian mode.		 */		REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);		lp->stats.tx_errors++;#ifndef final_version		{	int i;			DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n",						  lp->dirty_tx, lp->cur_tx,						  lp->tx_full ? " (full)" : "",						  lp->cur_rx ));			for( i = 0 ; i < RX_RING_SIZE; i++ )				DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n",							  i, MEM->rx_head[i].base,							  -MEM->rx_head[i].buf_length,							  MEM->rx_head[i].msg_length ));			for( i = 0 ; i < TX_RING_SIZE; i++ )				DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n",							  i, MEM->tx_head[i].base,							  -MEM->tx_head[i].length,							  MEM->tx_head[i].misc ));		}#endif		lance_init_ring(dev);		REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;		dev->tbusy = 0;		dev->trans_start = jiffies;		return( 0 );	}	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",				  dev->name, DREG ));	/* Block a timer-based transmit from overlapping.  This could better be	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */	if (test_and_set_bit( 0, (void*)&dev->tbusy ) != 0) {		DPRINTK( 0, ( "%s: Transmitter access conflict.\n", dev->name ));		return 1;	}	if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) {		DPRINTK( 0, ( "%s: tx queue lock!.\n", dev->name ));		/* don't clear dev->tbusy flag. */		return 1;	}	/* Fill in a Tx ring entry */	if (lance_debug >= 3) {		u_char *p;		int i;		printk( "%s: TX pkt type 0x%04x from ", dev->name,				((u_short *)skb->data)[6]);		for( p = &((u_char *)skb->data)[6], i = 0; i < 6; i++ )			printk("%02x%s", *p++, i != 5 ? ":" : "" );		printk(" to ");		for( p = (u_char *)skb->data, i = 0; i < 6; i++ )			printk("%02x%s", *p++, i != 5 ? ":" : "" );		printk(" data at 0x%08x len %d\n", (int)skb->data,			   (int)skb->len );	}

⌨️ 快捷键说明

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