- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# host_mem.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00013
    00014 /* Copyright (c) 2007, Atmel Corporation All rights reserved.
    00015  *
    00016  * Redistribution and use in source and binary forms, with or without
    00017  * modification, are permitted provided that the following conditions are met:
    00018  *
    00019  * 1. Redistributions of source code must retain the above copyright notice,
    00020  * this list of conditions and the following disclaimer.
    00021  *
    00022  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00023  * this list of conditions and the following disclaimer in the documentation
    00024  * and/or other materials provided with the distribution.
    00025  *
    00026  * 3. The name of ATMEL may not be used to endorse or promote products derived
    00027  * from this software without specific prior written permission.
    00028  *
    00029  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00030  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00031  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
    00032  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00033  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00034  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00035  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00036  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00037  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00038  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00039  */
    00040
    00041 //_____  I N C L U D E S ___________________________________________________
    00042
    00043 #include "config.h"                         // system configuration
    00044 #include <string.h>
    00045 #include "conf/conf_usb.h"
    00046 #include "host_mem.h"
    00047 #include "conf/conf_access.h"
    00048 #include "lib_mcu/usb/usb_drv.h"
    00049 #include "modules/usb/host_chap9/usb_host_enum.h"
    00050 #include "modules/usb/host_chap9/usb_host_task.h"
    00051 #include "modules/scsi_decoder/scsi_decoder.h"
    00052
    00053 //_____ D E F I N I T I O N ________________________________________________
    00054
    00055 #ifndef LOG_STR_CODE
    00056 #define LOG_STR_CODE(str)
    00057 #else
    00058 U8 code log_ms_connect[]="Mass Storage Connected";
    00059 #endif
    00060 #ifndef HOST_SECTOR_SIZE
    00061 #define HOST_SECTOR_SIZE   512   //default sector size is 512 bytes
    00062 #endif
    00063
    00064 #if (USB_HUB_SUPPORT==ENABLE)
    00065    #ifndef USB_MAX_DMS_NUMBER
    00066       #define USB_MAX_DMS_NUMBER    MAX_DEVICE_IN_USB_TREE-1
    00067    #endif
    00068 #else
    00069    #define USB_MAX_DMS_NUMBER 1
    00070 #endif
    00071
    00072 #ifndef USB_SUPPORT_MS_SECTOR_WR_MAX
    00073 #define USB_SUPPORT_MS_SECTOR_WR_MAX 1
    00074 #endif
    00075
    00076 #define USB_MAX_LUN_PER_DMS   4
    00077
    00078 // Structure data of CBW
    00079 typedef struct
    00080 {
    00081    U8 flag1;      //  0 - 'U'
    00082    U8 flag2;      //  1 - 'S'
    00083    U8 flag3;      //  2 - 'B'
    00084    U8 flag4;      //  3 - 'C'
    00085    U8 tag_lsb0;   //  4 - LSB0( CBW Tag )
    00086    U8 tag_lsb1;   //  5 - LSB1( CBW Tag )
    00087    U8 tag_lsb2;   //  6 - LSB2( CBW Tag )
    00088    U8 tag_lsb3;   //  7 - LSB3( CBW Tag )
    00089    U8 lgt_lsb0;   //  8 - LSB0( CBW Data Transfer Length )
    00090    U8 lgt_lsb1;   //  9 - LSB1( CBW Data Transfer Length )
    00091    U8 lgt_lsb2;   // 10 - LSB2( CBW Data Transfer Length )
    00092    U8 lgt_lsb3;   // 11 - LSB3( CBW Data Transfer Length )
    00093    U8 dir;        // 12 - CBW Flags
    00094    U8 lun;        // 13 - CBW LUN
    00095    U8 lgt;        // 14 - CBW length
    00096    U8 cmd;        // 15 - CBW Operation Code (= command)
    00097    U8 u8_data[15];// 16 - CBW Datas [15]
    00098 } S_cbw;
    00099
    00100 // Define the position of data in CBW struct
    00101 #define  HOST_MS_CBW_DATA_POS    16
    00102
    00103 // Information struct for each LUN
    00104 typedef struct
    00105 {
    00106    Bool b_first_unitready; // to send a BUSY/CHANGE status at first Unitready, bit Field corresponding at each LUN
    00107    Bool b_protected;       // bit Field corresponding at each LUN
    00108    U8 u8_block_size;       // unit 512B
    00109 } S_lun_info;
    00110
    00111 // Information struct for each MS device
    00112 typedef struct
    00113 {
    00114    U8 device_index;
    00115    U8 pipe_in;
    00116    U8 pipe_out;
    00117    U8 nb_lun;
    00118    S_lun_info lun_info[USB_MAX_LUN_PER_DMS];
    00119 } S_dms_device;
    00120
    00121
    00122 //_____ D E C L A R A T I O N ______________________________________________
    00123
    00124
    00125 S_cbw          g_ms_cbw;                           // Global CBW struct to optimize code
    00126 S_dms_device   g_ms_devices[USB_MAX_DMS_NUMBER];   // Information about each MS devices connected
    00127 U8    g_ms_nb_connected;                           // Number of MS device connected
    00128 U8    g_ms_sel_dms=0;                              // Index of current MS device
    00129 U8    g_ms_sel_lun;                                // Index of current LUN of current MS device
    00130
    00131 #if (USB_SUPPORT_MS_SECTOR_WR_MAX != 1)
    00132 U8    g_ms_cache[(USB_SUPPORT_MS_SECTOR_WR_MAX-1)*512];
    00133 #endif
    00134
    00135
    00136 // Variables to save a read context
    00137 // (to optimize the MS device with a sector size != 512B)
    00138 U8    g_readctx_b_run = FALSE;
    00139 U8    g_readctx_u8_device;
    00140 U8    g_readctx_u8_lun;
    00141 U32   g_readctx_u32_addr;
    00142 U16   g_readctx_u16_sector;
    00143
    00144
    00145 // Macro to control MS device state
    00146 #define  Is_host_ms_configured()    ((g_ms_nb_connected && Is_host_not_suspended() && Is_usb_id_host()) ? TRUE : FALSE )
    00147
    00148 // Current pipe corresponding at MS device selected
    00149 #define  DMS_pipe_in()              (g_ms_devices[g_ms_sel_dms].pipe_in)
    00150 #define  DMS_pipe_out()             (g_ms_devices[g_ms_sel_dms].pipe_out)
    00151
    00152
    00153 // Functions medium level
    00154 Ctrl_status host_mem_request_sense     ( void );
    00155
    00156 // Functions low level
    00157 Bool        host_mem_select_lun        ( U8 lun );
    00158 void        host_mem_cbw_init          ( void );
    00159 Bool        host_mem_cbw_send          ( void );
    00160 Ctrl_status host_mem_csw_read          ( void );
    00161 void        host_mem_stall_management  ( void );
    00162
    00163
    00164 //-----------------------------------------------------------------------
    00165 //------------ Functions to manage the list of MS devices ---------------
    00166
    00167
    00170 void host_mem_init( void )
    00171 {
    00172    U8 i;
    00173    // Reset Device MS struct
    00174    for(i=0; i<USB_MAX_DMS_NUMBER; i++)
    00175    {
    00176       g_ms_devices[i].device_index=0xFF;
    00177    }
    00178    g_ms_nb_connected=0;
    00179 }
    00180
    00181
    00184 Bool host_mem_install( void )
    00185 {
    00186    U32 capacity;
    00187    U8  device_num;
    00188    U8  interface_num;
    00189    U8  lun_offset;
    00190    U8  i;
    00191
    00192    // Check all devices connected
    00193    for( device_num=0; device_num<Get_nb_device(); device_num++)
    00194    {
    00195       Host_select_device(device_num);
    00196
    00197       // Check all interfaces of device
    00198       for( interface_num=0; interface_num < Get_nb_supported_interface(); interface_num++ )
    00199       {
    00200          if( Get_class(interface_num)!= MS_CLASS )
    00201             continue;   // It is not a MS interface
    00202
    00203          LOG_STR_CODE(log_ms_connect);
    00204
    00205          // If it is not the first MS device
    00206          if( g_ms_nb_connected != 0 )
    00207          {
    00208             // Check if already installed
    00209             for( i=0; i<g_ms_nb_connected; i++ )
    00210             {
    00211                if( g_ms_devices[i].device_index == device_num )
    00212                   break;
    00213             }
    00214             if( i!=g_ms_nb_connected )
    00215                break;      // Device already installed
    00216             // Check struct space free
    00217             if( USB_MAX_DMS_NUMBER == g_ms_nb_connected )
    00218                break;      // Too many MS device connected
    00219          }
    00220
    00221          //** Start install
    00222          g_ms_devices[g_ms_nb_connected].device_index = device_num;
    00223
    00224          // Get correct physical pipes associated to IN/OUT Mass Storage Endpoints
    00225          if(Is_ep_addr_in(Get_ep_addr(interface_num,0)))
    00226          {  //Yes associate it to the MassStorage IN pipe
    00227             g_ms_devices[g_ms_nb_connected].pipe_in=usb_tree.device[device_num].interface[interface_num].ep[0].pipe_number;
    00228             g_ms_devices[g_ms_nb_connected].pipe_out=usb_tree.device[device_num].interface[interface_num].ep[1].pipe_number;
    00229          }
    00230          else
    00231          {  //No, invert...
    00232             g_ms_devices[g_ms_nb_connected].pipe_in=usb_tree.device[device_num].interface[interface_num].ep[1].pipe_number;
    00233             g_ms_devices[g_ms_nb_connected].pipe_out=usb_tree.device[device_num].interface[interface_num].ep[0].pipe_number;
    00234          }
    00235
    00236          // Get last LUN number on the device mass storage connected
    00237          if( CONTROL_GOOD != host_ms_get_max_lun() )
    00238            data_stage[0] = 0; // If STALL request then last LUN number = 0
    00239          g_ms_devices[g_ms_nb_connected].nb_lun = data_stage[0]+1;   // Save number of LUN = last LUN number + 1
    00240
    00241          if( USB_MAX_LUN_PER_DMS < g_ms_devices[g_ms_nb_connected].nb_lun )
    00242             g_ms_devices[g_ms_nb_connected].nb_lun = USB_MAX_LUN_PER_DMS;   // Limitation on the number of LUN
    00243
    00244          // Compute LUN offset of this new device
    00245          lun_offset = 0;
    00246          for( i=0; i<g_ms_nb_connected; i++)
    00247          {
    00248             lun_offset +=g_ms_devices[i].nb_lun;
    00249          }
    00250
    00251          // Add the new MS device in MS strut
    00252          g_ms_sel_dms = g_ms_nb_connected;
    00253          g_ms_nb_connected++;
    00254
    00255          // Initialize all LUN from the new MS device
    00256          for( i=0; i<g_ms_devices[g_ms_sel_dms].nb_lun; i++ )
    00257          {
    00258             // Init struct of LUN
    00259             g_ms_devices[g_ms_sel_dms].lun_info[i].b_first_unitready = FALSE;
    00260             g_ms_devices[g_ms_sel_dms].lun_info[i].b_protected       = TRUE;
    00261             // Init MS corresponding at LUN
    00262             host_mem_inquiry( lun_offset+i );
    00263             host_mem_read_capacity( lun_offset+i, &capacity );
    00264          }
    00265          return TRUE;   // Install interface/device done
    00266       }
    00267    }
    00268    return FALSE;   // No MSC install
    00269 }
    00270
    00271
    00274 void host_mem_uninstall( void )
    00275 {
    00276    U8  device_num;
    00277    U8  i;
    00278    Bool b_last_ms_conected = TRUE;
    00279
    00280    for( i=g_ms_nb_connected; i!=0; i--)
    00281    {
    00282       device_num = g_ms_devices[i-1].device_index;
    00283       if( 0xFF == device_num )
    00284       {
    00285          // Device already remove but struct no updated
    00286          // it may be possible in case of many MS on USB HUB
    00287          g_ms_nb_connected--;
    00288          continue;
    00289       }
    00290       if( 0 == usb_tree.device[device_num].device_address )
    00291       {
    00292          g_ms_devices[i-1].device_index = 0xFF;
    00293          if( b_last_ms_conected )
    00294             g_ms_nb_connected--;
    00295       }else{
    00296          b_last_ms_conected = FALSE;
    00297       }
    00298    }
    00299 }
    00300
    00301
    00306 U8 host_mem_get_lun( void )
    00307 {
    00308    U8 i;
    00309    U8 host_ms_max_lun = 0;
    00310
    00311    if(!Is_host_ms_configured())
    00312       return 0;
    00313
    00314    for( i=0; i<g_ms_nb_connected; i++ )
    00315    {
    00316       host_ms_max_lun += g_ms_devices[i].nb_lun;
    00317    }
    00318    return host_ms_max_lun;
    00319 }
    00320
    00321
    00322 //-----------------------------------------------------------------------
    00323 //------------ Functions to control the state of each LUN ---------------
    00324
    00325
    00334 Ctrl_status host_mem_test_unit_ready(U8 lun)
    00335 {
    00336    Ctrl_status status;
    00337    U32   u32_nb_sector;
    00338
    00339    if( !host_mem_select_lun(lun) )
    00340       return CTRL_NO_PRESENT;
    00341    if (g_readctx_b_run)
    00342    {
    00343       host_mem_mem_2_ram_stop();
    00344       host_mem_select_lun(lun);
    00345    }
    00346
    00347    // Send CBW
    00348    host_mem_cbw_init();
    00349    // g_ms_cbw.lgt_lsb0 = 0;
    00350    g_ms_cbw.dir               = SBC_CMD_DIR_OUT;
    00351    g_ms_cbw.lgt               = 0x06;
    00352    g_ms_cbw.cmd               = SBC_CMD_TEST_UNIT_READY;
    00353    if( !host_mem_cbw_send() )
    00354       return CTRL_FAIL;
    00355
    00356    // Read CSW status
    00357    status = host_mem_csw_read();
    00358    if( status == CTRL_GOOD )
    00359    {
    00360       if( FALSE == g_ms_devices[g_ms_sel_dms].lun_info[g_ms_sel_lun].b_first_unitready )
    00361       {
    00362          // Signal the new diskl
    00363          status = CTRL_BUSY;
    00364          // U-Disk valid then update info LUN
    00365          if( CTRL_GOOD == host_mem_read_capacity( lun , &u32_nb_sector ) )
    00366          {
    00367             g_ms_devices[g_ms_sel_dms].lun_info[g_ms_sel_lun].b_protected       = host_mem_wr_protect( lun );
    00368             g_ms_devices[g_ms_sel_dms].lun_info[g_ms_sel_lun].b_first_unitready = TRUE;
    00369          }
    00370       }
    00371    }
    00372    else
    00373    {
    00374       g_ms_devices[g_ms_sel_dms].lun_info[g_ms_sel_lun].b_first_unitready = FALSE;
    00375    }
    00376    return status;
    00377 }
    00378
    00379
    00389 Ctrl_status host_mem_read_capacity(U8 lun, U32 _MEM_TYPE_SLOW_ *u32_nb_sector )
    00390 {
    00391    U16   nb;
    00392    U8    datas[8], status;
    00393
    00394    if( !host_mem_select_lun(lun) )
    00395       return CTRL_NO_PRESENT;
    00396    if (g_readctx_b_run)
    00397    {
    00398       host_mem_mem_2_ram_stop();
    00399       host_mem_select_lun(lun);
    00400    }
    00401
    00402    // Send CBW
    00403    host_mem_cbw_init();
    00404    g_ms_cbw.lgt_lsb0          = 0x08;
    00405    g_ms_cbw.dir               = SBC_CMD_DIR_IN;
    00406    g_ms_cbw.lgt               = 0x0A;
    00407    g_ms_cbw.cmd               = SBC_CMD_READ_CAPACITY;
    00408    if( !host_mem_cbw_send() )
    00409       return CTRL_FAIL;
    00410
    00411    // Receiv the capacity data
    00412    nb=8;
    00413    status = host_get_data(DMS_pipe_in(),&nb,datas);
    00414    if( PIPE_GOOD != status )
    00415    {
    00416       if( PIPE_STALL == status )
    00417         host_mem_stall_management();
    00418       host_mem_csw_read();
    00419       return CTRL_FAIL;
    00420    }
    00421
    00422    // Get last sector address
    00423    MSB0(*u32_nb_sector)      = datas[0];
    00424    MSB1(*u32_nb_sector)      = datas[1];
    00425    MSB2(*u32_nb_sector)      = datas[2];
    00426    MSB3(*u32_nb_sector)      = datas[3];
    00427    // Get block size (unit 512B)
    00428    g_ms_devices[ g_ms_sel_dms ].lun_info[ g_ms_sel_lun ].u8_block_size = datas[6]/2; // Block size MSB
    00429
    00430    // Read CSW status
    00431    return host_mem_csw_read();
    00432 }
    00433
    00434
    00441 U8    host_mem_read_sector_size( U8 lun )
    00442 {
    00443    host_mem_test_unit_ready( lun );
    00444    if( !host_mem_select_lun(lun) )
    00445       return 1;
    00446    return g_ms_devices[g_ms_sel_dms].lun_info[g_ms_sel_lun].u8_block_size;
    00447 }
    00448
    00449
    00457 Bool  host_mem_wr_protect_cache( U8 lun )
    00458 {
    00459    if( !host_mem_select_lun(lun) )
    00460       return TRUE;   // no present
    00461
    00462    return g_ms_devices[g_ms_sel_dms].lun_info[g_ms_sel_lun].b_protected;
    00463 }
    00464
    00465
    00472 Bool host_mem_wr_protect( U8 lun )
    00473 {
    00474    U16 nb;
    00475    U8 write_code[0x0C], status;
    00476
    00477    if( !host_mem_select_lun(lun) )
    00478       return TRUE;
    00479
    00480    if( USB_SUPPORT_MS_SECTOR_WR_MAX < g_ms_devices[ g_ms_sel_dms ].lun_info[ g_ms_sel_lun ].u8_block_size )
    00481       return TRUE;   // No supported this lun in write mode, because sector size != 512B
    00482
    00483    if (g_readctx_b_run)
    00484    {
    00485       host_mem_mem_2_ram_stop();
    00486       host_mem_select_lun(lun);
    00487    }
    00488
    00489    // Send CBW
    00490    host_mem_cbw_init();
    00491    g_ms_cbw.dir               = SBC_CMD_DIR_IN;
    00492    g_ms_cbw.lgt               = 0x06;
    00493    g_ms_cbw.cmd               = SBC_CMD_MODE_SENSE_6;
    00494    g_ms_cbw.lgt_lsb0          = 0x0C;
    00495    //g_ms_cbw.u8_data[16-16]  = 0x00;                 // 16 - CBWCB1 - Option
    00496    g_ms_cbw.u8_data[17-16]    = 0x3F;                 // 17 - CBWCB2 - Page Code 3F = return all mode pages
    00497    //g_ms_cbw.u8_data[18-16]  = 0x00;                 // 18 - CBWCB3 - reserved
    00498    g_ms_cbw.u8_data[19-16]    = 0x0C;                 // 19 - CBWCB4 - Allocation Length
    00499    //g_ms_cbw.u8_data[20-16]  = 0x00;                 // 20 - CBWCB5 - Control
    00500    if( !host_mem_cbw_send() )
    00501       return TRUE;
    00502
    00503    // Receiv
    00504    nb=0x0C;
    00505    status = host_get_data(DMS_pipe_in(),&nb,write_code);
    00506    if( PIPE_GOOD != status )
    00507    {
    00508       if( PIPE_STALL == status )
    00509         host_mem_stall_management();
    00510       write_code[2] = 0x00;   // error then no write protected by defaut
    00511    }
    00512
    00513    // Read CSW status
    00514    host_mem_csw_read();       // ignore error on CSW (in case of specific Udisk)
    00515
    00516    return (write_code[2] == 0x80);
    00517 }
    00518
    00519
    00524 Bool  host_mem_removal(void)
    00525 {
    00526    return TRUE;
    00527 }
    00528
    00529 /*
    00540 Ctrl_status host_mem_read_format_capacity( U8 lun )
    00541 {
    00542    U16 nb;
    00543    U8 datas[0xFC], status;
    00544
    00545    if( !host_mem_select_lun(lun) )
    00546       return CTRL_NO_PRESENT;
    00547    if (g_readctx_b_run)
    00548    {
    00549       host_mem_mem_2_ram_stop();
    00550       host_mem_select_lun(lun);
    00551    }
    00552
    00553    host_mem_cbw_init();
    00554    g_ms_cbw.lgt_lsb0          = 0xFC;
    00555    g_ms_cbw.dir               = SBC_CMD_DIR_IN;
    00556    g_ms_cbw.lgt               = 0x0C;
    00557    g_ms_cbw.cmd               = SBC_CMD_READ_FORMAT_CAPACITY;
    00558    //g_ms_cbw.u8_data[16-16]  = 0x00;              // 16 - CBWCB1 - relative address
    00559    //g_ms_cbw.u8_data[17-16]  = 0x00;              // 17 - CBWCB2 - MSB3(Logical Block Address)
    00560    //g_ms_cbw.u8_data[18-16]  = 0x00;              // 18 - CBWCB3 - MSB2(Logical Block Address)
    00561    //g_ms_cbw.u8_data[19-16]  = 0x00;              // 19 - CBWCB4 - MSB1(Logical Block Address)
    00562    //g_ms_cbw.u8_data[20-16]  = 0x00;              // 20 - CBWCB5 - MSB0(Logical Block Address)
    00563    //g_ms_cbw.u8_data[21-16]  = 0x00;              // 21 - CBWCB6 - reserved
    00564    //g_ms_cbw.u8_data[22-16]  = 0x00;              // 22 - CBWCB7 - reserved
    00565    g_ms_cbw.u8_data[23-16]  = 0xFC;                // 23 - CBWCB8 - PMI
    00566    //g_ms_cbw.u8_data[24-16]  = 0x00;              // 24 - CBWCB9 - Control
    00567    //g_ms_cbw.u8_data[25-16]  = 0x00;              // 25
    00568    //g_ms_cbw.u8_data[26-16]  = 0x00;              // 26
    00569    //g_ms_cbw.u8_data[27-16]  = 0x00;              // 27
    00570    //g_ms_cbw.u8_data[28-16]  = 0x00;              // 28
    00571    if( !host_mem_cbw_send() )
    00572       return CTRL_FAIL;
    00573
    00574    // Receiv Inquiry data
    00575    // Transfer data ...
    00576    nb=0xFC;
    00577    status = host_get_data(DMS_pipe_in(),&nb,datas);
    00578    // Ignore inquiry data
    00579    if( PIPE_STALL == status )
    00580      host_mem_stall_management();
    00581
    00582    // Read CSW status
    00583    return host_mem_csw_read();
    00584 }
    00585 */
    00586
    00597 Ctrl_status host_mem_inquiry( U8 lun )
    00598 {
    00599    U16 nb;
    00600    U8 datas[31], status;
    00601
    00602    if( !host_mem_select_lun(lun) )
    00603       return CTRL_NO_PRESENT;
    00604    if (g_readctx_b_run)
    00605    {
    00606       host_mem_mem_2_ram_stop();
    00607       host_mem_select_lun(lun);
    00608    }
    00609
    00610    host_mem_cbw_init();
    00611    g_ms_cbw.lgt_lsb0          = 0x24;
    00612    g_ms_cbw.dir               = SBC_CMD_DIR_IN;
    00613    g_ms_cbw.lgt               = 0x06;
    00614    g_ms_cbw.cmd               = SBC_CMD_INQUIRY;
    00615    //g_ms_cbw.u8_data[16-16]  = 0x00;              // 16 - CBWCB1 - Option
    00616    //g_ms_cbw.u8_data[17-16]  = 0x00;              // 17 - CBWCB2 - Page or operation code
    00617    //g_ms_cbw.u8_data[18-16]  = 0x00;              // 18 - CBWCB3 - reserved
    00618    g_ms_cbw.u8_data[19-16]    = 0x24;              // 19 - CBWCB4 - Allocation Length
    00619    //g_ms_cbw.u8_data[20-16]  = 0x00;              // 20 - CBWCB5 - Control
    00620    if( !host_mem_cbw_send() )
    00621       return CTRL_FAIL;
    00622
    00623    // Receiv Inquiry data
    00624    // Transfer data ...
    00625    nb=31;
    00626    status = host_get_data(DMS_pipe_in(),&nb,datas);
    00627    // Ignore inquiry data
    00628    if( PIPE_STALL == status )
    00629      host_mem_stall_management();
    00630
    00631    // Read CSW status
    00632    return host_mem_csw_read();
    00633 }
    00634
    00635
    00644 Ctrl_status host_mem_request_sense( void )
    00645 {
    00646    U16 nb;
    00647    U8 datas[17], status;
    00648    U8 sense_key, sense_key_add;
    00649
    00650    // Send CBW
    00651    host_mem_cbw_init();
    00652    g_ms_cbw.lgt_lsb0          = 0x12;
    00653    g_ms_cbw.dir               = SBC_CMD_DIR_IN;
    00654    g_ms_cbw.lgt               = 0x06;
    00655    g_ms_cbw.cmd               = SBC_CMD_REQUEST_SENSE;
    00656    //g_ms_cbw.u8_data[16-HOST_MS_CBW_DATA_POS]  = 0x00;  // 16 - CBWCB1 - reserved
    00657    //g_ms_cbw.u8_data[17-HOST_MS_CBW_DATA_POS]  = 0x00;  // 17 - CBWCB2 - reserved
    00658    //g_ms_cbw.u8_data[18-HOST_MS_CBW_DATA_POS]  = 0x00;  // 18 - CBWCB3 - reserved
    00659    g_ms_cbw.u8_data[19-HOST_MS_CBW_DATA_POS]    = 0x12;  // 19 - CBWCB4 - Allocation Length
    00660    //g_ms_cbw.u8_data[20-HOST_MS_CBW_DATA_POS]  = 0x00;  // 20 - CBWCW5 - Control
    00661    if( !host_mem_cbw_send() )
    00662       return CTRL_FAIL;
    00663
    00664    // Receiv Sense Code
    00665    nb=17;
    00666    status = host_get_data(DMS_pipe_in(),&nb,datas);
    00667    if( PIPE_GOOD != status )
    00668    {
    00669       if( PIPE_STALL == status )
    00670         host_mem_stall_management();
    00671       return CTRL_FAIL;
    00672    }
    00673
    00674    //  0 - Response Code
    00675    //  1 - obsolete
    00676    //  2 - Sense Key
    00677    sense_key = (0x0F & datas[2]);
    00678    //  3 - MSB3(Information)
    00679    //  4 - MSB2(Information)
    00680    //  5 - MSB1(Information)
    00681    //  6 - MSB0(Information)
    00682    //  7 - Additional Sense Length
    00683    //  8 - MSB3(Command Specific Information)
    00684    //  9 - MSB2(Command Specific Information)
    00685    // 10 - MSB1(Command Specific Information)
    00686    // 11 - MSB0(Command Specific Information)
    00687    // 12 - Additional Sense Code
    00688    sense_key_add = datas[12];
    00689    // 13 - Additional Sense Code Qualifier
    00690    // 14 - Field Replaceable Unit Code
    00691    // 15 - MSB2(Sense Key Specific)
    00692    // 16 - MSB1(Sense Key Specific)
    00693    // 17 - MSB0(Sense Key Specific)
    00694
    00695    // Receiv CSW, but ignore status
    00696    nb=13;
    00697    status = host_get_data(DMS_pipe_in(),&nb,datas);
    00698    if( PIPE_GOOD != status )
    00699    {
    00700       if( PIPE_STALL == status )
    00701         host_mem_stall_management();
    00702       return CTRL_FAIL;
    00703    }
    00704
    00705    // Translate Sense Code to device status
    00706    switch( sense_key )
    00707    {
    00708       case SBC_SENSE_KEY_NOT_READY:
    00709       if( SBC_ASC_MEDIUM_NOT_PRESENT == sense_key_add )
    00710          return CTRL_NO_PRESENT;
    00711       break;
    00712
    00713       case SBC_SENSE_KEY_UNIT_ATTENTION:
    00714       if( SBC_ASC_NOT_READY_TO_READY_CHANGE == sense_key_add )
    00715          return CTRL_BUSY;
    00716       if( SBC_ASC_MEDIUM_NOT_PRESENT == sense_key_add )
    00717          return CTRL_NO_PRESENT;
    00718       break;
    00719 /*
    00720       case SBC_SENSE_KEY_NO_SENSE:
    00721       case SBC_SENSE_KEY_HARDWARE_ERROR:
    00722       case SBC_SENSE_KEY_DATA_PROTECT:
    00723       break;
    00724 */
    00725    }
    00726    return CTRL_FAIL; // By default FAIL
    00727 }
    00728
    00729
    00730 //-----------------------------------------------------------------------
    00731 //-------- Functions to control read/write operations -------------------
    00732
    00733
    00747 Ctrl_status host_mem_mem_2_ram( U8 lun, U32 addr, U8 *ram )
    00748 {
    00749    U8    status;
    00750    U16   nb;
    00751    U8    u8_nb_sec_ignore_at_beg, u8_sector_size;
    00752    U32   u32_address;
    00753
    00754    if( !host_mem_select_lun(lun) )
    00755       return CTRL_FAIL; // no present
    00756
    00757    u8_nb_sec_ignore_at_beg    = 0;
    00758
    00759    if( g_readctx_b_run )
    00760    {
    00761       // Check if the sector requested is the following of previous read command
    00762       if( ( g_ms_devices[g_ms_sel_dms].device_index != g_readctx_u8_device)
    00763       ||  ( g_readctx_u8_lun != g_ms_sel_lun)
    00764       ||  ( g_readctx_u32_addr > addr)
    00765       ||  ( (g_readctx_u32_addr+g_readctx_u16_sector) <= addr ) )
    00766       {
    00767          host_mem_mem_2_ram_stop();
    00768          host_mem_select_lun(lun);
    00769       }else{
    00770          u8_nb_sec_ignore_at_beg = addr-g_readctx_u32_addr;
    00771       }
    00772    }
    00773
    00774    if( !g_readctx_b_run )
    00775    {
    00776       u8_sector_size = g_ms_devices[ g_ms_sel_dms ].lun_info[ g_ms_sel_lun ].u8_block_size;
    00777
    00778       // Compute the address in physical sector units
    00779       u32_address                = addr / u8_sector_size;
    00780       // Compute the number of sector to ignore from the beginning of the physical sector
    00781       u8_nb_sec_ignore_at_beg    = addr % u8_sector_size;
    00782       // Update context
    00783       g_readctx_u16_sector       = u8_sector_size;
    00784       g_readctx_u32_addr         = addr - u8_nb_sec_ignore_at_beg;
    00785
    00786       // Send CBW
    00787       host_mem_cbw_init();
    00788       g_ms_cbw.lgt_lsb0          = 0x00;
    00789       g_ms_cbw.lgt_lsb1          = u8_sector_size * (512/256);
    00790       g_ms_cbw.lgt_lsb2          = 0x00;
    00791       g_ms_cbw.lgt_lsb3          = 0x00;
    00792       g_ms_cbw.dir               = SBC_CMD_DIR_IN;
    00793       g_ms_cbw.lgt               = 0x0A;
    00794       g_ms_cbw.cmd               = SBC_CMD_READ_10;
    00795       //g_ms_cbw.u8_data[16-HOST_MS_CBW_DATA_POS]  = 0x00;              // 16 - CBWCB1 - Option
    00796       g_ms_cbw.u8_data[17-HOST_MS_CBW_DATA_POS]    = MSB0(u32_address); // 17 - CBWCB2 - MSB3(Logical Block Address)
    00797       g_ms_cbw.u8_data[18-HOST_MS_CBW_DATA_POS]    = MSB1(u32_address); // 18 - CBWCB3 - MSB2(Logical Block Address)
    00798       g_ms_cbw.u8_data[19-HOST_MS_CBW_DATA_POS]    = MSB2(u32_address); // 19 - CBWCB4 - MSB1(Logical Block Address)
    00799       g_ms_cbw.u8_data[20-HOST_MS_CBW_DATA_POS]    = MSB3(u32_address); // 20 - CBWCB5 - MSB0(Logical Block Address)
    00800       //g_ms_cbw.u8_data[21-HOST_MS_CBW_DATA_POS]  = 0x00;              // 21 - CBWCB6 - reserved
    00801       //g_ms_cbw.u8_data[22-HOST_MS_CBW_DATA_POS]  = 0x00;              // 22 - CBWCB7 - MSB1(Transfer Length)
    00802       g_ms_cbw.u8_data[23-HOST_MS_CBW_DATA_POS]    = 0x01;              // 23 - CBWCB8 - MSB0(Transfer Length)
    00803       //g_ms_cbw.u8_data[24-HOST_MS_CBW_DATA_POS]  = 0x00;              // 24 - CBWCB9 - Control
    00804       if( !host_mem_cbw_send() )
    00805          return CTRL_FAIL;
    00806    }
    00807
    00808    if( 0 != u8_nb_sec_ignore_at_beg )
    00809    {
    00810       // Ignore eventualy first sector of command (in case of device with sector >512B)
    00811       // Update sector remaining
    00812       g_readctx_u16_sector -= u8_nb_sec_ignore_at_beg;
    00813       g_readctx_u32_addr   += u8_nb_sec_ignore_at_beg;
    00814       while( 0 != u8_nb_sec_ignore_at_beg )
    00815       {
    00816          // Read one sector
    00817          nb=HOST_SECTOR_SIZE;
    00818          status = host_get_data(DMS_pipe_in(),&nb,NULL);
    00819          if(PIPE_GOOD != status)
    00820          {
    00821             if(PIPE_STALL==status)
    00822                host_mem_stall_management();
    00823             host_mem_csw_read();
    00824             return CTRL_FAIL;
    00825          }
    00826          u8_nb_sec_ignore_at_beg--;
    00827       }
    00828    }
    00829
    00830    // Transfer data ...
    00831    g_readctx_u16_sector--;
    00832    g_readctx_u32_addr++;
    00833    nb=HOST_SECTOR_SIZE;
    00834    status = host_get_data(DMS_pipe_in(),&nb,ram);
    00835    if(PIPE_GOOD != status)
    00836    {
    00837       if(PIPE_STALL==status)
    00838          host_mem_stall_management();
    00839       host_mem_csw_read();
    00840       return CTRL_FAIL;
    00841    }
    00842
    00843    if( 0 != g_readctx_u16_sector )
    00844    {
    00845       //  Update context
    00846       g_readctx_u8_device = g_ms_devices[g_ms_sel_dms].device_index;
    00847       g_readctx_u8_lun = g_ms_sel_lun;
    00848       g_readctx_b_run = TRUE;
    00849       return CTRL_GOOD;
    00850    }
    00851
    00852    // Read CSW status
    00853    g_readctx_b_run = FALSE;
    00854    return host_mem_csw_read();
    00855 }
    00856
    00857
    00866 Ctrl_status host_mem_mem_2_ram_stop( void )
    00867 {
    00868    U16 nb;
    00869    U8  status;
    00870
    00871    g_readctx_b_run = FALSE;
    00872
    00873    g_ms_sel_lun = g_readctx_u8_lun;
    00874    g_ms_sel_dms = g_readctx_u8_device;
    00875    Host_select_device( g_ms_devices[g_ms_sel_dms].device_index );
    00876
    00877    while( 0 != g_readctx_u16_sector )
    00878    {
    00879       // Read one sector
    00880       nb=HOST_SECTOR_SIZE;
    00881       status = host_get_data(DMS_pipe_in(),&nb,NULL);
    00882       if(PIPE_GOOD != status)
    00883       {
    00884          if(PIPE_STALL==status)
    00885             host_mem_stall_management();
    00886          host_mem_csw_read();
    00887          return CTRL_FAIL;
    00888       }
    00889       g_readctx_u16_sector--;
    00890    }
    00891
    00892    // Read CSW status
    00893    return host_mem_csw_read();
    00894 }
    00895
    00896
    00910 Ctrl_status host_mem_ram_2_mem( U8 lun, U32 addr, U8 *ram )
    00911 {
    00912    U8    status;
    00913    U16   nb, u16_sector;
    00914    U8    u8_nb_sec_ignore_at_beg, u8_sector_size;
    00915    U32   u32_address;
    00916 #if (USB_SUPPORT_MS_SECTOR_WR_MAX != 1)
    00917    Ctrl_status read_status;
    00918    U8    u8_i,u8_j;
    00919    U32   u32_addr;
    00920 #endif
    00921
    00922    if( !host_mem_select_lun(lun) )
    00923       return CTRL_FAIL; // no present
    00924
    00925    u8_sector_size = g_ms_devices[ g_ms_sel_dms ].lun_info[ g_ms_sel_lun ].u8_block_size;
    00926
    00927    if( USB_SUPPORT_MS_SECTOR_WR_MAX < u8_sector_size )
    00928       return CTRL_FAIL; // No supported this lun in write mode, because sector size != 512B
    00929
    00930
    00931    // Compute the address in physical sector units
    00932    u32_address                = addr / u8_sector_size;
    00933    // Compute the number of sector to ignore from the beginning of the physical sector
    00934    u8_nb_sec_ignore_at_beg    = addr % u8_sector_size;
    00935    // Update context
    00936    u16_sector                 = u8_sector_size;
    00937
    00938 #if (USB_SUPPORT_MS_SECTOR_WR_MAX != 1)
    00939    // If the sector size > 512B then read sector and store it in a buffer
    00940    if( 1 != u8_sector_size )
    00941    {
    00942       u32_addr = addr - u8_nb_sec_ignore_at_beg;
    00943       for( u8_i=0,u8_j=0 ; u8_i<u8_sector_size; u8_i++,u32_addr++ )
    00944       {
    00945          if( u8_i == u8_nb_sec_ignore_at_beg )
    00946             continue;
    00947          read_status = host_mem_mem_2_ram( lun, u32_addr, &g_ms_cache[u8_j*512] );
    00948          if( CTRL_GOOD != read_status )
    00949             return CTRL_GOOD;
    00950          u8_j++;
    00951       }
    00952    }
    00953 #endif
    00954
    00955    if (g_readctx_b_run)
    00956    {
    00957       host_mem_mem_2_ram_stop();
    00958       host_mem_select_lun(lun);
    00959    }
    00960
    00961    // Send CBW
    00962    host_mem_cbw_init();
    00963    //g_ms_cbw.lgt_lsb0        = 0x00;
    00964    g_ms_cbw.lgt_lsb1          = u8_sector_size * (512/256);
    00965    //g_ms_cbw.lgt_lsb2        = 0x00;
    00966    //g_ms_cbw.lgt_lsb3        = 0x00;
    00967    g_ms_cbw.dir               = SBC_CMD_DIR_OUT;
    00968    g_ms_cbw.lgt               = 0x0A;
    00969    g_ms_cbw.cmd               = SBC_CMD_WRITE_10;
    00970    //g_ms_cbw.u8_data[16-HOST_MS_CBW_DATA_POS]  = 0x00;        // 16 - CBWCB1 - Option
    00971    g_ms_cbw.u8_data[17-HOST_MS_CBW_DATA_POS]    = MSB0(u32_address);  // 17 - CBWCB2 - MSB3(Logical Block Address)
    00972    g_ms_cbw.u8_data[18-HOST_MS_CBW_DATA_POS]    = MSB1(u32_address);  // 18 - CBWCB3 - MSB2(Logical Block Address)
    00973    g_ms_cbw.u8_data[19-HOST_MS_CBW_DATA_POS]    = MSB2(u32_address);  // 19 - CBWCB4 - MSB1(Logical Block Address)
    00974    g_ms_cbw.u8_data[20-HOST_MS_CBW_DATA_POS]    = MSB3(u32_address);  // 20 - CBWCB5 - MSB0(Logical Block Address)
    00975    //g_ms_cbw.u8_data[21-HOST_MS_CBW_DATA_POS]  = 0x00;        // 21 - CBWCB6 - reserved
    00976    //g_ms_cbw.u8_data[22-HOST_MS_CBW_DATA_POS]  = 0x00;        // 22 - CBWCB7 - MSB1(Transfer Length)
    00977    g_ms_cbw.u8_data[23-HOST_MS_CBW_DATA_POS]    = 0x01;        // 23 - CBWCB8 - MSB0(Transfer Length)
    00978    //g_ms_cbw.u8_data[24-HOST_MS_CBW_DATA_POS]  = 0x00;        // 24 - CBWCB9 - Control
    00979    if( !host_mem_cbw_send() )
    00980       return CTRL_FAIL;
    00981
    00982 #if (USB_SUPPORT_MS_SECTOR_WR_MAX != 1)
    00983    if( 0 != u8_nb_sec_ignore_at_beg )
    00984    {
    00985       // Ignore eventualy first sector of command (in case of device with sector >512B)
    00986       // Update sector remaining
    00987       u16_sector -= u8_nb_sec_ignore_at_beg;
    00988       for( u8_i=0; u8_i < u8_nb_sec_ignore_at_beg; u8_i++ )
    00989       {
    00990          // Transfer data ...
    00991          nb=HOST_SECTOR_SIZE;
    00992          status = host_send_data(DMS_pipe_out(),nb,&g_ms_cache[u8_i*512]);
    00993          if(status==PIPE_STALL)
    00994          {
    00995             host_mem_stall_management();
    00996             host_mem_csw_read();
    00997             return CTRL_FAIL;
    00998          }
    00999       }
    01000    }
    01001 #endif
    01002
    01003    // Transfer data ...
    01004    u16_sector--;
    01005    nb=HOST_SECTOR_SIZE;
    01006    status = host_send_data(DMS_pipe_out(),nb,ram);
    01007    if(status==PIPE_STALL)
    01008    {
    01009       host_mem_stall_management();
    01010       host_mem_csw_read();
    01011       return CTRL_FAIL;
    01012    }
    01013
    01014 #if (USB_SUPPORT_MS_SECTOR_WR_MAX != 1)
    01015    while( 0 != u16_sector )
    01016    {
    01017       // Transfer data ...
    01018       nb=HOST_SECTOR_SIZE;
    01019       status = host_send_data(DMS_pipe_out(),nb,&g_ms_cache[u8_nb_sec_ignore_at_beg*512]);
    01020       if(status==PIPE_STALL)
    01021       {
    01022          host_mem_stall_management();
    01023          host_mem_csw_read();
    01024          return CTRL_FAIL;
    01025       }
    01026       u8_nb_sec_ignore_at_beg++;
    01027       u16_sector--;
    01028    }
    01029 #endif
    01030
    01031    // Read CSW status
    01032    return host_mem_csw_read();
    01033 }
    01034
    01035
    01036 //-----------------------------------------------------------------------
    01037 //-------------------- Functions low level ------------------------------
    01038
    01045 Bool host_mem_select_lun(U8 lun)
    01046 {
    01047    if( !Is_host_ms_configured() )
    01048       return FALSE;
    01049
    01050    for( g_ms_sel_dms=0; g_ms_sel_dms < g_ms_nb_connected; g_ms_sel_dms++ )
    01051    {
    01052       if(lun < g_ms_devices[g_ms_sel_dms].nb_lun )
    01053       {
    01054          if( 0xFF == g_ms_devices[g_ms_sel_dms].device_index )
    01055             return FALSE;                          // Device disconnected
    01056          g_ms_sel_lun = lun;
    01057          Host_select_device( g_ms_devices[g_ms_sel_dms].device_index );
    01058          return TRUE;
    01059       }
    01060       lun -= g_ms_devices[g_ms_sel_dms].nb_lun;
    01061    }
    01062    return FALSE;
    01063 }
    01064
    01065
    01068 void host_mem_cbw_init( void )
    01069 {
    01070    U8 tmp;
    01071
    01072    tmp = g_ms_cbw.tag_lsb0;
    01073    // Clear all structure
    01074    memset( &g_ms_cbw , 0, sizeof(g_ms_cbw) );
    01075    // Write Flag
    01076    g_ms_cbw.flag1 = 'U';
    01077    g_ms_cbw.flag2 = 'S';
    01078    g_ms_cbw.flag3 = 'B';
    01079    g_ms_cbw.flag4 = 'C';
    01080    // Increment tag
    01081    g_ms_cbw.tag_lsb0 = tmp+1;
    01082    // Update LUN
    01083    g_ms_cbw.lun = g_ms_sel_lun;
    01084 }
    01085
    01086
    01091 Bool host_mem_cbw_send( void )
    01092 {
    01093    return (PIPE_GOOD == host_send_data( DMS_pipe_out(), sizeof( g_ms_cbw ), (U8*) &g_ms_cbw ));
    01094 }
    01095
    01096
    01105 Ctrl_status host_mem_csw_read( void )
    01106 {
    01107    U16   nb;
    01108    U8    status;
    01109    U8    u8_datas[13];
    01110    Bool  b_status = TRUE;   // By default no error
    01111    Bool  b_stall  = TRUE;   // Accept one stall on CSW
    01112
    01113    while(1)
    01114    {
    01115       nb = 13;
    01116       status = host_get_data(DMS_pipe_in(),&nb,u8_datas);
    01117       if( PIPE_GOOD == status )
    01118          break;
    01119       if( PIPE_STALL == status )
    01120       {
    01121          host_mem_stall_management();
    01122          if( b_stall )
    01123          {
    01124             b_stall = FALSE;
    01125             continue;   // Error STALL but retry
    01126          }
    01127       }
    01128       return CTRL_FAIL;
    01129    }
    01130
    01131    if( PIPE_GOOD == status )
    01132    {
    01133       // CSW receiv then check CSW
    01134       // Check "USBS" string (0 to 3)
    01135       if(('U' != u8_datas[0] )
    01136       || ('S' != u8_datas[1] )
    01137       || ('B' != u8_datas[2] )
    01138       || ('S' != u8_datas[3] ) )
    01139       {
    01140          b_status = FALSE;    // Flag error
    01141       }
    01142       // Check CBW Tag (4 to 7)
    01143       if((g_ms_cbw.tag_lsb0 != u8_datas[4] )
    01144       || (0 != u8_datas[5] )
    01145       || (0 != u8_datas[6] )
    01146       || (0 != u8_datas[7] ) )
    01147       {
    01148          b_status = FALSE;    // Tag error
    01149       }
    01150       // CSW Data Residue (8 to 11)
    01151       // Check CSW status (12)
    01152       if ( 0 != u8_datas[12] )
    01153          b_status = FALSE;    // Status FAIL
    01154    }
    01155    else
    01156    {
    01157       b_status = FALSE;       // Error PIPE IN, then status FAIL
    01158    }
    01159
    01160    if( !b_status )
    01161       return host_mem_request_sense();
    01162
    01163    return CTRL_GOOD;
    01164 }
    01165
    01166
    01169 void host_mem_stall_management( void )
    01170 {
    01171    U8 dummy;
    01172
    01173    dummy = Host_get_endpoint_number() | ~MSK_EP_DIR;
    01174    host_clear_endpoint_feature(dummy);
    01175    Host_select_pipe(DMS_pipe_in());
    01176    Host_ack_stall();
    01177    Host_reset_pipe_data_toggle();
    01178 }
    01179
    01180