Contiki 2.5
scsi_decoder.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
2 /*! \file scsi_decoder.c *******************************************************
3  *
4  * \brief
5  * This file is the scsi decoder
6  *
7  * \addtogroup usbstick
8  *
9  * \author
10  * Atmel Corporation: http://www.atmel.com \n
11  * Support email: avr@atmel.com
12  ******************************************************************************/
13 /*
14  Copyright (c) 2004 ATMEL Corporation
15  All rights reserved.
16 
17  Redistribution and use in source and binary forms, with or without
18  modification, are permitted provided that the following conditions are met:
19 
20  * Redistributions of source code must retain the above copyright
21  notice, this list of conditions and the following disclaimer.
22  * Redistributions in binary form must reproduce the above copyright
23  notice, this list of conditions and the following disclaimer in
24  the documentation and/or other materials provided with the
25  distribution.
26  * Neither the name of the copyright holders nor the names of
27  contributors may be used to endorse or promote products derived
28  from this software without specific prior written permission.
29 
30  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  POSSIBILITY OF SUCH DAMAGE.
41 */
42 
43 /**
44  \addtogroup usbstorage
45  @{
46 */
47 
48 //_____ I N C L U D E S ___________________________________________________
49 
50 #include "config.h"
51 #include "storage/scsi_decoder.h"
52 #include "conf_usb.h"
53 #include "usb_drv.h"
54 #include "storage/ctrl_status.h"
55 #include "storage/ctrl_access.h"
56 
57 
58 //_____ M A C R O S ________________________________________________________
59 
60 
61 //_____ D E F I N I T I O N S ______________________________________________
62 
63 
64 U8 g_scsi_command[16];
65 U8 g_scsi_status;
66 U32 g_scsi_data_remaining;
67 
68 FLASH U8 g_sbc_vendor_id[8] = SBC_VENDOR_ID;
69 FLASH U8 g_sbc_product_id[16] = SBC_PRODUCT_ID;
70 FLASH U8 g_sbc_revision_id[4] = SBC_REVISION_ID;
71 
72 extern U8 usb_LUN;
73 
74  s_scsi_sense g_scsi_sense;
75 
76 
77 FLASH struct sbc_st_std_inquiry_data sbc_std_inquiry_data =
78 {
79  /* Byte 0 : 0x00 */
80  0x00, /* DeviceType: Direct-access device */
81  0, /* PeripheralQualifier : Currently connected */
82 
83  /* Byte 1 : 0x80 */
84  0, /* Reserved1 */
85  1, /* RMB : Medium is removable (this bit must be at 1, else the medium isn't see on Windows) */
86 
87  // /* Byte 2 : 0x02 */
88  // 0x02, /* Version: Device compliant to ANSI X3.131:1994 */
89 
90  /* Byte 2 : 0x00 */
91  0x00, /* Version: Device not compliant to any standard */
92 
93  /* Byte 3 : 0x02 */
94  2, /* Response data format */
95  0, /* NormACA */
96  0, /* Obsolete0 */
97  0, /* AERC */
98 
99  /* Byte 4 : 0x1F */
100  /* Byte 5 : 0x00 */
101  /* Byte 6 : 0x00 */
102  /* Reserved4[3] */
103  {
104  0x1F, /* Additional Length (n-4) */
105  0, /* SCCS : SCC supported */
106  0
107  },
108 
109  /* Byte 7 : 0x00 */
110  0, /* SoftReset */
111  0, /* CommandQueue */
112  0, /* Reserved5 */
113  0, /* LinkedCommands */
114  0, /* Synchronous */
115  0, /* Wide16Bit */
116  0, /* Wide32Bit */
117  0, /* RelativeAddressing */
118 };
119 
120 
121 static void send_informational_exceptions_page (void);
122 static void send_read_write_error_recovery_page (U8);
123 static void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length );
124 
125 
126 //_____ D E C L A R A T I O N S ____________________________________________
127 /**
128  * @brief SCSI decoder function
129  *
130  * This function read the SCSI command and launches the appropriate function
131  *
132  * @warning Code:.. bytes (function FLASH length)
133  *
134  * @return FALSE: result KO,
135  * TRUE: result OK
136  *
137  */
139 {
140 Bool status;
141 
142  if (g_scsi_command[0] == SBC_CMD_WRITE_10)
143  {
144  Scsi_start_write_action();
145  status = sbc_write_10();
146  Scsi_stop_write_action();
147  return status;
148  }
149  if (g_scsi_command[0] == SBC_CMD_READ_10 )
150  {
151  Scsi_start_read_action();
152  status = sbc_read_10();
153  Scsi_stop_read_action();
154  return status;
155  }
156 
157  switch (g_scsi_command[0]) /* check other command received */
158  {
159  case SBC_CMD_REQUEST_SENSE: /* 0x03 - Mandatory */
160  return sbc_request_sense();
161  break;
162 
163  case SBC_CMD_INQUIRY: /* 0x12 - Mandatory */
164  return sbc_inquiry();
165  break;
166 
167  case SBC_CMD_TEST_UNIT_READY: /* 0x00 - Mandatory */
168  return sbc_test_unit_ready();
169  break;
170 
171  case SBC_CMD_READ_CAPACITY: /* 0x25 - Mandatory */
172  return sbc_read_capacity();
173  break;
174 
175  case SBC_CMD_MODE_SENSE_6: /* 0x1A - Optional */
176  return sbc_mode_sense( FALSE );
177  break;
178 
179  case SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:/* 0x1E */
181  break;
182 
183  case SBC_CMD_VERIFY_10: /* 0x2F - Optional */
185  break;
186  case SBC_CMD_MODE_SENSE_10: /* 0x5A - Optional */
187  return sbc_mode_sense( TRUE );
188  break;
189 
190  case SBC_CMD_FORMAT_UNIT: /* 0x04 - Mandatory */
191 
192  case SBC_CMD_MODE_SELECT_6: /* 0x15 - Optional */
193 
194 
195 
196 
197  case SBC_CMD_START_STOP_UNIT: /* 0x1B - Optional */
198  case SBC_CMD_SEND_DIAGNOSTIC: /* 0x1D - */
199  case SBC_CMD_READ_LONG: /* 0x23 - Optional */
200  case SBC_CMD_SYNCHRONIZE_CACHE: /* 0x35 - Optional */
201  case SBC_CMD_WRITE_BUFFER: /* 0x3B - Optional */
202  case SBC_CMD_RESERVE_10: /* 0x56 - Mandatory */
203  case SBC_CMD_RELEASE_10: /* 0x57 - Mandatory - see chapter 7.16 - SPC 2 */
204  default:
205  { /* Command not supported */
206  Sbc_send_failed();
207  Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, 0x00);
208  return FALSE;
209  break;
210  }
211  }
212  return TRUE;
213 }
214 
215 
216 /**
217  * @brief This function manages the SCSI REQUEST SENSE command (0x03)
218  *
219  * The SCSI Sense contains the status of the last command
220  * This status is composed of 3 Bytes :
221  * - sense key (g_scsi_sense.key)
222  * - additional sense code (g_scsi_sense.asc)
223  * - additional sense code qualifier (g_scsi_sense.ascq)
224  *
225  * @warning Code:.. bytes (function code length)
226  *
227  * @return FALSE: result KO,
228  * TRUE: result OK
229  *
230  */
231 Bool sbc_request_sense (void)
232 {
233  U8 allocation_length, i;
234  U8 request_sens_output[18]; /* the maximum size of request is 17 */
235 
236  allocation_length = g_scsi_command[4]; /* Allocation length */
237 
238  /* Initialize the request sense data */
239  request_sens_output[0] = SBC_RESPONSE_CODE_SENSE; /* 70h */
240  request_sens_output[1] = 0x00; /* Obsolete */
241  request_sens_output[2] = g_scsi_sense.key;
242 
243  request_sens_output[3] = 0x00; /* For direct access media, Information field */
244  request_sens_output[4] = 0x00; /* give the unsigned logical block */
245  request_sens_output[5] = 0x00; /* address associated with the sense key */
246  request_sens_output[6] = 0x00;
247 
248  request_sens_output[7] = SBC_ADDITIONAL_SENSE_LENGTH; /* !! UFI device shall not adjust the Additional sense length to reflect truncation */
249  request_sens_output[8] = SBC_COMMAND_SPECIFIC_INFORMATION_3;
250  request_sens_output[9] = SBC_COMMAND_SPECIFIC_INFORMATION_2;
251  request_sens_output[10] = SBC_COMMAND_SPECIFIC_INFORMATION_1;
252  request_sens_output[11] = SBC_COMMAND_SPECIFIC_INFORMATION_0;
253 
254  request_sens_output[12] = g_scsi_sense.asc;
255  request_sens_output[13] = g_scsi_sense.ascq;
256 
257  request_sens_output[14] = SBC_FIELD_REPLACEABLE_UNIT_CODE;
258  request_sens_output[15] = SBC_SENSE_KEY_SPECIFIC_2;
259  request_sens_output[16] = SBC_SENSE_KEY_SPECIFIC_1;
260  request_sens_output[17] = SBC_SENSE_KEY_SPECIFIC_0;
261 
262  /* Send the request data */
263  for( i=0 ; i<allocation_length ; i++ )
264  {
265  Usb_write_byte( request_sens_output[i] );
266  }
267  Sbc_valid_write_usb( allocation_length );
268 
270 
271  return TRUE;
272 }
273 
274 /**
275  * @brief This function manages the SCSI INQUIRY command (0x12)
276  *
277  * The SCSI Inquiry field contains information regarding parameters
278  * of the target. For example:
279  * - vendor identification
280  * - product identification
281  * - peripheral qualifier
282  * - peripheral device type
283  * - etc
284  *
285  * @warning Code:.. bytes (function code length)
286  *
287  * @return FALSE: result KO,
288  * TRUE: result OK
289  *
290  */
291 Bool sbc_inquiry (void)
292 {
293  U8 allocation_length, i;
294 
295 #ifdef AVRGCC
296  PGM_VOID_P ptr;
297 #else
298  U8 FLASH *ptr;
299 #endif
300 
301  if( (0 == (g_scsi_command[1] & 0x03) ) // CMDT and EPVD bits are 0
302  && (0 == g_scsi_command[2] ) ) // PAGE or OPERATION CODE fields = 0x00?
303  {
304  //** send standard inquiry data
305 
306  // Check the size of inquiry data
307  allocation_length = g_scsi_command[4];
308  if (allocation_length > SBC_MAX_INQUIRY_DATA)
309  {
310  allocation_length = SBC_MAX_INQUIRY_DATA;
311  }
312 
313  // send first inquiry data (0 to 8)
314  ptr = (FLASH U8*) &sbc_std_inquiry_data;
315 
316  for ( i=0 ; ((i != 36) && (allocation_length > i)); i++)
317  {
318  if( 8 == i )
319  { // send vendor id (8 to 16)
320  ptr = (FLASH U8 *) &g_sbc_vendor_id;
321  }
322  if( 16 == i )
323  { // send product id (16 to 32)
324  ptr = (FLASH U8 *) &g_sbc_product_id;
325  }
326  if( 32 == i )
327  { // send revision id (32 to 36)
328  ptr = (FLASH U8 *) &g_sbc_revision_id;
329  }
330 #ifndef AVRGCC
331  Usb_write_byte((U8)(*ptr++)); // send tab
332 #else // AVRGCC does not support point to PGM space
333 #warning with avrgcc assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
334  Usb_write_byte(pgm_read_byte_near((unsigned int)ptr++));
335 #endif
336 
337  }
338 
339  // send data (36 to SBC_MAX_INQUIRY_DATA), and can be tranmitted by Bulk
340  // Description of next bytes (this bytes is always egal to 0) :
341  // VendorSpecific : 20 Bytes
342  // Next byte : 1 byte
343  // - InfoUnitSupport : 1 bit
344  // - QuickArbitSupport : 1 bit
345  // - Clocking : 2 bits
346  // - Reserved6 : 4 bits
347  // Reserved7 : 1 byte
348  // VersionDescriptor : 8 bytes
349  // Reserved8 : 22 bytes
350  // ...
351  while( allocation_length > i )
352  {
353  if (64 == i)
354  { // for each 64 bytes, send USB packet
355  Sbc_valid_write_usb(64);
356  allocation_length -= 64;
357  i = 0;
358  }
359  Usb_write_byte(0); // write value of last bytes of inquiry data
360  i++;
361  }
362  // send last USB packet
363  Sbc_valid_write_usb(allocation_length);
365  return TRUE;
366  }
367  else
368  { // (CMDT=EVPD <> 0) or (PAGE CODE <> 0x00)
369  Sbc_send_failed();
370  Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
371  return FALSE;
372  }
373 }
374 
375 
376 Bool sbc_test_unit_ready(void)
377 {
378  switch ( mem_test_unit_ready(usb_LUN) )
379  {
380  case CTRL_GOOD :
382  break;
383 
384  case CTRL_NO_PRESENT :
386  break;
387 
388  case CTRL_BUSY :
390  break;
391 
392  case CTRL_FAIL :
393  default :
395  break;
396  }
397  return TRUE;
398 }
399 
400 
401 Bool sbc_read_capacity (void)
402 {
403  _MEM_TYPE_SLOW_ U32 mem_size_nb_sector;
404 
405  switch ( mem_read_capacity( usb_LUN, &mem_size_nb_sector ) )
406  {
407  case CTRL_GOOD :
408  Usb_write_byte(MSB0(mem_size_nb_sector)); // return nb block
409  Usb_write_byte(MSB1(mem_size_nb_sector));
410  Usb_write_byte(MSB2(mem_size_nb_sector));
411  Usb_write_byte(MSB3(mem_size_nb_sector));
412  Usb_write_byte( 0 ); // return block size (= 512B)
413  Usb_write_byte( 0 );
414  Usb_write_byte( (U8)(512 >> 8) );
415  Usb_write_byte( (U8)(512 & 0xFF));
416 
417  Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH);
419  return TRUE;
420  break;
421 
422  case CTRL_NO_PRESENT :
424  break;
425 
426  case CTRL_BUSY :
428  break;
429 
430  case CTRL_FAIL :
431  default :
433  break;
434  }
435  return FALSE;
436 }
437 
438 
439 Bool sbc_read_10 (void)
440 {
441  U32 mass_addr; // rd or wr block address
442  U16 mass_size; // rd or write nb of blocks
443 
444  MSB0(mass_addr) = g_scsi_command[2]; // read address
445  MSB1(mass_addr) = g_scsi_command[3];
446  MSB2(mass_addr) = g_scsi_command[4];
447  MSB3(mass_addr) = g_scsi_command[5];
448 
449  MSB(mass_size) = g_scsi_command[7]; // read size
450  LSB(mass_size) = g_scsi_command[8];
451 
452  if (mass_size != 0)
453  {
454  switch ( memory_2_usb( usb_LUN , mass_addr, mass_size ) )
455  {
456  case CTRL_GOOD :
458  g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size);
459  return TRUE;
460  break;
461 
462  case CTRL_NO_PRESENT :
464  return FALSE;
465  break;
466 
467  case CTRL_BUSY :
469  return FALSE;
470  break;
471 
472  case CTRL_FAIL :
473  default :
475  return FALSE;
476  break;
477  }
478  }
479  else
480  { // No data to transfer
482  }
483  return TRUE;
484 }
485 
486 
487 Bool sbc_write_10 (void)
488 {
489  U32 mass_addr; // rd or wr block address
490  U16 mass_size; // rd or write nb of blocks
491 
492  MSB0(mass_addr) = g_scsi_command[2]; // read address
493  MSB1(mass_addr) = g_scsi_command[3];
494  MSB2(mass_addr) = g_scsi_command[4];
495  MSB3(mass_addr) = g_scsi_command[5];
496 
497  MSB(mass_size) = g_scsi_command[7]; // read size
498  LSB(mass_size) = g_scsi_command[8];
499 
500  if (mass_size != 0)
501  {
502  if( TRUE == mem_wr_protect( usb_LUN ) )
503  {
505  return FALSE;
506 #warning For Win98 data must be read to avoid blocking
507  }
508  else
509  {
510  switch (usb_2_memory( usb_LUN , mass_addr, mass_size ))
511  {
512  case CTRL_GOOD :
514  g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size);
515  return TRUE;
516  break;
517 
518  case CTRL_NO_PRESENT :
520  return FALSE;
521  break;
522 
523  case CTRL_BUSY :
525  return FALSE;
526  break;
527 
528  case CTRL_FAIL :
529  default :
531  return FALSE;
532  break;
533  }
534  }
535  }
536  else
537  { // No data to transfer
539  }
540  return TRUE;
541 }
542 
543 
544 /**
545  * @brief This function manages the SCSI MODE SENSE command (0x1A for sense 6 and 0x5A for sense 10)
546  *
547  * The SCSI mode sense function returns parameters to an application client.
548  * It is a complementary command to the SCSI MODE SELECT command.
549  *
550  * @warning Code:.. bytes (function code length)
551  *
552  * @param b_sense_10 ( TRUE = sense 10, TRUE = sense 6)
553  *
554  * @return FALSE: result KO,
555  * TRUE: result OK
556  *
557  */
558 Bool sbc_mode_sense( Bool b_sense_10 )
559 {
560  U8 allocation_length;
561 
562  if( b_sense_10 )
563  allocation_length = g_scsi_command[8];
564  else
565  allocation_length = g_scsi_command[4];
566 
567  // switch for page code
568  switch ( g_scsi_command[2] & SBC_MSK_PAGE_CODE )
569  {
570  case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS: /* Page Code: Informational exceptions control page */
571  sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS );
572  send_informational_exceptions_page();
573  Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
574  break;
575 
576  case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
577  sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY );
578  send_read_write_error_recovery_page(allocation_length);
579  Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
580  break;
581 
582  case SBC_PAGE_CODE_ALL:
583  sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_CODE_ALL );
584  if( b_sense_10 )
585  {
586  if (allocation_length == 8)
587  {
588  Sbc_valid_write_usb(8);
589  break;
590  }
591  }
592  else
593  {
594  if (allocation_length == 4)
595  {
596  Sbc_valid_write_usb(4);
597  break;
598  }
599  }
600  // send page by ascending order code
601  send_read_write_error_recovery_page(allocation_length); // 12 bytes
602  if (allocation_length > 12)
603  {
604  send_informational_exceptions_page(); // 12 bytes
605  Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
606  }
607  else
608  {
609  Sbc_valid_write_usb(allocation_length);
610  }
611  break;
612 
613  default:
614  Sbc_send_failed();
615  Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
616  return FALSE;
617  break;
618  }
620  return TRUE;
621 }
622 
623 
624 /**
625  * @brief This function send the header of the SCSI MODE SENSE command
626  *
627  * @param b_sense_10 TRUE = sense 10, FALSE = sense 6
628  * @param u8_data_length data length in byte
629  *
630  */
631 void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length )
632 {
633  // Send Data length
634  if( b_sense_10 )
635  {
636  Usb_write_byte(0);
637  }
638  Usb_write_byte( u8_data_length );
639 
640  // Send device type
641  Usb_write_byte(SBC_MEDIUM_TYPE);
642 
643  // Write protect status
644  if (mem_wr_protect( usb_LUN ))
645  {
646  Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_PROTECT); // Device is write protected
647  }
648  else
649  {
650  Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_ENABLE); // Device is write enabled
651  }
652 
653  if( b_sense_10 )
654  { // Reserved
655  Usb_write_byte(0);
656  Usb_write_byte(0);
657  }
658 
659  // Send Block descriptor length
660  if( b_sense_10 )
661  {
662  Usb_write_byte(0);
663  }
664  Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);
665 }
666 
667 
668 /**
669  * @brief This function writes informational exceptions page parameters
670  *
671  * @warning Code:.. bytes (function code length)
672  *
673  * @return FALSE: result KO,
674  * TRUE: result OK
675  *
676  */
677 void send_informational_exceptions_page (void)
678 {
679  Usb_write_byte(SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS); /* Page Code: Informational exceptions control page */
680  /* See chapter 8.3.8 on SPC-2 specification */
681  Usb_write_byte(SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS); /* Page Length */
682  Usb_write_byte(0x00); /* ..., Test bit = 0, ... */
683  Usb_write_byte(SBC_MRIE); /* MRIE = 0x05 */
684  Usb_write_byte(0x00); /* Interval Timer (MSB) */
685  Usb_write_byte(0x00);
686  Usb_write_byte(0x00);
687  Usb_write_byte(0x00); /* Interval Timer (LSB) */
688  Usb_write_byte(0x00); /* Report Count (MSB) */
689  Usb_write_byte(0x00);
690  Usb_write_byte(0x00);
691  Usb_write_byte(0x01); /* Report Count (LSB) */
692 }
693 
694 
695 /**
696  * @brief This function writes error recovery page
697  *
698  * @warning Code:.. bytes (function code length)
699  *
700  * @param length The length of
701  *
702  * @return FALSE: result KO,
703  * TRUE: result OK
704  *
705  */
706 void send_read_write_error_recovery_page (U8 length)
707 {
708  Usb_write_byte(SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY);
709 
710  Usb_write_byte(SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY); /* Page Length */
711  Usb_write_byte(0x80);
712  Usb_write_byte(SBC_READ_RETRY_COUNT);
713  Usb_write_byte(SBC_CORRECTION_SPAN);
714  Usb_write_byte(SBC_HEAD_OFFSET_COUNT);
715  Usb_write_byte(SBC_DATA_STROBE_OFFSET);
716  Usb_write_byte(0x00); /* Reserved */
717 
718  if (length > 12)
719  {
720  Usb_write_byte(SBC_WRITE_RETRY_COUNT);
721  Usb_write_byte(0x00);
722  Usb_write_byte(SBC_RECOVERY_LIMIT_MSB);
723  Usb_write_byte(SBC_RECOVERY_LIMIT_LSB);
724  }
725 }
726 
727 /**
728  * @brief This function manages the SCSI PREVENT ALLOW MEDIUM REMOVAL
729  * command (0x1E)
730  *
731  * The SCSI prevent allow medium removal command requests that the target
732  * enable or disable the removal of the medium in the logical unit.
733  *
734  * @warning Code:.. bytes (function code length)
735  *
736  * @return FALSE: result KO,
737  * TRUE: result OK
738  *
739  */
741 {
743  return TRUE;
744 }
745 
746 
747 //! This fonction send the UFI status GOOD
748 //!
750 {
751  Sbc_send_good();
752  Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
753 }
754 
755 //! This fonction send the UFI status "lun not present"
756 //!
758 {
759  Sbc_send_failed();
760  Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00);
761 }
762 
763 //! This fonction send the UFI status busy and change
764 //!
766 {
767  Sbc_send_failed();
768  Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00 );
769 }
770 
771 //! This fonction send the UFI status FAIL
772 //!
774 {
775  Sbc_send_failed();
776  Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
777 }
778 
779 //! This fonction send the UFI status FAIL because write protection
780 //!
782 {
783  Sbc_send_failed();
784  Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00);
785 }
786 
787 /** @} */