www.pudn.com > SMSC USB2.0.zip > fmcdev.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. 
  ____________________________________________________________________________ 
  ____________________________________________________________________________ 
 
   -  
  ____________________________________________________________________________ 
 
  comments tbd 
  ____________________________________________________________________________ 
 
  Revision History 
  Date      Who  Comment 
  ________  ___  _____________________________________________________________ 
  05/31/00  tbh  initial version 
 
============================================================================*/ 
 
//////////////////////////////////////////////////////////////////////////////// 
// 
// USER DEVICE MODULE  
// 
// atapi 
// 
// please try very hard to make this mcu independent... 
// yes, there are some #ifdefs.  but this hasta run on the 102 sooner or later. 
// 
//////////////////////////////////////////////////////////////////////////////// 
#define __fmcdev_dot_c__ 
#include "fmc.h" 
 
//------------------------------------------------------------------------------ 
// specify the product version number 
//------------------------------------------------------------------------------ 
#include "version.inc" 
 
#define _hi_digit(b) ((uint8) (((uint8)(b>>4)&0x0f) + (uint8)'0')),0 
#define _lo_digit(b) ((uint8) (((uint8)(b   )&0x0f) + (uint8)'0')),0 
 
//------------------------------------------------------------------------------ 
// 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    0x10  // product id hi  
#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}; 
//------------------------------------------------------------------------------ 
// globals - keep your grubby mitts off these!  they are for "kernel" use only! 
//------------------------------------------------------------------------------ 
#if defined(k_mcu_97FDC) || defined(k_mcu_97102) 
uint8 g_usb_dev_addr;  // pending usb address, cleared by isr 
uint8 g_usb_dev_cfg;   // active configuration 
uint8 g_usb_dev_stat;  // device status 
#endif 
 
 
 
 
void        fmc_init() reentrant ; 
static void fmc_dump_registers() reentrant ; 
static void fmc_debug_12kb_ram() reentrant ; 
 
 
//------------------------------------------------------------------------------ 
// globals - you hafta change the initializers for these to serve your needs. 
//------------------------------------------------------------------------------ 
// string descriptors (in a form that the smsc romset utility can use) 
// endian: lil big 
// addrhi: msb lsb 
// addrlo: lsb msb 
//------------------------------------------------------------------------------ 
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[35][2] =  
{ 
    34, 3,          
    "F", "M", "C", " ", 
#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] = {40, 3, "N", "o", "n", "e"}; 
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 
//------------------------------------------------------------------------------ 
 
#define k_usb_cfundscsz			0x07 
#define k_usb_fundsctyp			0x21 
// full speed configuration descriptor 
#ifdef DFU 
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_ifcdscrsz +              
    k_usb_ndpdscrsz +              
    k_usb_ndpdscrsz,              // total length lo 
    0,                            // total length hi  
    2,                            // number of interfaces   2 to accomodate the DFU 
    0x01,                         // configuration value  
    0x00,                         // index of string descriptor  
    0xC0,                         // attributes: bus powered, no remote wakeup  
    0xFA,                         // _max power: 500ma  
    // 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 
    0x02,                         // usb interface subclass: SFF 
    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  
    //The DFU interface 
    k_usb_ifcdscrsz,              // length of descriptor in bytes  
    k_usb_dscr_typ_interface,     // descriptor type: interface  
    1,                            // interface number  
    0,                            // alternate interface  
    0,                            // number of endpoints  
    0xFE,                         // usb interface class: mass storage 
    0x01,                         // usb interface subclass: SFF 
    0x00,                         // interface protocol: BOT (bulk only transport)  
    0x00                         // interface string index  
}; 
#else 
 
 
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: bus powered, no remote wakeup  
    0xFA,                         // _max power: 500ma  
    // 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 
    0x02,                         // usb interface subclass: SFF 
    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  
}; 
#endif 
//------------------------------------------------------------------------------ 
// 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: bus powered, no remote wakeup  
    0xFA,                         // _max power: 500ma  
    // 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 
    0x02,                         // usb interface subclass: SFF 
    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: bus powered, no remote wakeup  
    0xFA,                         // _max power: 500ma  
    // 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 
    0x02,                         // usb interface subclass: SFF 
    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: bus powered, no remote wakeup  
    0xFA,                         // _max power: 500ma  
    // 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 
    0x02,                         // usb interface subclass: SFF 
    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  
}; 
 
//------------------------------------------------------------------------------ 
// Declaration: 
//  void build_serial_dscr( uint8* bufp ) 
// Purpose: 
//  builds a custom serial string descriptor from whatever data 
//  whatever value is stored in the x_ata_dev_str_ser buffer 
//  and places the result in the location specified by buf 
// Arguments: 
//  uint8* bufp - pointer to buffer to store dynamic descriptor 
// Return: 
//  None 
//------------------------------------------------------------------------------ 
 
void build_serial_dscr(uint8* bufp )  
{ 
    uint8 i ; 
 
    // zero the memory 
    for (i=0;i<2*41;i++) 
        bufp[i]=0; 
 
    // set length & type 
    bufp[0]=40; 
    bufp[1]=3 ; 
 
    // set the ascii string values 
    for (i=0;iunicode) 
        bufp[2*i+2] = x_ata_dev_str_ser[i] ; 
    } 
 
    // viola.  done 
} 
 
/*****************************************************************************/ 
/* bot_set_serial_number                                                     */ 
/* 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. 
/*****************************************************************************/ 
void bot_set_serial_number() reentrant  
{ 
 
 
#ifdef k_support_eeprom 
  uint8 i ; 
   
  // read length from eeprom 
  x_ata_dev_str_ser_sz = eeprom_read(0) ;  
  trace1(0, eep, 0, "Reading %d bytes of serial data", x_ata_dev_str_ser_sz) ; 
 
  for(i=0; i>> 
// Target MCU:  
//  FDC, 102, 200 
// Declaration:  
//  uint8 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. 
//------------------------------------------------------------------------------ 
uint8 dev_mngr(t_message *msgp) reentrant  
{ 
    trace0(0, dev, 0, "dev_mngr()"); 
    switch (message_rd_id(msgp)) 
    { 
    case k_msg_initialize: 
        trace0(0, dev, 0, "k_msg_initialize"); 
        // initialize gpios 
 
        // initialize the hardware   
        // x_gpioa_out = kbm_msk_gpioa_out_unconfigured; 
        // x_gpioa_dir = kbm_msk_gpioa_dir_unconfigured;  
 
        // create threads - no device specific threads required 
        // register endpoints - do nothing here, the interface managers will handle it 
        // register interfaces - do nothing here, the interface managers will handle it 
         
        // initialize the application specific interface managers 
        fmcapp_mngr(msgp); 
        // exit, stage left 
        return k_success; 
 
    case k_msg_kill: 
        trace0(0, dev, 0, "k_msg_kill"); 
        // terminate this manager 
        //TBD 
        // propagate the message to the application specific interface managers 
        fmcapp_mngr(msgp); 
        // dfu_mngr(msgp); 
        return k_success; 
 
    case k_msg_usbrst: 
        trace0(0, dev, 0, "k_msg_usbrst"); 
        // configured -> unconfigured (same as set config 0 in ctl_cpex.c) 
        // config the gpios 
         
        // x_gpioa_out = kbm_msk_gpioa_out_unconfigured; 
        // x_gpioa_dir = kbm_msk_gpioa_dir_unconfigured;  
         
         
        // propagate the message to the application specific interface managers 
        fmcapp_mngr(msgp); 
        // dfu_mngr(msgp); 
        return k_success; 
 
    case k_msg_resume: 
        TRACE0(416, fmcdev, 0, "k_msg_resume"); 
        // process the usb resume notificaion 
         
        // config the gpios 
//        x_gpioa_out = kbm_msk_gpioa_out_resumed; 
//        x_gpioa_dir = kbm_msk_gpioa_dir_resumed;  
         
        // propagate the message to the application specific interface managers 
        fmcapp_mngr(msgp); 
 
        TRACE0(417, fmcdev, 0, "Device resumed") ; 
        return k_success; 
 
    case k_msg_suspend: 
        TRACE0(418, fmcdev, 0, "k_msg_suspend"); 
        // process the usb suspend notificaion 
        // propagate the message to the application specific interface managers 
        fmcapp_mngr(msgp); 
 
        TRACE0(419, fmcdev, 0, "Device suspended") ; 
        return k_success; 
 
    default: 
        TRACE0(420, fmcdev, 0, "error: dev_mngr(unexpected message)"); 
        // unexpected message 
        return k_error; 
    } 
    // unexpected message 
    return k_error; 
} 
 
//------------------------------------------------------------------------------ 
// <<< DEVICE - CONTROL PIPE EXTENSION >>> 
// Target MCU:  
//  FDC, 102, 200 
// Declaration:  
//  uint8 dev_cpex(t_message *msgp); 
// Purpose:  
//  Handles requests targeted to the device: standard, class, vendor. 
// Arguments:  
//  None. 
// Return:  
//  k_success	- Causes the protocol engine to complete the status stage successfully. 
//  k_error - Causes the protocol engine to stall the control pipe. 
//  k_in_progress - For k_msg_source_payload, causes the protocol engine to deliver  
//   another empty packet buffer to the cpex to be loaded for transmission. 
//   For k_msg_sink_payload, informs the protocol engine that the cpex expects at  
//   least one more payload buffer to be delivered to it by the protocol engine. 
//  k_finished - For k_msg_source_payload and k_msg_sink_payload, informs the  
//   protocol engine that the data phase is complete and no more data is expected  
//   in either direction. 
// Note: 
//  Do NOT yield from this routine.  It is part of the protocol engine's thread.   
//  It executes in the context of g_ix_ctl_thread.  Yielding from within this  
//  function will cause the protocol engine's state machine to float belly up. 
//  And that will cause your firmware to shuffle off this mortal coil, post haste. 
//------------------------------------------------------------------------------ 
uint8 dev_cpex(t_message *msgp) reentrant 
{ 
    uint8 pktsz; 
    uint8 pnr; 
    t_usb_rqst *rqstp; 
 
    trace1(0, dev, 0, "dev_cpex(msg:%04X)", message_rd_id(msgp)); 
    rqstp = (t_usb_rqst *)(message_rd_arg(msgp)); 
    switch (message_rd_id(msgp)) 
    { 
 
    case k_dsd_usb_get_descriptor: 
        g_wtmp = rqstp->wLengthHi; 
        g_wtmp *= 256; 
        g_wtmp += (uint16)rqstp->wLengthLo; 
        trace3(0, dev, 0, "wLengthHi:%02X wLengthLo:%02X wtmp:%d", rqstp->wLengthHi, rqstp->wLengthLo, g_wtmp); 
        switch (rqstp->wValueHi) 
        { 
        case k_usb_dscr_typ_device: 
            trace0(0, dev, 0, "RQ_GET_DESCRIPTOR: device"); 
 
            // tell the data pump where to find it and how much there is  
 
#ifdef k_20x_family 
#ifdef k_support_eeprom 
                trace0(0, dev, 0, "device reports a serial number, send correct descriptor") ; 
                trace1(0, dev, 0, "x_sie_conf:%02X",x_sie_conf); 
                if ((x_sie_conf & kbm_sie_conf_hspeed)) 
                { 
                    _payload_source(&g_hs_dev_dscr_w_ser, _min(g_hs_dev_dscr_w_ser[0], g_wtmp)); 
                } else 
                { 
                    _payload_source(&g_fs_dev_dscr_w_ser, _min(g_fs_dev_dscr_w_ser[0], g_wtmp)); 
                } 
#else // no eeprom support 
                trace0(0, dev, 0, "device did not report a serial number.  non specified") 
                trace1(0, dev, 0, "x_sie_conf:%02X",x_sie_conf); 
                if ((x_sie_conf & kbm_sie_conf_hspeed)) 
                { 
                    _payload_source(&g_hs_dev_dscr, _min(g_hs_dev_dscr[0], g_wtmp)); 
                } else 
                { 
                    _payload_source(&g_fs_dev_dscr, _min(g_fs_dev_dscr[0], g_wtmp)); 
                } 
#endif // k_support_eeprom 
#else 
            _payload_source(&g_fs_dev_dscr, _min(g_fs_dev_dscr[0], g_wtmp)); 
#endif 
            break; 
 
        case k_usb_dscr_typ_devqual: 
            trace0(0, dev, 0, "RQ_GET_DESCRIPTOR: devqual"); 
            // tell the data pump where to find it and how much there is  
#ifdef k_20x_family 
            trace1(0, dev, 0, "x_sie_conf:%02X",x_sie_conf); 
            if ((x_sie_conf & kbm_sie_conf_hspeed)) 
            { 
                _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)); 
            } 
#else 
            _payload_source(&g_fs_devqual_dscr, _min(g_fs_devqual_dscr[0], g_wtmp)); 
#endif 
            break; 
 
        case k_usb_dscr_typ_config: 
            trace0(0, 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  
#ifdef k_20x_family 
            trace1(0, dev, 0, "x_sie_conf:%02X",x_sie_conf); 
            if ((x_sie_conf & kbm_sie_conf_hspeed)) 
            { 
                _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)); 
            } 
#else 
            _payload_source(&g_cfg_dscr, _min(g_cfg_dscr[2], g_wtmp)); 
#endif 
            break; 
 
        case k_usb_dscr_typ_osconfig: 
            trace0(0, 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  
#ifdef k_20x_family 
            trace1(0, dev, 0, "x_sie_conf:%02X",x_sie_conf); 
            if ((x_sie_conf & kbm_sie_conf_hspeed)) 
            { 
                _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)); 
            } 
#else 
            _payload_source(&g_cfg_osdscr, _min(g_oscfg_dscr[2], g_wtmp)); 
#endif 
            break; 
 
        case k_usb_dscr_typ_string: 
            trace0(0, dev, 0, "RQ_GET_DESCRIPTOR: string"); 
            // make sure it is in the supported range 
            if (rqstp->wValueLo >= k_dev_max_string) 
                return k_error; 
 
            // check which string descriptor is requested 
            switch (rqstp->wValueLo) 
            { 
            case k_dev_idx_str_dscr_ser: 
                if (x_ata_dev_has_ser) 
                { 
                    trace0(0, dev, 0, "sending custom serial num") ; 
                    // build a serial descriptor and put it into the gp sram 
                    _build_serial_dscr(&x_sram_buffer[0]) ; 
                    // ship it 
                    _payload_source(&x_sram_buffer[0], _min(x_sram_buffer[0], g_wtmp)) ; 
                    break; 
                } else 
                { 
                    trace0(0, dev, 0, "sending default serial num") ; 
                    // send default. 
                    _payload_source(g_str_dscr[rqstp->wValueLo], _min(*((uint8 *)g_str_dscr[rqstp->wValueLo]), g_wtmp)); 
                } 
                break; 
            case k_dev_idx_str_dscr_prd: 
                trace0(0, dev, 0, "sending default product string descriptor") ; 
                _payload_source(g_str_dscr[rqstp->wValueLo], _min(*((uint8 *)g_str_dscr[rqstp->wValueLo]), g_wtmp)); 
                break; 
            case k_dev_idx_str_dscr_mfg: 
                trace0(0, dev, 0, "sending default manufacturer string descriptor") ; 
                _payload_source(g_str_dscr[rqstp->wValueLo], _min(*((uint8 *)g_str_dscr[rqstp->wValueLo]), g_wtmp)); 
                break; 
            case k_dev_idx_str_dscr_lng: 
                trace0(0, dev, 0, "sending default language string descriptor") ; 
                _payload_source(g_str_dscr[rqstp->wValueLo], _min(*((uint8 *)g_str_dscr[rqstp->wValueLo]), g_wtmp)); 
                break; 
 
            default: 
                // tell the data pump where to find it and how much there is  
                trace1(0, dev, 0, "unknown value for string descriptor index:%d.  Sending default", rqstp->wValueLo) ; 
                _payload_source(g_str_dscr[rqstp->wValueLo], _min(*((uint8 *)g_str_dscr[rqstp->wValueLo]), g_wtmp)); 
            } 
            break; 
 
        default: 
            return k_error; 
        } 
        return k_success; 
 
#if defined(k_mcu_97FDC) || defined(k_mcu_97102) 
    case k_hsd_usb_set_descriptor:     
        trace0(0, dev, 0, "RQ_SET_DESCRIPTOR"); 
        return k_error; 
 
    case k_dsd_usb_get_configuration:  
        trace0(0, dev, 0, "RQ_GET_CONFIGURATION"); 
        // tell the data pump where to find it and how much there is  
        _payload_source(&g_usb_dev_cfg, 1); 
        return k_success; 
#endif 
 
    case k_hsd_usb_set_configuration:  
        trace0(0, dev, 0, "RQ_SET_CONFIGURATION"); 
#ifdef k_20x_family 
        if (*(uint8 *)(message_rd_arg(msgp))) 
        { 
            // config the gpios 
//            x_gpioa_out = kbm_msk_gpioa_out_configured; 
//            x_gpioa_dir = kbm_msk_gpioa_dir_configured;  
        } else 
        { 
            // config the gpios 
//            x_gpioa_out = kbm_msk_gpioa_out_unconfigured; 
//            x_gpioa_dir = kbm_msk_gpioa_dir_unconfigured;  
        } 
#else 
        // make sure it is in the supported range 
        if (rqstp->wValueLo > g_fs_dev_dscr[k_usb_devdscrsz - 1]) 
            return k_error; 
        // remember it 
        g_usb_dev_cfg = rqstp->wValueLo; 
        if (g_usb_dev_cfg)  // unconfigured -> configured 
        { 
            // config the gpios 
            x_gpioa_out = kbm_msk_gpioa_out_configured; 
            x_gpioa_dir = kbm_msk_gpioa_dir_configured;  
            // enable/disable endpoints, clear toggles, etc. 
            endpoint_rx_enable(1); 
            endpoint_tx_enable(2); 
            //endpoint_rx_enable(2); // don't enable the endpoint here - wait until we are ready in ATAPI.c 
 
            endpoint_clr_rx_toggle(1); 
            endpoint_clr_tx_toggle(2); 
        } else  // configured -> unconfigured 
        { 
            // config the gpios 
            x_gpioa_out = kbm_msk_gpioa_out_unconfigured; 
            x_gpioa_dir = kbm_msk_gpioa_dir_unconfigured;  
            // enable/disable endpoints, clear toggles, etc. 
            endpoint_rx_disable(1); 
            endpoint_tx_disable(2); 
        } 
#endif 
        return k_success; 
 
    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; 
        mmu_wr_pkt(0, pnr, g_source_addr, pktsz); 
        g_source_addr += pktsz; 
        trace2(0, dev, 0, "k_msg_source_payload - pnr:%d pktsz:%d", pnr, 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)); 
#ifdef k_20x_family 
 
 
//!!!watch out for this on sink pkts!!!!      ////////////////// pkt size s/b part of message!!! 
        pktsz = x_ep0rx_bc; 
#else                                                  
        pktsz = _min(g_data_len, k_maxpktsz); 
#endif 
        g_data_len -= pktsz; 
        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; 
} 
//------------------------------------------------------------------------------ 
// <<< DEVICE - INTERRUPT HANDLER >>> 
// Target MCU:  
//  FDC, 102, 200 
// Declaration:  
//  void dev_intr(void); 
// 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 fuction is called from the kernel isrs.  Therefore it executes at  
//  interrupt level, not foreground level.  In this current version of the kernel, 
//  all interrupts use register bank 0, the same as the foreground.  Thus, 
//  other functions can be called from inside dev_intr() (as long as they are 
//  either truly reentrant, or never called from the foreground).  But future 
//  versions of the kernel may use alternate register banks... so it is wise 
//  to avoid calling functions herein.  (Macros are ok, though...). 
//  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. 
// $$$ 
// TBD: 
//  For the 200 this needs to be copied into executable ram by the kernel, 
//  to execute from the "cache".  This has not been implemented yet, so watch 
//  this space for updates. 
//------------------------------------------------------------------------------ 
uint8 dev_intr(uint8 intr) reentrant using 1  
{ 
    trace1(0, dev, 1, "-(dev_intr(%d))", intr);  
    switch (intr) 
    { 
 
 
        // 200 interrupts 
        //$$$ allow default processing for these 
        // they are only included here to see tracepoints... 
#ifdef k_20x_family 
    case k_irq_usb_stat_ep2_err:      // external0/x_usb_stat 
        // a token in the opposite direction inferred by the kbm_ep2_ctl_dir bit of x_ep2_ctl 
        // i.e., an unexpected in or out token 
        trace0(0, dev, 1, "--(k_irq_usb_stat_ep2_err)"); 
        return k_ignored; 
 
    case k_irq_usb_stat_2dot0:        // external0/x_usb_stat 
        // high speed signalling detected by the host 
        trace0(0, dev, 1, "--(k_irq_usb_stat_2dot0)"); 
        return k_ignored; 
 
    case k_irq_usb_stat_resume:       // external0/x_usb_stat 
        // resume signaling detected.  only valid if the sie is in the suspend state 
        // via bit kbm_sie_conf_suspend or register x_sie_conf 
        trace0(0, dev, 1, "--(k_irq_usb_stat_resume)"); 
        return k_ignored; 
 
    case k_irq_usb_stat_reset:        // external0/x_usb_stat 
        // indicates that a usb reset has been detected 
        trace0(0, dev, 1, "--(k_irq_usb_stat_reset)"); 
        return k_ignored; 
 
    case k_irq_usberr_to:             // external0/x_usb_stat/x_usb_err 
        // sof occurred before valid ack handshake from host on some ndp 
        trace0(0, dev, 1, "--(k_irq_usberr_to)"); 
        return k_ignored; 
 
    case k_irq_usberr_token:          // external0/x_usb_stat/x_usb_err 
        // unexpected token received from host on some ndp 
        trace0(0, dev, 1, "--(k_irq_usberr_token)"); 
        return k_ignored; 
 
    case k_irq_usberr_ovrflw:         // external0/x_usb_stat/x_usb_err 
        // ndp2 packet bigger than 512 bytes received, 
        // or ndp0/1 packet bigger than 64 bytes received 
        trace0(0, dev, 1, "--(k_irq_usberr_ovrflw)"); 
        return k_ignored; 
 
    case k_irq_usberr_stall:          // external0/x_usb_stat/x_usb_err 
        // received a token on some ndp while that ndp was stalled 
        trace0(0, dev, 1, "--(k_irq_usberr_stall)"); 
        return k_ignored; 
 
    case k_irq_usberr_dtog:           // external0/x_usb_stat/x_usb_err 
        // bad toggle received on some endpoint 
        trace0(0, dev, 1, "--(k_irq_usberr_dtog)"); 
        return k_ignored; 
 
    case k_irq_usberr_bitstf:         // external0/x_usb_stat/x_usb_err 
        // packet with bit stuff error received on some ndp 
        trace0(0, dev, 1, "--(k_irq_usberr_bitstf)"); 
        return k_ignored; 
 
    case k_irq_usberr_pid:            // external0/x_usb_stat/x_usb_err 
        // packet with pid error received on some ndp 
        trace0(0, dev, 1, "--(k_irq_usberr_pid)"); 
        return k_ignored; 
 
    case k_irq_usberr_crc:            // external0/x_usb_stat/x_usb_err 
        // packet with crc error received on some ndp 
        trace0(0, dev, 1, "--(k_irq_usberr_crc)"); 
        return k_ignored; 
 
    case k_irq_usb_setup:             // external0 
        // a setup was received on ndp0 
        trace0(0, dev, 1, "--(k_irq_usb_setup)"); 
        return k_ignored; 
 
    case k_irq_fdc:                   // external0 
        // interrupt from the fdc control block 
        trace0(0, dev, 1, "--(k_irq_fdc)"); 
        return k_success; 
 
        //$$$ these need to actually do something 
 
    case k_irq_ata:                   // external0 
        // interrupt from the ata control block 
        trace0(0, dev, 1, "--(k_irq_ata)"); 
        //g_intr_cnt++ ; 
        thread_set_sync(g_ix_ata_thread, kbm_sync_ata_irq); 
        return k_success; 
 
    case k_irq_ramrd_b:               // external0 
        // current xfer FROM sram buffer B has completed 
        trace0(0, dev, 1, "--(k_irq_ramrd_b)"); 
 
        thread_set_sync(g_ix_ata_thread, kbm_sync_usbtx);  
        return k_ignored; 
 
    case k_irq_ramrd_a:               // external0 
        // current xfer FROM sram buffer A has completed 
        trace0(0, dev, 1, "--(k_irq_ramrd_a)"); 
        thread_set_sync(g_ix_ata_thread, kbm_sync_usbtx);  
        return k_ignored; 
 
    case k_irq_ramwr_b:               // external0 
        // current xfer TO sram buffer B has completed 
        trace0(0, dev, 1, "--(k_irq_ramwr_b)"); 
        thread_set_sync(g_ix_ata_thread, kbm_sync_usbrx);  
        return k_ignored; 
 
    case k_irq_ramwr_a:               // external0 
        // current xfer TO sram buffer A has completed 
        trace0(0, dev, 1, "--(k_irq_ramwr_a)"); 
        thread_set_sync(g_ix_ata_thread, kbm_sync_usbrx);  
        return k_ignored; 
 
    case k_irq_usb_ep0zlp:                 // external1  
        // zero length packet received & ack'd on ndp0 
        trace0(0, dev, 1, "--(k_irq_usb_ep0zlp)"); 
        return k_ignored; 
 
    case k_irq_debug:                 // external1  
        // debug data transmitted through debug port (datagram style) 
        trace0(0, dev, 1, "--(k_irq_debug)"); 
        return k_ignored; 
 
        //$$$ allow default processing for these 
        // they are only included here to see tracepoints... 
 
    case k_irq_usb_ep1rx:             // external1  
        // packet received on ndp1 
        trace0(0, dev, 1, "--(k_irq_usb_ep1rx)"); 
        return k_ignored; 
 
    case k_irq_usb_ep1tx:             // external1  
        // packet transmitted (and ack came back) on ndp1 
        trace0(0, dev, 1, "--(k_irq_usb_ep1tx)"); 
        return k_ignored; 
 
    case k_irq_usb_ep0rx:             // external1  
        // packet received on ndp0 
        trace0(0, dev, 1, "--(k_irq_usb_ep0rx)"); 
        return k_ignored; 
 
    case k_irq_usb_ep0tx:             // external1  
        // packet transmitted (and ack came back) on ndp0 
        trace0(0, dev, 1, "--(k_irq_usb_ep0tx)"); 
        return k_ignored; 
 
    case k_irq_usb_suspend:           // external1 
        // indicates that a usb suspend has been detected 
        trace0(0, dev, 1, "--(k_irq_usb_suspend)"); 
        return k_ignored; 
 
    case k_irq_usb_reset:             // external2  
        // usb reset detected 
        trace0(0, dev, 1, "--(k_irq_usb_reset)"); 
        return k_ignored; 
 
    case k_irq_usb_resume:            // external2 
        // usn resume signaling detected 
        trace0(0, dev, 1, "--(k_irq_usb_resume)"); 
        return k_ignored; 
 
    case k_irq_external:              // external2 
        // an external irq woke up the processor from sleep 
        trace0(0, dev, 1, "--(k_irq_external)"); 
        return k_ignored; 
 
    case k_irq_req_set_stall:         // external3 
        // sie core processed request 
        trace0(0, dev, 1, "--(k_irq_req_set_stall)"); 
        return k_ignored; 
 
    case k_irq_req_clr_stall:         // external3 
        // sie core processed request 
        trace0(0, dev, 1, "--(k_irq_req_clr_stall)"); 
        // set our custom sync bit 
        if ( !(g_thread[g_ix_ata_thread].bits_got & kbm_sync_cfes ) ) 
        { 
            thread_set_sync( g_ix_ata_thread, kbm_sync_cfes ) ; 
        } 
        return k_ignored; 
 
    case k_irq_req_set_cfg:           // external3 
        // sie core processed request 
        trace1(0, dev, 1, "--(k_irq_req_set_cfg x_usb_conf:%02X)", x_usb_conf); 
        return k_ignored; 
 
    case k_irq_req_set_ifc:           // external3 
        // sie core processed request 
        trace0(0, dev, 1, "--(k_irq_req_set_ifc)"); 
        return k_ignored; 
 
    case k_irq_req_set_rwu:           // external3 
        // sie core processed request 
        trace0(0, dev, 1, "--(k_irq_req_set_rwu)"); 
        return k_ignored; 
 
    case k_irq_req_clr_rwu:           // external3 
        // sie core processed request 
        trace0(0, dev, 1, "--(k_irq_req_clr_rwu)"); 
        return k_ignored; 
 
    case k_irq_gpio6:                 // external4 
    case k_irq_gpio7:                 // external4 
    case k_irq_gpio5:                 // external4 
    case k_irq_gpio4:                 // external4 
    case k_irq_gpio3:                 // external4 
    case k_irq_gpio2:                 // external4 
    case k_irq_gpio1:                 // external4 
    case k_irq_gpio0:                 // external4 
        trace1(0, dev, 1, "--(gpio interrupt:(%d))", intr); 
        return k_ignored; 
 
    case k_irq_nyet2rx:               // external5 
        trace0(0, dev, 1, "--(k_irq_nyet2rx)"); 
        return k_ignored; 
 
    case k_irq_nyet0rx:               // external5 
        trace0(0, dev, 1, "--(k_irq_nyet0rx)"); 
        return k_ignored; 
 
    case k_irq_nak2tx:                // external5 
        trace0(0, dev, 1, "--(k_irq_nak2tx)"); 
        // set our usr synchronizer, knl isr auto-masked the nak irq 
        thread_set_sync( g_ix_ata_thread, kbm_sync_innak ) ; 
        return k_ignored; 
 
    case k_irq_nak2rx:                // external5 
        trace0(0, dev, 1, "--(k_irq_nak2rx)"); 
        // set our usr synchronizer, knl isr auto-masked the nak irq 
        thread_set_sync( g_ix_ata_thread, kbm_sync_outnak ) ; 
        return k_ignored; 
 
    case k_irq_nak1tx:                // external5 
        trace0(0, dev, 1, "--(k_irq_nak1tx)"); 
        return k_ignored; 
 
    case k_irq_nak1rx:                // external5 
        trace0(0, dev, 1, "--(k_irq_nak1rx)"); 
        return k_ignored; 
 
    case k_irq_nak0tx:                // external5 
        trace0(0, dev, 1, "--(k_irq_nak0tx)"); 
        return k_ignored; 
 
    case k_irq_nak0rx:                // external5 
        trace0(0, dev, 1, "--(k_irq_nak0rx)"); 
        return k_ignored; 
#endif 
 
    default: 
        trace0(0, dev, 0, "hey, I dunno how to process that interrupt....?"); 
        return k_ignored; 
    } 
    // how'd we get here? 
    return k_error; 
} 
//////////////////////////////////////////////////////////////////////////////// 
// 
// DEVICE POLLER 
// poll for non-interrupt events related to the device and synchronize  
// the associated thread(s). 
// 
//////////////////////////////////////////////////////////////////////////////// 
 
// i think we don't need this... 
// implement dev_poll_whatever() here if you end up needing it... 
 
//////////////////////////////////////////////////////////////////////////////// 
// 
// INTERFACE THREAD 
// handles the application specific state machine for the device. 
// 
//////////////////////////////////////////////////////////////////////////////// 
 
 
//------------------------------------------------------------------------------ 
void fmcdev_dumpram(uint8 addrlo, uint8 addrhi, uint16 length) reentrant 
{ 
    uint16 n; 
    uint8 item; 
    mcu_begin_critical_section(); 
    x_sram_addr_lo = addrlo; 
    x_sram_addr_hi = addrhi; 
    for(n=0; n