Extended Serial Device Driver (XSDD)

Entwurf eines Protokolls mit erweiterten Funktionen zur seriellen I/O

Author: Stephan Baucke
Erste Niederschrift: 7-Sept-1992
Letzte nderung: 11-Sept-1992

Einleitung
----------

Bekanntlich sind die Mglichkeiten des TOS zur Bedienung der seriellen Schnitt-
stellen recht beschrnkt:

- die Bedienung diverser Kontrolleitungen (wie DCD, DTR, RI usw.) ist nur durch
  Direktzugriff auf die Hardware mglich
- Es sind nur die von Rsconf angebotenen Baudraten einstellbar, auch wenn die
  Hardware mehr erlaubt
- Der Zugriff auf eine Schnittstelle von mehreren Programmen kann nicht koordiniert
  werden
- Da mit BIOS jedes Zeichen einzeln bertragen werden mu, ist die I/O-Performance
  nicht sehr hoch

Im Rahmen der Entwicklung eines seriellen Treibers fr MiNT, der diese Schwchen
beheben sollte, kam die Idee auf, die erweiterte Funktionalitt auch unter reinem
TOS zugnglich zu machen. Dies ist ein erster Vorschlag, wie das aussehen knnte.
Im wesentlichen werden dabei die Low-Level-Routinen des MiNT-Treibers ber einen
Cookie von auen zugnglich gemacht. Denkbar wre jedoch auch, die beiden Ebenen
vllig zu trennen und den MiNT-Treiber auf einen separaten TOS-Treiber aufzu-
setzen.


Das XSDD-Protokoll
------------------

Das XSDD-Protokoll untersttzt die ber Bconmap verwalteten Devices 6 bis ein-
schlielich <maptabsize+5> (soweit das zugrundeliegende TOS sie zur Verfgung
stellt), sowie das Device 1 (AUX). Operationen auf AUX beziehen sich immer auf
das zum Zeitpunkt des Aufrufs von XSDD gerade aktuelle Bconmap-Device. In Zu-
kunft wird AUX mglicherweise aus technischen Grnden nur noch dann untersttzt,
wenn das zugrundeliegende TOS kein Bconmap hat.

Der Treiber installiert einen Cookie "XSDD". Der Cookie zeigt auf den Einsprung-
punkt des XSDD-Treibers. Unmittelbar vor der Routine (also an Offset -4 vor der
Adresse aus dem Cookie) steht zur Absicherung nochmals die Long-Konstante "XSDD".

Aufruf: Welche Funktion ausgefhrt werden soll, wird durch einen Opcode (WORD)
angegeben. Dieser Opcode ist bei jedem Aufruf das erste Argument. Wenn ein un-
gltiger Opcode angegeben wird, wird EINVFN zurckgeliefert.

Die bergabe aller Parameter erfolgt nach GEMDOS-Konvention, d.h. auf dem Stack.
Der Rckgabewert wird in D0 geliefert. Auer D0 werden keine Register verndert.
Der Aufruf von XSDD darf AUSSCHLIESSLICH im Supervisor-Modus erfolgen. 

Z.Zt. sind die im folgenden aufgelisteten Funktionen vorgesehen (Opcodes mssen
noch vergeben werden). Fr die Parametertypen gilt folgende Vereinbarung:

BYTE:  8-Bit-Zeichen
WORD:  16-Bit signed Integer
UWORD: 16-Bit unsigned Integer
LONG:  32-Bit signed Integer

-----------------------------------------------------------------------------------
WORD XSVersion(void)
  Liefert die Versionsnummer des vom XSDD-Treibers implementierten Protokolls
  zurck, Major-Version im Hi-Byte, Minor-Version im Low-Byte (Beispiel: 0x0102
  entspricht Version 1.2). Diese Nummer soll nicht etwa die Version des Treiber-
  programms wiederspiegeln, sondern nur die des implementierten Protokolls.

  Rckgabe:
  Protokollversion.

-----------------------------------------------------------------------------------
WORD XSDriverInfo(BYTE *info, LONG *product, WORD *version)
  Dieser Aufruf liefert einen Info-String, eine Produktkennung, sowie die Version
  des jeweiligen Treiberprogramms zurck. `info' mu dabei auf einen mindestens 80
  Bytes groen Puffer zeigen, in den der Info-String nullterminiert eingetragen
  wird (der String kann z.B. den Author und den Namen des Treibers enthalten). In
  den LONG, auf den `product' zeigt, wird die Produktkennung eingetragen, sowie in
  das WORD, auf das `version' zeigt, die Treiberversion.
  
  Rckgabe
  0

-----------------------------------------------------------------------------------
WORD XSDevName(WORD device, BYTE *name)
  Ermittelt den Namen des zum BIOS-Device gehrigen Ports (z.B. "Modem1"). `name'
  mu auf ein mindestens 9 Bytes groes Array zeigen. Dort wird der Name nulltermi-
  niert eingetragen.
  
  Rckgabe:
  0 bei Erfolg
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
WORD XSReserve(WORD device)
  Device reservieren. Es handelt sich hier um ein "advisory" Locking, d.h. es ist
  darauf angewiesen, da jedes Programm den Lock abfragt und freiwillig auf weitere
  Zugriffe verzichtet, wenn das Device bereits belegt ist. Jedes Programm hat vor
  irgendeinem Zugriff auf das Device diesen Aufruf durchzufhren. Wenn das Device
  noch frei  war, ist es nach dem Aufruf reserviert. Wenn es bereits reserviert war,
  wird ein Fehlercode zurckgeliefert. In diesem Fall sollte keinerlei Zugriff mehr
  auf das Device erfolgen.
  
  Rckgabewert:
  0 - das Device ist jetzt reserviert
  EACCDN - das Gert war bereits reserviert
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
WORD XSRelease(WORD device)
  Device wieder freigeben. Dieser Aufruf darf NUR gemacht werden, wenn vorher
  ein erfolgreicher XSReserve durchgefhrt werden konnte (mit Rckgabe 0).

  Falls auf dem Device noch eine XSCtlSig-Routine angemeldet war, wird sie
  automatisch freigegeben.

  Rckgabewert:
  0 bei Erfolg, 
  EACCDN - wenn das Device nicht reserviert war.
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
LONG XSCapMap(WORD device)
  Fragt diverse Eigenschaften von Treiber und Device ab. Wenn kein Fehler vorliegt,
  wird ein Bitvektor zurckgeliefert. Folgende Bits sind z.Zt. definiert:

  #define XS_BREAK	0x01   /* Device kann Break senden */
  #define XS_RTSCTS 0x02   /* Device beherrscht RTS/CTS-Handshaking */
  #define XS_TANDEM 0x04   /* Device beherrscht XON/XOFF-Handshaking */  
  #define XS_IOBAUD 0x08   /* Device beherrscht verschiedene I- und O-Baudraten */

  #define XS_BIOSRW 0x8000 /* Treiber benutzt BIOS zum Lesen/Schreiben */
  
  Alle anderen Bits sind reserviert und sollten bis auf weiteres ignoriert
  werden.
  
  Rckgabewert:
  >=0 (LONG!) - Verfgbare Fhigkeiten
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
LONG XSIBaud(WORD device, LONG baudrate)
  Eingabe-Baudrate (genauer: bps) des angegebenen Devices setzen/abfragen. Die Baud-
  rate wird unkodiert im "Klartext" angegeben (38400L entspricht z.B. 38400 bps).
  Wenn -1L angegeben wird, wird die Baudrate nicht verndert (nur Abfrage). Falls
  eine Baudrate angfordert wird, die auf dem Device nicht zur Verfgung steht, wird
  die nchst niedrigere verfgbare eingestellt und zurckgeliefert.

  Die meisten Devices untersttzen keine getrennten Baudraten fr Ein- und Aus-
  gabe. In diesem Fall wird mit einem XSIBaud gleichzeitig auch die Ausgabe-
  Baudrate verndert (dies kann mit XSCapMap abgefragt werden).

  Rckgabewert:
  >0 - eingestellte Baudrate
  EUNDEV - Ungltiges Device

  Anmerkung: Durch die Rckgabe der nchst niedrigen verfgbaren Baudrate kann
  der Aufrufer alle fr dieses Device verfgbaren Baudraten durch "Abklappern"
  von oben nach unten ermitteln.

-----------------------------------------------------------------------------------
LONG XSOBaud(WORD device, LONG baudrate)
  Ausgabe-Baudrate (genauer: bps) des angegebenen Devices setzen/abfragen. Die
  Funktionsweise ist ansonsten analog zu XSIBaud.

  Die meisten Devices untersttzen keine getrennten Baudraten fr Ein- und Aus-
  gabe. In diesem Fall wird mit einem XSOBaud gleichzeitig auch die Eingabe-
  Baudrate verndert (dies kann mit XSCapMap abgefragt werden).

  Rckgabewert:
  >0 - eingestellte Baudrate
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
WORD XSBreak(WORD device, WORD on)
  Ein BREAK auf dem Device setzen/lschen. Wenn `on' ungleich 0 ist, wird BREAK
  gesetzt, ansonsten gelscht. Wenn das Device BREAK nicht beherrscht, wird der
  Aufruf ignoriert.

  Rckgabe: 
  0 bei Erfolg
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
LONG XSSetFlags(WORD device, UWORD flags)
  bertragungsparameter einstellen. Versuche, Einstellungen zu machen, die auf dem
  Device nicht mglich sind (d.h. solche, die XSCapMap als nicht verfgbar meldet),
  werden ignoriert. `flags' enthlt die Einstellung in folgender Kodierung (ent-
  spricht der des TIOCGFLAGS-Fcntl von MiNT):

  Maske: TF_STOPBITS 0x0003
  Werte:
	0x0000	Ungltig
	0x0001	1 Stop-Bit
	0x0002	1.5 Stop-Bits
	0x0003	2 Stop-Bits

  Maske: TF_CHARBITS 0x000C
  Werte:
    0x0000	8 Bits pro Zeichen
    0x0004	7 Bits
    0x0008	6 Bits
    0x000C	5 Bits

  Maske: TF_PARITY 0xc000
  Werte:
	0x0000  Keine Paritt
	0x4000	Gerade Paritt
	0x8000	Ungerade Paritt
	0xc000  Ungltig
	
  Weitere Bits:
	T_TANDEM	0x1000	XON/XOFF Handshake
	T_RTSCTS	0x2000	RTS/CTS Handshake

  Alle brigen Bits sind reserviert und sollten 0 sein.

  Rckgabewert:
  >=0 (LONG!) - die vor dem Aufruf eingestellten Flags
  ERANGE - es wurden ungltige Parameter festgestellt
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
LONG XSGetFlags(WORD device)
  bertragungsparameter abfragen.

  Rckgabewert:
  >=0 (LONG!) - Eingestellte Parameter (Kodierung siehe XSSetFlags).
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
LONG XSCtlMap(WORD device)
  Auf dem Device verfgbare Kontrolleitungen abfragen. Wenn kein Fehler vorliegt,
  wird ein Bitvektor zurckgeliefert, in dem fr die verfgbaren Kontrolleitungen
  das entsprechende Bit 1 ist, fr die nicht verfgbaren 0. Folgende Bits sind
  definiert:

  #define TIOCM_LE  0x01  			/* line enable */
  #define TIOCM_DTR 0x02  			/* data terminal ready */
  #define TIOCM_RTS 0x04  			/* ready to send */
  #define TIOCM_CTS 0x08  			/* clear to send */
  #define TIOCM_CAR 0x10  			/* carrier detect */
  #define TIOCM_RNG 0x20  			/* ring */
  #define TIOCM_DSR 0x40  			/* data set ready */

  Alle anderen Bits sind reserviert und sollten bis auf weiteres ignoriert
  werden.

  Rckgabewert:
  >=0 (LONG!) - Verfgbare Kontrolleitungen
  EUNDEV - Ungltiges Device

  Anmerkung: Die Werte werden mglicherweise noch gendert, um sie an die (hof-
  fentlich bald festgelegten) Definitionen der entsprechenden MiNT-Fcntls anzu-
  passen.

-----------------------------------------------------------------------------------
LONG XSGetCtl(WORD device)
  Status der Kontrolleitungen abfragen (DCD, RI etc.). Falls kein Fehler auf-
  tritt, wird ein Bit-Vektor geliefert (Kodierung wie bei XSCtlMap beschrieben).
  Die Bits sind 1, wenn die entsprechende Leitung aktiviert ist, sonst 0.

  Rckgabewert:
  >=0 (LONG!) - Status der Kontrolleitungen
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
WORD XSSetCtl(WORD device, UWORD ctl)
  Kontrolleitungen setzen. Kodierung wieder wie in XSCtlMap. Manche Leitungen (z.B.
  CTS) sind Read-only und knnen daher nicht beeinflut werden (das sollte aus dem
  Kontext hervorgehen). Versuche, solche und Leitungen, die nicht von dem Device
  untersttzt werden (d.h. von XSCtlMap als nicht verfgbar gemeldet wurden), zu
  beeinflussen, werden ignoriert.

  Rckgabewert:
  0 bei Erfolg
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
WORD XSOnCtl(WORD device, UWORD on_mask)
  Die Kontrolleitungen, deren Bit in `on_mask' gesetzt ist, aktivieren, ohne die
  anderen zu beeiflussen. Ansonsten gelten dieselben Bedingungen, wie bei XSSetCtl.

  Rckgabewert:
  0 bei Erfolg
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
WORD XSOffCtl(WORD device, UWORD off_mask)
  Die Kontrolleitungen, deren Bit in `off_mask' gesetzt ist, ausschalten, ohne die
  anderen zu beeiflussen. Ansonsten gelten dieselben Bedingungen, wie beiXSSetCtl.

  Rckgabewert:
  0 bei Erfolg
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
LONG XSInStat(WORD device)
  Ermittelt Anzahl der Zeichen, die z.Zt. auf dem Device zum Lesen verfgbar sind.
  Der zurckgelieferte Wert mu nicht exakt sein. Es ist nur garantiert, da mit
  dem nchsten Lesezugriff mindestens soviele Bytes gelesen werden knnen, es
  knnen aber auch mehr sein.
  
  Rckgabewert:
  >=0 - Anzahl der verfgbaren Zeichen
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
LONG XSOutStat(WORD device)
  Ermittelt Anzahl der Zeichen, die z.Zt. auf das Device geschrieben werden knnen.
  Der zurckgelieferte Wert mu nicht exakt sein. Es ist nur garantiert, da mit
  dem nchsten Schreibzugriff mindestens soviele Bytes ausgegeben werden knnen,
  es knnen aber auch mehr sein.

  Rckgabewert:
  >=0 - Anzahl der Zeichen, die ausgegeben werden knnen
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
LONG XSRead(WORD device, LONG count, BYTE *buffer)
  Maximal `count' Zeichen in den durch `buffer' angegebenen Speicherbereich lesen.
  Wenn z. Zt. nicht soviele Zeichen verfgbar sind, kehrt XSWrite sofort zurck
  (non-blocking).

  Rckgabewert:
  >=0 - Anzahl der Zeichen, die gelesen wurden wurden
  EUNDEV - Ungltiges Device
  Weitere (negative) TOS-Fehlernummern bei I/O-fehlern

-----------------------------------------------------------------------------------
LONG XSWrite(WORD device, LONG count, BYTE *buffer)
  `count' Zeichen aus dem durch `buffer' angegebenen Speicherbereich auf das Device
  schreiben. Wenn z. Zt. nicht so viele Zeichen geschrieben werden knnen, kehrt
  XSWrite sofort zurck (non-blocking).

  Rckgabewert:
  >=0 - Anzahl der Zeichen, die geschrieben wurden
  EUNDEV - Ungltiges Device
  Weitere (negative) TOS-Fehlernummern bei I/O-Fehlern

-----------------------------------------------------------------------------------
WORD XSFlush(WORD device, WORD mode)
  Verwerfe Zeichen, die noch im Puffer des Treibers stehen. `mode' gibt genauer
  an, was verworfen wird:
  0: Verwerfe Zeichen, die empfangen, aber noch nicht ausgelesen wurden
  1: Verwerfe Zeichen, die geschrieben, aber noch nicht gesendet wurden
  2: Verwerfe alle noch gepufferten Zeichen
  
  Wenn die Operation auf dem Device nicht mglich ist, wird der Aufruf ignoriert.
  
  Rckgabewert:
  0 bei Erfolg
  ERANGE - wenn `mode' nicht 0, 1 oder 2 ist
  EUNDEV - Ungltiges Device

-----------------------------------------------------------------------------------
WORD XSInSig(WORD device, void (*func)(WORD device))
  Weist den Treiber an, die durch `func' angegebene Funktion anzuspringen, sobald
  ein neues Zeichen von dem Device  eingetroffen ist. Der Routine wird dabei die
  Device-Nummer auf dem Stack bergeben. Die angegebene Routine wird sehr wahr-
  scheinlich aus einem Interrupt heraus aufgerufen. Dementsprechend darf sie keine
  Register verndern und sollte mglichst kurz sein. Die Routine wird nur genau
  einmal aufgerufen, danach wird der XSInSig automatisch wieder deaktiviert. Wenn
  vor dem Aufruf bereits ein XSInSig aktiv war, wird der neue nicht installiert
  und EACCDN zurckgeliefert.
  
  Wenn als `func' ein Null-Zeiger bergeben wird, wird ein vorher gesetzter XSInSig
  annuliert.
  
  XSInSig mu nicht auf jedem Device verfgbar sein; in diesem Fall wird EINVFN
  zurckgeliefert.

  Rckgabe:
  0 - bei Erfolg
  EINVFN - Device untersttzt XSInSig nicht
  EACCDN - Es ist bereits ein XSInSig aktiv
  EUNDEV - Ungltiges Device  

  Anmerkung: Diese Funktion ist in der Hauptsache zur Implementation von MiNT-
  Treibern gedacht und sollte von Anwendungsprogrammen nicht verwendet werden.

-----------------------------------------------------------------------------------
WORD XSOutSig(WORD device, void (*func)(WORD device))
  Weist den Treiber an, die durch `func' angegebene Funktion anzuspringen, sobald
  ein neues Zeichen auf das Device ausgegeben werden kann. Die Funktionsweise ist
  ansonsten analog zu XSInSig.

  Wenn als `func' ein Null-Zeiger bergeben wird, wird ein vorher gesetzter
  XSOutSig annuliert.
  
  XSOutSig mu nicht auf jedem Device verfgbar sein; in diesem Fall wird EINVFN
  zurckgeliefert.

 Rckgabe:
  0 - bei Erfolg
  EINVFN - Device untersttzt XSOutSig nicht
  EACCDN - Es ist bereits ein XSOutSig aktiv
  EUNDEV - Ungltiges Device  

  Anmerkung: Diese Funktion ist in der Hauptsache zur Implementation von MiNT-
  Treibern gedacht und sollte von Anwendungsprogrammen nicht verwendet werden.

-----------------------------------------------------------------------------------
LONG XSCtlSig(WORD device, UWORD ctl_mask, void (*func)(WORD device, UWORD ctl))
  Weist den Treiber an, die durch `func' angegebene Funktion anzuspringen, sobald
  sich der Zustand einer der in `ctl_mask' spezifizierten Kontrolleitungen ndert
  (Kodierung wie bei XSCtlMap angegeben). Der Routine wird dabei die Device-Nummer
  und ein Bitvektor, in dem das Bit der auslsenden Kontrolleitung gesetzt ist,
  auf dem Stack bergeben. Die angegebene Routine wird sehr wahrscheinlich aus
  einem Interrupt heraus aufgerufen. Dementsprechend darf sie keine Register ver-
  ndern und sollte mglichst kurz sein. Die Routine wird nur genau einmal aufge-
  rufen, danach wird der XSCtlSig automatisch wieder deaktiviert. Wenn vor dem
  Aufruf bereits ein XSCtlSig aktiv war, wird der neue nicht installiert und
  EACCDN zurckgeliefert.

  Wenn als `func' ein Null-Zeiger bergeben wird, wird ein vorher gesetzter
  XSCtlSig annuliert.
  
  XSCtlSig mu nicht auf jedem Device verfgbar sein; in diesem Fall wird EINVFN
  zurckgeliefert. Ebenso mu er nicht fr alle verfgbaren Kontrolleitungen ver-
  fgbar sein. Wenn in `ctl_mask' Kontrolleitungen angegeben werden, die durch
  XSCtlSig nicht untersttzt werden, wird das ignoriert. Auf welche Leitungen
  tatschlich reagiert wird, kann man aus dem Rckgabewert ersehen.

  Sobald ein Device mit XSRelease freigegeben wird, werden noch darauf installierte
  XCtlSig automatisch abgemeldet.
  
  Rckgabe:
  >0 (LONG!) - Maske mit den tatschlich bercksichtigten Kontrolleitungen.
  EINVFN - Device untersttzt XSCtlSig nicht
  EACCDN - Es ist bereits ein XSCtlSig aktiv
  EUNDEV - Ungltiges Device  

  Anmerkung: Diese Funktion kann z.B. verwendet werden, um effizient die RI- oder
  DCD-Leitungen zu berwachen (man installiert eine Routine, die im eigenen Pro-
  gramm ein Flag setzt und fragt dieses periodisch ab). ACHTUNG: Ein Programm,
  da diese Funktion benutzt, darf keinesfalls vergessen, den XSCtlSig vor dem
  Beenden wieder zu annulieren.

END-OF-TEXT