📄 e100_eeprom.c
字号:
/******************************************************************************* Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The full GNU General Public License is included in this distribution in the file called LICENSE. Contact Information: Linux NICS <linux.nics@intel.com> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//*********************************************************************** ** INTEL CORPORATION ** ** This software is supplied under the terms of the license included ** above. All use of this driver must be in accordance with the terms ** of that license. ** ** Module Name: e100_eeprom.c ** ** Abstract: This module contains routines to read and write to a ** serial EEPROM ** ** Environment: This file is intended to be specific to the Linux ** operating system. ** ***********************************************************************/#include "e100.h"#define CSR_EEPROM_CONTROL_FIELD(bdp) ((bdp)->scb->scb_eprm_cntrl)#define CSR_GENERAL_CONTROL2_FIELD(bdp) \ ((bdp)->scb->scb_ext.d102_scb.scb_gen_ctrl2)#define EEPROM_STALL_TIME 4#define EEPROM_CHECKSUM ((u16) 0xBABA)#define EEPROM_MAX_WORD_SIZE 256void e100_eeprom_cleanup(struct e100_private *adapter);u16 e100_eeprom_calculate_chksum(struct e100_private *adapter);static void e100_eeprom_write_word(struct e100_private *adapter, u16 reg, u16 data);void e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data, u16 size);u16 e100_eeprom_size(struct e100_private *adapter);u16 e100_eeprom_read(struct e100_private *adapter, u16 reg);static void shift_out_bits(struct e100_private *adapter, u16 data, u16 count);static u16 shift_in_bits(struct e100_private *adapter);static void raise_clock(struct e100_private *adapter, u16 *x);static void lower_clock(struct e100_private *adapter, u16 *x);static u16 eeprom_wait_cmd_done(struct e100_private *adapter);static void eeprom_stand_by(struct e100_private *adapter);//----------------------------------------------------------------------------------------// Procedure: eeprom_set_semaphore//// Description: This function set (write 1) Gamla EEPROM semaphore bit (bit 23 word 0x1C in the CSR).//// Arguments:// Adapter - Adapter context//// Returns: true if success// else return false ////----------------------------------------------------------------------------------------inline u8eeprom_set_semaphore(struct e100_private *adapter){ u16 data = 0; unsigned long expiration_time = jiffies + HZ / 100 + 1; do { // Get current value of General Control 2 data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); // Set bit 23 word 0x1C in the CSR. data |= SCB_GCR2_EEPROM_ACCESS_SEMAPHORE; writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter)); // Check to see if this bit set or not. data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); if (data & SCB_GCR2_EEPROM_ACCESS_SEMAPHORE) { return true; } if (time_before(jiffies, expiration_time)) yield(); else return false; } while (true);}//----------------------------------------------------------------------------------------// Procedure: eeprom_reset_semaphore//// Description: This function reset (write 0) Gamla EEPROM semaphore bit // (bit 23 word 0x1C in the CSR).//// Arguments: struct e100_private * adapter - Adapter context//----------------------------------------------------------------------------------------inline voideeprom_reset_semaphore(struct e100_private *adapter){ u16 data = 0; data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); data &= ~(SCB_GCR2_EEPROM_ACCESS_SEMAPHORE); writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter));}//----------------------------------------------------------------------------------------// Procedure: e100_eeprom_size//// Description: This routine determines the size of the EEPROM. This value should be// checked for validity - ie. is it too big or too small. The size returned// is then passed to the read/write functions.//// Returns:// Size of the eeprom, or zero if an error occurred//----------------------------------------------------------------------------------------u16e100_eeprom_size(struct e100_private *adapter){ u16 x, size = 1; // must be one to accumulate a product // if we've already stored this data, read from memory if (adapter->eeprom_size) { return adapter->eeprom_size; } // otherwise, read from the eeprom // Set EEPROM semaphore. if (adapter->rev_id >= D102_REV_ID) { if (!eeprom_set_semaphore(adapter)) return 0; } // enable the eeprom by setting EECS. x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EEDI | EEDO | EESK); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); // write the read opcode shift_out_bits(adapter, EEPROM_READ_OPCODE, 3); // experiment to discover the size of the eeprom. request register zero // and wait for the eeprom to tell us it has accepted the entire address. x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); do { size *= 2; // each bit of address doubles eeprom size x |= EEDO; // set bit to detect "dummy zero" x &= ~EEDI; // address consists of all zeros writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); readw(&(adapter->scb->scb_status)); udelay(EEPROM_STALL_TIME); raise_clock(adapter, &x); lower_clock(adapter, &x); // check for "dummy zero" x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); if (size > EEPROM_MAX_WORD_SIZE) { size = 0; break; } } while (x & EEDO); // read in the value requested (void) shift_in_bits(adapter); e100_eeprom_cleanup(adapter); // Clear EEPROM Semaphore. if (adapter->rev_id >= D102_REV_ID) { eeprom_reset_semaphore(adapter); } return size;}//----------------------------------------------------------------------------------------// Procedure: eeprom_address_size//// Description: determines the number of bits in an address for the eeprom acceptable// values are 64, 128, and 256// Arguments: size of the eeprom// Returns: bits in an address for that size eeprom//----------------------------------------------------------------------------------------static inline inteeprom_address_size(u16 size){ int isize = size; return (ffs(isize) - 1);}//----------------------------------------------------------------------------------------// Procedure: e100_eeprom_read//// Description: This routine serially reads one word out of the EEPROM.//// Arguments:// adapter - our adapter context// reg - EEPROM word to read.//// Returns:// Contents of EEPROM word (reg).//----------------------------------------------------------------------------------------u16e100_eeprom_read(struct e100_private *adapter, u16 reg){ u16 x, data, bits; // Set EEPROM semaphore. if (adapter->rev_id >= D102_REV_ID) { if (!eeprom_set_semaphore(adapter)) return 0; } // eeprom size is initialized to zero if (!adapter->eeprom_size) adapter->eeprom_size = e100_eeprom_size(adapter); bits = eeprom_address_size(adapter->eeprom_size); // select EEPROM, reset bits, set EECS x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EEDI | EEDO | EESK); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); // write the read opcode and register number in that order // The opcode is 3bits in length, reg is 'bits' bits long shift_out_bits(adapter, EEPROM_READ_OPCODE, 3); shift_out_bits(adapter, reg, bits); // Now read the data (16 bits) in from the selected EEPROM word data = shift_in_bits(adapter); e100_eeprom_cleanup(adapter); // Clear EEPROM Semaphore. if (adapter->rev_id >= D102_REV_ID) { eeprom_reset_semaphore(adapter); } return data;}//----------------------------------------------------------------------------------------// Procedure: shift_out_bits//// Description: This routine shifts data bits out to the EEPROM.//// Arguments:// data - data to send to the EEPROM.// count - number of data bits to shift out.//// Returns: (none)//----------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -