Page suivantePage pr�c�denteTable des mati�res

8. La structure d'en-t�te

La structure d'en-t�te struct sg_header est utilis�e comme couche de contr�le entre l'application et le pilote du noyau. Abordons maintenant le d�tail de ses composants.

int pack_len

d�finit la taille du bloc envoy� au pilote. Cette valeur est d�finie dans le noyau pour une utilisation interne.

int reply_len

d�finit la taille du bloc accept� en r�ponse. Cette valeur est d�finie du c�t� application.

int pack_id

Ce champ facilite l'appariement des r�ponses aux requ�tes. L'application peut fournir un identifiant unique � chaque requ�te. Supposons que vous ayez �crit un certain nombre de commandes (disons 4) pour un p�riph�rique. Celles-ci peuvent fonctionner en parall�le, l'une d'entre elles �tant la plus rapide. Lors de la lecture des r�ponses par quatre "read", celles-ci ne sont pas forc�ment dans l'ordre des requ�tes. Pour identifier la r�ponse correcte pour une requ�te, on peut utiliser le champ pack_id. Habituellement, cette valeur est incr�ment�e apr�s chaque requ�te (et boucle �ventuellement). Le nombre maximum de requ�tes �mises simultan�ment est limit� par le noyau � SG_MAX_QUEUE (en g�n�ral, quatre).

int result

C'est la valeur du r�sultat d'un appel � read ou � write. Elle est (parfois) d�finie par la le pilote g�n�rique (partie noyau). Il est plus prudent de le positionner � 9 avant l'appel � write. Ces codes sont d�clar�s dans le fichier errno.h (0 indique un r�sultat correct).

unsigned int twelve_byte:1

Ce champ n'est n�cessaire que lors de l'utilisation de commandes sp�cifiques non standard (dans la plage 0xc0 � 0xff). Lorsque la longueur de ces commandes est de 12 octets au lieu de 10, il faut positionner ce champ � 1 avant l'appel � write. D'autres longueurs de commandes ne peuvent �tre utilis�es. Ce champ est positionn� par l'application.

unsigned char sense_buffer[16]

Ce tampon est positionn� apr�s l'ex�cution d'une commande (apr�s un appel � read()) et contient le code de "sensation" SCSI (SCSI send code. NdT. : dans le reste du document, on utilisera simplement la formule "tampon SCSI"). Certains r�sultats de commandes doivent �tre lus � cet emplacement (par exemple pour TESTUNITREADY). Il ne contient habituellement que des octets nuls. La valeur de ce champ est positionn�e par le pilote g�n�rique (partie noyau).

L'exemple de fonction qui suit s'interface directement avec le pilote g�n�rique du noyau. Il d�finit la structure d'en-t�te, envoie la commande par write, lit le r�sultat par read et effectue un nombre (limit�) de contr�les d'erreurs. Les donn�es du tampon SCSI sont disponibles dans le tampon de sortie (sauf si un pointeur nul a �t� fourni, auquel cas elles se trouvent dans le tampon d'entr�e). Nous l'utiliserons dans les exemples qui suivent.

Note : positionnez la valeur de DEVICE � celle qui correspond � votre mat�riel.

#define DEVICE "/dev/sgc"
/* Programme d'exemple utilisant l'interface SCSI g�n�rique */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <scsi/sg.h>
#define SCSI_OFF sizeof(struct sg_header)
static  unsigned char cmd[SCSI_OFF + 18];       /* tampon de commande SCSI */
int     fd;                                     /*
 * descripteur de peripherique/
 * fichier SCSI
 */
/* traite une commande SCSI compl�te. Utilise l'interface g�n�rique */
static int handle_SCSI_cmd(unsigned cmd_len,     /* longueur de commande  */
 unsigned in_size,     /* taille data en entr�e */
 unsigned char *i_buff,/* tampon d'entr�e       *//
 unsigned out_size,    /* taille data en sortie */
 unsigned char *o_buff /* tampon de sortie      */
 )
{
 int status = 0;
 struct sg_header *sg_hd;
 /* v�rifications de s�curit� */
 if (!cmd_len) return -1;            /* n�cessite que cmd_len != 0 */
 if (!i_buff) return -1;             /* n�cessite que i_buff != NULL */
#ifdef SG_BIG_BUFF
 if (SCSI_OFF + cmd_len + in_size> SG_BIG_BUFF) return -1;
 if (SCSI_OFF + out_size> SG_BIG_BUFF) return -1;
#else
 if (SCSI_OFF + cmd_len + in_size> 4096) return -1;
 if (SCSI_OFF + out_size> 4096) return -1;
#endif
 if (!o_buff) out_size = 0;          /* pas de tampon de sortie, pas de */
 /* taille                          */
 /* construction de l'en-t�te g�n�rique de p�riph�rique */
 sg_hd = (struct sg_header *) i_buff;
 sg_hd->reply_len   = SCSI_OFF + out_size;
 sg_hd->twelve_byte = cmd_len == 12;
 sg_hd->result = 0;
#if     0
 sg_hd->pack_len    = SCSI_OFF + cmd_len + in_size; /* non indispensable */
 sg_hd->pack_id;     /* inutilise */
 sg_hd->other_flags; /* inutilise */
#endif
 /* envoi de la commande */
 status = write( fd, i_buff, SCSI_OFF + cmd_len + in_size );
 if ( status < 0 || status != SCSI_OFF + cmd_len + in_size ||
 sg_hd->result ) {
 /* condition d'erreur */
 fprintf( stderr, "write(generic) resultat = 0x%x cmd = 0x%x\n",
 sg_hd->result, i_buff[SCSI_OFF] );
 perror("");
 return status;
 }
 if (!o_buff) o_buff = i_buff; /* contr�le du pointeur du tampon */
 /* r�cup�ration du r�sultat */
 status = read( fd, o_buff, SCSI_OFF + out_size);
 if ( status < 0 || status != SCSI_OFF + out_size || sg_hd->result ) {
 /* condition d'erreur */
 fprintf( stderr, "read(generic) statut = 0x%x, resultat = 0x%x, "
 "cmd = 0x%x\n",
 status, sg_hd->result, o_buff[SCSI_OFF] );
 fprintf( stderr, "read(generic) tampon SCSI "
 "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
 sg_hd->sense_buffer[0],         sg_hd->sense_buffer[1],
 sg_hd->sense_buffer[2],         sg_hd->sense_buffer[3],
 sg_hd->sense_buffer[4],         sg_hd->sense_buffer[5],
 sg_hd->sense_buffer[6],         sg_hd->sense_buffer[7],
 sg_hd->sense_buffer[8],         sg_hd->sense_buffer[9],
 sg_hd->sense_buffer[10],        sg_hd->sense_buffer[11],
 sg_hd->sense_buffer[12],        sg_hd->sense_buffer[13],
 sg_hd->sense_buffer[14],        sg_hd->sense_buffer[15]);
 if (status < 0)
 perror("");
 }
 /* A-t-on ce qu'on attendait ? */
 if (status == SCSI_OFF + out_size) status = 0; /* on a tout */
 return status;  /* 0 indique que tout est bon */
}

Bien que cela puisse sembler quelque peu complexe au premier abord, une grande partie du code est d�di�e aux contr�le et d�tection d'erreurs (ce qui est utile m�me une fois que le code fonctionne correctement).

Handle_SCSI_cmd pr�sente une forme g�n�ralis�e pour tous les types de commandes SCSI, qui correspondent � l'une des cat�gories qui suivent :

 Mode de donn�es            |    Exemple de commande
=============================================================
ni entr�e ni sortie de donn�es  |     test d'unite pr�te
pas d'entr�e, sortie de donn�es |      requ�te, lecture
entr�e de donn�es, pas de sortie| selection de mode, �criture
 entr�e et sortie de donn�es   |     d�tection de mode


Page suivantePage pr�c�denteTable des mati�res

Hosting by: Hurra Communications GmbH
Generated: 2007-01-26 18:01:15