home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / DC-POS24.LZX / pOS / pOS_RKRM.lzx / pOS_RKRM / pDos / PortHd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-18  |  25.9 KB  |  848 lines

  1.  
  2. /*******************************************************************
  3.  $CRT 03 Jun 1996 : hb
  4.  
  5.  $AUT Holger Burkarth
  6.  $DAT >>PortHd.c<<   15 Mar 1997    09:21:39 - (C) ProDAD
  7. *******************************************************************/
  8.  
  9. //##ex mcpp:cppc -gs -o pos:pos/devs/PortHd.ddv p:pLib/DevCode.o p:/pOS_RKRM/pDos/PortHd.c -l pOSStub -l pOS -l CPPList
  10.  
  11. /***********************************************************
  12.   pOS programing example - Copyright (C) 1995-97 proDAD
  13.  
  14.   This code was written as an easy to understand example,
  15.   how to program pOS features. It is provided 'as-is',
  16.   without any express or implied warranty.
  17.  
  18.   Permission is hereby granted to use, copy and modify
  19.   this source code for any purpose, without fee, subject
  20.   to the following conditions:
  21.  
  22.     (1) This notice may not be removed or altered from any
  23.         source distribution.
  24.  
  25.     (2) Altered source versions must be plainly marked as
  26.         such, and must not be misrepresented as being
  27.         the original source code.
  28.  
  29.     (3) If only executable code is distributed, then the
  30.         accompanying documentation have to state that
  31.         "this software is based in part on examples of
  32.         the pOS developer packet".
  33.  
  34.     (4) Permission for use of this code is granted only
  35.         if the user accepts full responsibility for any
  36.         undesirable consequences. proDAD accept NO LIABILITY
  37.         for damages of any kind.
  38.  
  39.   ©proDAD
  40. ***********************************************************/
  41.  
  42. /*\
  43. *** Mount:
  44. ***
  45. *** TYPE_PICO DDNAME="devs:PortHd.ddv"
  46. *** STARTUP="DEVICE=pserial.device UNIT=0 TYPE_SER"
  47. ***
  48. \*/
  49.  
  50.  
  51. #define __COMPUTER_AMIGA 1
  52. #define NOMYDEBUG
  53.  
  54. #include "p:pExec/Types.h"
  55. #include "p:pExec/Memory.h"
  56. #include "p:pExec/Diagnos.h"
  57. #include "p:pExec/TstTags.h"
  58. #include "p:pDOS/ArgTags.h"
  59. #include "p:pDOS/DosErrors.h"
  60. #include "p:pDOS/DosDev.h"
  61. #include "p:pDOS/DosBase.h"
  62. #include "p:pDOS/Segment.h"
  63. #include "p:pExec/Sema.h"
  64. #include "p:pExec/Task.h"
  65. #include "p:pDOS/Files.h"
  66. #include "p:Device/Serial.h"
  67. #include "p:proto/pLibExt.h"
  68. #include "p:proto/pExec2.h"
  69. #include "p:proto/pDOS2.h"
  70. #include "p:proto/pList.h"
  71.  
  72. #ifdef _____ME_____
  73.   #include "grund/inc_string.h"
  74.   #include "grund/inc_limits.h"
  75. #else
  76.  #ifdef __cplusplus
  77.  extern "C" {
  78.  #endif
  79.   #include <string.h>
  80.   #include <limits.h>
  81.  #ifdef __cplusplus
  82.  }
  83.  #endif
  84. #endif
  85.  
  86.  
  87. #define __WWW(a) ;
  88. //#define __WWW(a) a;
  89.  
  90.  
  91.  
  92. #define    MAX(a,b)     ( (a)>(b)?(a):(b) )
  93. #define    MIN(a,b)     ( (a)<(b)?(a):(b) )
  94.  
  95. struct pOS_ExecBase        *gb_ExecBase;
  96. struct pOS_ExecLibFunction *gb_ExecLib;
  97. struct pOS_DosBase         *gb_DosBase;
  98.  
  99.  
  100.  
  101. struct PortDosDevice
  102. {
  103.   pOS_DosDevice       pdd_Dev;
  104.   pOS_Task           *pdd_Task;
  105.   pOS_Semaphore       pdd_Sem;
  106.   pOS_FileHandle      pdd_FH;
  107.   pOS_MsgPort         pdd_UnitPort;
  108.   pOS_MsgPort         pdd_ReadPort;
  109.   pOS_MsgPort         pdd_WritePort;
  110.   pOS_IOStdReq       *pdd_ReadIO;
  111.   pOS_IOStdReq       *pdd_WriteIO;
  112.   pOS_ExList          pdd_RdList;
  113.   pOS_DosIOReq       *pdd_ActReadIO;
  114.  
  115.   UBYTE   *pdd_Buffer;
  116.   size_t   pdd_BufSize;
  117.   size_t   pdd_ActSize;
  118.   UBYTE    pdd_FhIsOpen; /* Boolean */
  119.   UBYTE    pdd_SerMode;  /* Boolean */
  120.  
  121.   CHAR     pdd_StdControlString[8];
  122. };
  123.  
  124. /*\
  125. *** Allgemeines:
  126. *** In der pdd_RdList-Liste werden alle Read-IOs eingereiht, die nicht sofort
  127. *** bearbeitet werden können. Der aktuelle ReadIO wird in pdd_ReadIO vermerkt.
  128. *** Der pdd_ReadIO befindet sich in keiner Liste und kann somit sofort
  129. *** ge-replyed werden. Wogegen der Abort eines pdd_RdList-IOs ein pOS_Remove
  130. *** und dann ein pOS_ReplyMsg benötigt.
  131. ***
  132. \*/
  133.  
  134. extern ULONG *FuncTable[];
  135. extern BOOL pDevMain(_R_LB pOS_ExecBase*,_R_A0 PortDosDevice*);
  136.  
  137. const CHAR DeviceName[]  ="PortHandler.ddv";
  138. const CHAR DeviceIDName[]="PortHandler.ddv 1.0 ("__DATE2__") (Created by Holger Burkarth)";
  139. const pOS_TagItem DeviceDescribe[]=
  140. {
  141.   EXTSTTAG_MainOSID, pOS_MAINOSID,
  142.   TAG_END
  143. };
  144.  
  145.  
  146.  
  147. pOS_ResidentLibInit InitTable=
  148. {
  149.   sizeof(PortDosDevice),
  150.   FuncTable,
  151.   NULL,
  152.   (BOOL(*)(_R_LB pOS_ExecBase*,_R_A0 pOS_Library*))pDevMain
  153. };
  154.  
  155.  
  156.  
  157. BOOL OpenDev(PortDosDevice* dev);
  158. VOID CloseDev(PortDosDevice* dev);
  159.  
  160.  
  161.  
  162.  
  163. /*----------------------------------
  164. -----------------------------------*/
  165. BOOL pDevMain(_R_LB pOS_ExecBase* exec,_R_A0 PortDosDevice* dev)
  166. {
  167.   extern struct pOS_ExecBase        *gb_ExecBase;
  168.   extern struct pOS_ExecLibFunction *gb_ExecLib;
  169.   extern struct pOS_DosBase         *gb_DosBase;
  170.  
  171.   gb_ExecBase=(struct pOS_ExecBase*)exec;
  172.  
  173. /* Pre-pOS-Trick */
  174.   gb_ExecLib=*((struct pOS_ExecLibFunction**)dev->pdd_Dev.ddv_Dev.lib_Segm->sel_Seg.seg_Reserved2);
  175.  
  176.   gb_DosBase =(pOS_DosBase*)pOS_OpenLibrary("pDos.library",0);
  177.  
  178.   return( OpenDev(dev) );
  179. }
  180.  
  181.  
  182. /*----------------------------------
  183. -----------------------------------*/
  184. pOS_SegmentLst* Expunge_func(_R_LB PortDosDevice* dev)
  185. {
  186.   if(dev->pdd_Dev.ddv_Dev.lib_OpenCnt==0) {
  187.     pOS_SegmentLst* Seg=dev->pdd_Dev.ddv_Dev.lib_Segm;
  188.  
  189.     pOS_ListRemove(&dev->pdd_Dev.ddv_Dev.lib_Node);
  190.     CloseDev(dev);
  191.     pOS_CloseLibrary((struct pOS_Library*)gb_DosBase);
  192.     _pOS_FreeLibraryMem2(&dev->pdd_Dev.ddv_Dev);
  193.     return(Seg);
  194.   }
  195.   return(0);
  196. }
  197.  
  198.  
  199. /*----------------------------------
  200. -----------------------------------*/
  201. ULONG Reserved_func(_R_LB PortDosDevice*)
  202. {  return(0); }
  203.  
  204.  
  205. /*----------------------------------
  206. -----------------------------------*/
  207. VOID AbortIO_func(_R_LB PortDosDevice* dev,_R_A0 pOS_DosIOReq* io)
  208. {
  209. /*\
  210. *** Ein IO kann jederzeit abgebrochen werden. Damit kein 'Speichersalat'
  211. *** durch mehrere Tasks in (PortDosDevice) entsteht, wird eine Semaphore
  212. *** über (PortDosDevice) aufgespannt.
  213. *** Der Abort ist eine sensible Funktion und wird leider sehr oft fehlerhaft
  214. *** implementiert.
  215. *** Zuerst wird geprüft, ob unser 'io' in der aktuelle ReadIO ist. In diesem
  216. *** Fall können wird den 'io' als aborted kennzeichnen und zurücksenden (reply).
  217. *** Obwohl der Reply-Port unser Port ist, müssen wir pOS_ReplyMsg verwenden,
  218. *** nur so wird das Standard-Device-Verhalten aufrechterhalten.
  219. *** Damit das Device weiterarbeiten kann, legen wir den nächsten ReadIO aus
  220. *** der Warteschlange nach. Ist kein IO in der Warteliste, dann liefert
  221. *** pOS_ListRemHead null und pdd_ActReadIO wird autom. genullt.
  222. *** War unser 'io' nicht der aktuelle ReadIO, so existieren 3 mögliche Zustände.
  223. *** 1. Der 'io' wurde bereits als vollendet oder ReadWrite-Error an den ReplyPort
  224. *** zurückgesendet. Da nach ReplyMsg der ln_Type immer auf NTYP_REPLYMSG steht
  225. *** kann dies einfach ermittelt werden. Aber Vorsicht, die Abfrage darf auf
  226. *** keinem Fall ln_Type!=NTYP_REPLYMSG lauten, da ln_Type noch weitere Zustände
  227. *** wiedergibt. Es ist aber sicher ln_Type==NTYP_MESSAGE zu prüfen, nach einem
  228. *** pOS_PutMsg ist ln_Type immer auf NTYP_MESSAGE gesetzt.
  229. *** 2. Der 'io' befindet sich noch im pdd_UnitPort und hatte noch keinen Kontakt
  230. *** mit dem Handler-Task.
  231. *** 3. Der 'io' wurde vom Handler in die pdd_RdList-Warteschlange eingereiht.
  232. *** Fall 2 und 3 sind für uns als Abort-er gleichbedeutend. Der 'io' befindet
  233. *** sich in einer Liste und muß von uns erst mittels pOS_ListRemove aus der
  234. *** selbigen entfernt werden, denn ein Node kann zur gleich Zeit nur einer
  235. *** Liste angehören.
  236. \*/
  237.  
  238. __WWW( kprintf("AbortIO_func io=0x%lx\n",io) );
  239.  
  240.   pOS_ObtainSemaphore(&dev->pdd_Sem);
  241.   if(io==dev->pdd_ActReadIO) {
  242.     io->dr_Error2=DOSERR_Aborted;
  243.     pOS_ReplyMsg(&io->dr_Message);
  244.     dev->pdd_ActReadIO=(pOS_DosIOReq*)pOS_ListRemHead(&dev->pdd_RdList);
  245.   }
  246.   else if(io->dr_Message.mn_Node.ln_Type==NTYP_MESSAGE) {
  247.     pOS_ListRemove(&io->dr_Message.mn_Node);
  248.     io->dr_Error2=DOSERR_Aborted;
  249.     pOS_ReplyMsg(&io->dr_Message);
  250.   }
  251.   pOS_ReleaseSemaphore(&dev->pdd_Sem);
  252. }
  253.  
  254. /*----------------------------------
  255. -----------------------------------*/
  256. VOID BeginIO_func(_R_LB PortDosDevice* dev,_R_A0 pOS_DosIOReq* io)
  257. {
  258. /*\
  259. *** Der Handler-Task soll den 'io' bearbeiten. Wir reichen den 'io' nur weiter.
  260. \*/
  261.   io->dr_Error2=DOSERR_None;
  262.   io->dr_Flags &= ~IOREQF_Quick;
  263. __WWW( kprintf("BeginIO_func io=0x%lx\n",io) );
  264.   pOS_PutMsg(&dev->pdd_UnitPort,&io->dr_Message);
  265. }
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272. ULONG *FuncTable[]=
  273. {
  274.  (ULONG*)Reserved_func,
  275.  (ULONG*)Reserved_func,
  276.  (ULONG*)Expunge_func,
  277. // ------------
  278.  (ULONG*)Reserved_func,
  279.  (ULONG*)Reserved_func,
  280.  (ULONG*)Reserved_func,
  281.  (ULONG*)Reserved_func,
  282.  (ULONG*)Reserved_func,
  283.  (ULONG*)Reserved_func,
  284.  (ULONG*)Reserved_func,
  285.  (ULONG*)Reserved_func,
  286. // ------------
  287.  (ULONG*)BeginIO_func,
  288.  (ULONG*)AbortIO_func,
  289. // ------------
  290.  (ULONG*)Reserved_func,
  291.  (ULONG*)Reserved_func,
  292.  (ULONG*)Reserved_func,
  293.  (ULONG*)Reserved_func,
  294.  (ULONG*)Reserved_func,
  295.  (ULONG*)Reserved_func,
  296.  (ULONG*)Reserved_func,
  297.  (ULONG*)Reserved_func,
  298. // ------------
  299.  
  300.  (ULONG*)ULONG_MAX
  301. };
  302.  
  303. /***********************************************************************/
  304.  
  305. /*----------------------------------
  306. -----------------------------------*/
  307. VOID CloseIODev(PortDosDevice* Dev,BOOL DevIsOpen)
  308. {
  309.   if(DevIsOpen) {
  310. /*\
  311. *** Damit ein noch laufender Ser-IO uns nicht 'abschießt', wird sichergestellt,
  312. *** daß alle IOs ihre Tätigkeit beendet haben.
  313. *** Die pOS_Funktion pOS_CheckIO prüft, ob der IO bereits fertig ist. Läuft
  314. *** der IO noch, wir er mittels AbortIO abgebrochen. Um alle Probleme im
  315. *** Keim zu ersticken folgt pOS_WaitIO.
  316. \*/
  317.     if(!pOS_CheckIO((pOS_IORequest*)Dev->pdd_ReadIO))
  318.         pOS_AbortIO((pOS_IORequest*)Dev->pdd_ReadIO);
  319.     if(!pOS_CheckIO((pOS_IORequest*)Dev->pdd_WriteIO))
  320.         pOS_AbortIO((pOS_IORequest*)Dev->pdd_WriteIO);
  321.  
  322.     pOS_WaitIO((pOS_IORequest*)Dev->pdd_ReadIO);
  323.     pOS_WaitIO((pOS_IORequest*)Dev->pdd_WriteIO);
  324.     pOS_CloseDevice((pOS_IORequest*)Dev->pdd_ReadIO);
  325.   }
  326.   if(Dev->pdd_ReadIO)  pOS_DeleteIORequest((pOS_IORequest*)Dev->pdd_ReadIO);
  327.   if(Dev->pdd_WriteIO) pOS_DeleteIORequest((pOS_IORequest*)Dev->pdd_WriteIO);
  328.   if(Dev->pdd_Buffer)  pOS_FreeMem(Dev->pdd_Buffer,Dev->pdd_BufSize);
  329.   Dev->pdd_ReadIO= Dev->pdd_WriteIO= NULL;
  330.   Dev->pdd_Buffer=NULL;
  331. }
  332.  
  333. /*----------------------------------
  334. -----------------------------------*/
  335. BOOL OpenIODev(PortDosDevice* Dev)
  336. {
  337.   pOS_DosArgs* Args;
  338.   const pOS_DosMountDevice *const MD=Dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_Mount;
  339.   ULONG Ops[5]={0,0,0,1024,(ULONG)"9600/8N1N"};
  340.   BOOL DevIsOpen=FALSE;
  341.  
  342. __WWW( kprintf("OpenIODev\n") );
  343.  
  344. /*\
  345. *** Mount-Startup mittels der ReadArgs parsen. pOS_ReadDosArgs benötigt nicht
  346. *** unbedingt einen pOS_Process.
  347. *** Damit kein Speicherplatz unnötig verschwendet wird, werden die Args sofort
  348. *** wieder freigegeben. Beachte, daß nach pOS_DeleteDosArgs alle eventuellen
  349. *** Strings freigegeben werden.
  350. \*/
  351.   if(Args=pOS_ReadDosArgs(
  352. // 0          1        2            3          4
  353. "DEVICE/A, UNIT/N, TYPE_SER/S, BUFFERS/N/K, CONTROL/K",
  354.   Ops,sizeof(Ops)/sizeof(ULONG),
  355.   ARGTAG_Arguments, (ULONG)MD->dmd_U.dmd_Pico.dmpic_Startup,
  356.   TAG_DONE))
  357.   {
  358.     Dev->pdd_BufSize=*((ULONG*)Ops[3]);
  359.     if(Dev->pdd_BufSize<512) Dev->pdd_BufSize=512;
  360.     Dev->pdd_Buffer=(UBYTE*)pOS_AllocMem(Dev->pdd_BufSize,MEMF_PUBLIC);
  361.  
  362.     strncpy(Dev->pdd_StdControlString,(CHAR*)Ops[4],sizeof(Dev->pdd_StdControlString)-1);
  363.  
  364.     if(Dev->pdd_Buffer && Ops[2]) {
  365.       Dev->pdd_SerMode=TRUE;
  366.       Dev->pdd_ReadIO=(pOS_IOStdReq*)
  367.           pOS_CreateIORequest(&Dev->pdd_ReadPort,sizeof(pOS_SerialIO));
  368.       Dev->pdd_WriteIO=(pOS_IOStdReq*)
  369.           pOS_CreateIORequest(&Dev->pdd_WritePort,sizeof(pOS_SerialIO));
  370.     }
  371.  
  372.     if(Dev->pdd_ReadIO && Dev->pdd_WriteIO) {
  373.       pOS_OpenDevice((CHAR*)Ops[0],*((ULONG*)Ops[1]),(pOS_IORequest*)Dev->pdd_ReadIO,0,0);
  374.       if(Dev->pdd_ReadIO->io_Error==0) {
  375.         *Dev->pdd_WriteIO = *Dev->pdd_ReadIO;
  376.         Dev->pdd_WriteIO->io_Message.mn_ReplyPort=&Dev->pdd_WritePort;
  377.         DevIsOpen=TRUE;
  378. __WWW( kprintf("OpenIODev ok\n") );
  379.       }
  380.       else {
  381. __WWW( kprintf("OpenIODev Device-Error %ld\n",Dev->pdd_ReadIO->io_Error) );
  382.       }
  383.     }
  384.     pOS_DeleteDosArgs(Args);  /* Args freigeben */
  385.   }
  386.   else {
  387. __WWW( kprintf("OpenIODev Args-Error |%s|\n",MD->dmd_U.dmd_Pico.dmpic_Startup) );
  388.   }
  389.   return(DevIsOpen);
  390. }
  391.  
  392.  
  393.  
  394.  
  395.  
  396. /*----------------------------------
  397. -----------------------------------*/
  398. BOOL SetParam(PortDosDevice* Dev,const CHAR* name)
  399. {
  400.   pOS_DosArgs* Args;
  401.   ULONG Ops[2]={9600,(ULONG)"8N1N"};
  402.   BOOL Result=FALSE;
  403.  
  404.   if(Dev->pdd_SerMode) {
  405.     if(Args=pOS_ReadDosArgs(
  406. // 0      1
  407. "BAUD/N, MODE",
  408.     Ops,sizeof(Ops)/sizeof(ULONG),
  409.     ARGTAG_Arguments, (ULONG) (name ? name:Dev->pdd_StdControlString),
  410.     ARGTAG_Seperator, (ULONG)'/',
  411.     TAG_DONE))
  412.     {
  413.       pOS_SerialIO *const IO=(pOS_SerialIO*)Dev->pdd_ReadIO;
  414.       const CHAR *const Control=(CHAR*)Ops[1];
  415.       const size_t ControlLen=strlen(Control);
  416.  
  417.       IO->sio_Baud = *((ULONG*)Ops[0]);
  418.  
  419.  
  420. __WWW( kprintf("SetParam-SER Baud=%ld Control=|%s|\n",IO->sio_Baud,Control) );
  421.  
  422.  
  423.       if(Control[0]=='7') IO->sio_ReadLen = 7;
  424.       else                IO->sio_ReadLen = 8;
  425.  
  426.       switch(ControlLen>1 ? Control[1]:' ') {
  427.         case  'O':
  428.         case  'o':
  429.           IO->sio_SerFlags |= SERF_XDisabled | SERF_PartyOdd | SERF_PartyOn;
  430.           break;
  431.  
  432.         case  'E':
  433.         case  'e':
  434.           IO->sio_SerFlags |= SERF_XDisabled | SERF_PartyOn;
  435.           IO->sio_SerFlags &= ~SERF_PartyOdd;
  436.           break;
  437.  
  438.         default:
  439.           IO->sio_SerFlags |= SERF_XDisabled;
  440.           IO->sio_SerFlags &= ~(SERF_PartyOn | SERF_PartyOdd);
  441.       }
  442.  
  443.       if(ControlLen>2 && Control[2]=='2')
  444.            IO->sio_StopBits = 2;
  445.       else IO->sio_StopBits = 1;
  446.  
  447.  
  448.       switch(ControlLen>3 ? Control[3]:' ') {
  449.         case  'X':
  450.         case  'x':
  451.           IO->sio_SerFlags &= ~(SERF_XDisabled | SERF_7Wire);
  452.           break;
  453.  
  454.         case  'R':
  455.         case  'r':
  456.           IO->sio_SerFlags |= (SERF_XDisabled | SERF_7Wire);
  457.           break;
  458.  
  459.         default:
  460.           IO->sio_SerFlags |= SERF_XDisabled;
  461.           IO->sio_SerFlags &= ~SERF_7Wire;
  462.       }
  463.  
  464.  
  465.       IO->sio_WriteLen=IO->sio_ReadLen;
  466.  
  467.       IO->sio_Command=SERCMD_SetParams;
  468.       if(0==pOS_DoIO((pOS_IORequest*)IO)) {
  469.         Result=TRUE;
  470.       }
  471.  
  472.       pOS_DeleteDosArgs(Args);  /* Args freigeben */
  473.     }
  474.   }
  475.   else Result=TRUE;
  476.   return(Result);
  477. }
  478.  
  479.  
  480.  
  481.  
  482.  
  483. /*----------------------------------
  484. -----------------------------------*/
  485. VOID AbortAllPendingIOs(PortDosDevice* Dev)
  486. {
  487.   pOS_DosIOReq *IO;
  488.  
  489. __WWW( kprintf("AbortAllPendingIOs\n") );
  490.  
  491.   while(IO=(pOS_DosIOReq*)pOS_ListRemHead(&Dev->pdd_RdList)) {
  492.     IO->dr_Error2=DOSERR_Aborted;
  493.     pOS_ReplyMsg(&IO->dr_Message);
  494.   }
  495.   if(IO=Dev->pdd_ActReadIO) {
  496.     IO->dr_Error2=DOSERR_Aborted;
  497.     pOS_ReplyMsg(&IO->dr_Message);
  498.   }
  499. }
  500.  
  501.  
  502.  
  503. /*----------------------------------
  504. -----------------------------------*/
  505. VOID HandlerFunc(VOID)
  506. {
  507.   pOS_Task *const ThisTask=pOS_FindTask(NULL);
  508.   PortDosDevice *const Dev=(PortDosDevice*)ThisTask->tc_UserData[0];
  509.   BOOL DevIsOpen=FALSE;
  510.   UBYTE ReadChar;
  511.  
  512. __WWW( kprintf("HandlerFunc start\n") );
  513.  
  514.   pOS_ConstructMsgPort(&Dev->pdd_UnitPort);
  515.   pOS_ConstructMsgPort(&Dev->pdd_ReadPort);
  516.   pOS_ConstructMsgPort(&Dev->pdd_WritePort);
  517.   pOS_ListInit(&Dev->pdd_RdList);
  518.  
  519. /*\
  520. *** Standard-FileHandle vorbereiten. Da der Port-Handler immer nur ein File
  521. *** zur gleichen Zeit zuläßt, muß die FH nicht dynamisch Verwaltet werden.
  522. \*/
  523.   pOS_ConstructDosFH(&Dev->pdd_FH,&Dev->pdd_Dev,0);
  524.   Dev->pdd_FH.fh_Flags = FILEHDF_Interactive;
  525.  
  526.   if(1 /*OpenIODev(Dev)*/) {
  527.     const ULONG WaitSig=   (1<<Dev->pdd_UnitPort.mp_SigBit)
  528.                          | (1<<Dev->pdd_ReadPort.mp_SigBit) ;
  529.  
  530.     pOS_SendSignal(ThisTask->tc_FriendTask,SIGF_Signal); // *** OK
  531.     ThisTask->tc_FriendTask=NULL;
  532.  
  533.     while(ThisTask->tc_FriendTask==NULL) {
  534.       ULONG Sig;
  535.       Sig=pOS_WaitSignal(WaitSig);
  536.  
  537. /*\
  538. *** Der Zugriff auf (PortDosDevice) wird durch die pdd_Sem-Semaphore geschützt.
  539. *** Damit der Semaphore-Mechanismus nicht unnötige Systemzeit verschlingt, erfolgt
  540. *** der Lock/Unlock nur in der äußersten Schleife. Der Schutz ist nötig, da die
  541. *** Abort-Funktion ebenfalls auf die (PortDosDevice) zugreift.
  542. \*/
  543.       pOS_ObtainSemaphore(&Dev->pdd_Sem);
  544.  
  545.  
  546. /*\
  547. *** IO-Read ist vollendet.
  548. \*/
  549.       if(Sig & (1<<Dev->pdd_ReadPort.mp_SigBit)) {
  550. __WWW( kprintf("HandlerFunc ReadPort\n") );
  551.         if(pOS_GetMsg(&Dev->pdd_ReadPort)) { /* WICHTIG, ReplyPort wird geleert */
  552.           if(Dev->pdd_ReadIO->io_Error==0) {
  553.  
  554. #define t_RD Dev->pdd_ActReadIO->dr_U.dr_ReadFH
  555.  
  556. /*\
  557. *** Befindet sich ein ReadIO in der Bearbeitung, dann werden alle hereinkommenden
  558. *** Daten sofort dem IO zugewiesen. Ist der aktuelle IO fertigt, wird er Replyed
  559. *** und der nächste in der Warteschlange wird nachgelegt und wird so zum aktuellen.
  560. *** Gibt es keinen aktuellen ReadIO, dann werden alle Daten in den Lesepuffer
  561. *** geschrieben.
  562. \*/
  563.             if(Dev->pdd_ActReadIO) {
  564.               ((UBYTE*)t_RD.drrd_Adr)[t_RD.drrd_ResSize]=ReadChar;
  565.               ++t_RD.drrd_ResSize;
  566.               for(;;) {
  567.                 /**if(t_RD.drrd_ResSize == t_RD.drrd_Size) **/
  568.                 if(t_RD.drrd_ResSize != 0)
  569.                 {
  570.                   pOS_ReplyMsg(&Dev->pdd_ActReadIO->dr_Message);
  571.                   Dev->pdd_ActReadIO=(pOS_DosIOReq*)pOS_ListRemHead(&Dev->pdd_RdList);
  572.                 }
  573.                 else if(Dev->pdd_SerMode) {
  574.                   Dev->pdd_ReadIO->io_Command=SERCMD_Query;
  575.                   pOS_DoIO((pOS_IORequest*)Dev->pdd_ReadIO);
  576.                   if(Dev->pdd_ReadIO->io_Actual>0) {
  577.                     size_t Size;
  578.                     Size=t_RD.drrd_Size-t_RD.drrd_ResSize;
  579.                     Size=MIN(Size,Dev->pdd_ReadIO->io_Actual);
  580.                     Dev->pdd_ReadIO->io_Command=CMD_READ;
  581.                     Dev->pdd_ReadIO->io_Length=Size;
  582.                     Dev->pdd_ReadIO->io_Data=(APTR) ((ULONG)t_RD.drrd_Adr + t_RD.drrd_ResSize);
  583.                     pOS_DoIO((pOS_IORequest*)Dev->pdd_ReadIO);
  584.                     t_RD.drrd_ResSize+=Size;
  585.                     continue;
  586.                   }
  587.                 }
  588.                 break;
  589.               }
  590.             }
  591.             else if(Dev->pdd_ActSize<Dev->pdd_BufSize) {
  592.               Dev->pdd_Buffer[ Dev->pdd_ActSize++ ] = ReadChar;
  593.             }
  594. #undef t_RD
  595.           }
  596.  
  597. /*\
  598. *** Lesefehler vom Ser-Device. Der aktuelle ReadIO wird mit gesetztem Error
  599. *** abgebrochen.
  600. \*/
  601.           else {
  602. __WWW( kprintf("Read-Error %ld\n",Dev->pdd_ReadIO->io_Error) );
  603.  
  604.             if(Dev->pdd_ActReadIO) {
  605.               if(Dev->pdd_ReadIO->io_Error==SERIOERR_DetectedBreak) {
  606.                 Dev->pdd_ActReadIO->dr_Error2=0;
  607.                 Dev->pdd_ActReadIO->dr_U.dr_ReadFH.drrd_ResSize=0;
  608.               }
  609.               else {
  610.                 Dev->pdd_ActReadIO->dr_Error2=DOSERR_ReadWriteError;
  611.               }
  612.               pOS_ReplyMsg(&Dev->pdd_ActReadIO->dr_Message);
  613.               Dev->pdd_ActReadIO=(pOS_DosIOReq*)pOS_ListRemHead(&Dev->pdd_RdList);
  614.             }
  615.           }
  616.  
  617. /*\
  618. *** Ser-Device wieder starten, damit das nächste Byte gelesen werden kann.
  619. \*/
  620.           Dev->pdd_ReadIO->io_Command=CMD_READ;
  621.           Dev->pdd_ReadIO->io_Length=1;
  622.           Dev->pdd_ReadIO->io_Data=(APTR)&ReadChar;
  623.           pOS_SendIO((pOS_IORequest*)Dev->pdd_ReadIO);
  624.         }
  625.       }
  626.  
  627. /*\
  628. *** Von Dos kommende Msg.
  629. \*/
  630.       if(Sig & (1<<Dev->pdd_UnitPort.mp_SigBit)) {
  631.         pOS_DosIOReq *IO;
  632.  
  633. __WWW( kprintf("HandlerFunc UnitPort\n") );
  634.  
  635.         while(IO=(pOS_DosIOReq*)pOS_GetMsg(&Dev->pdd_UnitPort)) {
  636.           switch(IO->dr_Command) {
  637.  
  638. /*\
  639. *** Ein Anwenderprogramm hat pOS_OpenFile aufgerufen. Der Port-Handler unterstützt
  640. *** nur ein FH zur gleichen Zeit und frägt dies mittels pdd_FhIsOpen ab.
  641. *** Damit kein falscher Dateipfad entstehen kann, werden nur absolute Pfade
  642. *** (IO->dr_U.dr_OpenFH.drop_CurrLock==NULL) zugelassen.
  643. *** [absoluter Pfad => a:xxx oder con: oder par:]
  644. *** Konnten alle Resourcen alloziert werden, wird das Ser-Device gestartet.
  645. \*/
  646.             case DOSCMD_OpenFH:
  647. __WWW( kprintf(
  648. "DOSCMD_OpenFH<%lx> \n"
  649. " pdd_FhIsOpen = %ld\n"
  650. " drop_Name     =0x%lx\n"
  651. " drop_CurrDir  =0x%lx\n"
  652. ,IO,Dev->pdd_FhIsOpen,IO->dr_U.dr_OpenFH.drop_Name
  653. ,IO->dr_U.dr_OpenFH.drop_CurrLock) );
  654.  
  655.               if(Dev->pdd_FhIsOpen==0) {
  656.                 if(   IO->dr_U.dr_OpenFH.drop_Name!=NULL
  657.                    && IO->dr_U.dr_OpenFH.drop_CurrLock==NULL)
  658.                 {
  659.                   IO->dr_U.dr_OpenFH.drop_ResFH=&Dev->pdd_FH;
  660.                   Dev->pdd_FH.fh_Size=0; Dev->pdd_FH.fh_Pos=0;
  661.                   Dev->pdd_FH.fh_Access=IO->dr_U.dr_OpenFH.drop_Mode & FILEHDMOD_AcMsk;
  662.                   if(    (DevIsOpen=OpenIODev(Dev))
  663.                       && SetParam(Dev,IO->dr_U.dr_OpenFH.drop_Name))
  664.                   {
  665.                     Dev->pdd_ActSize=0;
  666.                     Dev->pdd_ReadIO->io_Command=CMD_READ;
  667.                     Dev->pdd_ReadIO->io_Data=(APTR)&ReadChar;
  668.                     Dev->pdd_ReadIO->io_Length=1;
  669. __WWW( kprintf("Send-ReadIO\n") );
  670.                     pOS_SendIO((pOS_IORequest*)Dev->pdd_ReadIO);
  671.  
  672.                     Dev->pdd_FhIsOpen=1;
  673.                   }
  674.                   else {
  675.                     CloseIODev(Dev,FALSE);
  676.                     IO->dr_Error2=DOSERR_ObjectNotFound;
  677.                   }
  678.                 }
  679.                 else IO->dr_Error2=DOSERR_WrongObjectType;
  680.               }
  681.               else IO->dr_Error2=DOSERR_ObjectExists;
  682.               break;
  683.  
  684.  
  685. /*\
  686. *** Das Anwenderprogramm ruft pOS_CloseFile() auf.
  687. *** Alle noch ausstehende IOs (Read-Requests) werden abgebrochen.
  688. *** Eigentlich dürften bei Close nie IOs ausstehen, dennoch wird hier
  689. *** dieser Fall als Anschauungsbeispiel verwendet.
  690. \*/
  691.             case DOSCMD_CloseFH:
  692. __WWW( kprintf("DOSCMD_CloseFH pdd_FhIsOpen=%ld\n",Dev->pdd_FhIsOpen) );
  693.  
  694.               if(Dev->pdd_FhIsOpen) {
  695.                 Dev->pdd_FhIsOpen=0;
  696.                 AbortAllPendingIOs(Dev);
  697.                 CloseIODev(Dev,DevIsOpen); DevIsOpen=FALSE;
  698.               }
  699.               else IO->dr_Error2=DOSERR_ObjectNotFound;
  700.               break;
  701.  
  702.  
  703. /*\
  704. *** Das Anwenderprogramm ruft pOS_ReadFile() auf.
  705. *** Befindet sich bereits ein IO in der Bearbeitung, so wird der neue IO
  706. *** in die Warteschlange eingereiht.
  707. *** Ist kein ReadIO in der Bearbeitung, dann wird zuerst ein eventueller
  708. *** Datenstrom, der in der Zwischenzeit von pOS_OpenFile() bis pOS_ReadFile()
  709. *** eingegangen ist, dem IO zugeordnet. Konnte der IO vollständig bedient werden,
  710. *** wird er sofort ge-replyed. Ansonsten wird der IO zum aktuellen.
  711. \*/
  712.             case DOSCMD_ReadFH:
  713. __WWW( kprintf(
  714. "DOSCMD_ReadFH\n"
  715. " drrd_Size     = %ld\n"
  716. " pdd_ActReadIO = 0x%lx\n"
  717. " pdd_ActSize   = %ld\n"
  718. ,IO->dr_U.dr_ReadFH.drrd_Size,Dev->pdd_ActReadIO,Dev->pdd_ActSize) );
  719.  
  720.               if(Dev->pdd_ActReadIO) {
  721.                 IO->dr_U.dr_ReadFH.drrd_ResSize=0;
  722.                 pOS_ListAddTail(&Dev->pdd_RdList,&IO->dr_Message.mn_Node);
  723.                 IO=NULL;
  724.               }
  725.               else {
  726. #define t_RD IO->dr_U.dr_ReadFH
  727.                 IO->dr_U.dr_ReadFH.drrd_ResSize=
  728.                          MIN(Dev->pdd_ActSize,IO->dr_U.dr_ReadFH.drrd_Size);
  729.                 memcpy(t_RD.drrd_Adr,Dev->pdd_Buffer,IO->dr_U.dr_ReadFH.drrd_ResSize);
  730.                 if(Dev->pdd_ActSize>IO->dr_U.dr_ReadFH.drrd_ResSize) {
  731.                   memmove(Dev->pdd_Buffer,
  732.                           &Dev->pdd_Buffer[IO->dr_U.dr_ReadFH.drrd_ResSize],
  733.                           Dev->pdd_ActSize-IO->dr_U.dr_ReadFH.drrd_ResSize);
  734.                 }
  735.                 Dev->pdd_ActSize-=IO->dr_U.dr_ReadFH.drrd_ResSize;
  736.  
  737.                 /** if(IO->dr_U.dr_ReadFH.drrd_ResSize<IO->dr_U.dr_ReadFH.drrd_Size) **/
  738.  
  739.                 if(IO->dr_U.dr_ReadFH.drrd_ResSize==0)
  740.                 {
  741.                   Dev->pdd_ActReadIO=IO;
  742.                   IO=NULL;
  743.                 }
  744. #undef t_RD
  745.               }
  746.               break;
  747.  
  748. /*\
  749. *** Das Anwenderprogramm ruft pOS_WriteFile() auf.
  750. *** Da der Port-Handler nur eine FileHandle unterstützt, darf der Write
  751. *** synchron erfolgen. Damit kein Konflikt mit einem parallel laufendem Read
  752. *** erfolgt, kommt beim Write ein eigener Ser-IO zum Einsatz.
  753. \*/
  754.             case DOSCMD_WriteFH:
  755. __WWW( kprintf(
  756. "DOSCMD_WriteFH\n"
  757. " drwd_Size = %ld\n"
  758. ,IO->dr_U.dr_WriteFH.drwd_Size) );
  759.  
  760.               Dev->pdd_WriteIO->io_Command=CMD_WRITE;
  761.               Dev->pdd_WriteIO->io_Data=(APTR)IO->dr_U.dr_WriteFH.drwd_Adr;
  762.               Dev->pdd_WriteIO->io_Length=IO->dr_U.dr_WriteFH.drwd_Size;
  763.               pOS_DoIO((pOS_IORequest*)Dev->pdd_WriteIO);
  764.               IO->dr_U.dr_WriteFH.drwd_ResSize=Dev->pdd_WriteIO->io_Actual;
  765.               if(Dev->pdd_WriteIO->io_Error)
  766.                    IO->dr_Error2=DOSERR_ReadWriteError;
  767.               break;
  768.  
  769.  
  770.             default: IO->dr_Error2=DOSERR_NotImplemented;
  771. __WWW( kprintf("UnknwonDos %ld\n",IO->dr_Command));
  772.           }
  773.  
  774.           if(IO) pOS_ReplyMsg(&IO->dr_Message);
  775.         }
  776.       }
  777.  
  778.       pOS_ReleaseSemaphore(&Dev->pdd_Sem);
  779.     }
  780.   }
  781.   else {
  782. __WWW( kprintf("HandlerFunc error-1\n") );
  783.   }
  784.  
  785.   CloseIODev(Dev,DevIsOpen);
  786.   pOS_DestructDosFH(&Dev->pdd_FH);
  787.  
  788. /*\
  789. *** Sämtliche MsgPorts, die mit pOS_ConstructMsgPort erzeugt wurden, müssen
  790. *** nicht freigeben werden, da sie keinen Speicherplatz belegen und das mp_SigBit
  791. *** wird autom. beim return() bzw. DeleteTask() freigegeben.
  792. \*/
  793.  
  794. __WWW( kprintf("HandlerFunc end\n") );
  795.  
  796.   Dev->pdd_Task=NULL;
  797.   pOS_DeleteTask(ThisTask,ThisTask->tc_FriendTask,SIGF_Signal);
  798. }
  799.  
  800.  
  801.  
  802.  
  803.  
  804. /*----------------------------------
  805. -----------------------------------*/
  806. BOOL OpenDev(PortDosDevice* dev)
  807. {
  808.   const pOS_DosMountDevice *const MD=dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_Mount;
  809.  
  810.   if(MD->dmd_Type==DMDTYP_Pico && MD->dmd_U.dmd_Pico.dmpic_Startup) {
  811.     pOS_InitSemaphore(&dev->pdd_Sem);
  812.     pOS_SetSignal(0,SIGF_Signal); // *** Signal löschen
  813.     dev->pdd_Task=pOS_CreateTask(MD->dmd_Node.ln_Name,5,
  814.                             (APTR)HandlerFunc,4000,sizeof(pOS_Task),(ULONG)dev,NULL);
  815.     if(dev->pdd_Task) pOS_WaitSignal(SIGF_Signal);
  816.   }
  817.   return(dev->pdd_Task!=NULL);
  818. }
  819.  
  820.  
  821. /*----------------------------------
  822. -----------------------------------*/
  823. VOID CloseDev(PortDosDevice* dev)
  824. {
  825.   if(dev->pdd_Task) {
  826. /*\
  827. *** Der Port-Handler verwendet keine Volumen, dennoch wird hier aufgezeigt,
  828. *** wie am Ende ein Volume gelöscht werden muß.
  829. \*/
  830.     if(dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_ActVolume) {
  831.       pOS_CloseDOSVolume(dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_ActVolume);
  832.       dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_ActVolume=NULL;
  833.     }
  834.  
  835. /*\
  836. *** Dem Handler-Task wird die Ausstiegsmarke tc_FriendTask gesetzt und
  837. *** damit der Handler sofort aggieren kann, wird er durch ein Signal
  838. *** aufgeweckt. Um Fehler auszuschließen warten wir, bis der Handler seine
  839. *** Tätigkeit beendet hat.
  840. \*/
  841.     dev->pdd_Task->tc_FriendTask=pOS_FindTask(NULL);
  842.     pOS_SendSignal(dev->pdd_Task,1<<dev->pdd_UnitPort.mp_SigBit);
  843.     while(dev->pdd_Task) pOS_WaitSignal(SIGF_Signal);
  844.   }
  845. }
  846.  
  847.  
  848.