/* File: request.c Author: Neil Cafferkey Copyright (C) 2001-2010 Neil Cafferkey This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include "device.h" #include "request_protos.h" #include "unit_protos.h" #define KNOWN_EVENTS (S2EVENT_ERROR|S2EVENT_TX|S2EVENT_RX|S2EVENT_ONLINE|\ S2EVENT_OFFLINE|S2EVENT_BUFF|S2EVENT_HARDWARE|S2EVENT_SOFTWARE) static BOOL CmdInvalid(struct IOSana2Req *request,struct DevBase *base); static BOOL CmdRead(struct IOSana2Req *request,struct DevBase *base); static BOOL CmdWrite(struct IOSana2Req *request,struct DevBase *base); static BOOL CmdFlush(struct IORequest *request,struct DevBase *base); static BOOL CmdS2DeviceQuery(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdGetStationAddress(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdConfigInterface(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdBroadcast(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdTrackType(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdUntrackType(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdGetTypeStats(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdGetSpecialStats(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdGetGlobalStats(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdOnEvent(struct IOSana2Req *request,struct DevBase *base); static BOOL CmdReadOrphan(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdOnline(struct IOSana2Req *request,struct DevBase *base); static BOOL CmdOffline(struct IOSana2Req *request,struct DevBase *base); static BOOL CmdDeviceQuery(struct IOStdReq *request, struct DevBase *base); static BOOL CmdAddMulticastAddresses(struct IOSana2Req *request, struct DevBase *base); static BOOL CmdDelMulticastAddresses(struct IOSana2Req *request, struct DevBase *base); static const UWORD supported_commands[]= { CMD_READ, CMD_WRITE, CMD_FLUSH, S2_DEVICEQUERY, S2_GETSTATIONADDRESS, S2_CONFIGINTERFACE, S2_ADDMULTICASTADDRESS, S2_DELMULTICASTADDRESS, S2_MULTICAST, S2_BROADCAST, S2_TRACKTYPE, S2_UNTRACKTYPE, S2_GETTYPESTATS, S2_GETSPECIALSTATS, S2_GETGLOBALSTATS, S2_ONEVENT, S2_READORPHAN, S2_ONLINE, S2_OFFLINE, NSCMD_DEVICEQUERY, S2_ADDMULTICASTADDRESSES, S2_DELMULTICASTADDRESSES, 0 }; struct Sana2DeviceQuery sana2_info= { 0, 0, 0, 0, ADDRESS_SIZE*8, MTU, 10000000, S2WireType_Ethernet }; /****i* 3c589.device/ServiceRequest **************************************** * * NAME * ServiceRequest -- Attempt to service a device request. * * SYNOPSIS * ServiceRequest(request) * * VOID ServiceRequest(struct IORequest *); * * FUNCTION * Attempts to carry out a request. The relevant unit's semaphore must * be obtained before calling this function. This function releases the * semaphore before returning. * * INPUTS * request * * RESULT * None. * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ VOID ServiceRequest(struct IOSana2Req *request,struct DevBase *base) { BOOL complete; switch(request->ios2_Req.io_Command) { case CMD_READ: complete=CmdRead(request,base); break; case CMD_WRITE: complete=CmdWrite(request,base); break; case CMD_FLUSH: complete=CmdFlush((APTR)request,base); break; case S2_DEVICEQUERY: complete=CmdS2DeviceQuery((APTR)request,base); break; case S2_GETSTATIONADDRESS: complete=CmdGetStationAddress((APTR)request,base); break; case S2_CONFIGINTERFACE: complete=CmdConfigInterface((APTR)request,base); break; case S2_ADDMULTICASTADDRESS: complete=CmdAddMulticastAddresses((APTR)request,base); break; case S2_DELMULTICASTADDRESS: complete=CmdDelMulticastAddresses((APTR)request,base); break; case S2_MULTICAST: complete=CmdWrite((APTR)request,base); break; case S2_BROADCAST: complete=CmdBroadcast((APTR)request,base); break; case S2_TRACKTYPE: complete=CmdTrackType((APTR)request,base); break; case S2_UNTRACKTYPE: complete=CmdUntrackType((APTR)request,base); break; case S2_GETTYPESTATS: complete=CmdGetTypeStats((APTR)request,base); break; case S2_GETSPECIALSTATS: complete=CmdGetSpecialStats((APTR)request,base); break; case S2_GETGLOBALSTATS: complete=CmdGetGlobalStats((APTR)request,base); break; case S2_ONEVENT: complete=CmdOnEvent((APTR)request,base); break; case S2_READORPHAN: complete=CmdReadOrphan((APTR)request,base); break; case S2_ONLINE: complete=CmdOnline((APTR)request,base); break; case S2_OFFLINE: complete=CmdOffline((APTR)request,base); break; case NSCMD_DEVICEQUERY: complete=CmdDeviceQuery((APTR)request,base); break; case S2_ADDMULTICASTADDRESSES: complete=CmdAddMulticastAddresses((APTR)request,base); break; case S2_DELMULTICASTADDRESSES: complete=CmdDelMulticastAddresses((APTR)request,base); break; default: complete=CmdInvalid((APTR)request,base); } if(complete&&((request->ios2_Req.io_Flags&IOF_QUICK)==0)) ReplyMsg((APTR)request); ReleaseSemaphore(&((struct DevUnit *)request->ios2_Req.io_Unit)-> access_lock); return; } /****i* 3c589.device/CMD_INVALID ******************************************* * * NAME * CMD_INVALID -- Reject invalid commands. * * FUNCTION * * INPUTS * None. * * RESULTS * io_Error - IOERR_NOCMD. * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdInvalid(struct IOSana2Req *request,struct DevBase *base) { request->ios2_Req.io_Error=IOERR_NOCMD; request->ios2_WireError=S2WERR_GENERIC_ERROR; return TRUE; } /****** 3c589.device/CMD_READ ********************************************** * * NAME * CMD_READ -- Read data. * * FUNCTION * * INPUTS * io_Flags * ios2_PacketType * ios2_Data * * RESULTS * io_Flags * io_Error * ios2_WireError * ios2_SrcAddr * ios2_DstAddr * ios2_DataLength * ios2_Data * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdRead(struct IOSana2Req *request,struct DevBase *base) { struct DevUnit *unit; struct Opener *opener; BOOL complete=FALSE; unit=(APTR)request->ios2_Req.io_Unit; if((unit->flags&UNITF_ONLINE)!=0) { opener=request->ios2_BufferManagement; PutRequest(&opener->read_port,(APTR)request,base); } else { request->ios2_Req.io_Error=S2ERR_OUTOFSERVICE; request->ios2_WireError=S2WERR_UNIT_OFFLINE; complete=TRUE; } /* Return */ return complete; } /****** 3c589.device/CMD_WRITE ********************************************* * * NAME * CMD_WRITE -- Write data. * * FUNCTION * * INPUTS * io_Flags * ios2_DstAddr * ios2_PacketType * ios2_DataLength * ios2_Data * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ /****** 3c589.device/S2_MULTICAST ****************************************** * * NAME * S2_MULTICAST -- * * FUNCTION * * INPUTS * io_Flags * ios2_DstAddr - multicast address. * ios2_PacketType * ios2_DataLength * ios2_Data * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdWrite(struct IOSana2Req *request,struct DevBase *base) { struct DevUnit *unit; BYTE error=0; ULONG wire_error; BOOL complete=FALSE; /* Check request is valid */ unit=(APTR)request->ios2_Req.io_Unit; if((unit->flags&UNITF_ONLINE)==0) { error=S2ERR_OUTOFSERVICE; wire_error=S2WERR_UNIT_OFFLINE; } else if((request->ios2_Req.io_Command==S2_MULTICAST)&& ((request->ios2_DstAddr[0]&0x1)==0)) { error=S2ERR_BAD_ADDRESS; wire_error=S2WERR_BAD_MULTICAST; } /* Queue request for sending */ if(error==0) PutRequest(unit->request_ports[WRITE_QUEUE],(APTR)request,base); else { request->ios2_Req.io_Error=error; request->ios2_WireError=wire_error; complete=TRUE; } /* Return */ return complete; } /****** 3c589.device/CMD_FLUSH ********************************************* * * NAME * CMD_FLUSH -- . * * FUNCTION * * INPUTS * None. * * RESULTS * io_Error * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdFlush(struct IORequest *request,struct DevBase *base) { FlushUnit((APTR)request->io_Unit,EVENT_QUEUE,IOERR_ABORTED,base); return TRUE; } /****** 3c589.device/S2_DEVICEQUERY **************************************** * * NAME * S2_DEVICEQUERY -- Query device capabilities. * * FUNCTION * * INPUTS * ios2_StatData - Pointer to Sana2DeviceQuery structure. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdS2DeviceQuery(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; struct Sana2DeviceQuery *info; ULONG size_available,size; /* Copy device info */ unit=(APTR)request->ios2_Req.io_Unit; info=request->ios2_StatData; size=size_available=info->SizeAvailable; if(size>sizeof(struct Sana2DeviceQuery)) size=sizeof(struct Sana2DeviceQuery); CopyMem(&sana2_info,info,size); if((unit->flags&UNITF_ROADRUNNER)!=0) info->BPS=100000000; info->SizeAvailable=size_available; info->SizeSupplied=size; /* Return */ return TRUE; } /****** 3c589.device/S2_GETSTATIONADDDRESS ********************************* * * NAME * S2_GETSTATIONADDDRESS -- * * FUNCTION * * INPUTS * None. * * RESULTS * io_Error * ios2_WireError * ios2_SrcAddr - current address. * ios2_DstAddr - default address (zero if none?). * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdGetStationAddress(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; /* Copy addresses */ unit=(APTR)request->ios2_Req.io_Unit; CopyMem(unit->address,request->ios2_SrcAddr,ADDRESS_SIZE); CopyMem(unit->default_address,request->ios2_DstAddr,ADDRESS_SIZE); /* Return */ return TRUE; } /****** 3c589.device/S2_CONFIGINTERFACE ************************************ * * NAME * S2_CONFIGINTERFACE -- * * FUNCTION * * INPUTS * ios2_SrcAddr - address to use. * * RESULTS * io_Error * ios2_WireError * ios2_SrcAddr - address used. * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdConfigInterface(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; /* Configure adapter */ unit=(APTR)request->ios2_Req.io_Unit; if((unit->flags&UNITF_CONFIGURED)==0) { CopyMem(request->ios2_SrcAddr,unit->address,ADDRESS_SIZE); if((unit->flags&UNITF_HAVEADAPTER)!=0) ConfigureAdapter(unit,base); unit->flags|=UNITF_CONFIGURED; } else { request->ios2_Req.io_Error=S2ERR_BAD_STATE; request->ios2_WireError=S2WERR_IS_CONFIGURED; } /* Return */ return TRUE; } /****** 3c589.device/S2_BROADCAST ****************************************** * * NAME * S2_BROADCAST -- * * FUNCTION * * INPUTS * io_Flags * ios2_PacketType * ios2_DataLength * ios2_Data * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdBroadcast(struct IOSana2Req *request, struct DevBase *base) { /* Fill in the broadcast address as destination */ *((ULONG *)request->ios2_DstAddr)=0xffffffff; *((UWORD *)(request->ios2_DstAddr+4))=0xffff; /* Queue the write as normal */ return CmdWrite(request,base); } /****** 3c589.device/S2_TRACKTYPE ****************************************** * * NAME * S2_TRACKTYPE -- * * FUNCTION * * INPUTS * ios2_PacketType - packet type to start tracking. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdTrackType(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; struct Opener *opener; ULONG packet_type,wire_error; struct TypeTracker *tracker; struct TypeStats *initial_stats; BYTE error=0; unit=(APTR)request->ios2_Req.io_Unit; packet_type=request->ios2_PacketType; /* Get global tracker */ tracker=(struct TypeTracker *) FindTypeStats(unit,&unit->type_trackers,packet_type,base); if(tracker!=NULL) tracker->user_count++; else { tracker=AllocMem(sizeof(struct TypeTracker),MEMF_PUBLIC|MEMF_CLEAR); if(tracker!=NULL) { tracker->packet_type=packet_type; tracker->user_count=1; Disable(); AddTail((APTR)&unit->type_trackers,(APTR)tracker); Enable(); } } /* Store initial figures for this opener */ opener=request->ios2_BufferManagement; initial_stats=FindTypeStats(unit,&opener->initial_stats,packet_type, base); if(initial_stats!=NULL) { error=S2ERR_BAD_STATE; wire_error=S2WERR_ALREADY_TRACKED; } if(error==0) { initial_stats=AllocMem(sizeof(struct TypeStats),MEMF_PUBLIC); if(initial_stats==NULL) { error=S2ERR_NO_RESOURCES; wire_error=S2WERR_GENERIC_ERROR; } } if(error==0) { CopyMem(tracker,initial_stats,sizeof(struct TypeStats)); AddTail((APTR)&opener->initial_stats,(APTR)initial_stats); } /* Return */ request->ios2_Req.io_Error=error; request->ios2_WireError=wire_error; return TRUE; } /****** 3c589.device/S2_UNTRACKTYPE **************************************** * * NAME * S2_UNTRACKTYPE -- * * FUNCTION * * INPUTS * ios2_PacketType - packet type to stop tracking. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdUntrackType(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; struct Opener *opener; ULONG packet_type; struct TypeTracker *tracker; struct TypeStats *initial_stats; unit=(APTR)request->ios2_Req.io_Unit; packet_type=request->ios2_PacketType; /* Get global tracker and initial figures */ tracker=(struct TypeTracker *) FindTypeStats(unit,&unit->type_trackers,packet_type,base); opener=request->ios2_BufferManagement; initial_stats=FindTypeStats(unit,&opener->initial_stats,packet_type, base); /* Decrement tracker usage and free unused structures */ if(initial_stats!=NULL) { if((--tracker->user_count)==0) { Disable(); Remove((APTR)tracker); Enable(); FreeMem(tracker,sizeof(struct TypeTracker)); } Remove((APTR)initial_stats); FreeMem(initial_stats,sizeof(struct TypeStats)); } else { request->ios2_Req.io_Error=S2ERR_BAD_STATE; request->ios2_WireError=S2WERR_NOT_TRACKED; } /* Return */ return TRUE; } /****** 3c589.device/S2_GETTYPESTATS *************************************** * * NAME * S2_GETTYPESTATS -- * * FUNCTION * * INPUTS * ios2_PacketType - packet type to get statistics on. * ios2_StatData - pointer to a Sana2PacketTypeStats structure. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdGetTypeStats(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; struct Opener *opener; ULONG packet_type; struct TypeStats *initial_stats,*tracker; struct Sana2PacketTypeStats *stats; unit=(APTR)request->ios2_Req.io_Unit; packet_type=request->ios2_PacketType; /* Get global tracker and initial figures */ tracker=FindTypeStats(unit,&unit->type_trackers,packet_type,base); opener=request->ios2_BufferManagement; initial_stats=FindTypeStats(unit,&opener->initial_stats,packet_type, base); /* Copy and adjust figures */ if(initial_stats!=NULL) { stats=request->ios2_StatData; CopyMem(&tracker->stats,stats,sizeof(struct Sana2PacketTypeStats)); stats->PacketsSent-=initial_stats->stats.PacketsSent; stats->PacketsReceived-=initial_stats->stats.PacketsReceived; stats->BytesSent-=initial_stats->stats.BytesSent; stats->BytesReceived-=initial_stats->stats.BytesReceived; stats->PacketsDropped-=initial_stats->stats.PacketsDropped; } else { request->ios2_Req.io_Error=S2ERR_BAD_STATE; request->ios2_WireError=S2WERR_NOT_TRACKED; } /* Return */ return TRUE; } /****** 3c589.device/S2_GETSPECIALSTATS ************************************ * * NAME * S2_GETSPECIALSTATS -- * * FUNCTION * * INPUTS * ios2_StatData - Pointer to Sana2SpecialStatHeader structure. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdGetSpecialStats(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; UWORD i,stat_count; struct Sana2SpecialStatHeader *header; struct Sana2SpecialStatRecord *record; /* Fill in stats */ unit=(APTR)request->ios2_Req.io_Unit; header=request->ios2_StatData; record=(APTR)(header+1); stat_count=header->RecordCountMax; if(stat_count>STAT_COUNT) stat_count=STAT_COUNT; for(i=0;iType=(S2WireType_Ethernet<<16)+i; record->Count=unit->special_stats[i]; record->String=(TEXT *)&unit->openers.mlh_Tail; record++; } header->RecordCountSupplied=stat_count; /* Return */ return TRUE; } /****** 3c589.device/S2_GETGLOBALSTATS ************************************* * * NAME * S2_GETGLOBALSTATS -- * * FUNCTION * * INPUTS * ios2_StatData - Pointer to Sana2DeviceStats structure. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdGetGlobalStats(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; /* Copy stats */ unit=(APTR)request->ios2_Req.io_Unit; CopyMem(&unit->stats,request->ios2_StatData, sizeof(struct Sana2DeviceStats)); /* Return */ return TRUE; } /****** 3c589.device/S2_ONEVENT ******************************************** * * NAME * S2_ONEVENT -- * * FUNCTION * * INPUTS * ios2_WireError * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdOnEvent(struct IOSana2Req *request,struct DevBase *base) { struct DevUnit *unit; ULONG events,wanted_events; BOOL complete=FALSE; /* Check if we understand the event types */ unit=(APTR)request->ios2_Req.io_Unit; wanted_events=request->ios2_WireError; if((wanted_events&~KNOWN_EVENTS)!=0) { request->ios2_Req.io_Error=S2ERR_NOT_SUPPORTED; events=S2WERR_BAD_EVENT; } else { if((unit->flags&UNITF_ONLINE)!=0) events=S2EVENT_ONLINE; else events=S2EVENT_OFFLINE; events&=wanted_events; } /* Reply request if a wanted event has already occurred */ if(events!=0) { request->ios2_WireError=events; complete=TRUE; } else PutRequest(unit->request_ports[EVENT_QUEUE],(APTR)request,base); /* Return */ return complete; } /****** 3c589.device/S2_READORPHAN ***************************************** * * NAME * S2_READORPHAN -- * * FUNCTION * * INPUTS * io_Flags * ios2_Data * * RESULTS * io_Flags * io_Error * ios2_WireError * ios2_PacketType - A copy of the packet's type field. * ios2_SrcAddr * ios2_DstAddr * ios2_DataLength * ios2_Data * * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdReadOrphan(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; BYTE error=0; ULONG wire_error; BOOL complete=FALSE; /* Check request is valid */ unit=(APTR)request->ios2_Req.io_Unit; if((unit->flags&UNITF_ONLINE)==0) { error=S2ERR_OUTOFSERVICE; wire_error=S2WERR_UNIT_OFFLINE; } /* Queue request */ if(error==0) PutRequest(unit->request_ports[ADOPT_QUEUE],(APTR)request,base); else { request->ios2_Req.io_Error=error; request->ios2_WireError=wire_error; complete=TRUE; } /* Return */ return complete; } /****** 3c589.device/S2_ONLINE ********************************************* * * NAME * S2_ONLINE -- * * FUNCTION * * INPUTS * None. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdOnline(struct IOSana2Req *request,struct DevBase *base) { struct DevUnit *unit; BYTE error=0; ULONG wire_error; UWORD i; /* Check request is valid */ unit=(APTR)request->ios2_Req.io_Unit; if((unit->flags&UNITF_CONFIGURED)==0) { error=S2ERR_BAD_STATE; wire_error=S2WERR_NOT_CONFIGURED; } if((unit->flags&UNITF_HAVEADAPTER)==0) { error=S2ERR_OUTOFSERVICE; wire_error=S2WERR_RCVREL_HDW_ERR; } /* Clear global and special stats and put adapter back online */ if((error==0)&&((unit->flags&UNITF_ONLINE)==0)) { unit->stats.PacketsReceived=0; unit->stats.PacketsSent=0; unit->stats.BadData=0; unit->stats.Overruns=0; unit->stats.UnknownTypesReceived=0; unit->stats.Reconfigurations=0; for(i=0;ispecial_stats[i]=0; GoOnline(unit,base); } /* Return */ request->ios2_Req.io_Error=error; request->ios2_WireError=wire_error; return TRUE; } /****** 3c589.device/S2_OFFLINE ******************************************** * * NAME * S2_OFFLINE -- * * FUNCTION * * INPUTS * None. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdOffline(struct IOSana2Req *request,struct DevBase *base) { struct DevUnit *unit; /* Put adapter offline */ unit=(APTR)request->ios2_Req.io_Unit; if((unit->flags&UNITF_ONLINE)!=0) GoOffline(unit,base); /* Return */ return TRUE; } /****** 3c589.device/NSCMD_DEVICEQUERY ************************************* * * NAME * NSCMD_DEVICEQUERY -- Query device capabilities. * * FUNCTION * * INPUTS * io_Length - ???. * io_Data - pointer to NSDeviceQueryResult structure. * * RESULTS * io_Error * io_Actual - size of structure device can handle. * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * * Note that we have to pretend the request structure is an IOStdReq. * */ static BOOL CmdDeviceQuery(struct IOStdReq *request, struct DevBase *base) { struct NSDeviceQueryResult *info; /* Set structure size twice */ info=request->io_Data; request->io_Actual=info->SizeAvailable= (ULONG)OFFSET(NSDeviceQueryResult,SupportedCommands)+sizeof(APTR); /* Report device details */ info->DeviceType=NSDEVTYPE_SANA2; info->DeviceSubType=0; info->SupportedCommands=(APTR)supported_commands; /* Return */ return TRUE; } /****** 3c589.device/S2_ADDMULTICASTADDRESS ******************************** * * NAME * S2_ADDMULTICASTADDRESS -- * * FUNCTION * * INPUTS * ios2_SrcAddr - multicast address. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ /****** 3c589.device/S2_ADDMULTICASTADDRESSES ****************************** * * NAME * S2_ADDMULTICASTADDRESSES -- * * FUNCTION * * INPUTS * ios2_SrcAddr - lower bound. * ios2_DstAddr - upper bound. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdAddMulticastAddresses(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; UBYTE *lower_bound,*upper_bound; unit=(APTR)request->ios2_Req.io_Unit; lower_bound=request->ios2_SrcAddr; if(request->ios2_Req.io_Command==S2_ADDMULTICASTADDRESS) upper_bound=lower_bound; else upper_bound=request->ios2_DstAddr; if(!AddMulticastRange(unit,lower_bound,upper_bound,base)) { request->ios2_Req.io_Error=S2ERR_NO_RESOURCES; request->ios2_WireError=S2WERR_GENERIC_ERROR; } /* Return */ return TRUE; } /****** 3c589.device/S2_DELMULTICASTADDRESS ******************************** * * NAME * S2_DELMULTICASTADDRESS -- * * FUNCTION * * INPUTS * ios2_SrcAddr - multicast address. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ /****** 3c589.device/S2_DELMULTICASTADDRESSES ****************************** * * NAME * S2_DELMULTICASTADDRESSES -- * * FUNCTION * * INPUTS * ios2_SrcAddr - lower bound. * ios2_DstAddr - upper bound. * * RESULTS * io_Error * ios2_WireError * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ static BOOL CmdDelMulticastAddresses(struct IOSana2Req *request, struct DevBase *base) { struct DevUnit *unit; UBYTE *lower_bound,*upper_bound; unit=(APTR)request->ios2_Req.io_Unit; lower_bound=request->ios2_SrcAddr; if(request->ios2_Req.io_Command==S2_DELMULTICASTADDRESS) upper_bound=lower_bound; else upper_bound=request->ios2_DstAddr; if(!RemMulticastRange(unit,lower_bound,upper_bound,base)) { request->ios2_Req.io_Error=S2ERR_BAD_STATE; request->ios2_WireError=S2WERR_BAD_MULTICAST; } /* Return */ return TRUE; } /****i* 3c589.device/PutRequest ******************************************** * * NAME * PutRequest -- . * * SYNOPSIS * PutRequest(port,request) * * VOID PutRequest(struct MsgPort *,struct IORequest *); * * FUNCTION * * INPUTS * port * request * * RESULT * None. * * EXAMPLE * * NOTES * * BUGS * * SEE ALSO * **************************************************************************** * */ VOID PutRequest(struct MsgPort *port,struct IORequest *request, struct DevBase *base) { request->io_Flags&=~IOF_QUICK; PutMsg(port,(APTR)request); return; }