[LINUX] Übersetzung von scsi_mid_low_api.txt

Ich habe scsi_mid_low_api.txt für meine eigene Studie übersetzt, machen Sie sich also eine Notiz. Introduction Dieses Dokument beschreibt die Schnittstelle zwischen dem Linux SCSI-Treiber der mittleren Ebene und dem SCSI-Treiber der unteren Ebene. Treiber niedrigerer Ebene (im Folgenden LLDs) werden durch verschiedene Dinge aufgerufen, wie z. B. Host-Bus-Adapter-Treiber (im Folgenden HBA) und Host-Treiber (im Folgenden HD). In diesem Zusammenhang bedeutet "Host" die Brücke, die den E / A-Bus (z. B. PCI oder ISA) mit einem einzelnen SCSI-Initiator-Port verbindet, der sich auf dem SCSI-Transport befindet. Der "Initiator" -Port (ein SCSI-Begriff, siehe SAM-3) sendet SCSI-Befehle an den "Ziel" SCSI-Port (z. B. Festplatte). In einem laufenden System können viele LLDs vorhanden sein, es gilt jedoch nur eine pro Hardwaretyp. Die meisten LLDs können einen oder mehrere SCSI-HBAs steuern. Einige HBAs enthalten mehrere Hosts.

SCSI-Transport kann auch ein externer Bus sein, der unter Linux bereits über ein eigenes Subsystem verfügt. (Beispiel: USB und ieee1394) In solchen Fällen wird die LLD im SCSI-Subsystem zu einer Softwarebrücke zu den Subsystemen anderer Treiber. Beispiele sind der USB-Speichertreiber (in dirvers / usb / storage) und der Treiber iee1394 / sbp2 (in drivers / ieee1394).

Beispielsweise steuert das aic7xxx LLD den Adaptec SCSI Parallel Interface (SPI) -Controller, der die 7xxx-Chipserie des Unternehmens verwendet. Aic7xxx LLD kann in den Kernel integriert oder als Modul geladen werden. Auf einem Linux-System läuft nur eine aic7xxx-LLD, die jedoch möglicherweise viele HBAs steuert. Diese HBAs können als PCI-Tochterplatinen vorhanden sein oder in die Hauptplatine (oder in beide) integriert sein. Einige aic7xxx-basierte HBAs sind Dual-Controller. Daher repräsentiert es zwei Hosts. Wie der neueste HBA hat jeder Host in aic7xxx seine eigene PCI-Geräteadresse. [Eine Eins-zu-Eins-Korrespondenz zwischen dem SCSI-Host und dem PCI-Gerät ist üblich, aber nicht erforderlich. (Beispiel: Bei Verwendung eines ISA-Adapters)]

Die SCSI-Mittelschicht isoliert die LLD von anderen Schichten, wie dem SCSI-Treiber für die obere Schicht und dem Blockschichttreiber.

Dieses Dokument entspricht in etwa der Linux-Kernel-Version 2.6.8.

Documentation Das SCSI-Dokumentationsverzeichnis befindet sich im Linxu-Quellbaum, normalerweise Documentation / scsi. Die meisten Dokumente sind Klartext (dh ASCII). Diese Datei heißt scsi_mid_low_api.txt und befindet sich in diesem Verzeichnis. Eine neuere Kopie dieses Dokuments http://web.archive.org/web/20070107183357rn_1/sg.torque.net/scsi/ Sie können es bei finden. Dort sind viele LLDs dokumentiert. (Beispiel: Aic7xxx.txt). Die mittlere SCSI-Ebene wird in scsi.txt kurz erwähnt, die eine URL zu einem Dokument enthält, das die Linux Kernel 2.4-Familie von SCSI-Subsystemen beschreibt. Die beiden Treiber der oberen Ebene haben Dokumente in diesem Verzeichnis. Das heißt, st.txt (SCSI-Bandtreiber) und scsi-generic.txt (für SG-Treiber).

Dokumente oder URLs zu einigen LLDs befinden sich möglicherweise im C-Quellcode oder im selben Verzeichnis wie der C-Quellcode. Um beispielsweise die URL für den USB-Massenspeichertreiber zu finden, suchen Sie im Verzeichnis / usr / src / linux / drivers / usb / storage.

Driver structure Traditionell bestehen LLDs für SCSI-Subsysteme aus mindestens zwei Dateien im Verzeichnis drivers / scsi. Ein Treiber namens xyz hat beispielsweise eine Header-Datei xyz.h und eine Quelldatei xyz.c. [Eigentlich gibt es keinen klaren Grund, warum Sie nicht alle in eine Datei schreiben können. Die Header-Datei kann extra sein]. Einige Treiber, die auf verschiedene Betriebssysteme portiert sind, haben mehr als eine Datei. Beispielsweise verfügt der aic7xxx-Treiber über separate Dateien für generische und betriebssystemspezifische Dateien (z. B. FreeBSD und Linux). Solche Treiber erstellen in der Regel ihre eigenen Verzeichnisse im Verzeichnis drivers / scsi.

Die folgenden Dateien (im Verzeichnis drivers / scsi) sollten beim Hinzufügen einer neuen LLD zu Linux beachtet werden. Makefile und Kconfig. Es ist wahrscheinlich am besten herauszufinden, wie Ihre vorhandene LLD konfiguriert ist.

Änderungen wurden an dieser Schnittstelle vorgenommen, als sich der Entwicklungskern der 2.5er-Serie zur Produktionsserie der 2.6er-Serie entwickelte. Ein Beispiel hierfür ist der Treiberinitialisierungscode, der die beiden Modelle aktiviert. Die alte Initialisierung basiert auf dem Host, der beim Laden des HBA-Treibers gefunden wurde. Ähnliche finden Sie in der 2.4-Serie. Dies wird als "passives" Initialisierungsmodell bezeichnet. Das neue Modell ermöglicht das Ein- und Ausstecken von HBA-Hotplugs während der Lebensdauer von LLD. Dies wird als "Hotplug" -Initialisierungsmodell bezeichnet. Das neue Modell wird bevorzugt, da es sowohl herkömmliche SCSI-Geräte, die permanent verbunden sind, als auch moderne SCSI-Geräte, die mit Hotplugs verbunden sind (z. B. USB- oder IEEE1394-verbundene Digitalkameras), auf dieselbe Weise behandelt. Beide Initialisierungsmodelle werden in den folgenden Abschnitten erläutert.

Es gibt verschiedene Möglichkeiten, die LLD mit dem SCSI-Subsystem zu verbinden: a) Führen Sie die Funktion direkt von der mittleren Ebene aus b) Über den Funktionszeiger für die Funktionsregistrierung von Mid Level. Mid Level wird diese Funktionen zu einem späteren Zeitpunkt ausführen. LLD bietet Implementierungen dieser Funktionen. c) Direkter Zugriff auf Instanzen bekannter Datenstrukturen, die von Mid Level verwaltet werden

a) Gruppenfunktionen sind im folgenden Kapitel "Mitgelieferte Funktionen der mittleren Ebene" aufgeführt.

b) Gruppenfunktionen sind im folgenden Kapitel "Schnittstellenfunktionen" aufgeführt. Diese Funktionszeiger sind in "struct scsi_host_template" vorhanden und werden von scsi_host_alloc () übergeben (* Hinweis 1). Funktionsschnittstellen, die LLD nicht bereitstellen möchte, setzen die entsprechenden Mitglieder von scsi_host_template auf NULL. Die Definition einer Instanz von scsi_host_template im Dateibereich setzt einen Funktionszeiger, der nicht explizit auf NULL initialisiert wurde.

c) Seien Sie vorsichtig, wenn Sie Gruppen verwenden, insbesondere in einer "Hotplug" -Umgebung. Die LLD muss die Lebensdauer der Instanz kennen, die mit der mittleren Ebene und anderen Ebenen geteilt wird.

Alle im LLD definierten Funktionen und alle im Dateibereich definierten Daten sollten statisch sein. Beispielsweise kann die in der LLD mit dem Namen xxx definierte Funktion slave_alloc () als "static int xxx_slave_alloc (struct scsi_device * sdev) {/ * code * /}" definiert werden.

(* Hinweis 1) Die Funktion scsi_host_alloc () wird fast immer durch die Funktion scsi_register () ersetzt. Die Funktionen scsi_register () und scsi_unregister () bleiben erhalten, um die Unterstützung für das passive Initialisierungsmodell aufrechtzuerhalten.

Hotplug initialization model Dieses Modell steuert, wann die LLD den SCSI-Host einführt und aus dem SCSI-Subsystem entfernt. Der Host wird so schnell wie die Treiberinitialisierung installiert und entfernt, sobald der Treiber heruntergefahren wird. Der Treiber antwortet normalerweise auf einen Rückruf von sysfs probe (), der angibt, dass ein HBA erkannt wurde. Nachdem überprüft wurde, ob das neue Gerät das ist, was die LLD steuern möchte, initialisiert die LLD den HBA und registriert dann den neuen Host auf der mittleren SCSI-Ebene.

Während der LLD-Initialisierung sollte sich der Treiber auf dem entsprechenden E / A-Bus registrieren, auf dem er erwartet, dass der HBA erkannt wird. (Beispiel: PCI-Bus). Dies ist wahrscheinlich über sysfs möglich. Einige Treiberparameter, insbesondere diejenigen, die nach dem Laden des Treibers beschreibbar sind, können zu diesem Zeitpunkt auch bei sysfs registriert werden. Die mittlere SCSI-Ebene erkennt die LLD, wenn sie den ersten HBA registriert.

Nach einiger Zeit erkennt die LLD den HBA und die nachfolgende allgemeine Anrufsequenz zwischen der LLD und der mittleren Ebene. Dieses Beispiel zeigt die mittlere Ebene, die nach neu eingeführten HBAs sucht, bei denen nur die ersten beiden der drei SCSI-Geräte eine Antwort zurückgeben.

        HBA PROBE: assume 2 SCSI devices found in scan
LLD                   mid level                    LLD
===-------------------=========--------------------===------
scsi_host_alloc()  -->
scsi_add_host()  ---->
scsi_scan_host()  -------+
                         |
                slave_alloc()
                slave_configure() -->  scsi_adjust_queue_depth()
                         |
                slave_alloc()
                slave_configure()
                         |
                slave_alloc()   ***
                slave_destroy() ***
------------------------------------------------------------

Wenn LLD die Standardeinstellungen für die Warteschlange anpassen möchte, ruft es scsi_adjust_queue_depth () in der Routine Slave_configure () auf.

*** Slave_alloc () -, Slave_destroy () -Paare werden für SCSI-Geräte aufgerufen, bei denen die mittlere Ebene nach dem Versuch eines Scans nicht reagiert.

Wenn der HBA entfernt wird, kann er Teil des normalen Herunterfahrvorgangs sein, der mit dem entladenen LLD-Modul verbunden ist, oder es kann eine Antwort auf den "Hot Unplug" sein, der durch Aufrufen des sysfs remove () - Rückrufs beabsichtigt ist. Vielleicht. In beiden Fällen ist die Reihenfolge dieselbe.

    HBA REMOVE: assume 2 SCSI devices attached
LLD                      mid level                 LLD
===----------------------=========-----------------===------
scsi_remove_host() ---------+
                            |
                     slave_destroy()
                     slave_destroy()
scsi_host_put()
------------------------------------------------------------

Es kann für LLD nützlich sein, einer Instanz der Scsi_Host-Struktur zu folgen (ein Zeiger auf den Rückgabewert von scsi_host_alloc ()). Solche Instanzen gehören der mittleren Ebene. Instanzen der Scsi_Host-Struktur werden über scsi_host_put () freigegeben, wenn der Referenzzähler Null erreicht.

Das interessante Entfernen des HBA, der die Festplatte steuert, die die SCSI-Befehle im bereitgestellten Dateisystem verarbeitet, ist eine interessante Situation. Die Referenzzähllogik wurde auf mittlerer Ebene eingeführt, um viele Probleme im Zusammenhang mit der mittleren Ebene anzugehen. Siehe das folgende Kapitel zur Referenzzählung.

Das Konzept des Hotplugs kann auf SCSI-Geräte erweitert werden. Derzeit scannt die Funktion scsi_scan_host () beim Hinzufügen des HBA das SCSI-Gerät, das an den SCSI-Transport des HBA angeschlossen ist. Bei neueren SCSI-Transporten kann der HBA nach Abschluss des Scanvorgangs auf neue SCSI-Geräte aufmerksam werden. Das LLD kann die folgende Sequenz verwenden, um die mittlere Ebene auf das SCSI-Gerät aufmerksam zu machen.

             SCSI DEVICE hotplug
LLD                   mid level                    LLD
===-------------------=========--------------------===------
scsi_add_device()  ------+
                         |
                    slave_alloc()
                    slave_configure()   [--> scsi_adjust_queue_depth()]
------------------------------------------------------------

In ähnlicher Weise kann die LLD feststellen, dass das SCSI-Gerät entfernt oder die Verbindung zum SCSI-Gerät unterbrochen wurde. Einige vorhandene SCSI-Transporte (z. B. SPI) wissen möglicherweise nicht, dass das SCSI-Gerät entfernt wurde, bis der SCSI-Befehl zum Offline-Schalten des von Mid-Level ausgegebenen SCSI-Geräts fehlschlägt. Das LLD, das das Entfernen des SCSI-Geräts erkennt, kann das Entfernen aus der oberen Schicht in der folgenden Reihenfolge starten.

              SCSI DEVICE hot unplug
LLD                      mid level                 LLD
===----------------------=========-----------------===------
scsi_remove_device() -------+
                            |
                     slave_destroy()
------------------------------------------------------------

Für LLD kann es nützlich sein, einer Instanz der scsi_device-Struktur zu folgen (Zeiger werden als Parameter an Rückrufe für Slave_alloc () und Slave_Configure () übergeben). Solche Instanzen gehören der mittleren Ebene. Die scsi_device-Struktur wird nach slave_destroy () freigegeben.

Passive initialization model Diese älteren LLDs enthalten eine Datei mit dem Namen "scsi_module.c" in ihrem Quellcode. Damit diese Datei funktioniert, müssen Sie eine Instanz der Struktur scsi_host_template mit dem Namen driver_template definieren. Hier ist eine typische Codesequenzverwendung für dieses Modell: static struct scsi_host_template driver_template = { ... }; #include "scsi_module.c" Die Datei Scsi_module.c enthält zwei Funktionen: --Init_this_scsi_driver () Wird ausgeführt, wenn LLD initialisiert wird (d. H. Beim Start oder beim Laden des Moduls). --Exit_this_scsi_driver () Wird ausgeführt, wenn LLD heruntergefahren wird (wenn das Modul entladen wird). Hinweis: Diese Funktionen sind mit den Modifikatoren __init und __exit gekennzeichnet, daher sollte LLD nicht explizit aufgerufen werden. (Weil der Kernel läuft)

Dies ist ein Beispiel, bei dem zwei Hosts erkannt werden (detect () gibt 2 zurück) und auf jedem Host ein SCSI-Bus-Scan durchgeführt wird, um ein SCSI-Gerät zu erkennen. (Das zweite SCSI-Gerät hat nicht geantwortet).

LLD                      mid level                 LLD
===----------------------=========-----------------===------
init_this_scsi_driver() ----+
                            |
                         detect()  -----------------+
                             |                       |
                            |                scsi_register()
                            |                scsi_register()
                            |
                      slave_alloc()
                      slave_configure()  -->  scsi_adjust_queue_depth()
                      slave_alloc()   ***
                      slave_destroy() ***
                            |
                      slave_alloc()
                      slave_configure()
                      slave_alloc()   ***
                      slave_destroy() ***
------------------------------------------------------------

Mid-Level deaktiviert die Warteschlange mit Tags, ruft scsi_adjust_queue_depth () auf und legt "cmd_per_lun" als Warteschlangenlänge für diesen Host fest. Diese Einstellungen können mit Slave_configure () von LLD überschrieben werden. *** Ein Paar aus Slave_alloc () und Slave_detroy () wird für SCSI-Geräte aufgerufen, deren mittlere Ebene versucht hat zu scannen und nicht reagiert hat.

Unten sehen Sie die Reihenfolge, in der das LLD heruntergefahren wird.

LLD                      mid level                 LLD
===----------------------=========-----------------===------
exit_this_scsi_driver() ----+
                            |
                     slave_destroy()
                         release()   -->   scsi_unregister()
                            |
                     slave_destroy()
                        release()   -->   scsi_unregister()
------------------------------------------------------------

LLD muss slave_destroy () nicht definieren (d. H. Es ist optional).

Der Nachteil des Modells der "passiven Initialisierung" besteht darin, dass das Registrieren und Aufheben der Registrierung von Hosts mit der LLD-Initialisierung und dem Herunterfahren verbunden ist. Sobald die LLD initialisiert ist, ist es nicht einfach, einen neu entstehenden Host (z. B. über einen Hotplug) hinzuzufügen, ohne den Treiber herunterzufahren oder neu zu initialisieren. Es kann möglich sein, eine LLD für beide Initialisierungsmodelle zu schreiben.

Reference Counting Der Scsi_Host-Struktur wurde eine Referenzzählungsinfrastruktur hinzugefügt. Dies erweitert effektiv den Besitz der Scsi_Host-Instanz durch die verschiedenen SCSI-Schichten, die sie verwenden. Zuvor befanden sich solche Instanzen ausschließlich im Besitz von Mid Level. LLDs müssen diese Referenzzählungen normalerweise nicht direkt manipulieren, in einigen Fällen jedoch.

Es gibt drei interessante Referenzzählfunktionen, die sich auf die Scsi_Host-Struktur beziehen. --scsi_host_alloc (): Gibt einen Zeiger auf eine neue Instanz der Scsi_Host-Struktur mit dem Referenzzähler 1 zurück. ^^ --scsi_host_get (): Fügt dem Referenzzähler für eine bestimmte Instanz 1 hinzu. --scsi_host_put (): Verringert den Referenzzähler für eine bestimmte Instanz um 1. Wenn der Referenzzähler 0 erreicht, geben Sie die angegebene Instanz frei

Der Struktur Scsi_device wurde eine Referenzzählungsinfrastruktur hinzugefügt. Der Besitz von Scsi_device-Instanzen wird effektiv durch die verschiedenen SCSI-Schichten erweitert, die sie verwenden. Zuvor befanden sich solche Instanzen ausschließlich im Besitz von Mid Level. Schauen Sie sich die Zugriffsfunktionen an, die gegen Ende von Include / scsi / scsi_device.h deklariert wurden. Wenn die LLD eine Kopie des Zeigers auf die Scsi_device-Instanz behalten möchte, sollte sie scsi_device_get () verwenden, um den Referenzzähler zu erhöhen. Wenn der Zeiger fertig ist, können Sie mit scsi_device_put () die Referenzanzahl reduzieren (und möglicherweise entfernen).

^^ Die Scsi_Host-Struktur hat tatsächlich zwei Referenzzählungen, die von diesen Funktionen parallel bearbeitet werden. (Shost_dev und host_gendev?)

Conventions Zunächst finden Sie Ideen zum Codierungsstil von Linus Tobals C in der Datei Documentation / CodingStyle.

Als nächstes wird versucht, Typedefs zu verbieten, die Synonyme für Struktur-Tags einführen. Beide befinden sich weiterhin im SCSI-Subsystem, aber solche typedefs wurden in eine einzelne Datei scsi_typedefs.h verschoben, um das zukünftige Entfernen zu vereinfachen. Zum Beispiel: "typedef struct scsi_cmnd Scsi_Cmnd;"

Außerdem fördern die meisten C99-Verbesserungen Erweiterungen, für die sie vom zugehörigen gcc-Compiler unterstützt werden. Daher werden Struktur- und Sequenzinitialisierer im C99-Stil bei Bedarf empfohlen. Übertreiben Sie es nicht, VLAs werden noch nicht richtig unterstützt. Die Ausnahme ist die Verwendung von Kommentaren im "//" - Stil. / * * / Stilkommentare werden unter Linux weiterhin bevorzugt.

Gut geschriebener, getesteter und dokumentierter Code muss nicht neu formuliert werden, um den oben genannten Konventionen zu entsprechen. Beispielsweise kommt der aic7xxx-Treiber von FreeBSD- und Adaptec-Labors zu Linux. Sicherlich haben FreeBSD und Adaptec ihre eigenen Codierungskonventionen.

Mid level supplied functions Diese Funktionen werden von der mittleren SCSI-Ebene zur Verwendung durch LLD bereitgestellt. Die Namen dieser Funktionen (dh Einstiegspunkte) werden exportiert, damit die LLD darauf zugreifen kann. Der Kernel lädt und bereitet die mittlere SCSI-Ebene für die Initialisierung vor, bevor eine LLD initialisiert wird. Die folgenden Funktionen sind in alphabetischer Reihenfolge aufgeführt und alle ihre Funktionsnamen beginnen mit "scsi_".

Summary:
scsi_activate_tcq - turn on tag command queueing
scsi_add_device - creates new scsi device (lu) instance
scsi_add_host - perform sysfs registration and set up transport class
scsi_adjust_queue_depth - change the queue depth on a SCSI device
scsi_bios_ptable - return copy of block device's partition table
scsi_block_requests - prevent further commands being queued to given host
scsi_deactivate_tcq - turn off tag command queueing
scsi_host_alloc - return a new scsi_host instance whose refcount==1
scsi_host_get - increments Scsi_Host instance's refcount
scsi_host_put - decrements Scsi_Host instance's refcount (free if 0)
scsi_partsize - parse partition table into cylinders, heads + sectors
scsi_register - create and register a scsi host adapter instance.
scsi_remove_device - detach and remove a SCSI device
scsi_remove_host - detach and remove all SCSI devices owned by host
scsi_report_bus_reset - report scsi _bus_ reset observed
scsi_scan_host - scan SCSI bus
scsi_track_queue_full - track successive QUEUE_FULL events 
scsi_unblock_requests - allow further commands to be queued to given host
scsi_unregister - [calls scsi_host_put()]

Details:

Kürzung

Interface Functions Schnittstellenfunktionen werden von LLD definiert und ihre Funktionszeiger werden in Instanzen der von scsi_host_alloc () [oder scsi_register () / init_this_scsi_driver ()] zugewiesenen Struktur scsi_host_template platziert. Einige sind obligatorisch. Schnittstellenfunktionen sollten als statisch deklariert werden. Die akzeptierte Konvention ist, dass der Treiber "xyz" seine Slave_configure () -Funktion als statisch int xyz_slave_configure (struct scsi_device * sdev) deklariert. Ebenso alle unten aufgeführten Schnittstellenfunktionen.

Ein Zeiger auf diese Funktion sollte im Mitglied slave_configure der Strukturinstanz scsi_host_template platziert werden. Ein Zeiger auf eine solche Instanz sollte an scsi_host_alloc () [oder scsi_register () / init_this_scsi_driver ()] der mittleren Ebene übergeben werden.

Schnittstellenfunktionen befinden sich auch direkt über der Definition der Struktur scsi_host_template in der Datei include / scsi / scsi_host.h. In einigen Fällen finden Sie Details darunter in scsi_host.h.

Die Schnittstellenfunktionen sind unten in alphabetischer Reihenfolge aufgeführt.

Summary:
bios_param - fetch head, sector, cylinder info for a disk
detect - detects HBAs this driver wants to control
eh_timed_out - notify the host that a command timer expired
eh_abort_handler - abort given command
eh_bus_reset_handler - issue SCSI bus reset
eh_device_reset_handler - issue SCSI device reset
eh_host_reset_handler - reset host (host bus adapter)
info - supply information about given host
ioctl - driver can respond to ioctls
proc_info - supports /proc/scsi/{driver_name}/{host_no}
queuecommand - queue scsi command, invoke 'done' on completion
release - release all resources associated with given host
slave_alloc - prior to any commands being sent to a new device 
slave_configure - driver fine tuning for given device after attach
slave_destroy - given device is about to be shut down
Details:

Kürzung

Data Structures struct scsi_host_template Für jede LLD *** gibt es eine "struct scsi_host_template". Es wird als statischer Dateibereich in der Treiberheaderdatei initialisiert. Mitglieder, die nicht explizit auf diese Weise initialisiert wurden, werden auf 0 oder NULL gesetzt. Die interessierenden Mitglieder sind: name --Treibername (Leerzeichen erlaubt, aber bis zu 80 Zeichen) proc_name-Wird von sysfs in einem der Verzeichnisse <proc_name> und "drivers" in "/ proc / scsi / <proc_name> / <host_no>" verwendet. Außerdem sollte "proc_name" nur Zeichen enthalten, die von Unix-Dateinamen akzeptiert werden. (* queuecommand) () --mid level ist der Hauptrückruf, mit dem SCSI-Befehle in die LLD eingefügt werden. Die Struktur scsi_host_template wird in include / scsi / scsi_host.h definiert und kommentiert.

*** In extremen Situationen kann ein Treiber mehrere Instanzen haben, wenn ein Treiber mehrere verschiedene Hardwareklassen steuert. (z. B. behandelt LLD sowohl ISA- als auch PCI-Karten und hat für jede Klasse eine separate scsi_host_template-Struktur).

struct Scsi_Host Für jeden von LLD gesteuerten Host (HBA) gibt es eine Scsi_Host-Struktur. Die Scsi_Host-Struktur hat viele Mitglieder gemeinsam mit der "struct scsi_host_template". Wenn eine neue Scsi_Host-Strukturinstanz erstellt wird (erstellt von scsi_host_alloc () in hosts.c), werden ihre gemeinsamen Mitglieder aus der scsi_host_template-Strukturinstanz des Treibers initialisiert. Die interessierenden Mitglieder sind:

host_no-Die einzige systemweite Nummer, die diesen Host identifiziert. Die Werte werden in aufsteigender Reihenfolge von 0 zugewiesen. can_queue - muss größer als 0 sein. Senden Sie nicht mehr Befehle an den Adapter als den Wert von can_queue. this_id - Repräsentiert die ID des SCSI-Hosts (Initiators). Bei Unbekannt auf -1 setzen. sg_tablesize - Maximale Anzahl von vom Host zugelassenen Scatter-Gather-Elementen. Wenn 0, bedeutet dies, dass der Host das Scatter-Gather nicht unterstützt. max_sectors - Die maximale Anzahl von Sektoren, die von einem einzelnen SCSI-Befehl zugelassen werden (normalerweise 512 Byte). Der Anfangswert 0 führt zur Einstellung von SCSI_DEFAULT_MAX_SECTORS (definiert in scsi_host.h), die derzeit 1024 setzt. Bisher beträgt die maximale Übertragungslänge einer Festplatte 512 KB, wenn max_sectors nicht definiert ist. Bitte beachten Sie, dass diese Größe für das Hochladen von Festplatten-Firmware möglicherweise nicht ausreicht. cmd_per_lun - Maximale Anzahl von Befehlen, die an ein vom Host gesteuertes Gerät in die Warteschlange gestellt werden können. Überschreiben durch LLD mit dem Aufruf von scsi_adjust_queue_depth (). Wenn unchecked_isa_dma -1 =>, werden nur die unteren 16 MB RAM verwendet (ISA-DMA-Adressierungsgrenze), und wenn 0> =, können 32-Bit- oder mehr DMA-Adressräume vollständig verwendet werden. use_clustering --1 => SCSI-Befehle der mittleren Ebene können zusammengeführt werden. 0 => Das Zusammenführen von SCSI-Befehlen ist nicht zulässig hostt - Ein Zeiger auf die scsi_host_template-Struktur des Treibers aus der generierten Scsi_Host-Strukturinstanz. Der Name von hostt-> proc_name -LLD. Dies ist der Name des von sysfs verwendeten Treibers. transportt - Ein Zeiger auf die Instanz scsi_transport_template (falls vorhanden). FC- und SPI-Transporte werden derzeit unterstützt. sh_list-Eine bidirektionale verknüpfte Liste mit allen Scsi_Host-Instanzen. (Derzeit und in aufsteigender Reihenfolge von host_no). my_devices - Eine bidirektionale verknüpfte Liste mit scsi_device-Strukturen, die zu diesem Host gehören. hostdata [0] - Reservierter Bereich für LLD am Ende der Scsi_Host-Struktur. Die Größe wird durch das zweite Argument von scsi_host_alloc () oder scsi_register () festgelegt. vendor_id - Ein eindeutiger Wert, der die vom Anbieter für Scsi_Host bereitgestellte LLD identifiziert. Wird meistens verwendet, um die Nachrichtenanforderung des Anbieters für spezielles Warmwasser zu validieren. Der Wert besteht aus dem Bezeichnertyp und dem herstellerspezifischen Wert. Eine Beschreibung der gültigen Formate finden Sie unter scsi_netlink.h.

Die scsi_host-Struktur ist in include / scsi / scsi_host.h definiert.

struct scsi_device Im Allgemeinen gibt es eine Instanz dieser Struktur für jede SCSI-LU auf einem Host. Das mit dem Host verbundene SCSI-Gerät wird durch die Kanalnummer, die Ziel-ID und die Nummer der logischen Einheit (lun) eindeutig identifiziert. Diese Struktur ist in include / scsi / scsi_device.h definiert.

struct scsi_cmnd Eine Instanz dieser Struktur gibt einen SCSI-Befehl an die LLD weiter und gibt eine Antwort an die mittlere Ebene zurück. Die mittlere SCSI-Ebene stellt SCSI-Befehle nicht über dem von scsi_adjust_queue_depth () (oder cmd_per_lun in der Scsi_Host-Struktur) beabsichtigten Wert in die Warteschlange. Für jedes SCSI-Gerät ist mindestens eine Instanz der Struktur scsi_cmnd verfügbar. Die interessierenden Mitglieder sind:

cmnd --Array mit SCSI-Befehlen cmnd_len - Länge des SCSI-Befehlsarrays (in Bytes) sc_data_direction - Die Richtung der Datenübertragung während der Datenphase. Siehe "enum dma_data_direction" in include / linux / dma-Mapping.h request_bufflen - Anzahl der zu übertragenden Datenbytes (0 bedeutet keine Übertragungsdaten) use_sg - == 0-> Verwenden Sie nicht die Streuliste. Das heißt, die Daten, die vom / zum Anforderungspuffer-> 0-> Streusammelliste von request_bufffer unter Verwendung des Elements use_sg (tatsächlich ein Array) übertragen werden. Request_buffer - Der Datenpuffer oder die Streusammelliste, die von der Einstellung von use_sg abhängt welcher. Scatter-Gather-Elemente werden durch die Struktur-Scatterliste in include / asm / Scatterlist.h definiert. done - Ein Funktionszeiger, der vom LLD aufgerufen werden soll, wenn der SCSI-Befehl ausgeführt wird (erfolgreich oder anderweitig). Wenn die LLD den Befehl akzeptiert (d. H. Queuecommand () gibt 0 zurück oder gibt 0 zurück), sollte er nur von der LLD aufgerufen werden. LLD kann vor dem Ende von queuecommand () gestartet werden. LLD sollte vor dem Aufruf von result --done festgelegt werden. Ein Wert von 0 bedeutet, dass der Befehl erfolgreich war. (Und alle Daten wurden vom / zum SCSI-Zielgerät übertragen.) Das Ergebnis ist eine 32-Bit-Ganzzahl ohne Vorzeichen, die als 4 verwandte Bytes angesehen wird. Der Wert des SCSI-Status ist LSB. Siehe die Konstanten, die den Makros status_byte (), msg_byte (), host_byte (), driver_byte () in Include / scsi / scsi.h zugeordnet sind. sense_buffer - Das Array, das geschrieben werden soll, wenn der SCSI-Status (LSB des Ergebnisses) auf CHECK CONDITION (2) gesetzt ist (maximale Länge: SCSI_SENSE_BUFFERSIZE-Bytes). Wenn CHECK CONDITION gesetzt ist und die oberen 4 Bits von sense_buffer [0] den Wert 7 haben, geht die mittlere Ebene davon aus, dass das sense_buffer-Array einen gültigen SCSI-Sense-Puffer enthält. Andernfalls gibt die mittlere Ebene den Befehl REQUESET SENSE SCSI aus, um den Erfassungspuffer abzurufen. Die letztere Strategie ist fehleranfällig, wenn eine Befehlswarteschlange vorhanden ist. LLD sollte also immer automatisch erkannt werden. device - Ein Zeiger auf das diesem Befehl zugeordnete Objekt scsi_device resid --LLD sollte auf diese vorzeichenbehaftete Ganzzahl abzüglich der angeforderten Übertragungslänge (d. h. request_buffer) abzüglich der Anzahl der tatsächlich übertragenen Bytes gesetzt werden. Der Rest ist auf 0 voreingestellt, und wenn kein Unterlauf (Überlauf ist selten) nicht erkannt werden kann, kann LLD ihn ignorieren. Wenn möglich, sollte LLD vor dem Start Rückstände setzen. Der interessanteste Fall ist die Datenübertragung von unterlaufenden SCSI-Zielgeräten (z. B. READs). underflow --LLD sollte (DID_ERROR_ << 16) in result setzen, wenn die Anzahl der tatsächlich übertragenen Bytes kleiner als dieser Wert ist. Nicht viele LLDs implementieren diese Prüfung und geben Fehlermeldungen im Protokoll aus, anstatt DID_ERROR zu melden. Besser für LLD ist es, Resid zu implementieren.

LLD empfiehlt, Reste für die Datenübertragung von SCSI-Zielgeräten (z. B. READs) festzulegen. Das Festlegen des Rests ist besonders wichtig für Datenübertragungen mit dem Sense-Schlüssel MEDIUM_ERROR und HARDWARE ERROR (RECOVERD ERROR, falls möglich). In diesen Fällen wissen Sie nicht, wie sehr die LLD die Daten akzeptiert, und der sicherste Ansatz besteht darin, die Daten nicht zu akzeptieren. Beispiel: LLD kann diese Hilfsfunktionen verwenden, um anzuzeigen, dass keine gültigen Daten empfangen wurden:

scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));

SCpnt ist ein Zeiger auf das Objekt scsi_cmnd. Der Rest wird auf diese Weise gesetzt, um anzuzeigen, dass nur drei 512-Byte-Blöcke empfangen wurden.

scsi_set_resid(SCpnt, scsi_bufflen(SCpnt) - (3 * 512));

Die scsi_cmnd-Struktur ist in include / scsi / scsi_cmnd.h definiert.

Locks Eine Instanz der Scsi_Host-Struktur verfügt über einen spin_lock namens Scsi_Host :: default_lock, der mit scsi_host_alloc () initialisiert wird. Innerhalb derselben Funktion wird der Zeiger Scsi_Host :: host_lock so initialisiert, dass er auf default_lock zeigt. Die Sperr- und Entsperrvorgänge werden dann von der mittleren Ebene mit dem Zeiger Scsi_Host :: host_lock ausgeführt. Der vorherige Treiber konnte host_lock überschreiben, dies ist jedoch nicht mehr zulässig.

Autosense Autosense (oder Auto-Sense) ist in der SAM-2-Dokumentation definiert, dass beim Auftreten des Status CHECK_CONDITION die automatische Antwort von Sense-Daten an den Anwendungsclient mit dem Abschluss des SCSI-Befehls zusammenfällt. LLDs sollten Autosense spielen. Dies sollte erfolgen, wenn die LLD jeweils einen PRÜFBEDINGUNG feststellt: a) Weisen Sie das SCSI-Protokoll an, in einer solchen Antwort mehr Daten abzuspielen. b) Alternativ gibt die LLD den Befehl REQUEST SENSE an sich selbst aus.

In beiden Fällen überprüft die mittlere Ebene beim Erkennen von CHECK CONDITION die Struktur scsi_cmnd :: sense_buffer [0], um festzustellen, ob LLD Autosense spielt. Wenn dieses Byte die oberen 4 Bits von 7 hat (dh 0b0111? Oder 0xf), wird angenommen, dass eine automatische Auswahl stattgefunden hat. Wenn es einen anderen Wert hat (und dieses Byte vor jedem Befehl auf 0 initialisiert wird), gibt die mittlere Ebene den Befehl REQUESET SENSE aus.

Wenn ein Befehl in der Warteschlange vorhanden ist, ist der Nexus, der die Erfassungspufferdaten von dem Befehl fernhält, der bis zum nächsten REQUESET SENSE fehlschlägt, möglicherweise nicht synchron. Dies ist der beste Grund, warum LLD Autosose spielt.

Recommended Posts

Übersetzung von scsi_mid_low_api.txt
Japanische Übersetzung des sysstat-Handbuchs
Japanische Übersetzung des Linux-Handbuchs
Japanische Übersetzung des e2fsprogs-Handbuchs
[Übersetzung] scikit-learn 0.18 Tutorial Inhaltsverzeichnis
TensorFlow Tutorial-Vektordarstellung von Wörtern (Übersetzung)
Japanische Übersetzung des man-db Handbuchs
Angemessene japanische Übersetzung von pytorch tensor_tutorial
Japanische Übersetzung des Util-Linux-Handbuchs
Japanische Übersetzung des iproute2-Handbuchs
[Übersetzung] scikit-learn 0.18 Benutzerhandbuch Inhaltsverzeichnis
Japanische Übersetzung: PEP 20 - Das Zen von Python
[Übersetzung] scikit-learn 0.18 Einführung in maschinelles Lernen durch Tutorial scikit-learn