コード例 #1
0
ファイル: smc91111.c プロジェクト: 0xFelix/u-boot-edminiv2
/*
 . Function: smc_enable
 . Purpose: let the chip talk to the outside work
 . Method:
 .	1.  Enable the transmitter
 .	2.  Enable the receiver
 .	3.  Enable interrupts
*/
static void smc_enable(struct eth_device *dev)
{
	PRINTK2("%s: smc_enable\n", SMC_DEV_NAME);
	SMC_SELECT_BANK( dev, 0 );
	/* see the header file for options in TCR/RCR DEFAULT*/
	SMC_outw( dev, TCR_DEFAULT, TCR_REG );
	SMC_outw( dev, RCR_DEFAULT, RCR_REG );

	/* clear MII_DIS */
/*	smc_write_phy_register(PHY_CNTL_REG, 0x0000); */
}
コード例 #2
0
ファイル: smc91111.c プロジェクト: 0xFelix/u-boot-edminiv2
/*
 . Function: smc_reset( void )
 . Purpose:
 .	This sets the SMC91111 chip to its normal state, hopefully from whatever
 .	mess that any other DOS driver has put it in.
 .
 . Maybe I should reset more registers to defaults in here?  SOFTRST  should
 . do that for me.
 .
 . Method:
 .	1.  send a SOFT RESET
 .	2.  wait for it to finish
 .	3.  enable autorelease mode
 .	4.  reset the memory management unit
 .	5.  clear all interrupts
 .
*/
static void smc_reset (struct eth_device *dev)
{
	PRINTK2 ("%s: smc_reset\n", SMC_DEV_NAME);

	/* This resets the registers mostly to defaults, but doesn't
	   affect EEPROM.  That seems unnecessary */
	SMC_SELECT_BANK (dev, 0);
	SMC_outw (dev, RCR_SOFTRST, RCR_REG);

	/* Setup the Configuration Register */
	/* This is necessary because the CONFIG_REG is not affected */
	/* by a soft reset */

	SMC_SELECT_BANK (dev, 1);
#if defined(CONFIG_SMC91111_EXT_PHY)
	SMC_outw (dev, CONFIG_DEFAULT | CONFIG_EXT_PHY, CONFIG_REG);
#else
	SMC_outw (dev, CONFIG_DEFAULT, CONFIG_REG);
#endif


	/* Release from possible power-down state */
	/* Configuration register is not affected by Soft Reset */
	SMC_outw (dev, SMC_inw (dev, CONFIG_REG) | CONFIG_EPH_POWER_EN,
		CONFIG_REG);

	SMC_SELECT_BANK (dev, 0);

	/* this should pause enough for the chip to be happy */
	udelay (10);

	/* Disable transmit and receive functionality */
	SMC_outw (dev, RCR_CLEAR, RCR_REG);
	SMC_outw (dev, TCR_CLEAR, TCR_REG);

	/* set the control register */
	SMC_SELECT_BANK (dev, 1);
	SMC_outw (dev, CTL_DEFAULT, CTL_REG);

	/* Reset the MMU */
	SMC_SELECT_BANK (dev, 2);
	smc_wait_mmu_release_complete (dev);
	SMC_outw (dev, MC_RESET, MMU_CMD_REG);
	while (SMC_inw (dev, MMU_CMD_REG) & MC_BUSY)
		udelay (1);	/* Wait until not busy */

	/* Note:  It doesn't seem that waiting for the MMU busy is needed here,
	   but this is a place where future chipsets _COULD_ break.  Be wary
	   of issuing another MMU command right after this */

	/* Disable all interrupts */
	SMC_outb (dev, 0, IM_REG);
}
コード例 #3
0
static inline void SMC_outsw(dword offset, uchar* buf, dword len)
{
	volatile word *p = (volatile word *)buf;

	while (len-- > 0) {
		SMC_outw(*p++, offset);
		barrier();
		*(volatile u32*)(0xc0000000);
	}
}
コード例 #4
0
ファイル: eeprom.c プロジェクト: Aircell/asp-u-boot
static int write_eeprom_reg(struct eth_device *dev, u16 value, u16 reg)
{
	int timeout;

	SMC_SELECT_BANK(dev, 2);
	SMC_outw(dev, reg, PTR_REG);

	SMC_SELECT_BANK(dev, 1);
	SMC_outw(dev, value, GP_REG);
	SMC_outw(dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT | CTL_STORE, CTL_REG);
	timeout = 100;
	while ((SMC_inw(dev, CTL_REG) & CTL_STORE) && --timeout)
		udelay (100);
	if (timeout == 0) {
		printf("Timeout Writing EEPROM register %02x\n", reg);
		return 0;
	}

	return 1;
}
コード例 #5
0
ファイル: eeprom.c プロジェクト: Aircell/asp-u-boot
static u16 read_eeprom_reg(struct eth_device *dev, u16 reg)
{
	int timeout;

	SMC_SELECT_BANK(dev, 2);
	SMC_outw(dev, reg, PTR_REG);

	SMC_SELECT_BANK(dev, 1);
	SMC_outw(dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT | CTL_RELOAD,
		 CTL_REG);
	timeout = 100;
	while((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
		udelay(100);
	if (timeout == 0) {
		printf("Timeout Reading EEPROM register %02x\n", reg);
		return 0;
	}

	return SMC_inw (dev, GP_REG);
}
コード例 #6
0
static void smc_hardware_send_pkt(unsigned long data)
{
	struct net_device *dev = (struct net_device *)data;
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;
	struct sk_buff *skb;
	unsigned int packet_no, len;
	unsigned char *buf;
	unsigned long flags;

	DBG(3, "%s: %s\n", dev->name, __func__);

	if (!smc_special_trylock(&lp->lock, flags)) {
		netif_stop_queue(dev);
		tasklet_schedule(&lp->tx_task);
		return;
	}

	skb = lp->pending_tx_skb;
	if (unlikely(!skb)) {
		smc_special_unlock(&lp->lock, flags);
		return;
	}
	lp->pending_tx_skb = NULL;

	packet_no = SMC_GET_AR(lp);
	if (unlikely(packet_no & AR_FAILED)) {
		printk("%s: Memory allocation failed.\n", dev->name);
		dev->stats.tx_errors++;
		dev->stats.tx_fifo_errors++;
		smc_special_unlock(&lp->lock, flags);
		goto done;
	}

	
	SMC_SET_PN(lp, packet_no);
	SMC_SET_PTR(lp, PTR_AUTOINC);

	buf = skb->data;
	len = skb->len;
	DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n",
		dev->name, packet_no, len, len, buf);
	PRINT_PKT(buf, len);

	
	SMC_PUT_PKT_HDR(lp, 0, len + 6);

	
	SMC_PUSH_DATA(lp, buf, len & ~1);

	
	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));

	
	if (THROTTLE_TX_PKTS)
		netif_stop_queue(dev);

	
	SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
	smc_special_unlock(&lp->lock, flags);

	dev->trans_start = jiffies;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += len;

	SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT);

done:	if (!THROTTLE_TX_PKTS)
		netif_wake_queue(dev);

	dev_kfree_skb(skb);
}
コード例 #7
0
ファイル: smc91111.c プロジェクト: 0xFelix/u-boot-edminiv2
/*
 . Function:  smc_send(struct net_device * )
 . Purpose:
 .	This sends the actual packet to the SMC9xxx chip.
 .
 . Algorithm:
 .	First, see if a saved_skb is available.
 .		( this should NOT be called if there is no 'saved_skb'
 .	Now, find the packet number that the chip allocated
 .	Point the data pointers at it in memory
 .	Set the length word in the chip's memory
 .	Dump the packet to chip memory
 .	Check if a last byte is needed ( odd length packet )
 .		if so, set the control flag right
 .	Tell the card to send it
 .	Enable the transmit interrupt, so I know if it failed
 .	Free the kernel data if I actually sent it.
*/
static int smc_send(struct eth_device *dev, void *packet, int packet_length)
{
	byte packet_no;
	byte *buf;
	int length;
	int numPages;
	int try = 0;
	int time_out;
	byte status;
	byte saved_pnr;
	word saved_ptr;

	/* save PTR and PNR registers before manipulation */
	SMC_SELECT_BANK (dev, 2);
	saved_pnr = SMC_inb( dev, PN_REG );
	saved_ptr = SMC_inw( dev, PTR_REG );

	PRINTK3 ("%s: smc_hardware_send_packet\n", SMC_DEV_NAME);

	length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN;

	/* allocate memory
	 ** The MMU wants the number of pages to be the number of 256 bytes
	 ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
	 **
	 ** The 91C111 ignores the size bits, but the code is left intact
	 ** for backwards and future compatibility.
	 **
	 ** Pkt size for allocating is data length +6 (for additional status
	 ** words, length and ctl!)
	 **
	 ** If odd size then last byte is included in this header.
	 */
	numPages = ((length & 0xfffe) + 6);
	numPages >>= 8;		/* Divide by 256 */

	if (numPages > 7) {
		printf ("%s: Far too big packet error. \n", SMC_DEV_NAME);
		return 0;
	}

	/* now, try to allocate the memory */
	SMC_SELECT_BANK (dev, 2);
	SMC_outw (dev, MC_ALLOC | numPages, MMU_CMD_REG);

	/* FIXME: the ALLOC_INT bit never gets set *
	 * so the following will always give a	   *
	 * memory allocation error.		   *
	 * same code works in armboot though	   *
	 * -ro
	 */

again:
	try++;
	time_out = MEMORY_WAIT_TIME;
	do {
		status = SMC_inb (dev, SMC91111_INT_REG);
		if (status & IM_ALLOC_INT) {
			/* acknowledge the interrupt */
			SMC_outb (dev, IM_ALLOC_INT, SMC91111_INT_REG);
			break;
		}
	} while (--time_out);

	if (!time_out) {
		PRINTK2 ("%s: memory allocation, try %d failed ...\n",
			 SMC_DEV_NAME, try);
		if (try < SMC_ALLOC_MAX_TRY)
			goto again;
		else
			return 0;
	}
コード例 #8
0
/*
 * This is called to actually send a packet to the chip.
 */
static void smc_hardware_send_pkt(unsigned long data)
{
	struct net_device *dev = (struct net_device *)data;
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;
	struct sk_buff *skb;
	unsigned int packet_no, len;
	unsigned char *buf;
	unsigned long flags;

	DBG(3, "%s: %s\n", dev->name, __func__);

	if (!smc_special_trylock(&lp->lock, flags)) {
		netif_stop_queue(dev);
		tasklet_schedule(&lp->tx_task);
		return;
	}

	skb = lp->pending_tx_skb;
	if (unlikely(!skb)) {
		smc_special_unlock(&lp->lock, flags);
		return;
	}
	lp->pending_tx_skb = NULL;

	packet_no = SMC_GET_AR(lp);
	if (unlikely(packet_no & AR_FAILED)) {
		printk("%s: Memory allocation failed.\n", dev->name);
		dev->stats.tx_errors++;
		dev->stats.tx_fifo_errors++;
		smc_special_unlock(&lp->lock, flags);
		goto done;
	}

	/* point to the beginning of the packet */
	SMC_SET_PN(lp, packet_no);
	SMC_SET_PTR(lp, PTR_AUTOINC);

	buf = skb->data;
	len = skb->len;
	DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n",
		dev->name, packet_no, len, len, buf);
	PRINT_PKT(buf, len);

	/*
	 * Send the packet length (+6 for status words, length, and ctl.
	 * The card will pad to 64 bytes with zeroes if packet is too small.
	 */
	SMC_PUT_PKT_HDR(lp, 0, len + 6);

	/* send the actual data */
	SMC_PUSH_DATA(lp, buf, len & ~1);

	/* Send final ctl word with the last byte if there is one */
	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));

	/*
	 * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
	 * have the effect of having at most one packet queued for TX
	 * in the chip's memory at all time.
	 *
	 * If THROTTLE_TX_PKTS is not set then the queue is stopped only
	 * when memory allocation (MC_ALLOC) does not succeed right away.
	 */
	if (THROTTLE_TX_PKTS)
		netif_stop_queue(dev);

	/* queue the packet for TX */
	SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
	smc_special_unlock(&lp->lock, flags);

	dev->trans_start = jiffies;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += len;

	SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT);

done:	if (!THROTTLE_TX_PKTS)
		netif_wake_queue(dev);

	dev_kfree_skb(skb);
}