Addition of USB files

This commit is contained in:
c_oflynn 2008-10-14 20:16:36 +00:00
parent a520fe4646
commit 219846f408
36 changed files with 11046 additions and 0 deletions

View file

@ -0,0 +1,515 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file avr_flash.c *********************************************************
*
* \brief
* This file writes/reads to/from flash memory internal to the AVR.
*
* \addtogroup usbstick
*
* \author
* Colin O'Flynn <coflynn@newae.com>
******************************************************************************/
/*
Copyright (c) 2008 Colin O'Flynn
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
//_____ I N C L U D E S ___________________________________________________
#include "config.h" // system configuration
#include "storage/avr_flash.h"
#include <avr/pgmspace.h>
#include <avr/boot.h>
#ifndef SPM_PAGESIZE
#error SPM_PAGESIZE undefined!!!
#endif
//_____ M A C R O S ________________________________________________________
//_____ P R I V A T E D E C L A R A T I O N _____________________________
//_____ D E F I N I T I O N ________________________________________________
#define MEM_BASE_ADDRESS 0x10000UL
DATA U32 gl_ptr_mem; /* memory data pointer */
/* Disk management */
bit reserved_disk_space = FALSE; /* reserved space for application on disk */
U32 AVRF_DISK_SIZE = 111; /* 57 KB, some room at end saved for bootloader section */
void avrf_check_init( void );
//_____ D E C L A R A T I O N ______________________________________________
//!
//! @brief This function initializes the hw/sw ressources required to drive the AVR Flash
//!
//! @warning Code:?? bytes (function code length)
//!
//!/
void avrf_mem_init(void)
{
;
}
//!
//! @brief This function tests the state of the AVR Flash
//!
//! @warning Code:?? bytes (function code length)
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//! Else -> CTRL_NO_PRESENT
//!/
Ctrl_status avrf_test_unit_ready(void)
{
return CTRL_GOOD;
}
//!
//! @brief This function gives the address of the last valid sector.
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param *u32_nb_sector number of sector (sector = 512B). OUT
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//!/
Ctrl_status avrf_read_capacity( U32 *u32_nb_sector )
{
*u32_nb_sector = AVRF_DISK_SIZE;
return CTRL_GOOD;
}
//!
//! @brief This function returns the write protected status of the memory.
//!
//! Only used by memory removal with a HARDWARE SPECIFIC write protected detection
//! !!! The customer must unplug the memory to change this write protected status,
//! which cannot be for a DF.
//!
//! @warning Code:?? bytes (function code length)
//!
//! @return FALSE -> the memory is not write-protected (always)
//!/
Bool avrf_wr_protect(void)
{
return FALSE;
}
//!
//! @brief This function tells if the memory has been removed or not.
//!
//! @warning Code:?? bytes (function code length)
//!
//! @return FALSE -> The memory isn't removed
//!/
Bool avrf_removal(void)
{
return FALSE;
}
//------------ STANDARD FUNCTIONS to read/write the memory --------------------
//!
//! @brief This function performs a read operation of n sectors from a given address on.
//! (sector = 512B)
//!
//! DATA FLOW is: AVRF => USB
//!
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param addr Sector address to start the read from
//! @param nb_sector Number of sectors to transfer
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//! A error occur -> CTRL_FAIL
//!
Ctrl_status avrf_read_10( U32 addr , U16 nb_sector )
{
avrf_read_open(addr); // wait device is not busy, then send command & address
avrf_read_sector(nb_sector); // transfer data from memory to USB
avrf_read_close(); // unselect memory
return CTRL_GOOD;
}
//! This fonction initialise the memory for a write operation
//!
//! DATA FLOW is: USB => DF
//!
//!
//! (sector = 512B)
//! @param addr Sector address to start write
//! @param nb_sector Number of sectors to transfer
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//! A error occur -> CTRL_FAIL
//!
Ctrl_status avrf_write_10( U32 addr , U16 nb_sector )
{
avrf_write_open(addr); // wait device is not busy, then send command & address
avrf_write_sector(nb_sector); // transfer data from memory to USB
avrf_write_close(); // unselect memory
return CTRL_GOOD;
}
//------------ AVR FLASH LOWER LEVEL ROUTIENS -----------------------------------------
//!
//! @brief This function opens a DF memory in read mode at a given sector address.
//!
//! NOTE: Address may not be synchronized on the beginning of a page (depending on the DF page size).
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param pos Logical sector address
//!
//! @return bit
//! The open succeeded -> OK
//!/
bit avrf_read_open (Uint32 pos)
{
// Set the global memory ptr at a Byte address.
gl_ptr_mem = (pos * 512) + MEM_BASE_ADDRESS;
return OK;
}
//!
//! @brief This function unselects the current DF memory.
//!
//! @warning Code:?? bytes (function code length)
//!
//!/
void avrf_read_close (void)
{
;
}
//!
//! @brief This function is optimized and writes nb-sector * 512 Bytes from
//! DataFlash memory to USB controller
//!
//! DATA FLOW is: DF => USB
//!
//!
//! NOTE:
//! - First call must be preceded by a call to the df_read_open() function,
//! - The USB EPIN must have been previously selected,
//! - USB ping-pong buffers are free,
//! - As 512 is always a sub-multiple of page size, there is no need to check
//! page end for each Bytes,
//! - Interrupts are disabled during transfer to avoid timer interrupt,
//! - nb_sector always >= 1, cannot be zero.
//!
//! @warning code:?? bytes (function code length)
//!
//! @param nb_sector number of contiguous sectors to read [IN]
//!
//! @return bit
//! The read succeeded -> OK
//!/
bit avrf_read_sector (Uint16 nb_sector)
{
U8 i,j;
do
{
for (i = 8; i != 0; i--)
{
Disable_interrupt(); // Global disable.
for (j = 0; j < 64; j++) {
Usb_write_byte(pgm_read_byte_far(gl_ptr_mem++));
}
//# Send the USB FIFO IN content to the USB Host.
Usb_send_in(); // Send the FIFO IN content to the USB Host.
Enable_interrupt(); // Global interrupt re-enable.
// Wait until the tx is done so that we may write to the FIFO IN again.
while(Is_usb_write_enabled()==FALSE);
}
nb_sector--; // 1 more sector read
}
while (nb_sector != 0);
return OK; // Read done.
}
//!
//! @brief This function opens a DF memory in write mode at a given sector
//! address.
//!
//! NOTE: If page buffer > 512 bytes, page content is first loaded in buffer to
//! be partially updated by write_byte or write64 functions.
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param pos Sector address
//!
//! @return bit
//! The open succeeded -> OK
//!/
bit avrf_write_open (Uint32 pos)
{
// Set the global memory ptr at a Byte address.
gl_ptr_mem = (pos * 512) + MEM_BASE_ADDRESS;
return OK;
}
//!
//! @brief This function fills the end of the logical sector (512B) and launch
//! page programming.
//!
//! @warning Code:?? bytes (function code length)
//!
//!/
void avrf_write_close (void)
{
;
}
/* This code can be setup to work with the DFU bootloader, which comes with the AT90USB1287. However I haven't
had time to test it with such */
#define LAST_BOOT_ENTRY 0xFFFE
void dfuclone_boot_buffer_write(uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word);
void dfuclone_boot_page_erase(uint32_t dummy1, uint16_t dummy2, uint32_t address);
void dfuclone_boot_page_write(uint32_t dummy1, uint16_t dummy2, uint32_t address);
/* Enable the use of the AVR DFU bootloader by defining "USE_AVRDFU_BOOTLOADER", it will
then call the low-level routines already in the bootloader. */
#ifdef USE_AVRDFU_BOOTLOADER
#error UNTESTED/UNSUPPORTED AT THIS TIME
// These functions pointers are used to call functions entry points in bootloader
void (*dfu_boot_buffer_write) (uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)=
(void (*)(uint16_t, uint32_t, uint16_t, uint16_t))(LAST_BOOT_ENTRY-6);
void (*dfu_boot_page_write) (uint32_t dummy1, uint16_t dummy2, uint32_t address)=
(void (*)(uint32_t, uint16_t, uint32_t))(LAST_BOOT_ENTRY-4);
void (*dfu_boot_page_erase) (uint32_t dummy1, uint16_t dummy2, uint32_t address)=
(void (*)(uint32_t, uint16_t, uint32_t))(LAST_BOOT_ENTRY-2);
#else
// These functions pointers are used to call functions entry points in bootloader
void (*dfu_boot_buffer_write) (uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)=
dfuclone_boot_buffer_write;
void (*dfu_boot_page_write) (uint32_t dummy1, uint16_t dummy2, uint32_t address)=
dfuclone_boot_page_write;
void (*dfu_boot_page_erase) (uint32_t dummy1, uint16_t dummy2, uint32_t address)=
dfuclone_boot_page_erase;
#endif
//!
//! @brief This function is optimized and writes nb-sector * 512 Bytes from
//! USB controller to DataFlash memory
//!
//! DATA FLOW is: USB => DF
//!
//!
//! NOTE:
//! - First call must be preceded by a call to the df_write_open() function,
//! - As 512 is always a sub-multiple of page size, there is no need to check
//! page end for each Bytes,
//! - The USB EPOUT must have been previously selected,
//! - Interrupts are disabled during transfer to avoid timer interrupt,
//! - nb_sector always >= 1, cannot be zero.
//!
//! @warning code:?? bytes (function code length)
//!
//! @param nb_sector number of contiguous sectors to write [IN]
//!
//! @return bit
//! The write succeeded -> OK
//!/
bit avrf_write_sector (Uint16 nb_sector)
{
Byte i, j;
U16 w;
U16 pgindex = 0;
U16 sector_bytecounter = 0;
do
{
//# Write 8x64b = 512b from the USB FIFO OUT.
for (i = 8; i != 0; i--)
{
// Wait end of rx in USB EPOUT.
while(Is_usb_read_enabled()==FALSE);
Disable_interrupt(); // Global disable.
//If start of page, erase it!
if (pgindex == 0) {
(*dfu_boot_page_erase)(0, 0, gl_ptr_mem);
}
//For all the data in the endpoint, write to flash temp page
for (j = 0; j < 32; j++) {
w = Usb_read_byte();
w += Usb_read_byte() << 8;
(*dfu_boot_buffer_write)(0, gl_ptr_mem, pgindex, w);
pgindex += 2;
}
Usb_ack_receive_out(); // USB EPOUT read acknowledgement.
//If we have filled flash page, write that sucker to memory
if (pgindex == SPM_PAGESIZE) {
(*dfu_boot_page_write)(0,0, gl_ptr_mem);
Enable_interrupt(); // Global enable again
gl_ptr_mem += SPM_PAGESIZE; // Update the memory pointer.
pgindex = 0;
sector_bytecounter += SPM_PAGESIZE;
if(sector_bytecounter == 512) {
nb_sector--; // 1 more sector written
sector_bytecounter = 0;
}
}
} // for (i = 8; i != 0; i--)
}
while (nb_sector != 0);
return OK; // Write done
}
#ifndef USE_AVRDFU_BOOTLOADER
/* Perform read/write of FLASH, using same calling convention as low-level routines in AVR DFU bootloader */
BOOTLOADER_SECTION void dfuclone_boot_buffer_write(uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)
{
boot_page_fill(baseaddr + pageaddr, word);
return;
}
BOOTLOADER_SECTION void dfuclone_boot_page_erase(uint32_t dummy1, uint16_t dummy2, uint32_t address)
{
boot_page_erase(address);
boot_spm_busy_wait();
boot_rww_enable();
return;
}
BOOTLOADER_SECTION void dfuclone_boot_page_write(uint32_t dummy1, uint16_t dummy2, uint32_t address)
{
boot_page_write(address);
boot_spm_busy_wait();
boot_rww_enable();
return;
}
#endif //USE_AVRDFU_BOOTLOADER
//------------ SPECIFIC FONCTION USB TRANSFER -----------------------------------------
//** If your device transfer have a specific transfer for USB (Particularity of Chejudo product, or bootloader)
// !!! In this case the driver must be know the USB access
//! This fonction transfer the memory data (programed in scsi_read_10) directly to the usb interface
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//!
Ctrl_status avrf_usb_read()
{
return CTRL_GOOD;
}
//! This fonction transfer the usb data (programed in scsi_write_10) directly to the memory data
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//!
Ctrl_status avrf_usb_write( void )
{
return CTRL_GOOD;
}
/** @} */

View file

@ -0,0 +1,135 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file avr_flash.h *********************************************************
*
* \brief
* This file writes/reads to/from flash memory internal to the AVR.
*
* \addtogroup usbstick
*
* \author
* Colin O'Flynn <coflynn@newae.com>
******************************************************************************/
/*
Copyright (c) 2008 Colin O'Flynn
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
#ifndef _DFMEM_H_
#define _DFMEM_H_
#include "conf_access.h"
#include "ctrl_status.h"
//_____ D E F I N I T I O N S ______________________________________________
//! FAT specification
#define ENTRY_SIZE 32 // size of entrie in byte
// First sector of the disk virtual (this disk isn't partitioned, only one partion)
#define PBR_SECTOR (0)
#define FAT_SECTOR (PBR_SECTOR + VMEM_RESERVED_SIZE)
#define ROOT_SECTOR (FAT_SECTOR + (VMEM_SIZE_FAT*VMEM_NB_FATS))
#define FILE_SECTOR (ROOT_SECTOR + ((ENTRY_SIZE*VMEM_NB_ROOT_ENTRY) / VMEM_SECTOR_SIZE)) // 1(sector) = size root dir
/* FAT Format Structure */
typedef struct
{
Uint16 nb_cylinder;
Byte nb_head;
Byte nb_sector;
Byte nb_hidden_sector;
Byte nb_sector_per_cluster;
} s_format;
#define MEM_BSY 0
#define MEM_OK 1
#define MEM_KO 2
//---- CONTROL FONCTIONS ----
// those fonctions are declared in df_mem.h
void avrf_mem_init(void);
Ctrl_status avrf_test_unit_ready(void);
Ctrl_status avrf_read_capacity( U32 _MEM_TYPE_SLOW_ *u32_nb_sector );
Bool avrf_wr_protect(void);
Bool avrf_removal(void);
//---- AVR FLASH LOW-LEVEL----
bit avrf_init (void);
bit avrf_mem_check(void);
bit avrf_read_open (Uint32);
void avrf_read_close (void);
bit avrf_write_open (Uint32);
void avrf_write_close (void);
//! Funtions to link USB DEVICE flow with data flash
bit avrf_write_sector (Uint16);
bit avrf_read_sector (Uint16);
s_format * avrf_format (void);
//---- ACCESS DATA FONCTIONS ----
// Standard functions for open in read/write mode the device
Ctrl_status avrf_read_10( U32 addr , U16 nb_sector );
Ctrl_status avrf_write_10( U32 addr , U16 nb_sector );
//** If your device transfer have a specific transfer for USB (Particularity of Chejudo product, or bootloader)
#ifdef DF_VALIDATION
#include "virtual_usb.h"
#else
#include "usb_drv.h" // In this case the driver must be known for the USB access
#endif
Ctrl_status avr_usb_read( void );
Ctrl_status avr_usb_write( void );
#endif // _DFMEM_H_
/** @} */

View file

@ -0,0 +1,197 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file conf_access.h *********************************************************************
*
* \brief
* This file contains the possible external configuration of the control access
*
* \addtogroup usbstick
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com
******************************************************************************/
/*
Copyright (c) 2004 ATMEL Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
#ifndef _CONF_ACCESS_H_
#define _CONF_ACCESS_H_
// Active the Logical Unit
#define LUN_0 DISABLE // On-Chip flash vitual memory
#define LUN_1 DISABLE // NF 2KB
#define LUN_2 DISABLE // NF 512B
#define LUN_3 DISABLE // Data Flash
#define LUN_4 ENABLE //On-chip 32KB
#define LUN_5 DISABLE
#define LUN_6 DISABLE
#define LUN_7 DISABLE
#define LUN_USB DISABLE
// LUN 0 DEFINE
#define LUN_0_INCLUDE "lib_mem\virtual_mem\virtual_mem.h"
#define Lun_0_test_unit_ready() virtual_test_unit_ready()
#define Lun_0_read_capacity(nb_sect) virtual_read_capacity(nb_sect)
#define Lun_0_wr_protect() virtual_wr_protect()
#define Lun_0_removal() virtual_removal()
#define Lun_0_read_10(ad, sec) virtual_read_10(ad, sec)
#define Lun_0_usb_read() virtual_usb_read()
#define Lun_0_write_10(ad, sec) virtual_write_10(ad, sec)
#define Lun_0_usb_write() virtual_usb_write()
#define Lun_0_ram_2_mem(addr , ram) virtual_ram_2_mem(addr, ram)
#define Lun_0_ram_2_mem_write() virtual_ram_2_mem_write()
#define Lun_0_mem_2_ram(addr , ram) virtual_mem_2_ram(addr, ram)
#define Lun_0_mem_2_ram_read() virtual_mem_2_ram_read()
#define LUN_0_NAME "VIRTUAL_MEM_ON_CHIP"
// LUN 1 DEFINE
#if (LUN_1 == ENABLE)
#define NF_2K_MEM ENABLE
#else
#define NF_2K_MEM DISABLE
#endif
#define LUN_1_INCLUDE "lib_mem\nf_1x_2kb\nf_mem.h"
#define Lun_1_test_unit_ready() nf_test_unit_ready()
#define Lun_1_read_capacity(nb_sect) nf_read_capacity(nb_sect)
#define Lun_1_wr_protect() nf_wr_protect()
#define Lun_1_removal() nf_removal()
#define Lun_1_read_10(ad, sec) nf_read_10(ad, sec)
#define Lun_1_usb_read() nf_usb_read()
#define Lun_1_write_10(ad, sec) nf_write_10(ad, sec)
#define Lun_1_usb_write() nf_usb_write()
#define Lun_1_ram_2_mem(addr , ram) TODO
#define Lun_1_ram_2_mem_write() TODO
#define Lun_1_mem_2_ram(addr , ram) TODO
#define Lun_1_mem_2_ram_read() TODO
// LUN 2 DEFINE
#if (LUN_2 == ENABLE)
#define NF_512_MEM ENABLE
#else
#define NF_512_MEM DISABLE
#endif
#define LUN_2_INCLUDE "lib_mem\nf_1x_512\nf_mem.h"
#define Lun_2_test_unit_ready() nf_test_unit_ready()
#define Lun_2_read_capacity(nb_sect) nf_read_capacity(nb_sect)
#define Lun_2_wr_protect() nf_wr_protect()
#define Lun_2_removal() nf_removal()
#define Lun_2_read_10(ad, sec) nf_read_10(ad, sec)
#define Lun_2_usb_read() nf_usb_read()
#define Lun_2_write_10(ad, sec) nf_write_10(ad, sec)
#define Lun_2_usb_write() nf_usb_write()
#define Lun_2_ram_2_mem(addr , ram) TODO
#define Lun_2_ram_2_mem_write() TODO
#define Lun_2_mem_2_ram(addr , ram) TODO
#define Lun_2_mem_2_ram_read() TODO
// LUN 3 DEFINE
#if (LUN_3 == ENABLE)
#define DF_MEM ENABLE
#else
#define DF_MEM DISABLE
#endif
#define LUN_ID_DF LUN_ID_3
#define LUN_3_INCLUDE "lib_mem\df\df_mem.h"
#define Lun_3_test_unit_ready() df_test_unit_ready()
#define Lun_3_read_capacity(nb_sect) df_read_capacity(nb_sect)
#define Lun_3_wr_protect() df_wr_protect()
#define Lun_3_removal() df_removal()
#define Lun_3_read_10(ad, sec) df_read_10(ad, sec)
#define Lun_3_usb_read() df_usb_read()
#define Lun_3_write_10(ad, sec) df_write_10(ad, sec)
#define Lun_3_usb_write() df_usb_write()
#define Lun_3_ram_2_mem(addr , ram) df_ram_2_df(addr, ram)
#define Lun_3_ram_2_mem_write() df_ram_2_df_write()
#define Lun_3_mem_2_ram(addr , ram) df_df_2_ram(addr, ram)
#define Lun_3_mem_2_ram_read() df_df_2_ram_read()
#define LUN_3_NAME "\"On board data flash\""
// LUN 3 DEFINE
#if (LUN_3 == ENABLE)
#define AVR_MEM ENABLE
#else
#define AVR_MEM DISABLE
#endif
#define LUN_ID_AVRF LUN_ID_4
#define LUN_4_INCLUDE "storage/avr_flash.h"
#define Lun_4_test_unit_ready() avrf_test_unit_ready()
#define Lun_4_read_capacity(nb_sect) avrf_read_capacity(nb_sect)
#define Lun_4_wr_protect() avrf_wr_protect()
#define Lun_4_removal() avrf_removal()
#define Lun_4_read_10(ad, sec) avrf_read_10(ad, sec)
#define Lun_4_usb_read() avrf_usb_read()
#define Lun_4_write_10(ad, sec) avrf_write_10(ad,sec)
#define Lun_4_usb_write() avrf_usb_write()
#define Lun_4_ram_2_mem(addr , ram) TODO
#define Lun_4_ram_2_mem_write() TODO
#define Lun_4_mem_2_ram(addr , ram) TODO
#define Lun_4_mem_2_ram_read() TODO
#define LUN_4_NAME "\"AVR Flash Memory\""
// LUN USB DEFINE
#if (LUN_USB == ENABLE)
#define MEM_USB ENABLE
#else
#define MEM_USB DISABLE
#endif
#define LUN_USB_INCLUDE "lib_mem\host_mem\host_mem.h"
#define Lun_usb_test_unit_ready(lun) host_test_unit_ready(lun)
#define Lun_usb_read_capacity(lun,nb_sect) host_read_capacity(lun,nb_sect)
#define Lun_usb_wr_protect(lun) host_wr_protect(lun)
#define Lun_usb_removal() host_removal()
#define Lun_usb_ram_2_mem(addr , ram) host_write_10_ram(addr, ram)
#define Lun_usb_mem_2_ram(addr , ram) host_read_10_ram(addr, ram)
#define LUN_USB_NAME "\"USB Remote memory\""
// ATMEL DEFINE - DO NOT MODIFY
// Active interface fonction
#define ACCESS_USB ENABLED // USB I/O in control access
#define ACCESS_STREAM DISABLED // Stream I/O in control access
#define ACCESS_STREAM_RECORD DISABLED // Stream I/O in control access AND RECORD MODE
#define ACCESS_MEM_TO_RAM DISABLED // RAM to Mem I/O in control access
#define ACCESS_MEM_TO_MEM DISABLED // Mem to Mem I/O in control access
// Specific option control access
#define GLOBAL_WR_PROTECT DISABLED // To manage a global write protection
#endif //! _CONF_ACCESS_H_
/** @} */

View file

@ -0,0 +1,973 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file ctrl_access.c *********************************************************************
*
* \brief
* This file contains the interface :
* - between USB <-> MEMORY
* OR
* - between USB <- Access Memory Ctrl -> Memory
*
* This interface may be controled by a "Access Memory Control" for :
* - include a management of write protect global or specific
* - include a management of access password
*
* \addtogroup usbstick
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com
******************************************************************************/
/*
Copyright (c) 2004 ATMEL Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
//_____ I N C L U D E S ____________________________________________________
#include "config.h"
#include "storage/ctrl_access.h"
//_____ D E F I N I T I O N S ______________________________________________
#if (ACCESS_MEM_TO_MEM == ENABLED)
#include "modules/file_system/fat.h"
U8 buf_sector[FS_SIZE_OF_SECTOR];
#endif
//! Computed the maximum of static lun (don't add the lun of Mass Storage in mode USB Host)
// FYC: Memory = Logical Unit
// CHECK FOR LUN DEFINE
#ifndef LUN_0
# error LUN_0 must be defined with ENABLE or DISABLE in conf_access.h
#endif
#ifndef LUN_1
# error LUN_1 must be defined with ENABLE or DISABLE in conf_access.h
#endif
#ifndef LUN_2
# error LUN_2 must be defined with ENABLE or DISABLE in conf_access.h
#endif
#ifndef LUN_3
# error LUN_3 must be defined with ENABLE or DISABLE in conf_access.h
#endif
#ifndef LUN_4
# error LUN_4 must be defined with ENABLE or DISABLE in conf_access.h
#endif
#ifndef LUN_5
# error LUN_5 must be defined with ENABLE or DISABLE in conf_access.h
#endif
#ifndef LUN_6
# error LUN_6 must be defined with ENABLE or DISABLE in conf_access.h
#endif
#ifndef LUN_7
# error LUN_7 must be defined with ENABLE or DISABLE in conf_access.h
#endif
#ifndef LUN_USB
# error LUN_USB must be defined with ENABLE or DISABLE in conf_access.h
#endif
#if (LUN_0 == ENABLE)
#define LUN_0_EN 1
U8 FLASH lun0_name[]=LUN_0_NAME;
#else
#define LUN_0_EN 0
#endif
#if (LUN_1 == ENABLE)
#define LUN_1_EN 1
U8 FLASH lun1_name[]=LUN_1_NAME;
#else
#define LUN_1_EN 0
#endif
#if (LUN_2 == ENABLE)
#define LUN_2_EN 1
U8 FLASH lun2_name[]=LUN_2_NAME;
#else
#define LUN_2_EN 0
#endif
#if (LUN_3 == ENABLE)
#define LUN_3_EN 1
U8 FLASH lun3_name[]=LUN_3_NAME;
#else
#define LUN_3_EN 0
#endif
#if (LUN_4 == ENABLE)
#define LUN_4_EN 1
U8 FLASH lun4_name[]=LUN_4_NAME;
#else
#define LUN_4_EN 0
#endif
#if (LUN_5 == ENABLE)
#define LUN_5_EN 1
U8 FLASH lun5_name[]=LUN_5_NAME;
#else
#define LUN_5_EN 0
#endif
#if (LUN_6 == ENABLE)
#define LUN_6_EN 1
U8 FLASH lun6_name[]=LUN_6_NAME;
#else
#define LUN_6_EN 0
#endif
#if (LUN_7 == ENABLE)
#define LUN_7_EN 1
U8 FLASH lun7_name[]=LUN_7_NAME;
#else
#define LUN_7_EN 0
#endif
#if (LUN_USB == ENABLE)
#define LUN_USB_EN 1
U8 FLASH lunusb_name[]=LUN_USB_NAME;
#else
#define LUN_USB_EN 0
#endif
#define LUN_ID_0 (0)
#define LUN_ID_1 (LUN_0_EN)
#define LUN_ID_2 (LUN_0_EN+LUN_1_EN)
#define LUN_ID_3 (LUN_0_EN+LUN_1_EN+LUN_2_EN)
#define LUN_ID_4 (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN)
#define LUN_ID_5 (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN+LUN_4_EN)
#define LUN_ID_6 (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN+LUN_4_EN+LUN_5_EN)
#define LUN_ID_7 (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN+LUN_4_EN+LUN_5_EN+LUN_6_EN)
#define MAX_LUN (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN+LUN_4_EN+LUN_5_EN+LUN_6_EN+LUN_7_EN)
#define LUN_ID_USB (MAX_LUN)
// Check configuration
#if (MAX_LUN == 0)
#error No memory is active in conf_access.h
#endif
// Write protect variable
#if (GLOBAL_WR_PROTECT == ENABLED)
static U8 g_u8_wr_protect;
#endif
//_____ D E F I N I T I O N S __ F O N C T I O N S _________________________
//! This fonction return the number of logical unit
//!
//! @return U8 number of logical unit in the system
//!
U8 get_nb_lun()
{
#if (MEM_USB == ENABLED)
return (MAX_LUN + Host_getlun());
#else
return MAX_LUN;
#endif
}
//! This fonction return the current logical unit
//!
//! @return U8 number of logical unit in the system
//!
U8 get_cur_lun()
{
return 0; //TODO
}
//! This fonction test the state of memory, and start the initialisation of the memory
//!
//! MORE (see SPC-3 §5.2.4) : The TEST UNIT READY command allows an application client
//! to poll a logical unit until it is ready without the need to allocate space for returned data.
//! The TEST UNIT READY command may be used to check the media status of logical units with removable media.
//!
//! @param lun Logical unit number
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//! Memory unplug -> CTRL_NO_PRESENT
//! Not initialize -> CTRL_BUSY
//!
Ctrl_status mem_test_unit_ready( U8 lun )
{
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
return Lun_0_test_unit_ready();
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
return Lun_1_test_unit_ready();
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
return Lun_2_test_unit_ready();
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
return Lun_3_test_unit_ready();
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
return Lun_4_test_unit_ready();
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
return Lun_5_test_unit_ready();
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
return Lun_6_test_unit_ready();
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
return Lun_7_test_unit_ready();
break;
# endif
# if (LUN_USB == ENABLE)
default:
return Lun_usb_test_unit_ready(lun - LUN_ID_USB);
break;
# endif
}
return CTRL_FAIL;
}
//! This fonction return the capacity of the memory
//!
//! @param lun Logical unit number
//! @param u32_nb_sector The sector to query
//!
//! @return *u16_nb_sector number of sector (sector = 512B)
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//! Memory unplug -> CTRL_NO_PRESENT
//!
Ctrl_status mem_read_capacity( U8 lun , U32 _MEM_TYPE_SLOW_ *u32_nb_sector )
{
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
return Lun_0_read_capacity( u32_nb_sector );
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
return Lun_1_read_capacity( u32_nb_sector );
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
return Lun_2_read_capacity( u32_nb_sector );
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
return Lun_3_read_capacity( u32_nb_sector );
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
return Lun_4_read_capacity( u32_nb_sector );
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
return Lun_5_read_capacity( u32_nb_sector );
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
return Lun_6_read_capacity( u32_nb_sector );
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
return Lun_7_read_capacity( u32_nb_sector );
break;
# endif
# if (LUN_USB == ENABLE)
default:
return Lun_usb_read_capacity( lun - LUN_ID_USB,u32_nb_sector );
break;
# endif
}
return CTRL_FAIL;
}
//! This fonction return is the write protected mode
//!
//! @param lun Logical unit number
//!
//! Only used by memory removal with a HARDWARE SPECIFIC write protected detection
//! !!! The customer must be unplug the card for change this write protected mode.
//!
//! @return TRUE -> the memory is protected
//!
Bool mem_wr_protect( U8 lun )
{
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
return Lun_0_wr_protect();
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
return Lun_1_wr_protect();
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
return Lun_2_wr_protect();
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
return Lun_3_wr_protect();
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
return Lun_4_wr_protect();
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
return Lun_5_wr_protect();
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
return Lun_6_wr_protect();
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
return Lun_7_wr_protect();
break;
# endif
# if (LUN_USB == ENABLE)
default:
return Lun_usb_wr_protect(lun - LUN_ID_USB);
break;
# endif
}
return CTRL_FAIL;
}
//! This fonction inform about the memory type
//!
//! @param lun Logical unit number
//!
//! @return TRUE -> The memory is removal
//!
Bool mem_removal( U8 lun )
{
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
return Lun_0_removal();
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
return Lun_1_removal();
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
return Lun_2_removal();
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
return Lun_3_removal();
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
return Lun_4_removal();
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
return Lun_5_removal();
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
return Lun_6_removal();
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
return Lun_7_removal();
break;
# endif
# if (LUN_USB == ENABLE)
default:
return Lun_usb_removal();
break;
# endif
}
return CTRL_FAIL;
}
//! This fonction returns a pointer to the LUN name
//!
//! @param lun Logical unit number
//!
//! @return pointer to code string
//!
U8 FLASH* mem_name( U8 lun )
{
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
return (U8 FLASH*)lun0_name;
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
return (U8 FLASH*)lun1_name;
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
return (U8 FLASH*)lun2_name;
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
return (U8 FLASH*)lun3_name;
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
return (U8 FLASH*)lun4_name;
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
return (U8 FLASH*)lun5_name;
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
return (U8 FLASH*)lun6_name;
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
return (U8 FLASH*)lun7_name;
break;
# endif
# if (LUN_USB == ENABLE)
default:
return (U8 FLASH*)lunusb_name;
break;
# endif
}
return 0; // Remove compiler warning
}
//************************************************************************************
//!----------- Listing of READ/WRITE interface with MODE ACCESS REGISTER -------------
//************************************************************************************
//! This fonction tranfer a data from memory to usb
//!
//! @param lun Logical unit number
//! @param addr Sector address to start read (sector = 512B)
//! @param nb_sector Number of sectors to transfer
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//! A error occur -> CTRL_FAIL
//! Memory unplug -> CTRL_NO_PRESENT
//!
Ctrl_status memory_2_usb( U8 lun , U32 addr , U16 nb_sector )
{
Ctrl_status status;
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
status = Lun_0_read_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_0_usb_read();
}
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
status = Lun_1_read_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_1_usb_read();
}
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
status = Lun_2_read_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_2_usb_read();
}
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
status = Lun_3_read_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_3_usb_read();
}
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
status = Lun_4_read_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_4_usb_read();
}
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
status = Lun_5_read_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_5_usb_read();
}
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
status = Lun_6_read_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_6_usb_read();
}
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
status = Lun_7_read_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_7_usb_read();
}
break;
# endif
}
return status;
}
//! This fonction trabsfer a data from usb to memory
//!
//! @param lun Logical unit number
//! @param addr Sector address to start write (sector = 512B)
//! @param nb_sector Number of sectors to transfer
//!
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//! A error occur -> CTRL_FAIL
//! Memory unplug -> CTRL_NO_PRESENT
//!
Ctrl_status usb_2_memory( U8 lun , U32 addr , U16 nb_sector )
{
Ctrl_status status;
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
status = Lun_0_write_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_0_usb_write();
}
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
status = Lun_1_write_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_1_usb_write();
}
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
status = Lun_2_write_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_2_usb_write();
}
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
status = Lun_3_write_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_3_usb_write();
}
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
status = Lun_4_write_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_4_usb_write();
}
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
status = Lun_5_write_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_5_usb_write();
}
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
status = Lun_6_write_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_6_usb_write();
}
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
status = Lun_7_write_10(addr , nb_sector);
if (CTRL_GOOD == status)
{
status = Lun_7_usb_write();
}
break;
# endif
}
return status;
}
//! Interface for RAM
#if (ACCESS_MEM_TO_RAM == ENABLED)
//! This fonction tranfer one sector data from memory to ram
//!
//! @param lun Logical unit number
//! @param addr Sector address to start read (sector = 512B)
//! @param ram Adresse of ram buffer (only xdata)
//!
//! @return TRUE -> The memory is removal
//!
Ctrl_status memory_2_ram( U8 lun , const U32 _MEM_TYPE_SLOW_ *addr , U8 _MEM_TYPE_SLOW_ *ram )
{
Ctrl_status status;
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
status = Lun_0_mem_2_ram(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_0_mem_2_ram_read();
}
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
status = Lun_1_mem_2_ram(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_1_mem_2_ram_read();
}
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
status = Lun_2_mem_2_ram(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_2_mem_2_ram_read();
}
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
status = Lun_3_mem_2_ram(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_3_mem_2_ram_read();
}
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
status = Lun_4_mem_2_ram(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_4_mem_2_ram_read();
}
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
status = Lun_5_mem_2_ram(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_5_mem_2_ram_read();
}
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
status = Lun_6_mem_2_ram(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_6_mem_2_ram_read();
}
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
status = Lun_7_mem_2_ram(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_7_mem_2_ram_read();
}
break;
# endif
# if (LUN_USB == ENABLE)
default:
return Lun_usb_mem_2_ram(*addr , ram);
# endif
}
return status;
}
#endif // ACCESS_MEM_TO_RAM == ENABLED
#if (ACCESS_MEM_TO_RAM==ENABLE)
//! This fonction trabsfer a data from ram to memory
//!
//! @param lun Logical unit number
//! @param addr Sector address to start write (sector = 512B)
//! @param ram Adresse of ram buffer (only xdata)
//!
//! @return TRUE -> The memory is removal
//!
Ctrl_status ram_2_memory( U8 lun , const U32 _MEM_TYPE_SLOW_ *addr , U8 _MEM_TYPE_SLOW_ * ram )
{
Ctrl_status status;
switch( lun )
{
# if (LUN_0 == ENABLE)
case LUN_ID_0:
status = Lun_0_ram_2_mem(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_0_ram_2_mem_write();
}
break;
# endif
# if (LUN_1 == ENABLE)
case LUN_ID_1:
status = Lun_1_ram_2_mem(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_1_ram_2_mem_write();
}
break;
# endif
# if (LUN_2 == ENABLE)
case LUN_ID_2:
status = Lun_2_ram_2_mem(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_2_ram_2_mem_write();
}
break;
# endif
# if (LUN_3 == ENABLE)
case LUN_ID_3:
status = Lun_3_ram_2_mem(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_3_ram_2_mem_write();
}
break;
# endif
# if (LUN_4 == ENABLE)
case LUN_ID_4:
status = Lun_4_ram_2_mem(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_4_ram_2_mem_write();
}
break;
# endif
# if (LUN_5 == ENABLE)
case LUN_ID_5:
status = Lun_5_ram_2_mem(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_5_ram_2_mem_write();
}
break;
# endif
# if (LUN_6 == ENABLE)
case LUN_ID_6:
status = Lun_6_ram_2_mem(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_6_ram_2_mem_write();
}
break;
# endif
# if (LUN_7 == ENABLE)
case LUN_ID_7:
status = Lun_7_ram_2_mem(*addr , ram);
if (CTRL_GOOD == status)
{
status = Lun_7_ram_2_mem_write();
}
break;
# endif
# if (LUN_USB == ENABLE)
default:
return Lun_usb_ram_2_mem(*addr , ram);
break;
# endif
}
return status;
}
#endif // ACCESS_RAM_TO_MEM == ENABLED
//! Interface for streaming interface
#if (ACCESS_STREAM == ENABLED)
// Interface for transfer MEM to MEM
# if (ACCESS_MEM_TO_MEM == ENABLED)
//! This fonction copy a data from memory to other memory
//!
//! @param src_lun The LUN of the source
//! @param src_addr The address of the source
//! @param dest_lun The LUN of the destination
//! @param dest_addr The address of the destination
//! @param nb_sector Number of sectors to transfer
//!
U8 stream_mem_to_mem( U8 src_lun , U32 src_addr , U8 dest_lun , U32 dest_addr , U16 nb_sector )
{
while(nb_sector)
{
memory_2_ram( src_lun , &src_addr , buf_sector );
ram_2_memory( dest_lun , &dest_addr , buf_sector );
src_addr++;
dest_addr++;
nb_sector--;
}
return CTRL_GOOD;
}
# endif // ACCESS_MEM_TO_MEM == ENABLED
//! Returns the state on a data transfer
//!
//! @param Id transfer id
//!
//! @return the state of the transfer
//! CTRL_GOOD It is finish
//! CTRL_BUSY It is running
//! CTRL_FAIL It is fail
//!
Ctrl_status stream_state( U8 Id )
{
return CTRL_GOOD;
}
//! Stop the data transfer
//!
//! @param Id Transfer id
//!
//! @return the number of sector remainder
//!
U16 stream_stop( U8 Id )
{
return 0;
}
#endif // ACCESS_STREAM == ENABLED
/** @} */

View file

@ -0,0 +1,157 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file ctrl_access.h *******************************************************
*
* \brief
* This file contains the interface :
* - between USB <-> MEMORY
* OR
* - between USB <- Access Memory Ctrl -> Memory
*
* This interface may be controled by a "Access Memory Control" for :
* - include a management of write protect global or specific
* - include a management of access password
*
* \addtogroup usbstick
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com
******************************************************************************/
/*
Copyright (c) 2004 ATMEL Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
#ifndef _MEM_CTRL_H_
#define _MEM_CTRL_H_
#include "storage/conf_access.h"
#include "storage/ctrl_status.h"
// FYC: Memory = Logical Unit
#if (LUN_0 == ENABLE)
#include LUN_0_INCLUDE
#endif
#if (LUN_1 == ENABLE)
#include LUN_1_INCLUDE
#endif
#if (LUN_2 == ENABLE)
#include LUN_2_INCLUDE
#endif
#if (LUN_3 == ENABLE)
#include LUN_3_INCLUDE
#endif
#if (LUN_4 == ENABLE)
#include LUN_4_INCLUDE
#endif
#if (LUN_5 == ENABLE)
#include LUN_5_INCLUDE
#endif
#if (LUN_6 == ENABLE)
#include LUN_6_INCLUDE
#endif
#if (LUN_7 == ENABLE)
#include LUN_7_INCLUDE
#endif
#if (LUN_USB == ENABLE)
#include LUN_USB_INCLUDE
#endif
//------- Test the configuration in conf_access.h
// Specific option control access
#ifndef GLOBAL_WR_PROTECT
# error GLOBAL_WR_PROTECT must be defined with ENABLED or DISABLED in conf_access.h
#endif
//------- END OF Test the configuration in conf_access.h
//_____ D E F I N I T I O N S ______________________________________________
//!**** Listing of commun interface ****************************************
U8 get_nb_lun();
U8 get_cur_lun();
Ctrl_status mem_test_unit_ready( U8 lun );
Ctrl_status mem_read_capacity( U8 lun , U32 _MEM_TYPE_SLOW_ *u32_nb_sector );
Bool mem_wr_protect( U8 lun );
Bool mem_removal( U8 lun );
U8 FLASH* mem_name( U8 lun );
//!**** Listing of READ/WRITE interface ************************************
//---- Interface for USB ---------------------------------------------------
Ctrl_status memory_2_usb( U8 lun , U32 addr , U16 nb_sector );
Ctrl_status usb_2_memory( U8 lun , U32 addr , U16 nb_sector );
#include "usb_drv.h"
#include "conf_usb.h"
//--------------------------------------------------------------------------
//---- Interface for RAM to MEM --------------------------------------------
Ctrl_status memory_2_ram( U8 lun , const U32 _MEM_TYPE_SLOW_ *addr , U8 _MEM_TYPE_SLOW_ *ram );
Ctrl_status ram_2_memory( U8 lun , const U32 _MEM_TYPE_SLOW_ *addr , U8 _MEM_TYPE_SLOW_ * ram );
//--------------------------------------------------------------------------
//!---- Interface for streaming interface ----------------------------------
#if (ACCESS_STREAM == ENABLED)
#define ID_STREAM_ERR 0xFF
// RLE #include "dfc_mngt.h"
#define TYPE_STREAM_AUDIO DFC_ID_AUDIOPROC1
#define TYPE_STREAM_AUDIO2 DFC_ID_AUDIOPROC2
#define TYPE_STREAM_SIO DFC_ID_SIO
#define TYPE_STREAM_SPI DFC_ID_SPI
#define TYPE_STREAM_DEVNULL DFC_ID_NULL_DEV
U8 stream_mem_to_mem ( U8 src_lun , U32 src_addr , U8 dest_lun , U32 dest_addr , U16 nb_sector );
U8 stream_read_10_start ( U8 TypeStream , U8 lun , U32 addr , U16 nb_sector );
U8 stream_write_10_start ( U8 TypeStream , U8 lun , U32 addr , U16 nb_sector );
U8 stream_to_stream_start ( U8 TypeStream_src , U8 TypeStream_dest , U16 nb_sector );
Ctrl_status stream_state( U8 Id );
U16 stream_stop( U8 Id );
#endif // (ACCESS_STREAM == ENABLED)
//--------------------------------------------------------------------------
#endif // _MEM_CTRL_H_
/**@}*/

View file

@ -0,0 +1,70 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file ctrl_status.h ********************************************************
*
* \brief
* This file contains the interface :
* - between USB <-> MEMORY
* OR
* - between USB <- Access Memory Ctrl -> Memory
*
* This interface may be controled by a "Access Memory Control" for :
* - include a management of write protect global or specific
* - include a management of access password
*
* \addtogroup usbstick
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com
******************************************************************************/
/*
Copyright (c) 2004 ATMEL Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
#ifndef _CTRL_STATUS_H_
#define _CTRL_STATUS_H_
//_____ D E F I N I T I O N S ______________________________________________
//! Define control status
typedef enum
{
CTRL_GOOD =(PASS ) // It is ready
, CTRL_FAIL =(FAIL ) // Memory fail
, CTRL_NO_PRESENT =(FAIL+1) // Memory unplug
, CTRL_BUSY =(FAIL+2) // Not initialize
} Ctrl_status;
#endif // _CTRL_STATUS_H_
/** @} */

View file

@ -0,0 +1,787 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file scsi_decoder.c *******************************************************
*
* \brief
* This file is the scsi decoder
*
* \addtogroup usbstick
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com
******************************************************************************/
/*
Copyright (c) 2004 ATMEL Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
//_____ I N C L U D E S ___________________________________________________
#include "config.h"
#include "storage/scsi_decoder.h"
#include "conf_usb.h"
#include "usb_drv.h"
#include "storage/ctrl_status.h"
#include "storage/ctrl_access.h"
//_____ M A C R O S ________________________________________________________
//_____ D E F I N I T I O N S ______________________________________________
U8 g_scsi_command[16];
U8 g_scsi_status;
U32 g_scsi_data_remaining;
FLASH U8 g_sbc_vendor_id[8] = SBC_VENDOR_ID;
FLASH U8 g_sbc_product_id[16] = SBC_PRODUCT_ID;
FLASH U8 g_sbc_revision_id[4] = SBC_REVISION_ID;
extern U8 usb_LUN;
s_scsi_sense g_scsi_sense;
FLASH struct sbc_st_std_inquiry_data sbc_std_inquiry_data =
{
/* Byte 0 : 0x00 */
0x00, /* DeviceType: Direct-access device */
0, /* PeripheralQualifier : Currently connected */
/* Byte 1 : 0x80 */
0, /* Reserved1 */
1, /* RMB : Medium is removable (this bit must be at 1, else the medium isn't see on Windows) */
// /* Byte 2 : 0x02 */
// 0x02, /* Version: Device compliant to ANSI X3.131:1994 */
/* Byte 2 : 0x00 */
0x00, /* Version: Device not compliant to any standard */
/* Byte 3 : 0x02 */
2, /* Response data format */
0, /* NormACA */
0, /* Obsolete0 */
0, /* AERC */
/* Byte 4 : 0x1F */
/* Byte 5 : 0x00 */
/* Byte 6 : 0x00 */
/* Reserved4[3] */
{
0x1F, /* Additional Length (n-4) */
0, /* SCCS : SCC supported */
0
},
/* Byte 7 : 0x00 */
0, /* SoftReset */
0, /* CommandQueue */
0, /* Reserved5 */
0, /* LinkedCommands */
0, /* Synchronous */
0, /* Wide16Bit */
0, /* Wide32Bit */
0, /* RelativeAddressing */
};
static void send_informational_exceptions_page (void);
static void send_read_write_error_recovery_page (U8);
static void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length );
//_____ D E C L A R A T I O N S ____________________________________________
/**
* @brief SCSI decoder function
*
* This function read the SCSI command and launches the appropriate function
*
* @warning Code:.. bytes (function FLASH length)
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
Bool scsi_decode_command(void)
{
Bool status;
if (g_scsi_command[0] == SBC_CMD_WRITE_10)
{
Scsi_start_write_action();
status = sbc_write_10();
Scsi_stop_write_action();
return status;
}
if (g_scsi_command[0] == SBC_CMD_READ_10 )
{
Scsi_start_read_action();
status = sbc_read_10();
Scsi_stop_read_action();
return status;
}
switch (g_scsi_command[0]) /* check other command received */
{
case SBC_CMD_REQUEST_SENSE: /* 0x03 - Mandatory */
return sbc_request_sense();
break;
case SBC_CMD_INQUIRY: /* 0x12 - Mandatory */
return sbc_inquiry();
break;
case SBC_CMD_TEST_UNIT_READY: /* 0x00 - Mandatory */
return sbc_test_unit_ready();
break;
case SBC_CMD_READ_CAPACITY: /* 0x25 - Mandatory */
return sbc_read_capacity();
break;
case SBC_CMD_MODE_SENSE_6: /* 0x1A - Optional */
return sbc_mode_sense( FALSE );
break;
case SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:/* 0x1E */
return sbc_prevent_allow_medium_removal();
break;
case SBC_CMD_VERIFY_10: /* 0x2F - Optional */
sbc_lun_status_is_good();
break;
case SBC_CMD_MODE_SENSE_10: /* 0x5A - Optional */
return sbc_mode_sense( TRUE );
break;
case SBC_CMD_FORMAT_UNIT: /* 0x04 - Mandatory */
case SBC_CMD_MODE_SELECT_6: /* 0x15 - Optional */
case SBC_CMD_START_STOP_UNIT: /* 0x1B - Optional */
case SBC_CMD_SEND_DIAGNOSTIC: /* 0x1D - */
case SBC_CMD_READ_LONG: /* 0x23 - Optional */
case SBC_CMD_SYNCHRONIZE_CACHE: /* 0x35 - Optional */
case SBC_CMD_WRITE_BUFFER: /* 0x3B - Optional */
case SBC_CMD_RESERVE_10: /* 0x56 - Mandatory */
case SBC_CMD_RELEASE_10: /* 0x57 - Mandatory - see chapter 7.16 - SPC 2 */
default:
{ /* Command not supported */
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, 0x00);
return FALSE;
break;
}
}
return TRUE;
}
/**
* @brief This function manages the SCSI REQUEST SENSE command (0x03)
*
* The SCSI Sense contains the status of the last command
* This status is composed of 3 Bytes :
* - sense key (g_scsi_sense.key)
* - additional sense code (g_scsi_sense.asc)
* - additional sense code qualifier (g_scsi_sense.ascq)
*
* @warning Code:.. bytes (function code length)
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
Bool sbc_request_sense (void)
{
U8 allocation_length, i;
U8 request_sens_output[18]; /* the maximum size of request is 17 */
allocation_length = g_scsi_command[4]; /* Allocation length */
/* Initialize the request sense data */
request_sens_output[0] = SBC_RESPONSE_CODE_SENSE; /* 70h */
request_sens_output[1] = 0x00; /* Obsolete */
request_sens_output[2] = g_scsi_sense.key;
request_sens_output[3] = 0x00; /* For direct access media, Information field */
request_sens_output[4] = 0x00; /* give the unsigned logical block */
request_sens_output[5] = 0x00; /* address associated with the sense key */
request_sens_output[6] = 0x00;
request_sens_output[7] = SBC_ADDITIONAL_SENSE_LENGTH; /* !! UFI device shall not adjust the Additional sense length to reflect truncation */
request_sens_output[8] = SBC_COMMAND_SPECIFIC_INFORMATION_3;
request_sens_output[9] = SBC_COMMAND_SPECIFIC_INFORMATION_2;
request_sens_output[10] = SBC_COMMAND_SPECIFIC_INFORMATION_1;
request_sens_output[11] = SBC_COMMAND_SPECIFIC_INFORMATION_0;
request_sens_output[12] = g_scsi_sense.asc;
request_sens_output[13] = g_scsi_sense.ascq;
request_sens_output[14] = SBC_FIELD_REPLACEABLE_UNIT_CODE;
request_sens_output[15] = SBC_SENSE_KEY_SPECIFIC_2;
request_sens_output[16] = SBC_SENSE_KEY_SPECIFIC_1;
request_sens_output[17] = SBC_SENSE_KEY_SPECIFIC_0;
/* Send the request data */
for( i=0 ; i<allocation_length ; i++ )
{
Usb_write_byte( request_sens_output[i] );
}
Sbc_valid_write_usb( allocation_length );
sbc_lun_status_is_good();
return TRUE;
}
/**
* @brief This function manages the SCSI INQUIRY command (0x12)
*
* The SCSI Inquiry field contains information regarding parameters
* of the target. For example:
* - vendor identification
* - product identification
* - peripheral qualifier
* - peripheral device type
* - etc
*
* @warning Code:.. bytes (function code length)
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
Bool sbc_inquiry (void)
{
U8 allocation_length, i;
#ifdef AVRGCC
PGM_VOID_P ptr;
#else
U8 FLASH *ptr;
#endif
if( (0 == (g_scsi_command[1] & 0x03) ) // CMDT and EPVD bits are 0
&& (0 == g_scsi_command[2] ) ) // PAGE or OPERATION CODE fields = 0x00?
{
//** send standard inquiry data
// Check the size of inquiry data
allocation_length = g_scsi_command[4];
if (allocation_length > SBC_MAX_INQUIRY_DATA)
{
allocation_length = SBC_MAX_INQUIRY_DATA;
}
// send first inquiry data (0 to 8)
ptr = (FLASH U8*) &sbc_std_inquiry_data;
for ( i=0 ; ((i != 36) && (allocation_length > i)); i++)
{
if( 8 == i )
{ // send vendor id (8 to 16)
ptr = (FLASH U8 *) &g_sbc_vendor_id;
}
if( 16 == i )
{ // send product id (16 to 32)
ptr = (FLASH U8 *) &g_sbc_product_id;
}
if( 32 == i )
{ // send revision id (32 to 36)
ptr = (FLASH U8 *) &g_sbc_revision_id;
}
#ifndef AVRGCC
Usb_write_byte((U8)(*ptr++)); // send tab
#else // AVRGCC does not support point to PGM space
#warning with avrgcc assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
Usb_write_byte(pgm_read_byte_near((unsigned int)ptr++));
#endif
}
// send data (36 to SBC_MAX_INQUIRY_DATA), and can be tranmitted by Bulk
// Description of next bytes (this bytes is always egal to 0) :
// VendorSpecific : 20 Bytes
// Next byte : 1 byte
// - InfoUnitSupport : 1 bit
// - QuickArbitSupport : 1 bit
// - Clocking : 2 bits
// - Reserved6 : 4 bits
// Reserved7 : 1 byte
// VersionDescriptor : 8 bytes
// Reserved8 : 22 bytes
// ...
while( allocation_length > i )
{
if (64 == i)
{ // for each 64 bytes, send USB packet
Sbc_valid_write_usb(64);
allocation_length -= 64;
i = 0;
}
Usb_write_byte(0); // write value of last bytes of inquiry data
i++;
}
// send last USB packet
Sbc_valid_write_usb(allocation_length);
sbc_lun_status_is_good();
return TRUE;
}
else
{ // (CMDT=EVPD <> 0) or (PAGE CODE <> 0x00)
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
return FALSE;
}
}
Bool sbc_test_unit_ready(void)
{
switch ( mem_test_unit_ready(usb_LUN) )
{
case CTRL_GOOD :
sbc_lun_status_is_good();
break;
case CTRL_NO_PRESENT :
sbc_lun_status_is_not_present();
break;
case CTRL_BUSY :
sbc_lun_status_is_busy_or_change();
break;
case CTRL_FAIL :
default :
sbc_lun_status_is_fail();
break;
}
return TRUE;
}
Bool sbc_read_capacity (void)
{
_MEM_TYPE_SLOW_ U32 mem_size_nb_sector;
switch ( mem_read_capacity( usb_LUN, &mem_size_nb_sector ) )
{
case CTRL_GOOD :
Usb_write_byte(MSB0(mem_size_nb_sector)); // return nb block
Usb_write_byte(MSB1(mem_size_nb_sector));
Usb_write_byte(MSB2(mem_size_nb_sector));
Usb_write_byte(MSB3(mem_size_nb_sector));
Usb_write_byte( 0 ); // return block size (= 512B)
Usb_write_byte( 0 );
Usb_write_byte( (U8)(512 >> 8) );
Usb_write_byte( (U8)(512 & 0xFF));
Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH);
sbc_lun_status_is_good();
return TRUE;
break;
case CTRL_NO_PRESENT :
sbc_lun_status_is_not_present();
break;
case CTRL_BUSY :
sbc_lun_status_is_busy_or_change();
break;
case CTRL_FAIL :
default :
sbc_lun_status_is_fail();
break;
}
return FALSE;
}
Bool sbc_read_10 (void)
{
U32 mass_addr; // rd or wr block address
U16 mass_size; // rd or write nb of blocks
MSB0(mass_addr) = g_scsi_command[2]; // read address
MSB1(mass_addr) = g_scsi_command[3];
MSB2(mass_addr) = g_scsi_command[4];
MSB3(mass_addr) = g_scsi_command[5];
MSB(mass_size) = g_scsi_command[7]; // read size
LSB(mass_size) = g_scsi_command[8];
if (mass_size != 0)
{
switch ( memory_2_usb( usb_LUN , mass_addr, mass_size ) )
{
case CTRL_GOOD :
sbc_lun_status_is_good();
g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size);
return TRUE;
break;
case CTRL_NO_PRESENT :
sbc_lun_status_is_not_present();
return FALSE;
break;
case CTRL_BUSY :
sbc_lun_status_is_busy_or_change();
return FALSE;
break;
case CTRL_FAIL :
default :
sbc_lun_status_is_fail();
return FALSE;
break;
}
}
else
{ // No data to transfer
sbc_lun_status_is_good();
}
return TRUE;
}
Bool sbc_write_10 (void)
{
U32 mass_addr; // rd or wr block address
U16 mass_size; // rd or write nb of blocks
MSB0(mass_addr) = g_scsi_command[2]; // read address
MSB1(mass_addr) = g_scsi_command[3];
MSB2(mass_addr) = g_scsi_command[4];
MSB3(mass_addr) = g_scsi_command[5];
MSB(mass_size) = g_scsi_command[7]; // read size
LSB(mass_size) = g_scsi_command[8];
if (mass_size != 0)
{
if( TRUE == mem_wr_protect( usb_LUN ) )
{
sbc_lun_status_is_protected();
return FALSE;
#warning For Win98 data must be read to avoid blocking
}
else
{
switch (usb_2_memory( usb_LUN , mass_addr, mass_size ))
{
case CTRL_GOOD :
sbc_lun_status_is_good();
g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size);
return TRUE;
break;
case CTRL_NO_PRESENT :
sbc_lun_status_is_not_present();
return FALSE;
break;
case CTRL_BUSY :
sbc_lun_status_is_busy_or_change();
return FALSE;
break;
case CTRL_FAIL :
default :
sbc_lun_status_is_fail();
return FALSE;
break;
}
}
}
else
{ // No data to transfer
sbc_lun_status_is_good();
}
return TRUE;
}
/**
* @brief This function manages the SCSI MODE SENSE command (0x1A for sense 6 and 0x5A for sense 10)
*
* The SCSI mode sense function returns parameters to an application client.
* It is a complementary command to the SCSI MODE SELECT command.
*
* @warning Code:.. bytes (function code length)
*
* @param b_sense_10 ( TRUE = sense 10, TRUE = sense 6)
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
Bool sbc_mode_sense( Bool b_sense_10 )
{
U8 allocation_length;
if( b_sense_10 )
allocation_length = g_scsi_command[8];
else
allocation_length = g_scsi_command[4];
// switch for page code
switch ( g_scsi_command[2] & SBC_MSK_PAGE_CODE )
{
case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS: /* Page Code: Informational exceptions control page */
sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS );
send_informational_exceptions_page();
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
break;
case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY );
send_read_write_error_recovery_page(allocation_length);
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
break;
case SBC_PAGE_CODE_ALL:
sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_CODE_ALL );
if( b_sense_10 )
{
if (allocation_length == 8)
{
Sbc_valid_write_usb(8);
break;
}
}
else
{
if (allocation_length == 4)
{
Sbc_valid_write_usb(4);
break;
}
}
// send page by ascending order code
send_read_write_error_recovery_page(allocation_length); // 12 bytes
if (allocation_length > 12)
{
send_informational_exceptions_page(); // 12 bytes
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
}
else
{
Sbc_valid_write_usb(allocation_length);
}
break;
default:
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
return FALSE;
break;
}
sbc_lun_status_is_good();
return TRUE;
}
/**
* @brief This function send the header of the SCSI MODE SENSE command
*
* @param b_sense_10 TRUE = sense 10, FALSE = sense 6
* @param u8_data_length data length in byte
*
*/
void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length )
{
// Send Data length
if( b_sense_10 )
{
Usb_write_byte(0);
}
Usb_write_byte( u8_data_length );
// Send device type
Usb_write_byte(SBC_MEDIUM_TYPE);
// Write protect status
if (mem_wr_protect( usb_LUN ))
{
Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_PROTECT); // Device is write protected
}
else
{
Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_ENABLE); // Device is write enabled
}
if( b_sense_10 )
{ // Reserved
Usb_write_byte(0);
Usb_write_byte(0);
}
// Send Block descriptor length
if( b_sense_10 )
{
Usb_write_byte(0);
}
Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);
}
/**
* @brief This function writes informational exceptions page parameters
*
* @warning Code:.. bytes (function code length)
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
void send_informational_exceptions_page (void)
{
Usb_write_byte(SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS); /* Page Code: Informational exceptions control page */
/* See chapter 8.3.8 on SPC-2 specification */
Usb_write_byte(SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS); /* Page Length */
Usb_write_byte(0x00); /* ..., Test bit = 0, ... */
Usb_write_byte(SBC_MRIE); /* MRIE = 0x05 */
Usb_write_byte(0x00); /* Interval Timer (MSB) */
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00); /* Interval Timer (LSB) */
Usb_write_byte(0x00); /* Report Count (MSB) */
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x01); /* Report Count (LSB) */
}
/**
* @brief This function writes error recovery page
*
* @warning Code:.. bytes (function code length)
*
* @param length The length of
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
void send_read_write_error_recovery_page (U8 length)
{
Usb_write_byte(SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY);
Usb_write_byte(SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY); /* Page Length */
Usb_write_byte(0x80);
Usb_write_byte(SBC_READ_RETRY_COUNT);
Usb_write_byte(SBC_CORRECTION_SPAN);
Usb_write_byte(SBC_HEAD_OFFSET_COUNT);
Usb_write_byte(SBC_DATA_STROBE_OFFSET);
Usb_write_byte(0x00); /* Reserved */
if (length > 12)
{
Usb_write_byte(SBC_WRITE_RETRY_COUNT);
Usb_write_byte(0x00);
Usb_write_byte(SBC_RECOVERY_LIMIT_MSB);
Usb_write_byte(SBC_RECOVERY_LIMIT_LSB);
}
}
/**
* @brief This function manages the SCSI PREVENT ALLOW MEDIUM REMOVAL
* command (0x1E)
*
* The SCSI prevent allow medium removal command requests that the target
* enable or disable the removal of the medium in the logical unit.
*
* @warning Code:.. bytes (function code length)
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
Bool sbc_prevent_allow_medium_removal(void)
{
sbc_lun_status_is_good();
return TRUE;
}
//! This fonction send the UFI status GOOD
//!
void sbc_lun_status_is_good(void)
{
Sbc_send_good();
Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
}
//! This fonction send the UFI status "lun not present"
//!
void sbc_lun_status_is_not_present(void)
{
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00);
}
//! This fonction send the UFI status busy and change
//!
void sbc_lun_status_is_busy_or_change(void)
{
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00 );
}
//! This fonction send the UFI status FAIL
//!
void sbc_lun_status_is_fail(void)
{
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
}
//! This fonction send the UFI status FAIL because write protection
//!
void sbc_lun_status_is_protected(void)
{
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00);
}
/** @} */

View file

@ -0,0 +1,338 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file scsi_decoder.h *******************************************************
*
* \brief
* This file is the scsi decoder
*
* \addtogroup usbstick
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com
******************************************************************************/
/*
Copyright (c) 2004 ATMEL Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
#ifndef _SCSI_DECODER_H_
#define _SCSI_DECODER_H_
//_____ I N C L U D E S ____________________________________________________
//_____ M A C R O S ________________________________________________________
typedef struct
{
U8 key;
U8 asc;
U8 ascq;
} s_scsi_sense;
//_____ D E C L A R A T I O N S ____________________________________________
Bool scsi_decode_command (void);
/****************************************************************************/
/* Command for all SCSI device types */
/****************************************************************************/
#define SBC_CMD_TEST_UNIT_READY (0x00)
#define SBC_CMD_REQUEST_SENSE (0x03)
#define SBC_CMD_FORMAT_UNIT (0x04)
#define SBC_CMD_READ_6 (0x08)
#define SBC_CMD_INQUIRY (0x12)
#define SBC_CMD_MODE_SELECT_6 (0x15)
#define SBC_CMD_MODE_SENSE_6 (0x1A)
#define SBC_CMD_START_STOP_UNIT (0x1B)
#define SBC_CMD_RECEIVE_DIAGNOSTICS (0x1C)
#define SBC_CMD_SEND_DIAGNOSTIC (0x1D)
#define SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL (0x1E)
#define SBC_CMD_READ_LONG (0x23)
#define SBC_CMD_READ_CAPACITY (0x25)
#define SBC_CMD_READ_CD_ROM_CAPACITY (0x25)
#define SBC_CMD_READ_10 (0x28)
#define SBC_CMD_WRITE_10 (0x2A)
#define SBC_CMD_VERIFY_10 (0x2F)
#define SBC_CMD_SYNCHRONIZE_CACHE (0x35)
#define SBC_CMD_WRITE_BUFFER (0x3B)
#define SBC_CMD_CHANGE_DEFINITION (0x40)
#define SBC_CMD_READ_TOC (0x43)
#define SBC_CMD_MODE_SELECT_10 (0x55)
#define SBC_CMD_RESERVE_10 (0x56)
#define SBC_CMD_RELEASE_10 (0x57)
#define SBC_CMD_MODE_SENSE_10 (0x5A)
#define SBC_CONTROL_BYTE (0x00)
#define SBC_CMD_DIR_IN (0x80)
#define SBC_CMD_DIR_OUT (0x00)
/****************************************************************************/
/* Sense Key Code */
/****************************************************************************/
#define SBC_SENSE_KEY_NO_SENSE (0x00)
#define SBC_SENSE_KEY_RECOVERED_ERROR (0x01)
#define SBC_SENSE_KEY_NOT_READY (0x02)
#define SBC_SENSE_KEY_MEDIUM_ERROR (0x03)
#define SBC_SENSE_KEY_HARDWARE_ERROR (0x04)
#define SBC_SENSE_KEY_ILLEGAL_REQUEST (0x05)
#define SBC_SENSE_KEY_UNIT_ATTENTION (0x06)
#define SBC_SENSE_KEY_DATA_PROTECT (0x07)
#define SBC_SENSE_KEY_BLANK_CHECK (0x08)
#define SBC_SENSE_KEY_VENDOR_SPECIFIC (0x09)
#define SBC_SENSE_KEY_COPY_ABORTED (0x0A)
#define SBC_SENSE_KEY_ABORTED_COMMAND (0x0B)
#define SBC_SENSE_KEY_VOLUME_OVERFLOW (0x0D)
#define SBC_SENSE_KEY_MISCOMPARE (0x0E)
/****************************************************************************/
/* ASC code assignments */
/****************************************************************************/
#define SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION (0x00)
#define SBC_ASC_LOGICAL_UNIT_NOT_READY (0x04)
#define SBC_ASC_INVALID_FIELD_IN_CDB (0x24)
#define SBC_ASC_WRITE_PROTECTED (0x27)
#define SBC_ASC_FORMAT_ERROR (0x31)
#define SBC_ASC_INVALID_COMMAND_OPERATION_CODE (0x20)
#define SBC_ASC_NOT_READY_TO_READY_CHANGE (0x28)
#define SBC_ASC_MEDIUM_NOT_PRESENT (0x3A)
/****************************************************************************/
/* ASCQ code assignments */
/****************************************************************************/
#define SBC_ASCQ_FORMAT_COMMAND_FAILED (0x01)
#define SBC_ASCQ_INITIALIZING_COMMAND_REQUIRED (0x02)
#define SBC_ASCQ_OPERATION_IN_PROGRESS (0x07)
/****************************************************************************/
/* REQUEST SENSE PARAMETERS */
/****************************************************************************/
#define SBC_RESPONSE_CODE_SENSE (0x70)
#define SBC_ADDITIONAL_SENSE_LENGTH (0x0A)
#define SBC_COMMAND_SPECIFIC_INFORMATION_3 (0x00)
#define SBC_COMMAND_SPECIFIC_INFORMATION_2 (0x00)
#define SBC_COMMAND_SPECIFIC_INFORMATION_1 (0x00)
#define SBC_COMMAND_SPECIFIC_INFORMATION_0 (0x00)
#define SBC_FIELD_REPLACEABLE_UNIT_CODE (0x00)
#define SBC_SENSE_KEY_SPECIFIC_2 (0x00)
#define SBC_SENSE_KEY_SPECIFIC_1 (0x00)
#define SBC_SENSE_KEY_SPECIFIC_0 (0x00)
/******* number of bytes of READ CAPACITY response *********/
#define SBC_READ_CAPACITY_LENGTH (0x08)
/****************************************************************************/
/*MODE SENSE and REQUEST SENSE DEFINITIONS */
/****************************************************************************/
/*************** Direct access medium type ****************/
#define SBC_DEFAULT_MEDIUM_TYPE (0x00)
#define SBC_FLEXIBLE_DISK_SINGLE_SIDED_UNSPECIFIED (0x01)
#define SBC_FLEXIBLE_DISK_DOUBLE_SIDED_UNSPECIFIED (0x02)
#define SBC_MEDIUM_TYPE SBC_DEFAULT_MEDIUM_TYPE
#define SBC_DEV_SPEC_PARAM_WR_ENABLE (0x00)
#define SBC_DEV_SPEC_PARAM_WR_PROTECT (0x80)
#define SBC_BLOCK_DESCRIPTOR_LENGTH (0x00)
#define SBC_MSK_DBD (0x08)
#define SBC_MSK_PAGE_CONTROL (0xC0)
#define SBC_MSK_PAGE_CODE (0x3F)
/************ General Page Code paramaters *****************/
#define SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY (0x01)
#define SBC_PAGE_CODE_FORMAT_DEVICE (0x03)
#define SBC_PAGE_CODE_FLEXIBLE_DISK (0x05)
#define SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS (0x1C)
#define SBC_PAGE_CODE_ALL (0x3F)
#define SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS (0x0A)
#define SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY (0x0A)
#define SBC_PAGE_LENGTH_FLEXIBLE_DISK (0x1E)
#define SBC_PAGE_LENGTH_FORMAT_DEVICE (0x16)
#define SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS (SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS + 2 + 3)
#define SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY (SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY + 2 + 3 )
#define SBC_MODE_DATA_LENGTH_FLEXIBLE_DISK (SBC_PAGE_LENGTH_FLEXIBLE_DISK + 2 + 3 )
#define SBC_MODE_DATA_LENGTH_FORMAT_DEVICE (SBC_PAGE_LENGTH_FORMAT_DEVICE + 2 + 3 )
/*SBC_PAGE_LENGTH_FLEXIBLE_DISK + 2 + \*/
#define SBC_MODE_DATA_LENGTH_CODE_ALL (SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY + 2 + \
SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS + 2 + \
SBC_BLOCK_DESCRIPTOR_LENGTH + \
+ 3 )
/* SBC_MODE_DATA_LENGTH_FORMAT_DEVICE + 2 + \*/
/****** Information exceptions control page parameters *****/
#define SBC_MRIE (0x05)
/*************** Format device page parameters *************/
#define SBC_TRACK_PER_ZONE_MSB (0x00)
#define SBC_TRACK_PER_ZONE_LSB (0x00)
#define SBC_ALTERNATE_SECTORS_PER_ZONE_MSB (0x00)
#define SBC_ALTERNATE_SECTORS_PER_ZONE_LSB (0x00)
#define SBC_ALTERNATE_TRACK_PER_ZONE_MSB (0x00)
#define SBC_ALTERNATE_TRACK_PER_ZONE_LSB (0x00)
#define SBC_ALTERNATE_TRACK_PER_LU_MSB (0x00)
#define SBC_ALTERNATE_TRACK_PER_LU_LSB (0x00)
/************* Flexible Disk page Parameters ***************/
#define SBC_TRANSFER_RATE_MSB (0x13)
#define SBC_TRANSFER_RATE_LSB (0x88)
/* 1388h 5 Mbit/s */
/* 07D0h 2 Mbit/s */
/* 03E8h 1 Mbit/s */
/* 01F4h 500 kbit/s */
/* 012Ch 300 kbit/s */
/* 00FAh 250 kbit/s */
#define SBC_NUMBER_OF_HEAD (0x04)
#define SBC_SECTOR_PER_TRACK (0x20)
#define SBC_DATA_BYTE_PER_SECTOR_MSB (0x02)
#define SBC_DATA_BYTE_PER_SECTOR_LSB (0x00)
#define SBC_NUMBER_OF_CYLINDERS_MSB (0x01)
#define SBC_NUMBER_OF_CYLINDERS_LSB (0xE9)
#define SBC_STARTING_CYLINDER_WRITE_COMPENSATION_MSB (0x00)
#define SBC_STARTING_CYLINDER_WRITE_COMPENSATION_LSB (0x00)
#define SBC_STARTING_CYLINDER_REDUCED_WRITE_MSB (0x00)
#define SBC_STARTING_CYLINDER_REDUCED_WRITE_LSB (0x00)
#define SBC_DEVICE_STEP_RATE_MSB (0x00)
#define SBC_DEVICE_STEP_RATE_LSB (0x00)
#define SBC_DEVICE_STEP_PULSE_WIDTH (0x00)
#define SBC_HEAD_SETTLE_DELAY_MSB (0x00)
#define SBC_HEAD_SETTLE_DELAY_LSB (0x00)
#define SBC_MOTOR_ON_DELAY (0x00)
#define SBC_MOTOR_OFF_DELAY (0x00)
#define SBC_STEP_PULSE_PER_CYLINDER (0x00)
#define SBC_WRITE_COMPENSATION (0x00)
#define SBC_HEAD_LOAD_DELAY (0x00)
#define SBC_HEAD_UNLOAD_DELAY (0x00)
#define SBC_PIN34_PIN2 (0x00)
#define SBC_PIN4_PIN1 (0x00)
#define SBC_MEDIUM_ROTATION_RATE_MSB (0x00)
#define SBC_MEDIUM_ROTATION_RATE_LSB (0x00)
/************ Read/Write Error Recovery parameters**********/
#define SBC_READ_RETRY_COUNT (0x03)
#define SBC_WRITE_RETRY_COUNT (0x80)
#define SBC_CORRECTION_SPAN (0x00)
#define SBC_HEAD_OFFSET_COUNT (0x00)
#define SBC_DATA_STROBE_OFFSET (0x00)
#define SBC_RECOVERY_LIMIT_MSB (0x00)
#define SBC_RECOVERY_LIMIT_LSB (0x00)
/*_____ D E F I N I T I O N ________________________________________________*/
#define SBC_MAX_INQUIRY_DATA (0x60) // value ?
struct sbc_st_std_inquiry_data
{
Byte DeviceType : 5;
Byte PeripheralQualifier : 3;
Byte Reserved1 : 7;
Byte RemovableMedia : 1;
Byte Version;
Byte Reserved3 : 5;
Byte NormACA : 1;
Byte Obsolete0 : 1;
Byte AERC : 1;
Byte Reserved4[3];
Byte SoftReset : 1;
Byte CommandQueue : 1;
Byte Reserved5 : 1;
Byte LinkedCommands : 1;
Byte Synchronous : 1;
Byte Wide16Bit : 1;
Byte Wide32Bit : 1;
Byte RelativeAddressing : 1;
};
//_____ D E C L A R A T I O N S ____________________________________________
#define Sbc_send_failed() (g_scsi_status = COMMAND_FAILED)
#define Sbc_send_check_condition() (g_scsi_status = CHECK_CONDITION)
#define Sbc_send_good() (g_scsi_status = COMMAND_PASSED)
/*#define Sbc_valid_write_usb(length) ( Usb_set_TXRDY(), \
dCBWDataTransferLength -= length, \
while (!Usb_tx_complete()),\
Usb_clear_TXCMPL() )
*/
#define Sbc_build_sense(skey, sasc, sascq) ( g_scsi_sense.key = skey, \
g_scsi_sense.asc = sasc, \
g_scsi_sense.ascq = sascq )
#define Sbc_valid_write_usb(length) ( Usb_send_in(), \
g_scsi_data_remaining -= length )
#define COMMAND_PASSED 0x00
#define COMMAND_FAILED 0x01
#define CHECK_CONDITION 0x02
#define PHASE_ERROR 0x02
Bool sbc_inquiry (void);
Bool sbc_mode_sense( Bool sense_10 );
Bool sbc_mode_select_6 (void);
Bool sbc_request_sense (void);
Bool sbc_format (void);
Bool sbc_write_10 (void);
Bool sbc_read_10 (void);
Bool sbc_test_unit_ready(void);
Bool sbc_read_capacity(void);
Bool sbc_prevent_allow_medium_removal(void);
void sbc_lun_status_is_good(void);
void sbc_lun_status_is_busy_or_change(void);
void sbc_lun_status_is_not_present(void);
void sbc_lun_status_is_fail(void);
void sbc_lun_status_is_protected(void);
#endif /* _SCSI_DECODER_H_ */
/** @} */

View file

@ -0,0 +1,276 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file usb_task.c *********************************************************************
*
* \brief
* This file manages the USB storage.
*
* \addtogroup usbstick
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com
******************************************************************************/
/*
Copyright (c) 2004 ATMEL Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\addtogroup usbstorage
@{
*/
//_____ I N C L U D E S ___________________________________________________
#include "contiki.h"
#include "usb_drv.h"
#include "storage/storage_task.h"
#include "usb_descriptors.h"
#include "usb_standard_request.h"
#include "usb_specific_request.h"
#include "storage/scsi_decoder.h"
#include "storage/ctrl_access.h"
//_____ M A C R O S ________________________________________________________
//_____ D E F I N I T I O N S ______________________________________________
//_____ D E C L A R A T I O N S ____________________________________________
extern U8 usb_configuration_nb;
static bit ms_data_direction;
static U8 dCBWTag[4];
extern U8 g_scsi_status;
extern U32 g_scsi_data_remaining;
extern bit ms_multiple_drive;
extern U8 g_scsi_command[16];
U8 usb_LUN;
void usb_mass_storage_cbw (void);
void usb_mass_storage_csw (void);
#define Usb_set_ms_data_direction_in() (ms_data_direction = 1)
#define Usb_set_ms_data_direction_out() (ms_data_direction = 0)
#define Is_usb_ms_data_direction_in() (ms_data_direction == 1)
static struct etimer et;
PROCESS(storage_process, "Storage process");
/**
* \brief USB Mass Storage Class Process
*
* This is the link between USB and the "good stuff". In this routine data
* is received and processed by USB Storage Class
*/
PROCESS_THREAD(storage_process, ev, data_proc)
{
PROCESS_BEGIN();
while(1) {
if (usb_mode == mass_storage) {
if (Is_device_enumerated()) {
Usb_select_endpoint(MS_OUT_EP);
if (Is_usb_receive_out()) {
usb_mass_storage_cbw();
usb_mass_storage_csw();
}
}
}
if (usb_mode == mass_storage) {
etimer_set(&et, CLOCK_SECOND/250 + 1);
} else {
etimer_set(&et, CLOCK_SECOND);
}
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
} //while(1)
PROCESS_END();
}
//! @brief USB Command Block Wrapper (CBW) management
//!
//! This function decodes the CBW command and stores the SCSI command
//!
//! @warning Code:?? bytes (function code length)
//!
void usb_mass_storage_cbw (void)
{
bit cbw_error;
uint8_t c;
uint8_t dummy;
cbw_error = FALSE;
Usb_select_endpoint(MS_OUT_EP); //! check if dCBWSignature is correct
if (0x55 != Usb_read_byte())
{ cbw_error = TRUE; } //! 'U'
if (0x53 != Usb_read_byte())
{ cbw_error = TRUE; } //! 'S'
if (0x42 != Usb_read_byte())
{ cbw_error = TRUE; } //! 'B'
if (0x43 != Usb_read_byte())
{ cbw_error = TRUE; } //! 'C'
dCBWTag[0] = Usb_read_byte(); //! Store CBW Tag to be repeated in CSW
dCBWTag[1] = Usb_read_byte();
dCBWTag[2] = Usb_read_byte();
dCBWTag[3] = Usb_read_byte();
LSB0(g_scsi_data_remaining) = Usb_read_byte();
LSB1(g_scsi_data_remaining) = Usb_read_byte();
LSB2(g_scsi_data_remaining) = Usb_read_byte();
LSB3(g_scsi_data_remaining) = Usb_read_byte();
if (Usb_read_byte() != 0x00) //! if (bmCBWFlags.bit7 == 1) {direction = IN}
{
Usb_set_ms_data_direction_in();
if (cbw_error)
{
Usb_ack_receive_out();
Usb_select_endpoint(MS_IN_EP);
Usb_enable_stall_handshake();
return;
}
}
else
{
Usb_set_ms_data_direction_out();
if (cbw_error)
{
Usb_enable_stall_handshake();
Usb_ack_receive_out();
return;
}
}
usb_LUN = Usb_read_byte();
if (!ms_multiple_drive)
{
usb_LUN = get_cur_lun();
}
dummy = Usb_read_byte(); //! dummy CBWCBLength read
for (c=0; c<16; c++) // store scsi_command
{
g_scsi_command[c] = Usb_read_byte();
}
Usb_ack_receive_out();
if (Is_usb_ms_data_direction_in())
{
Usb_select_endpoint(MS_IN_EP);
}
if (TRUE != scsi_decode_command())
{
if (g_scsi_data_remaining != 0)
{
Usb_enable_stall_handshake();
}
}
}
//! @brief USB Command Status Wrapper (CSW) management
//!
//! This function sends the status in relation with the last CBW
//!
void usb_mass_storage_csw (void)
{
Usb_select_endpoint(MS_IN_EP);
while (Is_usb_endpoint_stall_requested())
{
Usb_select_endpoint(EP_CONTROL);
if (Is_usb_receive_setup()) { usb_process_request(); }
Usb_select_endpoint(MS_IN_EP);
}
Usb_select_endpoint(MS_OUT_EP);
while (Is_usb_endpoint_stall_requested())
{
Usb_select_endpoint(EP_CONTROL);
if (Is_usb_receive_setup()) { usb_process_request(); }
Usb_select_endpoint(MS_OUT_EP);
}
Usb_select_endpoint(MS_IN_EP);
while(!Is_usb_write_enabled());
//! write CSW Signature
Usb_write_byte(0x55); //! 'U'
Usb_write_byte(0x53); //! 'S'
Usb_write_byte(0x42); //! 'B'
Usb_write_byte(0x53); //! 'S'
//! write stored CBW Tag
Usb_write_byte(dCBWTag[0]);
Usb_write_byte(dCBWTag[1]);
Usb_write_byte(dCBWTag[2]);
Usb_write_byte(dCBWTag[3]);
//! write data residue value
Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[3] );
Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[2] );
Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[1] );
Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[0] );
//! write command status
Usb_write_byte(g_scsi_status); //! 0 -> PASS, 1 -> FAIL
Usb_send_in();
}
/** @} */

View file

@ -0,0 +1,69 @@
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file storage_task.c **********************************************************
*
* \brief
* This file manages the USB storage.
*
* \addtogroup usbstick
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com
******************************************************************************/
/*
Copyright (c) 2004 ATMEL Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
\ingroup usbstick
\defgroup usbstorage USB Mass Storage Task
@{
*/
#ifndef _STORAGE_TASK_H_
#define _STORAGE_TASK_H_
//_____ I N C L U D E S ____________________________________________________
#include "config.h"
//_____ M A C R O S ________________________________________________________
//_____ D E C L A R A T I O N S ____________________________________________
void sof_action(void);
PROCESS_NAME(storage_process);
#endif /* _STORAGE_TASK_H_ */
/** @} */