Example #1
0
static int
igb_read_mac_addr(struct e1000_hw *hw)
{
	u32 rar_high;
	u32 rar_low;
	u16 i;

	rar_high = E1000_READ_REG(hw, E1000_RAH(0));
	rar_low = E1000_READ_REG(hw, E1000_RAL(0));

	for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
		hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));

	for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
		hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));

	for (i = 0; i < ETH_ADDR_LEN; i++)
		hw->mac.addr[i] = hw->mac.perm_addr[i];

	return E1000_SUCCESS;

}
Example #2
0
File: e1000.c Project: MG47/JOS-MG
int E1000_attach_function(struct pci_func *pcif)
{
    pci_func_enable(pcif);
    e1000_bar_base = mmio_map_region(pcif->reg_base[0], pcif->reg_size[0] );

    /* Debugging*/
    //    cprintf("value of device status register%x\n", *(e1000_bar_address+ 0x00008/4)); 

	int i;
	for (i = 0; i < E1000_TX_DESCS; ++i) 
    {
		tx_descriptors[i].status = E1000_TXD_STAT_DD;
	}

    /* Transmitter registers*/
	e1000_bar_base[E1000_TDH / 4] = 0;
	e1000_bar_base[E1000_TDT / 4] = 0;
    
    e1000_bar_base[E1000_TDBAL / 4] = PADDR(tx_descriptors);
	e1000_bar_base[E1000_TDBAH / 4] = 0;
	e1000_bar_base[E1000_TDLEN / 4] = sizeof(struct tx_desc) * E1000_TX_DESCS;

	e1000_bar_base[E1000_TCTL / 4] |= E1000_TCTL_EN;
	e1000_bar_base[E1000_TCTL / 4] |= E1000_TCTL_PSP;

	e1000_bar_base[E1000_TCTL / 4] &= ~E1000_TCTL_CT;
	e1000_bar_base[E1000_TCTL / 4] |= (E1000_TCTL_CT_VAL << 4);

	e1000_bar_base[E1000_TCTL / 4] &= ~E1000_TCTL_COLD;
	e1000_bar_base[E1000_TCTL / 4] |= (E1000_TCTL_COLD_VAL << 12);

	e1000_bar_base[E1000_TIPG / 4] = (E1000_TIPG_IPGT_VAL ) | (E1000_TIPG_IPGR1_VAL << 10)
	                                      | (E1000_TIPG_IPGR2_VAL << 20) | (E1000_TIPG_RESERVED_VAL << 30);

    /* Receiver registers */
	
  
    e1000_bar_base[E1000_RDBAL / 4] = PADDR(rx_descriptors);
	e1000_bar_base[E1000_RDBAH / 4] = 0;
	e1000_bar_base[E1000_RDLEN / 4] = sizeof(struct rx_desc) * E1000_RX_DESCS;



    for (i = 0; i < E1000_TX_DESCS; ++i) 
    {
		rx_descriptors[i].addr = PADDR(rx_bufs[i]);
	}

    e1000_bar_base[E1000_IMS / 4] = 0;
    for (i = 0; i < E1000_N_MTA_ELEMS; ++i) 
    {
		e1000_bar_base[E1000_MTA / 4] = 0;
	}

    e1000_bar_base[E1000_RDH / 4] = 0;
	e1000_bar_base[E1000_RDT / 4] = E1000_RX_DESCS - 1;
  
    e1000_bar_base[E1000_RCTL / 4] |= E1000_RCTL_EN;
    e1000_bar_base[E1000_RCTL / 4] &= ~E1000_RCTL_LPE;
	e1000_bar_base[E1000_RCTL / 4] |= E1000_RCTL_BAM;
    e1000_bar_base[E1000_RCTL / 4] |= E1000_RCTL_SECRC;


    e1000_bar_base[E1000_RAL(0) / 4] = 0x12005452;
    e1000_bar_base[E1000_RAH(0) / 4] = 0x5634;
    e1000_bar_base[E1000_RAH(0) / 4] |= E1000_RAH_AV;

    /* Test tx_packet transmit*/
    /* Debugging
        char d='a';
        E1000_tx_packet(&d, 1);
    */
    return 0;
}
Example #3
0
/*------------------------------------------------------------------------
 * _82545EM_init_hw - Initialize the hardware
 *------------------------------------------------------------------------
 */
local status _82545EM_init_hw(
	struct 	ether *ethptr
	)
{
	uint16 i;
	uint32 ctrl;
	uint16 	mii_autoneg_adv_reg, mii_1000t_ctrl_reg;
	uint16 	phy_data, phy_ctrl, phy_status;

	/* Setup the receive address */
	/* Zero out the other receive addresses */

	for (i = 1; i < E1000_82545EM_RAR_ENTRIES; i++) {
		e1000_io_writel(ethptr->iobase, E1000_RAL(i), 0);
	    	e1000_io_flush(ethptr->iobase);
	    	e1000_io_writel(ethptr->iobase, E1000_RAH(i), 0);
	    	e1000_io_flush(ethptr->iobase);
	}

	/* Zero out the Multicast HASH table */

	for (i = 0; i < E1000_82545EM_MTA_ENTRIES; i++) {
		e1000_io_writel(ethptr->iobase, E1000_MTA + (i << 2), 0);
	    	e1000_io_flush(ethptr->iobase);
	}

	/* Configure copper link settings */

	kprintf("Setup link ... \n");

	ctrl = e1000_io_readl(ethptr->iobase, E1000_CTRL);
	ctrl |= E1000_CTRL_SLU;
	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
	e1000_io_writel(ethptr->iobase, E1000_CTRL, ctrl);

    	if (_82545EM_read_phy_reg(ethptr, M88E1000_PHY_SPEC_CTRL, 
			       &phy_data) != OK)
		return SYSERR;

	phy_data |= M88E1000_PSCR_AUTO_X_MODE;
	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;

	if (_82545EM_write_phy_reg(ethptr, M88E1000_PHY_SPEC_CTRL, 
				phy_data) != OK)
		return SYSERR;

	/* Commit the changes. */

    	if (_82545EM_read_phy_reg(ethptr, E1000_PHY_CONTROL, 
				  &phy_ctrl) != OK)
		return SYSERR;

	phy_ctrl |= E1000_MII_CR_RESET;
	
	if (_82545EM_write_phy_reg(ethptr, E1000_PHY_CONTROL, 
				   phy_ctrl) != OK)
		return SYSERR;
	
	DELAY(1);

	/* Setup autoneg and flow control advertisement and perform 	*/
	/* 	autonegotiation. 					*/

	if (_82545EM_read_phy_reg(ethptr, E1000_PHY_AUTONEG_ADV, 
			       &mii_autoneg_adv_reg) != OK)
		return SYSERR;

    	if (_82545EM_read_phy_reg(ethptr, E1000_PHY_1000T_CTRL, 
			       &mii_1000t_ctrl_reg) != OK)
		return SYSERR;

	mii_autoneg_adv_reg |= (E1000_NWAY_AR_100TX_FD_CAPS |
				E1000_NWAY_AR_100TX_HD_CAPS |
				E1000_NWAY_AR_10T_FD_CAPS   |
				E1000_NWAY_AR_10T_HD_CAPS);
	mii_1000t_ctrl_reg &= ~E1000_CR_1000T_HD_CAPS;
	mii_1000t_ctrl_reg |= E1000_CR_1000T_FD_CAPS;

	mii_autoneg_adv_reg &= ~(E1000_NWAY_AR_ASM_DIR | 
				 E1000_NWAY_AR_PAUSE);

	if (_82545EM_write_phy_reg(ethptr, E1000_PHY_AUTONEG_ADV, 
				mii_autoneg_adv_reg) != OK)
		return SYSERR;

	if (_82545EM_write_phy_reg(ethptr, E1000_PHY_1000T_CTRL, 
				mii_1000t_ctrl_reg) != OK)
		return SYSERR;

	/* Restart auto-negotiation. */

	if (_82545EM_read_phy_reg(ethptr, E1000_PHY_CONTROL, 
				  &phy_ctrl) != OK)
		return SYSERR;

    	phy_ctrl |= (E1000_MII_CR_AUTO_NEG_EN | 
		     E1000_MII_CR_RESTART_AUTO_NEG);

	if (_82545EM_write_phy_reg(ethptr, E1000_PHY_CONTROL, 
				   phy_ctrl) != OK)
		return SYSERR;

	/* Wait for auto-negotiation to complete */

	for (;;) {
		if (_82545EM_read_phy_reg(ethptr, E1000_PHY_STATUS, 
				       &phy_status) != OK)
			DELAY(10);
		    
		if (_82545EM_read_phy_reg(ethptr, E1000_PHY_STATUS, 
				       &phy_status) != OK)
			return SYSERR;
		
		if ((phy_status & E1000_MII_SR_LINK_STATUS) && 
		    (phy_status & E1000_MII_SR_AUTONEG_COMPLETE)) {
			break;
		}
		
		MDELAY(100);
	}

	ctrl = e1000_io_readl(ethptr->iobase, E1000_CTRL);
	ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
	e1000_io_writel(ethptr->iobase, E1000_CTRL, ctrl);

	return OK;
}
Example #4
0
/*------------------------------------------------------------------------
 * _82545EMInit - initialize Intel 82545EM Ethernet NIC
 *------------------------------------------------------------------------
 */
status 	_82545EMInit(
	struct 	ether *ethptr
	)
{
	struct	e1000_tx_desc* txRingPtr;
	struct	e1000_rx_desc*	rxRingPtr;
	uint16  command;
	int32	i;
	uint32  rar_low, rar_high, bufptr;

	/* Read PCI configuration information */
	/* Read I/O base address */

	pci_bios_read_config_dword(ethptr->pcidev, E1000_PCI_IOBASE,
			(uint32 *)&ethptr->iobase);
	ethptr->iobase &= ~1;
	ethptr->iobase &= 0xffff; /* the low bit is set to indicate I/O */

	/* Read interrupt line number */

	pci_bios_read_config_byte (ethptr->pcidev, E1000_PCI_IRQ,
			(byte *)&(ethptr->dev->dvirq));

	/* Enable PCI bus master, I/O port access */

	pci_bios_read_config_word(ethptr->pcidev, E1000_PCI_COMMAND, 
			&command);
	command |= E1000_PCI_CMD_MASK;
	pci_bios_write_config_word(ethptr->pcidev, E1000_PCI_COMMAND, 
			command);

	/* Read the MAC address */
	
	rar_low = e1000_io_readl(ethptr->iobase, E1000_RAL(0));
	rar_high = e1000_io_readl(ethptr->iobase, E1000_RAH(0));

	for (i = 0; i < ETH_ADDR_LEN; i++) 
		ethptr->devAddress[i] = (byte)(rar_low >> (i*8));
	for (i = 0; i < ETH_ADDR_LEN; i++)
		ethptr->devAddress[i + 4] = (byte)(rar_high >> (i*8));

	kprintf("MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n",
			0xff&ethptr->devAddress[0],
			0xff&ethptr->devAddress[1],
			0xff&ethptr->devAddress[2],
			0xff&ethptr->devAddress[3],
			0xff&ethptr->devAddress[4],
			0xff&ethptr->devAddress[5]);

	/* Initialize structure pointers */

	ethptr->rxRingSize = E1000_RX_RING_SIZE;
	ethptr->txRingSize = E1000_TX_RING_SIZE;
	ethptr->isem = semcreate(0);
	ethptr->osem = semcreate(ethptr->txRingSize);

	/* Rings must be aligned on a 16-byte boundary */
	
	ethptr->rxRing = (void *)getmem((ethptr->rxRingSize + 1)
			* E1000_RDSIZE);
	ethptr->txRing = (void *)getmem((ethptr->txRingSize + 1)
			* E1000_TDSIZE);
	ethptr->rxRing = (void *)(((uint32)ethptr->rxRing + 0xf) & ~0xf);
	ethptr->txRing = (void *)(((uint32)ethptr->txRing + 0xf) & ~0xf);
	
	/* Buffers are highly recommended to be allocated on cache-line */
	/* 	size (64-byte for E8400) 				*/
	
	ethptr->rxBufs = (void *)getmem((ethptr->rxRingSize + 1) 
			* ETH_BUF_SIZE);
	ethptr->txBufs = (void *)getmem((ethptr->txRingSize + 1) 
			* ETH_BUF_SIZE);
	ethptr->rxBufs = (void *)(((uint32)ethptr->rxBufs + 0x3f) 
			& ~0x3f);
	ethptr->txBufs = (void *)(((uint32)ethptr->txBufs + 0x3f) 
			& ~0x3f);

	if ( (SYSERR == (uint32)ethptr->rxBufs) || 
	     (SYSERR == (uint32)ethptr->txBufs) ) {
		return SYSERR;
	}

	/* Set buffer pointers and rings to zero */
	
	memset(ethptr->rxBufs, '\0', ethptr->rxRingSize * ETH_BUF_SIZE);
	memset(ethptr->txBufs, '\0', ethptr->txRingSize * ETH_BUF_SIZE);
	memset(ethptr->rxRing, '\0', E1000_RDSIZE * ethptr->rxRingSize);
	memset(ethptr->txRing, '\0', E1000_TDSIZE * ethptr->txRingSize);

	/* Insert the buffer into descriptor ring */
	
	rxRingPtr = (struct e1000_rx_desc *)ethptr->rxRing;
	bufptr = (uint32)ethptr->rxBufs;
	for (i = 0; i < ethptr->rxRingSize; i++) {
		rxRingPtr->buffer_addr = (uint64)bufptr;
		rxRingPtr++;
		bufptr += ETH_BUF_SIZE;
	}

	txRingPtr = (struct e1000_tx_desc *)ethptr->txRing;
	bufptr = (uint32)ethptr->txBufs;
	for (i = 0; i < ethptr->txRingSize; i++) {
		txRingPtr->buffer_addr = (uint64)bufptr;
		txRingPtr++;
		bufptr += ETH_BUF_SIZE;
	}

	/* Reset packet buffer allocation to default */

	e1000_io_writel(ethptr->iobase, E1000_PBA, E1000_PBA_48K);

	/* Reset the NIC to bring it into a known state and initialize it */

	_82545EM_reset_hw(ethptr);

	/* Initialize the hardware */

	if (_82545EM_init_hw(ethptr) != OK)
		return SYSERR;

	/* Configure the NIC */

	e1000_io_writel(ethptr->iobase, E1000_AIT, 0);

	/* Configure the RX */

	_82545EM_configure_rx(ethptr);
	
	/* Configure the TX */

	_82545EM_configure_tx(ethptr);

	/* Register the interrupt and enable interrupt */
	
	set_evec(ethptr->dev->dvirq + IRQBASE, (uint32)e1000Dispatch);
	e1000IrqEnable(ethptr);

	return OK;
}