home *** CD-ROM | disk | FTP | other *** search
- /*
- * PLIP.device - Parallel Line Internet Protocol
- *
- * A SANA2 networking device driver for two Amigas connected via their
- * parallel ports.
- *
- * By Oliver Wagner with a little assistance of Michael Balzer.
- * Copyright (c) 1993-1994 Oliver Wagner and Michael Balzer.
- *
- */
-
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/cia.h>
- #include <proto/misc.h>
- #include <proto/utility.h>
- #include <proto/timer.h>
- #include <devices/sana2.h>
- #include <hardware/cia.h>
- #include <resources/misc.h>
- #include <exec/memory.h>
- #include <dos/dostags.h>
- #include <string.h>
-
- #define min __builtin_min
- #define max __builtin_max
- #define abs __builtin_abs
-
- #define SERVER_TASK "PLIP Server Task"
-
- #define PLIP_MTU 8192
- #define PLIP_DEFMTU 1024
- #define PLIP_BPS 15000
- #define PLIP_HWTYPE 13
- #define PLIP_RETRIES 63
-
- LONG plip_bps = PLIP_BPS;
- LONG plip_mtu = PLIP_DEFMTU;
- LONG plip_retries = PLIP_RETRIES;
-
- #define ios2_Error ios2_Req.io_Error
- #define ios2_Flags ios2_Req.io_Flags
-
- #define PKTFRAMESIZE 8
-
- struct intdata {
- /*0*/ USHORT mode,pad1;
- /*4*/ ULONG recsig; /* signals for receive */
- /*8*/ struct Task *sigtask; /* device task to signal */
- /*12*/ struct ExecBase *SysBase; /* local sysbase copy for interrupt */
- };
-
- struct sendframe {
- long sync;
- short size;
- unsigned short crc;
- long pkt;
- unsigned char data[PLIP_MTU];
- } sendframe, receiveframe;
-
- #define SYNCBYTE 0x42
-
- struct trackrec {
- struct MinNode n;
- ULONG packettype;
- struct Sana2PacketTypeStats s2ps;
- };
-
- struct MyDev {
- struct Library l;
- UBYTE flags, pad;
- APTR seglist;
- };
-
- struct BufRoutines {
- long __asm (*CopyToBuff)(register __a0 void*,register __a1 void*,register __d0 long);
- long __asm (*CopyFromBuff)(register __a0 void*,register __a1 void*,register __d0 long);
- };
-
- extern far volatile struct CIA ciaa,ciab;
-
- __aligned struct Library *MiscBase, *CIAABase;
- struct Library *UtilityBase, *TimerBase;
- struct DosLibrary *DOSBase;
- struct ExecBase *SysBase;
-
- static __aligned struct intdata intdata;
- static __aligned struct Interrupt intstruc;
- static long allocflags;
- static struct MsgPort *serverport, *timerport;
- static __aligned struct Sana2DeviceStats devstats; /* device stats */
- static __aligned struct timerequest treq;
- static __aligned struct List readlist, writelist, eventlist, readorphanlist, tracklist;
- static __aligned struct SignalSemaphore eventlistsem, writelistsem, tracklistsem;
-
- #define FLG_CLIENT 1 /* client mode */
- #define FLG_EXCLUSIVE 2 /* current opener is exclusive */
- #define FLG_NOTCONFIGURED 4 /* not configured */
- #define FLG_OFFLINE 8
- #define ISOFFLINE (devflags & (FLG_OFFLINE | FLG_NOTCONFIGURED))
- static long devflags = FLG_NOTCONFIGURED; /* current flags */
-
- #define IM_CLIENT 1 /* client mode */
- #define IM_SEND 2 /* sending pkt */
- #define IM_REC 4 /* receiving */
- #define IM_GETHEADER 8 /* got 1 char */
- #define IM_BUFF2 16 /* just filled second buffer */
- #define IM_RXERROR 32 /* receive error */
- #define IM_GOTSYNC 64
-
- extern void intcode(void);
- extern void __asm settimeout(register __d0 ULONG timeout);
- extern void __asm parinit(register __d0 int);
- extern long __asm testbusy(void), testpout(void);
- extern void __asm setbusy(register __d0 long), setpout(register __d0 long);
-
- extern long __asm waitinputtoggle(void);
- extern void __asm setciaoutput(void);
- extern void __asm outputtoggle(void);
- extern void __asm sampleinput(void);
-
- extern USHORT __asm CRC16( register __a0 UBYTE *, register __d0 SHORT );
-
- /***********************************************************
- * TRACKTYPE support
- */
-
- static struct trackrec * __inline findtracktype( ULONG type )
- {
- struct trackrec * tr = ( struct trackrec * ) tracklist.lh_Head;
-
- while( tr->n.mln_Succ )
- {
- if( tr->packettype == type )
- return( tr );
- tr = ( struct trackrec * ) tr->n.mln_Succ;
- }
-
- return( NULL );
- }
-
- static int addtracktype( ULONG type )
- {
- struct trackrec *tr;
-
- ObtainSemaphore( &tracklistsem );
- tr = findtracktype( type );
- if( tr )
- {
- ReleaseSemaphore( &tracklistsem );
- return( -1 );
- }
- else
- {
- tr = AllocMem( sizeof( *tr ), MEMF_CLEAR );
- if( !tr )
- {
- ReleaseSemaphore( &tracklistsem );
- return( -2 );
- }
- tr->packettype = type;
- AddTail( &tracklist, ( struct Node * ) tr );
- }
-
- ReleaseSemaphore( &tracklistsem );
- return( 0 );
- }
-
- static int remtracktype( ULONG type )
- {
- struct trackrec *tr;
-
- ObtainSemaphore( &tracklistsem );
-
- tr = findtracktype( type );
- if( tr )
- {
- Remove( ( struct Node * ) tr );
- FreeMem( tr, sizeof( *tr ) );
- ReleaseSemaphore( &tracklistsem );
- return( 0 );
- }
- ReleaseSemaphore( &tracklistsem );
- return( -1 );
- }
-
- static void __inline dotracktype( ULONG type, ULONG ps, ULONG pr, ULONG bs, ULONG br, ULONG pd )
- {
- struct trackrec * tr;
-
- ObtainSemaphoreShared( &tracklistsem );
- tr = findtracktype( type );
- if( tr )
- {
- tr->s2ps.PacketsSent += ps;
- tr->s2ps.PacketsReceived += pr;
- tr->s2ps.BytesSent += bs;
- tr->s2ps.BytesReceived += br;
- tr->s2ps.PacketsDropped += pd;
- }
- ReleaseSemaphore( &tracklistsem );
- }
-
- static int gettrackrec( ULONG type, APTR info )
- {
- struct trackrec * tr;
-
- ObtainSemaphoreShared( &tracklistsem );
- tr = findtracktype( type );
- if( tr )
- {
- memcpy( info, &tr->s2ps, sizeof( tr->s2ps ) );
- ReleaseSemaphore( &tracklistsem );
- return( 0 );
- }
- ReleaseSemaphore( &tracklistsem );
- return( -1 );
- }
-
- /***********************************************************
- * CIA Zugriff
- */
-
- static void __inline writecia( unsigned char val )
- {
- ciaa.ciaprb = val;
- }
-
- static unsigned char __inline readciabyte( void )
- {
- return( ciaa.ciaprb );
- }
-
-
- /***********************************************************
- * Event-Handling: Alle Event-Requests zurückschicken,
- * die auf das eingetretene Ereignis passen.
- */
-
- void DoEvent( long event )
- {
- struct IOSana2Req *ior, *ior2;
-
- ObtainSemaphore( &eventlistsem );
-
- for( ior = (struct IOSana2Req *) eventlist.lh_Head;
- ior2 = (struct IOSana2Req *) ior->ios2_Req.io_Message.mn_Node.ln_Succ;
- ior = ior2 )
- {
- if( ior->ios2_WireError & event )
- {
- Remove( ior );
- ReplyMsg( ior );
- }
- }
-
- ReleaseSemaphore( &eventlistsem );
- }
-
-
- /***********************************************************
- * Interrupt Support
- */
-
- static void __inline disableint( void )
- {
- AbleICR( CIAABase, CIAICRF_FLG );
- }
-
- static void __inline enableint( void )
- {
- AbleICR( CIAABase, CIAICRF_FLG | CIAICRF_SETCLR );
- }
-
-
- static long setupint( void )
- {
- MiscBase = OpenResource( "misc.resource" );
- CIAABase = OpenResource( "ciaa.resource" );
-
- /* Parallel-Port allokieren */
- if( AllocMiscResource( MR_PARALLELPORT, "plip.device" ) ) return 1;
- allocflags |= 1;
- if( AllocMiscResource( MR_PARALLELBITS, "plip.device" ) ) return 2;
- allocflags |= 2;
-
- intstruc.is_Node.ln_Type = NT_INTERRUPT;
- intstruc.is_Node.ln_Pri = 0;
- intstruc.is_Node.ln_Name = "PLIP PORTS Interrupt";
- intstruc.is_Data = &intdata;
- intstruc.is_Code = intcode;
-
- /* Interrupt einfügen */
- Disable();
- {
- /* Parallel-Port initialisieren */
- parinit( intdata.mode & IM_CLIENT );
-
- if( AddICRVector( CIAABase, CIAICRB_FLG, &intstruc ) )
- {
- Enable();
- return 3;
- }
-
- allocflags |= 4;
- }
- Enable();
-
- enableint();
-
- return 0;
- }
-
- static void cleanupint( void )
- {
- if( allocflags & 4 ) RemICRVector( CIAABase, CIAICRB_FLG, &intstruc );
- if( allocflags & 2 ) FreeMiscResource( MR_PARALLELBITS );
- if( allocflags & 1 ) FreeMiscResource( MR_PARALLELPORT );
- allocflags = 0;
- }
-
-
- /***********************************************************
- * WRITE
- *
- * Der Leser steuert über POUT (bzw. BUSY) die Übertragung.
- * Init: Schreiber schreibt Byte 1, was beim Leser einen Interrupt
- * auslöst. Der Leser quittiert den Empfang jedes Bytes mit einem Wechsel
- * der Handshake-Leitung, der Schreiber zeigt dem Leser durch Wechsel
- * der anderen Handshake-Leitung an, wenn ein Byte bereit steht.
- *
- * Um Deadlocks zu vermeiden (race condition) wird _einmal_ _vor_ der
- * Übertragung der Zustand des Handshakes eingelesen und dann immer
- * nur noch ohne vorherigen Lesezugriff auf den Wechsel gewartet.
- */
-
- /* Falls beim Warten auf die Lesebestätigung ein Timeout passiert: */
- #define ABORTWRITE { \
- DoEvent( S2EVENT_ERROR | S2EVENT_TX ); \
- intdata.mode &= ~IM_SEND; \
- parinit( intdata.mode & IM_CLIENT ); \
- enableint(); \
- return(-1); }
-
- static long procwrite( unsigned char *data, long size )
- {
- /* Init */
- disableint();
- setciaoutput();
-
- /* aktuellen Stand der Handshake-Leitung samplen */
- sampleinput();
-
- /* Übertragung anstoßen */
- writecia( *data++ );
-
- while( --size )
- {
- if( !waitinputtoggle() ) ABORTWRITE;
- writecia( *data++ );
- outputtoggle();
- }
-
- /* Bestätigung für letztes Byte abwarten */
- if( !waitinputtoggle() ) ABORTWRITE;
-
- /* Ok. */
- intdata.mode &= ~IM_SEND;
- parinit( intdata.mode & IM_CLIENT );
- enableint();
- devstats.PacketsSent++;
-
- return 0;
- }
-
-
- /***********************************************************
- * READ
- *
- * Wird vom Interrupt aus angestoßen.
- */
-
- /* Falls beim Warten auf das nächste Byte ein Timeout passiert: */
- #define ABORTREAD { \
- devstats.BadData++; \
- DoEvent( S2EVENT_ERROR | S2EVENT_RX ); \
- intdata.mode &= ~IM_REC; \
- parinit( intdata.mode & IM_CLIENT ); \
- enableint(); \
- return; }
-
- static void procread( void )
- {
- unsigned short crc;
- short len;
- int l;
- long bufferror,pkttyp;
-
- struct IOSana2Req *got, *ro;
- unsigned char *d, ch;
-
- /* Init */
- disableint();
- sampleinput();
-
- /* SYNC? */
- if( readciabyte() != 0x42 ) ABORTREAD;
-
- /* restliche SYNC-Bytes überlesen */
- for(;;)
- {
- outputtoggle();
- if( !waitinputtoggle() ) ABORTREAD;
-
- if( (ch = readciabyte()) != 0x42 )
- break;
- }
-
- /* Größe des Packets einlesen */
- d = (unsigned char *) &receiveframe.size;
- *d++ = ch;
- outputtoggle();
-
- if( !waitinputtoggle() ) ABORTREAD;
- *d++ = readciabyte();
- outputtoggle();
-
- /* Packetgröße sinnvoll? */
- len = receiveframe.size;
- if( len < 6 || len > plip_mtu+6 ) ABORTREAD;
-
- /* len Bytes einlesen */
- while( len-- )
- {
- if( !waitinputtoggle() ) ABORTREAD;
- *d++ = readciabyte();
- outputtoggle();
- }
-
- /* fertig mit Lesen */
- intdata.mode &= ~IM_REC;
-
- /* Exit */
- parinit( intdata.mode & IM_CLIENT );
- enableint();
-
- /* CRC check */
- pkttyp = receiveframe.pkt;
- l = receiveframe.size - 6;
- d = receiveframe.data;
-
- crc = CRC16( d, l );
-
- if( crc == receiveframe.crc )
- {
- /* CRC OK! */
-
- devstats.PacketsReceived++;
-
- dotracktype( pkttyp, 0, 1, 0, l, 0 );
-
- for( got = (struct IOSana2Req *) readlist.lh_Head;
- got && got->ios2_Req.io_Message.mn_Node.ln_Succ;
- got = (struct IOSana2Req *) got->ios2_Req.io_Message.mn_Node.ln_Succ )
- {
- if( got->ios2_PacketType == pkttyp )
- {
- /* Hurra, der will's haben! */
- Remove( got );
-
- /* Daten kopieren */
- bufferror = ((struct BufRoutines *) got->ios2_BufferManagement)
- -> CopyToBuff( got->ios2_Data, receiveframe.data, receiveframe.size - 6 );
-
- /* Fehler? */
- if( !bufferror )
- {
- got->ios2_Error = S2ERR_SOFTWARE;
- got->ios2_WireError = S2WERR_BUFF_ERROR;
- }
- else
- {
- got->ios2_Error = got->ios2_WireError = 0;
- }
-
- /* Request befriedigen */
- got->ios2_Flags = 0;
- got->ios2_SrcAddr[0] = (devflags & FLG_CLIENT) ? 0 : (1<<7);
- got->ios2_DstAddr[0] = (devflags & FLG_CLIENT) ? (1<<7) : 0 ;
- got->ios2_DataLength = receiveframe.size - 6;
- ReplyMsg( got );
-
- /* und 'raus */
- got=0;
- break;
- }
- }
- }
- else
- {
- /* CRC ERROR! */
-
- /* Clients Bescheid sagen, daß Müll ankam */
- DoEvent( S2EVENT_ERROR | S2EVENT_RX );
-
- got = 0;
- devstats.BadData++;
- }
-
- if( got )
- {
- /* Hm... wir haben ein Packet bekommen, das keiner haben will... */
- devstats.UnknownTypesReceived++;
-
- /* ...aber vielleicht ist da ja jemand, der genau solche Packets auffängt: */
- if( ro = (struct IOSana2Req *) RemHead( &readorphanlist ) )
- {
- /* Packet komplett kopieren */
- bufferror = ((struct BufRoutines *) ro->ios2_BufferManagement)
- -> CopyToBuff( ro->ios2_Data, &receiveframe.pkt, receiveframe.size - 2 );
-
- /* Fehler? */
- if( !bufferror )
- {
- ro->ios2_Error = S2ERR_SOFTWARE;
- ro->ios2_WireError = S2WERR_BUFF_ERROR;
- }
- else
- {
- ro->ios2_Error = ro->ios2_WireError = 0;
- }
-
- /* Request befriedigen */
- ro->ios2_Flags = 0;
- ro->ios2_SrcAddr[0] = (devflags & FLG_CLIENT) ? 0 : (1<<7);
- ro->ios2_DstAddr[0] = (devflags & FLG_CLIENT) ? (1<<7) : 0 ;
- ro->ios2_DataLength = receiveframe.size - 2;
- ReplyMsg( ro );
- }
-
- /* Noe, also entsorgen */
- dotracktype( pkttyp, 0, 0, 0, 0, 1 );
-
- }
-
- }
-
- /***********************************************************
- * READARGS - reads ENV:PLIP
- */
-
- static void __saveds readargs( void )
- {
- struct RDArgs *rda;
- struct args {
- ULONG *timeout;
- LONG *priority;
- ULONG *mtu;
- ULONG *bps;
- ULONG *retries;
- } args = { 0 };
- BPTR plipvar = Open( "ENV:SANA2/PLIP.config", MODE_OLDFILE );
- BPTR oldinput, infowin, oldoutput;
-
- infowin = Open( "con://320/128/PLIP V38.11/NOSIZE/INACTIVE", MODE_NEWFILE );
-
- if( infowin )
- {
- FPrintf( infowin,
- "\x1b[0 p\n"
- "\x1b[1mPLIP V38.11\x1b[0m (" __DATE__ " " __TIME__ ")\n"
- "by \x1b[3mOliver Wagner\x1b[0m & \x1b[3mMichael Balzer\x1b[0m\n"
- "Freeware -- see manual!\n\n" );
- }
-
- if( !plipvar )
- goto xit;
-
- oldinput = SelectInput( plipvar );
-
- rda = ReadArgs( "TIMEOUT/K/N,PRIORITY=PRI/K/N,MTU/K/N,BPS/K/N,RETRIES/K/N" , (LONG *)&args, NULL );
-
- if(rda)
- {
- if(args.timeout)
- {
- settimeout( *args.timeout );
- if( infowin ) FPrintf(infowin, " Timeout.: %lx/%ld\n", *args.timeout, *args.timeout);
- }
- if(args.priority)
- {
- SetTaskPri( FindTask(SERVER_TASK), *args.priority);
- if( infowin ) FPrintf(infowin, " Priority: %ld\n", *args.priority);
- }
- if( args.mtu )
- {
- if( *args.mtu <= PLIP_MTU )
- {
- plip_mtu = *args.mtu;
- if( infowin ) FPrintf(infowin, " MTU: %ld\n", *args.mtu);
- }
- }
- if( args.bps )
- {
- plip_bps = *args.bps;
- if( infowin ) FPrintf(infowin, " BPS: %ld\n", *args.bps);
- }
- if( args.retries )
- {
- if( *args.retries <= 127 )
- {
- plip_retries = *args.retries;
- if( infowin ) FPrintf(infowin, " Max Retries: %ld\n", *args.retries);
- }
- }
- FreeArgs( rda );
- }
- else if(infowin)
- {
- oldoutput = SelectOutput( infowin );
- PrintFault( IoErr(), "\x07 PLIP");
- SelectOutput( oldoutput );
- }
-
- Close( SelectInput( oldinput ));
-
- xit:
- /* Wake up Main server */
- Signal( intdata.sigtask, SIGBREAKF_CTRL_E );
-
- if( infowin )
- {
- Delay( 10*50 );
- Close( infowin );
- }
-
- }
-
-
-
- /***********************************************************
- * MAINLOOP - Device Dispatcher
- */
-
- static void __saveds servertask( void )
- {
- long portsig, s, timersig;
- struct IOSana2Req *currentwrite = 0, *got, *nextwrite;
- long timerqueued = 0, readstart = 0x42, bufferror;
-
- /*
- * Setup
- */
-
- s = AllocSignal( -1 );
- intdata.recsig = 1L << s;
-
- serverport = CreateMsgPort();
- timerport = CreateMsgPort();
- portsig = 1 << serverport->mp_SigBit;
- timersig = 1 << timerport->mp_SigBit;
-
- NewList( &readlist );
- NewList( &writelist );
- NewList( &eventlist );
- NewList( &readorphanlist );
- NewList( &tracklist );
-
- InitSemaphore( &eventlistsem );
- InitSemaphore( &writelistsem );
- InitSemaphore( &tracklistsem );
-
- treq.tr_node.io_Message.mn_ReplyPort = timerport;
- OpenDevice( "timer.device", UNIT_VBLANK, &treq, 0 );
- TimerBase = (struct Library *) treq.tr_node.io_Device;
- GetSysTime( &devstats.LastStart );
-
- CreateNewProcTags(
- NP_Entry, readargs,
- NP_Name, "PLIP Arg Parser Process",
- NP_Priority, 5,
- NP_WindowPtr, -1,
- TAG_DONE
- );
-
- /* Wait for reply from Arg Parser */
- Wait( SIGBREAKF_CTRL_E );
-
- for(;;)
- {
-
- /* Wir lassen uns regelmäßig vom timer.device aufwecken, damit
- * keine Senderequests liegen bleiben, wenn wir nicht sofort
- * die Leitung bekommen können
- */
- if( !timerqueued )
- {
- treq.tr_time.tv_secs = 2 + (devflags & FLG_CLIENT);
- treq.tr_time.tv_micro = 0;
- treq.tr_node.io_Command = TR_ADDREQUEST;
- SendIO( &treq );
- timerqueued = 1;
- }
-
- s = Wait( intdata.recsig | portsig | timersig );
-
- if( s & intdata.recsig )
- {
- /* Interrupt: Packet empfangen */
- procread();
- }
-
- if( s & timersig )
- {
- /* Aufwecksignal */
- AbortIO( &treq );
- WaitIO( &treq );
- timerqueued = 0;
- }
-
- if( s & portsig )
- {
- /* Kommandos (Requests) entgegennehmen */
-
- while( got = (struct IOSana2Req *) GetMsg( serverport ) )
- {
-
- if( got->ios2_Req.io_Command == CMD_READ )
- AddTail( &readlist, got );
- else if( got->ios2_Req.io_Command == S2_READORPHAN )
- AddTail( &readorphanlist, got );
- else
- {
- ObtainSemaphore( &writelistsem );
- AddTail( &writelist, got );
- ReleaseSemaphore( &writelistsem );
- }
- }
- }
-
- /*
- * So, Signale alle erledigt; haben wir 'was zu schreiben?
- */
-
- ObtainSemaphore( &writelistsem );
-
- for( currentwrite = (struct IOSana2Req *) writelist.lh_Head;
- nextwrite = (struct IOSana2Req *) currentwrite->ios2_Req.io_Message.mn_Node.ln_Succ;
- currentwrite = nextwrite )
- {
-
- /* Inzwischen ein Read-Interrupt? */
- if( SetSignal(0,0) & intdata.recsig) break;
-
- /* Arbitration */
- if( devflags & FLG_CLIENT )
- {
- /* Leitung frei? */
- if( !testbusy() )
- break; /* später nochmal versuchen */
-
- /* Sende-Status setzen */
- setpout( 1 );
-
- /* Leitung immer noch frei? */
- if( !testbusy() )
- {
- setpout( 0 );
- break; /* später nochmal versuchen */
- }
- }
- else
- {
- /* Leitung frei? */
- if( testpout() )
- break; /* später nochmal versuchen */
-
- /* Sende-Status setzen */
- setbusy( 0 );
-
- /* Leitung immer noch frei? */
- if( testpout() )
- {
- /*setbusy( 1 );*/
- break; /* später nochmal versuchen */
- }
- }
-
- /* Gut, wir können beginnen zu senden */
-
- /* Daten kopieren */
- bufferror = ((struct BufRoutines *) currentwrite->ios2_BufferManagement)
- -> CopyFromBuff( sendframe.data, currentwrite->ios2_Data, currentwrite->ios2_DataLength );
-
- /* Fehler? */
- if( !bufferror )
- {
- currentwrite->ios2_Error = S2ERR_SOFTWARE;
- currentwrite->ios2_WireError = S2WERR_BUFF_ERROR;
- Remove( currentwrite );
- ReplyMsg( currentwrite );
- continue;
- /* weiter mit nächstem Write-Req */
- }
-
- /* Packet-Header füllen */
- sendframe.sync = 0x42424242;
- sendframe.pkt = currentwrite->ios2_PacketType;
- sendframe.size = currentwrite->ios2_DataLength + 6;
-
- /* CRC berechnen und einsetzen */
- {
- int l = currentwrite->ios2_DataLength;
- unsigned char *d = sendframe.data;
- unsigned short crc = 0;
-
- crc = CRC16( d, l );
-
- sendframe.crc = crc;
- }
-
- /* Packet Senden */
-
- readstart = procwrite( (char *) &sendframe, sendframe.size + 6 );
-
- if( !readstart )
- {
- /* Packet erfolgreich gesendet */
- dotracktype( sendframe.pkt, 1, 0, currentwrite->ios2_DataLength, 0, 0 );
- currentwrite->ios2_Error = currentwrite->ios2_WireError = 0;
- Remove( currentwrite );
- ReplyMsg( currentwrite );
- }
- else
- {
- /* Fehler; WriteRetryCounter erhöhen */
- if( ( currentwrite->ios2_Error++ ) > plip_retries )
- {
- /* Maximale Fehleranzahl erreicht */
- currentwrite->ios2_Error = S2ERR_BAD_STATE;
- currentwrite->ios2_WireError = S2WERR_GENERIC_ERROR;
- Remove( currentwrite );
- ReplyMsg( currentwrite );
- }
- break;
- }
- }
-
- ReleaseSemaphore( &writelistsem );
-
- /* Alle Signale bearbeitet */
- }
- }
-
-
- /************************************************************
- * DEVICE-Management und -Support
- */
-
- long __asm __saveds DevOpen( register __a1 struct IOSana2Req *ior,
- register __d0 long unit, register __d1 long flags,
- register __a6 struct MyDev *devnode )
- {
- struct TagItem *ti;
- struct BufRoutines *br;
-
- devnode->l.lib_OpenCnt++; /* Expunge-Schutz */
-
- if( unit < 0 || unit > 1 )
- {
- devnode->l.lib_OpenCnt--;
- ior->ios2_Req.io_Error = -1;
- ior->ios2_Req.io_Device = (struct Device *) -1;
- return( -1 );
- /* openfailed */
- }
-
- /* already open? */
- if( devnode->l.lib_OpenCnt > 1 )
- {
- if( (unit && !(devflags & FLG_CLIENT)) ||
- (flags & SANA2OPF_MINE) )
- {
- /* busy/open */
- devnode->l.lib_OpenCnt--;
- ior->ios2_Req.io_Error = -1;
- ior->ios2_Req.io_Device = (struct Device *) -1;
- return( -1 );
- }
- }
-
- if( flags & SANA2OPF_MINE )
- devflags |= FLG_EXCLUSIVE;
-
- if( unit )
- {
- devflags |= FLG_CLIENT;
- intdata.mode |= IM_CLIENT;
- }
-
- intdata.SysBase=SysBase; /* Clone SysBase */
-
- /* Start Server Process */
- if( !intdata.sigtask )
- intdata.sigtask = CreateTask( SERVER_TASK, 15, servertask, 4000);
-
- if( !intdata.sigtask )
- {
- /* kein Task */
- devnode->l.lib_OpenCnt--;
- ior->ios2_Req.io_Error = -1;
- ior->ios2_Req.io_Device = (struct Device *) -1;
- return( -1 );
- }
-
- /* Task Setup Done; convert Taglist */
- br = AllocMem( 8, MEMF_CLEAR );
-
- if( ti = FindTagItem(S2_CopyToBuff, ior->ios2_BufferManagement) )
- br->CopyToBuff = ti->ti_Data;
-
- if( ti = FindTagItem(S2_CopyFromBuff, ior->ios2_BufferManagement) )
- br->CopyFromBuff = ti->ti_Data;
-
- if( !br->CopyToBuff || !br->CopyFromBuff )
- {
- FreeMem( br, 8 );
- devnode->l.lib_OpenCnt--;
- ior->ios2_Req.io_Error = -1;
- ior->ios2_Req.io_Device = (struct Device *) -1;
- return( -1 );
- }
-
- devnode->l.lib_Flags &= ~LIBF_DELEXP;
-
- ior->ios2_BufferManagement = br;
- ior->ios2_Req.io_Unit = (struct Unit *) br;
- ior->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
- ior->ios2_Req.io_Error = 0;
- return( 0 );
- }
-
-
- static long goonline( void )
- {
- long x;
-
- if( ISOFFLINE )
- {
- if( x = setupint() )
- return( -1 );
-
- devflags &= ~(FLG_OFFLINE | FLG_NOTCONFIGURED);
- }
-
- return( 0 );
- }
-
-
- static void gooffline( void )
- {
- if( ! (ISOFFLINE) )
- {
- cleanupint();
- devflags |= FLG_OFFLINE;
- }
- }
-
-
- long __asm __saveds DevExpunge( register __a6 struct MyDev *devnode )
- {
- long seglist;
- struct trackrec *trackrec;
-
- if( devnode->l.lib_OpenCnt )
- {
- devnode->l.lib_Flags |= LIBF_DELEXP;
- return( 0 );
- }
-
- gooffline();
-
- if( intdata.sigtask ) RemTask( intdata.sigtask );
-
- if( serverport ) FreeMem( serverport, sizeof(struct MsgPort) );
- if( timerport ) FreeMem( timerport, sizeof(struct MsgPort) );
-
- Remove( devnode );
- seglist = (long) devnode->seglist;
- FreeMem( ((char *) devnode) - devnode->l.lib_NegSize,
- devnode->l.lib_PosSize + devnode->l.lib_NegSize );
-
- /* Free tracktype records */
- while( ( trackrec = ( struct trackrec * ) RemHead( &tracklist ) ) )
- FreeMem( trackrec, sizeof( *trackrec ) );
-
- return( seglist );
- }
-
-
- long __asm __saveds DevClose( register __a1 struct IOSana2Req *ior,
- register __a6 struct MyDev *devnode )
- {
- FreeMem( ior->ios2_Req.io_Unit, 8 );
-
- ior->ios2_Req.io_Device = (struct Device *) -1;
- ior->ios2_Req.io_Unit = (struct Unit *) -1;
-
- if( !(--devnode->l.lib_OpenCnt) ) /* ERROR! */
- {
- devflags &= ~FLG_EXCLUSIVE;
- if( devnode->l.lib_Flags & LIBF_DELEXP )
- return( DevExpunge(devnode) );
- }
-
- return( 0 );
- }
-
-
- void __saveds __asm DevBeginIO( register __a1 struct IOSana2Req *ior )
- {
- struct Sana2DeviceQuery *devquery;
-
- ior->ios2_Error = IOERR_NOCMD;
-
- switch( ior->ios2_Req.io_Command )
- {
- case S2_GETSTATIONADDRESS:
- ior->ios2_SrcAddr[0] = ior->ios2_DstAddr[0] = (devflags & FLG_CLIENT) ? 1<<7 : 0;
- ior->ios2_Error = ior->ios2_WireError = 0;
- break;
-
- case S2_TRACKTYPE:
- if( addtracktype( ior->ios2_PacketType ) )
- {
- ior->ios2_Error = S2ERR_BAD_STATE;
- ior->ios2_WireError = S2WERR_ALREADY_TRACKED;
- }
- else
- ior->ios2_Error = ior->ios2_WireError = 0;
- break;
-
- case S2_UNTRACKTYPE:
- if( remtracktype( ior->ios2_PacketType ) )
- {
- ior->ios2_Error = S2ERR_BAD_STATE;
- ior->ios2_WireError = S2WERR_NOT_TRACKED;
- }
- else
- ior->ios2_Error = ior->ios2_WireError = 0;
- break;
-
-
- case S2_GETTYPESTATS:
- if( gettrackrec( ior->ios2_PacketType, ior->ios2_StatData ) )
- {
- ior->ios2_Error = S2ERR_BAD_STATE;
- ior->ios2_WireError = S2WERR_NOT_TRACKED;
- }
- else
- ior->ios2_Error = ior->ios2_WireError = 0;
- break;
-
- case S2_GETGLOBALSTATS:
- memcpy( ior->ios2_StatData, &devstats, sizeof(struct Sana2DeviceStats) );
- ior->ios2_Error = ior->ios2_WireError = 0;
- break;
-
- case S2_DEVICEQUERY:
- ior->ios2_Error = ior->ios2_WireError = 0;
- devquery = ior->ios2_StatData;
- devquery->DevQueryFormat = devquery->DeviceLevel = 0;
-
- if( devquery->SizeAvailable > 3 ) devquery->AddrFieldSize = 1;
- if( devquery->SizeAvailable > 5 ) devquery->MTU = plip_mtu;
- if( devquery->SizeAvailable > 9 ) devquery->BPS = plip_bps;
- if( devquery->SizeAvailable > 13 ) devquery->HardwareType = PLIP_HWTYPE;
-
- devquery->SizeSupplied = min( devquery->SizeAvailable, 18 );
- break;
-
- case S2_ONLINE:
- if( goonline() )
- ior->ios2_Error = S2ERR_NO_RESOURCES;
- else
- ior->ios2_Error = ior->ios2_WireError = 0;
- break;
-
- case S2_OFFLINE:
- gooffline();
- ior->ios2_Error = ior->ios2_WireError = 0;
- break;
-
- case S2_ONEVENT:
- ObtainSemaphore( &eventlistsem );
- AddTail( &eventlist, ior );
- ReleaseSemaphore( &eventlistsem );
- return;
-
- case CMD_READ:
- case S2_READORPHAN:
- if( ISOFFLINE )
- {
- ior->ios2_Error = S2ERR_OUTOFSERVICE;
- ior->ios2_WireError = S2WERR_UNIT_OFFLINE;
- break;
- }
-
- PutMsg( serverport, ior );
- return;
-
- case CMD_WRITE:
- case S2_BROADCAST:
- if( ISOFFLINE )
- {
- ior->ios2_Error = S2ERR_OUTOFSERVICE;
- ior->ios2_WireError = S2WERR_UNIT_OFFLINE;
- break;
- }
-
- if( ior->ios2_DataLength > plip_mtu )
- {
- ior->ios2_Error = S2ERR_MTU_EXCEEDED;
- ior->ios2_WireError = 0;
- break;
- }
-
- /* 38.10: ios2_Error wird als WriteRetryCounter benutzt */
-
- ior->ios2_Error = 0;
-
- PutMsg( serverport, ior );
- return;
-
- case S2_CONFIGINTERFACE:
- if( devflags & FLG_NOTCONFIGURED )
- {
- ior->ios2_SrcAddr[0] = (devflags & FLG_CLIENT) ? (1<<7) : 0;
-
- if( goonline() )
- {
- ior->ios2_Error = S2ERR_NO_RESOURCES;
- ior->ios2_WireError = 0;
- }
- else
- {
- ior->ios2_Error = ior->ios2_WireError = 0;
- }
-
- break;
- }
-
- ior->ios2_Error = S2ERR_SOFTWARE;
- ior->ios2_WireError = S2WERR_IS_CONFIGURED;
- break;
- }
-
- ior->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
- return;
- }
-
-
- static long isinlist( struct Node *n, struct List *l )
- {
- struct Node *cmp = l->lh_Head;
-
- while( cmp != n && cmp->ln_Succ )
- cmp = cmp->ln_Succ;
-
- return( cmp == n );
- }
-
-
- long __asm __saveds DevAbortIO( register __a1 struct IOSana2Req *ior )
- {
- Forbid();
-
- if( isinlist(ior, &eventlist) ||
- isinlist(ior, &readlist) ||
- isinlist(ior, &readorphanlist) )
- {
- Remove( ior );
- ior->ios2_Error = IOERR_ABORTED;
- ior->ios2_WireError = 0;
- ReplyMsg( ior );
- Permit();
- return( 0 );
- }
- else
- {
- ObtainSemaphore( &writelistsem );
-
- if( isinlist(ior, &writelist) )
- {
- Remove( ior );
- ReleaseSemaphore( &writelistsem );
-
- ior->ios2_Error = IOERR_ABORTED;
- ior->ios2_WireError = 0;
-
- ReplyMsg( ior );
- Permit();
- return( 0 );
- }
-
- ReleaseSemaphore( &writelistsem );
- }
-
- Permit();
-
- return( -1 );
- }
-
- /* EOF */
-