2012-08-08 8 views
6

Próbuję wydać scsi read(10) i write(10) na dysk SSD. Używam this example code jako kodu odniesienia/podstawowego.SCSI Read (10) i Write (10) z interfejsem standardowym SCSI

To jest moje SCSI przeczytać:

#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)); 
} 

A to moja SCSI zapisu:

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); 
    } 
} 

W poniższym przykładzie zrobić

  1. SCSI czytać
  2. SCSI napisać
  3. SCSI czytać

I wydrukować zrzutów heksowych danych, które jest napisane (SCSI zapisu) i co jest czytane (SCSI czytać)

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           .... 

fter ponownie uruchomiony trzy polecenia, powinienem czytać Abcdefg z pierwszym czytaniem. Dobrze? Ale ich ponowne uruchomienie nic nie zmienia. Można teraz założyć, że pamięć, której używam, ma nadal dane z poprzednich funkcji, ale otrzymuję ten sam wynik, mimo że uruchamiam memset(Readbuff,0,sizeof(Readbuff)) przed zdarzeniem sys_read().

Zakładam, że LBA, którą próbuję napisać, może nie wolno pisać, a ja czytam pamięć podręczną. Jednak interakcja z adresami LBA z 0x00-0xFF nic nie zmienia - Oznacza to, że czytam te same dane (Abcdefg).

Czy znasz przykładową implementację SCSI do odczytu lub zapisu z interfejsem generycznym scsi?

Odpowiedz

4

W SCSI jednostki LBA i długość transferu są w blokach, czasami nazywane sektorami. To prawie zawsze 512 bajtów. Tak więc nie można odczytać lub zapisać tylko 32 bajtów. Co najmniej, będziesz musiał zrobić 512 bajtów == jeden blok. Ten jeden punkt to większość tego, co musisz naprawić.

Twoja długość transferu wynosi zero w twojej implementacji scsi_write, więc w rzeczywistości nie będzie zapisywać żadnych danych.

Powinieneś używać różnych buforów dla CDB i danych do zapisu/odczytu. Podejrzewam, że zamieszanie wokół tych buforów prowadzi twoją implementację do pisania po zakończeniu jednej z twoich statycznie przydzielonych tablic i nad ReadBufferem. Uruchom go pod valgrind i zobacz, co się pojawi.

I wreszcie, wiele może pójść źle w tym, co jest w handle_scsi_cmd. Konfigurowanie transferu danych może być trudne ... w szczególności upewnij się, że jesteś w prostej linii, w którą stronę dane idą w kierunku dxfer_direction nagłówka I/O: SG_DXFER_TO_DEV do zapisu, SG_DXFER_FROM_DEV do odczytu.

Sprawdź ten przykład, jak wykonać odczyt (16). Jest to bardziej zgodne z tym, co próbujesz osiągnąć.

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

+0

bardzo dziękuję. Przykład sg3_utils bardzo mi pomógł i działa teraz. – samuirai