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