home *** CD-ROM | disk | FTP | other *** search
- /*
- ** $Source: HOG:Other/networking/sana2/src/slip/RCS/device_funcs.c,v $
- ** $State: Exp $
- ** $Revision: 37.5 $
- ** $Date: 92/12/16 13:45:22 $
- ** $Author: bj $
- **
- ** Amiga SANA-II Example SLIP device driver.
- **
- ** (C) Copyright 1992 Commodore-Amiga, Inc.
- **
- */
-
- #ifndef EOFMODE
- # define EOFMODE 1
- #endif
- #ifndef DEMANDREAD
- # define DEMANDREAD 1
- #endif
-
- #include "slip_device.h"
- #if DEBUG
- #include "syslog.h"
- #else
- #define debug(x)
- #endif
-
- #include <dos/dostags.h>
- #include <dos/rdargs.h>
- #include <intuition/intuition.h>
-
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/utility_protos.h>
- #include <clib/timer_protos.h>
- #include <clib/alib_stdio_protos.h>
- #include <clib/intuition_protos.h>
-
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/dos_pragmas.h>
- #include <pragmas/utility_pragmas.h>
- #include <pragmas/timer_pragmas.h>
- #include <pragmas/intuition_pragmas.h>
-
- #include <string.h>
- #include "device_protos.h"
-
- /*
- ** External variables and functions
- **
- */
-
- extern struct SLIPDevice *ExtDeviceBase;
- extern ULONG IPToNum(STRPTR ipstr);
- extern VOID kprintf(STRPTR fmt, ...);
-
- #if CSLIP
- const char SLIPName[] = "cslip.device";
- #else
- const char SLIPName[] = "slip.device";
- #endif
-
- /*
- ** Device Open vector
- **
- ** a1 - SANA2 IO Request
- ** a6 - Pointer to our device base
- ** d0 - Unit number
- ** d1 - Flags
- **
- */
-
- ULONG ASM DevOpen(REG(a1) struct IOSana2Req *ios2,
- REG(a6) struct SLIPDevice *SLIPDevice,
- REG(d0) ULONG s2unit,
- REG(d1) ULONG s2flags)
- {
- struct SLIPDevUnit *sdu;
- struct TagItem *bufftag;
- struct Library *UtilityBase;
- struct BufferManagement *bm;
- ULONG returncode;
- BOOL status = FALSE;
-
- /* Make sure our open remains single-threaded. */
- ObtainSemaphore(&SLIPDevice->sd_Lock); /* Enforce single threading since we may need to
- Wait() when starting up the Unit process */
-
- #if DEBUG
- initsyslog();
- #endif
- SLIPDevice->sd_Device.lib_OpenCnt++; /* So we won't expunge ourselves... */
-
- if(s2unit < SD_MAXUNITS) /* Legal Unit? */
- {
- if(sdu = InitSLIPUnit(s2unit)) /* Initialize the Unit */
- {
- if(UtilityBase = OpenLibrary("utility.library",37L)) /* For Tag functions */
- {
- /* Allocate a structure to store the pointers to the callback routines. */
-
- if(bm = AllocMem(sizeof(struct BufferManagement),MEMF_CLEAR|MEMF_PUBLIC))
- {
- /* Note: I don't complain if I can't find pointers to the callback routines.
- This is because there are some programs that may need to open me, but
- will never use any device commands that require the callbacks. */
-
- if(bufftag = FindTagItem(S2_CopyToBuff, (struct TagItem *)ios2->ios2_BufferManagement))
- {
- bm->bm_CopyToBuffer = (SANA2_CTB) bufftag->ti_Data;
- }
-
- if(bufftag = FindTagItem(S2_CopyFromBuff, (struct TagItem *)ios2->ios2_BufferManagement))
- {
- bm->bm_CopyFromBuffer = (SANA2_CFB) bufftag->ti_Data;
- }
-
- AddTail((struct List *)&sdu->sdu_BuffMgmt,(struct Node *)bm);
-
- /* Everything went okay. */
- status = TRUE;
- returncode = 0;
- SLIPDevice->sd_Device.lib_OpenCnt++;
- SLIPDevice->sd_Device.lib_Flags &=~LIBF_DELEXP;
- sdu->sdu_Unit.unit_OpenCnt++;
-
- /* Fix up the initial io request */
- ios2->ios2_BufferManagement = (VOID *)bm;
- ios2->ios2_Req.io_Error = 0;
- ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
- ios2->ios2_Req.io_Unit = sdu;
- ios2->ios2_Req.io_Device = SLIPDevice;
- }
- CloseLibrary(UtilityBase);
- }
- }
- }
- /* See if something went wrong. */
- if(!status)
- {
- ios2->ios2_Req.io_Error = IOERR_OPENFAIL;
- ios2->ios2_Req.io_Unit = (struct Unit *) -1;
- ios2->ios2_Req.io_Device = (struct Device *) -1;
- returncode = IOERR_OPENFAIL;
- }
- SLIPDevice->sd_Device.lib_OpenCnt--;
- ReleaseSemaphore(&SLIPDevice->sd_Lock);
-
- return(returncode);
- }
-
- /*
- ** Device Close vector.
- **
- ** a1 - IOReq
- ** a6 - Device Pointer
- **
- */
-
- BPTR ASM DevClose(REG(a1) struct IOSana2Req *ios2,
- REG(a6) struct SLIPDevice *SLIPDevice)
- {
- struct SLIPDevUnit *sdu;
- BPTR seglist = 0L;
-
- ObtainSemaphore(&SLIPDevice->sd_Lock);
-
- sdu = (struct SLIPDevUnit *)ios2->ios2_Req.io_Unit;
-
- /* Trash the io_Device and io_Unit fields so that any attempt to use this
- request will die immediatly. */
-
- ios2->ios2_Req.io_Device = (struct Device *) -1;
- ios2->ios2_Req.io_Unit = (struct Unit *) -1;
-
- /* I always shut the unit process down if the open count drops to zero.
- That way, if I need to expunge, I never have to Wait(). */
-
- sdu->sdu_Unit.unit_OpenCnt--;
- if(!sdu->sdu_Unit.unit_OpenCnt)
- {
- ExpungeUnit(sdu);
- }
-
- SLIPDevice->sd_Device.lib_OpenCnt--;
-
- ReleaseSemaphore(&SLIPDevice->sd_Lock);
-
- /* Check to see if we've been asked to expunge. */
- if(SLIPDevice->sd_Device.lib_Flags & LIBF_DELEXP)
- seglist = DevExpunge(SLIPDevice);
-
- return(seglist);
- }
-
-
- /*
- ** Device Expunge vector
- **
- ** a6 - Device base
- **
- ** Note: You may NEVER EVER Wait() in expunge. Period.
- ** Don't even *think* about it.
- */
-
- BPTR ASM DevExpunge(REG(a6) struct SLIPDevice *SLIPDevice)
- {
- BPTR seglist;
- ULONG devbase;
- LONG devbasesize;
-
- if(SLIPDevice->sd_Device.lib_OpenCnt)
- {
- /* Sorry, we're busy. We'll expunge later on
- if we can. */
- SLIPDevice->sd_Device.lib_Flags |= LIBF_DELEXP;
- seglist = (BPTR)0L;
- }
- else
- {
- /* Free up our library base and function table after
- removing ourselves from the library list. */
- Remove((struct Node *)SLIPDevice);
- seglist = SLIPDevice->sd_SegList;
-
- devbase = (ULONG) SLIPDevice;
-
- devbasesize = (ULONG)SLIPDevice->sd_Device.lib_NegSize;
- devbase = devbase - devbasesize;
-
- devbasesize += (ULONG)SLIPDevice->sd_Device.lib_PosSize;
-
- #if DEBUG
- uninitsyslog();
- #endif
- FreeMem((APTR)devbase,devbasesize);
- ExtDeviceBase = NULL;
- }
- return(seglist);
- }
-
- /*
- ** InitSLIPUnit
- **
- ** Initialize (if needed) a new SLIP device Unit and process.
- **
- */
-
- struct SLIPDevUnit *InitSLIPUnit(ULONG s2unit)
- {
- struct SLIPDevice *SLIPDevice = SLIPBase;
- struct SLIPDevUnit *sdu;
- struct TagItem NPTags[]={NP_Entry, 0, NP_Name, 0, NP_Priority, SLIP_PRI, TAG_DONE, 0};
- struct MsgPort *replyport;
-
- /* Check to see if the Unit is already up and running. If
- it is, just drop through. If not, try to start it up. */
-
- if(!SLIPDevice->sd_Units[s2unit])
- {
- /* Open up dos.library */
- if(SLIPDevice->sd_DOSBase = OpenLibrary("dos.library",37L))
- {
- /* Allocate a new Unit structure */
- if(sdu = AllocMem(sizeof(struct SLIPDevUnit), MEMF_CLEAR|MEMF_PUBLIC))
- {
- /* Do some initialization on the Unit structure */
-
- NewList(&sdu->sdu_Unit.unit_MsgPort.mp_MsgList);
- sdu->sdu_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
- sdu->sdu_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
- sdu->sdu_Unit.unit_MsgPort.mp_Node.ln_Name = (char *)SLIPName;
-
- sdu->sdu_UnitNum = s2unit;
- sdu->sdu_Device = (struct Device *) SLIPDevice;
-
- /* Try to read in our configuration file */
- if(ReadConfig(sdu))
- {
- /* Start up the unit process */
- if(replyport = CreateMsgPort())
- {
- SLIPDevice->sd_Startup.Msg.mn_ReplyPort = replyport;
- SLIPDevice->sd_Startup.Device = (struct Device *) SLIPDevice;
- SLIPDevice->sd_Startup.Unit = (struct Unit *)sdu;
-
- NPTags[0].ti_Data = (ULONG) &DevProcCEntry;
- NPTags[1].ti_Data = (ULONG) SLIPName; /* Process name */
- /* Rhialto: use opener's priority */
- NPTags[2].ti_Data = (ULONG) FindTask(NULL)->tc_Node.ln_Pri;
-
- /*ExtDeviceBase = (struct Library *)SLIPDevice;*/
-
- if(sdu->sdu_Proc = CreateNewProc(NPTags))
- {
- PutMsg(&sdu->sdu_Proc->pr_MsgPort,(struct Message *)&SLIPDevice->sd_Startup);
- WaitPort(replyport);
- GetMsg(replyport);
- }
- DeleteMsgPort(replyport);
- }
- }
-
- if(!sdu->sdu_Proc)
- {
- /* The Unit process couldn't start for some reason, so free the Unit structure. */
- FreeMem(sdu,sizeof(struct SLIPDevUnit));
- }
- else
- {
- /* Set up the Unit structure pointer in the device base */
- SLIPDevice->sd_Units[s2unit] = (struct Unit *)sdu;
- }
- }
- CloseLibrary(SLIPDevice->sd_DOSBase);
- }
- }
- return((struct SLIPDevUnit *)SLIPDevice->sd_Units[s2unit]);
- }
-
- /*
- **
- ** ExpungeUnit
- **
- ** Tells a unit process to go away...
- **
- ** This function is called from the DevClose routine when the open count for a
- ** unit reaches zero. This routine signals the unit process to exit and then
- ** waits for the unit process to acknowledge. The unit structure is then
- ** freed.
- */
-
- VOID ExpungeUnit(struct SLIPDevUnit *sdu)
- {
- struct SLIPDevice *SLIPDevice = SLIPBase;
- struct Task *unittask;
-
- unittask = (struct Task *)sdu->sdu_Proc;
-
- sdu->sdu_Proc = (struct Process *)FindTask(0L);
-
- Signal(unittask,SIGBREAKF_CTRL_F);
- Wait(SIGBREAKF_CTRL_F);
-
- SLIPDevice->sd_Units[sdu->sdu_UnitNum] = NULL;
-
- FreeMem(sdu, sizeof(struct SLIPDevUnit));
- }
-
- /*
- **
- ** ReadConfig
- **
- ** Attempt to read in and parse the driver's configuration file.
- **
- ** The files are named by ENV:SANA2/slipX.config where X is the decimal
- ** representation of the device's unit number.
- **
- */
-
- BOOL ReadConfig(struct SLIPDevUnit *sdu)
- {
- UBYTE *linebuff,buff[40];
- STRPTR termchar;
- struct RDArgs *rdargs;
- BPTR ConfigFile;
- LONG args[6];
- BOOL status = FALSE;
- ULONG linenum=0;
- UWORD i;
-
- /* Create the name of our config file.. */
- sprintf(buff,"ENV:SANA2/slip%ld.config",(ULONG)sdu->sdu_UnitNum);
-
- /* ...and open it. */
- if(ConfigFile = Open(buff,MODE_OLDFILE))
- {
- /* Here, I use ReadArgs() to do the file parsing for me. */
-
- if(linebuff = AllocMem(256,MEMF_CLEAR|MEMF_PUBLIC))
- {
- if(rdargs = AllocDosObject(DOS_RDARGS, NULL))
- {
- while(FGets(ConfigFile, linebuff, 255))
- {
- linenum++;
- if(linebuff[0] == '#') /* Skip comment lines */
- continue;
-
- rdargs->RDA_Source.CS_Buffer = linebuff;
- rdargs->RDA_Source.CS_Length = 256;
- rdargs->RDA_Source.CS_CurChr = 0;
-
- /* ReadArgs() requires that the line be null-terminated
- or funny things happen. */
-
- termchar = (STRPTR) linebuff + strlen(linebuff);
- *termchar = '\n';
- termchar++;
- *termchar = 0;
-
- for(i = 0; i< 6; i++)
- args[i]=0;
-
- /* Parse the line...*/
-
- if(ReadArgs("SERNAME/A,SERUNIT/A/N,SERBAUD/A/N,IPSTR/A,CD=CARRIERDETECT/S,7WIRE/S",args,rdargs))
- {
- strcpy(sdu->sdu_SerDevName,(STRPTR)args[0]);
- sdu->sdu_SerUnitNum = *((ULONG *)args[1]);
- sdu->sdu_BaudRate = *((ULONG *)args[2]);
- sdu->sdu_StAddr = /* Rhialto */
- sdu->sdu_HwAddr = IPToNum((STRPTR)args[3]);
-
- if(args[4])
- sdu->sdu_State |= SLIPUF_CD;
-
- if(args[5])
- sdu->sdu_State |= SLIPUF_7WIRE;
-
- status = TRUE;
- FreeArgs(rdargs);
- break;
- }
- else
- {
- struct Library *IntuitionBase;
- struct EasyStruct es;
- if(IntuitionBase = OpenLibrary("intuition.library",37L))
- {
- es.es_StructSize=sizeof(struct EasyStruct);
- es.es_Flags=0;
- es.es_Title=(char *)SLIPName;
- es.es_TextFormat="Error in configuration file on line %ld.";
- es.es_GadgetFormat="Okay";
- EasyRequestArgs(NULL, &es, 0, &linenum);
- CloseLibrary(IntuitionBase);
- }
- break;
- }
-
- }
- FreeDosObject(DOS_RDARGS,rdargs);
- }
- FreeMem(linebuff, 256);
- }
- Close(ConfigFile);
- }
- return(status);
- }
-
-
- /*
- **
- ** BeginIO
- **
- ** This is the dispatch point for the driver's incoming IORequests.
- **
- */
-
- #define SLIP_IMMEDIATES 0L
-
- VOID ASM DevBeginIO(REG(a1) struct IOSana2Req *ios2,
- REG(a6) struct SLIPDevice *SLIPDevice)
- {
- ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
-
- if(ios2->ios2_Req.io_Command < S2_END)
- {
- if((1L << ios2->ios2_Req.io_Command) & SLIP_IMMEDIATES)
- {
- PerformIO(ios2);
- }
- else
- {
- ios2->ios2_Req.io_Flags &= ~IOF_QUICK;
- PutMsg((struct MsgPort *)ios2->ios2_Req.io_Unit,(struct Message *)ios2);
- }
- }
- else
- {
- ios2->ios2_Req.io_Error = IOERR_NOCMD;
- TermIO(ios2);
- }
- }
-
- /*
- ** This routine is used to dispatch an IO request either from BeginIO
- ** or from the Unit process.
- */
- VOID PerformIO(struct IOSana2Req *ios2)
- {
- struct SLIPDevUnit *sdu;
-
- sdu = (struct SLIPDevUnit *)ios2->ios2_Req.io_Unit;
-
- ios2->ios2_Req.io_Error = 0;
-
- switch(ios2->ios2_Req.io_Command)
- {
- case CMD_READ: ReadPacket(sdu,ios2);
- break;
-
- case CMD_WRITE: WritePacket(sdu,ios2);
- break;
-
- case S2_DEVICEQUERY: DeviceQuery(sdu,ios2);
- break;
-
- case S2_GETSTATIONADDRESS: GetStationAddress(sdu,ios2);
- break;
-
- case S2_CONFIGINTERFACE: ConfigInterface(sdu,ios2);
- break;
-
- case S2_ADDMULTICASTADDRESS:
- case S2_DELMULTICASTADDRESS:
- case S2_MULTICAST: ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
- ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
- TermIO(ios2);
- break;
-
- case S2_BROADCAST: WritePacket(sdu,ios2);
- break;
-
- case S2_TRACKTYPE: TrackType(sdu,ios2);
- break;
-
- case S2_UNTRACKTYPE: UnTrackType(sdu,ios2);
- break;
-
- case S2_GETTYPESTATS: GetTypeStats(sdu,ios2);
- break;
-
- case S2_GETSPECIALSTATS: GetSpecialStats(sdu,ios2);
- break;
-
- case S2_GETGLOBALSTATS: GetGlobalStats(sdu,ios2);
- break;
-
- case S2_ONEVENT: OnEvent(sdu,ios2);
- break;
-
- case S2_READORPHAN: ReadOrphan(sdu,ios2);
- break;
-
- case S2_ONLINE: Online(sdu,ios2);
- break;
-
- case S2_OFFLINE: Offline(sdu,ios2);
- break;
-
- default: ios2->ios2_Req.io_Error = IOERR_NOCMD;
- TermIO(ios2);
- break;
- }
- }
-
- /*
- ** This function returns any device specific statistics that
- ** we may have. Unfortunately, we don't have and SLIP specific
- ** statistics.
- */
- VOID GetSpecialStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- struct Sana2SpecialStatHeader *stats;
-
- stats = (struct Sana2SpecialStatHeader *)ios2->ios2_StatData;
-
- #if CSLIP
- {
- int count;
- struct Sana2SpecialStatRecord *r;
-
- count = stats->RecordCountMax;
- if (count > 11)
- count = 11;
- r = (struct Sana2SpecialStatRecord *)(stats + 1);
- r = &r[count - 1];
-
- switch (count) {
- case 11:
- r->Type = S2SS_CSLIP_I_TOSSED;
- r->String = "i_tossed";
- r->Count = sdu->sdu_slcompress.sls_i_tossed;
- r--;
- case 10:
- r->Type = S2SS_CSLIP_I_ERROR;
- r->String = "i_error";
- r->Count = sdu->sdu_slcompress.sls_i_error;
- r--;
- case 9:
- r->Type = S2SS_CSLIP_I_COMPRESSED;
- r->String = "i_compressed";
- r->Count = sdu->sdu_slcompress.sls_i_compressed;
- r--;
- case 8:
- r->Type = S2SS_CSLIP_I_UNCOMPRESSED;
- r->String = "i_uncompressed";
- r->Count = sdu->sdu_slcompress.sls_i_uncompressed;
- r--;
- case 7:
- r->Type = S2SS_CSLIP_I_IP;
- r->String = "i_ip";
- r->Count = sdu->sdu_slcompress.sls_i_ip;
- r--;
- case 6:
- r->Type = S2SS_CSLIP_O_MISSES;
- r->String = "o_misses";
- r->Count = sdu->sdu_slcompress.sls_o_misses;
- r--;
- case 5:
- r->Type = S2SS_CSLIP_O_SEARCHES;
- r->String = "o_searches";
- r->Count = sdu->sdu_slcompress.sls_o_searches;
- r--;
- case 4:
- r->Type = S2SS_CSLIP_O_COMPRESSED;
- r->String = "o_compressed";
- r->Count = sdu->sdu_slcompress.sls_o_compressed;
- r--;
- case 3:
- r->Type = S2SS_CSLIP_O_UNCOMPRESSED;
- r->String = "o_uncompressed";
- r->Count = sdu->sdu_slcompress.sls_o_uncompressed;
- r--;
- case 2:
- r->Type = S2SS_CSLIP_O_TCP;
- r->String = "o_tcp";
- r->Count = sdu->sdu_slcompress.sls_o_tcp;
- r--;
- case 1:
- r->Type = S2SS_CSLIP_O_NONTCP;
- r->String = "o_nontcp";
- r->Count = sdu->sdu_slcompress.sls_o_nontcp;
- case 0:
- break;
- }
-
- stats->RecordCountSupplied = count;
- }
- #else
- stats->RecordCountSupplied = 0;
- #endif
- TermIO(ios2);
- }
-
- /*
- ** This function returns the global statistics for the
- ** slip device.
- */
- VOID GetGlobalStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- struct Sana2DeviceStats *stats;
-
- stats = (struct Sana2DeviceStats *)ios2->ios2_StatData;
-
- stats->PacketsReceived = sdu->sdu_Stats.PacketsReceived;
- stats->PacketsSent = sdu->sdu_Stats.PacketsSent;
- stats->BadData = sdu->sdu_Stats.BadData;
- stats->Overruns = sdu->sdu_Stats.Overruns;
- stats->UnknownTypesReceived = sdu->sdu_Stats.UnknownTypesReceived;
- stats->Reconfigurations = sdu->sdu_Stats.Reconfigurations;
- stats->LastStart.tv_secs = sdu->sdu_Stats.LastStart.tv_secs;
- stats->LastStart.tv_micro = sdu->sdu_Stats.LastStart.tv_micro; /* Rhialto */
-
- /* Rhialto: huh?
- ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
- ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
- */
- TermIO(ios2);
- }
-
- /*
- ** This function returns statistics for a specific
- ** type of packet that is being tracked. Unfortunately,
- ** SLIP can't differentiate between different packet
- ** types, which makes packet type tracking essentially
- ** useless as the numbers would essentially be the same
- ** as those found via S2_GETGLOBALSTATS.
- **
- ** Just to be thourough, I have arbitrarily picked
- ** the packet type for SLIP IP packets to be 2048, the
- ** same as tha used for Ethernet. This will at least
- ** allow you to track IP packets.
- */
- VOID GetTypeStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- struct Sana2PacketTypeStats *stats;
- struct SuperS2PTStats *sstats;
-
- ObtainSemaphore(&sdu->sdu_ListLock);
-
- stats = (struct Sana2PacketTypeStats *)ios2->ios2_StatData;
- sstats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
-
- while(sstats->ss_Node.mln_Succ)
- {
- if(ios2->ios2_PacketType == sstats->ss_PType)
- {
- stats->PacketsSent = sstats->ss_Stats.PacketsSent;
- stats->PacketsReceived = sstats->ss_Stats.PacketsReceived;
- stats->BytesSent = sstats->ss_Stats.BytesSent;
- stats->BytesReceived = sstats->ss_Stats.BytesReceived;
- stats->PacketsDropped = sstats->ss_Stats.PacketsDropped;
- break;
- }
- sstats = (struct SuperS2PTStats *)sstats->ss_Node.mln_Succ;
- }
- ReleaseSemaphore(&sdu->sdu_ListLock);
- if(!sstats->ss_Node.mln_Succ)
- {
- ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
- ios2->ios2_WireError = S2WERR_NOT_TRACKED;
- }
- TermIO(ios2);
- }
-
- /*
- ** This function adds a packet type to the list
- ** of those that are being tracked.
- */
- VOID TrackType(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- struct SuperS2PTStats *stats;
-
- ObtainSemaphore(&sdu->sdu_ListLock);
-
- stats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
-
- while(stats->ss_Node.mln_Succ)
- {
- if(ios2->ios2_PacketType == stats->ss_PType)
- {
- ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
- ios2->ios2_WireError = S2WERR_ALREADY_TRACKED;
- break; /* Rhialto */
- }
- stats = (struct SuperS2PTStats *)stats->ss_Node.mln_Succ;
- }
- if(!stats->ss_Node.mln_Succ)
- {
- if(stats = AllocMem(sizeof(struct SuperS2PTStats),MEMF_CLEAR|MEMF_PUBLIC))
- {
- stats->ss_PType = ios2->ios2_PacketType; /* Rhialto */
- if(ios2->ios2_PacketType == 2048)
- sdu->sdu_IPTrack = stats;
- AddTail((struct List *)&sdu->sdu_Track,(struct Node *)stats);
- }
- }
- ReleaseSemaphore(&sdu->sdu_ListLock);
-
- TermIO(ios2);
- }
-
- /*
- ** This function removes a packet type from the
- ** list of those that are being tracked.
- */
- VOID UnTrackType(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- struct SuperS2PTStats *stats;
- struct SuperS2PTStats *stats_next;
-
- ObtainSemaphore(&sdu->sdu_ListLock);
-
- stats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
-
- while(stats->ss_Node.mln_Succ)
- {
- stats_next = (struct SuperS2PTStats *)stats->ss_Node.mln_Succ;
- if(ios2->ios2_PacketType == stats->ss_PType)
- {
- if(ios2->ios2_PacketType == 2048)
- sdu->sdu_IPTrack = NULL;
- Remove((struct Node *)stats);
- FreeMem(stats,sizeof(struct SuperS2PTStats));
- stats = NULL;
- break;
- }
- stats = stats_next;
- }
- if(stats)
- {
- ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
- ios2->ios2_WireError = S2WERR_NOT_TRACKED;
- }
- ReleaseSemaphore(&sdu->sdu_ListLock);
-
- TermIO(ios2);
- }
-
- /*
- ** This function is called whenever we receive a packet
- ** from the serial device driver.
- **
- */
- VOID PacketReceived(struct SLIPDevUnit *sdu, ULONG length)
- {
- sdu->sdu_Stats.PacketsReceived++;
-
- if(sdu->sdu_IPTrack)
- {
- sdu->sdu_IPTrack->ss_Stats.PacketsReceived++;
- sdu->sdu_IPTrack->ss_Stats.BytesReceived+=length;
- }
- }
-
- /*
- ** This function is called whenever a packet is
- ** sent to the serial device driver.
- */
- VOID PacketSent(struct SLIPDevUnit *sdu, ULONG length)
- {
- sdu->sdu_Stats.PacketsSent++;
-
- if(sdu->sdu_IPTrack)
- {
- sdu->sdu_IPTrack->ss_Stats.PacketsSent++;
- sdu->sdu_IPTrack->ss_Stats.BytesSent+=length;
- }
- }
-
- /*
- ** This function is called whenever a packet that
- ** is too large is received.
- */
- VOID PacketOverrun(struct SLIPDevUnit *sdu)
- {
- #if CSLIP
- sl_uncompress_tcp(NULL, TYPE_ERROR, &sdu->sdu_slcompress);
- #endif
- sdu->sdu_Stats.Overruns++;
- DoEvent(sdu, S2EVENT_RX);
- }
-
- /*
- ** This function is called whenever a packet with
- ** garbage data is encountered.
- */
- VOID ReceivedGarbage(struct SLIPDevUnit *sdu)
- {
- #if CSLIP
- sl_uncompress_tcp(NULL, TYPE_ERROR, &sdu->sdu_slcompress);
- #endif
- sdu->sdu_Stats.BadData++;
- DoEvent(sdu, S2EVENT_RX);
- }
-
- /*
- ** This function is called whenever a packet
- ** is dropped by the SLIP driver.
- */
- VOID PacketDropped(struct SLIPDevUnit *sdu)
- {
- if(sdu->sdu_IPTrack)
- {
- sdu->sdu_IPTrack->ss_Stats.PacketsDropped++;
- }
- }
-
- /*
- ** This function is used to return an IO request
- ** back to the sender.
- */
- VOID TermIO(struct IOSana2Req *ios2)
- {
- if(!(ios2->ios2_Req.io_Flags & IOF_QUICK))
- ReplyMsg((struct Message *)ios2);
- }
-
- /*
- ** The device AbortIO() entry point.
- **
- ** A1 - The IO request to be aborted.
- ** A3 - The unit pointer NOT!
- ** A6 - The device base.
- */
- ULONG ASM DevAbortIO(REG(a1) struct IOSana2Req *ios2,
- REG(a6) struct SLIPDevice *SLIPDevice)
- {
- struct SLIPDevUnit *sdu = (struct SLIPDevUnit *)ios2->ios2_Req.io_Unit;
- ULONG result = 0L;
-
- ObtainSemaphore(&sdu->sdu_ListLock);
- if(ios2->ios2_Req.io_Message.mn_Node.ln_Type != NT_REPLYMSG)
- {
- switch(ios2->ios2_Req.io_Command)
- {
- case CMD_READ: result=AbortReq(&sdu->sdu_Rx,ios2);
- break;
-
- case CMD_WRITE: result=AbortReq(&sdu->sdu_Tx,ios2);
- break;
-
- case S2_READORPHAN: result=AbortReq(&sdu->sdu_RxOrph,ios2);
- break;
-
- case S2_ONEVENT: result=AbortReq(&sdu->sdu_Events,ios2);
- break;
-
- default: result=IOERR_NOCMD;
- break;
- }
- }
- ReleaseSemaphore(&sdu->sdu_ListLock);
- return(result);
- }
-
- /*
- ** This funcion is used to locate an IO request in a linked
- ** list and abort it if found.
- */
- ULONG AbortReq(struct MinList *minlist, struct IOSana2Req *ios2)
- {
- struct Node *node, *next;
- ULONG result=IOERR_NOCMD;
-
- node = (struct Node *)minlist->mlh_Head;
-
- while(node->ln_Succ)
- {
- next = node->ln_Succ;
-
- if(node == (struct Node *)ios2)
- {
- Remove((struct Node *)ios2);
- ios2->ios2_Req.io_Error = IOERR_ABORTED;
- TermIO(ios2);
- result = 0;
- }
- node = next;
- }
- return(result);
- }
-
- /*
- ** This function handles S2_CONFIGINTERFACE commands.
- */
- VOID ConfigInterface(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
-
- /* Note: we may only be configured once. */
- if(!(sdu->sdu_State & SLIPUF_CONFIG))
- {
- if(OpenSerial(sdu))
- {
- CopyMem(&sdu->sdu_StAddr,&ios2->ios2_SrcAddr,4);
- sdu->sdu_State |= SLIPUF_CONFIG;
- }
- }
- else
- {
- /* Sorry, we're already configured. */
- ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
- ios2->ios2_WireError = S2WERR_IS_CONFIGURED;
- }
- TermIO(ios2);
- }
-
- /*
- ** This function handles S2_GETSTATIONADDRESS commands.
- **
- ** We don't really have a hardware address, so we will
- ** just clear the source address field.
- ** Rhialto: What we want is the config file address as hardware
- *8 address, and the S2_CONFIGINTERFACE address as current address.
- */
-
- VOID GetStationAddress(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- memset(ios2->ios2_DstAddr, 0, SANA2_MAX_ADDR_BYTES);
- memset(ios2->ios2_SrcAddr, 0, SANA2_MAX_ADDR_BYTES);
- memcpy(ios2->ios2_SrcAddr, &sdu->sdu_StAddr, 4);
- memcpy(ios2->ios2_DstAddr, &sdu->sdu_HwAddr, 4);
-
- TermIO(ios2);
- }
-
- /*
- ** This function handles S2_DEVICEQUERY comands.
- ** Rhialto: Give the format of the data, and the *correct* size!
- */
- VOID DeviceQuery(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- struct Sana2DeviceQuery *sdq;
-
- sdq = (struct Sana2DeviceQuery *)ios2->ios2_StatData;
-
- sdq->DevQueryFormat = 0;
- sdq->DeviceLevel = 0;
- sdq->AddrFieldSize = 32; /* 32-bit IP address */
- sdq->MTU = SLIP_MTU; /* 1006 byte max */
- sdq->BPS = sdu->sdu_BaudRate;
- #if CSLIP
- sdq->HardwareType = S2WireType_CSLIP;
- #else
- sdq->HardwareType = S2WireType_SLIP;
- #endif
-
- sdq->SizeSupplied = sizeof(*sdq);
- TermIO(ios2);
- }
-
- /*
- ** This function is used for handling CMD_WRITE
- ** commands.
- */
- VOID WritePacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
-
- /* Make sure that we are online. */
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- /* Make sure it's a legal length. */
- if(ios2->ios2_DataLength <= SLIP_MTU)
- {
- /* See if our serial CMD_WRITE command is busy. If it's not, send
- the IO request to SendPacket. */
- if(CheckIO((struct IORequest *)sdu->sdu_SerTx))
- {
- WaitIO((struct IORequest *)sdu->sdu_SerTx);
- SendPacket(sdu, ios2);
- }
- else
- {
- /* We'll have to queue the packet for later...*/
- ios2->ios2_Req.io_Flags &= ~IOF_QUICK;
- ObtainSemaphore(&sdu->sdu_ListLock);
- AddTail((struct List *)&sdu->sdu_Tx,(struct Node *)ios2);
- ReleaseSemaphore(&sdu->sdu_ListLock);
- }
- }
- else
- {
- /* Sorry, the packet is too long! */
- ios2->ios2_Req.io_Error = S2ERR_MTU_EXCEEDED;
- ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
- TermIO(ios2);
- DoEvent(sdu,S2EVENT_TX);
- }
- }
- else
- {
- /* Sorry, we're offline */
- ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
- ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
- TermIO(ios2);
- }
- }
-
- VOID SendPacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- struct IOExtSer *ioser;
- struct BufferManagement *bm;
- ULONG framelength;
-
- bm =(struct BufferManagement *) ios2->ios2_BufferManagement;
-
- /* Copy the data out of the packet into our temporary buffer. */
- if((*bm->bm_CopyFromBuffer)(sdu->sdu_TxBuff,ios2->ios2_Data,ios2->ios2_DataLength))
- {
- #if CSLIP
- struct mbuf m;
- unsigned char type;
-
- m.m_off = sdu->sdu_TxBuff;
- m.m_len = ios2->ios2_DataLength;
-
- /* Appendix B.1 Living without a framing `type' byte */
-
- type = sl_compress_tcp(&m, &sdu->sdu_slcompress);
- m.m_off[0] |= type;
-
- /* Encode the packet in SLIP format */
- framelength=EncodeSLIP(m.m_off,sdu->sdu_TxSLIP,m.m_len);
- PacketSent(sdu,m.m_len);
- #else
- /* Encode the packet in SLIP format */
- framelength=EncodeSLIP(sdu->sdu_TxBuff,sdu->sdu_TxSLIP,ios2->ios2_DataLength);
- PacketSent(sdu,ios2->ios2_DataLength);
- #endif
-
- ioser = sdu->sdu_SerTx;
- ioser->IOSer.io_Data = sdu->sdu_TxSLIP;
- ioser->IOSer.io_Length = framelength;
- ioser->IOSer.io_Command = CMD_WRITE;
- ioser->IOSer.io_Error = 0;
- ioser->IOSer.io_Message.mn_Node.ln_Type = 0;
-
- /* Send the packet to the serial device driver */
- SendIO((struct IORequest *)ioser);
- }
- else
- {
- /* Something went wrong...*/
- ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
- ios2->ios2_WireError = S2WERR_BUFF_ERROR;
- DoEvent(sdu,S2EVENT_BUFF);
- }
- TermIO(ios2);
- }
-
- /*
- ** This routine encodes a packet in SLIP format.
- **
- ** The format is quite simple.
- **
- ** SLIP Encoding:
- **
- ** SLIP_ESC -> SLIP_ESC SLIP_ESC_ESC
- ** SLIP_END -> SLIP_ESC SLIP_ESC_END
- **
- ** The packet is preceded and terminated with a SLIP_END as prescribed by
- ** rfc 1055.
- **
- */
- ULONG EncodeSLIP(UBYTE *source, UBYTE *dest, ULONG length)
- {
- UBYTE ch;
- UBYTE *current;
-
- current = dest;
-
- *current = SLIP_END;
- current++;
-
- while(length--)
- {
- ch = *source;
- source++;
-
- if(ch == SLIP_ESC)
- {
- *current = SLIP_ESC;
- current++;
- ch = SLIP_ESC_ESC;
- }
- else if(ch == SLIP_END)
- {
- *current = SLIP_ESC;
- current ++;
- ch = SLIP_ESC_END;
- }
- *current = ch;
- current++;
- }
- *current = SLIP_END;
- current++;
-
- return((ULONG)(current - dest));
- }
-
- /*
- ** This routine handles CMD_READ commands. We
- ** always queue these unless we're offline.
- */
- VOID ReadPacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
-
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- /* Queue it... */
- ObtainSemaphore(&sdu->sdu_ListLock);
- AddTail((struct List *)&sdu->sdu_Rx,(struct Node *)ios2);
- #if DEMANDREAD
- if (sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type == NT_FREEMSG)
- QueueSerRequest(sdu);
- #endif
- ReleaseSemaphore(&sdu->sdu_ListLock);
- }
- else
- {
- /* Sorry, we're offline */
- ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
- ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
- TermIO(ios2);
- }
- }
-
- /*
- ** This routine handles CMD_READORPHAN commands. We
- ** always queue these unless we're offline.
- **
- ** Note: These IO requests will never get satisfied.
- ** Since SLIP doesn't contain packet type information,
- ** there is no way to identify what type of packets
- ** are being received or sent. Thus, we simply ignore
- ** the packet type and *assume* that the packets are
- ** IP packets.
- */
- VOID ReadOrphan(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
-
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- /* Queue it...*/
- ObtainSemaphore(&sdu->sdu_ListLock);
- AddTail((struct List *)&sdu->sdu_RxOrph,(struct Node *)ios2);
- #if DEMANDREAD
- if (sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type == NT_FREEMSG)
- QueueSerRequest(sdu);
- #endif
- ReleaseSemaphore(&sdu->sdu_ListLock);
- }
- else
- {
- /* Sorry, we're offline */
- ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
- ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
- TermIO(ios2);
- }
- }
-
- /*
- ** This routine initializes our IO requests and buffers
- ** for serial i/o and SLIP encoding/decoding.
- */
- BOOL InitSerial(struct SLIPDevUnit *sdu)
- {
- ULONG *clr;
- BOOL status = FALSE;
-
- for(clr = (ULONG *) &sdu->sdu_SerRx; clr <= (ULONG *) &sdu->sdu_TxSLIP; clr++)
- *clr = 0L;
-
- if(sdu->sdu_TxPort = CreateMsgPort())
- {
- if(sdu->sdu_SerTx = CreateIORequest(sdu->sdu_TxPort,sizeof(struct IOExtSer)))
- {
- if(sdu->sdu_RxPort = CreateMsgPort())
- {
- if(sdu->sdu_SerRx = CreateIORequest(sdu->sdu_RxPort,sizeof(struct IOExtSer)))
- {
- if(sdu->sdu_TxBuff = AllocMem((SLIP_MTU + BUF_SLOP) * 2 + MAX_HDR,MEMF_CLEAR|MEMF_PUBLIC))
- {
- sdu->sdu_RxBuff = sdu->sdu_TxBuff + SLIP_MTU + BUF_SLOP + MAX_HDR;
- sdu->sdu_RxBuffPtr = sdu->sdu_RxBuff;
-
- if(sdu->sdu_TxSLIP = AllocMem((SLIP_MTU*2 + BUF_SLOP) * 2,MEMF_CLEAR|MEMF_PUBLIC))
- {
- sdu->sdu_RxSLIP = sdu->sdu_TxSLIP + SLIP_MTU*2 + BUF_SLOP;
- {
- status = TRUE;
- }
- }
- }
- }
- }
- }
- }
- if(!status)
- DeinitSerial(sdu);
- return(status);
- }
-
- /*
- ** This routine cleans up our serial i/o requests
- ** and misc. buffers.
- */
- VOID DeinitSerial(struct SLIPDevUnit *sdu)
- {
- if(sdu->sdu_SerTx)
- DeleteIORequest(sdu->sdu_SerTx);
-
- if(sdu->sdu_TxPort)
- DeleteMsgPort(sdu->sdu_TxPort);
-
- if(sdu->sdu_SerRx)
- DeleteIORequest(sdu->sdu_SerRx);
-
- if(sdu->sdu_RxPort)
- DeleteMsgPort(sdu->sdu_RxPort);
-
- if(sdu->sdu_TxBuff)
- FreeMem(sdu->sdu_TxBuff, (SLIP_MTU + BUF_SLOP) * 2 + MAX_HDR);
-
- if(sdu->sdu_TxSLIP)
- FreeMem(sdu->sdu_TxSLIP,(SLIP_MTU*2 + BUF_SLOP) * 2);
- }
-
- /*
- ** This routine handles S2_ONEVNET commands.
- */
- VOID OnEvent(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
-
- switch(ios2->ios2_WireError)
- {
- /* Special case. We may already be online, in which
- case the IO request should return immediately. Otherwise
- we queue it for later. */
-
- case S2EVENT_ONLINE:
- if(sdu->sdu_State & SLIPUF_ONLINE)
- TermIO(ios2);
- else
- {
- ObtainSemaphore(&sdu->sdu_ListLock);
- AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
- ReleaseSemaphore(&sdu->sdu_ListLock);
- }
- break;
-
- /* Same as with S2EVENT_ONLINE, but the opposite
- happens. */
- case S2EVENT_OFFLINE:
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- ObtainSemaphore(&sdu->sdu_ListLock);
- AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
- ReleaseSemaphore(&sdu->sdu_ListLock);
- }
- else
- TermIO(ios2);
- break;
-
- /* Just queue everything else. */
- default:
- ObtainSemaphore(&sdu->sdu_ListLock);
- AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
- ReleaseSemaphore(&sdu->sdu_ListLock);
- break;
- }
- }
-
- /*
- ** This routine opens the serial device driver and attempts to bring
- ** the device online.
- */
- BOOL OpenSerial(struct SLIPDevUnit *sdu)
- {
- BOOL status = TRUE;
- ULONG odflags;
-
- sdu->sdu_SerRx->IOSer.io_Device = NULL;
-
- odflags = SERF_XDISABLED|SERF_RAD_BOOGIE;
- if(sdu->sdu_State & SLIPUF_7WIRE)
- odflags |= SERF_7WIRE;
-
- /* Rhialto: odflags must be in io_SerFlags, not in OpenDevice! */
- sdu->sdu_SerTx->io_SerFlags = odflags;
-
- if(!OpenDevice(sdu->sdu_SerDevName,sdu->sdu_SerUnitNum,(struct IORequest *)sdu->sdu_SerTx,0))
- {
- /* Set up our serial parameters */
- sdu->sdu_SerRx->IOSer.io_Device = sdu->sdu_SerTx->IOSer.io_Device;
- sdu->sdu_SerRx->IOSer.io_Unit = sdu->sdu_SerTx->IOSer.io_Unit;
-
- sdu->sdu_SerTx->IOSer.io_Command = SDCMD_SETPARAMS;
- sdu->sdu_SerTx->io_Baud = sdu->sdu_BaudRate;
- sdu->sdu_SerTx->io_RBufLen = 16384L;
- sdu->sdu_SerTx->io_ReadLen = 8;
- sdu->sdu_SerTx->io_WriteLen = 8;
- sdu->sdu_SerTx->io_StopBits = 1;
- sdu->sdu_SerTx->io_SerFlags = odflags;
- #if EOFMODE
- sdu->sdu_SerTx->io_TermArray.TermArray0 =
- sdu->sdu_SerTx->io_TermArray.TermArray1 =
- 0x01010101 * ((unsigned char)SLIP_END);
- #endif
- if(!DoIO((struct IORequest *)sdu->sdu_SerTx))
- {
- /* Assume we're now online */
- sdu->sdu_State |= SLIPUF_ONLINE;
-
- /* Are we checking for serial detect? */
- if(sdu->sdu_State & SLIPUF_CD)
- {
- sdu->sdu_SerTx->IOSer.io_Command = SDCMD_QUERY;
- if(!DoIO((struct IORequest *)sdu->sdu_SerTx))
- {
- if(sdu->sdu_SerTx->io_Status & (1<<5))
- {
- /* Sorry, no carrier, shut down the serial driver
- and set our state to offline. */
- CloseDevice((struct IORequest *)sdu->sdu_SerTx);
- sdu->sdu_State &= ~SLIPUF_ONLINE;
- }
- }
- else
- status = FALSE;
- }
- if(status)
- {
- /* Queue up the initial CMD_READ command for the
- serial driver. */
- sdu->sdu_SerRx->IOSer.io_Command = CMD_READ;
- sdu->sdu_SerRx->IOSer.io_Length = 1;
- sdu->sdu_SerRx->IOSer.io_Data = sdu->sdu_RxSLIP;
- #if EOFMODE
- sdu->sdu_SerRx->io_SerFlags = SERF_EOFMODE|odflags;
- sdu->sdu_SerRx->io_TermArray.TermArray0 =
- sdu->sdu_SerRx->io_TermArray.TermArray1 =
- 0x01010101 * ((unsigned char)SLIP_END);
- #else
- sdu->sdu_SerRx->io_SerFlags = odflags;
- #endif
- SendIO((struct IORequest *)sdu->sdu_SerRx);
- }
- }
- else
- status = FALSE;
-
- if(!status)
- CloseDevice((struct IORequest *)sdu->sdu_SerTx);
- }
- else
- {
- struct Library *IntuitionBase;
- struct EasyStruct es;
- ULONG args[2];
- args[0]=(ULONG)sdu->sdu_SerDevName;
- args[1]=(ULONG)sdu->sdu_SerUnitNum;
- if(IntuitionBase = OpenLibrary("intuition.library",37L))
- {
- es.es_StructSize=sizeof(struct EasyStruct);
- es.es_Flags=0;
- es.es_Title=(char *)SLIPName;
- es.es_TextFormat="Couldn't open %s unit %ld.";
- es.es_GadgetFormat="Okay";
- EasyRequestArgs(NULL, &es, 0, (APTR)args);
- CloseLibrary(IntuitionBase);
- }
- status = FALSE;
- }
- if(sdu->sdu_State & SLIPUF_ONLINE)
- MarkTimeOnline(sdu);
-
- return(status);
- }
-
- /*
- ** This routine gets the current system time and stores
- ** it in our global statistics structure.
- */
-
- VOID MarkTimeOnline(struct SLIPDevUnit *sdu)
- {
- register struct Library *TimerBase;
- struct timerequest *treq;
-
- if(treq = (struct timerequest *)AllocMem(sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR))
- {
- if(!OpenDevice("timer.device",UNIT_MICROHZ,(struct IORequest *)treq,0L))
- {
- TimerBase = (struct Library *)treq->tr_node.io_Device;
- GetSysTime(&sdu->sdu_Stats.LastStart);
- CloseDevice((struct IORequest *)treq);
- }
- FreeMem(treq,sizeof(struct timerequest));
- }
- }
-
- /*
- ** This routine aborts any pending activity with the serial
- ** device driver and then brings the slip driver offline.
- */
- VOID CloseSerial(struct SLIPDevUnit *sdu)
- {
- AbortIO((struct IORequest *)sdu->sdu_SerRx);
- WaitIO((struct IORequest *)sdu->sdu_SerRx);
-
- while(GetMsg(sdu->sdu_RxPort));
-
- AbortIO((struct IORequest *)sdu->sdu_SerTx);
- WaitIO((struct IORequest *)sdu->sdu_SerTx);
-
- while(GetMsg(sdu->sdu_TxPort));
-
- CloseDevice((struct IORequest *)sdu->sdu_SerRx);
-
- sdu->sdu_State &= ~SLIPUF_ONLINE;
- }
-
- /*
- ** This routime handles CMD_ONLINE commands.
- */
- VOID Online(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
-
- if(!(sdu->sdu_State & SLIPUF_ONLINE))
- {
- /* We're offline. Try to go online. */
- if(OpenSerial(sdu))
- {
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- /* In case someone wants to know...*/
- DoEvent(sdu, S2EVENT_ONLINE);
- }
- else
- {
- /* Sorry, the attempt to go online failed. */
- ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
- ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
- }
- }
- else
- {
- /* A general problem occured. */
- ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
- ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
- }
- }
- TermIO(ios2);
- }
-
- /*
- ** This routine handles CMD_OFFLINE commands.
- */
- VOID Offline(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
- {
- TermIO(ios2);
-
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- /* We're online, so shut everything down. */
- CloseSerial(sdu);
- DoOffline(sdu);
- DoEvent(sdu,S2EVENT_OFFLINE);
- }
- }
-
- /*
- ** This routine is called whenever an "important"
- ** SANA-II event occurs.
- */
- VOID DoEvent(struct SLIPDevUnit *sdu, ULONG event)
- {
- struct IOSana2Req *ios2;
- struct IOSana2Req *ios2_next;
-
- ObtainSemaphore(&sdu->sdu_ListLock);
-
- ios2 = (struct IOSana2Req *)sdu->sdu_Events.mlh_Head;
-
- while(ios2->ios2_Req.io_Message.mn_Node.ln_Succ)
- {
- ios2_next = (struct IOSana2Req *)ios2->ios2_Req.io_Message.mn_Node.ln_Succ;
-
- /* Is this the event they are looking for? */
- if(ios2->ios2_WireError == event)
- {
- Remove((struct Node *)ios2);
- TermIO(ios2);
- }
- ios2 = ios2_next;
- }
- ReleaseSemaphore(&sdu->sdu_ListLock);
- }
-
- /*
- ** This routine is called whenever the device needs to
- ** be taken offline. We return any pending CMD_READ's
- ** or CMD_WRITE's to their senders.
- */
- VOID DoOffline(struct SLIPDevUnit *sdu)
- {
- struct IOSana2Req *ios2;
-
- ObtainSemaphore(&sdu->sdu_ListLock);
-
- while(ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Rx))
- {
- ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
- ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
- TermIO(ios2);
- }
-
- while(ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Tx))
- {
- ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
- ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
- TermIO(ios2);
- }
- ReleaseSemaphore(&sdu->sdu_ListLock);
- }
-
- /*
- ** This routine is called whenever a CMD_WRITE request
- ** has returned from the serial driver.
- */
- VOID ServiceTxPort(struct SLIPDevUnit *sdu)
- {
- struct IOSana2Req *ios2;
-
- /* See if we have any pending CMD_WRITE requests. */
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- ObtainSemaphore(&sdu->sdu_ListLock);
- ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Tx);
- ReleaseSemaphore(&sdu->sdu_ListLock);
-
- if(ios2)
- {
- SendPacket(sdu, ios2);
- sdu->sdu_NoMore = 1;
- }
- }
- else
- sdu->sdu_NoMore = 1;
- }
-
- /*
- ** This routine is called whenever a CMD_READ request
- ** returns from the serial driver. It decodes the
- ** packet data and tries to build complete packets.
- */
- VOID DoSerial(struct SLIPDevUnit *sdu, struct IOExtSer *ioSer)
- {
- UBYTE *rx_ptr,*packet_ptr;
- UBYTE rx_byte, packet_byte;
- ULONG length;
-
- packet_ptr = sdu->sdu_RxBuffPtr;
- rx_ptr = sdu->sdu_RxSLIP;
-
- length = ioSer->IOSer.io_Actual; /* Rhialto: Was io_Length */
-
- while(length--)
- {
- rx_byte = packet_byte = *rx_ptr;
- rx_ptr++;
-
- /* Handle SLIP packet decoding...*/
- if(sdu->sdu_Escape)
- {
- if(rx_byte == SLIP_ESC_ESC)
- packet_byte = SLIP_ESC;
- else if(rx_byte = SLIP_ESC_END)
- packet_byte = SLIP_END;
- else
- ReceivedGarbage(sdu); /* This packet may be hosed */
-
- sdu->sdu_Escape = FALSE;
- }
- else if(rx_byte == SLIP_ESC)
- {
- sdu->sdu_Escape = TRUE;
- continue;
- }
- else if(rx_byte == SLIP_END)
- {
- GotPacket(sdu,(ULONG)(packet_ptr - sdu->sdu_RxBuff));
- packet_ptr = sdu->sdu_RxBuff;
- continue;
- }
- *packet_ptr = packet_byte;
- packet_ptr++;
-
- if(((ULONG)(packet_ptr - sdu->sdu_RxBuff)) > SLIP_MTU)
- {
- packet_ptr = sdu->sdu_RxBuff;
- PacketOverrun(sdu);
- }
- }
- sdu->sdu_RxBuffPtr = packet_ptr;
-
- /* Queue up another CMD_READ request...*/
- #if DEMANDREAD
- /* Rhialto: but only if we are sure that we won't drop that packet */
- /*ObtainSemaphore(&sdu->sdu_ListLock);*/
- /* Semaphore protection of sdu_Rx, sdu_RxOrph, and sdu_Tx is not
- * really necessary, since they are only accessed from the
- * Unit task, because there are no IMMEDIATE device commands.
- */
- if (!IsListEmpty((struct List *)&sdu->sdu_Rx) ||
- !IsListEmpty((struct List *)&sdu->sdu_RxOrph))
- QueueSerRequest(sdu);
- else
- sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type = NT_FREEMSG;
- /*ReleaseSemaphore(&sdu->sdu_ListLock);*/
- #else
- QueueSerRequest(sdu);
- #endif
- }
-
- /*
- ** This routine is called whenever we think we've got
- ** a complete packet to satisfy a CMD_READ request.
- */
- VOID GotPacket(struct SLIPDevUnit *sdu, ULONG length)
- {
- struct IOSana2Req *ios2;
- struct BufferManagement *bm;
-
- /* We ignore zero-length packets. These occur
- in between legal SLIP packets due to the
- way SLIP packets are framed. */
-
- if(length)
- {
- PacketReceived(sdu,length);
- ObtainSemaphore(&sdu->sdu_ListLock);
-
- ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Rx);
-
- if(!ios2)
- ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_RxOrph);
-
- ReleaseSemaphore(&sdu->sdu_ListLock);
-
- if(ios2)
- {
- #if CSLIP
- /* Appendix B.1 Living without a framing `type' byte */
- struct mbuf m;
- unsigned char type;
-
- m.m_off = sdu->sdu_RxBuff;
- m.m_len = length;
-
- type = m.m_off[0];
-
- if (type & 0x80)
- type = TYPE_COMPRESSED_TCP;
- else if (type >= 0x70) {
- type = TYPE_UNCOMPRESSED_TCP;
- m.m_off[0] &= ~0x30;
- } else
- type = TYPE_IP;
- if (NULL == sl_uncompress_tcp(&m, type, &sdu->sdu_slcompress))
- return;
-
- bm = (struct BufferManagement *)ios2->ios2_BufferManagement;
-
- /* Copy the data into the protocol stack's buffer using its
- supplied callback routine. */
- if((*bm->bm_CopyToBuffer)(ios2->ios2_Data,m.m_off,m.m_len))
- {
- ios2->ios2_DataLength = m.m_len;
- }
- #else
- bm = (struct BufferManagement *)ios2->ios2_BufferManagement;
-
- /* Copy the data into the protocol stack's buffer using its
- supplied callback routine. */
- if((*bm->bm_CopyToBuffer)(ios2->ios2_Data,sdu->sdu_RxBuff,length))
- {
- ios2->ios2_DataLength = length;
- }
- #endif
- else
- {
- ios2->ios2_DataLength = 0;
- ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
- ios2->ios2_WireError = S2WERR_BUFF_ERROR;
- DoEvent(sdu,S2EVENT_BUFF);
- }
- TermIO(ios2);
- }
- else
- PacketDropped(sdu);
- }
- sdu->sdu_Escape = 0;
- }
-
- /*
- ** This routine is called whenever we need to
- ** get more data from the serial port. We first
- ** to a SDCMD_QUERY to see how much data is available,
- ** if any.
- ** Rhialto: without EOF mode, this makes the thing a real CPU hog,
- ** as long as input is coming in and read requests are pending.
- ** And since it runs at pri 5, that is a real disaster.
- */
- VOID QueueSerRequest(struct SLIPDevUnit *sdu)
- {
- #if EOFMODE == 0
- sdu->sdu_SerRx->IOSer.io_Command = SDCMD_QUERY;
- DoIO((struct IORequest *)sdu->sdu_SerRx);
- #endif
-
- if(sdu->sdu_State & SLIPUF_CD)
- {
- #if EOFMODE
- sdu->sdu_SerRx->IOSer.io_Command = SDCMD_QUERY;
- DoIO((struct IORequest *)sdu->sdu_SerRx);
- #endif
- if(sdu->sdu_SerRx->io_Status & (1<<5))
- {
- /* Oops! We've lost carrier. Go offline. */
- CloseSerial(sdu);
- DoOffline(sdu);
- DoEvent(sdu,S2EVENT_OFFLINE);
- return;
- }
- }
- sdu->sdu_SerRx->IOSer.io_Command = CMD_READ;
- sdu->sdu_SerRx->IOSer.io_Data = sdu->sdu_RxSLIP;
- #if EOFMODE
- sdu->sdu_SerRx->IOSer.io_Length = SLIP_MTU * 2 + 1;
- #else
- /* Rhialto: This could lead to requesting more than the buffer
- * size! The serial.device has a 16K buffer. (See SDCMD_SETPARAMS)
- */
- sdu->sdu_SerRx->IOSer.io_Length = sdu->sdu_SerRx->IOSer.io_Actual;
-
- if (sdu->sdu_SerRx->IOSer.io_Length > (SLIP_MTU*2 + BUF_SLOP))
- sdu->sdu_SerRx->IOSer.io_Length = (SLIP_MTU*2 + BUF_SLOP);
- else
- /* If the number of bytes available is zero, queue a request
- for one byte. */
- if(!sdu->sdu_SerRx->IOSer.io_Length)
- sdu->sdu_SerRx->IOSer.io_Length = 1;
- #endif
-
- SendIO((struct IORequest *)sdu->sdu_SerRx);
- }
-
- /*
- ** This is the C entry point for the Unit process.
- */
-
- VOID ASM DevProcCEntry(VOID)
- {
- struct Process *proc;
- struct SLIPDevUnit *sdu;
- struct IOExtSer *ioser;
- struct StartupMessage *sm;
- struct BufferManagement *bm;
- struct IOSana2Req *ios2;
- ULONG waitmask,signals;
- UBYTE signalbit;
-
- /* Find our Process pointer and wait for our startup
- message to arrive. */
-
- proc = (struct Process *)FindTask(0L);
-
- WaitPort(&proc->pr_MsgPort);
-
- /* Pull the startup message off of our process messageport. */
- sm = (struct StartupMessage *)GetMsg(&proc->pr_MsgPort);
-
- /* Grab our Unit pointer. */
- sdu = (struct SLIPDevUnit *)sm->Unit;
-
- /* Attempt to allocate a signal bit for our Unit MsgPort. */
- signalbit = AllocSignal(-1L);
- if(signalbit != -1)
- {
- /* Set up our Unit's MsgPort. */
- sdu->sdu_Unit.unit_MsgPort.mp_SigBit = signalbit;
- sdu->sdu_Unit.unit_MsgPort.mp_SigTask = (struct Task *)proc;
- sdu->sdu_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
-
- /* Initialize our list semaphore */
- InitSemaphore(&sdu->sdu_ListLock);
-
- /* Initialize our linked lists. */
- NewList((struct List *)&sdu->sdu_Rx);
- NewList((struct List *)&sdu->sdu_RxOrph);
- NewList((struct List *)&sdu->sdu_Tx);
- NewList((struct List *)&sdu->sdu_Events);
- NewList((struct List *)&sdu->sdu_BuffMgmt);
- NewList((struct List *)&sdu->sdu_Track);
-
- #if CSLIP
- /* Initialise the compression stuff */
- sl_compress_init(&sdu->sdu_slcompress, 16, 16);
- #endif
-
- /* Initialize the serial stuff. If all goes okay,
- set sdu->sdu_Proc to pointer to our unit process.
- This will let the Unit init code know that were
- are okay. */
-
- if(InitSerial(sdu))
- sdu->sdu_Proc = proc;
- }
- /* Reply to our startup message */
- ReplyMsg((struct Message *)sm);
-
- /* Check sdu->sdu_Proc to see if everything went okay up
- above. */
- if(sdu->sdu_Proc)
- {
- waitmask = (1L<<signalbit) | (1L<<sdu->sdu_RxPort->mp_SigBit) |
- (1L<<sdu->sdu_TxPort->mp_SigBit) | SIGBREAKF_CTRL_F;
-
- /* Loop...*/
-
- while(TRUE)
- {
- signals = Wait(waitmask);
-
- /* Have we been signaled to shut down? */
- if(signals & SIGBREAKF_CTRL_F)
- break;
-
- /* I use this flag to make sure I don't sit idle
- with a message sitting on one of my message ports. */
-
- sdu->sdu_NoMore = TRUE; /* Make sure we run at least once. */
-
- while(sdu->sdu_NoMore)
- {
- sdu->sdu_NoMore = FALSE;
-
- if(ios2 = (struct IOSana2Req *)GetMsg((struct MsgPort *)sdu))
- {
- sdu->sdu_NoMore = TRUE;
- PerformIO(ios2);
- }
- if(ioser = (struct IOExtSer *)GetMsg(sdu->sdu_RxPort))
- {
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- sdu->sdu_NoMore = TRUE;
- DoSerial(sdu, ioser);
- }
- }
- if(ioser = (struct IOExtSer *)GetMsg(sdu->sdu_TxPort))
- {
- sdu->sdu_NoMore = TRUE;
- ServiceTxPort(sdu);
- }
- }
- }
- /* If we're online, we need to shut everything down. */
- if(sdu->sdu_State & SLIPUF_ONLINE)
- {
- CloseSerial(sdu);
- FreeSignal(signalbit);
- while(bm = (struct BufferManagement *)RemHead((struct List *)&sdu->sdu_BuffMgmt))
- FreeMem(bm,sizeof(struct BufferManagement));
-
- }
- DeinitSerial(sdu);
- #if CSLIP
- sl_compress_deinit(&sdu->sdu_slcompress);
- #endif
-
- /* Signal the other side we're exiting. Make sure that
- we exit before they wake up by using the same trick
- when replying to Workbench startup messages. */
-
- Forbid();
- Signal((struct Task *)sdu->sdu_Proc,SIGBREAKF_CTRL_F);
- }
- /* Something went wrong in the init code. Drop out. */
- else
- {
- if(signalbit)
- FreeSignal(signalbit);
- }
- }
-
- /* List init routine. */
- VOID NewList(struct List *list)
- {
- list->lh_Head = (struct Node *)&list->lh_Tail;
- list->lh_Tail = NULL;
- list->lh_TailPred = (struct Node *)list;
- }
-