La programmazione sotto SCSI di Andrea Vallinotto
Secondo esempio: INQUIRY
Il secondo esempio è un po' più complesso, e comporta la lettura dei dati di
Inquiry. Questi sono i dati fondamentali di un dispositivo, che riportano
una 'fotografia' in generale dell'unità in questione. I vari campi che si
possono leggere sono descritti in dettaglio nello standard: in questo caso
nell'SPC, perché questo, come il precendente TEST_UNIT_READY, è un comando che si
applica a tutti i tipi di periferiche. Anzi: è il comando che viene sempre inviato
all'inizializzazione della catena; serve all'host adapter per riconoscere
quali unità sono presenti, e comportarsi di conseguenza.
Come sempre, c'è una versione "ridotta all'osso" del comando, quella che devono
seguire tutti i prodotti. Poi alcuni dispositivi con un ricco set di comandi e
con una buona implementazione, ritornano (se richiesti) alcune notizie
addizionali: alcuni hard-disk IBM ad esempio, dicono anche il ... luogo di nascita,
ovvero il nome dello stabilimento che li ha prodotti. Nello SCSI-3 (SPC-2) inoltre,
questo comando è stato esteso per ritornare in maniera opportuna l'elenco di
tutti i comandi che l'unità supporta. Questo è veramente molto utile per gli
implementatori di software di alto livello. Purtroppo, essendo questa feature di
recente creazione, bisognerà attendere ancora qualche tempo per poterla vedere
nei prodotti in commercio.
In ogni caso, anche con una risposta minima, dai dati di Inquiry si ottengono
tutte le inforazioni essenziali su un device, ed anche un po' di più.
Dal punto di vista della programmazione, ciò che cambia è che dobbiamo riservare
uno spazio per i dati in entrata - e poi interpretarli, se vogliamo. La
documentazione SCSI del comando Inquiry dà tutte le informazioni necessarie per
l'interpretazione dei dati ritornati. La dimensione da riservare la ricaviamo
dai nostri abituali libri delle magie: in questo caso, l'SPC (o SPC-2). Il
numero minimo di bytes ritornati in questo caso è 36.
inquiry.c
Terzo esempio: uso della doppia lettura per READ_DEFECT_DATA
Il prossimo esempio illustra una tecnica spesso usata: la doppia lettura. Questo
genere di tecnica (che in effetti porta a dare due comandi), serve quando
si vuole effettuare una lettura di cui non si conosce la dimensione a priori.
Questo accade spesso, e a ben vedere anche l'esempio precedente poteva
beneficiare di questa tecnica (perché i dati di Inquiry sono al minimo
36, ma spesso di più).
Come si procede? Tutti i comandi che possono ritornare una lunghezza non
stimabile prima della chiamata, contengono nei primi bytes ritornati un campo
detto Additional length o List length. In questo campo
(che può essere di 8, 16 o più bit) viene ritornata la lunghezza complessiva dei
dati disponibili. Non a caso, lo SCSI permette che se la dimensione di RAM
allocata in memoria centrale è minore dei dati teoricamente disponibili,
vengano trasmessi solo quei dati per i quali è stato riservato lo spazio (il
campo scsi_Length). Riassumendo:
- Si invia un primo comando, avendo allocato la lunghezza necessaria
per arrivare a leggere il campo Additional length.
- Si legge il campo relativo e di conseguenza si rialloca il buffer dati
e si cambia il CDB (perché contiene Allocation Length!!).
- Si effettua la seconda lettura, e questa volta i dati saranno
trasferiti per intero.
Questa tecnica è da utilizzarsi quando la dimensione dei dati è molto variabile:
infatti nell'esempio precedente dell'Inquiry, per essere sicuri di prendere
tutti i dati, bastava allocare 252 miseri bytes. Al contrario, per letture più
grandi (come la defect list dell'esempio che segue, o le mode pages) è meglio usare questo
sistema, e non basarsi su una sovrastima mal fatta (del genere "640k
basteranno per tutti").
getd.c
Dare un SENSE ai nostri errori
ovvero come leggere i dati di SENSE
In caso di errore, se l'opportuno flag di AUTOSENSE è stato configurato, in sensebuffer->buf
troviamo il già menzionato buffer di sense, corrispondente ai dati in risposta al comando
REQUEST_SENSE (vedi SPC o SPC-2). È una sequenza di byte di lunghezza
minima (e spesso massima) di 18 bytes. In questi bytes è contenuta una
descrizione minuziosa del tipo di errore riscontrato. Anche in questo caso sta
al buon cuore del produttore dotare la periferica di un più o meno adeguato set
di codici d'errore. Lo standard di suo ce la mette tutta, definendo qualcosa
come più di 300 codici d'errore diversi (a fondo dell'articolo si trova un breve
elenco dei più strani).
La decodifica dei codici d'errori è pressochè gerarchica:
l'errore viene definito in maniera via via più precisa. Il primo campo da leggere
è il primo byte che può avere valori 0x70 o 0x71: in caso contrario il dispositivo
ha risposto in maniera non standard, e quindi il resto dei dati ha una
sintassi "vendor specific", cioè non standard (buona fortuna, e ricordatevi dei carboni
ardenti).
Il campo Sense key è un nibble (4 bit) che indica la categoria
generica dell'errore; quindi i due campi più specifici sono detti ASC e ASCQ,
ovvero Additional Sense Code ed Additional Sense Code Qualifier.
Combinando questi due valori, si ottiene il codice specifico dell'errore: l'elenco
completo si trova nella documentazione SCSI. L'include accluso (sense_codes.h) definisce tutti i
codici SCSI-2; essendo questi due bytes contigui ed allineati, si possono leggere
direttamente sulle architetture Big-endian. Per le little-endian
invece, c'è un'apposita macro per fare le conversioni.
Il campo Sense-Key specific infine, può contenere dei dati addizionali, nel
caso ce ne fosse bisogno.
Qualche altra cosa con cui far colpo sugli amici....
In genere, quando si invia sul bus un determinato comando, si deve attendere
fino al suo completamento per poterne inviare un altro (a meno che si stia
dialogando in sincorno con riselezione). Questo fatto in alcuni casi può non
essere desiderabile; anche nel caso della riselezione infatti, non è possibile
inviare un secondo comando allo stesso dispositivo, fin quando il primo non è
stato completato. Nel caso di operazioni che richiedono molto tempo, è utile
poter sapere come stanno andando le cose. La soluzione sta in un flag che alcuni
comandi implementano, detto Immed (= 'immediate'). Per i
dispositivi che implementano questo flag (che è sempre opzionale), il
comportamento è il seguente: al ricevimento del comando, viene validato il CDB,
e l'eventuale lista dei parametri in fase dati, quindi il comando ritorna subito lo
stato.
Mentre l'operazione è in corso, il dispositivo risponde solo ad un limitato set
di comandi, perché ovviamente è occupato.
Un buon esempio (per gli hard disk) è il comando FORMAT_UNIT, che effettua la
formattazione a basso livello - "Kids, don't try this at home".
In un'operazione così lunga (e delicata), sarebbe bello poter aver indicazione
se tutto sta procedendo per il verso giusto, ed a che punto è l'operazione.
Impostando a 1 il flag di Immed (che in questo specifico caso si trova nella
parameter list), possiamo avere l'indicazione del progresso inviando successivi
comandi REQUEST_SENSE: durante la formattazione il disco risponderà con dei
valori ASC - ASCQ corrispondenti a LOGICAL UNIT NOT READY FORMAT IN PROGRESS
; il campo Sense-key specific avrà un progress indicator
codificato in maniera particolare.
- ASSIGN_FAILURE_OCCURRED
- Assign Diff: NIL:
- AUTOMATIC_DOCUMENT_FEEDER_LIFT_UP
- Chiudi 'sto coso!
- BLOCK_NOT_COMPRESSIBLE
- È inutile che ti ostini.
- CANNOT_WRITE_MEDIUM_UNKNOWN_FORMAT
- Banana in disk drive.
- CLEANING_REQUESTED
- Mi insaponi?
- COMMANDS_CLEARED_BY_ANOTHER_INITIATOR
- Questa catena è troppo piccola per due controller.
- COPY_PROT_KEY_EXCH_FAIL_AUTHENTICATION_FAILURE
- La chiave pirata non funziona...
- DOCUMENT_JAM_IN_AUTOMATIC_DOCUMENT_FEEDER
- E adesso chi lo sblocca?
- ERROR_TOO_LONG_TO_CORRECT
- È una storia troppo lunga...
- EXCHANGE_OF_LOGICAL_UNIT_FAILED
- Mai giocare al gioco delle tre carte.
- FAILED_TO_SENSE_TOP_OF_FORM
- Ma quant'è lungo il foglio?
- GENERATION_DOES_NOT_EXIST
- La generazione X
- INSUFFICIENT_REGISTRATION_RESOURCES
- Shareware di poco successo.
- INVALID_COMBINATION_OF_WINDOWS_SPECIFIED
- Windows'98 e X-Windows
- LAMP_FAILURE
- Hanno spento la luce al fondo del tunnel.
- LOGICAL_UNIT_NOT_READY_MANUAL_INTERVENTION_REQUIRED
- Dagli un calcio e riparte.
- OUT_OF_FOCUS
- Oggi vedo doppio.
- PACKET_DOES_NOT_FIT_IN_AVAILABLE_SPACE
- Allargare il deposito, please.
- TOO_MANY_WINDOWS_SPECIFIED
- Windows'95, Windows'98, Windows NT, etc...
- WARNING_SPECIFIED_TEMPERATURE_EXCEEDED
- Ho il cervello arrosto. Meglio piantarla qui.
|
|
|