home *** CD-ROM | disk | FTP | other *** search
-
- /*******************************************************************
- $CRT 03 Jun 1996 : hb
-
- $AUT Holger Burkarth
- $DAT >>PortHd.c<< 15 Mar 1997 09:21:39 - (C) ProDAD
- *******************************************************************/
-
- //##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
-
- /***********************************************************
- pOS programing example - Copyright (C) 1995-97 proDAD
-
- This code was written as an easy to understand example,
- how to program pOS features. It is provided 'as-is',
- without any express or implied warranty.
-
- Permission is hereby granted to use, copy and modify
- this source code for any purpose, without fee, subject
- to the following conditions:
-
- (1) This notice may not be removed or altered from any
- source distribution.
-
- (2) Altered source versions must be plainly marked as
- such, and must not be misrepresented as being
- the original source code.
-
- (3) If only executable code is distributed, then the
- accompanying documentation have to state that
- "this software is based in part on examples of
- the pOS developer packet".
-
- (4) Permission for use of this code is granted only
- if the user accepts full responsibility for any
- undesirable consequences. proDAD accept NO LIABILITY
- for damages of any kind.
-
- ©proDAD
- ***********************************************************/
-
- /*\
- *** Mount:
- ***
- *** TYPE_PICO DDNAME="devs:PortHd.ddv"
- *** STARTUP="DEVICE=pserial.device UNIT=0 TYPE_SER"
- ***
- \*/
-
-
- #define __COMPUTER_AMIGA 1
- #define NOMYDEBUG
-
- #include "p:pExec/Types.h"
- #include "p:pExec/Memory.h"
- #include "p:pExec/Diagnos.h"
- #include "p:pExec/TstTags.h"
- #include "p:pDOS/ArgTags.h"
- #include "p:pDOS/DosErrors.h"
- #include "p:pDOS/DosDev.h"
- #include "p:pDOS/DosBase.h"
- #include "p:pDOS/Segment.h"
- #include "p:pExec/Sema.h"
- #include "p:pExec/Task.h"
- #include "p:pDOS/Files.h"
- #include "p:Device/Serial.h"
- #include "p:proto/pLibExt.h"
- #include "p:proto/pExec2.h"
- #include "p:proto/pDOS2.h"
- #include "p:proto/pList.h"
-
- #ifdef _____ME_____
- #include "grund/inc_string.h"
- #include "grund/inc_limits.h"
- #else
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include <string.h>
- #include <limits.h>
- #ifdef __cplusplus
- }
- #endif
- #endif
-
-
- #define __WWW(a) ;
- //#define __WWW(a) a;
-
-
-
- #define MAX(a,b) ( (a)>(b)?(a):(b) )
- #define MIN(a,b) ( (a)<(b)?(a):(b) )
-
- struct pOS_ExecBase *gb_ExecBase;
- struct pOS_ExecLibFunction *gb_ExecLib;
- struct pOS_DosBase *gb_DosBase;
-
-
-
- struct PortDosDevice
- {
- pOS_DosDevice pdd_Dev;
- pOS_Task *pdd_Task;
- pOS_Semaphore pdd_Sem;
- pOS_FileHandle pdd_FH;
- pOS_MsgPort pdd_UnitPort;
- pOS_MsgPort pdd_ReadPort;
- pOS_MsgPort pdd_WritePort;
- pOS_IOStdReq *pdd_ReadIO;
- pOS_IOStdReq *pdd_WriteIO;
- pOS_ExList pdd_RdList;
- pOS_DosIOReq *pdd_ActReadIO;
-
- UBYTE *pdd_Buffer;
- size_t pdd_BufSize;
- size_t pdd_ActSize;
- UBYTE pdd_FhIsOpen; /* Boolean */
- UBYTE pdd_SerMode; /* Boolean */
-
- CHAR pdd_StdControlString[8];
- };
-
- /*\
- *** Allgemeines:
- *** In der pdd_RdList-Liste werden alle Read-IOs eingereiht, die nicht sofort
- *** bearbeitet werden können. Der aktuelle ReadIO wird in pdd_ReadIO vermerkt.
- *** Der pdd_ReadIO befindet sich in keiner Liste und kann somit sofort
- *** ge-replyed werden. Wogegen der Abort eines pdd_RdList-IOs ein pOS_Remove
- *** und dann ein pOS_ReplyMsg benötigt.
- ***
- \*/
-
- extern ULONG *FuncTable[];
- extern BOOL pDevMain(_R_LB pOS_ExecBase*,_R_A0 PortDosDevice*);
-
- const CHAR DeviceName[] ="PortHandler.ddv";
- const CHAR DeviceIDName[]="PortHandler.ddv 1.0 ("__DATE2__") (Created by Holger Burkarth)";
- const pOS_TagItem DeviceDescribe[]=
- {
- EXTSTTAG_MainOSID, pOS_MAINOSID,
- TAG_END
- };
-
-
-
- pOS_ResidentLibInit InitTable=
- {
- sizeof(PortDosDevice),
- FuncTable,
- NULL,
- (BOOL(*)(_R_LB pOS_ExecBase*,_R_A0 pOS_Library*))pDevMain
- };
-
-
-
- BOOL OpenDev(PortDosDevice* dev);
- VOID CloseDev(PortDosDevice* dev);
-
-
-
-
- /*----------------------------------
- -----------------------------------*/
- BOOL pDevMain(_R_LB pOS_ExecBase* exec,_R_A0 PortDosDevice* dev)
- {
- extern struct pOS_ExecBase *gb_ExecBase;
- extern struct pOS_ExecLibFunction *gb_ExecLib;
- extern struct pOS_DosBase *gb_DosBase;
-
- gb_ExecBase=(struct pOS_ExecBase*)exec;
-
- /* Pre-pOS-Trick */
- gb_ExecLib=*((struct pOS_ExecLibFunction**)dev->pdd_Dev.ddv_Dev.lib_Segm->sel_Seg.seg_Reserved2);
-
- gb_DosBase =(pOS_DosBase*)pOS_OpenLibrary("pDos.library",0);
-
- return( OpenDev(dev) );
- }
-
-
- /*----------------------------------
- -----------------------------------*/
- pOS_SegmentLst* Expunge_func(_R_LB PortDosDevice* dev)
- {
- if(dev->pdd_Dev.ddv_Dev.lib_OpenCnt==0) {
- pOS_SegmentLst* Seg=dev->pdd_Dev.ddv_Dev.lib_Segm;
-
- pOS_ListRemove(&dev->pdd_Dev.ddv_Dev.lib_Node);
- CloseDev(dev);
- pOS_CloseLibrary((struct pOS_Library*)gb_DosBase);
- _pOS_FreeLibraryMem2(&dev->pdd_Dev.ddv_Dev);
- return(Seg);
- }
- return(0);
- }
-
-
- /*----------------------------------
- -----------------------------------*/
- ULONG Reserved_func(_R_LB PortDosDevice*)
- { return(0); }
-
-
- /*----------------------------------
- -----------------------------------*/
- VOID AbortIO_func(_R_LB PortDosDevice* dev,_R_A0 pOS_DosIOReq* io)
- {
- /*\
- *** Ein IO kann jederzeit abgebrochen werden. Damit kein 'Speichersalat'
- *** durch mehrere Tasks in (PortDosDevice) entsteht, wird eine Semaphore
- *** über (PortDosDevice) aufgespannt.
- *** Der Abort ist eine sensible Funktion und wird leider sehr oft fehlerhaft
- *** implementiert.
- *** Zuerst wird geprüft, ob unser 'io' in der aktuelle ReadIO ist. In diesem
- *** Fall können wird den 'io' als aborted kennzeichnen und zurücksenden (reply).
- *** Obwohl der Reply-Port unser Port ist, müssen wir pOS_ReplyMsg verwenden,
- *** nur so wird das Standard-Device-Verhalten aufrechterhalten.
- *** Damit das Device weiterarbeiten kann, legen wir den nächsten ReadIO aus
- *** der Warteschlange nach. Ist kein IO in der Warteliste, dann liefert
- *** pOS_ListRemHead null und pdd_ActReadIO wird autom. genullt.
- *** War unser 'io' nicht der aktuelle ReadIO, so existieren 3 mögliche Zustände.
- *** 1. Der 'io' wurde bereits als vollendet oder ReadWrite-Error an den ReplyPort
- *** zurückgesendet. Da nach ReplyMsg der ln_Type immer auf NTYP_REPLYMSG steht
- *** kann dies einfach ermittelt werden. Aber Vorsicht, die Abfrage darf auf
- *** keinem Fall ln_Type!=NTYP_REPLYMSG lauten, da ln_Type noch weitere Zustände
- *** wiedergibt. Es ist aber sicher ln_Type==NTYP_MESSAGE zu prüfen, nach einem
- *** pOS_PutMsg ist ln_Type immer auf NTYP_MESSAGE gesetzt.
- *** 2. Der 'io' befindet sich noch im pdd_UnitPort und hatte noch keinen Kontakt
- *** mit dem Handler-Task.
- *** 3. Der 'io' wurde vom Handler in die pdd_RdList-Warteschlange eingereiht.
- *** Fall 2 und 3 sind für uns als Abort-er gleichbedeutend. Der 'io' befindet
- *** sich in einer Liste und muß von uns erst mittels pOS_ListRemove aus der
- *** selbigen entfernt werden, denn ein Node kann zur gleich Zeit nur einer
- *** Liste angehören.
- \*/
-
- __WWW( kprintf("AbortIO_func io=0x%lx\n",io) );
-
- pOS_ObtainSemaphore(&dev->pdd_Sem);
- if(io==dev->pdd_ActReadIO) {
- io->dr_Error2=DOSERR_Aborted;
- pOS_ReplyMsg(&io->dr_Message);
- dev->pdd_ActReadIO=(pOS_DosIOReq*)pOS_ListRemHead(&dev->pdd_RdList);
- }
- else if(io->dr_Message.mn_Node.ln_Type==NTYP_MESSAGE) {
- pOS_ListRemove(&io->dr_Message.mn_Node);
- io->dr_Error2=DOSERR_Aborted;
- pOS_ReplyMsg(&io->dr_Message);
- }
- pOS_ReleaseSemaphore(&dev->pdd_Sem);
- }
-
- /*----------------------------------
- -----------------------------------*/
- VOID BeginIO_func(_R_LB PortDosDevice* dev,_R_A0 pOS_DosIOReq* io)
- {
- /*\
- *** Der Handler-Task soll den 'io' bearbeiten. Wir reichen den 'io' nur weiter.
- \*/
- io->dr_Error2=DOSERR_None;
- io->dr_Flags &= ~IOREQF_Quick;
- __WWW( kprintf("BeginIO_func io=0x%lx\n",io) );
- pOS_PutMsg(&dev->pdd_UnitPort,&io->dr_Message);
- }
-
-
-
-
-
-
- ULONG *FuncTable[]=
- {
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Expunge_func,
- // ------------
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- // ------------
- (ULONG*)BeginIO_func,
- (ULONG*)AbortIO_func,
- // ------------
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- (ULONG*)Reserved_func,
- // ------------
-
- (ULONG*)ULONG_MAX
- };
-
- /***********************************************************************/
-
- /*----------------------------------
- -----------------------------------*/
- VOID CloseIODev(PortDosDevice* Dev,BOOL DevIsOpen)
- {
- if(DevIsOpen) {
- /*\
- *** Damit ein noch laufender Ser-IO uns nicht 'abschießt', wird sichergestellt,
- *** daß alle IOs ihre Tätigkeit beendet haben.
- *** Die pOS_Funktion pOS_CheckIO prüft, ob der IO bereits fertig ist. Läuft
- *** der IO noch, wir er mittels AbortIO abgebrochen. Um alle Probleme im
- *** Keim zu ersticken folgt pOS_WaitIO.
- \*/
- if(!pOS_CheckIO((pOS_IORequest*)Dev->pdd_ReadIO))
- pOS_AbortIO((pOS_IORequest*)Dev->pdd_ReadIO);
- if(!pOS_CheckIO((pOS_IORequest*)Dev->pdd_WriteIO))
- pOS_AbortIO((pOS_IORequest*)Dev->pdd_WriteIO);
-
- pOS_WaitIO((pOS_IORequest*)Dev->pdd_ReadIO);
- pOS_WaitIO((pOS_IORequest*)Dev->pdd_WriteIO);
- pOS_CloseDevice((pOS_IORequest*)Dev->pdd_ReadIO);
- }
- if(Dev->pdd_ReadIO) pOS_DeleteIORequest((pOS_IORequest*)Dev->pdd_ReadIO);
- if(Dev->pdd_WriteIO) pOS_DeleteIORequest((pOS_IORequest*)Dev->pdd_WriteIO);
- if(Dev->pdd_Buffer) pOS_FreeMem(Dev->pdd_Buffer,Dev->pdd_BufSize);
- Dev->pdd_ReadIO= Dev->pdd_WriteIO= NULL;
- Dev->pdd_Buffer=NULL;
- }
-
- /*----------------------------------
- -----------------------------------*/
- BOOL OpenIODev(PortDosDevice* Dev)
- {
- pOS_DosArgs* Args;
- const pOS_DosMountDevice *const MD=Dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_Mount;
- ULONG Ops[5]={0,0,0,1024,(ULONG)"9600/8N1N"};
- BOOL DevIsOpen=FALSE;
-
- __WWW( kprintf("OpenIODev\n") );
-
- /*\
- *** Mount-Startup mittels der ReadArgs parsen. pOS_ReadDosArgs benötigt nicht
- *** unbedingt einen pOS_Process.
- *** Damit kein Speicherplatz unnötig verschwendet wird, werden die Args sofort
- *** wieder freigegeben. Beachte, daß nach pOS_DeleteDosArgs alle eventuellen
- *** Strings freigegeben werden.
- \*/
- if(Args=pOS_ReadDosArgs(
- // 0 1 2 3 4
- "DEVICE/A, UNIT/N, TYPE_SER/S, BUFFERS/N/K, CONTROL/K",
- Ops,sizeof(Ops)/sizeof(ULONG),
- ARGTAG_Arguments, (ULONG)MD->dmd_U.dmd_Pico.dmpic_Startup,
- TAG_DONE))
- {
- Dev->pdd_BufSize=*((ULONG*)Ops[3]);
- if(Dev->pdd_BufSize<512) Dev->pdd_BufSize=512;
- Dev->pdd_Buffer=(UBYTE*)pOS_AllocMem(Dev->pdd_BufSize,MEMF_PUBLIC);
-
- strncpy(Dev->pdd_StdControlString,(CHAR*)Ops[4],sizeof(Dev->pdd_StdControlString)-1);
-
- if(Dev->pdd_Buffer && Ops[2]) {
- Dev->pdd_SerMode=TRUE;
- Dev->pdd_ReadIO=(pOS_IOStdReq*)
- pOS_CreateIORequest(&Dev->pdd_ReadPort,sizeof(pOS_SerialIO));
- Dev->pdd_WriteIO=(pOS_IOStdReq*)
- pOS_CreateIORequest(&Dev->pdd_WritePort,sizeof(pOS_SerialIO));
- }
-
- if(Dev->pdd_ReadIO && Dev->pdd_WriteIO) {
- pOS_OpenDevice((CHAR*)Ops[0],*((ULONG*)Ops[1]),(pOS_IORequest*)Dev->pdd_ReadIO,0,0);
- if(Dev->pdd_ReadIO->io_Error==0) {
- *Dev->pdd_WriteIO = *Dev->pdd_ReadIO;
- Dev->pdd_WriteIO->io_Message.mn_ReplyPort=&Dev->pdd_WritePort;
- DevIsOpen=TRUE;
- __WWW( kprintf("OpenIODev ok\n") );
- }
- else {
- __WWW( kprintf("OpenIODev Device-Error %ld\n",Dev->pdd_ReadIO->io_Error) );
- }
- }
- pOS_DeleteDosArgs(Args); /* Args freigeben */
- }
- else {
- __WWW( kprintf("OpenIODev Args-Error |%s|\n",MD->dmd_U.dmd_Pico.dmpic_Startup) );
- }
- return(DevIsOpen);
- }
-
-
-
-
-
- /*----------------------------------
- -----------------------------------*/
- BOOL SetParam(PortDosDevice* Dev,const CHAR* name)
- {
- pOS_DosArgs* Args;
- ULONG Ops[2]={9600,(ULONG)"8N1N"};
- BOOL Result=FALSE;
-
- if(Dev->pdd_SerMode) {
- if(Args=pOS_ReadDosArgs(
- // 0 1
- "BAUD/N, MODE",
- Ops,sizeof(Ops)/sizeof(ULONG),
- ARGTAG_Arguments, (ULONG) (name ? name:Dev->pdd_StdControlString),
- ARGTAG_Seperator, (ULONG)'/',
- TAG_DONE))
- {
- pOS_SerialIO *const IO=(pOS_SerialIO*)Dev->pdd_ReadIO;
- const CHAR *const Control=(CHAR*)Ops[1];
- const size_t ControlLen=strlen(Control);
-
- IO->sio_Baud = *((ULONG*)Ops[0]);
-
-
- __WWW( kprintf("SetParam-SER Baud=%ld Control=|%s|\n",IO->sio_Baud,Control) );
-
-
- if(Control[0]=='7') IO->sio_ReadLen = 7;
- else IO->sio_ReadLen = 8;
-
- switch(ControlLen>1 ? Control[1]:' ') {
- case 'O':
- case 'o':
- IO->sio_SerFlags |= SERF_XDisabled | SERF_PartyOdd | SERF_PartyOn;
- break;
-
- case 'E':
- case 'e':
- IO->sio_SerFlags |= SERF_XDisabled | SERF_PartyOn;
- IO->sio_SerFlags &= ~SERF_PartyOdd;
- break;
-
- default:
- IO->sio_SerFlags |= SERF_XDisabled;
- IO->sio_SerFlags &= ~(SERF_PartyOn | SERF_PartyOdd);
- }
-
- if(ControlLen>2 && Control[2]=='2')
- IO->sio_StopBits = 2;
- else IO->sio_StopBits = 1;
-
-
- switch(ControlLen>3 ? Control[3]:' ') {
- case 'X':
- case 'x':
- IO->sio_SerFlags &= ~(SERF_XDisabled | SERF_7Wire);
- break;
-
- case 'R':
- case 'r':
- IO->sio_SerFlags |= (SERF_XDisabled | SERF_7Wire);
- break;
-
- default:
- IO->sio_SerFlags |= SERF_XDisabled;
- IO->sio_SerFlags &= ~SERF_7Wire;
- }
-
-
- IO->sio_WriteLen=IO->sio_ReadLen;
-
- IO->sio_Command=SERCMD_SetParams;
- if(0==pOS_DoIO((pOS_IORequest*)IO)) {
- Result=TRUE;
- }
-
- pOS_DeleteDosArgs(Args); /* Args freigeben */
- }
- }
- else Result=TRUE;
- return(Result);
- }
-
-
-
-
-
- /*----------------------------------
- -----------------------------------*/
- VOID AbortAllPendingIOs(PortDosDevice* Dev)
- {
- pOS_DosIOReq *IO;
-
- __WWW( kprintf("AbortAllPendingIOs\n") );
-
- while(IO=(pOS_DosIOReq*)pOS_ListRemHead(&Dev->pdd_RdList)) {
- IO->dr_Error2=DOSERR_Aborted;
- pOS_ReplyMsg(&IO->dr_Message);
- }
- if(IO=Dev->pdd_ActReadIO) {
- IO->dr_Error2=DOSERR_Aborted;
- pOS_ReplyMsg(&IO->dr_Message);
- }
- }
-
-
-
- /*----------------------------------
- -----------------------------------*/
- VOID HandlerFunc(VOID)
- {
- pOS_Task *const ThisTask=pOS_FindTask(NULL);
- PortDosDevice *const Dev=(PortDosDevice*)ThisTask->tc_UserData[0];
- BOOL DevIsOpen=FALSE;
- UBYTE ReadChar;
-
- __WWW( kprintf("HandlerFunc start\n") );
-
- pOS_ConstructMsgPort(&Dev->pdd_UnitPort);
- pOS_ConstructMsgPort(&Dev->pdd_ReadPort);
- pOS_ConstructMsgPort(&Dev->pdd_WritePort);
- pOS_ListInit(&Dev->pdd_RdList);
-
- /*\
- *** Standard-FileHandle vorbereiten. Da der Port-Handler immer nur ein File
- *** zur gleichen Zeit zuläßt, muß die FH nicht dynamisch Verwaltet werden.
- \*/
- pOS_ConstructDosFH(&Dev->pdd_FH,&Dev->pdd_Dev,0);
- Dev->pdd_FH.fh_Flags = FILEHDF_Interactive;
-
- if(1 /*OpenIODev(Dev)*/) {
- const ULONG WaitSig= (1<<Dev->pdd_UnitPort.mp_SigBit)
- | (1<<Dev->pdd_ReadPort.mp_SigBit) ;
-
- pOS_SendSignal(ThisTask->tc_FriendTask,SIGF_Signal); // *** OK
- ThisTask->tc_FriendTask=NULL;
-
- while(ThisTask->tc_FriendTask==NULL) {
- ULONG Sig;
- Sig=pOS_WaitSignal(WaitSig);
-
- /*\
- *** Der Zugriff auf (PortDosDevice) wird durch die pdd_Sem-Semaphore geschützt.
- *** Damit der Semaphore-Mechanismus nicht unnötige Systemzeit verschlingt, erfolgt
- *** der Lock/Unlock nur in der äußersten Schleife. Der Schutz ist nötig, da die
- *** Abort-Funktion ebenfalls auf die (PortDosDevice) zugreift.
- \*/
- pOS_ObtainSemaphore(&Dev->pdd_Sem);
-
-
- /*\
- *** IO-Read ist vollendet.
- \*/
- if(Sig & (1<<Dev->pdd_ReadPort.mp_SigBit)) {
- __WWW( kprintf("HandlerFunc ReadPort\n") );
- if(pOS_GetMsg(&Dev->pdd_ReadPort)) { /* WICHTIG, ReplyPort wird geleert */
- if(Dev->pdd_ReadIO->io_Error==0) {
-
- #define t_RD Dev->pdd_ActReadIO->dr_U.dr_ReadFH
-
- /*\
- *** Befindet sich ein ReadIO in der Bearbeitung, dann werden alle hereinkommenden
- *** Daten sofort dem IO zugewiesen. Ist der aktuelle IO fertigt, wird er Replyed
- *** und der nächste in der Warteschlange wird nachgelegt und wird so zum aktuellen.
- *** Gibt es keinen aktuellen ReadIO, dann werden alle Daten in den Lesepuffer
- *** geschrieben.
- \*/
- if(Dev->pdd_ActReadIO) {
- ((UBYTE*)t_RD.drrd_Adr)[t_RD.drrd_ResSize]=ReadChar;
- ++t_RD.drrd_ResSize;
- for(;;) {
- /**if(t_RD.drrd_ResSize == t_RD.drrd_Size) **/
- if(t_RD.drrd_ResSize != 0)
- {
- pOS_ReplyMsg(&Dev->pdd_ActReadIO->dr_Message);
- Dev->pdd_ActReadIO=(pOS_DosIOReq*)pOS_ListRemHead(&Dev->pdd_RdList);
- }
- else if(Dev->pdd_SerMode) {
- Dev->pdd_ReadIO->io_Command=SERCMD_Query;
- pOS_DoIO((pOS_IORequest*)Dev->pdd_ReadIO);
- if(Dev->pdd_ReadIO->io_Actual>0) {
- size_t Size;
- Size=t_RD.drrd_Size-t_RD.drrd_ResSize;
- Size=MIN(Size,Dev->pdd_ReadIO->io_Actual);
- Dev->pdd_ReadIO->io_Command=CMD_READ;
- Dev->pdd_ReadIO->io_Length=Size;
- Dev->pdd_ReadIO->io_Data=(APTR) ((ULONG)t_RD.drrd_Adr + t_RD.drrd_ResSize);
- pOS_DoIO((pOS_IORequest*)Dev->pdd_ReadIO);
- t_RD.drrd_ResSize+=Size;
- continue;
- }
- }
- break;
- }
- }
- else if(Dev->pdd_ActSize<Dev->pdd_BufSize) {
- Dev->pdd_Buffer[ Dev->pdd_ActSize++ ] = ReadChar;
- }
- #undef t_RD
- }
-
- /*\
- *** Lesefehler vom Ser-Device. Der aktuelle ReadIO wird mit gesetztem Error
- *** abgebrochen.
- \*/
- else {
- __WWW( kprintf("Read-Error %ld\n",Dev->pdd_ReadIO->io_Error) );
-
- if(Dev->pdd_ActReadIO) {
- if(Dev->pdd_ReadIO->io_Error==SERIOERR_DetectedBreak) {
- Dev->pdd_ActReadIO->dr_Error2=0;
- Dev->pdd_ActReadIO->dr_U.dr_ReadFH.drrd_ResSize=0;
- }
- else {
- Dev->pdd_ActReadIO->dr_Error2=DOSERR_ReadWriteError;
- }
- pOS_ReplyMsg(&Dev->pdd_ActReadIO->dr_Message);
- Dev->pdd_ActReadIO=(pOS_DosIOReq*)pOS_ListRemHead(&Dev->pdd_RdList);
- }
- }
-
- /*\
- *** Ser-Device wieder starten, damit das nächste Byte gelesen werden kann.
- \*/
- Dev->pdd_ReadIO->io_Command=CMD_READ;
- Dev->pdd_ReadIO->io_Length=1;
- Dev->pdd_ReadIO->io_Data=(APTR)&ReadChar;
- pOS_SendIO((pOS_IORequest*)Dev->pdd_ReadIO);
- }
- }
-
- /*\
- *** Von Dos kommende Msg.
- \*/
- if(Sig & (1<<Dev->pdd_UnitPort.mp_SigBit)) {
- pOS_DosIOReq *IO;
-
- __WWW( kprintf("HandlerFunc UnitPort\n") );
-
- while(IO=(pOS_DosIOReq*)pOS_GetMsg(&Dev->pdd_UnitPort)) {
- switch(IO->dr_Command) {
-
- /*\
- *** Ein Anwenderprogramm hat pOS_OpenFile aufgerufen. Der Port-Handler unterstützt
- *** nur ein FH zur gleichen Zeit und frägt dies mittels pdd_FhIsOpen ab.
- *** Damit kein falscher Dateipfad entstehen kann, werden nur absolute Pfade
- *** (IO->dr_U.dr_OpenFH.drop_CurrLock==NULL) zugelassen.
- *** [absoluter Pfad => a:xxx oder con: oder par:]
- *** Konnten alle Resourcen alloziert werden, wird das Ser-Device gestartet.
- \*/
- case DOSCMD_OpenFH:
- __WWW( kprintf(
- "DOSCMD_OpenFH<%lx> \n"
- " pdd_FhIsOpen = %ld\n"
- " drop_Name =0x%lx\n"
- " drop_CurrDir =0x%lx\n"
- ,IO,Dev->pdd_FhIsOpen,IO->dr_U.dr_OpenFH.drop_Name
- ,IO->dr_U.dr_OpenFH.drop_CurrLock) );
-
- if(Dev->pdd_FhIsOpen==0) {
- if( IO->dr_U.dr_OpenFH.drop_Name!=NULL
- && IO->dr_U.dr_OpenFH.drop_CurrLock==NULL)
- {
- IO->dr_U.dr_OpenFH.drop_ResFH=&Dev->pdd_FH;
- Dev->pdd_FH.fh_Size=0; Dev->pdd_FH.fh_Pos=0;
- Dev->pdd_FH.fh_Access=IO->dr_U.dr_OpenFH.drop_Mode & FILEHDMOD_AcMsk;
- if( (DevIsOpen=OpenIODev(Dev))
- && SetParam(Dev,IO->dr_U.dr_OpenFH.drop_Name))
- {
- Dev->pdd_ActSize=0;
- Dev->pdd_ReadIO->io_Command=CMD_READ;
- Dev->pdd_ReadIO->io_Data=(APTR)&ReadChar;
- Dev->pdd_ReadIO->io_Length=1;
- __WWW( kprintf("Send-ReadIO\n") );
- pOS_SendIO((pOS_IORequest*)Dev->pdd_ReadIO);
-
- Dev->pdd_FhIsOpen=1;
- }
- else {
- CloseIODev(Dev,FALSE);
- IO->dr_Error2=DOSERR_ObjectNotFound;
- }
- }
- else IO->dr_Error2=DOSERR_WrongObjectType;
- }
- else IO->dr_Error2=DOSERR_ObjectExists;
- break;
-
-
- /*\
- *** Das Anwenderprogramm ruft pOS_CloseFile() auf.
- *** Alle noch ausstehende IOs (Read-Requests) werden abgebrochen.
- *** Eigentlich dürften bei Close nie IOs ausstehen, dennoch wird hier
- *** dieser Fall als Anschauungsbeispiel verwendet.
- \*/
- case DOSCMD_CloseFH:
- __WWW( kprintf("DOSCMD_CloseFH pdd_FhIsOpen=%ld\n",Dev->pdd_FhIsOpen) );
-
- if(Dev->pdd_FhIsOpen) {
- Dev->pdd_FhIsOpen=0;
- AbortAllPendingIOs(Dev);
- CloseIODev(Dev,DevIsOpen); DevIsOpen=FALSE;
- }
- else IO->dr_Error2=DOSERR_ObjectNotFound;
- break;
-
-
- /*\
- *** Das Anwenderprogramm ruft pOS_ReadFile() auf.
- *** Befindet sich bereits ein IO in der Bearbeitung, so wird der neue IO
- *** in die Warteschlange eingereiht.
- *** Ist kein ReadIO in der Bearbeitung, dann wird zuerst ein eventueller
- *** Datenstrom, der in der Zwischenzeit von pOS_OpenFile() bis pOS_ReadFile()
- *** eingegangen ist, dem IO zugeordnet. Konnte der IO vollständig bedient werden,
- *** wird er sofort ge-replyed. Ansonsten wird der IO zum aktuellen.
- \*/
- case DOSCMD_ReadFH:
- __WWW( kprintf(
- "DOSCMD_ReadFH\n"
- " drrd_Size = %ld\n"
- " pdd_ActReadIO = 0x%lx\n"
- " pdd_ActSize = %ld\n"
- ,IO->dr_U.dr_ReadFH.drrd_Size,Dev->pdd_ActReadIO,Dev->pdd_ActSize) );
-
- if(Dev->pdd_ActReadIO) {
- IO->dr_U.dr_ReadFH.drrd_ResSize=0;
- pOS_ListAddTail(&Dev->pdd_RdList,&IO->dr_Message.mn_Node);
- IO=NULL;
- }
- else {
- #define t_RD IO->dr_U.dr_ReadFH
- IO->dr_U.dr_ReadFH.drrd_ResSize=
- MIN(Dev->pdd_ActSize,IO->dr_U.dr_ReadFH.drrd_Size);
- memcpy(t_RD.drrd_Adr,Dev->pdd_Buffer,IO->dr_U.dr_ReadFH.drrd_ResSize);
- if(Dev->pdd_ActSize>IO->dr_U.dr_ReadFH.drrd_ResSize) {
- memmove(Dev->pdd_Buffer,
- &Dev->pdd_Buffer[IO->dr_U.dr_ReadFH.drrd_ResSize],
- Dev->pdd_ActSize-IO->dr_U.dr_ReadFH.drrd_ResSize);
- }
- Dev->pdd_ActSize-=IO->dr_U.dr_ReadFH.drrd_ResSize;
-
- /** if(IO->dr_U.dr_ReadFH.drrd_ResSize<IO->dr_U.dr_ReadFH.drrd_Size) **/
-
- if(IO->dr_U.dr_ReadFH.drrd_ResSize==0)
- {
- Dev->pdd_ActReadIO=IO;
- IO=NULL;
- }
- #undef t_RD
- }
- break;
-
- /*\
- *** Das Anwenderprogramm ruft pOS_WriteFile() auf.
- *** Da der Port-Handler nur eine FileHandle unterstützt, darf der Write
- *** synchron erfolgen. Damit kein Konflikt mit einem parallel laufendem Read
- *** erfolgt, kommt beim Write ein eigener Ser-IO zum Einsatz.
- \*/
- case DOSCMD_WriteFH:
- __WWW( kprintf(
- "DOSCMD_WriteFH\n"
- " drwd_Size = %ld\n"
- ,IO->dr_U.dr_WriteFH.drwd_Size) );
-
- Dev->pdd_WriteIO->io_Command=CMD_WRITE;
- Dev->pdd_WriteIO->io_Data=(APTR)IO->dr_U.dr_WriteFH.drwd_Adr;
- Dev->pdd_WriteIO->io_Length=IO->dr_U.dr_WriteFH.drwd_Size;
- pOS_DoIO((pOS_IORequest*)Dev->pdd_WriteIO);
- IO->dr_U.dr_WriteFH.drwd_ResSize=Dev->pdd_WriteIO->io_Actual;
- if(Dev->pdd_WriteIO->io_Error)
- IO->dr_Error2=DOSERR_ReadWriteError;
- break;
-
-
- default: IO->dr_Error2=DOSERR_NotImplemented;
- __WWW( kprintf("UnknwonDos %ld\n",IO->dr_Command));
- }
-
- if(IO) pOS_ReplyMsg(&IO->dr_Message);
- }
- }
-
- pOS_ReleaseSemaphore(&Dev->pdd_Sem);
- }
- }
- else {
- __WWW( kprintf("HandlerFunc error-1\n") );
- }
-
- CloseIODev(Dev,DevIsOpen);
- pOS_DestructDosFH(&Dev->pdd_FH);
-
- /*\
- *** Sämtliche MsgPorts, die mit pOS_ConstructMsgPort erzeugt wurden, müssen
- *** nicht freigeben werden, da sie keinen Speicherplatz belegen und das mp_SigBit
- *** wird autom. beim return() bzw. DeleteTask() freigegeben.
- \*/
-
- __WWW( kprintf("HandlerFunc end\n") );
-
- Dev->pdd_Task=NULL;
- pOS_DeleteTask(ThisTask,ThisTask->tc_FriendTask,SIGF_Signal);
- }
-
-
-
-
-
- /*----------------------------------
- -----------------------------------*/
- BOOL OpenDev(PortDosDevice* dev)
- {
- const pOS_DosMountDevice *const MD=dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_Mount;
-
- if(MD->dmd_Type==DMDTYP_Pico && MD->dmd_U.dmd_Pico.dmpic_Startup) {
- pOS_InitSemaphore(&dev->pdd_Sem);
- pOS_SetSignal(0,SIGF_Signal); // *** Signal löschen
- dev->pdd_Task=pOS_CreateTask(MD->dmd_Node.ln_Name,5,
- (APTR)HandlerFunc,4000,sizeof(pOS_Task),(ULONG)dev,NULL);
- if(dev->pdd_Task) pOS_WaitSignal(SIGF_Signal);
- }
- return(dev->pdd_Task!=NULL);
- }
-
-
- /*----------------------------------
- -----------------------------------*/
- VOID CloseDev(PortDosDevice* dev)
- {
- if(dev->pdd_Task) {
- /*\
- *** Der Port-Handler verwendet keine Volumen, dennoch wird hier aufgezeigt,
- *** wie am Ende ein Volume gelöscht werden muß.
- \*/
- if(dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_ActVolume) {
- pOS_CloseDOSVolume(dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_ActVolume);
- dev->pdd_Dev.ddv_U.ddv_Handler.ddvh_ActVolume=NULL;
- }
-
- /*\
- *** Dem Handler-Task wird die Ausstiegsmarke tc_FriendTask gesetzt und
- *** damit der Handler sofort aggieren kann, wird er durch ein Signal
- *** aufgeweckt. Um Fehler auszuschließen warten wir, bis der Handler seine
- *** Tätigkeit beendet hat.
- \*/
- dev->pdd_Task->tc_FriendTask=pOS_FindTask(NULL);
- pOS_SendSignal(dev->pdd_Task,1<<dev->pdd_UnitPort.mp_SigBit);
- while(dev->pdd_Task) pOS_WaitSignal(SIGF_Signal);
- }
- }
-
-
-