📄 e100_eeprom.c
字号:
static voidshift_out_bits(struct e100_private *adapter, u16 data, u16 count){ u16 x, mask; mask = 1 << (count - 1); x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EEDO | EEDI); do { x &= ~EEDI; if (data & mask) x |= EEDI; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); readw(&(adapter->scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME); raise_clock(adapter, &x); lower_clock(adapter, &x); mask = mask >> 1; } while (mask); x &= ~EEDI; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));}//----------------------------------------------------------------------------------------// Procedure: raise_clock//// Description: This routine raises the EEPROM's clock input (EESK)//// Arguments:// x - Ptr to the EEPROM control register's current value//// Returns: (none)//----------------------------------------------------------------------------------------voidraise_clock(struct e100_private *adapter, u16 *x){ *x = *x | EESK; writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter)); readw(&(adapter->scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME);}//----------------------------------------------------------------------------------------// Procedure: lower_clock//// Description: This routine lower's the EEPROM's clock input (EESK)//// Arguments:// x - Ptr to the EEPROM control register's current value//// Returns: (none)//----------------------------------------------------------------------------------------voidlower_clock(struct e100_private *adapter, u16 *x){ *x = *x & ~EESK; writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter)); readw(&(adapter->scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME);}//----------------------------------------------------------------------------------------// Procedure: shift_in_bits//// Description: This routine shifts data bits in from the EEPROM.//// Arguments://// Returns:// The contents of that particular EEPROM word//----------------------------------------------------------------------------------------static u16shift_in_bits(struct e100_private *adapter){ u16 x, d, i; x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EEDO | EEDI); d = 0; for (i = 0; i < 16; i++) { d <<= 1; raise_clock(adapter, &x); x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~EEDI; if (x & EEDO) d |= 1; lower_clock(adapter, &x); } return d;}//----------------------------------------------------------------------------------------// Procedure: e100_eeprom_cleanup//// Description: This routine returns the EEPROM to an idle state//----------------------------------------------------------------------------------------voide100_eeprom_cleanup(struct e100_private *adapter){ u16 x; x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EECS | EEDI); writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); raise_clock(adapter, &x); lower_clock(adapter, &x);}//**********************************************************************************// Procedure: e100_eeprom_update_chksum//// Description: Calculates the checksum and writes it to the EEProm. // It calculates the checksum accroding to the formula: // Checksum = 0xBABA - (sum of first 63 words).////-----------------------------------------------------------------------------------u16e100_eeprom_calculate_chksum(struct e100_private *adapter){ u16 idx, xsum_index, checksum = 0; // eeprom size is initialized to zero if (!adapter->eeprom_size) adapter->eeprom_size = e100_eeprom_size(adapter); xsum_index = adapter->eeprom_size - 1; for (idx = 0; idx < xsum_index; idx++) checksum += e100_eeprom_read(adapter, idx); checksum = EEPROM_CHECKSUM - checksum; return checksum;}//----------------------------------------------------------------------------------------// Procedure: e100_eeprom_write_word//// Description: This routine writes a word to a specific EEPROM location without.// taking EEPROM semaphore and updating checksum. // Use e100_eeprom_write_block for the EEPROM update// Arguments: reg - The EEPROM word that we are going to write to.// data - The data (word) that we are going to write to the EEPROM.//----------------------------------------------------------------------------------------static voide100_eeprom_write_word(struct e100_private *adapter, u16 reg, u16 data){ u16 x; u16 bits; bits = eeprom_address_size(adapter->eeprom_size); /* select EEPROM, mask off ASIC and reset bits, set EECS */ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EEDI | EEDO | EESK); writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); readw(&(adapter->scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); shift_out_bits(adapter, EEPROM_EWEN_OPCODE, 5); shift_out_bits(adapter, reg, (u16) (bits - 2)); if (!eeprom_wait_cmd_done(adapter)) return; /* write the new word to the EEPROM & send the write opcode the EEPORM */ shift_out_bits(adapter, EEPROM_WRITE_OPCODE, 3); /* select which word in the EEPROM that we are writing to */ shift_out_bits(adapter, reg, bits); /* write the data to the selected EEPROM word */ shift_out_bits(adapter, data, 16); if (!eeprom_wait_cmd_done(adapter)) return; shift_out_bits(adapter, EEPROM_EWDS_OPCODE, 5); shift_out_bits(adapter, reg, (u16) (bits - 2)); if (!eeprom_wait_cmd_done(adapter)) return; e100_eeprom_cleanup(adapter);}//----------------------------------------------------------------------------------------// Procedure: e100_eeprom_write_block//// Description: This routine writes a block of words starting from specified EEPROM // location and updates checksum// Arguments: reg - The EEPROM word that we are going to write to.// data - The data (word) that we are going to write to the EEPROM.//----------------------------------------------------------------------------------------voide100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data, u16 size){ u16 checksum; u16 i; if (!adapter->eeprom_size) adapter->eeprom_size = e100_eeprom_size(adapter); // Set EEPROM semaphore. if (adapter->rev_id >= D102_REV_ID) { if (!eeprom_set_semaphore(adapter)) return; } for (i = 0; i < size; i++) { e100_eeprom_write_word(adapter, start + i, data[i]); } //Update checksum checksum = e100_eeprom_calculate_chksum(adapter); e100_eeprom_write_word(adapter, (adapter->eeprom_size - 1), checksum); // Clear EEPROM Semaphore. if (adapter->rev_id >= D102_REV_ID) { eeprom_reset_semaphore(adapter); }}//----------------------------------------------------------------------------------------// Procedure: eeprom_wait_cmd_done//// Description: This routine waits for the the EEPROM to finish its command. // Specifically, it waits for EEDO (data out) to go high.// Returns: true - If the command finished// false - If the command never finished (EEDO stayed low)//----------------------------------------------------------------------------------------static u16eeprom_wait_cmd_done(struct e100_private *adapter){ u16 x; unsigned long expiration_time = jiffies + HZ / 100 + 1; eeprom_stand_by(adapter); do { rmb(); x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); if (x & EEDO) return true; if (time_before(jiffies, expiration_time)) yield(); else return false; } while (true);}//----------------------------------------------------------------------------------------// Procedure: eeprom_stand_by//// Description: This routine lowers the EEPROM chip select (EECS) for a few microseconds.//----------------------------------------------------------------------------------------static voideeprom_stand_by(struct e100_private *adapter){ u16 x; x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EECS | EESK); writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); readw(&(adapter->scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); readw(&(adapter->scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -