
Backgroundknowledge concerning the Devices:
-------------------------------------------

The pOS-Device is an extended Library. Mechanisms laid out
especially for Communication are part of the Devices.
The pExec-Kernel offers IO-Functions.
pOS_DoIO, pOS_SendIO, pOS_BeginIO, pOS_AbortIO, pOS_CheckIO, pOS_WaitIO.

For the Application a Device is an IO-Pool. Any Action can be
handled completely via pOS_DoIO. Via pOS_SendIO pOS_BeginIO 
the Action can be handled asynchronously to the Application.
A IO started this way can aborted at any given time with pOS_AbortIO.
Should the IO already be finished at the time of the pOS_AbortIO call,
the Abort has no result and the IO is ended correctly. A running
IO can be checked for his State at any time. The Function pOS_CheckIO 
determines, whether the IO is completed or if the IO is still
in progress. For Synchronisation afterwards serves the pOS_WaitIO-
Function, that waits until the IO is completed.

The pOS defines some Commends (CMD) for Device-Handling.
  (enum pOS_IOReqCommands) : io_Command

CMD_INVALID
 Non-definded Command, the Device always answers with IOERR_NoCMD.

CMD_RESET
 The Device is reset to Standardmode (Mode at power-up).
 All IOs are aborted and marked with IOERR_Aborted.
 All Buffers are reset.

CMD_READ
 io_Data points to the Buffer, that is to be filed with Data. Buffersize is
 stored in io_Length. After Completion of the Action that Buffersize 
 is found in io_Actual. The User has to test each Request via io_Error
 and io_Actual.
 With the Device-Handling only io_Flags, io_Actual, io_Error are changed.

CMD_WRITE
 The Buffer of io_Data is written. The Buffersize is stored in
 io_Length.
 With the Device-Handling only io_Flags, io_Actual, io_Error are changed.

CMD_UPDATE
 All buffered Data are written onto the Volume.

CMD_CLEAR
 All Databuffers are emptied.

CMD_STOP
 The Device is stopped. Via CMD_START the Device may be
 reactivated.

CMD_START
 see CMD_STOP

CMD_FLUSH
 All still uncompleted IOs are interrupted and marked as IOERR_Aborted.
 Only the currently handled IO is unaffected and continued as usual.

CMD_NONSTD
 Fill-in, from this Point on device-specific Commands may occur.



Each Call of pOS_DoIO, pOS_SendIO, pOS_BeginIO, pOS_WaitIO deletes and sets
the new io_Error. The other Device-IO-Funktionen do not change the io_Error
directly. It is possible though, that parallel to the User-Task the io_Error
is changed. Therefore the io_Error may be read only after completion of 
the IO.
The pOS defines in io_Error Standard-Errors with <0, as follows:
 (enum pOS_IOReqErrors) : io_Error

IOERR_None = 0
 There is no Error.

IOERR_OpenFail
 pOS_OpenDevice failed. The 'Error' is set into io_Error and 
 returned by pOS_OpenDevice.

IOERR_Aborted
 The IO was aborted prematurely via pOS_AbortIO or CMD_RESET, CMD_FLUSH
 Standard definition says that io_Actual always shows the currently
 valid State of work. From this may however after Abort nothing be 
 concluded about some possible completion in part.

IOERR_NoCMD
 The Command io_Command is unknown to the Device.

IOERR_BadLength
 The Working Length io_Length is wrong.

IOERR_BadAddress
 The Bufferaddress io_Data is wrong.

IOERR_UnitBusy
 If a Unit can not be opened shared, every pOS_OpenDevice from now on
 sets this Error.
 E.g. "pserial.device"

IOERR_Selftest
 Hardware is running a Selftest currently.

IOERR_NoMem
 General Lack of Memory.

IOERR_NoSubCMD
 Unknown Subcommand.


The following Device-Functions are impleneted into pOS:

pOS_OpenDevice
 Open the Device. Before a Device can be used,it has to be opened 
 and 'burned' on an IO. Any Errorcan be read in io_Error.

pOS_CloseDevice
 If a Device has been opened successfully via pOS_OpenDevice, it
 has to be closed again on the End.

pOS_DoIO
 The io_Command is executed synchronously and any Error that has happened
 can be read into io_Error. Before the Start the
 IOREQF_Quick-Flag is always deleted.

pOS_SendIO
 Like pOS_DoIO, only the Command is executed asynchronously to the Application.
 Before the Start the IOREQF_Quick-Flag is always set.
 Every asynchronous IO MUST be removed with pOS_WaitIO or pOS_GetMsg 
 from the ReplyPort.

pOS_BeginIO
 Like pOS_SendIO, only the IOREQF_Quick-Flag is not changed.

pOS_AbortIO
 An asynchronous IO is aborted. If the IO is completed by the time of the call
 of pOS_AbortIO, the Abort is without effect. If an IO was aborted,
 pOS_WaitIO or GetMsg have to be used like in the Standard case.
 The Abort modifies io_Error.
 pOS_Abort mayonly be used between pOS_SendIO/pOS_BeginIO and
 pOS_WaitIO.

pOS_CheckIO
 Checks, whether the IO is already completed. pOS_CheckIO gives a sensible
 Status only after pOS_SendIO/pOS_BeginIO and before pOS_WaitIO.

pOS_WaitIO
 Waits until the IO is completed or removes the IO from the ReplyPort.


How a Device is used:
---------------------

{
  pOS_MsgPort  ReplyPort;
  pOS_SerialIO *IO;

/*\
*** For Intertask-Communication with the Device a MsgPort is needed.
*** All IOs are sent to the ReplyPort at Completion or Abort.
\*/
  pOS_ConstructMsgPort(&ReplyPort);

/*\
*** The real Communication is done via the IORequest-Structure, that is
*** mostly called 'IO'. The Device puts its private Data into
*** pOS_OpenDevice and brings the IO up to date after each change.
\*/
  IO=(pOS_SerialIO*)pOS_CreateIORequest(&ReplyPort,sizeof(pOS_SerialIO));
  if(IO) {

/*\
*** The Device is opened and 'burned' into the IO-Structure.
*** If the process fails, pOS_OpenDevice returns the Error.
\*/
    if(0==pOS_OpenDevice("pserial.device",0,(pOS_IORequest*)IO,0,0)) {

/*\
*** The 'pserial.device' is to write a string. The pOS_DoIO-Function
*** executes the writecommand synchronously and returns the Error
*** if applicable.
\*/
      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);

/*\
*** After completion the Device MUST be closed again.
\*/
      pOS_CloseDevice((pOS_IORequest*)IO);
    }
    else printf("Cannot open device, error=%ld\n",IO->sio_Error);

/*\
*** The IO-Memory is released.
\*/
    pOS_DeleteIORequest((pOS_IORequest*)IO);
  }
  else printf("no mem\n");

/*\
*** The mp_SigBit is released.
\*/
  pOS_DestructMsgPort(&ReplyPort);
}


Simple asynchronous Device-Communication:
------------------------------------------

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

/*\
*** Starting of the asynchronous Device-Handling.
\*/
  pOS_SendIO((pOS_IORequest*)IO);
  ...
  ... asynchronous Action
  ...

/*\
*** Between pOS_SendIO and pOS_WaitIO the IO may not be changed !!!
***
*** Waiting, until the Device is finished with its handling.
\*/
  pOS_WaitIO((pOS_IORequest*)IO);
  if(IO->sio_Error != IOERR_None) ...
  ...
}




Extended asynchronous Device-Communication:
------------------------------------------

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

/*\
*** Start of the asynchronous Device-Handling.
\*/
  pOS_SendIO((pOS_IORequest*)IO);
  ...
  ... asynhronous Action
  ...

/*\
*** Abort of a Device-Handling. The following pOS_WaitIO
*** MUST be called upon.
\*/
  if(...) pOS_AbortIO((pOS_IORequest*)IO);


/*\
*** Between pOS_SendIO and pOS_WaitIO the IO must not be changed !!!
***
*** Wait, until the Device has completed its handling.
\*/
  pOS_WaitIO((pOS_IORequest*)IO);
  if(IO->sio_Error != IOERR_None) ...
  ...
}

©proDAD
