Le HOWTO Linux de la programmation SCSI
Heiko Eissfeldt
[email protected] (version francaise
: Thierry Danis
[email protected], le 26 Janvier 1998,
largement basee sur la traduction de la version v1.4 faite
par Bernard Choppy
[email protected]).
v1.5, 7 Juin 1996
Ce document traite de la programmation de l'interface SCSI generique
de Linux.
11.. LLeess nnoouuvveeaauutteess
Les interfaces des nouveaux noyaux ont un peu change. Le chapitre
'rescrutation des peripheriques' est concerne par ces changements. Il
est maintenant possible d'ajouter et d'enlever des peripheriques SCSI
a chaud et a la volee.
A partir de la version 1.3.98, certains fichiers d'inclusion
importants ont ete deplaces ou decoupes (sg.h and scsi.h).
Quelques bugs idiots ont ete remplaces par d'autres.
22.. IInnttrroodduuccttiioonn
Ce document est un guide d'installation et de programmation de
l'interface generique SCSI de Linux.
Il traite des prerequis du noyau, de l'organisation des peripheriques,
et de l'interaction de base avec ces derniers. Quelques exemples
simples de programmation en C sont inclus. Pour de plus amples details
sur la norme SCSI et les informations associees, reportez-vous a
l'annexe de ce document.
Note : la version texte simple de ce document ne dispose pas de
references croisees (indiquees par ``'').
33.. QQuu''eesstt--ccee qquuee ll''iinntteerrffaaccee SSCCSSII ggeenneerriiqquuee ??
L'interface generique SCSI a ete faite pour fournir un acces general a
des peripheriques SCSI (eventuellement exotiques). Elle a ete
developpee par Lawrence Foard (
[email protected]) et sponsorisee
par Killy Corporation (voir les commentaires du fichier
drivers/scsi/sg.h).
Cette interface permet a des programmes applicatifs (c'est-a-dire hors
du noyau) d'acceder aux fonctionnalites de certains peripheriques. Le
developpement de pilotes dans le noyau, plus risques et difficiles a
mettre au point, n'est ainsi plus necessaire.
Neanmoins, si le peripherique n'est pas correctement programme, il est
possible de bloquer le bus SCSI, le pilote, ou le noyau. C'est
pourquoi il est important de programmer correctement le pilote
generique, et de commencer par sauvegarder tous les fichiers afin
d'eviter une perte de donnees. Une autre precaution utile est de faire
un sync avant de lancer vos programmes pour garantir l'ecriture de
tous les tampons sur le disque ; cela limitera la perte de donnees en
cas de blocage du systeme.
Un autre avantage du pilote generique est que, aussi longtemps que
l'interface elle-meme ne change pas, toutes les applications restent
independantes des nouveaux developpements du noyau. En comparaison,
les pilotes de bas niveau du noyau doivent suivre les evolutions
internes de celui-ci.
Typiquement, le pilote generique est utilise pour communiquer avec les
nouveaux equipements SCSI qui exigent l'ecriture d'applications
utilisateur specifiques pour tirer avantage de leurs fonctionalites
(par exemple les scanners, les imprimantes, le juke-boxes de CDROM).
L'interface generique permet un developpement rapide de ces
applications.
44.. QQuuee ffaauutt--iill ppoouurr ll''uuttiilliisseerr ??
44..11.. CCoonnffiigguurraattiioonn dduu nnooyyaauu
Il vous faut evidemment un adapteur SCSI reconnu. De plus, votre noyau
doit etre compile avec le support du pilote generique, en plus de
celui pour votre adapteur. La configuration du noyau Linux (par make
config sous /usr/src/linux) doit ressembler a :
...
*
* SCSI support
*
SCSI support? (CONFIG_SCSI) [n] y
*
* SCSI support type (disk, tape, CDrom)
*
...
Scsi generic support (CONFIG_CHR_DEV_SG) [n] y
*
* SCSI low-level drivers
*
...
Si le noyau est modulable, vous pouvez tout aussi bien utiliser les
modules.
44..22.. FFiicchhiieerrss ssppeecciiaauuxx
Le pilote generique utilise ses propres fichiers speciaux. Ils peuvent
etre crees par le script MAKEDEV, que l'on trouve habituellement dans
le repertoire /dev. La commande MAKEDEV sg cree les fichiers suivants
:
crw------- 1 root system 21, 0 Aug 20 20:09 /dev/sga
crw------- 1 root system 21, 1 Aug 20 20:09 /dev/sgb
crw------- 1 root system 21, 2 Aug 20 20:09 /dev/sgc
crw------- 1 root system 21, 3 Aug 20 20:09 /dev/sgd
crw------- 1 root system 21, 4 Aug 20 20:09 /dev/sge
crw------- 1 root system 21, 5 Aug 20 20:09 /dev/sgf
crw------- 1 root system 21, 6 Aug 20 20:09 /dev/sgg
crw------- 1 root system 21, 7 Aug 20 20:09 /dev/sgh
| |
numeros majeur, mineur
Notez que ces fichiers sont des fichiers en mode caractere pour
permettre les acces directs. Sur certains systemes, ces fichiers
peuvent s'appeler /dev/{sg0,sg1,...}, en fonction de votre
installation. Vous devrez donc adapter les exemples qui suivant en
consequence.
44..33.. OOrrggaanniissaattiioonn ddeess ppeerriipphheerriiqquueess
Les fichiers speciaux sont affectes dynamiquement aux ID/LUN (LUN :
Unite logique) du bus SCSI. Les peripheriques sont consecutivement
alloues selon les unites logiques de chaque peripherique detecte lors
de la scrutation du bus, les plus petits LUN/ID/BUS etant alloues en
premier. Le noyau commence par le premier controleur SCSI et continue
sans interruption avec tous les autres adapteurs. Cette etape est
actuellement realisee lors de l'initialisation du pilote SCSI.
Par exemple, si vous avez trois peripheriques SCSI configures avec les
ID 1, 3 et 5 sur le premier bus SCSI (chacun avec une seule unite
logique), l'affectation sera la suivante :
/dev/sga -> SCSI id 1
/dev/sgb -> SCSI id 3
/dev/sgc -> SCSI id 5
Si vous ajoutez maintenant un nouveau peripherique d'identificateur 4,
l'organisation apres la prochaine scrutation du bus sera :
/dev/sga -> SCSI id 1
/dev/sgb -> SCSI id 3
/dev/sgc -> SCSI id 4
/dev/sgd -> SCSI id 5
Notez le changement pour l'identificateur 5 - le peripherique
correspondant n'est plus affecte a /dev/sgc, mais a /dev/sgd.
Les noyaux plus recents permettent de changer cet ordre.
44..33..11.. IInnsseerrttiioonn eett rreettrraaiitt ddyynnaammiiqquueess ddee ppeerriipphheerriiqquueess SSCCSSII
Dans les noyaux recents avec un systeme de fichier /proc monte, il est
possible de retirer et d'ajouter un peripherique libre (non-busy) a la
volee.
Pour enlever un peripherique SCSI :
echo "scsi remove-single-device a b c d" > /proc/scsi/scsi
De la meme maniere, ajouter un peripherique SCSI se fera par :
echo "scsi add-single-device a b c d" > /proc/scsi/scsi
Ici, a, b, c et d sont definis de la facon suivante :
a == identificateur de l'adapteur (le premier a l'id 0)
b == canal SCSI sur l'adapteur (le premier a le numero 0)
c == ID
d == LUN (la premiere ayant le numero 0)
Ainsi, si nous desirons intervertir l'affectation des fichiers
/dev/sgc et /dev/sgd de l'exemple precedent, nous pouvons faire :
echo "scsi remove-single-device 0 0 4 0" > /proc/scsi/scsi
echo "scsi remove-single-device 0 0 5 0" > /proc/scsi/scsi
echo "scsi add-single-device 0 0 5 0" > /proc/scsi/scsi
echo "scsi add-single-device 0 0 4 0" > /proc/scsi/scsi
puisque les peripheriques generiques sont alloues dans leur ordre
d'insertion.
Si vous voulez ajouter de nouveaux peripheriques sur le bus SCSI,
gardez a l'esprit qu'un nombre limite d'entrees supplementaires a ete
attribue. La memoire a ete allouee au demarrage, et il n'y a de place
que pour 2 entrees supplementaires.
55.. LLee gguuiiddee dduu pprrooggrraammmmeeuurr
Les sections qui suivent s'adressent aux programmeurs desireux
d'utiliser l'interface generique SCSI dans leurs propres applications.
Nous allons donner un exemple permettant d'acceder a un peripherique
SCSI par le biais des commandes INQUIRY et TESTUNITREADY.
Lors de l'utilisation de ces exemples, prenez garde a ce qui suit :
+o l'emplacement des fichiers d'inclusion sg.h et scsi.h a change a
partir du noyau 1.3.98. Ces fichiers se trouvent maintenant a
/usr/src/linux/include/scsi, qui devrait etre un lien vers
/usr/include/scsi. Dans les versions precedentes, ils se trouvaient
dans /usr/src/linux/drivers/scsi. Nous supposerons dans la suite
que vous utilisez un de ces noyaux recents.
+o l'interface generique SCSI a ete etendue dans la version 1.1.68 du
noyau. Les exemples necessitent au moins cette version. En
revanche, evitez d'utiliser les noyaux de 1.1.77 a 1.1.89 qui
disposent d'une interface generique SCSI defectueuse.
+o la constante DEVICE de la section qui decrit le peripherique accede
doit etre positionnee en fonction de vos peripheriques disponibles
(reportez-vous au chapitre ``La structure d'en-tete'').
66.. VVuuee dd''eennsseemmbbllee ddee llaa pprrooggrraammmmaattiioonn ddeess ppeerriipphheerriiqquueess
Le fichier d'inclusion include/scsi/sg.h contient une description de
l'interface (celle du noyau 1.3.98) :
struct sg_header
{
/*
* longueur du paquet entrant (y compris en-tete)
*/
int pack_len;
/*
* taille max de la reponse attendue
*/
int reply_len;
/*
* numero d'id du paquet
*/
int pack_id;
/*
* 0 == ok,
* pour les autres, voir les codes pour errno
*/
int result;
/*
* Force la longueur a 12 pour les commandes des
* groupes 6 & 7
*/
unsigned int twelve_byte:1;
/*
* pour utilisation future
*/
unsigned int other_flags:31;
/*
* uniquement utilise lors des lectures
*/
unsigned char sense_buffer[16];
/*
* la commande suit puis les donnees de la
* commande
* .............
*/
Cette structure decrit comment une commande SCSI doit etre traitee et
disposer de place pour le resultat de son execution. Les composants
individuels de la structure seront abordes plus loin a la section ``La
structure d'en-tete''.
La methode generale pour echanger des donnees avec le pilote generique
est la suivante : pour envoyer une commande a un peripherique
generique ouvert, il faut ecrire (write()) un bloc compose des trois
parties suivantes :
struct sg_header
commande SCSI
donnees envoyees avec la commande
Pour obtenir le resultat d'une commande, il faut lire (read()) un bloc
composes des parties suivantes (similaires a l'ecriture) :
struct sg_header
donnees en entree
Il s'agit d'une vue generale de la procedure. Les sections qui suivent
decrivent chaque etape en detail.
NOTE : jusqu'a de recentes versions du noyau, il etait necessaire de
bloquer le signal SIGINT entre les appels write() et le read()
correspondant (par exemple, par sigprocmask()). Un retour apres la
partie ecriture sans lecture pour recuperer les resultats va bloquer
les acces suivants. Le blocage du signal n'a pas encore ete inclus
dans le code des exemples. Evitez donc d'envoyer un SIGINT (par ^C,
par exemple) lors du test de ceux-ci.
77.. OOuuvveerrttuurree dduu ppeerriipphheerriiqquuee
Un peripherique generique doit etre ouvert avant tout acces en lecture
ou en ecriture :
int fd = open(nom_du_peripherique, O_RDWR);
(ce qui precede s'applique aussi pour les materiels en lecture seule
comme les lecteurs de CDROM).
Il faut executer un write pour envoyer la commande et un read pour en
lire le resultat. En cas d'erreur, le code de retour est negatif (se
reporter a la section ``Traitement d'erreurs'' pour la liste complete
des codes de retour).
88.. LLaa ssttrruuccttuurree dd''eenn--tteettee
La structure d'en-tete struct sg_header est utilisee comme couche de
controle entre l'application et le pilote du noyau. Abordons
maintenant le detail de ses composants.
iinntt ppaacckk__lleenn
definit la taille du bloc envoye au pilote. Cette valeur est
definie dans le noyau pour une utilisation interne.
iinntt rreeppllyy__lleenn
definit la taille du bloc accepte en reponse. Cette valeur est
definie du cote application.
iinntt ppaacckk__iidd
Ce champ facilite l'appariement des reponses aux requetes.
L'application peut fournir un identifiant unique a chaque
requete. Supposons que vous ayez ecrit un certain nombre de
commandes (disons 4) pour un peripherique. Celles-ci peuvent
fonctionner en parallele, l'une d'entre elles etant la plus
rapide. Lors de la lecture des reponses par quatre "read",
celles-ci ne sont pas forcement dans l'ordre des requetes. Pour
identifier la reponse correcte pour une requete, on peut
utiliser le champ pack_id. Habituellement, cette valeur est
incrementee apres chaque requete (et boucle eventuellement). Le
nombre maximum de requetes emises simultanement est limite par
le noyau a SG_MAX_QUEUE (en general, quatre).
iinntt rreessuulltt
C'est la valeur du resultat d'un appel a read ou a write. Elle
est (parfois) definie par la le pilote generique (partie noyau).
Il est plus prudent de le positionner a 9 avant l'appel a write.
Ces codes sont declares dans le fichier errno.h (0 indique un
resultat correct).
uunnssiiggnneedd iinntt ttwweellvvee__bbyyttee::11
Ce champ n'est necessaire que lors de l'utilisation de commandes
specifiques non standard (dans la plage 0xc0 a 0xff). Lorsque la
longueur de ces commandes est de 12 octets au lieu de 10, il
faut positionner ce champ a 1 avant l'appel a write. D'autres
longueurs de commandes ne peuvent etre utilisees. Ce champ est
positionne par l'application.
uunnssiiggnneedd cchhaarr sseennssee__bbuuffffeerr[[1166]]
Ce tampon est positionne apres l'execution d'une commande (apres
un appel a 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 resultats de
commandes doivent etre lus a cet emplacement (par exemple pour
TESTUNITREADY). Il ne contient habituellement que des octets
nuls. La valeur de ce champ est positionnee par le pilote
generique (partie noyau).
L'exemple de fonction qui suit s'interface directement avec le pilote
generique du noyau. Il definit la structure d'en-tete, envoie la
commande par write, lit le resultat par read et effectue un nombre
(limite) de controles d'erreurs. Les donnees du tampon SCSI sont
disponibles dans le tampon de sortie (sauf si un pointeur nul a ete
fourni, auquel cas elles se trouvent dans le tampon d'entree). Nous
l'utiliserons dans les exemples qui suivent.
Note : positionnez la valeur de DEVICE a celle qui correspond a votre
materiel.
#define DEVICE "/dev/sgc"
/* Programme d'exemple utilisant l'interface SCSI generique */
#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 complete. Utilise l'interface generique */
static int handle_SCSI_cmd(unsigned cmd_len, /* longueur de commande */
unsigned in_size, /* taille data en entree */
unsigned char *i_buff,/* tampon d'entree *//
unsigned out_size, /* taille data en sortie */
unsigned char *o_buff /* tampon de sortie */
)
{
int status = 0;
struct sg_header *sg_hd;
/* verifications de securite */
if (!cmd_len) return -1; /* necessite que cmd_len != 0 */
if (!i_buff) return -1; /* necessite 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-tete generique de peripherique */
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; /* controle du pointeur du tampon */
/* recuperation du resultat */
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 dediee aux controle et detection
d'erreurs (ce qui est utile meme une fois que le code fonctionne
correctement).
Handle_SCSI_cmd presente une forme generalisee pour tous les types de
commandes SCSI, qui correspondent a l'une des categories qui suivent :
Mode de donnees | Exemple de commande
=============================================================
ni entree ni sortie de donnees | test d'unite prete
pas d'entree, sortie de donnees | requete, lecture
entree de donnees, pas de sortie| selection de mode, ecriture
entree et sortie de donnees | detection de mode
99.. EExxeemmppllee ddee ccoommmmaannddee ddee rreeqquueettee
L'une des commandes SCSI de base est INQUIRY, utilisee pour identifier
les type et constructeur du peripherique. Voici la definition issue de
la specification SCSI-2 (se reporter au standard SCSI-2 pour les
details).
Table 44: Commande INQUIRY
+=====-========-========-========-========-========-========-========-========+
| Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|Octet| | | | | | | | |
|=====+=======================================================================|
| 0 | Code operation (12h) |
|-----+-----------------------------------------------------------------------|
| 1 |Numero d'unite logique | Reserve | EVPD |
|-----+-----------------------------------------------------------------------|
| 2 | Code page |
|-----+-----------------------------------------------------------------------|
| 3 | Reserve |
|-----+-----------------------------------------------------------------------|
| 4 | Taille d'allocation |
|-----+-----------------------------------------------------------------------|
| 5 | Controle |
+=============================================================================+
Les donnees en sortie ont l'allure suivante :
Table 45: Format standard de donnees INQUIRY
+=====-========-========-========-========-========-========-========-========+
| Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|Octet| | | | | | | | |
|=====+==========================+============================================|
| 0 | Qualificateur de periph. | Type de peripherique |
|-----+-----------------------------------------------------------------------|
| 1 | RMB | Modificateur de type de peripherique |
|-----+-----------------------------------------------------------------------|
| 2 | Version ISO | Version ECMA | Version approuvee ANSI |
|-----+-----------------+-----------------------------------------------------|
| 3 | AENC | TrmIOP | Reserve | Format de donnees en reponse |
|-----+-----------------------------------------------------------------------|
| 4 | Longueur additionnelle (n-4) |
|-----+-----------------------------------------------------------------------|
| 5 | Reserve |
|-----+-----------------------------------------------------------------------|
| 6 | Reserve |
|-----+-----------------------------------------------------------------------|
| 7 | RelAdr | WBus32 | WBus16 | Sync | Linked |Reserve | CmdQue | SftRe |
|-----+-----------------------------------------------------------------------|
| 8 | (MSB) |
|- - -+--- Identification de constructeur ---|
| 15 | (LSB) |
|-----+-----------------------------------------------------------------------|
| 16 | (MSB) |
|- - -+--- Identification de produit ---|
| 31 | (LSB) |
|-----+-----------------------------------------------------------------------|
| 32 | (MSB) |
|- - -+--- Niveau de revision du produit ---|
| 35 | (LSB) |
|-----+-----------------------------------------------------------------------|
| 36 | |
|- - -+--- Specifique constructeur ---|
| 55 | |
|-----+-----------------------------------------------------------------------|
| 56 | |
|- - -+--- Reserve ---|
| 95 | |
|=====+=======================================================================|
| | Parametres specifiques constructeur |
|=====+=======================================================================|
| 96 | |
|- - -+--- Specifique constructeur ---|
| n | |
+=============================================================================+
L'exemple qui suit utilise la fonction de bas niveau handle_SCSI_cmd
pour effectuer la commande SCSI INQUIRY.
Tout d'abord, nous ajoutons le bloc de commande a l'en-tete generique,
puis appelons handle_SCSI_cmd. Notez que l'argument taille de tampon
en sortie de l'appel handle_SCSI_cmd exclut la taille de l'en-tete
generique. Apres l'execution de la commande, le tampon de sortie
contient les informations, sauf si une erreur s'est produite.
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
#define INQUIRY_REPLY_LEN 96
#define INQUIRY_VENDOR 8 /* decalage vers le nom du constructeur */
/* recherche du constructeur et du modele */
static unsigned char *Inquiry ( void )
{
unsigned char Inqbuffer[ SCSI_OFF + INQUIRY_REPLY_LEN ];
unsigned char cmdblk [ INQUIRY_CMDLEN ] =
{ INQUIRY_CMD, /* commande */
0, /* lun/reserve */
0, /* code de page */
0, /* reserve */
INQUIRY_REPLY_LEN, /* longueur allocation */
0 };/* reserve / drapeau / lien */
memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
/*
* +------------------+
* | struct sg_header | <- commande
* +------------------+
* | copie de cmdblk | <- commande + SCSI_OFF
* +------------------+
*/
if (handle_SCSI_cmd(sizeof(cmdblk), 0, cmd,
sizeof(Inqbuffer) - SCSI_OFF, Inqbuffer )) {
fprintf( stderr, "La requete a echoue\n" );
exit(2);
}
return (Inqbuffer + SCSI_OFF);
}
L'exemple ci-dessus suit cette structure. La fonction Inquiry recopie
son bloc de commande apres l'en-tete generique (donne par SCSI_OFF).
Les donnees en entree sont absentes de cette commande. handle_SCSI_cmd
definit la structure d'en-tete. Nous pouvons maintenant implementer la
fonction main qui complete ce programme d'exemple fonctionnel.
void main( void )
{
fd = open(DEVICE, O_RDWR);
if (fd < 0) {
fprintf( stderr, "Il faut les permissions lecture/ecriture pour "DEVICE".\n" );
exit(1);
}
/* affiche certains champs du resultat de Inquiry() */
printf( "%s\n", Inquiry() + INQUIRY_VENDOR );
}
Tout d'abord, nous ouvrons le peripherique, controlons l'absence
d'erreur, puis appelons la fonction de haut niveau. Ensuite, nous
affichons des resultats sous une forme lisible, dont le constructeur,
le produit et la version.
Note : il y a plus d'informations dans le resultat de "Inquiry" que ce
que fournit ce petit programme. Il vous est loisible d'etendre celui-
ci au type de peripherique, version ANSI, etc. Le type de peripherique
a une importance particuliere, puisqu'il determine les jeux de
commandes obligatoires et facultatives pour celui-ci. Si vous ne
souhaitez pas le programmer vous-meme, Eric Youngdale a realise le
programme scsiinfo, qui fournit a peu pres toute information
disponible pour un peripherique SCSI. Cherchez sur tsx-11.mit.edu dans
pub/Linux/ALPHA/scsi (NdT : on trouvera ce programme sur les sites
miroirs francais, comme ftp.ibp.fr, a un emplacement similaire).
1100.. LLee ""ttaammppoonn SSCCSSII""
Les commandes qui ne renvoient pas de donnees peuvent fournir des
informations d'etat a l'aide du tampon SCSI (qui fait partie
integrante de la structure d'en-tete). Les donnees d'etat sont
disponibles lorsque la commande precedente s'est terminee avec un
statut "CHECK CONDITION". Dans ce cas, le noyau rapatrie
automatiquement les donnees d'etat a l'aide d'une commande "REQUEST
SENSE". Sa structure est la suivante :
+=====-========-========-========-========-========-========-========-========+
| Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|Octet| | | | | | | | |
|=====+========+==============================================================|
| 0 | Valide | Code d'erreur (70h ou 71h) |
|-----+-----------------------------------------------------------------------|
| 1 | Numero de segment |
|-----+-----------------------------------------------------------------------|
| 2 |Filemark| EOM | ILI |Reserve | Clef d'etat |
|-----+-----------------------------------------------------------------------|
| 3 | (MSB) |
|- - -+--- Information ---|
| 6 | (LSB) |
|-----+-----------------------------------------------------------------------|
| 7 | Longueur additionnelle d'etat (n-7) |
|-----+-----------------------------------------------------------------------|
| 8 | (MSB) |
|- - -+--- Information specifique de la commande ---|
| 11 | (LSB) |
|-----+-----------------------------------------------------------------------|
| 12 | Code d'etat additionnel |
|-----+-----------------------------------------------------------------------|
| 13 | Qualificateur de code d'etat additionnel |
|-----+-----------------------------------------------------------------------|
| 14 | Code d'unite de champ remplacable |
|-----+-----------------------------------------------------------------------|
| 15 | SKSV | |
|- - -+------------ Specifique clef d'etat ---|
| 17 | |
|-----+-----------------------------------------------------------------------|
| 18 | |
|- - -+--- Octets supplementaires d'etat ---|
| n | |
+=============================================================================+
Note : les champs les plus utiles sont la clef d'etat (cf. section
``Clefs du buffer SCSI''), le code d'etat additionnel et le
qualificateur de code d'etat additionnel (cf. section ``Codes et
qualificateurs du buffer SCSI additionnels''). Les deux derniers sont
utilises en combinaison l'un avec l'autre.
1111.. EExxeemmppllee dd''uuttiilliissaattiioonn dduu ttaammppoonn SSCCSSII
Nous allons utiliser ici la commande "TEST UNIT READY" pour controler
si un support est charge dans notre peripherique. Les declarations
d'en-tete et la fonction handle_SCSI_cmd de l'exemple de "Inquiry"
seront aussi necessaires.
Table 73: Commande TEST UNIT READY
+=====-========-========-========-========-========-========-========-========+
| Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|Octet| | | | | | | | |
|=====+=======================================================================|
| 0 | Code operation (00h) |
|-----+-----------------------------------------------------------------------|
| 1 |Numero d'unite logique LUN| Reserve |
|-----+-----------------------------------------------------------------------|
| 2 | Reserve |
|-----+-----------------------------------------------------------------------|
| 3 | Reserve |
|-----+-----------------------------------------------------------------------|
| 4 | Reserve |
|-----+-----------------------------------------------------------------------|
| 5 | Controle |
+=============================================================================+
Voici la fonction qui l'implemente :
#define TESTUNITREADY_CMD 0
#define TESTUNITREADY_CMDLEN 6
#define ADD_SENSECODE 12
#define ADD_SC_QUALIFIER 13
#define NO_MEDIA_SC 0x3a
#define NO_MEDIA_SCQ 0x00
int TestForMedium ( void )
{
/* demande le statut READY */
static unsigned char cmdblk [TESTUNITREADY_CMDLEN] = {
TESTUNITREADY_CMD, /* commande */
0, /* lun/reserve */
0, /* reserve */
0, /* reserve */
0, /* reserve */
0};/* controle */
memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
/*
* +------------------+
* | struct sg_header | <- commande
* +------------------+
* | copie de cmdblk | <- commande + SCSI_OFF
* +------------------+
*/
if (handle_SCSI_cmd(sizeof(cmdblk), 0, cmd,
0, NULL)) {
fprintf (stderr, "Unite non prete\n");
exit(2);
}
return
*(((struct sg_header*)cmd)->sense_buffer +ADD_SENSECODE) !=
NO_MEDIA_SC ||
*(((struct sg_header*)cmd)->sense_buffer +ADD_SC_QUALIFIER) !=
NO_MEDIA_SCQ;
}
Nous pouvons maintenant realiser le controle a l'aide de la fonction
main :
void main( void )
{
fd = open(DEVICE, O_RDWR);
if (fd < 0) {
fprintf( stderr, "Il faut les permissions lecture/ecriture pour "DEVICE".\n"
);
exit(1);
}
/* on regarde si le support est charge */
if (!TestForMedium()) {
printf("le support n'est pas charge\n");
} else {
printf("le support est charge\n");
}
}
Le fichier generic_demo.c en annexe contient les deux exemples.
1122.. FFoonnccttiioonnss iiooccttll
Deux fonctions ioctl sont disponibles :
+o ioctl(fd, SG_SET_TIMEOUT, &Timeout); definit la valeur du timeout a
Timeout * 10 millisecondes. Timeout doit etre declare en tant
qu'entier (int).
+o ioctl(fd, SG_GET_TIMEOUT, &Timeout); lit la valeur du timeout en
cours. Timeout doit etre declare en tant qu'entier (int).
1133.. VVaalleeuurrss ppaarr ddeeffaauutt dduu ppiilloottee
1133..11.. TTaaiilllleess ddee ttrraannssffeerrtt
Actuellement (au moins jusqu'au noyau version 1.1.68), les tailles
d'entree et de sortie doivent etre inferieures ou egales a 4096
octets, sauf si le noyau a ete compile avec la constante SG_BIG_BUFF
definie, auquel cas elles sont limitees a SG_BIG_BUFF (soit 32768)
octets. Les tailles donnees comprennent l'en-tete generique ainsi que
le bloc de commande fourni en entree. SG_BIG_BUFF peut etre augmentee
sans probleme jusqu'a (131072 - 512). Pour en beneficier, vous devrez
bien evidemment regenerer un nouveau noyau et redemarrer avec.
1133..22.. TTiimmeeoouutt eett vvaalleeuurrss ddee rreeeessssaaiiss
La valeur du timeout par defaut est d'une minute (Timeout = 6 000).
Elle peut etre modifiee a l'aide d'un appel a ioctl (cf. section
``Fonctions ioctl''). Le nombre de reessais par defaut est un.
1144.. CCoommmmeenntt oobbtteenniirr lleess ssppeecciiffiiccaattiioonnss SSCCSSII ??
Il existe des normes appelees SCSI-1, SCSI-2 et SCSI-3. Les normes
assurent a peu de choses pres la compatibilite ascendante.
Le standard SCSI-1 est (d'apres l'auteur) en grande partie obsolete,
et SCSI-2 est celui qui est le plus largement utilise. SCSI-3 est tres
jeune et tres cher. Ces jeux de commandes normalises definissent des
commandes obligatoires et facultatives pour les constructeurs de
materiels SCSI et doivent etre preferees aux extensions specifiques
non normalisees et pour lesquelles l'information est plus difficile a
obtenir. Evidemment, il n'y a parfois aucune alternative a ces
extensions proprietaires.
Des copies electroniques sont disponibles par FTP anonyme depuis :
+o ftp.cs.tulane.edu:pub/scsi
+o ftp.symbios.com:/pub/standards
+o ftp.cs.uni-sb.de:/pub/misc/doc/scsi
(J'ai eu mes specifications SCSI dans le CD-ROM Linux d'Yggdrasil,
dans le repertoires /usr/doc/scsi-2 et /usr/doc/scsi-1).
La FAQ SCSI liste aussi les sources d'information imprimee suivantes :
Les specifications SCSI - disponible depuis :
Global Engineering Documents
15 Inverness Way East
Englewood Co 80112-5704
(800) 854-7179
SCSI-1: X3.131-1986
SCSI-2: X3.131-199x
SCSI-3 X3T9.2/91-010R4 Working Draft
(Global Engineering Documentation in Irvine, CA (714)261-1455??)
SCSI-1: Doc \# X3.131-1986 from ANSI, 1430 Broadway, NY, NY 10018
IN-DEPTH EXPLORATION OF SCSI peut etre trouve chez
Solution Technology, Attn: SCSI Publications, POB 104, Boulder Creek,
CA 95006, (408)338-4285, FAX (408)338-4374
THE SCSI ENCYLOPEDIA et SCSI BENCH REFERENCE peuvent etre obtenus chez
ENDL Publishing, 14426 Black Walnut Ct., Saratoga, CA 95090,
(408)867-6642, FAX (408)867-2115
SCSI: UNDERSTANDING THE SMALL COMPUTER SYSTEM INTERFACE est publie chez
Prentice-Hall, ISBN 0-13-796855-8
1155.. DD''aauuttrreess ssoouurrcceess dd''iinnffoorrmmaattiioonn
1155..11.. HHOOWWTTOOss eett FFAAQQss
Le SSCCSSII--HHOOWWTTOO Linux de Drew Eckhardt (NdT : disponible en version
francaise) traite de tous les controleurs SCSI reconnus ainsi que des
questions specifiques aux peripheriques. De nombreux aides pour le
depannage sont fournies. Il est disponible sur sunsite.unc.edu dans
/pub/Linux/docs/LDP et sur ses sites miroirs.
Les questions generales concernant le SCSI ont une reponse dans la FAQ
SCSI du groupe de news comp.periphs.scsi (disponible sur tsx-11 dans
/pub/linux/ALPHA/scsi et sur les sites miroirs).
1155..22.. LLaa lliissttee ddee mmeessssaaggeerriiee
Il existe une lliissttee ddee mmeessssaaggeerriiee qui traite des rapports d'anomalies
et questions sur le developpement SCSI sous Linux. Pour la rejoindre,
envoyez un courrier a
[email protected] avec la ligne
subscribe linux-scsi dans le corps du message. Les messages doivent
etre envoyes a
[email protected]. Un texte d'aide peut etre
demande par envoi de la ligne de message "help" a
[email protected].
1155..33.. EExxeemmpplleess ddee ccooddee
ssuunnssiittee..uunncc..eedduu:: aappppss//ggrraapphhiiccss//hhppssccaannppbbmm--00..33aa..ttaarr..ggzz
Ce paquetage gere un scanner HP scanjet a l'aide de l'interface
generique.
ttssxx--1111..mmiitt..eedduu:: BBEETTAA//ccddrroomm//pprriivvaattee//mmkkiissooffss//ccddwwrriittee--11..33..ttaarr..ggzz
Le paquetage cdwrite utilise l'interface generique pour ecrire
une image de CD sur un graveur.
ssuunnssiittee..uunncc..eedduu:: aappppss//ssoouunndd//ccddss//ccddddaa22wwaavv**..ssrrcc..ttaarr..ggzz
Un composant pour mes propres applications, qui copie des pistes
audio de CD sous forme de fichiers wav.
1166.. AAuuttrreess cchhoosseess uuttiilleess
Des choses qui pourraient devenir pratiques. Je n'ai aucune idee de la
presence de versions plus recentes ou meilleures ici ou la. Toute
information est la bienvenue.
1166..11.. AAiiddeess aa ll''eeccrriittuurree ddee ppiillootteess ddee ppeerriipphheerriiqquueess
Ces documents peuvent etre trouves sur le serveur ftp de
sunsite.unc.edu et sur ses miroirs.
//ppuubb//LLiinnuuxx//ddooccss//kkeerrnneell//kkeerrnneell--hhaacckkeerrss--gguuiiddee
Le guide des stakhanovistes du noyau LDP (NdT : Projet de
Documentation Linux). Il est peut-etre un peu ancien, mais
traite les points les plus fondamentaux.
//ppuubb//LLiinnuuxx//ddooccss//kkeerrnneell//ddrriivveerrss..ddoocc..zz
Ce document traite de l'ecriture de pilotes caracteres.
//ppuubb//LLiinnuuxx//ddooccss//kkeerrnneell//ttuuttoorriiaall..ddoocc..zz
Tutoriel sur l'ecriture d'un pilote de peripherique caractere
avec le code.
//ppuubb//LLiinnuuxx//ddooccss//kkeerrnneell//ssccssii..ppaappeerr..ttaarr..ggzz
Un document Latex decrivant comment ecrire un pilote SCSI.
//ppuubb//LLiinnuuxx//ddooccss//hhaarrddwwaarree//DDEEVVIICCEESS
Une liste des numeros majeurs et mineurs utilises par Linux.
1166..22.. UUttiilliittaaiirreess
ttssxx--1111..mmiitt..eedduu:: AALLPPHHAA//ssccssii//ssccssiiiinnffoo**..ttaarr..ggzz
Programme d'interrogation d'un peripherique SCSI pour obtenir
ses parametres d'utilisation, listes de defauts, etc. Une
interface X necessitant Tk/Tcl/wish est disponible. Avec cette
derniere, vous pouvez facilement modifier la configuration du
lecteur.
ttssxx--1111..mmiitt..eedduu:: AALLPPHHAA//kkddeebbuugg
Une extension a pour le deverminage du noyau.
1177.. AAuuttrreess iinntteerrffaacceess dd''aacccceess aauu SSCCSSII
Sous Linux, on peut acceder differemment au SCSI via des appels ioctl
SCSI_IOCTL_SEND_COMMAND qui necessitent des privileges root. Les
paquetages "scsiinfos" ainsi que "cdda2wav" les utilisent.
D'autres interfaces similaires sont utilisees dans le monde Unix, mais
ne sont pas disponibles pour Linux :
1. CAM (Common Access Method) developpee par Future Domain et d'autres
constructeurs SCSI. Linux dispose maintenant d'un petit support
pour un systeme CAM SCSI (essentiellement pour bouter depuis un
disque dur). CAM supporte meme le mode "target", qui permet de
deguiser un ordinateur en peripherique SCSI (c.a.d. realiser un
petit reseau SCSI).
2. ASPI (Advanced SCSI Programming Interface) developpee par Adaptec.
C'est le standard de facto pour les machines MS-DOS.
3. ??? est disponible sur NeXTStep.
4. DSLIB est disponible sur Silicon Graphics.
5. SCSI... est disponible sur les machines SUN.
6. SCO Unix a aussi quelque chose.
7. HPUX utilise des ioctl. -->
D'autres interfaces applicatives existent aussi chez SCO(TM),
NeXT(TM), Silicon Graphics(TM) et SUN(TM).
1188.. CCoommmmeennttaaiirreess ffiinnaallss
L'interface generique SCSI jette un pont sur le fosse entre les
applications utilisateur et les peripheriques specifiques. Mais plutot
que de charger de nombreux programmes avec des jeux similaires de
fonctions de bas niveau, il serait plus souhaitable de disposer d'une
bibliotheque partagee avec un jeu generalise de fonctions de bas
niveau pour un usage particulier. Le but principal est de disposer de
couches d'interfaces independantes. Une bonne conception doit separer
une application en routines de bas niveau et independantes du
materiel. Celles-ci peuvent etre placees dans une bibliotheque
partagee et rendues disponibles pour toutes les applications. Ainsi,
les interfaces standardisees doivent etre suivies autant que possible
avant d'en realiser de nouvelles.
Vous devriez maintenant en savoir plus que moi sur l'interface
generique SCSI de Linux. Vous pouvez donc commencer a developper de
puissantes applications pour le plus grand benefice de la communaute
Linux...
1199.. RReemmeerrcciieemmeennttss
Un grand merci a Jeff Tranter pour ses corrections et ameliorations
considerables de ce texte, ainsi qu'a Carlos Puchol pour ses
commentaires utiles. L'aide de Drew Eckhardt et Eric Youngdale sur
mes premieres questions (idiotes) sur l'utilisation de cette interface
a ete appreciee.
TT.. AAnnnneexxee
UU.. TTrraaiitteemmeenntt dd''eerrrreeuurrss
Les fonctions open, ioctl, write et read peuvent renvoyer des erreurs.
Dans ce cas, leur valeur de retour est -1 et la variable globale errno
est positionnee au numero d'erreur (negatif). Les valeurs de errno
sont definies dans /usr/include/errno.h. Les valeurs negatives
possibles sont les suivantes :
Fonction | Erreur | Description
=========|==============|==================================================
open | ENXIO | peripherique invalide
| EACCES | l'acces n'est pas en lecture/ecriture (O_RDWR)
| EBUSY | le peripherique est accede en mode non bloquant,
| | mais il est occupe actuellement
| ERESTARTSYS | erreur interne. Essayez de la rendre reproductible
| | et informez-en le canal SCSI (pour les details sur
| | le rapport de bogue, se reporter au SCSI-HOWTO de
| | Drew Eckhardts).
ioctl | ENXIO | peripherique invalide
read | EAGAIN | le peripherique bloque. Essayez plus tard.
| ERESTARTSYS | erreur interne. Essayez de la rendre reproductible
| | et informez-en le canal SCSI (pour les details sur
| | le rapport de bogue, se reporter au SCSI-HOWTO de
| | Drew Eckhardts).
write | EIO | taille trop petite (plus petite que cette de l'en-
| | tete generique). Attention : il n'y a actuellement
| | aucun controle de debordement.
| EAGAIN | le peripherique bloque. Essayez plus tard.
| ENOMEM | la memoire necessaire pour cette requete ne peut
| | etre allouee. Essayez plus tard sauf si vous depas-
| | sez la taille maximale de transfert (cf. ci-dessus).
select | | sans description
close | | sans description
Pour la lecture et l'ecriture, des valeurs de retour positivent
indiquent comme d'habitude la quantite d'octets transferes. Cette
valeur doit correspondre a celle demandee.
UU..11.. DDeeccooddaaggee ddee ll''eettaatt dd''eerrrreeuurr
En plus, une information detaillee est fournie par hd_status du noyau
et par sense_buffer du peripherique (cf. section ref id="sec-
sensebuff" name="Le tampon SCSI">), les deux utilisant la structure
d'en-tete generique.
Les differents sens de hd_status peuvent etre trouves dans
drivers/scsi/scsi.h. Cet unsigned int est compose de differentes
parties :
lsb | ... | ... | msb
=======|===========|===========|============
status | sense key | host code | driver byte
Les macros de drivers/scsi/scsi.h sont disponibles, mais elles ne
peuvent malheureusement pas etre facilement utilisees a cause
d'interdependances tordues entre fichiers d'en-tete. Il faudrait faire
une passe sur ces fichiers pour clarifier les choses.
Macro | Description
=======================|=================================================
status_byte(hd_status) | Etat du peripherique. cf. section Codes d'etat
msg_byte(hd_status) | du peripherique. cf. section buffer SCSI
host_byte(hd_status) | du noyau. cf. section codes hote
driver_byte(hd_status) | du noyau. cf. section codes intermediaires
UU..22.. CCooddeess dd''eettaatt
Les codes d'etat de peripherique qui suivent (issus de
drivers/scsi/scsi.h) sont disponibles :
Valeur | Symbole
=======|=====================
0x00 | GOOD
0x01 | CHECK_CONDITION
0x02 | CONDITION_GOOD
0x04 | BUSY
0x08 | INTERMEDIATE_GOOD
0x0a | INTERMEDIATE_C_GOOD
0x0c | RESERVATION_CONFLICT
On constate que ces valeurs symboliques ont subi un ddeeccaallaaggee ddrrooiitt.
Lorsque l'etat indique CHECK_CONDITION, les donnees du buffer SCSI
sont valides (controlez en particulier le code d'etat additionnel et
le qualificateur de code d'etat additionnel).
Les valeurs qui suivent concernent les specifications SCSI-2 :
Table 27 : Code de l'octet d'etat
+=================================-==============================+
| Bits de l'octet d'etat | Etat |
| 7 6 5 4 3 2 1 0 | |
|---------------------------------+------------------------------|
| R R 0 0 0 0 0 R | GOOD |
| R R 0 0 0 0 1 R | CHECK CONDITION |
| R R 0 0 0 1 0 R | CONDITION MET |
| R R 0 0 1 0 0 R | BUSY |
| R R 0 1 0 0 0 R | INTERMEDIATE |
| R R 0 1 0 1 0 R | INTERMEDIATE-CONDITION MET |
| R R 0 1 1 0 0 R | RESERVATION CONFLICT |
| R R 1 0 0 0 1 R | COMMAND TERMINATED |
| R R 1 0 1 0 0 R | QUEUE FULL |
| | |
| Tous autres codes | Reserve |
|----------------------------------------------------------------|
| R = Bit reserve |
+================================================================+
La definition des codes de l'octet d'etat sont donnees ci-dessous :
GGOOOODD..
Cet etat indique que la cible a correctement execute la
commande.
CCHHEECCKK CCOONNDDIITTIIOONN..
Cet etat indique qu'une condition de contention s'est produite
(cf. 6.6).
CCOONNDDIITTIIOONN MMEETT..
Cet etat, ou INTERMEDIATE-CONDITION MET est renvoye lorsque les
conditions de l'operation demandee sont satisfaites (cf.
commandes SEARCH DATA et PRE-FETCH).
BBUUSSYY..
Cet etat indique que la cible est occupee. Il peut etre renvoye
lorsque la cible ne peut accepter de commande depuis un
initiateur inacceptable par ailleurs (i.e. conflit d'absence de
reservation). L'action de reprise recommandee est une nouvelle
tentative ulterieure.
IINNTTEERRMMEEDDIIAATTEE..
Cet etat, ou INTERMEDIATE-CONDITION MET doit etre renvoyee apres
chaque commande reussie d'une serie de commandes liees (sauf
pour la derniere), sauf si celle-ci se termine par un CHECK
CONDITION, RESERVATION CONFLICT, ou COMMAND TERMINATED. Si ni
INTERMEDIATE ni INTERMEDIATE-CONDITION MET n'est renvoye, la
serie de commandes se termine, ainsi que le processus
d'entrees/sorties.
IINNTTEERRMMEEDDIIAATTEE--CCOONNDDIITTIIOONN MMEETT..
Cet etat est la combinaison de CONDITION MET et de INTERMEDIATE.
RREESSEERRVVAATTIIOONN CCOONNFFLLIICCTT..
Cet etat doit etre renvoye lorsqu'un initiateur tente d'acceder
a une unite logique ou a un extension a l'interieur d'une unite
logique reservee avec un type de reservation en conflit pour un
autre peripherique SCSI (cf. commandes RESERVE et RESERVE UNIT).
L'action de reprise recommandee est une nouvelle tentative
ulterieure.
CCOOMMMMAANNDD TTEERRMMIINNAATTEEDD..
Cet etat doit etre renvoye lorsque la cible termine le processus
d'entrees/sorties apres reception d'un message TERMINATE I/O
PROCESS (cf. 5.6.22). Cet etat indique aussi qu'une condition de
contention s'est produite (cf. 6.6).
QQUUEEUUEE FFUULLLL..
Cet etat doit etre implemente si la file d'attente marquee
(tagged queuing) l'est aussi. Il est renvoye lors de la
reception d'un message SIMPLE QUEUE TAG, ORDERED QUEUE TAG, ou
HEAD OF QUEUE TAG et que la file de commandes est pleine. Le
processus d'entree/sortie n'est alors pas place dans la file de
commandes.
UU..33.. CClleeffss dduu bbuuffffeerr SSCCSSII
Les clefs resultantes peuvent etre rapatriees a l'aide de la macro
msg_byte (cf. section ``Decodage de l'etat d'erreur''). Les symboles
du noyau qui suivent sont predefinis dans drivers/scsi/scsi.h :
Valeur | Symbole
=======|================
0x00 | NO_SENSE
0x01 | RECOVERED_ERROR
0x02 | NOT_READY
0x03 | MEDIUM_ERROR
0x04 | HARDWARE_ERROR
0x05 | ILLEGAL_REQUEST
0x06 | UNIT_ATTENTION
0x07 | DATA_PROTECT
0x08 | BLANK_CHECK
0x0a | COPY_ABORTED
0x0b | ABORTED_COMMAND
0x0d | VOLUME_OVERFLOW
0x0e | MISCOMPARE
Une liste extraite de la doc SCSI-2 suit (issue de la section
7.2.14.3) :
Table 69: Description des clefs (0h-7h) du buffer SCSI
+========-====================================================================+
| Clef | Description |
|--------+--------------------------------------------------------------------|
| 0h | NO SENSE. Indique qu'aucune information specifique n'est |
| | disponible pour l'unite logique designee. C'est le cas pour les |
| | commandes reussies ou celles dont l'etat est CHECK CONDITION ou |
| | COMMAND TERMINATED a cause de l'un des bits filemark, EOM ou ILI. |
|--------+--------------------------------------------------------------------|
| 1h | RECOVERED ERROR. Indique que la reussite de la derniere commande |
| | fut conditionnee par une action de reparation effectuee par la |
| | cible. Les octets additionnels peuvent fournir des details, ainsi |
| | que le champ information. Lorsque plusieurs erreurs reparees se |
| | produisent durant une commande, le choix de celle indiquee |
| | (premiere, derniere, plus severe, etc.) depend du peripherique. |
|--------+--------------------------------------------------------------------|
| 2h | NOT READY. Indique que l'unite logique est inaccessible. Une |
| | intervention manuelle peut etre necessaire. |
|--------+--------------------------------------------------------------------|
| 3h | MEDIUM ERROR. Indique la fin d'une commande sur une erreur non- |
| | recuperable, causee probablement par un defaut du support ou une |
| | erreur de donnees. Cette clef peut aussi etre renvoyee si la |
| | cible ne peut faire la distinction entre un defaut du support et |
| | un defaut specifique du materiel (clef 4h). |
|--------+--------------------------------------------------------------------|
| 4h | HARDWARE ERROR. Indique que la cible a detecte une erreur mate- |
| | rielle irrecuperable (defaut du controleur, du peripherique, er- |
| | reur de parite, etc.) lors de l'execution de la commande ou d'un |
| | auto-test. |
|--------+--------------------------------------------------------------------|
| 5h | ILLEGAL REQUEST. Indique qu'un parametre illegal a ete detecte |
| | dans le bloc de description de commande ou dans les parametres |
| | additionnels (pour certaines commandes : FORMAT UNIT, SEARCH DATA,|
| | etc.). Si la cible detecte un parametre incorrect, il doit termi- |
| | ner celle-ci sans modifier le contenu du support. Si le parametre |
| | incorrect se trouve dans les parametres additionnels, la cible |
| | peut avoir deja modifie le support. Cette clef est aussi renvoyee |
| | lors de la reception d'un message IDENTIFY invalide (5.6.7). |
|--------+--------------------------------------------------------------------|
| 6h | UNIT ATTENTION. Indique que le support amovible a pu etre change |
| | ou que la cible a ete reinitialisee. Cf. 6.9 pour d'autres infor- |
| | mation sur cette condition. |
|--------+--------------------------------------------------------------------|
| 7h | DATA PROTECT. Indique qu'une commande de lecture ou d'ecriture a |
| | ete tentee sur un bloc protege contre cette operation. Celle-ci |
| | n'est pas effectuee. |
+=============================================================================+
Table 70: Description des clefs (8h-Fh) du buffer SCSI
+========-====================================================================+
| Clef | Description |
|--------+--------------------------------------------------------------------|
| 8h | BLANK CHECK. Indique qu'un peripherique a ecriture unique ou |
| | sequentiel a trouve un support vierge ou une indication de fin de |
| | donnees de formatage lors de la lecture, ou qu'un support non |
| | vierge a ecriture seule a ete trouve pendant l'ecriture. |
|--------+--------------------------------------------------------------------|
| 9h | Vendor Specific. Cette clef est disponible pour indiquer des |
| | cas particuliers specifiques du constructeur. |
|--------+--------------------------------------------------------------------|
| Ah | COPY ABORTED. Indique qu'une commande COPY, COMPARE ou COPY AND |
| | VERIFY a echoue a cause d'une condition d'erreur sur le periphe- |
| | rique source, destination ou les deux (cf. 7.2.3.2 pour plus de |
| | details). |
|--------+--------------------------------------------------------------------|
| Bh | ABORTED COMMAND. Indique que la cible a abandonne la commande. |
| | L'initiateur peut eventuellement corriger le probleme par une |
| | nouvelle tentative. |
|--------+--------------------------------------------------------------------|
| Ch | EQUAL. Indique qu'une commande SEARCH DATA a satisfait une con- |
| | dition d'egalite. |
|--------+--------------------------------------------------------------------|
| Dh | VOLUME OVERFLOW. Indique qu'un peripherique a memoire-tampon a |
| | atteint la fin de partition et que des donnees non ecrites sur le |
| | support peuvent rester dans le tampon. Une (ou plusieurs) commande|
| | RECOVER BUFFER DATA peut etre tentee pour lire les donnees non |
| | ecrites depuis le tampon. |
|--------+--------------------------------------------------------------------|
| Eh | MISCOMPARE. Indique que les donnees source ne correspondent pas |
| | a celles lues sur le support. |
|--------+--------------------------------------------------------------------|
| Fh | RESERVE. |
+=============================================================================+
UU..44.. CCooddeess hhoottee
Les codes hotes qui suivent sont definis au niveau de
drivers/scsi/scsi.h. Ils sont positionnes par le pilote du noyau et
doivent etre utilises avec la macro host_byte (cf. section ``Decodage
de l'etat d'erreur'') :
Valeur | Symbole | Description
=======|================|========================================
0x00 | DID_OK | Pas d'erreur
0x01 | DID_NO_CONNECT | Connexion impossible avant le timeout
0x02 | DID_BUS_BUSY | BUS occupe durant la periode de timeout
0x03 | DID_TIME_OUT | Timeout atteint pour une autre raison
0x04 | DID_BAD_TARGET | Mauvaise cible
0x05 | DID_ABORT | Arret effectue pour une autre raison
0x06 | DID_PARITY | Erreur de parite
0x07 | DID_ERROR | Erreur interne
0x08 | DID_RESET | Reinitialise par quelqu'un
0x09 | DID_BAD_INTR | Interruption inattendue recue
UU..55.. CCooddeess dduu ppiilloottee
Le pilote de niveau intermediaire categorise l'etat renvoye par le
pilote de bas niveau en fonction du buffer SCSI du peripherique. Il
suggere certaines actions pouvant etre tentees comme un reessai, un
abandon ou un changement de topographie. La routine scsi_done de
scsi.c effectue un travail tres differencie fonde sur host_byte(),
status_byte(), msg_byte() et la suggestion precedente. Ensuite, il
positionne l'octet du pilote afin d'indiquer ce qui a ete realise.
L'octet du pilote est en deux parties : l'etat du pilote et la
suggestion. Chaque moitie est composee des valeurs suivantes (de
scsi.h) combinees par un OR :
Valeur | Symbole | Description ou etat du pilote
=======|================|========================================
0x00 | DRIVER_OK | pas d'erreur
0x01 | DRIVER_BUSY | inutilise
0x02 | DRIVER_SOFT | inutilise
0x03 | DRIVER_MEDIA | inutilise
0x04 | DRIVER_ERROR | erreur interne du pilote
0x05 | DRIVER_INVALID | termine (DID_BAD_TARGET ou DID_ABORT)
0x06 | DRIVER_TIMEOUT | termine avec timeout
0x07 | DRIVER_HARD | termine avec une erreur fatale
0x08 | DRIVER_SENSE | buffer SCSI disponible pour informations
Valeur | Symbole | Description de la suggestion
=======|================|========================================
0x10 | SUGGEST_RETRY | reessayer la requete SCSI
0x20 | SUGGEST_ABORT | abandonner la requete
0x30 | SUGGEST_REMAP | remape le bloc (non encore implemente)
0x40 | SUGGEST_DIE | laisser le noyau tomber en "panic"
0x80 | SUGGEST_SENSE | lire le buffer SCSI du peripherique
0xff | SUGGEST_IS_OK | rien a faire
VV.. CCooddeess eett qquuaalliiffiiccaatteeuurrss dduu bbuuffffeerr SSCCSSII aaddddiittiioonnnneellss
Lorsque l'etat de la commande SCSI executee est CHECK_CONDITION, des
donnees sont disponibles dans le buffer SCSI. Les code et
qualificateur additionnels se trouvent dans ce tampon.
Je joins ici deux tables issues des specifications SCSI-2. La premiere
est triee alphabetiquement, la seconde, numeriquement (NdT : la
traduction ayant un tantinet bouleverse l'ordre alphabetique, seule la
table triee par numeros a ete conservee. Le lecteur pourra se reporter
a la version originale en americain pour la liste alphabetique).
VV..11.. AASSCC eett AASSCCQQ ddaannss ll''oorrddrree nnuummeerriiqquuee
La table qui suit fournit une liste de descriptions avec les
peripheriques auxquels elles s'appliquent.
Table 364 : Assignements ASC et ASCQ
+=============================================================================+
| D - peripherique a acces Direct (Disque) |
| .T - peripherique a acces sequenTiel (bande magneTique) |
| . I - Imprimante |
| . P - Processeur |
| . .W -WORM (CD-ROM inscriptible une fois) |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| ASC ASCQ DTIPWRSOMC DESCRIPTION |
| --- ---- ----------------------------------------------------- |
| 00 00 DTIPWRSOMC pas d'information additionnelle |
| 00 01 T marque de fichier detectee |
| 00 02 T S fin de partition/medium detectee |
| 00 03 T marque de jeu detectee |
| 00 04 T S debut de partition/medium detecte |
| 00 05 T S fin de donnees detectee |
| 00 06 DTIPWRSOMC fin du processus d'E/S |
| 00 11 R lecture audio en cours |
| 00 12 R lecture audio suspendue |
| 00 13 R lecture audio terminee avec succes |
| 00 14 R lecture audio stoppee pour cause d'erreur |
| 00 15 R pas d'etat audio en cours a retourner |
| 01 00 DW O pas de signal d'index/de secteur |
| 02 00 D WR OM deplacement incomplet |
| 03 00 DTI W SO echec d'ecriture sur le peripherique |
| 03 01 T pas d'ecriture en cours |
| 03 02 T trop d'erreurs d'ecriture |
| 04 00 DTIPWRSOMC unite logique non prete, cause inconnue |
| 04 01 DTIPWRSOMC unite logique en preparation |
| 04 02 DTIPWRSOMC unite logique non prete, commande d'init necessaire |
| 04 03 DTIPWRSOMC unite logique non prete, intervention manuelle necess.|
| 04 04 DTI O unite logique non prete, formatage en cours |
| 05 00 DTI WRSOMC l'unite logique ne repond pas a la selection |
| 06 00 D WR OM pas de position de reference trouvee |
| 07 00 DTI WRSOM selection de plusieurs peripheriques |
| 08 00 DTI WRSOMC echec de communication avec l'unite logique |
| 08 01 DTI WRSOMC timeout de communication avec l'unite logique |
| 08 02 DTI WRSOMC erreur de parite en communication avec l'unite logique|
| 09 00 DT WR O erreur de suivi de piste |
| 09 01 WR O defaillance du servo de suivi de piste |
| 09 02 WR O defaillance du servo de focalisation |
| 09 03 WR O defaillance du servo de SPINDLE |
+=============================================================================+
Table 364 : (suite)
+=============================================================================+
| D - peripherique a acces Direct (Disque) |
| .T - peripherique a acces sequenTiel (bande magneTique) |
| . I - Imprimante |
| . P - Processeur |
| . .W -WORM (CD-ROM inscriptible une fois) |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| ASC ASCQ DTIPWRSOMC DESCRIPTION |
| --- ---- ----------------------------------------------------- |
| 0A 00 DTIPWRSOMC debordement de la trace d'erreur |
| 0B 00 |
| 0C 00 T S erreur d'ecriture |
| 0C 01 D W O erreud d'ecriture corrigee par auto-reallocation |
| 0C 02 D W O erreur d'ecriture - auto-reallocation impossible |
| 0D 00 |
| 0E 00 |
| 0F 00 |
| 10 00 D W O erreur ID, CRC ou ECC |
| 11 00 DT WRSO erreur de lecture irrecuperable |
| 11 01 DT W SO nombre d'essais atteint |
| 11 02 DT W SO erreur trop longue a corriger |
| 11 03 DT W SO erreurs de lecture multiples |
| 11 04 D W O erreur de lecture - auto-reallocation impossible |
| 11 05 WR O erreur irrecuperable L-EC |
| 11 06 WR O erreur irrecuperable CIRC |
| 11 07 W O erreur de resynchronisation de donnees |
| 11 08 T lecture de bloc incomplete |
| 11 09 T pas de breche trouvee |
| 11 0A DT O erreur mal corrigee |
| 11 0B D W O erreur de lecture - reassignement recommande |
| 11 0C D W O erreur de lecture - reecriture recommandee |
| 12 00 D W O marque d'adresse introuvable pour le champ ID |
| 13 00 D W O marque d'adresse introuvable pour le champ donnees |
| 14 00 DTI WRSO identite enregistree introuvable |
| 14 01 DT WR O enregistrement introuvable |
| 14 02 T marque de fichier ou de jeu introuvable |
| 14 03 T fin de donnees introuvable |
| 14 04 T erreur de sequence de bloc |
| 15 00 DTI WRSOM erreur de positionnement aleatoire |
| 15 01 DTI WRSOM erreur de positionnement mecanique |
| 15 02 DT WR O erreur de positionnement detectee par la lecture |
| 16 00 DW O erreur de marque de synchronisation de donnees |
| 17 00 DT WRSO donnees recuperees sans correction d'erreur |
| 17 01 DT WRSO donnees recuperees apres plusieurs essais |
| 17 02 DT WR O donnees recuperees avec un decalage de tete positif |
| 17 03 DT WR O donnees recuperees avec un decalage de tete negatif |
| 17 04 WR O donnees recuperees avec plusieurs essais et/ou CIRC |
| 17 05 D WR O donnees recuperees sur l'ID de secteur precedent |
| 17 06 D W O donnees recuperees sans ECC - donnees auto-reallouees |
| 17 07 D W O donnees recuperees sans ECC - reassignement recommande|
| 17 08 D W O donnees recuperees sans ECC - reecriture recommandee |
| 18 00 DT WR O donnees recuperees avec correction d'erreur |
| 18 01 D WR O donnees recuperees avec correction & plusieurs essais |
| 18 02 D WR O donnees recuperees - donnees auto-reallouees |
| 18 03 R donnees recuperees avec CIRC |
| 18 04 R donnees recuperees avec LEC |
| 18 05 D WR O donnees recuperees - reassignement recommande |
| 18 06 D WR O donnees recuperees - reecriture recommandee |
+=============================================================================+
Table 364 : (suite)
+=============================================================================+
| D - peripherique a acces Direct (Disque) |
| .T - peripherique a acces sequenTiel (bande magneTique) |
| . I - Imprimante |
| . P - Processeur |
| . .W -WORM (CD-ROM inscriptible une fois) |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| ASC ASCQ DTIPWRSOMC DESCRIPTION |
| --- ---- ----------------------------------------------------- |
| 19 00 D O erreur de liste de defauts |
| 19 01 D O liste de defauts indisponible |
| 19 02 D O erreur de liste de defauts en liste primaire |
| 19 03 D O erreur de liste de defauts en liste secondaire (grown)|
| 1A 00 DTIPWRSOMC erreur de taille de la liste de defauts |
| 1B 00 DTIPWRSOMC erreur de transfert de donnees synchrone |
| 1C 00 D O liste de defauts introuvable |
| 1C 01 D O liste de defauts primaire introuvable |
| 1C 02 D O liste de defauts secondaire (grown) introuvable |
| 1D 00 D W O erreur de comparaison durant la verification |
| 1E 00 D W O ID recupere avec ECC |
| 1F 00 |
| 20 00 DTIPWRSOMC code d'operation de commande incorrect |
| 21 00 DT WR OM adresse du bloc logique hors limites |
| 21 01 M adresse d'element incorrecte |
| 22 00 D fonction illegale (seulement 20 00, 24 00 ou 26 00) |
| 23 00 |
| 24 00 DTIPWRSOMC champ incorrect en CDB |
| 25 00 DTIPWRSOMC unite logique non supportee |
| 26 00 DTIPWRSOMC champ incorrect en liste de parametres |
| 26 01 DTIPWRSOMC parametre non supporte |
| 26 02 DTIPWRSOMC valeur de parametre incorrecte |
| 26 03 DTIPWRSOMC parametres de seuil non supportes |
| 27 00 DT W O protection en ecriture |
| 28 00 DTIPWRSOMC transition non-pret/pret (changement de medium ?) |
| 28 01 M acces a un element import ou export |
| 29 00 DTIPWRSOMC allumage, reinit. ou reinit. du bus a eu lieu |
| 2A 00 DTI WRSOMC parametres changes |
| 2A 01 DTI WRSOMC parametres de mode changes |
| 2A 02 DTI WRSOMC parametres de trace changes |
| 2B 00 DTIPWRSO C copie impossible : deconnexion du host impossible |
| 2C 00 DTIPWRSOMC erreur de sequence de commandes |
| 2C 01 S trop de fenetres specifiees |
| 2C 02 S combinaison de fenetres incorrecte specifiee |
| 2D 00 T erreur d'ecriture en ecrasement de donnees |
| 2E 00 |
| 2F 00 DTIPWRSOMC commandes annulees par un autre initiateur |
| 30 00 DT WR OM medium incompatible present |
| 30 01 DT WR O medium illisible - format inconnu |
| 30 02 DT WR O medium illisible - format incompatible |
| 30 03 DT cartouche de nettoyage presente |
| 31 00 DT W O format du medium endommage |
| 31 01 D I O echec de la commande de format |
| 32 00 D W O plus d'emplacement de defaut disponible |
| 32 01 D W O echec de mise a jour de la liste de defauts |
| 33 00 T erreur de longueur de bande |
| 34 00 |
| 35 00 |
| 36 00 I manque d'encre, de ruban ou de toner |
+=============================================================================+
Table 364 : (suite)
+=============================================================================+
| D - peripherique a acces Direct (Disque) |
| .T - peripherique a acces sequenTiel (bande magneTique) |
| . I - Imprimante |
| . P - Processeur |
| . .W -WORM (CD-ROM inscriptible une fois) |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| ASC ASCQ DTIPWRSOMC DESCRIPTION |
| --- ---- ----------------------------------------------------- |
| 37 00 DTI WRSOMC parametre arrondi |
| 38 00 |
| 39 00 DTI WRSOMC sauvegarde de parametres non supportee |
| 3A 00 DTI WRSOM pas de medium |
| 3B 00 TI erreur de positionnement sequentiel |
| 3B 01 T erreur de positionnement de la bande au debut |
| 3B 02 T erreur de positionnement de la bande a la fin |
| 3B 03 I bande ou feuille-a-feuille non pret |
| 3B 04 I erreur de SLEW (NdT : !?) |
| 3B 05 I bourrage papier |
| 3B 06 I haut de page non detecte |
| 3B 07 I bas de page non detecte |
| 3B 08 T erreur de repositionnement |
| 3B 09 S lecture apres la fin du medium |
| 3B 0A S lecture avant le debut du medium |
| 3B 0B S position apres la fin du medium |
| 3B 0C S position avant le debut du medium |
| 3B 0D M emplacement de destination occupe |
| 3B 0E M emplacement d'origine vide |
| 3C 00 |
| 3D 00 DTIPWRSOMC bits incorrects dans le message d'identification |
| 3E 00 DTIPWRSOMC auto-configuration de l'unite non encore realisee |
| 3F 00 DTIPWRSOMC les conditions de fonctionnement ont change |
| 3F 01 DTIPWRSOMC le micro-code a ete change |
| 3F 02 DTIPWRSOMC definition de fonctionnement modifiee |
| 3F 03 DTIPWRSOMC les donnees de requete ont change |
| 40 00 D defaillance RAM (40nn obligatoire) |
| 40 NN DTIPWRSOMC echec de diagnostic du composant nn (80h-FFh) |
| 41 00 D echec du chemin de donnees (40nn obligatoire) |
| 42 00 D echec d'alllumage ou d'auto-test (40nn obligatoire) |
| 43 00 DTIPWRSOMC erreur de message |
| 44 00 DTIPWRSOMC defaillance de cible interne |
| 45 00 DTIPWRSOMC echec de selection ou de reselection |
| 46 00 DTIPWRSOMC echec de la reinitialisation logicielle |
| 47 00 DTIPWRSOMC erreur de parite SCSI |
| 48 00 DTIPWRSOMC reception de message d'erreur detecte par initiateur |
| 49 00 DTIPWRSOMC erreur message incorrect |
| 4A 00 DTIPWRSOMC erreur de phase de commande |
| 4B 00 DTIPWRSOMC erreur de phase de donnees |
| 4C 00 DTIPWRSOMC echec de l'auto-configuration de l'unite logique |
| 4D 00 |
| 4E 00 DTIPWRSOMC commandes en recouvrement |
| 4F 00 |
| 50 00 T erreur d'ecriture en ajout |
| 50 01 T erreur de positionnement en ajout |
| 50 02 T erreur de positionnement par rapport au timing |
| 51 00 T O erreur d'effacement |
| 52 00 T defaut de cartouche |
+=============================================================================+
Table 364 : (suite)
+=============================================================================+
| D - peripherique a acces Direct (Disque) |
| .T - peripherique a acces sequenTiel (bande magneTique) |
| . I - Imprimante |
| . P - Processeur |
| . .W -WORM (CD-ROM inscriptible une fois) |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| ASC ASCQ DTIPWRSOMC DESCRIPTION |
| --- ---- ----------------------------------------------------- |
| 53 00 DTI WRSOM echec de chargement ou d'ejection du medium |
| 53 01 T echec de dechargement de la bande |
| 53 02 DT WR OM peripherique protege contre le changement de medium |
| 54 00 P defaillance de l'interface host-SCSI |
| 55 00 P defaut de ressources systeme |
| 56 00 |
| 57 00 R impossible de recuperer la table du contenu |
| 58 00 O la generation n'existe pas |
| 59 00 O lecture de bloc mis a jour |
| 5A 00 DTIPWRSOM requete operateur ou demande de changement d'etat |
| 5A 01 DT WR OM requete operateur d'extraction du medium |
| 5A 02 DT W O l'operateur a selectionne la protection en ecriture |
| 5A 03 DT W O l'operateur a selectionne l'autorisation d'ecriture |
| 5B 00 DTIPWRSOM exception de trace |
| 5B 01 DTIPWRSOM condition de seuil remplie |
| 5B 02 DTIPWRSOM compteur de trace au maximum |
| 5B 03 DTIPWRSOM plus de code pour la liste de trace |
| 5C 00 D O changement d'etat RPL |
| 5C 01 D O SPINDLES synchronisees |
| 5C 02 D O SPINDLES non synchronisees |
| 5D 00 |
| 5E 00 |
| 5F 00 |
| 60 00 S defaillance de la lampe |
| 61 00 S erreur d'acquisition video |
| 61 01 S impossible de capturer la video |
| 61 02 S hors de la zone focalisee |
| 62 00 S erreur de positionnement de la tete de digitalisation |
| 63 00 R fin de zone utilisateur sur cette piste |
| 64 00 R mode illegal pour cette piste |
| 65 00 |
| 66 00 |
| 67 00 |
| 68 00 |
| 69 00 |
| 6A 00 |
| 6B 00 |
| 6C 00 |
| 6D 00 |
| 6E 00 |
| 6F 00 |
+=============================================================================+
Table 364 : (fin)
+=============================================================================+
| D - peripherique a acces Direct (Disque) |
| .T - peripherique a acces sequenTiel (bande magneTique) |
| . I - Imprimante |
| . P - Processeur |
| . .W -WORM (CD-ROM inscriptible une fois) |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| ASC ASCQ DTIPWRSOMC DESCRIPTION |
| --- ---- ----------------------------------------------------- |
| 70 00 |
| 71 00 |
| 72 00 |
| 73 00 |
| 74 00 |
| 75 00 |
| 76 00 |
| 77 00 |
| 78 00 |
| 79 00 |
| 7A 00 |
| 7B 00 |
| 7C 00 |
| 7D 00 |
| 7E 00 |
| 7F 00 |
| |
| 80 xxh \ |
| jusqu'a > specifique constructeur |
| FF xxh / |
| |
| xxh 80 \ |
| jusqu'a > qualification du standard ASC specifique constructeur |
| xxh FF / |
| TOUS LES CODES VIDES OU NON MONTRES SONT RESERVES |
+=============================================================================+
WW.. RReeffeerreennccee rraappiiddee ddeess ccoommmmaannddeess SSCCSSII
La table 365 est une liste ordonnee numeriquement des codes operation
des commandes.
Table 365 : Codes operations SCSI-2
+=============================================================================+
| D - peripherique a acces Direct Clef de colonne |
| .T - peripherique a acces sequenTiel N = Necessaire |
| . I - Imprimante O = Optionnel |
| . P - Processeur C = Constructeur |
| . .W -WORM (CD-ROM inscriptible une fois) R = Reserve |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| OP DTIPWRSOMC Description |
|----------+----------+-------------------------------------------------------|
| 00 NNNNNNNNNN test d'unite prete |
| 01 N rembobinage |
| 01 O C OO OO remise a zero de l'unite |
| 02 CCCCCC C |
| 03 NNNNNNNNNN requete de buffer SCSI |
| 04 O formatage |
| 04 N O formatage de l'unite |
| 05 CNCCCC C lecture des limites de bloc |
| 06 CCCCCC C |
| 07 O initialisation de l'etat d'un element |
| 07 OCC O OC reassignation de blocs |
| 08 N lecture de message (06) |
| 08 ONC OO OC lecture (06) |
| 08 O reception |
| 09 CCCCCC C |
| 0A N impression |
| 0A N emission de message (06) |
| 0A N emission (06) |
| 0A ON O OC ecriture (06) |
| 0B O OO OC deplacement (06) |
| 0B O SLEW et impression |
| 0C CCCCCC C |
| 0D CCCCCC C |
| 0E CCCCCC C |
| 0F COCCCC C lecture inversee |
| 10 O O synchronisation du tampon |
| 10 CN CCC ecriture de marques de fichiers |
| 11 CNCCCC espace |
| 12 NNNNNNNNNN requete |
| 13 COCCCC verification (06) |
| 14 COOCCC recuperation des donnees bufferisees |
| 15 ONO OOOOOO selection de mode (06) |
| 16 N NN NO reservation |
| 16 NN N reservation d'unite |
| 17 N NN NO liberation |
| 17 NN N liberation d'unite |
| 18 OOOOOOOO copie |
| 19 CNCCCC effacement |
| 1A ONO OOOOOO lecture du buffer SCSI (06) |
| 1B O chargement dechargement |
| 1B O digitalisation |
| 1B O arret d'impression |
| 1B O OO O arret demarrage de l'unite |
+=============================================================================+
Table 365 : (suite)
+=============================================================================+
| D - peripherique a acces Direct Clef de colonne |
| .T - peripherique a acces sequenTiel N = Necessaire |
| . I - Imprimante O = Optionnel |
| . P - Processeur C = Constructeur |
| . .W -WORM (CD-ROM inscriptible une fois) R = Reserve |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| OP DTIPWRSOMC Description |
|----------+----------+-------------------------------------------------------|
| 1C OOOOOOOOOO reception des resultats du diagnostic |
| 1D NNNNNNNNNN emission de diagnostic |
| 1E OO OO OO protection contre l'enlevement du medium |
| 1F |
| 20 C CC C |
| 21 C CC C |
| 22 C CC C |
| 23 C CC C |
| 24 C CCN definition de fenetre |
| 25 O lecture de fenetre |
| 25 N N N lecture de capacite |
| 25 N lecture de capacite de cd-rom |
| 26 C CC |
| 27 C CC |
| 28 O lecture de message (10) |
| 28 N NNNN lecture (10) |
| 29 C CC O lecture de generation |
| 2A O emission de message (10) |
| 2A O emission (10) |
| 2A N N N ecriture (10) |
| 2B O localisation |
| 2B O positionnement sur element |
| 2B O OO O deplacement (10) |
| 2C C O effacement (10) |
| 2D C O O lecture de bloc mis a jour |
| 2E O O O lecture et verification (10) |
| 2F O OO O verification (10) |
| 30 O OO O lecture de donnee haute (10) |
| 31 O position d'objet |
| 31 O OO O recherche de donnee egale (10) |
| 32 O OO O recherche de donnee basse (10) |
| 33 O OO O definition de limites (10) |
| 34 O lecture de l'etat du tampon de donnees |
| 34 O OO O pre-lecture |
| 34 O lecture de position |
| 35 O OO O synchronisation du cache |
| 36 O OO O verrouillage/deverrouillage du cache |
| 37 O O lecture de donnees defectueuses (10) |
| 38 O O digitalisation du medium |
| 39 OOOOOOOO comparaison |
| 3A OOOOOOOO copie et verification |
| 3B OOOOOOOOOO ecriture de tampon |
| 3C OOOOOOOOOO lecture de tampon |
| 3D O O mise a jour de bloc |
| 3E O OO O lecture longue |
| 3F O O O ecriture longue |
+=============================================================================+
Table 365 : (suite)
+=============================================================================+
| D - peripherique a acces Direct Clef de colonne |
| .T - peripherique a acces sequenTiel N = Necessaire |
| . I - Imprimante O = Optionnel |
| . P - Processeur C = Constructeur |
| . .W -WORM (CD-ROM inscriptible une fois) R = Reserve |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| OP DTIPWRSOMC Description |
|----------+----------+-------------------------------------------------------|
| 40 OOOOOOOOOO changement de definition |
| 41 O ecriture identique |
| 42 O lecture de sous-canal |
| 43 O lecture du TOC |
| 44 O lecture d'en-tete |
| 45 O lecture audio (10) |
| 46 |
| 47 O lecture audio MSF |
| 48 O lecture d'index de piste audio |
| 49 O lecture de piste relative (10) |
| 4A |
| 4B O reprise de pause |
| 4C OOOOOOOOOO trace de selection |
| 4D OOOOOOOOOO trace du buffer SCSI |
| 4E |
| 4F |
| 50 |
| 51 |
| 52 |
| 53 |
| 54 |
| 55 OOO OOOOOO mode de selection (10) |
| 56 |
| 57 |
| 58 |
| 59 |
| 5A OOO OOOOOO mode du buffer SCSI (10) |
| 5B |
| 5C |
| 5D |
| 5E |
| 5F |
+=============================================================================+
Table 365 : (fin)
+=============================================================================+
| D - peripherique a acces Direct Clef de colonne |
| .T - peripherique a acces sequenTiel N = Necessaire |
| . I - Imprimante O = Optionnel |
| . P - Processeur C = Constructeur |
| . .W -WORM (CD-ROM inscriptible une fois) R = Reserve |
| . . R - CD-ROM (lecture seule) |
| . . S - Scanner ou numeriseur |
| . . .O - memoire Optique |
| . . . M - changeur de Media |
| . . . C - peripherique de Communications |
| . . . . |
| OP DTLPWRSOMC Description |
|----------+----------+-------------------------------------------------------|
| A0 |
| A1 |
| A2 |
| A3 |
| A4 |
| A5 N deplacement de medium |
| A5 O lecture audio (12) |
| A6 O changement de medium |
| A7 |
| A8 O lecture de message (12) |
| A8 OO O lecture (12) |
| A9 O lecture de piste relative (12) |
| AA O emission de message (12) |
| AA O O ecriture (12) |
| AB |
| AC O effacement (12) |
| AD |
| AE O O ecriture et verification (12) |
| AF OO O verification (12) |
| B0 OO O recherche de donnee haute (12) |
| B1 OO O recherche de donnee egale (12) |
| B2 OO O recherche de donnee basse (12) |
| B3 OO O definition des limites (12) |
| B4 |
| B5 |
| B5 O demande d'adresse d'element volume |
| B6 |
| B6 O emission de TAG de volume |
| B7 O lecture des donnees de defauts (12) |
| B8 |
| B8 O lecture de l'etat d'element |
| B9 |
| BA |
| BB |
| BC |
| BD |
| BE |
| BF |
+=============================================================================+
XX.. PPrrooggrraammmmeess dd''eexxeemmppllee
Voici le programme exemple en C qui demande le constructeur et le
modele et indique si un medium est charge dans le peripherique.
#define DEVICE "/dev/sgc"
/* Programme de demonstration de l'interface SCSI generique */
#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 commandes SCSI */
int fd; /* descripteur de periph./fichier SCSI */
/* traite une commande SCSI complete. Utilise l'interface SCSI generique */
static int handle_scsi_cmd(unsigned cmd_len, /* longueur */
unsigned in_size, /* taille data IN */
unsigned char *i_buff, /* tampon IN */
unsigned out_size, /* taille data OUT */
unsigned char *o_buff /* tampon OUT */
)
{
int status = 0;
struct sg_header *sg_hd;
/* quelques controles de routine */
if (!cmd_len) return -1; /* cmd_len doit etre != 0 */
if (!i_buff) return -1; /* tampon IN doit etre != 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;
/* construction de l'en-tete du pilote generique */
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; /* pas 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 ) {
/* une erreur s'est produite */
fprintf( stderr, "ecriture (generique) resultat = 0x%x cmd = 0x%x\n",
sg_hd->result, i_buff[SCSI_OFF] );
perror("");
return status;
}
if (!o_buff) o_buff = i_buff; /* controle du pointeur du tampon */
/* recuperation du resultat */
status = read( fd, o_buff, SCSI_OFF + out_size);
if ( status < 0 || status != SCSI_OFF + out_size || sg_hd->result ) {
/* une erreur s'est produite */
fprintf( stderr, "lecture (generique) resultat = 0x%x cmd = 0x%x\n",
sg_hd->result, o_buff[SCSI_OFF] );
fprintf( stderr, "read(generic) sense "
"%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("");
}
/* Voyons si nous avons ce que nous attendions */
if (status == SCSI_OFF + out_size) status = 0; /* on a tout */
return status; /* 0 indique que tout est OK */
}
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
#define INQUIRY_REPLY_LEN 96
#define INQUIRY_VENDOR 8 /* Decalage sur le constructeur dans la reponse */
/* On demande le constructeur et le modele */
static unsigned char *Inquiry ( void )
{
unsigned char Inqbuffer[ SCSI_OFF + INQUIRY_REPLY_LEN ];
unsigned char cmdblk [ INQUIRY_CMDLEN ] =
{ INQUIRY_CMD, /* commande */
0, /* lun/reserve */
0, /* code page */
0, /* reserve */
INQUIRY_REPLY_LEN, /* longueur d'allocation */
0 };/* reserve/drapeau/lien */
memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
/*
* +------------------+
* | struct sg_header | <- cmd
* +------------------+
* | copie de cmdblk | <- cmd + SCSI_OFF
* +------------------+
*/
if (handle_scsi_cmd(sizeof(cmdblk), 0, cmd,
sizeof(Inqbuffer) - SCSI_OFF, Inqbuffer )) {
fprintf( stderr, "Echec de la demande\n" );
exit(2);
}
return (Inqbuffer + SCSI_OFF);
}
#define TESTUNITREADY_CMD 0
#define TESTUNITREADY_CMDLEN 6
#define ADD_SENSECODE 12
#define ADD_SC_QUALIFIER 13
#define NO_MEDIA_SC 0x3a
#define NO_MEDIA_SCQ 0x00
int TestForMedium ( void )
{
/* demande de l'etat READY */
static unsigned char cmdblk [TESTUNITREADY_CMDLEN] = {
TESTUNITREADY_CMD, /* commande */
0, /* lun/reserve */
0, /* reserve */
0, /* reserve */
0, /* reserve */
0};/* reserve */
memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
/*
* +------------------+
* | struct sg_header | <- cmd
* +------------------+
* | copie de cmdblk | <- cmd + SCSI_OFF
* +------------------+
*/
if (handle_scsi_cmd(sizeof(cmdblk), 0, cmd,
0, NULL)) {
fprintf (stderr, "Echec du test d'unite prete\n");
exit(2);
}
return
*(((struct sg_header*)cmd)->sense_buffer +ADD_SENSECODE) !=
NO_MEDIA_SC ||
*(((struct sg_header*)cmd)->sense_buffer +ADD_SC_QUALIFIER) !=
NO_MEDIA_SCQ;
}
void main( void )
{
fd = open(DEVICE, O_RDWR);
if (fd < 0) {
fprintf( stderr, "Il faut les droits lecture/ecriture sur "DEVICE".\n" );
exit(1);
}
/* on ecrit quelques champs du resultat de la requete */
printf( "%s\n", Inquiry() + INQUIRY_VENDOR );
/* on regarde si le medium est charge */
if (!TestForMedium()) {
printf("pas de medium charge\n");
} else {
printf("un medium est present\n");
}
}