<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<!--
     The FreeBSD Documentation Project
     The FreeBSD German Documentation Project

     $FreeBSD$
     $FreeBSDde: de-docproj/books/developers-handbook/dma/chapter.sgml,v 1.11 2009/02/15 14:17:12 jkois Exp $
     basiert auf: 1.6
-->

<chapter id="dma">
  <chapterinfo>
    <authorgroup>
      <author>
	<firstname>Daniel</firstname>
	<surname>Seuffert</surname>
	<contrib>Übersetzt von </contrib>
      </author>
    </authorgroup>
  </chapterinfo>

  <title>DMA</title>

  <sect1 id="dma-basics">
    <title>DMA: Was es ist und wie es funktioniert</title>

    <para><emphasis>Copyright &copy; 1995,1997 &a.uhclem;, Alle Rechte
      vorbehalten. 10. Dezember 1996. Letztes Update Oktober
      1997.</emphasis></para>

    <para>Direct Memory Access (DMA) ist eine Methode, die es erlaubt,
      Daten von einem Ort in einem Rechner an einen anderen ohne
      Eingriff des Prozessors (CPU) zu übertragen.</para>

    <para>Die Art und Weise, in der die DMA-Funktion implementiert
      ist, variiert zwischen den Rechnerarchitekturen. Daher
      beschränken wir uns im Folgenden ausschließlich auf die
      Methoden und Implementierungen auf IBM Personal Computer (PC),
      dem IBM PC/AT und all seinen Nachfolgern und Nachbauten.</para>

    <para>Das DMA-Subsystem basiert auf dem &intel; 8237
      DMA-Controller. Der 8237 enthält vier DMA-Kanäle,
      welche unabhängig voneinander programmiert werden
      können, und jeder dieser Kanäle kann zu einem
      beliebigen Zeitpunkt aktiv sein. Diese Kanäle sind mit 0,
      1, 2 und 3 nummeriert. Beginnend mit dem PC/AT fügte IBM
      einen zweiten 8237-Chip hinzu und nummerierte dessen Kanäle
      mit 4, 5, 6 und 7.</para>

    <para>Der originale DMA-Controller (0, 1, 2 and 3) bewegt ein Byte
      bei jedem Transfer. Der zweite DMA-Controller (4, 5, 6, and 7)
      bewegt 16-Bits aus zwei benachbarten Speicherplätzen bei
      jedem Transfer, wobei das erste Byte immer von einer
      geradzahligen Adresse stammt. Die zwei Controller sind
      identische Komponenten und der Unterschied in der
      Transfergröße wird durch die Art und Weise
      verursacht, wie der zweite Controller im System beschaltet
      ist.</para>

    <para>Der 8237 hat zwei elektrische Signale für jeden
      Kanal: DRQ und -DACK. Zusätzlich gibt es weitere Signale
      mit den Namen HRQ (Hold Request), HLDA (Hold Acknowledge), -EOP
      (End of Process) sowie die Kontrollsignale für den Bus:
      -MEMR (Memory Read), -MEMW (Memory Write), -IOR (I/O Read) und
      -IOW (I/O Write).</para>

    <para>Der 8237 DMA-Controller ist ein sogenannter
      <quote>fly-by</quote>-DMA-Controller. Das bedeutet, dass
      die von einem zu einem anderen Bereich bewegten Daten weder den
      DMA-Chip durchlaufen noch darin gespeichert werden. Daraus
      folgt, dass der DMA-Controller nur zwischen einem I/O-Port und
      einer Speicheradresse Daten bewegen kann, nicht zwischen zwei
      I/O-Ports oder zwei Speicherbereichen.</para>

    <note>
      <para>Der 8237 erlaubt es, dass zwei Kanäle verbunden
	werden, um DMA-Operationen zwischen zwei Speicherbereichen in
	einem nicht-<quote>fly-by</quote>-Modus durchzuführen.
	Aber niemand in der PC-Industrie benutzt diese begrenzte
	Resource, da es schneller ist die Daten mittels der CPU
	zwischen Speicherbereichen zu bewegen.</para> </note>

    <para>In der PC-Architekur wird jeder DMA-Kanal normalerweise
      nur dann aktiviert, wenn die Hardware, welche einen gegebenen
      DMA-Kanal benutzt, einen Transfer durch Setzen der DRQ-Linie
      verlangt.</para>

    <sect2>
      <title>Beispiel eines DMA-Transfers</title>

      <para>Hier ist ein Beispiel für die notwendigen Schritte,
	welche einen DMA-Transfer veranlassen und durchführen.
	In diesem Beispiel hat der Diskettencontroller (floppy disk
	controller, FDC) nur ein Byte zu lesen und verlangt vom
	DMA-Controller dieses Byte im Speicher unter der Adresse
	0x00123456 abzulegen. Der Prozess beginnt damit, dass der
	FDC das DRQ2-Signal (die DRQ-Linie für DMA-Kanal 2)
	setzt, um den DMA-Controller zu alarmieren.</para>

      <para>Der DMA-Controller registriert, dass das DRQ2-Signal
	gesetzt ist. Der DMA-Controller stellt sicher, dass der
	DMA-Kanal 2 programmiert und unmaskiert (freigegeben) ist. Der
	DMA-Controller stellt gleichzeitig sicher, dass keiner
	der anderen DMA-Kanäle aktiv ist oder aktiv sein
	möchte und eine höhere Prioritäti hat. Sobald
	all diese Überprüfungen durchlaufen sind, fordert
	der DMA-Controller die CPU auf, den Bus freizugeben, damit der
	DMA-Controller ihn nutzen kann.  Diese Anforderung erfolgt
	durch Setzen des HRQ-Signals, welches zur CPU geht.</para>

      <para>Die CPU erkennt das HRQ-Signal und führt den
	aktuellen Befehl komplett aus. Sobald die CPU den Bus
	freigeben kann, wird sie dies tun. Nun sind alle normalerweise
	von der CPU erzeugten Signale (-MEMR, -MEMW, -IOR, -IOW und
	ein paar andere) in einem Status mit einem dritten Zustand
	(weder hoch noch niedrig) und die CPU teilt dem DMA-Controller
	mittels des HLDA-Signals mit, dass er nun die Kontrolle
	über den Bus hat.</para>

      <para>Abhängig vom Prozessor kann die CPU noch einige
	zusätzliche Befehle ausführen ohne die Kontrolle des
	Bus, aber letztendlich muss sie warten, wenn sie Befehle
	verarbeiten will, welche etwas aus dem Speicher lesen
	müssen, was nicht im internen Prozessor-Cache oder der
	Pipeline ist.</para>

      <para>Da der DMA-Controller nun <quote>verantwortlich
	ist</quote>, aktiviert er seine -MEMR, -MEMW, -IOR, -IOW
	Output-Signale und der Output des DMA-Controllers wird auf
	0x3456 gesetzt, damit das zu übertragende Byte zu einem
	bestimmten Speicherbereich gelangt.</para>

      <para>Der DMA-Controller verständigt nun das Gerät,
	welches die Anforderung veranlasst hat, dass der Transfer
	beginnt. Dies geschieht durch Setzen des Signals -DACK oder im
	Fall des Diskettencontrollers durch -DACK2.</para>

      <para>Der Floppy-Controller ist nun dafür verantwortlich
	das zu übertragende Byte auf den Datenbahnen des Bus zu
	platziren. Sofern der Floppy-Controller nicht mehr Zeit
	braucht, um das Daten-Byte auf den Bus zu bringen (falls dies
	erforderlich ist benachrichtigt das Peripheriegerät
	mittels READY-Signal den DMA-Controller), dann wird der
	DMA-Controller ein Zeitsignal warten und die Signale -MEMW und
	-IOR widerrufen, damit der Speicher das Byte auf dem Bus
	sperrt und speichert und der FDC weiß, dass das
	Byte übertragen wurde.</para>

      <para>Da der DMA-Zyklus nur ein einzelnes Byte auf einmal
	überträgt, wird der FDC nun das Signal DRQ2
	deaktivieren und der DMA-Controller weiß, dass er
	nicht länger benötigt wird. Der DMA-Controller setzt
	das -DACK2-Signal wieder und der FDC registriert, dass
	er aufhören muss Daten an den Bus zu senden.</para>

      <para>Der DMA-Controller wird nun überprüfen, ob
	andere DMA-Kanäle irgendwelche Arbeiten bereithalten.
	Falls keiner der Kanäle DRQ-Signale gesetzt hat,
	weiß der Controller, dass er seine Arbeit beendet
	hat und setzt -MEMR, -MEMW, -IOR, -IOW und die Adress-Signale
	auf den dritten Zustand.</para>

      <para>Abschliessend setzt der DMA-Controller wieder das
	HRQ-Signal. Die CPU registriert dies und entfernt das
	HOLDA-Signal wieder. Die CPU aktiviert nun ihre -MEMR, -MEMW,
	-IOR, -IOW und Adress-Ausgänge und fährt mit der
	Verarbeitung von Befehlen und dem Zugriff auf Hauptspeicher
	und Peripherie fort.</para>

      <para>Für einen typischen Sektor einer Diskette wird der
	obige Prozess 512 Mal wiederholt, einmal für jedes  Byte.
	Nach dem Transfer eines Byte wird jeweils das Adressregister
	im DMA-Controller erhöht und der Zähler vermindert,
	welcher anzeigt, wieviel Bytes noch zu übertragen
	sind.</para>

      <para>Sobald der Zähler Null erreicht hat, setzt der
	DMA-Controller das EOP-Signal, welches anzeigt, dass der
	Zähler Null erreicht hat und keine weiteren Daten zu
	übertragen sind, bis der DMA-Controller wieder durch die
	CPU programmiert wird. Dieses Ereignis bezeichnet man als
	Terminal Count (TC). Es gibt nur ein EOP-Signal und da nur
	jeweils ein DMA-Kanal gleichzeitig aktiv sein kann, muss
	der aktive DMA-Kanal auch derjenige sein, welcher soeben seine
	Aufgabe beendet hat.</para>

      <para>Falls ein Peripheriegerät einen Interrupt erzeugen
	will, wenn der Transfer eines Pufferspeichers beendet ist,
	dann kann es überprüfen, ob sein -DACK-Signal und
	EOP-Signal gleichzeitig anliegen. Falls dies zutrifft wird der
	DMA-Controller keine weiteren Informationen ohne Eingriff der
	CPU für dieses Peripheriegerät übertragen. Das
	Peripheriegerät kann nun eines der Interrupt-Signale
	einfügen, um die Aufmerksamkeit der CPU zu erlangen. In
	der PC-Architektur ist der DMA-Controller selbst nicht in der
	Lage Interrupts zu erzeugen. Das Peripheriegerät und
	seine beigeordnete Hardware sind für die Erzeugung jedes
	Interrupts verantwortlich, welcher auftritt. In der Folge gibt
	es Peripheriegeräte, welche DMA nutzen aber keine
	Interrupts erzeugen.</para>

      <para>Es ist wichtig zu verstehen, dass obwohl die CPU
	jedesmal den Bus an den DMA-Controller freigibt, wenn dieser
	ihn anfordert, dieser Vorgang sowohl für das
	Betriebssystem als auch die Applikation unsichtbar ist - außer
	bei kleinen Änderungen im Zeitbedarf des Prozessors beim
	Ausführen von Befehlen, wenn der DMA-Controller aktiv
	ist. Folglich muss der Prozessor die
	Peripheriegeräte und die Register im DMA-Chip
	ständig abfragen oder einen Interrupt von einem
	Peripheriegerät empfangen, um sicher zu sein, dass
	ein bestimmter DMA-Transfer beendet wurde.</para>
    </sect2>

    <sect2>
      <title>DMA-Seitenregister und 16
	Megabyte-Adressraumbeschränkungen</title>

      <para>Sie haben vielleicht vorhin bemerkt, dass der
	DMA-Controller die Adress-Linien nicht auf 0x00123456 gesetzt
	hat, wie wir angaben, sondern auf 0x3456. Der Grund
	hierfür erfordert ein wenig Erklärung.</para>

      <para>Als der originale IBM PC entworfen wurde hat IBM
	entschieden sowohl DMA als auch Interrupt-Controller
	einzusetzen, welche für den 8085 entwickelt worden waren,
	einen 8 Bit-Prozessor mit einem Adressraum von 16 Bit (64K).
	Da der IBM PC mehr als 64K unterstützte, musste etwas
	geschehen, damit der DMA-Controller Adressbereiche oberhalb
	der 64K-Grenze auslesen und beschreiben konnte. IBM
	führte einen zusätzlichen, externen Signalspeicher
	für jeden DMA-Kanal ein, welcher die oberen Bits einer
	Adresse enthält, welche ausgelesen oder beschrieben
	werden soll. Immer wenn ein DMA-Controller aktiv ist, wird der
	Inhalt dieses Signalspeichers cwauf denzum Adress-Bus
	geschrieben und dort gehalten, bis die DMA-Operation für
	diesen Kanal beendet ist. IBM nannte diese zusätzlichen
	Signalspeicher <quote>Seitenregister</quote> (Page
	Register).</para>

      <para>Für das obige Beispiel würde der DMA-Controller also den
	0x3456-Teil der Adresse auf den Bus setzen und das Seitenregister
	für den DMA-Kanal 2 würde dem Bus 0x0012xxxx hinzufügen.
	Zusammen bilden beide Werte die komplette Speicheradresse, auf die
	zugegriffen werden soll.</para>

      <para>Da das Seitenregister unabhängig vom DMA-Chip ist,
	darf der zu lesende oder zu schreibende Speicherbereich die
	64K-Grenze nicht überschreiten. Wenn der DMA-Controller
	beispielsweise auf die Speicheradresse 0xffff zugreift, dann
	wird der Controller nach dem Transfer das Adress-Register
	erhöhen und auf das nächste Byte an der Adresse
	0x0000, nicht 0x10000, zugreifen. Dieses Zuzulassen ist
	wahrscheinlich nicht beabsichtigt.</para>

      <note>
	<para><quote>Physikalische</quote> 64K-Grenzen sollten nicht
	  mit 8086-Modus 64K-<quote>Segmenten</quote> verwechselt
	  werden, welche durch mathematisches Addieren eines
	  Segment-Registers an ein Offset-Register erzeugt werden.
	  Seitenregister haben keinen Adressüberhang und werden
	  imathematisch durch ein OR zusammengefügt.</para>
      </note>

      <para>Um die Angelegenheit noch komplizierter zu machen, weisen
	die externen DMA-Signalspeicher auf dem PC/AT nur 8 Bytes auf,
	also 8+16 = 24 Bits. Dies bedeutet, dass der
	DMA-Controller nur auf Speicherbereiche zwischen 0 und 16
	Megabyte zeigen kann. Für neuere Rechner, die mehr als 16
	Megabyte an Speicher aufweisen, kann der Standard
	PC-kompatible DMA-Controller keine Speicherbereiche oberhalb
	von 16 Megabyte adressieren.</para>

      <para>Um diese Beschränkung zu umgehen reservieren
	Betriebssysteme einen RAM-Puffer in einem Bereich unterhalb
	von 16 Megabyte, der außerdem einen physisch begrenzten
	Bereich von 64K nicht überschreitet. Dann wird der
	DMA-Controller so programmiert, dass er Daten vom
	Peripheriegerät in diesen Puffer überträgt.
	Sobald der DMA-Controller die Daten in den Puffer
	übertragen hat, wird das Betriebssystem sie in den
	Bereich übertragen, an dem sie wirklich gespeichert
	werden sollen.</para>

      <para>Beim Schreiben von Daten von Adressen oberhalb von 16
	Megabyte an ein DMA-basiertes Peripheriegerät müssen
	die Daten zuerst von dort, wo sie liegen, in einen Puffer
	unterhalb von 16 Megabyte geschrieben werden und dann kann der
	DMA-Controller die Daten vom Puffer auf die Peripherie
	kopieren. In FreeBSD werden diese reservierten Puffer
	<quote>Bounce Buffers</quote> genannt. In der &ms-dos;-Welt
	werden sie manchmal als <quote>Smart Buffers</quote>
	bezeichnet.</para>

      <note>
	<para>Eine neuere Ausführung des 8237, 82374 genannt,
	  weist 16 Bit-Seitenregister auf und erlaubt Zugriff auf den
	  gesamten 32 Bit Adressraum ohne Zuhilfenahme von Bounce
	  Buffers.</para>
      </note>
    </sect2>

    <sect2>
      <title>DMA-Operationsmodi und Einstellungen</title>

      <para>Der 8237 DMA-Controller kann in verschiedenen Modi
	betrieben werden. Die Wichtigsten sind:</para>

      <variablelist>
	<varlistentry>
	  <term>Single</term>

	  <listitem>
	    <para>Ein einziges Byte (oder Wort) wird übertragen.
	      Der DMA-Controller muss für jedes
	      zusätzliche Byte den Bus freigeben und neu
	      anfordern. Dieser Modus wird normalerweise von
	      Geräten benutzt, welche nicht einen gesamten Block
	      von Daten auf einmal übertragen können. Das
	      Peripheriegerät wird den DMA-Controller jedesmal
	      anfordern, wenn es für einen weiteren Transfer
	      bereit ist.</para>

	    <para>Der Standard PC-kompatible Floppy-Controller (NEC
	      765) hat nur einen Puffer mit einem Byte, daher nutzt er
	      diesen Modus.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Block/Demand</term>

	  <listitem>
	    <para>Sobald der DMA-Controller den Bus übernommen
	      hat, wird ein ganzer Block von Daten übertragen bis
	      zu einem Maximum von 64K. Wenn das Peripheriegerät
	      zusätzliche Zeit benötigt, kann es das
	      READY-Signal setzen, um den Transfer kurzfristig zu
	      unterbrechen. READY sollte nicht exzessiv benutzt werden
	      und für langsame Peripheriegeräte sollte
	      stattdessen der Single Transfer-Modus genutzt
	      werden.</para>

	    <para>Der Unterschied zwischen Block und Demand ist,
	      dass sobald ein Block-Transfer gestartet ist,
	      dieser solange läuft, bis der Transfer-Zähler
	      Null erreicht. DRQ muss nur gesetzt werden, bis
	      -DACK gesetzt wird. Der Demand-Modus überträgt
	      ein weiteres Byte, bis DRQ gelöscht wird. An diesem
	      Punkt unterbricht der DMA-Controller die
	      Übertragung und gibt den Bus wieder an die CPU
	      zurück. Wenn DRQ wieder eingesetzt wird geht der
	      Transfer an der Stelle weiter, an welcher er
	      unterbrochen wurde.</para>

	    <para>Ältere Festplattencontroller benutzten den
	      Demand-Modus bis die CPU-Geschwindigkeiten stiegen,
	      sodass der Transfer mittels CPU schneller war,
	      insbesondere wenn die benutzten Speicherbereiche
	      jenseits der 16 Megabyte-Marke lagen.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Cascade</term>

	  <listitem>
	    <para>Dieser Mechanismus erlaubt einem DMA-Kanal den Bus
	      anzufordern, wobei dann aber das zugehörige
	      Peripheriegerät dafür verantwortlich ist die
	      Adressinformationen an den Bus zu senden anstatt des
	      DMA-Controllers. Dies wird auch dazu genutzt, um eine
	      Technik zu implementieren, die man als <quote>Bus
	      Mastering</quote> bezeichnet.</para>

	    <para>Wenn ein DMA-Kanal im Cascade-Modus Kontrolle
	      über den Bus erlangt, dann stellt der Controller
	      nicht die Adressen und I/O-Kontrollsignale auf den Bus,
	      wie es normalerweise der Fall ist. Stattdessen setzt der
	      Controller nur das -DACK-Signal für den aktiven
	      DMA-Kanal.</para>

	    <para>Nun ist es Aufgabe Peripheriegerätes, welches
	      mit diesem DMA-Kanal verbunden ist, die Adressen und
	      Bus-Kontrollsignale zu liefern. Das Peripheriegerät
	      hat vollständige Kontrolle über den Bus und
	      kann Lese- oder Schreibvorgänge an jeder Adresse
	      unterhalb von 16 Megabyte ausführen. Wenn es fertig
	      ist, setzt es das DRQ-Signal und der DMA-Controller kann
	      die Kontrolle an die CPU oder einen anderen DMA-Kanal
	      übergeben.</para>

	    <para>Der Cascade-Modus kann verwendet werden, um mehrere
	      DMA-Controller in Reihe zu schalten und genau dafür
	      wird der DMA-Kanal 4 in der PC-Architektur genutzt. Wenn
	      ein Peripheriegerät den Bus auf den
	      DMA-Kanälen 0, 1, 2 oder 3 verlangt, dann setzt der
	      abhängige DMA-Controller (slave DMA) HLDREQ, aber
	      dieses Signal ist in Wirklichkeit verbunden mit DRQ4 auf
	      dem primären DMA-Controller anstatt mit der CPU.
	      Der primäre DMA-Controller nimmt an, er habe Arbeit
	      zu leisten auf Kanal 4, und fordert den Bus an von der
	      CPU mit dem HLDREQ-Signal. Sobald die CPU die Kontrolle
	      des Bus an den primären DMA-Controller
	      übergeben hat, wird -DACK4 gesetzt und dieser Kanal
	      ist in Wirklichkeit mit dem abhängigen
	      DMA-Controller über das HDLA-Signal verbunden. Der
	      abhängige Controller überträgt dann die
	      Daten für den DMA-Kanal, der die Anforderung
	      gestellt hat (0, 1, 2 oder 3) oder der Controller
	      übergibt den Bus an ein Peripheriegerät,
	      welches selbst ein eigenes Bus-Mastering
	      durchführen will, z.B. einen
	      SCSI-Controller.</para>

	    <para>Wegen dieser Schaltungsanordnung können auf
	      PC/AT-Systemen nur die DMA-Kanäle 0, 1, 2, 3, 5, 6
	      und 7 mit Peripheriegeräten genutzt werden.</para>

	    <note>
	      <para>Der DMA-Kanal 0 war auf frühen IBM PCs
		für Auffrischungs-Operationen reserviert, aber
		auf modernen Rechnern ist er allgemein für
		Peripheriegeräte verfügbar.</para>
	    </note>

	    <para>Wenn ein Peripheriegerät Bus Mastering
	      durchführt, ist es wichtig, dass es konstant
	      Daten vom oder zum Speicher überträgt, solange
	      es die Kontrolle über den Bus hält. Falls das
	      Peripheriegerät dies nicht kann, muss es den
	      Bus häufig freigeben, damit das System
	      Auffrischungsoperationen am Hauptspeicher vornehmen
	      kann.</para>

	    <para>Das dynamische RAM als Hauptspeicher in allen PCs
	      muss regelmäßig aufgefrischt werden, damit
	      die gespeicherten Bits <quote>geladen</quote> gehalten
	      werden. Dynamisches Ram besteht aus Millionen von
	      Transistoren, die jedes ein Bit Daten enthalten. Die
	      Transistoren sind geladen, um <literal>1</literal>
	      darzustellen, oder entladen, um <literal>0</literal> zu
	      repräsentieren. Da alle Transistoren Ladung
	      abgeben, muss in regelmäßigen Abständen
	      der Ladungsinhalt aufgefrischt werden durch
	      Wiederbeschreibung, um den Wert <literal>1</literal> zu
	      erhalten. Die RAM-Chips übernehmen diese Aufgabe
	      selbst, aber sie müssen dazu vom Rest des Rechners
	      angewiesen werden, damit die
	      Auffrischungsaktivitäten nicht mit den normalen
	      Zugriffen auf das RAM kollidieren. Falls der Rechner
	      das RAM nicht auffrischen kann wird der Inhalt des
	      Speichers binnen weniger Millisekunden
	      beschädigt.</para>

	    <para>Da Lese- und Schreibzyklen als Auffrischungszyklen
	      <quote>zählen</quote> (ein Auffrischungszyklus
	      eines dynamischen RAM ist in Wirklichkeit ein
	      unvollständiger Lesezyklus), wird diese Aktion den
	      gesamten Speicher auffrischen, solange der
	      abhängige Controller fortfährt Daten an
	      aufeinander folgenden Speicherbereiche zu lesen oder
	      dorthin zu schreiben.</para>

	    <para>Bus-Mastering findet man in einigen SCSI-Controllern
	      und anderen hochwertigen Peripherie-Controllern.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Autoinitialize</term>

	  <listitem>
	    <para>Dieser Modus veranlasst den DMA-Controller dazu
	      Byte-, Block- oder Demand-Transfers auszuführen.
	      Aber wenn der DMA-Übertragungszähler Null
	      erreicht hat, dann werden die Zähler und Adressen
	      wieder auf den Wert zurückgesetzt, den sie
	      aufwiesen, als der DMA-Kanal ursprünglich
	      programmiert wurde. Das bedeutet, dass
	      Transfers zugelassen werden, solange das
	      Peripheriegerät sie anfordert. Es ist Aufgabe der
	      CPU neue Daten rechtzeitig in den Puffer zu schicken,
	      damit das Peripheriegerät sie schreiben kann bzw.
	      die neuen Daten aus dem Puffer zu lesen, wenn der
	      DMA-Controller bei Eingabeoperationen Daten
	      schreibt.</para>

	    <para>Diese Technik wird häufig bei Audiogeräten
	      genutzt, die kleine oder gar keine
	      <quote>Sample</quote>-Puffer in Hardware aufweisen.
	      Dadurch entsteht zusätzlicher CPU-Overhead bei der
	      Verwaltung dieses <quote>zirkulären</quote>
	      Puffers, aber in manchen Fällen ist es der einzige
	      Weg, um die Latenz zu beseitigen, die auftritt, wenn der
	      DMA-Zähler Null erreicht und der DMA-Controller mit
	      den Transfers anhält, bis er neu programmiert
	      ist.</para>
	  </listitem>
	</varlistentry>
      </variablelist>
    </sect2>

    <sect2>
      <title>Das Programmieren des DMA-Controllers</title>

      <para>Der zu programmierende DMA-Kanal sollte immer
	<quote>maskiert</quote> werden, bevor irgendwelche
	Einstellungen geladen werden. Dies soll deswegen geschehen,
	weil die Hardware unerwarteterweise DRQ für diesen Kanal
	setzen könnte und der Controller könnte antworten,
	obwohl noch nicht alle Parameter geladen oder aktualisiert
	wurden.</para>

      <para>Nach der Maskierung muss der Host die Richtung des
	Transfers festlegen (Speicher-zu-I/O oder I/O-zu-Speicher),
	welcher DMA-Modus für den Transfer genutzt wird (Single,
	Block, Demand, Cascade, etc.) und schließlich werden die
	Adresse und die Länge des Transfers geladen. Die
	Länge ist um 1 kleiner als die durch den DMA-Controller
	zu übertragende. Das LSB und das MSB der Adresse und der
	Länge werden auf den gleichen 8 Bit I/O-Port geschrieben,
	also muss zunächst ein anderer Port geschrieben
	werden, um zu gewährleisten, dass der DMA-Controller
	das erste Byte als LSB und das zweite Byte als MSB der
	Länge und der Adresse akzeptiert.</para>

      <para>Stellen Sie dann sicher, dass Sie das Seitenregister
	aktualisiert haben, welches extern zum DMA-Controller ist und
	durch ein anderes Set von I/O-Ports angesprochen wird.</para>

      <para>Sobald alle Einstellungen fertig sind, kann der DMA-Kanal
	demaskiert werden. Dieser Kanal wird nun als
	<quote>geschützt</quote> betrachtet und wird antworten,
	wenn die DRQ-Linie für diesen Kanal gesetzt wird.</para>

      <para>Schlagen Sie im Hardware Handbuch für
	ausführliche Programmierdetails zum 8237 nach. Sie werden
	auch auf die I/O-Portübersicht für den PC
	zurückgreifen mü, welches beschreibt, wo die
	DMA-Register und Seitenregister sich befinden. Eine
	vollständige Tabelle der Ports finden Sie unten.</para>
    </sect2>

    <sect2>
      <title>DMA Port-Übersicht</title>

      <para>Alle Systeme, die auf dem IBM-PC und PC/AT basieren, weisen
	die gleiche DMA-Hardware an identischen I/O-Ports auf. Die
	vollständige Liste ist unten aufgeführt. Dem
	DMA-Controller #2 zugewiesene Ports sind auf
	nicht-AT-Systemeni undefiniert.</para>

      <sect3>
	<title>0x00&ndash;0x1f DMA-Controller #1 (Kanäle 0, 1, 2
	  und 3)</title>

	<para>DMA-Adressregister und -Zählregister</para>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="3">
	    <tbody>
	      <row>
		<entry>0x00</entry>
		<entry>write</entry>
		<entry>Kanal 0 Startadresse</entry>
	      </row>

	      <row>
		<entry>0x00</entry>
		<entry>read</entry>
		<entry>Kanal 0 gegenwärtige Adresse</entry>
	      </row>

	      <row>
		<entry>0x01</entry>
		<entry>write</entry>
		<entry>Kanal 0 Anfangs-Wortnummer</entry>
	      </row>

	      <row>
		<entry>0x01</entry>
		<entry>read</entry>
		<entry>Kanal 0 verbleibende Wortzahl</entry>
	      </row>

	      <row>
		<entry>0x02</entry>
		<entry>write</entry>
		<entry>Kanal 1 Startadresse</entry>
	      </row>

	      <row>
		<entry>0x02</entry>
		<entry>read</entry>
		<entry>Kanal 1 gegenwärtige Adresse</entry>
	      </row>

	      <row>
		<entry>0x03</entry>
		<entry>write</entry>
		<entry>Kanal 1 Anfangs-Wortnummer</entry>
	      </row>

	      <row>
		<entry>0x03</entry>
		<entry>read</entry>
		<entry>Kanal 1 verbleibende Wortzahl</entry>
	      </row>

	      <row>
		<entry>0x04</entry>
		<entry>write</entry>
		<entry>Kanal 2 Startadresse</entry>
	      </row>

	      <row>
		<entry>0x04</entry>
		<entry>read</entry>
		<entry>Kanal 2 gegenwärtige Adresse</entry>
	      </row>

	      <row>
		<entry>0x05</entry>
		<entry>write</entry>
		<entry>Kanal 2 Anfangs-Wortnummer</entry>
	      </row>

	      <row>
		<entry>0x05</entry>
		<entry>read</entry>
		<entry>Kanal 2 verbleibende Wortzahl</entry>
	      </row>

	      <row>
		<entry>0x06</entry>
		<entry>write</entry>
		<entry>Kanal 3 Startadresse</entry>
	      </row>

	      <row>
		<entry>0x06</entry>
		<entry>read</entry>
		<entry>Kanal 3 gegenwärtige Adresse</entry>
	      </row>

	      <row>
		<entry>0x07</entry>
		<entry>write</entry>
		<entry>Kanal 3 Anfangs-Wortnummer</entry>
	      </row>

	      <row>
		<entry>0x07</entry>
		<entry>read</entry>
		<entry>Kanal 3 verbleibende Wortzahl</entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>

	<para>DMA-Befehlsregister</para>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="3">
	    <tbody>
	      <row>
		<entry>0x08</entry>
		<entry>write</entry>
		<entry>Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0x08</entry>
		<entry>read</entry>
		<entry>Status-Register</entry>
	      </row>

	      <row>
		<entry>0x09</entry>
		<entry>write</entry>
		<entry>Anforderungsregister</entry>
	      </row>

	      <row>
		<entry>0x09</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0x0a</entry>
		<entry>write</entry>
		<entry>Single Mask Register Bit</entry>
	      </row>

	      <row>
		<entry>0x0a</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0x0b</entry>
		<entry>write</entry>
		<entry>Modusregister</entry>
	      </row>

	      <row>
		<entry>0x0b</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0x0c</entry>
		<entry>write</entry>
		<entry>Flip-Flop zm Löschen des LSB/MSB</entry>
	      </row>

	      <row>
		<entry>0x0c</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0x0d</entry>
		<entry>write</entry>
		<entry>Master Clear/Reset</entry>
	      </row>

	      <row>
		<entry>0x0d</entry>
		<entry>read</entry>
		<entry>Temporäres Register (in neueren Versionen
		  nicht verfügbar).</entry>
	      </row>

	      <row>
		<entry>0x0e</entry>
		<entry>write</entry>
		<entry>Läsche Mask-Register</entry>
	      </row>

	      <row>
		<entry>0x0e</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0x0f</entry>
		<entry>write</entry>
		<entry>Schreibe alle Mask-Register-Bits</entry>
	      </row>

	      <row>
		<entry>0x0f</entry>
		<entry>read</entry>
		<entry>Lese alle Mask-Register-Bits (nur auf &intel;
	      82374)</entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>
      </sect3>

      <sect3>
	<title>0xc0&ndash;0xdf DMA-Controller #2 (Kanäle 4, 5, 6 und
	  7)</title>

	<para>DMA-Adressregister und -Zählregister</para>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="3">
	    <tbody>
	      <row>
		<entry>0xc0</entry>
		<entry>write</entry>
		<entry>Kanal 4 Startadresse</entry>
	      </row>

	      <row>
		<entry>0xc0</entry>
		<entry>read</entry>
		<entry>Kanal 4 gegenwärtige Adresse</entry>
	      </row>

	      <row>
		<entry>0xc2</entry>
		<entry>write</entry>
		<entry>Kanal 4 Anfangs-Wortnummer</entry>
	      </row>

	      <row>
		<entry>0xc2</entry>
		<entry>read</entry>
		<entry>Kanal 4 verbleibende Wortzahl</entry>
	      </row>

	      <row>
		<entry>0xc4</entry>
		<entry>write</entry>
		<entry>Kanal 5 Startadresse</entry>
	      </row>

	      <row>
		<entry>0xc4</entry>
		<entry>read</entry>
		<entry>Kanal 5 gegenwärtige Adresse</entry>
	      </row>

	      <row>
		<entry>0xc6</entry>
		<entry>write</entry>
		<entry>Kanal 5 Anfangs-Wortnummer</entry>
	      </row>

	      <row>
		<entry>0xc6</entry>
		<entry>read</entry>
		<entry>Kanal 5 verbleibende Wortzahl</entry>
	      </row>

	      <row>
		<entry>0xc8</entry>
		<entry>write</entry>
		<entry>Kanal 6 Startadresse</entry>
	      </row>

	      <row>
		<entry>0xc8</entry>
		<entry>read</entry>
		<entry>Kanal 6 gegenwärtige Adresse</entry>
	      </row>

	      <row>
		<entry>0xca</entry>
		<entry>write</entry>
		<entry>Kanal 6 Anfangs-Wortnummer</entry>
	      </row>

	      <row>
		<entry>0xca</entry>
		<entry>read</entry>
		<entry>Kanal 6 verbleibende Wortzahl</entry>
	      </row>

	      <row>
		<entry>0xcc</entry>
		<entry>write</entry>
		<entry>Kanal 7 Startadresse</entry>
	      </row>

	      <row>
		<entry>0xcc</entry>
		<entry>read</entry>
		<entry>Kanal 7 gegenwärtige Adresse</entry>
	      </row>

	      <row>
		<entry>0xce</entry>
		<entry>write</entry>
		<entry>Kanal 7 Anfangs-Wortnummer</entry>
	      </row>

	      <row>
		<entry>0xce</entry>
		<entry>read</entry>
		<entry>Kanal 7 verbleibende Wortzahl</entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>

	<para>DMA-Befehlsregister</para>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="3">
	    <tbody>
	      <row>
		<entry>0xd0</entry>
		<entry>write</entry>
		<entry>Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0xd0</entry>
		<entry>read</entry>
		<entry>Status-Register</entry>
	      </row>

	      <row>
		<entry>0xd2</entry>
		<entry>write</entry>
		<entry>Anforderungsregister</entry>
	      </row>

	      <row>
		<entry>0xd2</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0xd4</entry>
		<entry>write</entry>
		<entry>Single Mask Register Bit</entry>
	      </row>

	      <row>
		<entry>0xd4</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0xd6</entry>
		<entry>write</entry>
		<entry>Modusregister</entry>
	      </row>

	      <row>
		<entry>0xd6</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0xd8</entry>
		<entry>write</entry>
		<entry>Flip-Flop zum Löschen des LSB/MSB</entry>
	      </row>

	      <row>
		<entry>0xd8</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0xda</entry>
		<entry>write</entry>
		<entry>Master Clear/Reset</entry>
	      </row>

	      <row>
		<entry>0xda</entry>
		<entry>read</entry>
		<entry>temporäres Register (nicht verfügbar
		  auf &intel; 82374)</entry>
	      </row>

	      <row>
		<entry>0xdc</entry>
		<entry>write</entry>
		<entry>Lösche Mask-Register</entry>
	      </row>

	      <row>
		<entry>0xdc</entry>
		<entry>read</entry>
		<entry>-</entry>
	      </row>

	      <row>
		<entry>0xde</entry>
		<entry>write</entry>
		<entry>Schreibe alle Mask-Register-Bits</entry>
	      </row>

	      <row>
		<entry>0xdf</entry>
		<entry>read</entry>
		<entry>Lese alle Mask-Register-Bits (nur auf &intel;
		  82374)</entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>
      </sect3>

      <sect3>
	<title>0x80&ndash;0x9f DMA-Seitenregister</title>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="3">
	    <tbody>
	      <row>
		<entry>0x87</entry>
		<entry>r/w</entry>
		<entry>Kanal 0 niederes Byte (23-16)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x83</entry>
		<entry>r/w</entry>
		<entry>Kanal 1 niederes Byte (23-16)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x81</entry>
		<entry>r/w</entry>
		<entry>Kanal 2 niederes Byte (23-16)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x82</entry>
		<entry>r/w</entry>
		<entry>Kanal 3 niederes Byte (23-16)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x8b</entry>
		<entry>r/w</entry>
		<entry>Kanal 5 niederes Byte (23-16)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x89</entry>
		<entry>r/w</entry>
		<entry>Kanal 6 niederes Byte (23-16)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x8a</entry>
		<entry>r/w</entry>
		<entry>Kanal 7 niederes Byte (23-16)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x8f</entry>
		<entry>r/w</entry>
		<entry>niederes Byte Seitenauffrischung</entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>
      </sect3>

      <sect3>
	<title>0x400&ndash;0x4ff 82374 Erweiterte DMA-Register</title>

	<para>Die &intel; 82374 EISA-System-Komponente (EISA System
	  Component ESC) wurde Anfang 1996 eingeführt und
	  beinhaltet einen DMA-Controller, der die Funktionen des 8237
	  und zusätzlich andere PC-kompatible
	  Kern-Peripheriekomponenten in einer einzigen Komponente
	  vereint. Dieser Chip wurde für EISA und PCI-Plattformen
	  entworfen und stellt moderne DMA-Funktionen wie
	  Scatter-Gather, Ring-Puffer und direkten Zugriff des
	  DMA-Controllers auf alle 32 Bit des Adressraumes zur
	  Verfügung.</para>

	<para>Werden diese Leistungsmerkmale genutzt, dann sollte Code
	  hinzugefügt werden, der die gleiche Funktionalität
	  für Geräte aus den 16 Jahren PC-kompatibler
	  Geräte vor diesem Chip zur Verfügung stellt. Aus
	  Kompatibilitätsgründen müssen einige der
	  Register des 82374 programmiert werden
	  <emphasis>nachdem</emphasis> die traditionellen Register des
	  8237 für jeden Transfer programmiert wurden. Das
	  Schreiben in eines der traditionellen 8237-Register
	  führt dazu, dass einige der erweiterten Register
	  des 82374 aus Kompatibilitätsgründen auf Null
	  gesetzt werden.</para>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="3">
	    <tbody>
	      <row>
		<entry>0x401</entry>
		<entry>r/w</entry>
		<entry>Kanal 0 hohes Byte (Bits 23-16)
		  Word-Zähler</entry>
	      </row>

	      <row>
		<entry>0x403</entry>
		<entry>r/w</entry>
		<entry>Kanal 1 hohes Byte (Bits 23-16)
		  Word-Zähler</entry>
	      </row>

	      <row>
		<entry>0x405</entry>
		<entry>r/w</entry>
		<entry>Kanal 2 hohes Byte (Bits 23-16)
		  Word-Zähler</entry>
	      </row>

	      <row>
		<entry>0x407</entry>
		<entry>r/w</entry>
		<entry>Kanal 3 hohes Byte (Bits 23-16)
		  Word-Zähler</entry>
	      </row>

	      <row>
		<entry>0x4c6</entry>
		<entry>r/w</entry>
		<entry>Kanal 5 hohes Byte (Bits 23-16)
		  Word-Zähler</entry>
	      </row>

	      <row>
		<entry>0x4ca</entry>
		<entry>r/w</entry>
		<entry>Kanal 6 hohes Byte (Bits 23-16)
		  Word-Zähler</entry>
	      </row>

	      <row>
		<entry>0x4ce</entry>
		<entry>r/w</entry>
		<entry>Kanal 7 hohes Byte (Bits 23-16)
		  Word-Zähler</entry>
	      </row>

	      <row>
		<entry>0x487</entry>
		<entry>r/w</entry>
		<entry>Kanal 0 hohes Byte (Bits 31-24)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x483</entry>
		<entry>r/w</entry>
		<entry>Kanal 1 hohes Byte (Bits 31-24)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x481</entry>
		<entry>r/w</entry>
		<entry>Kanal 2 hohes Byte (Bits 31-24)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x482</entry>
		<entry>r/w</entry>
		<entry>Kanal 3 hohes Byte (Bits 31-24)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x48b</entry>
		<entry>r/w</entry>
		<entry>Kanal 5 hohes Byte (Bits 31-24)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x489</entry>
		<entry>r/w</entry>
		<entry>Kanal 6 hohes Byte (Bits 31-24)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x48a</entry>
		<entry>r/w</entry>
		<entry>Kanal 6 hohes Byte (Bits 31-24)
		  Seitenregister</entry>
	      </row>

	      <row>
		<entry>0x48f</entry>
		<entry>r/w</entry>
		<entry>hohes Byte Seitenauffrischung</entry>
	      </row>

	      <row>
		<entry>0x4e0</entry>
		<entry>r/w</entry>
		<entry>Kanal 0 Halteregister (Bits 7-2)</entry>
	      </row>

	      <row>
		<entry>0x4e1</entry>
		<entry>r/w</entry>
		<entry>Kanal 0 Halteregister (Bits 15-8)</entry>
	      </row>

	      <row>
		<entry>0x4e2</entry>
		<entry>r/w</entry>
		<entry>Kanal 0 Halteregister (Bits 23-16)</entry>
	      </row>

	      <row>
		<entry>0x4e4</entry>
		<entry>r/w</entry>
		<entry>Kanal 1 Halteregister (Bits 7-2)</entry>
	      </row>

	      <row>
		<entry>0x4e5</entry>
		<entry>r/w</entry>
		<entry>Kanal 1 Halteregister (Bits 15-8)</entry>
	      </row>

	      <row>
		<entry>0x4e6</entry>
		<entry>r/w</entry>
		<entry>Kanal 1 Halteregister (Bits 23-16)</entry>
	      </row>

	      <row>
		<entry>0x4e8</entry>
		<entry>r/w</entry>
		<entry>Kanal 2 Halteregister (Bits 7-2)</entry>
	      </row>

	      <row>
		<entry>0x4e9</entry>
		<entry>r/w</entry>
		<entry>Kanal 2 Halteregister (Bits 15-8)</entry>
	      </row>

	      <row>
		<entry>0x4ea</entry>
		<entry>r/w</entry>
		<entry>Kanal 2 Halteregister (Bits 23-16)</entry>
	      </row>

	      <row>
		<entry>0x4ec</entry>
		<entry>r/w</entry>
		<entry>Kanal 3 Halteregister (Bits 7-2)</entry>
	      </row>

	      <row>
		<entry>0x4ed</entry>
		<entry>r/w</entry>
		<entry>Kanal 3 Halteregister (Bits 15-8)</entry>
	      </row>

	      <row>
		<entry>0x4ee</entry>
		<entry>r/w</entry>
		<entry>Kanal 3 Halteregister (Bits 23-16)</entry>
	      </row>

	      <row>
		<entry>0x4f4</entry>
		<entry>r/w</entry>
		<entry>Kanal 5 Halteregister (Bits 7-2)</entry>
	      </row>

	      <row>
		<entry>0x4f5</entry>
		<entry>r/w</entry>
		<entry>Kanal 5 Halteregister (Bits 15-8)</entry>
	      </row>

	      <row>
		<entry>0x4f6</entry>
		<entry>r/w</entry>
		<entry>Kanal 5 Halteregister (Bits 23-16)</entry>
	      </row>

	      <row>
		<entry>0x4f8</entry>
		<entry>r/w</entry>
		<entry>Kanal 6 Halteregister (Bits 7-2)</entry>
	      </row>

	      <row>
		<entry>0x4f9</entry>
		<entry>r/w</entry>
		<entry>Kanal 6 Halteregister (Bits 15-8)</entry>
	      </row>

	      <row>
		<entry>0x4fa</entry>
		<entry>r/w</entry>
		<entry>Kanal 6 Halteregister (Bits 23-16)</entry>
	      </row>

	      <row>
		<entry>0x4fc</entry>
		<entry>r/w</entry>
		<entry>Kanal 7 Halteregister (Bits 7-2)</entry>
	      </row>

	      <row>
		<entry>0x4fd</entry>
		<entry>r/w</entry>
		<entry>Kanal 7 Halteregister (Bits 15-8)</entry>
	      </row>

	      <row>
		<entry>0x4fe</entry>
		<entry>r/w</entry>
		<entry>Kanal 7 Halteregister (Bits 23-16)</entry>
	      </row>

	      <row>
		<entry>0x40a</entry>
		<entry>write</entry>
		<entry>Kanal 0-3 Chaining-Modusregister</entry>
	      </row>

	      <row>
		<entry>0x40a</entry>
		<entry>read</entry>
		<entry>Kanal Interrupt Status-Register</entry>
	      </row>

	      <row>
		<entry>0x4d4</entry>
		<entry>write</entry>
		<entry>Kanal 4-7 Chaining-Modusregister</entry>
	      </row>

	      <row>
		<entry>0x4d4</entry>
		<entry>read</entry>
		<entry>Chaining Mode Status</entry>
	      </row>

	      <row>
		<entry>0x40c</entry>
		<entry>read</entry>
		<entry>Chain Buffer Expiration
		  Kontrollregister</entry>
	      </row>

	      <row>
		<entry>0x410</entry>
		<entry>write</entry>
		<entry>Kanal 0 Scatter-Gather Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0x411</entry>
		<entry>write</entry>
		<entry>Kanal 1 Scatter-Gather Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0x412</entry>
		<entry>write</entry>
		<entry>Kanal 2 Scatter-Gather Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0x413</entry>
		<entry>write</entry>
		<entry>Kanal 3 Scatter-Gather Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0x415</entry>
		<entry>write</entry>
		<entry>Kanal 5 Scatter-Gather Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0x416</entry>
		<entry>write</entry>
		<entry>Kanal 6 Scatter-Gather Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0x417</entry>
		<entry>write</entry>
		<entry>Kanal 7 Scatter-Gather Befehlsregister</entry>
	      </row>

	      <row>
		<entry>0x418</entry>
		<entry>read</entry>
		<entry>Kanal 0 Scatter-Gather Statusregister</entry>
	      </row>

	      <row>
		<entry>0x419</entry>
		<entry>read</entry>
		<entry>Kanal 1 Scatter-Gather Statusregister</entry>
	      </row>

	      <row>
		<entry>0x41a</entry>
		<entry>read</entry>
		<entry>Kanal 2 Scatter-Gather Statusregister</entry>
	      </row>

	      <row>
		<entry>0x41b</entry>
		<entry>read</entry>
		<entry>Kanal 3 Scatter-Gather Statusregister</entry>
	      </row>

	      <row>
		<entry>0x41d</entry>
		<entry>read</entry>
		<entry>Kanal 5 Scatter-Gather Statusregister</entry>
	      </row>

	      <row>
		<entry>0x41e</entry>
		<entry>read</entry>
		<entry>Kanal 5 Scatter-Gather Statusregister</entry>
	      </row>

	      <row>
		<entry>0x41f</entry>
		<entry>read</entry>
		<entry>Kanal 7 Scatter-Gather Statusregister</entry>
	      </row>

	      <row>
		<entry>0x420-0x423</entry>
		<entry>r/w</entry>
		<entry>Kanal 0 Scatter-Gather Descriptor Table Pointer
		  Register</entry>
	      </row>

	      <row>
		<entry>0x424-0x427</entry>
		<entry>r/w</entry>
		<entry>Kanal 1 Scatter-Gather Descriptor Table Pointer
		  Register</entry>
	      </row>

	      <row>
		<entry>0x428-0x42b</entry>
		<entry>r/w</entry>
		<entry>Kanal 2 Scatter-Gather Descriptor Table Pointer
		  Register</entry>
	      </row>

	      <row>
		<entry>0x42c-0x42f</entry>
		<entry>r/w</entry>
		<entry>Kanal 3 Scatter-Gather Descriptor Table Pointer
		  Register</entry>
	      </row>

	      <row>
		<entry>0x434-0x437</entry>
		<entry>r/w</entry>
		<entry>Kanal 5 Scatter-Gather Descriptor Table Pointer
		  Register</entry>
	      </row>

	      <row>
		<entry>0x438-0x43b</entry>
		<entry>r/w</entry>
		<entry>Kanal 6 Scatter-Gather Descriptor Table Pointer
		  Register</entry>
	      </row>

	      <row>
		<entry>0x43c-0x43f</entry>
		<entry>r/w</entry>
		<entry>Kanal 7 Scatter-Gather Descriptor Table Pointer
		  Register</entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>
      </sect3>
    </sect2>
  </sect1>
</chapter>