2012-08-08 11 views
6

Intento emitir un scsi read(10) y write(10) en una SSD. Yo uso this example code como referencia/código básico.Lectura SCSI (10) y escritura (10) con la interfaz genérica SCSI

Ésta es mis SCSI leen:

#define READ_REPLY_LEN 32 
#define READ_CMDLEN 10 
void scsi_read() 
{ 
    unsigned char Readbuffer[ SCSI_OFF + READ_REPLY_LEN ]; 
    unsigned char cmdblk [ READ_CMDLEN ] = 
     {  0x28, /* command */ 
        0, /* lun/reserved */ 
        0, /* lba */ 
        0, /* lba */ 
        0, /* lba */ 
        0, /* lba */ 
        0, /* reserved */ 
        0, /* transfer length */ 
    READ_REPLY_LEN, /* transfer length */ 
        0 };/* reserved/flag/link */ 
    memset(Readbuffer,0,sizeof(Readbuffer)); 
    memcpy(cmd + SCSI_OFF, cmdblk, sizeof(cmdblk)); 

    /* 
    * +------------------+ 
    * | struct sg_header | <- cmd 
    * +------------------+ 
    * | copy of cmdblk | <- cmd + SCSI_OFF 
    * +------------------+ 
    */ 

    if (handle_scsi_cmd(sizeof(cmdblk), 0, cmd, 
         sizeof(Readbuffer) - SCSI_OFF, Readbuffer)) { 
     fprintf(stderr, "read failed\n"); 
     exit(2); 
    } 
    hex_dump(Readbuffer,sizeof(Readbuffer)); 
} 

y este es mi SCSI de escritura:

void scsi_write (void) 
{ 
    unsigned char Writebuffer[SCSI_OFF]; 
    unsigned char cmdblk [] = 
     {  0x2A, /* 0: command */ 
        0, /* 1: lun/reserved */ 
        0, /* 2: LBA */ 
        0, /* 3: LBA */ 
        0, /* 4: LBA */ 
        0, /* 5: LBA */ 
        0, /* 6: reserved */ 
        0, /* 7: transfer length */ 
        0, /* 8: transfer length */ 
        0 };/* 9: control */ 

    memset(Writebuffer,0,sizeof(Writebuffer)); 
    memcpy(cmd + SCSI_OFF, cmdblk, sizeof(cmdblk)); 
    cmd[SCSI_OFF+sizeof(cmdblk)+0] = 'A'; 
    cmd[SCSI_OFF+sizeof(cmdblk)+1] = 'b'; 
    cmd[SCSI_OFF+sizeof(cmdblk)+2] = 'c'; 
    cmd[SCSI_OFF+sizeof(cmdblk)+3] = 'd'; 
    cmd[SCSI_OFF+sizeof(cmdblk)+4] = 'e'; 
    cmd[SCSI_OFF+sizeof(cmdblk)+5] = 'f'; 
    cmd[SCSI_OFF+sizeof(cmdblk)+6] = 'g'; 
    cmd[SCSI_OFF+sizeof(cmdblk)+7] = 0; 
    /* 
    * +------------------+ 
    * | struct sg_header | <- cmd 
    * +------------------+ 
    * | copy of cmdblk | <- cmd + SCSI_OFF 
    * +------------------+ 
    * | data to write | 
    * +------------------+ 
    */ 

    if (handle_scsi_cmd(sizeof(cmdblk), 8, cmd, 
         sizeof(Writebuffer) - SCSI_OFF, Writebuffer)) { 
     fprintf(stderr, "write failed\n"); 
     exit(2); 
    } 
} 

En el siguiente ejemplo que hago

  1. SCSI leen
  2. SCSI escriben
  3. SCSI leen

Y imprimen los hexdumps de los datos que se escribe (SCSI escritura) y lo que se lee (SCSI leen)

Read(10) 
[0000] 00 00 00 44 00 00 00 44 00 00 00 00 00 00 00 00 ...D...D ........ 
[0010] 00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ 
[0020] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ 
[0030] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ 
[0040] 00 00 00 00           .... 

Write(10): 
[0000] 00 00 00 00 00 00 00 24 00 00 00 00 00 00 00 00 ........ ........ 
[0010] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ 
[0020] 00 00 00 00 2A 00 00 00 00 00 00 00 00 00 41 62 ........ ......Ab 
[0030] 63 64 65 66 67 00         cdefg. 

Read(10): 
[0000] 00 00 00 44 00 00 00 44 00 00 00 00 00 00 00 00 ...D...D ........ 
[0010] 04 00 20 00 70 00 02 00 00 00 00 0A 00 00 00 00 ....p... ........ 
[0020] 04 00 00 00 41 62 63 64 65 66 67 00 00 00 00 00 ....Abcd efg..... 
[0030] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ 
[0040] 00 00 00 00           .... 

espués de gestión de los tres órdenes de nuevo, que debería leer Abcdefg con la primera lectura. ¿Derecha? Pero ejecutarlos de nuevo no cambia nada. Ahora puede suponer que la memoria que uso aún conserva los datos de funciones anteriores, pero obtengo el mismo resultado aunque ejecuto memset(Readbuff,0,sizeof(Readbuff)) antes de que ocurra el sys_read().

Supuse que quizás el LBA que trato de escribir tiene prohibido escribir, y leo el caché. Pero interar en LBA Adresses desde 0x00-0xFF no cambia nada - Eso significa que leo los mismos datos (Abcdefg).

¿Conoces una implementación de ejemplo de lectura o escritura scsi con la interfaz genérica scsi?

Respuesta

4

En SCSI, las unidades del LBA y la longitud de transferencia están en bloques, a veces llamados sectores. Esto es casi siempre 512 bytes. Entonces, no puedes leer o escribir solo 32 bytes. Como mínimo, tendrá que hacer 512 bytes == un bloque. Este punto es la mayor parte de lo que necesita corregir.

La longitud de su transferencia es cero en su implementación scsi_write, por lo que no va a escribir ningún dato.

Debe utilizar diferentes almacenamientos intermedios para el CDB y los datos de escritura/lectura. Sospecho que la confusión acerca de estos búferes está llevando a su implementación a escribir más allá del final de una de sus matrices asignadas estáticamente y sobre su ReadBuffer. Ejecútelo bajo valgrind y vea lo que aparece.

Y, por último, muchas cosas podrían salir mal en lo que sea que esté en handle_scsi_cmd. Puede ser complicado configurar la transferencia de datos ... en particular, asegúrese de estar seguro de la dirección en que se encuentran los datos en el dxfer_direction del encabezado de E/S: SG_DXFER_TO_DEV para escritura, SG_DXFER_FROM_DEV para lectura.

Vea este ejemplo de cómo leer (16). Esto es más acorde con lo que estás tratando de lograr.

http://fossies.org/linux/misc/sg3_utils-1.33.tgz:a/sg3_utils-1.33/examples/sg_simple16.c

+0

muchas gracias. El ejemplo de sg3_utils me ayudó mucho y funciona ahora. – samuirai