Skip to content
Snippets Groups Projects
atarilance.c 33.3 KiB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
				if (skb == NULL) {
					DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
								  dev->name ));
					for( i = 0; i < RX_RING_SIZE; i++ )
						if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag &
							RMD1_OWN_CHIP)
							break;

					if (i > RX_RING_SIZE - 2) {
Linus Torvalds's avatar
Linus Torvalds committed
						head->flag |= RMD1_OWN_CHIP;
						lp->cur_rx++;
					}
					break;
				}

				if (lance_debug >= 3) {
					u_char *data = PKTBUF_ADDR(head);

					printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM "
						   "data %02x %02x %02x %02x %02x %02x %02x %02x "
Linus Torvalds's avatar
Linus Torvalds committed
						   "len %d\n",
						   dev->name, ((u_short *)data)[6],
						   &data[6], data,
Linus Torvalds's avatar
Linus Torvalds committed
						   data[15], data[16], data[17], data[18],
						   data[19], data[20], data[21], data[22],
Linus Torvalds's avatar
Linus Torvalds committed
				}

				skb_reserve( skb, 2 );	/* 16 byte align */
				skb_put( skb, pkt_len );	/* Make room */
				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
				skb->protocol = eth_type_trans( skb, dev );
				netif_rx( skb );
				dev->stats.rx_packets++;
				dev->stats.rx_bytes += pkt_len;
Linus Torvalds's avatar
Linus Torvalds committed
			}
		}

		head->flag |= RMD1_OWN_CHIP;
		entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
	}
	lp->cur_rx &= RX_RING_MOD_MASK;

	/* From lance.c (Donald Becker): */
	/* We should check that at least two ring entries are free.	 If not,
	   we should free one and mark stats->rx_dropped++. */

	return 0;
}


static int lance_close( struct net_device *dev )
{
	struct lance_private *lp = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
	struct lance_ioreg	 *IO = lp->iobase;

	netif_stop_queue (dev);

	AREG = CSR0;

	DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n",
				  dev->name, DREG ));

	/* We stop the LANCE here -- it occasionally polls
	   memory if we don't. */
	DREG = CSR0_STOP;

	return 0;
}


/* Set or clear the multicast filter for this adaptor.
   num_addrs == -1		Promiscuous mode, receive all packets
   num_addrs == 0		Normal mode, clear multicast list
   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
						best-effort filtering.
 */

static void set_multicast_list( struct net_device *dev )
{
	struct lance_private *lp = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
	struct lance_ioreg	 *IO = lp->iobase;

	if (netif_running(dev))
		/* Only possible if board is already started */
		return;

	/* We take the simple way out and always enable promiscuous mode. */
	DREG = CSR0_STOP; /* Temporarily stop the lance. */

	if (dev->flags & IFF_PROMISC) {
		/* Log any net taps. */
		DPRINTK( 2, ( "%s: Promiscuous mode enabled.\n", dev->name ));
Linus Torvalds's avatar
Linus Torvalds committed
		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
	} else {
		short multicast_table[4];
		int num_addrs = netdev_mc_count(dev);
Linus Torvalds's avatar
Linus Torvalds committed
		int i;
		/* We don't use the multicast table, but rely on upper-layer
		 * filtering. */
		memset( multicast_table, (num_addrs == 0) ? 0 : -1,
				sizeof(multicast_table) );
		for( i = 0; i < 4; i++ )
			REGA( CSR8+i ) = multicast_table[i];
		REGA( CSR15 ) = 0; /* Unset promiscuous mode */
	}

	/*
	 * 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);

	/* Resume normal operation and reset AREG to CSR0 */
	REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT;
}


/* This is needed for old RieblCards and possible for new RieblCards */

static int lance_set_mac_address( struct net_device *dev, void *addr )
{
	struct lance_private *lp = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
	struct sockaddr *saddr = addr;
	int i;

	if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
		return -EOPNOTSUPP;
Linus Torvalds's avatar
Linus Torvalds committed

	if (netif_running(dev)) {
		/* Only possible while card isn't started */
		DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
					  dev->name ));
		return -EIO;
Linus Torvalds's avatar
Linus Torvalds committed
	}

	memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
	for( i = 0; i < 6; i++ )
		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
	lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 );
	/* set also the magic for future sessions */
	*RIEBL_MAGIC_ADDR = RIEBL_MAGIC;

Linus Torvalds's avatar
Linus Torvalds committed
#ifdef MODULE
static struct net_device *atarilance_dev;

Linus Torvalds's avatar
Linus Torvalds committed
{
	atarilance_dev = atarilance_probe(-1);
	if (IS_ERR(atarilance_dev))
		return PTR_ERR(atarilance_dev);
	return 0;
}

static void __exit atarilance_module_exit(void)
Linus Torvalds's avatar
Linus Torvalds committed
{
	unregister_netdev(atarilance_dev);
	free_irq(atarilance_dev->irq, atarilance_dev);
	free_netdev(atarilance_dev);
}
module_init(atarilance_module_init);
module_exit(atarilance_module_exit);
Linus Torvalds's avatar
Linus Torvalds committed
#endif /* MODULE */
Linus Torvalds's avatar
Linus Torvalds committed

/*
 * Local variables:
 *  c-indent-level: 4
 *  tab-width: 4
 * End:
 */