⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ich8lan.c

📁 grub源码分析文档
💻 C
📖 第 1 页 / 共 5 页
字号:
			    hw->nvm.flash_base_addr;	do {		udelay(1);		/* Steps */		ret_val = e1000_flash_cycle_init_ich8lan(hw);		if (ret_val)			break;		hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */		hsflctl.hsf_ctrl.fldbcount = size -1;		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;		ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);		ew32flash(ICH_FLASH_FADDR, flash_linear_addr);		if (size == 1)			flash_data = (u32)data & 0x00FF;		else			flash_data = (u32)data;		ew32flash(ICH_FLASH_FDATA0, flash_data);		/*		 * check if FCERR is set to 1 , if set to 1, clear it		 * and try the whole sequence a few more times else done		 */		ret_val = e1000_flash_cycle_ich8lan(hw,					       ICH_FLASH_WRITE_COMMAND_TIMEOUT);		if (!ret_val)			break;		/*		 * If we're here, then things are most likely		 * completely hosed, but if the error condition		 * is detected, it won't hurt to give it another		 * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.		 */		hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);		if (hsfsts.hsf_status.flcerr == 1)			/* Repeat for some time before giving up. */			continue;		if (hsfsts.hsf_status.flcdone == 0) {			hw_dbg(hw, "Timeout error - flash cycle "				 "did not complete.");			break;		}	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);	return ret_val;}/** *  e1000_write_flash_byte_ich8lan - Write a single byte to NVM *  @hw: pointer to the HW structure *  @offset: The index of the byte to read. *  @data: The byte to write to the NVM. * *  Writes a single byte to the NVM using the flash access registers. **/static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,					  u8 data){	u16 word = (u16)data;	return e1000_write_flash_data_ich8lan(hw, offset, 1, word);}/** *  e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM *  @hw: pointer to the HW structure *  @offset: The offset of the byte to write. *  @byte: The byte to write to the NVM. * *  Writes a single byte to the NVM using the flash access registers. *  Goes through a retry algorithm before giving up. **/static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,						u32 offset, u8 byte){	s32 ret_val;	u16 program_retries;	ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);	if (!ret_val)		return ret_val;	for (program_retries = 0; program_retries < 100; program_retries++) {		hw_dbg(hw, "Retrying Byte %2.2X at offset %u\n", byte, offset);		udelay(100);		ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);		if (!ret_val)			break;	}	if (program_retries == 100)		return -E1000_ERR_NVM;	return 0;}/** *  e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM *  @hw: pointer to the HW structure *  @bank: 0 for first bank, 1 for second bank, etc. * *  Erases the bank specified. Each bank is a 4k block. Banks are 0 based. *  bank N is 4096 * N + flash_reg_addr. **/static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank){	struct e1000_nvm_info *nvm = &hw->nvm;	union ich8_hws_flash_status hsfsts;	union ich8_hws_flash_ctrl hsflctl;	u32 flash_linear_addr;	/* bank size is in 16bit words - adjust to bytes */	u32 flash_bank_size = nvm->flash_bank_size * 2;	s32 ret_val;	s32 count = 0;	s32 iteration;	s32 sector_size;	s32 j;	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);	/*	 * Determine HW Sector size: Read BERASE bits of hw flash status	 * register	 * 00: The Hw sector is 256 bytes, hence we need to erase 16	 *     consecutive sectors.  The start index for the nth Hw sector	 *     can be calculated as = bank * 4096 + n * 256	 * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.	 *     The start index for the nth Hw sector can be calculated	 *     as = bank * 4096	 * 10: The Hw sector is 8K bytes, nth sector = bank * 8192	 *     (ich9 only, otherwise error condition)	 * 11: The Hw sector is 64K bytes, nth sector = bank * 65536	 */	switch (hsfsts.hsf_status.berasesz) {	case 0:		/* Hw sector size 256 */		sector_size = ICH_FLASH_SEG_SIZE_256;		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256;		break;	case 1:		sector_size = ICH_FLASH_SEG_SIZE_4K;		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K;		break;	case 2:		if (hw->mac.type == e1000_ich9lan) {			sector_size = ICH_FLASH_SEG_SIZE_8K;			iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K;		} else {			return -E1000_ERR_NVM;		}		break;	case 3:		sector_size = ICH_FLASH_SEG_SIZE_64K;		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K;		break;	default:		return -E1000_ERR_NVM;	}	/* Start with the base address, then add the sector offset. */	flash_linear_addr = hw->nvm.flash_base_addr;	flash_linear_addr += (bank) ? (sector_size * iteration) : 0;	for (j = 0; j < iteration ; j++) {		do {			/* Steps */			ret_val = e1000_flash_cycle_init_ich8lan(hw);			if (ret_val)				return ret_val;			/*			 * Write a value 11 (block Erase) in Flash			 * Cycle field in hw flash control			 */			hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);			hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;			ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);			/*			 * Write the last 24 bits of an index within the			 * block into Flash Linear address field in Flash			 * Address.			 */			flash_linear_addr += (j * sector_size);			ew32flash(ICH_FLASH_FADDR, flash_linear_addr);			ret_val = e1000_flash_cycle_ich8lan(hw,					       ICH_FLASH_ERASE_COMMAND_TIMEOUT);			if (ret_val == 0)				break;			/*			 * Check if FCERR is set to 1.  If 1,			 * clear it and try the whole sequence			 * a few more times else Done			 */			hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);			if (hsfsts.hsf_status.flcerr == 1)				/* repeat for some time before giving up */				continue;			else if (hsfsts.hsf_status.flcdone == 0)				return ret_val;		} while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT);	}	return 0;}/** *  e1000_valid_led_default_ich8lan - Set the default LED settings *  @hw: pointer to the HW structure *  @data: Pointer to the LED settings * *  Reads the LED default settings from the NVM to data.  If the NVM LED *  settings is all 0's or F's, set the LED default to a valid LED default *  setting. **/static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data){	s32 ret_val;	ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);	if (ret_val) {		hw_dbg(hw, "NVM Read Error\n");		return ret_val;	}	if (*data == ID_LED_RESERVED_0000 ||	    *data == ID_LED_RESERVED_FFFF)		*data = ID_LED_DEFAULT_ICH8LAN;	return 0;}/** *  e1000_get_bus_info_ich8lan - Get/Set the bus type and width *  @hw: pointer to the HW structure * *  ICH8 use the PCI Express bus, but does not contain a PCI Express Capability *  register, so the the bus width is hard coded. **/static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw){	struct e1000_bus_info *bus = &hw->bus;	s32 ret_val;	ret_val = e1000e_get_bus_info_pcie(hw);	/*	 * ICH devices are "PCI Express"-ish.  They have	 * a configuration space, but do not contain	 * PCI Express Capability registers, so bus width	 * must be hardcoded.	 */	if (bus->width == e1000_bus_width_unknown)		bus->width = e1000_bus_width_pcie_x1;	return ret_val;}/** *  e1000_reset_hw_ich8lan - Reset the hardware *  @hw: pointer to the HW structure * *  Does a full reset of the hardware which includes a reset of the PHY and *  MAC. **/static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw){	u32 ctrl, icr, kab;	s32 ret_val;	/*	 * Prevent the PCI-E bus from sticking if there is no TLP connection	 * on the last TLP read/write transaction when MAC is reset.	 */	ret_val = e1000e_disable_pcie_master(hw);	if (ret_val) {		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");	}	hw_dbg(hw, "Masking off all interrupts\n");	ew32(IMC, 0xffffffff);	/*	 * Disable the Transmit and Receive units.  Then delay to allow	 * any pending transactions to complete before we hit the MAC	 * with the global reset.	 */	ew32(RCTL, 0);	ew32(TCTL, E1000_TCTL_PSP);	e1e_flush();	msleep(10);	/* Workaround for ICH8 bit corruption issue in FIFO memory */	if (hw->mac.type == e1000_ich8lan) {		/* Set Tx and Rx buffer allocation to 8k apiece. */		ew32(PBA, E1000_PBA_8K);		/* Set Packet Buffer Size to 16k. */		ew32(PBS, E1000_PBS_16K);	}	ctrl = er32(CTRL);	if (!e1000_check_reset_block(hw)) {		/*		 * PHY HW reset requires MAC CORE reset at the same		 * time to make sure the interface between MAC and the		 * external PHY is reset.		 */		ctrl |= E1000_CTRL_PHY_RST;	}	ret_val = e1000_acquire_swflag_ich8lan(hw);	hw_dbg(hw, "Issuing a global reset to ich8lan");	ew32(CTRL, (ctrl | E1000_CTRL_RST));	msleep(20);	ret_val = e1000e_get_auto_rd_done(hw);	if (ret_val) {		/*		 * When auto config read does not complete, do not		 * return with an error. This can happen in situations		 * where there is no eeprom and prevents getting link.		 */		hw_dbg(hw, "Auto Read Done did not complete\n");	}	ew32(IMC, 0xffffffff);	icr = er32(ICR);	kab = er32(KABGTXD);	kab |= E1000_KABGTXD_BGSQLBIAS;	ew32(KABGTXD, kab);	return ret_val;}/** *  e1000_init_hw_ich8lan - Initialize the hardware *  @hw: pointer to the HW structure * *  Prepares the hardware for transmit and receive by doing the following: *   - initialize hardware bits *   - initialize LED identification *   - setup receive address registers *   - setup flow control *   - setup transmit descriptors *   - clear statistics **/static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 ctrl_ext, txdctl, snoop;	s32 ret_val;	u16 i;	e1000_initialize_hw_bits_ich8lan(hw);	/* Initialize identification LED */	ret_val = e1000e_id_led_init(hw);	if (ret_val) {		hw_dbg(hw, "Error initializing identification LED\n");		/* This is not fatal and we should not stop init due to this */	}	/* Setup the receive address. */	e1000e_init_rx_addrs(hw, mac->rar_entry_count);	/* Zero out the Multicast HASH table */	hw_dbg(hw, "Zeroing the MTA\n");	for (i = 0; i < mac->mta_reg_count; i++)		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);	/* Setup link and flow control */	ret_val = e1000_setup_link_ich8lan(hw);	/* Set the transmit descriptor write-back policy for both queues */	txdctl = er32(TXDCTL(0));	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |		 E1000_TXDCTL_FULL_TX_DESC_WB;	txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |		 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;	ew32(TXDCTL(0), txdctl);	txdctl = er32(TXDCTL(1));	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |		 E1000_TXDCTL_FULL_TX_DESC_WB;	txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |		 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;	ew32(TXDCTL(1), txdctl);	/*	 * ICH8 has opposite polarity of no_snoop bits.	 * By default, we should use snoop behavior.	 */	if (mac->type == e1000_ich8lan)		snoop = PCIE_ICH8_SNOOP_ALL;	else		snoop = (u32) ~(PCIE_NO_SNOOP_ALL);	e1000e_set_pcie_no_snoop(hw, snoop);	ctrl_ext = er32(CTRL_EXT);	ctrl_ext |= E1000_CTRL_EXT_RO_DIS;	ew32(CTRL_EXT, ctrl_ext);	/*	 * Clear all of the statistics registers (clear on read).  It is	 * important that we do this after we have tried to establish link	 * because the symbol error count will increment wildly if there	 * is no link.	 */	e1000_clear_hw_cntrs_ich8lan(hw);	return 0;}/** *  e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits *  @hw: pointer to the HW structure * *  Sets/Clears required hardware bits necessary for correctly setting up the *  hardware for transmit and receive. **/static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw){	u32 reg;	/* Extended Device Control */	reg = er32(CTRL_EXT);	reg |= (1 << 22);	ew32(CTRL_EXT, reg);	/* Transmit Descriptor Control 0 */	reg = er32(TXDCTL(0));	reg |= (1 << 22);	ew32(TXDCTL(0), reg);	/* Transmit Descriptor Control 1 */	reg = er32(TXDCTL(1));	reg |= (1 << 22);	ew32(TXDCTL(1), reg);	/* Transmit Arbitration Control 0 */	reg = er32(TARC(0));	if (hw->mac.type == e1000_ich8lan)		reg |= (1 << 28) | (1 << 29);	reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27);	ew32(TARC(0), reg);	/* Transmit Arbitration Control 1 */	reg = er32(TARC(1));	if (er32(TCTL) & E1000_TCTL_MULR)		reg &= ~(1 << 28);	else		reg |= (1 << 28);	reg |= (1 << 24) | (1 << 26) | (1 << 30);	ew32(TARC(1), reg);	/* Device Status */	if (hw->mac.type == e1000_ich8lan) {		reg = er32(STATUS);		reg &= ~(1 << 31);		ew32(STATUS, reg);	}}/** *  e1000_setup_link_ich8lan - Setup flow control and link settings *  @hw: pointer to the HW structure * *  Determines which flow control settings to use, then configures flow

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -