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 M”glichkeiten des TOS zur Bedienung der seriellen Schnitt- stellen recht beschr„nkt: - die Bedienung diverser Kontrolleitungen (wie DCD, DTR, RI usw.) ist nur durch Direktzugriff auf die Hardware m”glich - 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 fr MiNT, der diese Schw„chen beheben sollte, kam die Idee auf, die erweiterte Funktionalit„t auch unter reinem TOS zug„nglich zu machen. Dies ist ein erster Vorschlag, wie das aussehen k”nnte. Im wesentlichen werden dabei die Low-Level-Routinen des MiNT-Treibers ber einen Cookie von aužen zug„nglich gemacht. Denkbar w„re jedoch auch, die beiden Ebenen v”llig zu trennen und den MiNT-Treiber auf einen separaten TOS-Treiber aufzu- setzen. Das XSDD-Protokoll ------------------ Das XSDD-Protokoll untersttzt die ber Bconmap verwalteten Devices 6 bis ein- schliežlich (soweit das zugrundeliegende TOS sie zur Verfgung 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 m”glicherweise aus technischen Grnden nur noch dann untersttzt, 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 ausgefhrt werden soll, wird durch einen Opcode (WORD) angegeben. Dieser Opcode ist bei jedem Aufruf das erste Argument. Wenn ein un- gltiger Opcode angegeben wird, wird EINVFN zurckgeliefert. Die šbergabe aller Parameter erfolgt nach GEMDOS-Konvention, d.h. auf dem Stack. Der Rckgabewert wird in D0 geliefert. Aužer D0 werden keine Register ver„ndert. Der Aufruf von XSDD darf AUSSCHLIESSLICH im Supervisor-Modus erfolgen. Z.Zt. sind die im folgenden aufgelisteten Funktionen vorgesehen (Opcodes mssen noch vergeben werden). Fr 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 zurck, 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. Rckgabe: Protokollversion. ----------------------------------------------------------------------------------- WORD XSDriverInfo(BYTE *info, LONG *product, WORD *version) Dieser Aufruf liefert einen Info-String, eine Produktkennung, sowie die Version des jeweiligen Treiberprogramms zurck. `info' muž dabei auf einen mindestens 80 Bytes grožen 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. Rckgabe 0 ----------------------------------------------------------------------------------- WORD XSDevName(WORD device, BYTE *name) Ermittelt den Namen des zum BIOS-Device geh”rigen Ports (z.B. "Modem1"). `name' muž auf ein mindestens 9 Bytes grožes Array zeigen. Dort wird der Name nulltermi- niert eingetragen. Rckgabe: 0 bei Erfolg EUNDEV - Ungltiges 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 durchzufhren. Wenn das Device noch frei war, ist es nach dem Aufruf reserviert. Wenn es bereits reserviert war, wird ein Fehlercode zurckgeliefert. In diesem Fall sollte keinerlei Zugriff mehr auf das Device erfolgen. Rckgabewert: 0 - das Device ist jetzt reserviert EACCDN - das Ger„t war bereits reserviert EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- WORD XSRelease(WORD device) Device wieder freigeben. Dieser Aufruf darf NUR gemacht werden, wenn vorher ein erfolgreicher XSReserve durchgefhrt werden konnte (mit Rckgabe 0). Falls auf dem Device noch eine XSCtlSig-Routine angemeldet war, wird sie automatisch freigegeben. Rckgabewert: 0 bei Erfolg, EACCDN - wenn das Device nicht reserviert war. EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- LONG XSCapMap(WORD device) Fragt diverse Eigenschaften von Treiber und Device ab. Wenn kein Fehler vorliegt, wird ein Bitvektor zurckgeliefert. 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. Rckgabewert: >=0 (LONG!) - Verfgbare F„higkeiten EUNDEV - Ungltiges 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 ver„ndert (nur Abfrage). Falls eine Baudrate angfordert wird, die auf dem Device nicht zur Verfgung steht, wird die n„chst niedrigere verfgbare eingestellt und zurckgeliefert. Die meisten Devices untersttzen keine getrennten Baudraten fr Ein- und Aus- gabe. In diesem Fall wird mit einem XSIBaud gleichzeitig auch die Ausgabe- Baudrate ver„ndert (dies kann mit XSCapMap abgefragt werden). Rckgabewert: >0 - eingestellte Baudrate EUNDEV - Ungltiges Device Anmerkung: Durch die Rckgabe der n„chst niedrigen verfgbaren Baudrate kann der Aufrufer alle fr dieses Device verfgbaren 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 untersttzen keine getrennten Baudraten fr Ein- und Aus- gabe. In diesem Fall wird mit einem XSOBaud gleichzeitig auch die Eingabe- Baudrate ver„ndert (dies kann mit XSCapMap abgefragt werden). Rckgabewert: >0 - eingestellte Baudrate EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- WORD XSBreak(WORD device, WORD on) Ein BREAK auf dem Device setzen/l”schen. Wenn `on' ungleich 0 ist, wird BREAK gesetzt, ansonsten gel”scht. Wenn das Device BREAK nicht beherrscht, wird der Aufruf ignoriert. Rckgabe: 0 bei Erfolg EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- LONG XSSetFlags(WORD device, UWORD flags) šbertragungsparameter einstellen. Versuche, Einstellungen zu machen, die auf dem Device nicht m”glich sind (d.h. solche, die XSCapMap als nicht verfgbar meldet), werden ignoriert. `flags' enth„lt die Einstellung in folgender Kodierung (ent- spricht der des TIOCGFLAGS-Fcntl von MiNT): Maske: TF_STOPBITS 0x0003 Werte: 0x0000 Ungltig 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 Parit„t 0x4000 Gerade Parit„t 0x8000 Ungerade Parit„t 0xc000 Ungltig Weitere Bits: T_TANDEM 0x1000 XON/XOFF Handshake T_RTSCTS 0x2000 RTS/CTS Handshake Alle brigen Bits sind reserviert und sollten 0 sein. Rckgabewert: >=0 (LONG!) - die vor dem Aufruf eingestellten Flags ERANGE - es wurden ungltige Parameter festgestellt EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- LONG XSGetFlags(WORD device) šbertragungsparameter abfragen. Rckgabewert: >=0 (LONG!) - Eingestellte Parameter (Kodierung siehe XSSetFlags). EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- LONG XSCtlMap(WORD device) Auf dem Device verfgbare Kontrolleitungen abfragen. Wenn kein Fehler vorliegt, wird ein Bitvektor zurckgeliefert, in dem fr die verfgbaren Kontrolleitungen das entsprechende Bit 1 ist, fr die nicht verfgbaren 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. Rckgabewert: >=0 (LONG!) - Verfgbare Kontrolleitungen EUNDEV - Ungltiges Device Anmerkung: Die Werte werden m”glicherweise noch ge„ndert, 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. Rckgabewert: >=0 (LONG!) - Status der Kontrolleitungen EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- WORD XSSetCtl(WORD device, UWORD ctl) Kontrolleitungen setzen. Kodierung wieder wie in XSCtlMap. Manche Leitungen (z.B. CTS) sind Read-only und k”nnen daher nicht beeinflužt werden (das sollte aus dem Kontext hervorgehen). Versuche, solche und Leitungen, die nicht von dem Device untersttzt werden (d.h. von XSCtlMap als nicht verfgbar gemeldet wurden), zu beeinflussen, werden ignoriert. Rckgabewert: 0 bei Erfolg EUNDEV - Ungltiges 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. Rckgabewert: 0 bei Erfolg EUNDEV - Ungltiges 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. Rckgabewert: 0 bei Erfolg EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- LONG XSInStat(WORD device) Ermittelt Anzahl der Zeichen, die z.Zt. auf dem Device zum Lesen verfgbar sind. Der zurckgelieferte Wert muž nicht exakt sein. Es ist nur garantiert, daž mit dem n„chsten Lesezugriff mindestens soviele Bytes gelesen werden k”nnen, es k”nnen aber auch mehr sein. Rckgabewert: >=0 - Anzahl der verfgbaren Zeichen EUNDEV - Ungltiges Device ----------------------------------------------------------------------------------- LONG XSOutStat(WORD device) Ermittelt Anzahl der Zeichen, die z.Zt. auf das Device geschrieben werden k”nnen. Der zurckgelieferte Wert muž nicht exakt sein. Es ist nur garantiert, daž mit dem n„chsten Schreibzugriff mindestens soviele Bytes ausgegeben werden k”nnen, es k”nnen aber auch mehr sein. Rckgabewert: >=0 - Anzahl der Zeichen, die ausgegeben werden k”nnen EUNDEV - Ungltiges 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 verfgbar sind, kehrt XSWrite sofort zurck (non-blocking). Rckgabewert: >=0 - Anzahl der Zeichen, die gelesen wurden wurden EUNDEV - Ungltiges 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 k”nnen, kehrt XSWrite sofort zurck (non-blocking). Rckgabewert: >=0 - Anzahl der Zeichen, die geschrieben wurden EUNDEV - Ungltiges 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 m”glich ist, wird der Aufruf ignoriert. Rckgabewert: 0 bei Erfolg ERANGE - wenn `mode' nicht 0, 1 oder 2 ist EUNDEV - Ungltiges 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 ver„ndern und sollte m”glichst 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 zurckgeliefert. Wenn als `func' ein Null-Zeiger bergeben wird, wird ein vorher gesetzter XSInSig annuliert. XSInSig muž nicht auf jedem Device verfgbar sein; in diesem Fall wird EINVFN zurckgeliefert. Rckgabe: 0 - bei Erfolg EINVFN - Device untersttzt XSInSig nicht EACCDN - Es ist bereits ein XSInSig aktiv EUNDEV - Ungltiges 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 verfgbar sein; in diesem Fall wird EINVFN zurckgeliefert. Rckgabe: 0 - bei Erfolg EINVFN - Device untersttzt XSOutSig nicht EACCDN - Es ist bereits ein XSOutSig aktiv EUNDEV - Ungltiges 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 ausl”senden 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 m”glichst 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 zurckgeliefert. Wenn als `func' ein Null-Zeiger bergeben wird, wird ein vorher gesetzter XSCtlSig annuliert. XSCtlSig muž nicht auf jedem Device verfgbar sein; in diesem Fall wird EINVFN zurckgeliefert. Ebenso muž er nicht fr alle verfgbaren Kontrolleitungen ver- fgbar sein. Wenn in `ctl_mask' Kontrolleitungen angegeben werden, die durch XSCtlSig nicht untersttzt werden, wird das ignoriert. Auf welche Leitungen tats„chlich reagiert wird, kann man aus dem Rckgabewert ersehen. Sobald ein Device mit XSRelease freigegeben wird, werden noch darauf installierte XCtlSig automatisch abgemeldet. Rckgabe: >0 (LONG!) - Maske mit den tats„chlich bercksichtigten Kontrolleitungen. EINVFN - Device untersttzt XSCtlSig nicht EACCDN - Es ist bereits ein XSCtlSig aktiv EUNDEV - Ungltiges 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