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.
d�finit la taille du bloc envoy� au pilote. Cette valeur est d�finie dans le noyau pour une utilisation interne.
d�finit la taille du bloc accept� en r�ponse. Cette valeur est d�finie du c�t� application.
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).
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).
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.
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
Hosting by: Hurra Communications GmbH
Generated: 2007-01-26 18:01:15