
Hintergrundwissen zu den Devices:
-----------------------------------

Das pOS-Device ist eine erweiterte Library. Speziell zur
Kommuntikation ausgelegte Mechanismem sind Bestandteil der Devices.
Der pExec-Kernel stellt IO-Funktionen bereit.
pOS_DoIO, pOS_SendIO, pOS_BeginIO, pOS_AbortIO, pOS_CheckIO, pOS_WaitIO.

Von Sicht des Anwenderprogramms aus ist ein Device ein IO-Pool. Eine Aktion
kann mittels pOS_DoIO vollständig bearbeitet werden. Mit pOS_SendIO und
pOS_BeginIO kann die Aktion asynchron zum Anwenderprogramm erfolgen.
Ein so gestarteter IO kann jederzeit mit pOS_AbortIO abgebrochen werden.
Sollte der IO beim Aufruf von pOS_AbortIO schon fertig sein, so hat
der Abort keine Auswirkung und der IO ist korrekt beendet. Ein laufender
IO kann jederzeit auf seinen Status geprüft werden. Die Funktion
pOS_CheckIO ermittelt, ob der IO abgeschlossen ist oder ob der IO noch
bearbeitet wird. Zur nachträglichen Synchronisation dient die pOS_WaitIO-
Funtion, die solange wartet, bis der IO bearbeitet ist.

Das pOS definiert einige Kommandos (CMD) für die Device-Handhabung.
  (enum pOS_IOReqCommands) : io_Command

CMD_INVALID
 Nicht definiertes Kommando, das Device antwortet immer mit IOERR_NoCMD.

CMD_RESET
 Das Device wird in den Grundzustand (Einschaltzustand) zurückgesetzt.
 Alle IOs werden abgebrochen und mit IOERR_Aborted gekennzeichnet.
 Sämtliche Puffer werden zurückgesetzt.

CMD_READ
 io_Data zeigt auf den Puffer, der mit Daten gefüllt werden soll. Die Puffergröße
 wird in io_Length vermerkt. Nach Vollendung der Aktion steht in io_Actual die
 beschriebene Puffergröße. Der Anwender muß jeden Request mittels io_Error
 und io_Actual prüfen.
 Durch die Device-Bearbeitung wird nur io_Flags, io_Actual, io_Error verändert.

CMD_WRITE
 Der Puffer von io_Data wird geschrieben. Die Puffergröße befindet sich in
 io_Length.
 Durch die Device-Bearbeitung wird nur io_Flags, io_Actual, io_Error verändert.

CMD_UPDATE
 Sämtliche gepufferte Daten werden auf den Datenträger geschrieben.

CMD_CLEAR
 Sämtliche Datenpuffer werden geleert.

CMD_STOP
 Das Device wird angehalten. Durch CMD_START kann das Device wieder aktiviert
 werden.

CMD_START
 siehe CMD_STOP

CMD_FLUSH
 Alle noch ausstehenden IOs werden abgebrochen und als IOERR_Aborted gekennzeichnet.
 Nur der aktuell bearbeitete IO ist nicht betroffen und wird normal weiterbearbeitet.

CMD_NONSTD
 Platzhalter, ab dieser Position können device-eigene Kommandos folgen.



Jeder Aufruf von pOS_DoIO, pOS_SendIO, pOS_BeginIO, pOS_WaitIO löscht und setzt
den neuen io_Error. Die restlichen Device-IO-Funktionen verändert den io_Error
nicht direkt. Es ist aber denkbar, daß parallel zum Anwender-Task der io_Error
verändert wird. Deshalb darf der io_Error erst nach Vollendung des IO's ausgelesen
werden.
Das pOS definiert in io_Error Standard-Errors mit <0, wie folgt:
 (enum pOS_IOReqErrors) : io_Error

IOERR_None = 0
 Es liegt kein Fehler vor.

IOERR_OpenFail
 pOS_OpenDevice ist fehlgeschlagen. Der 'Error' wird in io_Error gesetzt und
 von pOS_OpenDevice zurückgegeben.

IOERR_Aborted
 Der IO wurde durch pOS_AbortIO oder durch CMD_RESET, CMD_FLUSH vorzeitig
 abgebrochen. Die Grunddefinition besagt, daß io_Actual immer den aktuell
 gültigen Bearbeitungs-Stand anzeigt. Hieraus darf aber beim Abort nicht
 auf eine eventuelle Teilbearbeitung geschlossen werden.

IOERR_NoCMD
 Das Kommando io_Command ist dem Device nicht bekannt.

IOERR_BadLength
 Die Bearbeitungslänge io_Length ist falsch.

IOERR_BadAddress
 Die Pufferadresse io_Data ist falsch.

IOERR_UnitBusy
 Kann eine Unit nicht ge-shared geöffnet werden, wird bei jedem
 weiteren pOS_OpenDevice dieser Fehler gesetzt.
 Z.B. "pserial.device"

IOERR_Selftest
 Hardware führt zur Zeit einen Selbsttest durch.

IOERR_NoMem
 Allgemeiner Speichermangel.

IOERR_NoSubCMD
 Unbekanntes Unterkommando.


Im pOS sind folgende Device-Funktionen implementiert:

pOS_OpenDevice
 Device öffnen. Bevor ein Device eingesetzt werden kann, muß es geöffnet
 und auf einen IO 'eingebrant' werden. Ein Fehler kann in io_Error
 ausgelesen werden.

pOS_CloseDevice
 Konnte ein Device mittels pOS_OpenDevice erfolgreich geöffnet werden, so
 muß es am Ende wieder geschlossen werden.

pOS_DoIO
 Das io_Command wird synchron ausgeführt und ein eventuell aufgetretener
 Error kann in io_Error ausgelesen werden. Vor dem Start wird immer das
 IOREQF_Quick-Flag gelöscht.

pOS_SendIO
 Wie pOS_DoIO, jedoch wird das Kommando asynchron zum Anwenderprogramm ausgeführt.
 Vor dem Start wird immer das IOREQF_Quick-Flag gesetzt.
 Jeder asynchrone IO MUSS mit pOS_WaitIO bzw. pOS_GetMsg vom ReplyPort
 entfert werden.

pOS_BeginIO
 Wie pOS_SendIO, aber das IOREQF_Quick-Flag wird nicht verändert.

pOS_AbortIO
 Ein asynchroner IO wird abgebrochen. Ist der IO zum Zeitpunkt vom Aufruf von
 pOS_AbortIO bereits vollendet, so ist der Abort wirkungslos. Wurde ein IO
 abgebrochen, muß wie im Normalfall pOS_WaitIO bzw. GetMsg verwendet werden.
 Der Abort modifiziert io_Error.
 pOS_Abort darf nur zwischen pOS_SendIO/pOS_BeginIO und pOS_WaitIO eingesetzt
 werden.

pOS_CheckIO
 Prüft, ob der IO bereits vollendet ist. pOS_CheckIO liefert nur nach
 pOS_SendIO/pOS_BeginIO und vor pOS_WaitIO einen sinnvollen Status.

pOS_WaitIO
 Wartet bis der IO vollendet ist bzw. entfernt den IO vom ReplyPort.


Wie wird ein Device verwendet:
------------------------------

{
  pOS_MsgPort  ReplyPort;
  pOS_SerialIO *IO;

/*\
*** Zur Intertask-Kommunikation mit dem Device wird ein MsgPort benötigt.
*** Alle IOs werden nach Vollendung bzw. nach Abort an den ReplyPort gesendet.
\*/
  pOS_ConstructMsgPort(&ReplyPort);

/*\
*** Die eigentliche Kommunikation erfolgt über die IORequest-Stuktur, die
*** oft als 'IO' bezeichnet wird. Das Device setzt seine privaten Daten
*** in pOS_OpenDevice und aktuallisiert den IO bei der Bearbeitung.
\*/
  IO=(pOS_SerialIO*)pOS_CreateIORequest(&ReplyPort,sizeof(pOS_SerialIO));
  if(IO) {

/*\
*** Das Device wird geöffnet und auf die IO-Struktur 'eingebrant'.
*** Sollte der Vorgang fehlschlagen, liefert pOS_OpenDevice den Error
*** zurück.
\*/
    if(0==pOS_OpenDevice("pserial.device",0,(pOS_IORequest*)IO,0,0)) {

/*\
*** Das "pserial.device" soll eine Zeichenkette schreiben. Die pOS_DoIO-Funktion
*** führt das Schreibkommando synchron aus und meldet uns einen eventuellen
*** Fehler zurück.
\*/
      IO->sio_Command=CMD_WRITE;
      IO->sio_Data=(APTR)"12345";
      IO->sio_Length=5;
      if(0==pOS_DoIO((pOS_IORequest*)IO)) printf("ok\n");
      else printf("Cannot CMD_WRITE, error=%ld\n",IO->sio_Error);

/*\
*** Nach vollbrachter Arbeit muß das Device unbedingt wieder geschlossen werden.
\*/
      pOS_CloseDevice((pOS_IORequest*)IO);
    }
    else printf("Cannot open device, error=%ld\n",IO->sio_Error);

/*\
*** Der IO-Speicher wird freigegeben.
\*/
    pOS_DeleteIORequest((pOS_IORequest*)IO);
  }
  else printf("no mem\n");

/*\
*** Das mp_SigBit wird freigegeben.
\*/
  pOS_DestructMsgPort(&ReplyPort);
}


Einfache asynchrone Device-Kommunikation:
------------------------------------------

{
  ...
  IO->sio_Command=CMD_WRITE;
  IO->sio_Data=(APTR)"12345";
  IO->sio_Length=5;

/*\
*** Starten der asynchronen Device-Bearbeitung.
\*/
  pOS_SendIO((pOS_IORequest*)IO);
  ...
  ... asynhrone Aktion
  ...

/*\
*** Zwischen pOS_SendIO und pOS_WaitIO darf die IO nicht verändert werden !!!
***
*** Warten, bis das Device seine Bearbeitung vollendet hat.
\*/
  pOS_WaitIO((pOS_IORequest*)IO);
  if(IO->sio_Error != IOERR_None) ...
  ...
}




Erweiterte asynchrone Device-Kommunikation:
------------------------------------------

{
  ...
  IO->sio_Command=CMD_WRITE;
  IO->sio_Data=(APTR)"12345";
  IO->sio_Length=5;

/*\
*** Starten der asynchronen Device-Bearbeitung.
\*/
  pOS_SendIO((pOS_IORequest*)IO);
  ...
  ... asynhrone Aktion
  ...

/*\
*** Abbrechen einer Device-Bearbeitung. Der folgende pOS_WaitIO
*** MUSS unbedingt aufgerufen werden.
\*/
  if(...) pOS_AbortIO((pOS_IORequest*)IO);


/*\
*** Zwischen pOS_SendIO und pOS_WaitIO darf die IO nicht verändert werden !!!
***
*** Warten, bis das Device seine Bearbeitung vollendet hat.
\*/
  pOS_WaitIO((pOS_IORequest*)IO);
  if(IO->sio_Error != IOERR_None) ...
  ...
}

©proDAD
