www.pudn.com > SMSC USB2.0.zip > device_new.c
/*============================================================================
____________________________________________________________________________
______________________________________________
SSSS M M CCCC Standard Microsystems Corporation
S MM MM SSSS C Austin Design Center
SSS M M M S C 11000 N. Mopac Expressway
S M M SSS C Stonelake Bldg. 6, Suite 500
SSSS M M S CCCC Austin, Texas 78759
SSSS ______________________________________________
____________________________________________________________________________
Copyright(C) 1999, Standard Microsystems Corporation
All Rights Reserved.
This program code listing is proprietary to SMSC and may not be copied,
distributed, or used without a license to do so. Such license may have
Limited or Restricted Rights. Please refer to the license for further
clarification.
____________________________________________________________________________
Notice: The program contained in this listing is a proprietary trade
secret of SMSC, Hauppauge, New York, and is copyrighted
under the United States Copyright Act of 1976 as an unpublished work,
pursuant to Section 104 and Section 408 of Title XVII of the United
States code. Unauthorized copying, adaption, distribution, use, or
display is prohibited by this law.
____________________________________________________________________________
Use, duplication, or disclosure by the Government is subject to
restrictions as set forth in subparagraph(c)(1)(ii) of the Rights
in Technical Data and Computer Software clause at DFARS 52.227-7013.
Contractor/Manufacturer is Standard Microsystems Corporation,
80 Arkay Drive, Hauppauge, New York, 1178-8847.
____________________________________________________________________________
____________________________________________________________________________
device.c - the device manager implementarion
____________________________________________________________________________
comments tbd
____________________________________________________________________________
Revision History
Date Who Comment
________ ___ _____________________________________________________________
05/31/00 tbh initial version
09/04/01 tbh auto version the product string.
add reserved space to work with dfu on the 201
09/05/01 tbh changed set_config arg to value instead of reference since cannot
use address of sfr. (building with registers as sfr instead
of xdata reveled this compilation issue)
09/##/01 tbh optimized for speed
11/07/01 rcc added phy #define below to choose your klsi phy rev see dev_intitilize
11/26/01 cds fixed dev_source_eeprom to return correct string length in
response to a 2-byte get_descriptor (string) request.
11/28/01 tbh modified eeprom source/sink to work with writeee.exe.
12/01/01 tbh added all 210 interrupts. added code to probe cards.
01/15/02 cds fixed version string generation to use two digits when the
version constant is >= 0x10, not > 0x10.
02/26/02 tbh added logical to physical lun mapping
changed strcpy to strncpy for safety
03/11/02 tbh added usage of in dev_intr bit g_force_media_changed. then removed it.
03/12/02 tbh changed card establish to media change handler.
03/28/02 tbh make sure phy lun for mmc is init'd on power up.
04/01/02 ds Enabled proper handling of the k_irq_fmc_err_sd_blk_ovrun intr, instead of handling it in
case k_irq_fmc_err
04/01/02 tbh only init logical luns < k_max_log_lun
04/15/02 tbh remembed previous configuration so on usb reset can check to
see if had been configured
04/18/02 cds added thread_set_sync(g_ix_dev_thread, kbm_sync_fmc_blk) to the
dev_intr handlers which intercept the smart media ecc detection bits so that
it can stop the fmc_xfer and allow a resume.
04/24/02 tbh added k_dvd_inq_devid, upgraded eeprom support to use new 201 scheme
04/25/02 tbh top level device thread now does not attempt to scan card slots
for media change until after the device has fully enumerated
through set-config(1) (which results in a dev_pwr_up()) so that
the dev_pwr_up() does not cause re-initialization of all of the
cards. this fixes the bug with wp-sd card on pwr on, and speeds
up enumeration.
06/19/02 tbh the mscbot dfa has been replaced with a high priority thread.
so the device thread had to be rewritten essentially from the
ground up to accomodate it.
added handler for k_irq_fmc_sdc_flash_prg_err,
enhanced handler for k_irq_fmc_sdc_crc_err
06/20/02 cds added nand hd lun initialization, if it is included in the build options.
06/20/02 tbh fixed a problem of powering on with no media and havinf the host
try to do a read even avter seeing a no-media sense code.
06/21/02 tbh don't probe cards on an inquiry command, to make working
when plugin with 4 cards laded on MacOS X 10.1.5
============================================================================*/
#define __device_dot_c__
#include "project.h"
#include "dev.h"
//------------------------------------------------------------------------------
// required global constant to communicate desired settings to minimos
#ifdef k_pfm_6126
code t_dev_attribute_mask k_dev_attributes = kbm_hub_enabled;
#else
code t_dev_attribute_mask k_dev_attributes = kbm_none;
#endif
//------------------------------------------------------------------------------
// device id to avoid use of driver with roque devices
static code uint8 _devid[] = {'C','o','p','y','r','i','g','h','t',' ','(','C',')',' ','2','0','0','2',' ','S','M','S','C',0};
//------------------------------------------------------------------------------
// offset into the device descriptor for sundry items
#define k_ix_dev_vid_lo 8
#define k_ix_dev_vid_hi 9
#define k_ix_dev_pid_lo 10
#define k_ix_dev_pid_hi 11
#define k_ix_dev_ver_lo 12
#define k_ix_dev_ver_hi 13
//------------------------------------------------------------------------------
// vendor id and product id (SMSC -> 0106 dec = 0424 hex)
#define k_vendorhi 0x04 // vendor id hi
#define k_vendorlo 0x24 // vendor id lo
#define k_dev_producthi 0x20 // product id hi
// #define k_dev_productlo 0xFC // product id lo
#define k_dev_productlo 0xCD // product id lo
//------------------------------------------------------------------------------
// version descriptor (not a usb thing, its used by the smsc romset utility)
// $$$ note that romset as is wont work on this because there are now multiple
// device and configuration descriptors. romset needs to be updated.
uint8 code g_version[] = {k_vendorhi, k_vendorlo, k_dev_producthi, k_dev_productlo, kbcd_dev_version_major, kbcd_dev_version_minor};
//------------------------------------------------------------------------------
// this app is downloadable via dfu, so we must reserve a hole in code space
// to make dfu work properly on the 201...
#if !defined(k_ram_isr) && !defined(k_support_otprom)
uint8 code reserved[768] _at_ 0x0400;
#endif
//------------------------------------------------------------------------------
// string descriptors (in a form that the smsc romset utility can use)
#define _hi_digit(b) ((uint8) (((uint8)(b>>4)&0x0F) + (uint8)'0')),0
#define _lo_digit(b) ((uint8) (((uint8)(b )&0x0F) + (uint8)'0')),0
uint8 code g_str_lng[4] = {4, 3, 0x09, 0x04}; // (English lo 0x09, hi 0x04)
uint8 code g_str_mfg[17][2] = {10, 3, "S", "M", "S", "C"};
uint8 code g_str_prd[63][2] =
{
62, 3,
"F", "l", "a", "s", "h",
" ", "M", "e", "d", "i",
"a", " ", "C", "o", "n",
"t", "r", "o", "l", "l",
"e", "r", " ",
#if (kbcd_dev_version_major>=0x10)
_hi_digit(kbcd_dev_version_major),
#endif
_lo_digit(kbcd_dev_version_major), ".",
#if (kbcd_dev_version_minor>=0x10)
_hi_digit(kbcd_dev_version_minor),
#endif
_lo_digit(kbcd_dev_version_minor), ".",
#if (kbcd_dev_version_external_change>=0x10)
_hi_digit(kbcd_dev_version_external_change),
#endif
_lo_digit(kbcd_dev_version_external_change), ".",
#if (kbcd_dev_version_internal_change>=0x10)
_hi_digit(kbcd_dev_version_internal_change),
#endif
_lo_digit(kbcd_dev_version_internal_change)
};
uint8 code g_str_ser[41][2] = {64, 3, " "};
uint8 code *code g_str_dscr[k_dev_max_string] = {g_str_lng, g_str_mfg, g_str_prd, g_str_ser};
//------------------------------------------------------------------------------
// string descriptor indicies
#define k_dev_idx_str_dscr_lng 0
#define k_dev_idx_str_dscr_mfg 1
#define k_dev_idx_str_dscr_prd 2
#define k_dev_idx_str_dscr_ser 3
//------------------------------------------------------------------------------
// device descriptor
//------------------------------------------------------------------------------
// full speed device descriptor
uint8 code g_fs_dev_dscr[] =
{
k_usb_devdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_device, // descriptor type: device
0x10, // usb version lo
0x01, // usb version hi
0x00, // device class: see interfaces
0x00, // subclass: see interfaces
0x00, // protocol: see interfaces
k_maxpktsz, // ndp 0 max packet size (8,16,32,64)
k_vendorlo, // vendor lo
k_vendorhi, // vendor hi
k_dev_productlo, // product lo
k_dev_producthi, // product hi
kbcd_dev_version_minor, // device release lo
kbcd_dev_version_major, // device release hi
k_dev_idx_str_dscr_mfg, // manufacturer string index
k_dev_idx_str_dscr_prd, // product string index
0, // serial string index
k_dev_max_configuration // number of configurations
};
// full speed device descriptor with serial number - cds
uint8 code g_fs_dev_dscr_w_ser[] =
{
k_usb_devdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_device, // descriptor type: device
0x10, // usb version lo
0x01, // usb version hi
0x00, // device class: see interfaces
0x00, // subclass: see interfaces
0x00, // protocol: see interfaces
k_maxpktsz, // ndp 0 max packet size (8,16,32,64)
k_vendorlo, // vendor lo
k_vendorhi, // vendor hi
k_dev_productlo, // product lo
k_dev_producthi, // product hi
kbcd_dev_version_minor, // device release lo
kbcd_dev_version_major, // device release hi
k_dev_idx_str_dscr_mfg, // manufacturer string index
k_dev_idx_str_dscr_prd, // product string index
k_dev_idx_str_dscr_ser, // cds - serial string index
k_dev_max_configuration // number of configurations
};
//------------------------------------------------------------------------------
// high speed device descriptor
uint8 code g_hs_dev_dscr[] =
{
k_usb_devdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_device, // descriptor type: device
0x00, // usb version lo
0x02, // usb version hi
0x00, // device class: see interfaces
0x00, // subclass: see interfaces
0x00, // protocol: see interfaces
k_maxpktsz, // ndp 0 max packet size (8,16,32,64)
k_vendorlo, // vendor lo
k_vendorhi, // vendor hi
k_dev_productlo, // product lo
k_dev_producthi, // product hi
kbcd_dev_version_minor, // device release lo
kbcd_dev_version_major, // device release hi
k_dev_idx_str_dscr_mfg, // manufacturer string index
k_dev_idx_str_dscr_prd, // product string index
0, // serial string index
k_dev_max_configuration // number of configurations
};
// high speed device descriptor with serial number - cds
uint8 code g_hs_dev_dscr_w_ser[] =
{
k_usb_devdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_device, // descriptor type: device
0x00, // usb version lo
0x02, // usb version hi
0x00, // device class: see interfaces
0x00, // subclass: see interfaces
0x00, // protocol: see interfaces
k_maxpktsz, // ndp 0 max packet size (8,16,32,64)
k_vendorlo, // vendor lo
k_vendorhi, // vendor hi
k_dev_productlo, // product lo
k_dev_producthi, // product hi
kbcd_dev_version_minor, // device release lo
kbcd_dev_version_major, // device release hi
k_dev_idx_str_dscr_mfg, // manufacturer string index
k_dev_idx_str_dscr_prd, // product string index
k_dev_idx_str_dscr_ser, // cds - serial string index
k_dev_max_configuration // number of configurations
};
//------------------------------------------------------------------------------
// device qualifier descriptor
//------------------------------------------------------------------------------
// full speed device qualifier descriptor
uint8 code g_fs_devqual_dscr[] =
{
k_usb_devqualdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_devqual, // descriptor type: device qualifier
0x00, // usb version lo
0x02, // usb version hi
0x00, // device class: see interfaces
0x00, // subclass: see interfaces
0x00, // protocol: see interfaces
k_maxpktsz, // ndp 0 max packet size, other speed
k_dev_max_configuration, // number of other speed configurations
0 // reserved
};
//------------------------------------------------------------------------------
// high speed device qualifier descriptor
uint8 code g_hs_devqual_dscr[] =
{
k_usb_devqualdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_devqual, // descriptor type: device qualifier
0x00, // usb version lo
0x02, // usb version hi
0x00, // device class: see interfaces
0x00, // subclass: see interfaces
0x00, // protocol: see interfaces
k_maxpktsz, // ndp 0 max packet size, other speed
k_dev_max_configuration, // number of other speed configurations
0 // reserved
};
//------------------------------------------------------------------------------
// configuration descriptor
//------------------------------------------------------------------------------
// full speed configuration descriptor
uint8 code g_fs_cfg_dscr[] =
{
k_usb_cfgdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_config, // descriptor type: configuration
k_usb_cfgdscrsz +
k_usb_ifcdscrsz +
k_usb_ndpdscrsz +
k_usb_ndpdscrsz, // total length lo
0, // total length hi
1, // number of interfaces 2 to accomodate the DFU
0x01, // configuration value
0x00, // index of string descriptor
0xC0, // attributes: self powered, no remote wakeup
0x01, // _max power: 2ma
// interface descriptor: BOT mass storage
k_usb_ifcdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_interface, // descriptor type: interface
0, // interface number
0, // alternate interface
2, // number of endpoints
0x08, // usb interface class: mass storage
0x06, // usb interface subclass: scsi
0x50, // interface protocol: BOT (bulk only transport)
0x00, // interface string index
// endpoint descriptor: bulk out
k_usb_ndpdscrsz, // length of descriptor in bytes
0x05, // descriptor type: endpoint
0x02, // endpoint 2, out
0x02, // bulk
k_fs_maxpktsz, // max packet size lo
0x00, // max packet size hi
0x01, // polling interval
// endpoint descriptor: bulk in
k_usb_ndpdscrsz, // length of descriptor in bytes
0x05, // descriptor type: endpoint
0x82, // endpoint 2, in
0x02, // bulk
k_fs_maxpktsz, // max packet size lo
0x00, // max packet size hi
0x00 // polling interval
};
//------------------------------------------------------------------------------
// high speed configuration descriptor
uint8 code g_hs_cfg_dscr[] =
{
k_usb_cfgdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_config, // descriptor type: configuration
k_usb_cfgdscrsz +
k_usb_ifcdscrsz +
k_usb_ndpdscrsz +
k_usb_ndpdscrsz, // total length lo
0, // total length hi
1, // number of interfaces
0x01, // configuration value
0x00, // index of string descriptor
0xC0, // attributes: self powered, no remote wakeup
0x01, // _max power: 2ma
// interface descriptor: BOT mass storage
k_usb_ifcdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_interface, // descriptor type: interface
0, // interface number
0, // alternate interface
2, // number of endpoints
0x08, // usb interface class: mass storage
0x06, // usb interface subclass: scsi
0x50, // interface protocol: BOT (bulk only transport)
0x00, // interface string index
// endpoint descriptor: bulk out
k_usb_ndpdscrsz, // length of descriptor in bytes
0x05, // descriptor type: endpoint
0x02, // endpoint 2, out
0x02, // bulk
_l(k_hs_maxpktsz), // max packet size lo
_h(k_hs_maxpktsz), // max packet size hi
0x01, // polling interval
// endpoint descriptor: bulk in
k_usb_ndpdscrsz, // length of descriptor in bytes
0x05, // descriptor type: endpoint
0x82, // endpoint 2, in
0x02, // bulk
_l(k_hs_maxpktsz), // max packet size lo
_h(k_hs_maxpktsz), // max packet size hi
0x00, // polling interval
};
//------------------------------------------------------------------------------
// other speed configuration descriptor
//------------------------------------------------------------------------------
// full speed other speed configuration descriptor
uint8 code g_fs_oscfg_dscr[] =
{
k_usb_cfgdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_osconfig, // descriptor type: other speed configuration
k_usb_cfgdscrsz +
k_usb_ifcdscrsz +
k_usb_ndpdscrsz +
k_usb_ndpdscrsz, // total length lo
0, // total length hi
1, // number of interfaces
0x01, // configuration value
0x00, // index of string descriptor
0xC0, // attributes: self powered, no remote wakeup
0x01, // _max power: 2ma
// interface descriptor: BOT mass storage
k_usb_ifcdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_interface, // descriptor type: interface
0, // interface number
0, // alternate interface
2, // number of endpoints
0x08, // usb interface class: mass storage
0x06, // usb interface subclass: scsi
0x50, // interface protocol: BOT (bulk only transport)
0x00, // interface string index
// endpoint descriptor: bulk out
k_usb_ndpdscrsz, // length of descriptor in bytes
0x05, // descriptor type: endpoint
0x02, // endpoint 2, out
0x02, // bulk
k_fs_maxpktsz, // max packet size lo
0x00, // max packet size hi
0x01, // polling interval
// endpoint descriptor: bulk in
k_usb_ndpdscrsz, // length of descriptor in bytes
0x05, // descriptor type: endpoint
0x82, // endpoint 2, in
0x02, // bulk
k_fs_maxpktsz, // max packet size lo
0x00, // max packet size hi
0x00, // polling interval
};
//------------------------------------------------------------------------------
// high speed other speed configuration descriptor
uint8 code g_hs_oscfg_dscr[] =
{
k_usb_cfgdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_osconfig, // descriptor type: other speed configuration
k_usb_cfgdscrsz +
k_usb_ifcdscrsz +
k_usb_ndpdscrsz +
k_usb_ndpdscrsz, // total length lo
0, // total length hi
1, // number of interfaces
0x01, // configuration value
0x00, // index of string descriptor
0xC0, // attributes: self powered, no remote wakeup
0x01, // _max power: 2ma
// interface descriptor: BOT mass storage
k_usb_ifcdscrsz, // length of descriptor in bytes
k_usb_dscr_typ_interface, // descriptor type: interface
0, // interface number
0, // alternate interface
2, // number of endpoints
0x08, // usb interface class: mass storage
0x06, // usb interface subclass: scsi
0x50, // interface protocol: BOT (bulk only transport)
0x00, // interface string index
// endpoint descriptor: bulk out
k_usb_ndpdscrsz, // length of descriptor in bytes
0x05, // descriptor type: endpoint
0x02, // endpoint 2, out
0x02, // bulk
_l(k_hs_maxpktsz), // max packet size lo
_h(k_hs_maxpktsz), // max packet size hi
0x01, // polling interval
// endpoint descriptor: bulk in
k_usb_ndpdscrsz, // length of descriptor in bytes
0x05, // descriptor type: endpoint
0x82, // endpoint 2, in
0x02, // bulk
_l(k_hs_maxpktsz), // max packet size lo
_h(k_hs_maxpktsz), // max packet size hi
0x00, // polling interval
};
//------------------------------------------------------------------------------
// globals
uint8 g_ix_dev_thread;
#define g_ix_mscbot_thread g_ix_dev_thread
#define k_ix_ser 0
#define k_sz_ser 26
#define k_ix_vid_lo 26
#define k_ix_vid_hi 27
#define k_ix_pid_lo 28
#define k_ix_pid_hi 29
#define k_ix_lng 30
#define k_sz_lng 4
#define k_ix_mfr 34
#define k_sz_mfr 60
#define k_ix_prd 94
#define k_sz_prd 60
#define k_ix_attr_hi 154
#define k_ix_attr_lh 155
#define k_ix_attr_hl 156
#define k_ix_attr_lo 157
// 158<->251 reserved
// ata0 format signature
#define k_ix_ata0_sig_hi 252
#define k_ix_ata0_sig_lh 253
#define k_ix_ata0_sig_hl 254
#define k_ix_ata0_sig_lo 255
#define k_ata0_sig_hi 0x61 // 'a'
#define k_ata0_sig_lh 0x74 // 't'
#define k_ata0_sig_hl 0x61 // 'a'
#define k_ata0_sig_lo 0x30 // '0'
// locals
// static bit _source_eeprom_raw; // true to source as serial num, false to source as string dscr
static bit _nvram_data_valid;
static bit _nvram_insert_vidpid;
static xdata uint8 _nvram_ix;
static xdata uint16 _nvram_sz;
static bit _serial_number_valid;
//------------------------------------------------------------------------------
// must store a copy of config so it can be checked after the usbrst arrives
// since on the 20x family the configuration is cleared by hardware.
static uint8 _most_recent_config = 0;
//+-----------------------------------------------------------------------------
// Name:
// dev_exception
//
// Declaration:
// void dev_exception(void);
//
// Purpose:
// Hard error. Log message to trace fifo and halt.
//
// Arguments:
// None.
//
// Return:
// Does not return.No return value.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dev_exception(uint16 ec) reentrant
{
ec=ec; // keep compiler happy for release builds
trace0(0, stk, 0, "** fatal exception **");
trace1(0, stk, 0, " code: %04x", ec);
trace1(0, stk, 0, " thd: %d", g_tid);
thread_halt();
}
//------------------------------------------------------------------------------
// Declaration:
// uint8 dev_rd_most_recent_config(void);
//
// Purpose:
// Report the most recent value set by a "set_configuration" request.
//
// Arguments:
// None.
//
// Return:
// A uint8 representing the most recent usb configuration value.
//------------------------------------------------------------------------------
uint8 dev_rd_most_recent_config() reentrant
{
return _most_recent_config;
}
//------------------------------------------------------------------------------
// Declaration:
// void dev_wr_most_recent_config(uint8 cfg);
//
// Purpose:
// Allow interface managers to clear it before rebooting.
//
// Arguments:
// None.
//
// Return:
// A uint8 representing the most recent usb configuration value.
//------------------------------------------------------------------------------
void dev_wr_most_recent_config(uint8 cfg) reentrant
{
_most_recent_config = cfg;
}
//+-----------------------------------------------------------------------------
// Name:
// dev_initialize
//
// Declaration:
// void dev_initialize(void);
//
// Purpose:
// Called once on POR. initialize device hardware.
//
// Arguments:
// None.
//
// Return:
// None.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
static void dev_initialize(void) reentrant;
static void dev_initialize() reentrant
{
TRACE0(1, dev, 1, "dev_initialize()" );
#ifdef k_mcu_97201
// setup ATA control register. clr muxen to select ATA interface.
_mcu_register_set_bits(x_ata_ctl, kbm_ata_ctl_out_control);
_mcu_register_clr_bits(x_ata_ctl, kbm_ata_ctl_muxen);
// initialize test register so proper phy will be controlled
#ifdef k_rev_c_klsi_phy
XBYTE[0x3F10] = 0x01; // rev C klsi phy
#else
XBYTE[0x3F10] = 0x00; // rev A klsi phy
#endif
#endif
#ifdef k_mcu_97210
#ifdef k_pkg_100
TRACE0(2, dev, 0, "package: 100 pin");
_mcu_register_set_bits( x_fmc_mode_ctl, kbm_fmc_mode_ctl_mux_en );
#endif
#ifdef k_pkg_128
TRACE0(3, dev, 0, "package: 128 pin");
_mcu_register_clr_bits( x_fmc_mode_ctl, kbm_fmc_mode_ctl_mux_en );
#endif
#endif
}
//+-----------------------------------------------------------------------------
// Name:
// dev_power_up
//
// Declaration:
// void dev_power_up(void);
//
// Purpose:
// Called on set-config(1), and resume if configuration is non-zero.
// Power on the flash media sockets as appropriate.
//
// Arguments:
// None.
//
// Return:
// None.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
static void dev_power_up(void) reentrant;
static void dev_power_up() reentrant
{
uint8 ps;
TRACE0(4, dev, 1, "dev_power_up()" );
// temporary - disable card status change irq's on power down, enable on power up
irq_control(k_irq_crd_sts_chg, kbm_irqctl_clear |kbm_irqctl_unmask);
ps = _mcu_register_rd(x_crd_ps);
// compact flash
#if (k_log_lun_cf < k_max_log_lun)
if (ps & kbm_crd_ps_cf)
{
TRACE0(5, dev, 0, "_cf_pwr_on()") ;
_cf_pwr_on();
_inserted(k_lun_cf);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio13);
#endif
}
#endif
// memory stick
#if (k_log_lun_ms < k_max_log_lun)
if (ps & kbm_crd_ps_ms)
{
_ms_pwr_on();
_inserted(k_lun_ms);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio12);
#endif
}
#endif
// smart media
#if (k_log_lun_sm < k_max_log_lun)
if (ps & kbm_crd_ps_sm)
{
_sm_pwr_on();
_inserted(k_lun_sm);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio14);
#endif
}
#endif
// secure digital / multi media card
#if (k_log_lun_sd < k_max_log_lun)
_sd_pwr_off();
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio15);
#endif
_sd_inserted_ejected();
_lun_map_log2phy(k_log_lun_sd, k_lun_sd);
#endif
// nand drive
#if (k_log_lun_nand < k_max_log_lun)
_nand_pwr_on();
// $$$ cds - this doesn't really make sense for a fixed drive.
// Will have to figure something out... like moving this to a lun-specific
// location
_inserted(k_lun_nand);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio14);
#endif
#endif
}
//+-----------------------------------------------------------------------------
// Name:
// dev_power_dn
//
// Declaration:
// void dev_power_dn(void);
//
// Purpose:
// Called on set-config(0), and suspend if configuration is non-zero.
// Power off the flash media sockets and mark the media as ejected.
//
// Arguments:
// None.
//
// Return:
// None.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
static void dev_power_dn(void) reentrant;
static void dev_power_dn() reentrant
{
TRACE0(6, dev, 1, "dev_power_dn()" );
// temporary - disable card status change irq's on power down, enable on power up
irq_control(k_irq_crd_sts_chg, kbm_irqctl_mask);
// simulate eject on all cards
_ejected(k_lun_cf);
_ejected(k_lun_ms);
_ejected(k_lun_sm);
//_sd_inserted_ejected();
// turn off all power to cards, indicator leds, etc
gpio_clrbit(0);
_mcu_register_set_bits(x_gpiob_out, kbm_gpio8 |kbm_gpio9 |kbm_gpio10 |kbm_gpio11 |kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
#ifdef k_pfm_led
// turn off the activity/inserted LEDs
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
#endif
}
//------------------------------------------------------------------------------
// prototypes
// top level state machine for built only transport
static void dev_thread_wait_csw(void) reentrant;
static void dev_thread_wait_cbw(void) reentrant;
static void dev_thread_wait_create1(void) reentrant;
static void dev_thread_wait_create(void) reentrant;
//------------------------------------------------------------------------------
// Declaration:
// t_result dev_mngr(t_message *msgp);
//
// Purpose:
// This is the manager for all things related to the whole device.
//
// Arguments:
// None.
//
// Return:
// k_success
// k_error
//
// Note:
// Do NOT yield from this routine. It is NOT part of any thread. It does
// not execute in an any thread's context. Yielding from within this function
// will cause your firmware to crash.
//
// Since:
// u2dp-1.0
//------------------------------------------------------------------------------
t_result dev_mngr(t_message_ref msgp) reentrant
{
uint8 lun;
TRACE0(31, dev, 0, "dev_mngr()");
switch (message_rd_id(msgp))
{
case k_msg_initialize:
TRACE0(32, dev, 0, "k_msg_initialize");
//fmc_dump_registers();
// create threads
g_ix_dev_thread = thread_create(dev_thread_wait_create, NULL, k_yes);
// set up the gpio interface
gpio_initialize();
// initialize the application
dev_initialize();
// set the output bits, turn them all off
gpio_bit_is_output(0);
gpio_bit_is_output(5);
_mcu_register_set_bits(x_gpiob_dir, kbm_gpio8 |kbm_gpio9 |kbm_gpio10 |kbm_gpio11 |kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
_mcu_register_set_bits(x_gpiob_out, kbm_gpio8 |kbm_gpio9 |kbm_gpio10 |kbm_gpio11 |kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
// data access led off
gpio_clrbit(0); // 0 is off
gpio_setbit(5); // 1 is off
// card power
#if (k_log_lun_cf < k_max_log_lun)
TRACE0(33, dev, 0, "_cf_pwr_off()") ;
_cf_pwr_off();
#endif
#if (k_log_lun_ms < k_max_log_lun)
_ms_pwr_off();
#endif
#if (k_log_lun_sm < k_max_log_lun)
_sm_pwr_on(); // must be on at power up to initialize inserted card, if present
#endif
#if (k_log_lun_sd < k_max_log_lun)
_sd_pwr_off();
#endif
#if (k_log_lun_nand < k_max_log_lun)
_nand_pwr_on(); // must be on at power up to initialize chips & retrieve boot block
#endif
#ifdef k_pfm_demo
// turn off the debug lights of science
_mcu_register_set_bits(x_gpiob_out, kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
#endif
#ifdef k_pfm_led
// turn off the activity/inserted LEDs
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
#endif
#ifdef k_pfm_profile
_profile_initialize();
#endif
// initialize the application specific interface managers
mscbot_mngr(msgp);
// setup the default logical to physical lun mapping
if (k_log_lun_cf < k_max_log_lun)
{
_lun_map_log2phy(k_log_lun_cf, k_lun_cf);
}
if (k_log_lun_ms < k_max_log_lun)
{
_lun_map_log2phy(k_log_lun_ms, k_lun_ms);
}
if (k_log_lun_sm < k_max_log_lun)
{
_lun_map_log2phy(k_log_lun_sm, k_lun_sm);
}
if (k_log_lun_sd < k_max_log_lun)
{
_lun_map_log2phy(k_log_lun_sd, k_lun_sd);
}
if (k_log_lun_nand < k_max_log_lun)
{
_lun_map_log2phy(k_log_lun_nand, k_lun_nand);
}
// initialize the physical luns
for (lun=0; lunwLengthHi;
g_wtmp *= 256;
g_wtmp += (uint16)rqstp->wLengthLo;
switch (message_rd_id(msgp))
{
case k_dsd_usb_get_descriptor:
_nvram_insert_vidpid = k_false;
_nvram_ix = 0;
_nvram_sz = 0;
TRACE3(39, dev, 0, "wLengthHi:%02X wLengthLo:%02X wtmp:%d", rqstp->wLengthHi, rqstp->wLengthLo, g_wtmp);
switch (rqstp->wValueHi)
{
case k_usb_dscr_typ_device:
TRACE0(40, dev, 0, "RQ_GET_DESCRIPTOR: device");
// tell the data pump where to find it and how much there is
if (sie_is_high_speed())
{
// eeprom vid/pid => if eeprom is valid, insert vidpid
_nvram_insert_vidpid = _nvram_data_valid;
_payload_source((_serial_number_valid?(&g_hs_dev_dscr_w_ser):(&g_hs_dev_dscr)), _min(g_hs_dev_dscr[0], g_wtmp));
}
else
{
// eeprom vid/pid => if eeprom is valid, insert vidpid
_nvram_insert_vidpid = _nvram_data_valid;
_payload_source((_serial_number_valid?(&g_fs_dev_dscr_w_ser):(&g_fs_dev_dscr)), _min(g_fs_dev_dscr[0], g_wtmp));
}
break;
case k_usb_dscr_typ_devqual:
TRACE0(41, dev, 0, "RQ_GET_DESCRIPTOR: devqual");
// tell the data pump where to find it and how much there is
if (sie_is_high_speed())
{
_payload_source(&g_fs_devqual_dscr, _min(g_fs_devqual_dscr[0], g_wtmp));
}
else
{
_payload_source(&g_hs_devqual_dscr, _min(g_hs_devqual_dscr[0], g_wtmp));
}
break;
case k_usb_dscr_typ_config:
TRACE0(42, dev, 0, "RQ_GET_DESCRIPTOR: configuration");
// make sure it is in the supported range
if (rqstp->wValueLo > k_dev_max_configuration)
return k_error;
// tell the data pump where to find it and how much there is
if (sie_is_high_speed())
{
_payload_source(&g_hs_cfg_dscr, _min(g_hs_cfg_dscr[2], g_wtmp));
}
else
{
_payload_source(&g_fs_cfg_dscr, _min(g_fs_cfg_dscr[2], g_wtmp));
}
break;
case k_usb_dscr_typ_osconfig:
TRACE0(43, dev, 0, "RQ_GET_DESCRIPTOR: other speed configuration");
// make sure it is in the supported range
if (rqstp->wValueLo > k_dev_max_configuration)
return k_error;
// tell the data pump where to find it and how much there is
if (sie_is_high_speed())
{
_payload_source( &g_fs_oscfg_dscr, _min(g_fs_oscfg_dscr[2], g_wtmp));
}
else
{
_payload_source(&g_hs_oscfg_dscr, _min(g_hs_oscfg_dscr[2], g_wtmp));
}
break;
case k_usb_dscr_typ_string:
TRACE0(44, dev, 0, "RQ_GET_DESCRIPTOR: string");
// make sure it is in the supported range
if (rqstp->wValueLo >= k_dev_max_string)
return k_error;
#ifdef k_support_nvram
// tell the data pump where to find it and how much there is
// grab string from rom, unless its asking for the serial number...
if (_nvram_data_valid)
{
switch (rqstp->wValueLo)
{
case k_dev_idx_str_dscr_lng:
TRACE0(45, dev, 0, "source: eeprom Language ID String descriptor");
_nvram_ix = k_ix_lng; // data only (same semantics as _source_eeprom_raw=k_false)
_nvram_sz = nvram_read(k_ix_lng);
break;
case k_dev_idx_str_dscr_mfg:
TRACE0(46, dev, 0, "source: eeprom Manufacturer ID String descriptor");
_nvram_ix = k_ix_mfr; // data only (same semantics as _source_eeprom_raw=k_false)
_nvram_sz = nvram_read(k_ix_mfr);
break;
case k_dev_idx_str_dscr_prd:
TRACE0(47, dev, 0, "source: eeprom Product ID String descriptor");
_nvram_ix = k_ix_prd; // data only (same semantics as _source_eeprom_raw=k_false)
_nvram_sz = nvram_read(k_ix_prd);
break;
case k_dev_idx_str_dscr_ser:
// ... in which case, extract it from the eeprom
if (_serial_number_valid)
{
TRACE0(48, dev, 0, "source: eeprom Serial Number String descriptor");
_nvram_ix = k_ix_ser; // data only (same semantics as _source_eeprom_raw=k_false)
_nvram_sz = nvram_read(k_ix_ser);
}
else
{
TRACE0(49, dev, 0, "warning: source, eeprom Serial Number String, not valid. no serial # reported");
return k_error;
}
break;
default:
TRACE1(50, dev, 0, "warning: no string descriptor at index %d", rqstp->wValueLo);
return k_error;
}
// send it along
// _payload_source(NULL, _min(eeprom_read(_nvram_ix), g_wtmp));
_payload_source(NULL, _min(_nvram_sz, g_wtmp));
}
else
{
if (rqstp->wValueLo != k_dev_idx_str_dscr_ser)
{
TRACE0(51, dev, 0, "source: default string descriptor");
_payload_source(g_str_dscr[rqstp->wValueLo], _min(*((uint8 *)g_str_dscr[rqstp->wValueLo]), g_wtmp));
}
else
{
// cannot happen
TRACE1(52, dev, 0, "warning: no string descriptor at index %d", rqstp->wValueLo);
return k_error;
}
}
#else
TRACE0(53, dev, 0, "source: default string descriptor (eeprom support disabled)");
_payload_source(g_str_dscr[rqstp->wValueLo], _min(*((uint8 *)g_str_dscr[rqstp->wValueLo]), g_wtmp));
#endif
break;
default:
return k_error;
}
return k_success;
case k_hsd_usb_set_configuration:
TRACE0(54, dev, 0, "RQ_SET_CONFIGURATION");
if ((uint8)message_rd_arg(msgp)) // unconfigured -> configured
dev_power_up();
else
dev_power_dn();
dev_wr_most_recent_config(sie_rd_configuration());
return k_success;
// vendor specific requests
case k_hci_dfu_detach:
trace0(0, dfu, 0, "k_hci_dfu_detach");
return dfu_cpex(msgp);
case k_hvd_wr_eerom:
TRACE1(55, dev, 0, "k_hvd_wr_eerom - length:%d", g_wtmp);
_nvram_ix = 0;
_nvram_sz = 256;
_payload_sink(NULL, _min(256, g_wtmp));
return k_success;
case k_dvd_rd_eerom:
TRACE1(56, dev, 0, "k_hvd_rd_eerom - length:%d", g_wtmp);
_nvram_ix = 0;
_nvram_sz = 256;
_payload_source(NULL, _min(256, g_wtmp));
return k_success;
case k_dvd_inq_devid:
TRACE0(57, dev, 0, "k_dvd_inq_devid");
_payload_source(_devid, sizeof(_devid));
return k_success;
// requests from the usb protocol engine
case k_msg_source_payload:
// load some application specific data into a packet buffer
// return k_in_progress if app expects to be supply at least one more packet's worth of data
// return k_finished otherwise
pnr = *(uint8 *)message_rd_arg(msgp);
pktsz = _min(g_data_len, k_maxpktsz);
g_data_len -= pktsz;
TRACE2(58, dev, 0, "k_msg_source_payload - pnr:%d pktsz:%d", pnr, pktsz);
// NULL addr means read non-volitile memory location like eeprom, flashed config info or hard-coded bytes
#ifdef k_support_nvram
if (NULL == g_source_addr)
{
nvram_source_payload(pnr, pktsz) ;
}
else
#endif
{
// write the default data
mmu_wr_pkt(0, pnr, g_source_addr, pktsz);
#ifdef k_support_nvram
if ( _nvram_insert_vidpid )
{
// overwrite the default data with eeprom vid-pid
mcu_begin_critical_section();
_mcu_register_wr(x_sram_addr_lo, (k_pkt_addrlo[pnr]+k_ix_dev_vid_lo) );
_mcu_register_wr(x_sram_addr_hi, k_pkt_addrhi[pnr]);
_mcu_register_wr(x_sram_data, nvram_read(k_ix_vid_lo));
_mcu_register_wr(x_sram_data, nvram_read(k_ix_vid_hi));
_mcu_register_wr(x_sram_data, nvram_read(k_ix_pid_lo));
_mcu_register_wr(x_sram_data, nvram_read(k_ix_pid_hi));
_nvram_insert_vidpid = k_false;
mcu_end_critical_section();
}
#endif
g_source_addr += pktsz;
}
return g_data_len ? k_in_progress : k_finished;
case k_msg_sink_payload:
// unload data from a packet buffer and do something application specific with it
// return k_in_progress if app can process this request
// return k_finished otherwise
pnr = *(uint8 *)message_rd_arg(msgp);
TRACE1(59, dev, 0, "and the packet number is:%d", pnr);
pktsz = _min(g_data_len, k_maxpktsz);
g_data_len -= pktsz;
#ifdef k_support_nvram
// NULL means write the eeprom
if (NULL == g_sink_addr)
{
nvram_sink_payload(pnr, pktsz) ;
}
else
#endif
{
mmu_rd_pkt(pnr, pktsz, g_sink_addr);
g_sink_addr += pktsz;
}
return g_data_len ? k_in_progress : k_finished;
default:
return k_error;
}
return k_error;
}
//------------------------------------------------------------------------------
// Declaration:
// t_result dev_intr(uint8 intr);
//
// Purpose:
// Handle interrupts.
//
// Arguments:
// intr - the interrupt that occurred. It is a number, not a bitmask.
//
// Return:
// k_ignored - causes default processing within the kernel isr
// k_success - prevents default processing within the kernel isr
//
// Note:
// This function is called from the kernel isrs. Therefore it executes at
// interrupt level, not foreground level.
//
// This function uses register bank 1 (as do the kernel's isrs) so you cannot
// call any function that is not wrapped by the #pragma NOAREGS.
// Only functions wrapped by this #pragma are callable from the isrs
// (except this one, of course, because it explicitly uses register bank 1...)
//
// Do NOT yield from this routine. It is NOT part of any thread. It does
// not execute in an any thread's context. Yielding from within this function
// will cause your firmware to flounder, panic, flail, and eventually expire.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
extern t_isr_fragment _hpbot_thread_entry;
t_result dev_intr(uint8 intr) reentrant using 1
{
t_result rslt;
TRACE1(60, dev, 1, "-(dev_intr(%d))", intr);
_stack_check();
// give first crack at it to the high priority interrupt chain
rslt = k_ignored;
if (_hpbot_thread_entry)
rslt = (*_hpbot_thread_entry)(intr);
if (rslt != k_ignored)
return rslt;
// high priority interupt chain didn't process it, so synchronize the foreground
switch (intr)
{
case k_irq_ramwr_a: // external0
// current xfer TO sram buffer A has completed
TRACE0(61, dev, 1, "--(k_irq_ramwr_a)");
thread_set_sync(g_ix_dev_thread, kbm_sync_usbrx);
return k_ignored;
case k_irq_ramwr_b: // external0
// current xfer TO sram buffer B has completed
TRACE0(62, dev, 1, "--(k_irq_ramwr_b)");
thread_set_sync(g_ix_dev_thread, kbm_sync_usbrx);
return k_ignored;
case k_irq_ramrd_a: // external0
// current xfer FROM sram buffer A has completed
TRACE0(63, dev, 1, "--(k_irq_ramrd_a)");
thread_set_sync(g_ix_dev_thread, kbm_sync_usbtx);
return k_ignored;
case k_irq_ramrd_b: // external0
// current xfer FROM sram buffer B has completed
TRACE0(64, dev, 1, "--(k_irq_ramrd_b)");
thread_set_sync(g_ix_dev_thread, kbm_sync_usbtx);
return k_ignored;
case k_irq_nak2rx: // external5
TRACE0(65, dev, 1, "--(k_irq_nak2rx)");
// set our usr synchronizer, knl isr auto-masked the nak irq
thread_set_sync(g_ix_dev_thread, kbm_sync_outnak);
return k_ignored;
case k_irq_nak2tx: // external5
TRACE0(66, dev, 1, "--(k_irq_nak2tx)");
// set our usr synchronizer, knl isr auto-masked the nak irq
thread_set_sync(g_ix_dev_thread, kbm_sync_innak);
return k_ignored;
case k_irq_usb_reset:
TRACE0(67, dev, 1, "--(k_irq_usb_reset)");
case k_irq_usb_stat_reset: // external0/x_usb_stat
// indicates that a usb reset has been detected
//TRACE0(95, dev, 1, "--(k_irq_usb_stat_reset)");
// don't disturb the mscbot thread if we aren't even enumerated yet
// because its probably initializing the drive still
if (dev_rd_most_recent_config())
{
// make sure to clear it so next reset during re-enum
// will not keep continually resetting the mcu.
dev_wr_most_recent_config(0);
TRACE0(68, dev, 1, "setting reset synch because configuration is set");
thread_set_sync(g_ix_dev_thread, kbm_sync_usbrst);
}
return k_ignored;
case k_irq_blk_xfer_complete: // external 0
TRACE0(69, dev, 1, "--(k_irq_blk_xfer_complete)");
thread_set_sync(g_ix_dev_thread, kbm_sync_fmc_blk);
x_imr0 |= kbm_isr0_blk_xfer_complete; //!!! persistent???
return k_success;
case k_irq_fmc: // external0
TRACE0(70, dev, 1, "--(k_irq_fmc)");
// may have to expand this function to decide _who_ interrupted us at this point
// by checking on who is currently in control of the mux
thread_set_sync(g_ix_dev_thread, kbm_sync_fmc_irq);
x_imr0 |= kbm_isr0_fmc_irq;
return k_success;
case k_irq_fmc_cfc_dev_err: // cfc_stat
TRACE0(71, dev, 1, "--(k_irq_fmc_cfc_dev_err)");
return k_success;
case k_irq_fmc_iordy_err: // cfc_stat
TRACE0(72, dev, 1, "--(k_irq_fmc_iordy_err)");
return k_success;
case k_irq_fmc_cfc_intrq: // cfc_stat
TRACE0(73, dev, 1, "--(k_irq_fmc_cfc_intrq)");
return k_success;
case k_irq_fmc_cfc_xrdy: // cfc_stat
TRACE0(74, dev, 1, "--(k_irq_fmc_cfc_xrdy)");
return k_success;
case k_irq_fmc_cfc_rrdy: // cfc_stat
TRACE0(75, dev, 1, "--(k_irq_fmc_cfc_rrdy)");
return k_success;
case k_irq_fmc_sm_ecc_err_d_a: // smc_stat
TRACE0(76, dev, 1, "--(k_irq_fmc_sm_ecc_err_d_a)");
thread_set_sync(g_ix_dev_thread, kbm_sync_fmc_blk);
return k_success;
case k_irq_fmc_sm_ecc_err_d_b: // smc_stat
TRACE0(77, dev, 1, "--(k_irq_fmc_sm_ecc_err_d_b)");
thread_set_sync(g_ix_dev_thread, kbm_sync_fmc_blk);
return k_success;
case k_irq_fmc_sm_ecc_err_c_a: // smc_stat
TRACE0(78, dev, 1, "--(k_irq_fmc_sm_ecc_err_c_a)");
thread_set_sync(g_ix_dev_thread, kbm_sync_fmc_blk);
return k_success;
case k_irq_fmc_sm_ecc_err_c_b: // smc_stat
TRACE0(79, dev, 1, "--(k_irq_fmc_sm_ecc_err_c_b)");
thread_set_sync(g_ix_dev_thread, kbm_sync_fmc_blk);
return k_success;
case k_irq_fmc_sm_rdy: // smc_stat
TRACE0(80, dev, 1, "--(k_irq_fmc_sm_rdy)");
return k_success;
case k_irq_fmc_msc_rdy: // msc_stat
TRACE0(81, dev, 1, "--(k_irq_fmc_msc_rdy)");
return k_success;
case k_irq_fmc_msc_sif_int: // msc_stat
TRACE0(82, dev, 1, "--(k_irq_fmc_msc_sif_int)");
return k_success;
case k_irq_fmc_msc_drq: // msc_stat
TRACE0(83, dev, 1, "--(k_irq_fmc_msc_drq)");
return k_success;
case k_irq_fmc_msc_crc_err: // msc_stat
TRACE0(84, dev, 1, "--(k_irq_fmc_msc_crc_err)");
return k_success;
case k_irq_fmc_msc_timeout_err: // msc_stat
TRACE0(85, dev, 1, "--(k_irq_fmc_msc_timeout_err)");
return k_success;
case k_irq_fmc_sdc_crc_err: // sdc_stat
TRACE0(86, dev, 1, "--(k_irq_fmc_sdc_crc_err)");
//set the abort sync, so that we can exit immediately from wait_xxx_timeout functions
thread_set_sync(g_ix_dev_thread, kbm_sync_abort);
// mask the intrrupt so it doesn't disturb us
irq_control(k_irq_fmc_sdc_crc_err, kbm_irqctl_clear |kbm_irqctl_mask);
return k_success;
case k_irq_fmc_sdc_crd_rdy: // sdc_stat
TRACE0(87, dev, 1, "--(k_irq_fmc_sdc_crd_rdy)");
return k_success;
case k_irq_fmc_sdc_rsp_rdy: // sdc_stat
TRACE0(88, dev, 1, "--(k_irq_fmc_sdc_rsp_rdy)");
return k_success;
case k_irq_fmc_sdc_cmd_rdy: // sdc_stat
TRACE0(89, dev, 1, "--(k_irq_fmc_sdc_cmd_rdy)");
return k_success;
case k_irq_fmc_sdc_flash_prg_err: // external0
TRACE0(90, dev, 1, "--(k_irq_fmc_sdc_flash_prg_err)");
//set the abort sync, so that we can exit immediately from wait_xxx_timeout functions
thread_set_sync(g_ix_dev_thread, kbm_sync_abort);
// mask the intrrupt so it doesn't disturb us
irq_control(k_irq_fmc_sdc_flash_prg_err, kbm_irqctl_clear |kbm_irqctl_mask);
return k_success;
case k_irq_cf_insert: // external2
TRACE0(91, dev, 1, "--(k_irq_cf_insert, media present, media unknown, media_changed)");
TRACE0(92, dev, 0, "_cf_pwr_on()") ;
_cf_pwr_on();
_inserted(k_lun_cf);
#ifdef k_pfm_led
_mcu_register_set_bits(x_gpiob_out, kbm_gpio13);
#endif
return k_ignored;
case k_irq_ms_insert: // external2
TRACE0(93, dev, 1, "--(k_irq_ms_insert, media present, media unknown, media_changed)");
_ms_pwr_on();
_inserted(k_lun_ms);
#ifdef k_pfm_led
_mcu_register_set_bits(x_gpiob_out, kbm_gpio12);
#endif
return k_ignored;
case k_irq_sm_insert: // external2
TRACE0(94, dev, 1, "--(k_irq_sm_insert, media present, media unknown, media_changed)");
_sm_pwr_on();
_inserted(k_lun_sm);
#ifdef k_pfm_led
_mcu_register_set_bits(x_gpiob_out, kbm_gpio14);
#endif
return k_ignored;
case k_irq_cf_eject: // external2
TRACE0(95, dev, 1, "--(k_irq_cf_eject, no media)");
TRACE0(96, dev, 0, "_cf_pwr_off()") ;
_cf_pwr_off();
_ejected(k_lun_cf);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio13);
#endif
return k_ignored;
case k_irq_ms_eject: // external2
TRACE0(97, dev, 1, "--(k_irq_ms_eject, no media)");
_ms_pwr_off();
_ejected(k_lun_ms);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio12);
#endif
return k_ignored;
case k_irq_sm_eject: // external2
TRACE0(98, dev, 1, "--(k_irq_sm_eject, no media)");
_sm_pwr_off();
_ejected(k_lun_sm);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio14);
#endif
return k_ignored;
case k_irq_sd_insert_eject: // external2
_lun_map_log2phy(k_log_lun_sd, k_lun_sd);
// don't mask the interrupt back in here, dfa_sd_initialize() does it when its done.
TRACE0(99, dev, 1, "--(k_irq_sd_insert_eject)");
_lun_map_log2phy(k_log_lun_sd, k_lun_sd);
_mcu_register_clr_bits(x_crd_ps, kbm_crd_ps_sd |kbm_crd_ps_mmc);
#ifdef k_pfm_led
_mcu_register_clr_bits(x_gpiob_out, kbm_gpio15);
#endif
_inserted(k_lun_sd);
_inserted(k_lun_mmc);
return k_ignored;
case k_irq_fmc_err_sd_blk_ovrun: // external2
TRACE0(100, dev, 1, "--(k_irq_fmc_err_sd_blk_ovrun)");
//set the abort sync, so that we can exit immediately from wait_xxx_timeout functions
thread_set_sync(g_ix_dev_thread, kbm_sync_abort);
// mask the intrrupt so it doesn't disturb us
irq_control(k_irq_fmc_err_sd_blk_ovrun, kbm_irqctl_clear |kbm_irqctl_mask);
return k_ignored;
default:
return k_ignored;
}
// how'd we get here?
return k_error;
}
//------------------------------------------------------------------------------
// holds return values from dfa's, accessed via argp.
static t_result _result;
//+-----------------------------------------------------------------------------
// Name:
// media_changed1
//
// Declaration:
// void media_changed1(void);
//
// Purpose:
// Called once per lun per media change.
// Runs _dfa_lun_initialize_media
//
// Arguments:
// None.
// However, relies on g_active_lun.
// Activates on kbm_sync_create.
//
// Return:
// No return value.
// However, the DFA's argument pointer is written with a t_result indicating:
// k_success - command completed.
// k_usbrst - usb reset signalling was detected while executing the command.
// k_aborted - traffic occurred on the control pipe while wexecuting the command (probably a mass storage reset).
// k_timeout - a timeout limit exceeded while executing the command.
// (This allows the caller to see the return value, via the argp, after the DFA terminates).
//
// Notes:
// This is a STATE in a DFA, not a FUNCTION.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
static void media_changed1(void) reentrant;
static void media_changed1() reentrant
{
TRACE0(101, dev, 0, "media_changed1()");
// check the results of _dfa_lun_reset_media...
if ((k_success == _result) && _lun_is_media_changed(g_active_lun))
{
// init media and return to dev_thread_wait_cbw
thread_run_dfa(_dfa_lun_initialize_media(g_active_lun), (void*) &_result, thread_end_dfa);
}
// reset failed, skip init, return to dev_thread_wait_cbw
thread_end_dfa();
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_media_changed
//
// Declaration:
// void dfa_media_changed(void);
//
// Purpose:
// Run once per lun per media change.
// Runs _dfa_lun_reset_media
//
// Arguments:
// None.
// However, the physical lun number must be passed in the thread's argp field.
// Activates on kbm_sync_create.
//
// Return:
// No return value.
// However, the DFA's argument pointer is written with a t_result indicating:
// k_success - command completed.
// k_usbrst - usb reset signalling was detected while executing the command.
// k_aborted - traffic occurred on the control pipe while wexecuting the command (probably a mass storage reset).
// k_timeout - a timeout limit exceeded while executing the command.
// (This allows the caller to see the return value, via the argp, after the DFA terminates).
// g_active_lun is modified here.
//
// Notes:
// This is a DFA, not a FUNCTION.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
static void dfa_media_changed(void) reentrant;
static void dfa_media_changed() reentrant
{
TRACE0(102, dev, 0, "dfa_media_changed()");
thread_clr_sync(kbm_sync_create);
TRACE1(103, dev, 0, "establish lun %d", g_active_lun);
thread_run_dfa(_dfa_lun_reset_media(g_active_lun), (void*) &_result, media_changed1);
}
//------------------------------------------------------------------------------
// Activates on kbm_sync_create.
//------------------------------------------------------------------------------
static void dev_thread_wait_csw() reentrant
{
TRACE0(104, dev, 0, "dev_thread_wait_csw()");
fgnd_hpbot_wait_status_start(_result);
thread_yield_ex2(kbm_sync_cbw, dev_thread_wait_cbw);
}
//------------------------------------------------------------------------------
// Activates on kbm_sync_cbw.
//------------------------------------------------------------------------------
static void dev_thread_wait_cbw() reentrant
{
uint8 media;
TRACE0(105, dev, 0, "dev_thread_wait_cbw()");
_lun_enable_mux(g_active_lun)();
// don't probe the cards on an inquiry
if (k_protocol_inquiry != g_bot_cbw.cdb[0])
{
if (_lun_is_media_changed(g_active_lun))
{
TRACE1(106, dev, 0, "media changed on phylun: %d", g_active_lun);
thread_run_dfa(dfa_media_changed, NULL, dev_thread_wait_cbw);
}
}
_thread_clr_sync(kbm_sync_cbw);
// BBB: the first optimization to this was to call these directly from dfa_lun_process_cb.
// that eliminated a dfa layer (55usec push, 66usec pop) and required no changes here.
// the second optimization was to call it directly from here on rd/wr.
// that eliminated another dfa layer cutting out 240 to 270 usec in toto (as measured).
thread_wr_dfa_argp(&_result);
media = _lun_data(g_active_lun, media);
#if 1
// this snippet fixes a problem of powering on with no media and havinf the host
// try to do a read even avter seeing a no-media sense code.
if (!(media & kbm_lun_media_present))
thread_run_dfa(_dfa_lun_process_cb(g_active_lun), &_result, dev_thread_wait_csw);
if (media & kbm_lun_media_changed)
thread_run_dfa(_dfa_lun_process_cb(g_active_lun), &_result, dev_thread_wait_csw);
if (media & kbm_lun_media_unknown)
thread_run_dfa(_dfa_lun_process_cb(g_active_lun), &_result, dev_thread_wait_csw);
#endif
switch (g_bot_cbw.cdb[0])
{
case k_protocol_read_10:
case k_protocol_read_12:
trace0(0, lun, 0, "cb-read (fast)");
//thread_run_dfa(_dfa_lun_read(g_active_lun), &_result, dev_thread_wait_csw);
(*_dfa_lun_read(g_active_lun))();
dev_thread_wait_csw();
case k_protocol_write_10:
case k_protocol_write_12:
trace0(0, lun, 0, "cb-write (fast)");
//thread_run_dfa(_dfa_lun_write(g_active_lun), &_result, dev_thread_wait_csw);
(*_dfa_lun_write(g_active_lun))();
dev_thread_wait_csw();
default:
thread_run_dfa(_dfa_lun_process_cb(g_active_lun), &_result, dev_thread_wait_csw);
}
}
//+-----------------------------------------------------------------------------
// Name:
// dev_thread_wait_create
//
// Declaration:
// void dev_thread_wait_create(void);
//
// Purpose:
// Called at POR.
//
// Arguments:
// None.
// Activates on kbm_sync_create.
//
// Return:
// No return value.
// This is the top level device thread. It never returns.
//
// Notes:
// This is a STATE in the top level device thread, not a FUNCTION.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
static void dev_thread_wait_create() reentrant
{
TRACE0(107, dev, 0, "dev_thread_wait_create()");
thread_clr_sync(kbm_sync_create);
TRACE0(108, dev, 0, "fire off the high prority bot interrupt chain");
fgnd_hpbot_wait_create();
// wait until a cbw arrives
thread_yield_ex2(kbm_sync_cbw, dev_thread_wait_cbw);
}
//---eof------------------------------------------------------------------------