This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

USB MSC class and CD ROM subclass

Hi Dear Friends,
I've used mass storage code from sample codes of KEIL on AT91SAM7x.
And it works correctly and shows it as Flash memory in the windows.Then I changed it to apear as CD-ROM in windows.I have changed PDT and block size and added SCSI commands that requires.

Now I want to replace the contents of the disk image into CD one, which is formatted following to ISO966 spec . And there is my problem. I confused about it.In Primary Volume Descriptor should I placed the path table first and then placed the root? And I have problem with the path table itself too.

Can anyone help me about it? Or give me an example or tutorial about ISO?

I have used the Nero too to create ISO file but when it created the ISO File size is about 1 MB although I just put the same README.TXT that are in DISKImg.c and its size is just 94 B. What am I missing?

Parents
  • Sorry for my long absence.

    In your last post, you asked about READ TOC (0x43) command.

    There are four types of this command, identified by its parameters
    1) MSF:0, FORMAT:0
    2) MSF:0, FORMAT:1
    3) MSF:1, FORMAT:0
    4) MSF:1, FORMAT:2 (format field is assigned to MSb 2bits of Control byte - legacy form)

    The return data blocks are slightly different each other.

    - Windows and Linux ask 1),2),3)
    - MacOSX retrieves 1),4)

    As of the details of this command, refer to SCSI MMC-6 (mmc6r02g.pdf)
    (search mmc6r02g.pdf)

    Here is the implementation

    //
    // READ TOC implementation
    //
    
    #define BIGLONG(x) (((x) >> 24) & 0xFF), (((x) >> 16) & 0xFF), (((x) >> 8) & 0xFF), ((x) & 0xFF)
    #define BCD(x)     (((((x) / 10) << 4) & 0xF0) | (((x) % 10) & 0x0F))
    
    #define LBA2M(x)   BCD( ((x) + 150) / 75  / 60)
    #define LBA2S(x)   BCD((((x) + 150) / 75) % 60)
    #define LBA2F(x)   BCD( ((x) + 150) % 75)
    
    #define LBA2MH(x)   ( ((x) + 150) / 75  / 60)
    #define LBA2SH(x)   ((((x) + 150) / 75) % 60)
    #define LBA2FH(x)   ( ((x) + 150) % 75)
    
    const U8 SCSI_TOC_LBA0[] = {
           // TOC response header
      0x00, 0x12,             // Data Length
      0x01,                   // First Track
      0x01,                   // Last Track
           // track descriptor 1
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0x01,                   // Track Number
      0x00,                   // Reserved
      0x00, 0x00, 0x00, 0x00, // start address in MSF format (fixed)
           // track descriptor 2
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0xAA,                   // Track Number: Lead-out area
      0x00,                   // Reserved
      BIGLONG( MSC_BlockCount )  // Lead-out start address in MSF format
                              // (variable, depending on the size of track 1)
    };
    
    const U8 SCSI_TOC_LBA1[] = {
           // TOC response header
      0x00, 0x0A,             // Data Length
      0x01,                   // First Track
      0x01,                   // Last Track
            // track descriptor
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0x01,                   // Track Number
      0x00,                   // Reserved
      0x00, 0x00, 0x00, 0x00  // Track Start Address
    };
    
    const U8 SCSI_TOC_MSF0[] = {
           // TOC response header
      0x00, 0x12,             // Data Length
      0x01,                   // First Track
      0x01,                   // Last Track
           // track descriptor 1
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0x01,                   // Track Number
      0x00,                   // Reserved
      0x00, 0x00, 0x02, 0x00, // start address in MSF format (fixed)
           // track descriptor 2
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0xAA,                   // Track Number: Lead-out area
      0x00,                   // Reserved
      0x00,                   // Lead-out start address in MSF format
      LBA2M( MSC_BlockCount ), // (variable, depending on the size of track 1)
      LBA2S( MSC_BlockCount ),
      LBA2F( MSC_BlockCount )
    };
    
    const U8 SCSI_TOC_MSF2[] = {
           // TOC response header
      0x00, 0x2E,             // Data Length
      0x01,                   // First Track
      0x01,                   // Last Track
           // track descriptors
    // Session ADR/CTRL  TNO   POINT  Min Sec Frame  ZERO PMIN PSEC PFRAME
        0x01,    0x14,   0x00, 0xA0, 0x00,0x00,0x00, 0x00,0x01,0x00,0x00,
        0x01,    0x14,   0x00, 0xA1, 0x00,0x00,0x00, 0x00,0x01,0x00,0x00,
        0x01,    0x14,   0x00, 0xA2, 0x00,0x00,0x00, 0x00,LBA2MH( MSC_BlockCount ),
                                                               LBA2SH( MSC_BlockCount ),
                                                                    LBA2FH( MSC_BlockCount ),
        0x01,    0x14,   0x00, 0x01, 0x00,0x00,0x00, 0x00,0x01,0x02,0x00,
    };
    
    void MSC_ReadTOC (void) {
    
      U32 n = (CBW.CB[7] << 8) | CBW.CB[8];  // allocation length
      U8 msf    =  CBW.CB[1] & 0x02;
      U8 format = (CBW.CB[2] & 0x0F) | (CBW.CB[9] >> 6);
    
      if ( (msf == 0) && (format == 0) )
      {
        BulkLen = sizeof(SCSI_TOC_LBA0);
        BulkPtr = (U8 *)SCSI_TOC_LBA0;
      }
      else
      if ( (msf == 0) && (format == 1) )
      {
        BulkLen = sizeof(SCSI_TOC_LBA1);
        BulkPtr = (U8 *)SCSI_TOC_LBA1;
      }
      else
      if ( (msf == 2) && (format == 0) )
      {
        BulkLen = sizeof(SCSI_TOC_MSF0);
        BulkPtr = (U8 *)SCSI_TOC_MSF0;
      }
      else
      if ( (msf == 2) && (format == 2) )
      {
        BulkLen = sizeof(SCSI_TOC_MSF2);
        BulkPtr = (U8 *)SCSI_TOC_MSF2;
      }
      else
      {
        MSC_SetStallEP(MSC_EP_IN);
        CSW.bStatus = CSW_CMD_FAILED;
        sense_error_num = SENSE_INVALID_COMMAND_OPERATION_CODE;
        MSC_SetCSW();
        return;
      }
    
      if ( BulkLen > n ) BulkLen = n;
      DataInTransfer();
    }
    

    Tsuneo

Reply
  • Sorry for my long absence.

    In your last post, you asked about READ TOC (0x43) command.

    There are four types of this command, identified by its parameters
    1) MSF:0, FORMAT:0
    2) MSF:0, FORMAT:1
    3) MSF:1, FORMAT:0
    4) MSF:1, FORMAT:2 (format field is assigned to MSb 2bits of Control byte - legacy form)

    The return data blocks are slightly different each other.

    - Windows and Linux ask 1),2),3)
    - MacOSX retrieves 1),4)

    As of the details of this command, refer to SCSI MMC-6 (mmc6r02g.pdf)
    (search mmc6r02g.pdf)

    Here is the implementation

    //
    // READ TOC implementation
    //
    
    #define BIGLONG(x) (((x) >> 24) & 0xFF), (((x) >> 16) & 0xFF), (((x) >> 8) & 0xFF), ((x) & 0xFF)
    #define BCD(x)     (((((x) / 10) << 4) & 0xF0) | (((x) % 10) & 0x0F))
    
    #define LBA2M(x)   BCD( ((x) + 150) / 75  / 60)
    #define LBA2S(x)   BCD((((x) + 150) / 75) % 60)
    #define LBA2F(x)   BCD( ((x) + 150) % 75)
    
    #define LBA2MH(x)   ( ((x) + 150) / 75  / 60)
    #define LBA2SH(x)   ((((x) + 150) / 75) % 60)
    #define LBA2FH(x)   ( ((x) + 150) % 75)
    
    const U8 SCSI_TOC_LBA0[] = {
           // TOC response header
      0x00, 0x12,             // Data Length
      0x01,                   // First Track
      0x01,                   // Last Track
           // track descriptor 1
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0x01,                   // Track Number
      0x00,                   // Reserved
      0x00, 0x00, 0x00, 0x00, // start address in MSF format (fixed)
           // track descriptor 2
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0xAA,                   // Track Number: Lead-out area
      0x00,                   // Reserved
      BIGLONG( MSC_BlockCount )  // Lead-out start address in MSF format
                              // (variable, depending on the size of track 1)
    };
    
    const U8 SCSI_TOC_LBA1[] = {
           // TOC response header
      0x00, 0x0A,             // Data Length
      0x01,                   // First Track
      0x01,                   // Last Track
            // track descriptor
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0x01,                   // Track Number
      0x00,                   // Reserved
      0x00, 0x00, 0x00, 0x00  // Track Start Address
    };
    
    const U8 SCSI_TOC_MSF0[] = {
           // TOC response header
      0x00, 0x12,             // Data Length
      0x01,                   // First Track
      0x01,                   // Last Track
           // track descriptor 1
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0x01,                   // Track Number
      0x00,                   // Reserved
      0x00, 0x00, 0x02, 0x00, // start address in MSF format (fixed)
           // track descriptor 2
      0x00,                   // Reserved
      0x14,                   // ADR/CONTROL
      0xAA,                   // Track Number: Lead-out area
      0x00,                   // Reserved
      0x00,                   // Lead-out start address in MSF format
      LBA2M( MSC_BlockCount ), // (variable, depending on the size of track 1)
      LBA2S( MSC_BlockCount ),
      LBA2F( MSC_BlockCount )
    };
    
    const U8 SCSI_TOC_MSF2[] = {
           // TOC response header
      0x00, 0x2E,             // Data Length
      0x01,                   // First Track
      0x01,                   // Last Track
           // track descriptors
    // Session ADR/CTRL  TNO   POINT  Min Sec Frame  ZERO PMIN PSEC PFRAME
        0x01,    0x14,   0x00, 0xA0, 0x00,0x00,0x00, 0x00,0x01,0x00,0x00,
        0x01,    0x14,   0x00, 0xA1, 0x00,0x00,0x00, 0x00,0x01,0x00,0x00,
        0x01,    0x14,   0x00, 0xA2, 0x00,0x00,0x00, 0x00,LBA2MH( MSC_BlockCount ),
                                                               LBA2SH( MSC_BlockCount ),
                                                                    LBA2FH( MSC_BlockCount ),
        0x01,    0x14,   0x00, 0x01, 0x00,0x00,0x00, 0x00,0x01,0x02,0x00,
    };
    
    void MSC_ReadTOC (void) {
    
      U32 n = (CBW.CB[7] << 8) | CBW.CB[8];  // allocation length
      U8 msf    =  CBW.CB[1] & 0x02;
      U8 format = (CBW.CB[2] & 0x0F) | (CBW.CB[9] >> 6);
    
      if ( (msf == 0) && (format == 0) )
      {
        BulkLen = sizeof(SCSI_TOC_LBA0);
        BulkPtr = (U8 *)SCSI_TOC_LBA0;
      }
      else
      if ( (msf == 0) && (format == 1) )
      {
        BulkLen = sizeof(SCSI_TOC_LBA1);
        BulkPtr = (U8 *)SCSI_TOC_LBA1;
      }
      else
      if ( (msf == 2) && (format == 0) )
      {
        BulkLen = sizeof(SCSI_TOC_MSF0);
        BulkPtr = (U8 *)SCSI_TOC_MSF0;
      }
      else
      if ( (msf == 2) && (format == 2) )
      {
        BulkLen = sizeof(SCSI_TOC_MSF2);
        BulkPtr = (U8 *)SCSI_TOC_MSF2;
      }
      else
      {
        MSC_SetStallEP(MSC_EP_IN);
        CSW.bStatus = CSW_CMD_FAILED;
        sense_error_num = SENSE_INVALID_COMMAND_OPERATION_CODE;
        MSC_SetCSW();
        return;
      }
    
      if ( BulkLen > n ) BulkLen = n;
      DataInTransfer();
    }
    

    Tsuneo

Children