Skip to content
Snippets Groups Projects
e1000.c 155 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	inval_end = inval_start + roundup(sizeof(*rd), ARCH_DMA_MINALIGN);
    	invalidate_dcache_range(inval_start, inval_end);
    
    
    	if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD)
    		return 0;
    	/*DEBUGOUT("recv: packet len=%d \n", rd->length); */
    
    	/* Packet received, make sure the data are re-loaded from RAM. */
    	len = le32_to_cpu(rd->length);
    	invalidate_dcache_range((u32)packet,
    				(u32)packet + roundup(len, ARCH_DMA_MINALIGN));
    	NetReceive((uchar *)packet, len);
    
    	fill_rx(hw);
    	return 1;
    }
    
    /**************************************************************************
    TRANSMIT - Transmit a frame
    ***************************************************************************/
    
    static int e1000_transmit(struct eth_device *nic, void *txpacket, int length)
    
    	void *nv_packet = (void *)txpacket;
    
    	struct e1000_hw *hw = nic->priv;
    	struct e1000_tx_desc *txp;
    	int i = 0;
    
    	uint32_t flush_start, flush_end;
    
    
    	txp = tx_base + tx_tail;
    	tx_tail = (tx_tail + 1) % 8;
    
    
    	txp->buffer_addr = cpu_to_le64(virt_to_bus(hw->pdev, nv_packet));
    
    	txp->lower.data = cpu_to_le32(hw->txd_cmd | length);
    
    	txp->upper.data = 0;
    
    
    	/* Dump the packet into RAM so e1000 can pick them. */
    	flush_dcache_range((u32)nv_packet,
    			   (u32)nv_packet + roundup(length, ARCH_DMA_MINALIGN));
    	/* Dump the descriptor into RAM as well. */
    	flush_start = ((u32)txp) & ~(ARCH_DMA_MINALIGN - 1);
    	flush_end = flush_start + roundup(sizeof(*txp), ARCH_DMA_MINALIGN);
    	flush_dcache_range(flush_start, flush_end);
    
    
    	E1000_WRITE_REG(hw, TDT, tx_tail);
    
    
    	E1000_WRITE_FLUSH(hw);
    
    	while (1) {
    		invalidate_dcache_range(flush_start, flush_end);
    		if (le32_to_cpu(txp->upper.data) & E1000_TXD_STAT_DD)
    			break;
    
    		if (i++ > TOUT_LOOP) {
    			DEBUGOUT("e1000: tx timeout\n");
    			return 0;
    		}
    		udelay(10);	/* give the nic a chance to write to the register */
    	}
    	return 1;
    }
    
    /*reset function*/
    static inline int
    e1000_reset(struct eth_device *nic)
    {
    	struct e1000_hw *hw = nic->priv;
    
    	e1000_reset_hw(hw);
    	if (hw->mac_type >= e1000_82544) {
    		E1000_WRITE_REG(hw, WUC, 0);
    	}
    	return e1000_init_hw(nic);
    }
    
    /**************************************************************************
    DISABLE - Turn off ethernet interface
    ***************************************************************************/
    static void
    e1000_disable(struct eth_device *nic)
    {
    	struct e1000_hw *hw = nic->priv;
    
    	/* Turn off the ethernet interface */
    	E1000_WRITE_REG(hw, RCTL, 0);
    	E1000_WRITE_REG(hw, TCTL, 0);
    
    	/* Clear the transmit ring */
    	E1000_WRITE_REG(hw, TDH, 0);
    	E1000_WRITE_REG(hw, TDT, 0);
    
    	/* Clear the receive ring */
    	E1000_WRITE_REG(hw, RDH, 0);
    	E1000_WRITE_REG(hw, RDT, 0);
    
    	/* put the card in its initial state */
    #if 0
    	E1000_WRITE_REG(hw, CTRL, E1000_CTRL_RST);
    #endif
    	mdelay(10);
    
    }
    
    /**************************************************************************
    INIT - set up ethernet interface(s)
    ***************************************************************************/
    static int
    e1000_init(struct eth_device *nic, bd_t * bis)
    {
    	struct e1000_hw *hw = nic->priv;
    	int ret_val = 0;
    
    	ret_val = e1000_reset(nic);
    	if (ret_val < 0) {
    		if ((ret_val == -E1000_ERR_NOLINK) ||
    		    (ret_val == -E1000_ERR_TIMEOUT)) {
    
    			E1000_ERR(hw->nic, "Valid Link not detected\n");
    
    			E1000_ERR(hw->nic, "Hardware Initialization Failed\n");
    
    		}
    		return 0;
    	}
    	e1000_configure_tx(hw);
    	e1000_setup_rctl(hw);
    	e1000_configure_rx(hw);
    	return 1;
    }
    
    
    /******************************************************************************
     * Gets the current PCI bus type of hardware
     *
     * hw - Struct containing variables accessed by shared code
     *****************************************************************************/
    void e1000_get_bus_type(struct e1000_hw *hw)
    {
    	uint32_t status;
    
    	switch (hw->mac_type) {
    	case e1000_82542_rev2_0:
    	case e1000_82542_rev2_1:
    		hw->bus_type = e1000_bus_type_pci;
    		break;
    	case e1000_82571:
    	case e1000_82572:
    	case e1000_82573:
    
    	case e1000_82574:
    
    	case e1000_80003es2lan:
    		hw->bus_type = e1000_bus_type_pci_express;
    		break;
    	case e1000_ich8lan:
    		hw->bus_type = e1000_bus_type_pci_express;
    		break;
    	default:
    		status = E1000_READ_REG(hw, STATUS);
    		hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
    				e1000_bus_type_pcix : e1000_bus_type_pci;
    		break;
    	}
    }
    
    
    /* A list of all registered e1000 devices */
    static LIST_HEAD(e1000_hw_list);
    
    
    /**************************************************************************
    PROBE - Look for an adapter, this routine's visible to the outside
    You should omit the last argument struct pci_device * for a non-PCI NIC
    ***************************************************************************/
    int
    e1000_initialize(bd_t * bis)
    {
    
    	DEBUGFUNC();
    
    
    	/* Find and probe all the matching PCI devices */
    	for (i = 0; (devno = pci_find_devices(e1000_supported, i)) >= 0; i++) {
    		u32 val;
    
    		/*
    		 * These will never get freed due to errors, this allows us to
    		 * perform SPI EEPROM programming from U-boot, for example.
    		 */
    		struct eth_device *nic = malloc(sizeof(*nic));
    		struct e1000_hw *hw = malloc(sizeof(*hw));
    		if (!nic || !hw) {
    			printf("e1000#%u: Out of Memory!\n", i);
    
    		/* Make sure all of the fields are initially zeroed */
    
    		memset(nic, 0, sizeof(*nic));
    
    		/* Assign the passed-in values */
    		hw->cardnum = i;
    
    		hw->pdev = devno;
    
    		/* Generate a card name */
    		sprintf(nic->name, "e1000#%u", hw->cardnum);
    
    		/* Print a debug message with the IO base address */
    		pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &val);
    		E1000_DBG(nic, "iobase 0x%08x\n", val & 0xfffffff0);
    
    		/* Try to enable I/O accesses and bus-mastering */
    		val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
    		pci_write_config_dword(devno, PCI_COMMAND, val);
    
    		/* Make sure it worked */
    		pci_read_config_dword(devno, PCI_COMMAND, &val);
    		if (!(val & PCI_COMMAND_MEMORY)) {
    			E1000_ERR(nic, "Can't enable I/O memory\n");
    			continue;
    		}
    		if (!(val & PCI_COMMAND_MASTER)) {
    			E1000_ERR(nic, "Can't enable bus-mastering\n");
    			continue;
    		}
    
    
    		/* Are these variables needed? */
    		hw->fc = e1000_fc_default;
    		hw->original_fc = e1000_fc_default;
    		hw->autoneg_failed = 0;
    
    		hw->autoneg = 1;
    
    York Sun's avatar
    York Sun committed
    		hw->get_link_status = true;
    
    		hw->hw_addr = pci_map_bar(devno,	PCI_BASE_ADDRESS_0,
    							PCI_REGION_MEM);
    
    		hw->mac_type = e1000_undefined;
    
    		/* MAC and Phy settings */
    
    		if (e1000_sw_init(nic) < 0) {
    			E1000_ERR(nic, "Software init failed\n");
    			continue;
    
    		if (e1000_check_phy_reset_block(hw))
    
    			E1000_ERR(nic, "PHY Reset is blocked!\n");
    
    
    		/* Basic init was OK, reset the hardware and allow SPI access */
    
    		e1000_reset_hw(hw);
    
    		list_add_tail(&hw->list_node, &e1000_hw_list);
    
    #ifndef CONFIG_E1000_NO_NVM
    
    		/* Validate the EEPROM and get chipset information */
    
    #if !defined(CONFIG_MVBC_1G)
    
    		if (e1000_init_eeprom_params(hw)) {
    
    			E1000_ERR(nic, "EEPROM is invalid!\n");
    			continue;
    
    		if (e1000_validate_eeprom_checksum(hw))
    
    		e1000_read_mac_addr(nic);
    
    		e1000_get_bus_type(hw);
    
    #ifndef CONFIG_E1000_NO_NVM
    
    		printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n       ",
    
    		       nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2],
    		       nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]);
    
    #else
    		memset(nic->enetaddr, 0, 6);
    		printf("e1000: no NVM\n");
    #endif
    
    		/* Set up the function pointers and register the device */
    
    		nic->init = e1000_init;
    		nic->recv = e1000_poll;
    		nic->send = e1000_transmit;
    		nic->halt = e1000_disable;
    		eth_register(nic);
    	}
    
    
    struct e1000_hw *e1000_find_card(unsigned int cardnum)
    {
    	struct e1000_hw *hw;
    
    	list_for_each_entry(hw, &e1000_hw_list, list_node)
    		if (hw->cardnum == cardnum)
    			return hw;
    
    	return NULL;
    }
    
    #ifdef CONFIG_CMD_E1000
    static int do_e1000(cmd_tbl_t *cmdtp, int flag,
    		int argc, char * const argv[])
    {
    	struct e1000_hw *hw;
    
    	if (argc < 3) {
    		cmd_usage(cmdtp);
    		return 1;
    	}
    
    	/* Make sure we can find the requested e1000 card */
    	hw = e1000_find_card(simple_strtoul(argv[1], NULL, 10));
    	if (!hw) {
    		printf("e1000: ERROR: No such device: e1000#%s\n", argv[1]);
    		return 1;
    	}
    
    	if (!strcmp(argv[2], "print-mac-address")) {
    		unsigned char *mac = hw->nic->enetaddr;
    		printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
    			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    		return 0;
    	}
    
    #ifdef CONFIG_E1000_SPI
    	/* Handle the "SPI" subcommand */
    	if (!strcmp(argv[2], "spi"))
    		return do_e1000_spi(cmdtp, hw, argc - 3, argv + 3);
    #endif
    
    	cmd_usage(cmdtp);
    	return 1;
    }
    
    U_BOOT_CMD(
    	e1000, 7, 0, do_e1000,
    	"Intel e1000 controller management",
    	/*  */"<card#> print-mac-address\n"
    #ifdef CONFIG_E1000_SPI
    	"e1000 <card#> spi show [<offset> [<length>]]\n"
    	"e1000 <card#> spi dump <addr> <offset> <length>\n"
    	"e1000 <card#> spi program <addr> <offset> <length>\n"
    	"e1000 <card#> spi checksum [update]\n"
    #endif
    	"       - Manage the Intel E1000 PCI device"
    );
    #endif /* not CONFIG_CMD_E1000 */