📄 device.c
字号:
//#elif defined (k_opt_nand)
//do nothing
#else
return;
#endif
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void nvstore_write_disable() reentrant
{
#ifdef k_opt_eeprom
eeprom_write_disable();
//#elif defined (k_opt_otprom)
//otprom_write_flush();
#elif defined (k_opt_nand)
nand_boot_write_flush();
#else
return;
#endif
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static t_result dev_sink_nvdata_to_eeprom(uint8 pnr, uint8 len) reentrant;
static t_result dev_sink_nvdata_to_eeprom(uint8 pnr, uint8 len) reentrant
{
#ifdef k_opt_eeprom
uint8 i;
uint8 c;
uint8 v;
trace0(0, dev, 0, "dev_sink_nvdata_to_eeprom");
eeprom_write_enable();
// sink data
i=0;
trace1(0, dev, 0, "writing %d bytes...", len);
while (i<len)
{
mmu_rd(pnr, i++, 1, &c);
eeprom_write(_nvstore_ix++,c);
}
eeprom_write_disable();
// verify data
i=0;
_nvstore_ix -= len;
trace1(0, dev, 0, "verifying %d bytes...", len);
while (i < len)
{
mmu_rd(pnr, i++, 1, &c);
v=eeprom_read(_nvstore_ix++);
if (c != v)
{
trace3(0, dev, 0, "nvstore(%d) failure. expected: %02X, got: %02X", (i-1), c, v);
return(k_error);
}
}
trace0(0, dev, 0, "data written and verified");
return(k_success);
#else
pnr=pnr; len=len;
return(k_false);
#endif // k_opt_eeprom
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static t_result dev_sink_nvdata_to_otprom(uint8 pnr, uint8 len) reentrant;
static t_result dev_sink_nvdata_to_otprom(uint8 pnr, uint8 len) reentrant
{
#ifdef k_opt_otprom
trace0(0, dev, 0, "dev_sink_nvdata_to_otprom - only supports sst39lf010");
mmu_rd(pnr, 0, len, (t_xdata_ref)(k_ram_base + (k_nvstore_base - k_otprom_base) + _nvstore_ix));
_nvstore_ix += len;
// not verifying the data here. host can issue eeread to verify.
return(k_success);
#else
pnr=pnr; len=len;
return(k_false);
#endif // k_opt_otprom
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static t_result dev_sink_nvdata_to_nand(uint8 pnr, uint8 len) reentrant;
static t_result dev_sink_nvdata_to_nand(uint8 pnr, uint8 len) reentrant
{
#ifdef k_opt_nand
uint8 i;
uint8 c;
trace0(0, dev, 0, "dev_sink_nvdata_to_nand()");
// sink data
i=0;
trace1(0, dev, 0, "writing %d bytes...", len);
while (i<len)
{
mmu_rd(pnr, i++, 1, &c);
nand_boot_write(_nvstore_ix++,c);
}
return(k_success);
#else
pnr=pnr;len=len;
return(k_false);
#endif // k_opt_nand
}
//------------------------------------------------------------------------------
// this function converts whatever is in the x_ata_dev_str_ser buffer or, if
// used, the serial eeprom, into a bulk-only compliant serial number of at
// least 12 bytes.
//------------------------------------------------------------------------------
#define _nvdata(__offset) g_sector_buffer[(__offset)]
static void dev_validate_nvstore(void) reentrant;
static void dev_validate_nvstore() reentrant
{
#ifdef k_opt_nvstore
uint8 i,b;
uint8 sz;
trace0(0, dev, 0, "dev_validate_nvstore()");
for (i=0; i<255; i++)
{
g_sector_buffer[i] = nvstore_read(i);
//TRACE2(36, dev, 0, "nvdata[%03d]:0x%02X", i, _nvdata(i));
}
g_sector_buffer[255] = nvstore_read(255);
//TRACE1(37, dev, 0, "nvdata[255]:0x%02X", _nvdata(255));
_nvstore_data_valid = k_false;
_serial_number_valid = k_false;
g_dev_attr_lo = k_attr_lo_default;
g_password_validated = k_yes;
g_blink_interval = 0x0A;
_blink_counter = 0x00;
_seconds_counter = k_counts_per_sec;
g_nvstore_post_access_blink_secs = 0x00;
g_post_access_blink_secs = 0x00;
g_activity_led_idle_bright = k_true;
// check the configuration descriptor fields
if (_nvdata(k_ix_maxpwr) > 0x31)
{
trace0(0, dev, 0, "error: bMaxPower > 98ma");
}
if (_nvdata(k_ix_maxpwr) < 0x01)
{
trace0(0, dev, 0, "error: bMaxPower < 2ma");
}
if ((_nvdata(k_ix_bmattrib) != 0xC0) && (_nvdata(k_ix_bmattrib) != 0x80))
{
trace1(0, dev, 0, "error: bmAttributes is invalid:%02X", _nvdata(k_ix_bmattrib));
// this is wrong enough that the nvstore data cannot be trusted, regardless of the signature
return;
}
// check the signature
if ((_nvdata(k_ix_sig_hi) == k_sig_ata1_hi) &&
(_nvdata(k_ix_sig_lh) == k_sig_ata1_lh) &&
(_nvdata(k_ix_sig_hl) == k_sig_ata1_hl) &&
(_nvdata(k_ix_sig_lo) == k_sig_ata1_lo))
{
trace0(0, dev, 0, "nvstore contains valid signature.");
_nvstore_data_valid = k_true;
}
else
{
trace4(0, dev, 0, "nvstore signature is invalid:%02X%02X%02X%02X",
_nvdata(k_ix_sig_hi),_nvdata(k_ix_sig_lh),_nvdata(k_ix_sig_hl),_nvdata(k_ix_sig_lo));
return;
}
// could use an attribute bit to enable password
#ifdef k_opt_password
// if there is no password then password is considered to be validated
b = _nvdata(k_ix_password);
if ((b == 0xFF) || (b == 0x00)) //0xFF and 0x00 are the password termination characters.
{
g_password_validated = k_yes;
trace0(0, dev, 0, "no password exists, so password is considered valid, and media is not removable");
}
else
{
g_password_validated = k_no;
trace0(0, dev, 0, "password exists, so password is not valid, and media is removable");
}
#endif
//Determine attributes for blinky light
//read the blink interval byte
g_blink_interval = _nvdata(k_ix_blink_interval);
//do we need to continue blinking?
g_nvstore_post_access_blink_secs = _nvdata(k_ix_blinks_after_access);
trace2(0, dev, 0, "blink interval:%d post:%d", g_blink_interval, g_nvstore_post_access_blink_secs);
//do they want the led kept on all the time and then blink on access?
g_activity_led_idle_bright = g_blink_interval & 0x80;
//the last 7 bits is a multiple of 10ms, as the blink interval
g_blink_interval &= 0x7f;
//blink counter starts with the blink interval
_blink_counter = g_blink_interval;
trace2(0, dev, 0, " g_activity_led_idle_bright: %d g_blink_interval: %d" , (uint8)g_activity_led_idle_bright,g_blink_interval);
// process attribute flags
g_dev_attr_lo = _nvdata(k_ix_attr_lo);
//g_dev_attr_hl = nvstore_read(k_ix_attr_hl);
//g_dev_attr_lh = nvstore_read(k_ix_attr_lh);
// g_dev_attr_hi = _nvdata(k_ix_attr_hi);
trace1(0, dev, 0, "attribute: force smart media compatible timing:%c", ((g_dev_attr_lo&kbm_attr_lo_sm_timing)?'Y':'N'));
trace1(0, dev, 0, "attribute: nand flash hard drives to always enumerate as removable media:%c", ((g_dev_attr_lo&kbm_attr_lo_hd_as_rm)?'Y':'N'));
trace1(0, dev, 0, "attribute: use gpio5 as sd card detect:%c", ((g_dev_attr_lo&kbm_attr_lo_gpio5_as_sd_insert)?'Y':'N'));
trace1(0, dev, 0, "attribute: Always report iSerial as zero in the device descriptor:%c", ((g_dev_attr_lo&kbm_attr_lo_force_zero_iserial)?'Y':'N'));
// copy the device id strings for each lun into the _lun_data
// (only 7 chars worth gets assembled into the inquiry data for icon matching)
for (i=0;i<k_max_log_lun;i++)
{
uint8 offset;
// this assumes each 7-byte string is sequential in nvstore!
// also, this can only handle up to 4 luns
offset=k_sz_lun_id*i+k_ix_lun0_id;
if (isprint(_nvdata(offset)))
{
lun_set_active(_lun_log2phy(i));
memcpy(_lun_data(device_id), &(_nvdata(offset)), k_sz_lun_id); //k_lun_max_devid_sz);
}
}
/*
#if (k_max_log_lun > 0)
if (isprint(_nvdata(k_ix_lun0_id)))
{
lun_set_active(_lun_log2phy(0));
memcpy(_lun_data(device_id), &(_nvdata(k_ix_lun0_id)), 7); //k_lun_max_devid_sz);
}
#endif
#if (k_max_log_lun > 1)
if (isprint(_nvdata(k_ix_lun1_id)))
{
lun_set_active(_lun_log2phy(0));
memcpy(_lun_data(_lun_log2phy(1), device_id), &(_nvdata(k_ix_lun1_id)), 7);
}
#endif
#if (k_max_log_lun > 2)
if (isprint(_nvdata(k_ix_lun2_id)))
{
lun_set_active(_lun_log2phy(0));
memcpy(_lun_data(_lun_log2phy(2), device_id), &(_nvdata(k_ix_lun2_id)), 7);
}
#endif
#if (k_max_log_lun > 3)
if (isprint(_nvdata(k_ix_lun3_id)))
{
lun_set_active(_lun_log2phy(0));
memcpy(_lun_data(_lun_log2phy(3), device_id), &(_nvdata(k_ix_lun3_id)), 7);
}
#endif
*/
// validate serial number
// read length from nvstore config
sz = _nvdata(k_ix_ser);
if (sz != k_sz_ser)
{
trace1(0, dev, 0, "serial number invalid. byte0:%d s/b 26", sz);
return;
}
// make sure its a string descriptor
b = _nvdata(1);
if (b != 0x03)
{
trace1(0, dev, 0, "serial number invalid. byte1:%d s/b 0x03", b);
return;
}
trace1(0, dev, 0, "Reading %d bytes of serial data", sz);
for (i=0; i< sz-2; i++)
{
b = _nvdata(i+2);
// even bytes contain ascii values
if (!(i&1))
{
if ('0' <= b && '9' >= b)
continue;
else
if ('a' <= b && b <= 'f')
continue;
else
if ('A' <= b && b <= 'F')
continue;
else
{
trace2(0, dev, 0, "serial_number[%d]:'%c' - invalid mass storage class digit. s/b hex character.", i, b);
return;
}
}
// odd bytes contain zeros (because its unicode...)
else
{
if (b)
{
trace2(0, dev, 0, "serial_number[%d]:'%c' - s/b zero (for hi byte of unicode char).", i, b);
return;
}
}
}
trace0(0, dev, 0, "serial number is valid");
_serial_number_valid = k_true;
// force iSerial to zero by claiming the serial number is not valid
if (g_dev_attr_lo & kbm_attr_lo_force_zero_iserial)
{
trace0(0, dev, 0, "iSerial forced to zero");
_serial_number_valid = k_false;
}
if (g_dev_attr_lo&kbm_attr_lo_use_inq_mfr_prd_ids)
{
trace0(0, dev, 0, "using IMIDS & IPIDS fields for Inquiry Data") ;
for (i=0; i<k_sz_inq_vid; i++)
{
b=_nvdata(k_ix_inq_vid+i);
g_inq_vid[i]=isprint(b)?b:' ';
}
// insert the inquiry product id header string (created from nvstore)
for (i=0;i<k_sz_inq_pid_hdr; i++)
{
b=_nvdata(k_ix_inq_pid_hdr+i);
g_inq_pid_hdr[i]=isprint(b)?b:' ';
}
}
else
{
// extract the vendor id from mfr string descriptor, store in g_inq_vid, converting uni->ascii
trace0(0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -