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; }
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; }
/*------------------------------------------------------------------------ * _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; }
/*------------------------------------------------------------------------ * _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 *)ðptr->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ðptr->devAddress[0], 0xffðptr->devAddress[1], 0xffðptr->devAddress[2], 0xffðptr->devAddress[3], 0xffðptr->devAddress[4], 0xffðptr->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; }