- Fixes to OS wrappers to allow extra mask parameter for PCCard status
[AROS.git] / workbench / devs / networks / etherlink3 / request.c
blobf0e148c088f6ea6f36469b21b445d52ad4252b19
1 /*
3 Copyright (C) 2001-2005 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 #include <exec/types.h>
24 #include <exec/errors.h>
25 #include <exec/initializers.h>
26 #include <devices/newstyle.h>
28 #include <proto/exec.h>
29 #include <proto/utility.h>
31 #include "device.h"
33 #include "request_protos.h"
34 #include "unit_protos.h"
37 #define KNOWN_EVENTS \
38 (S2EVENT_ERROR | S2EVENT_TX | S2EVENT_RX | S2EVENT_ONLINE \
39 | S2EVENT_OFFLINE | S2EVENT_BUFF | S2EVENT_HARDWARE | S2EVENT_SOFTWARE)
42 static BOOL CmdInvalid(struct IOSana2Req *request, struct DevBase *base);
43 static BOOL CmdRead(struct IOSana2Req *request, struct DevBase *base);
44 static BOOL CmdWrite(struct IOSana2Req *request, struct DevBase *base);
45 static BOOL CmdFlush(struct IORequest *request, struct DevBase *base);
46 static BOOL CmdS2DeviceQuery(struct IOSana2Req *request,
47 struct DevBase *base);
48 static BOOL CmdGetStationAddress(struct IOSana2Req *request,
49 struct DevBase *base);
50 static BOOL CmdConfigInterface(struct IOSana2Req *request,
51 struct DevBase *base);
52 static BOOL CmdBroadcast(struct IOSana2Req *request,
53 struct DevBase *base);
54 static BOOL CmdTrackType(struct IOSana2Req *request,
55 struct DevBase *base);
56 static BOOL CmdUntrackType(struct IOSana2Req *request,
57 struct DevBase *base);
58 static BOOL CmdGetTypeStats(struct IOSana2Req *request,
59 struct DevBase *base);
60 static BOOL CmdGetSpecialStats(struct IOSana2Req *request,
61 struct DevBase *base);
62 static BOOL CmdGetGlobalStats(struct IOSana2Req *request,
63 struct DevBase *base);
64 static BOOL CmdOnEvent(struct IOSana2Req *request, struct DevBase *base);
65 static BOOL CmdReadOrphan(struct IOSana2Req *request,
66 struct DevBase *base);
67 static BOOL CmdOnline(struct IOSana2Req *request, struct DevBase *base);
68 static BOOL CmdOffline(struct IOSana2Req *request, struct DevBase *base);
69 static BOOL CmdDeviceQuery(struct IOStdReq *request,
70 struct DevBase *base);
71 static BOOL CmdAddMulticastAddresses(struct IOSana2Req *request,
72 struct DevBase *base);
73 static BOOL CmdDelMulticastAddresses(struct IOSana2Req *request,
74 struct DevBase *base);
77 static const UWORD supported_commands[] =
79 CMD_READ,
80 CMD_WRITE,
81 CMD_FLUSH,
82 S2_DEVICEQUERY,
83 S2_GETSTATIONADDRESS,
84 S2_CONFIGINTERFACE,
85 S2_ADDMULTICASTADDRESS,
86 S2_DELMULTICASTADDRESS,
87 S2_MULTICAST,
88 S2_BROADCAST,
89 S2_TRACKTYPE,
90 S2_UNTRACKTYPE,
91 S2_GETTYPESTATS,
92 S2_GETSPECIALSTATS,
93 S2_GETGLOBALSTATS,
94 S2_ONEVENT,
95 S2_READORPHAN,
96 S2_ONLINE,
97 S2_OFFLINE,
98 NSCMD_DEVICEQUERY,
99 S2_ADDMULTICASTADDRESSES,
100 S2_DELMULTICASTADDRESSES,
105 static const struct Sana2DeviceQuery sana2_info =
111 ETH_ADDRESSSIZE * 8,
112 ETH_MTU,
114 S2WireType_Ethernet
119 const TEXT badmulticast_name[] = "Bad multicasts";
120 const TEXT retries_name[] = "Retries";
121 const TEXT fifo_underruns_name[] = "Underruns";
124 static const TEXT *const special_stat_names[] =
126 badmulticast_name,
127 retries_name,
128 fifo_underruns_name
133 /****i* etherlink3.device/ServiceRequest ***********************************
135 * NAME
136 * ServiceRequest -- Attempt to service a device request.
138 * SYNOPSIS
139 * ServiceRequest(request)
141 * VOID ServiceRequest(struct IORequest *);
143 * FUNCTION
144 * Attempts to carry out a request. The relevant unit's semaphore must
145 * be obtained before calling this function. This function releases the
146 * semaphore before returning.
148 ****************************************************************************
152 VOID ServiceRequest(struct IOSana2Req *request, struct DevBase *base)
154 BOOL complete;
156 switch(request->ios2_Req.io_Command)
158 case CMD_READ:
159 complete = CmdRead(request, base);
160 break;
161 case CMD_WRITE:
162 complete = CmdWrite(request, base);
163 break;
164 case CMD_FLUSH:
165 complete = CmdFlush((APTR)request, base);
166 break;
167 case S2_DEVICEQUERY:
168 complete = CmdS2DeviceQuery((APTR)request, base);
169 break;
170 case S2_GETSTATIONADDRESS:
171 complete = CmdGetStationAddress((APTR)request, base);
172 break;
173 case S2_CONFIGINTERFACE:
174 complete = CmdConfigInterface((APTR)request, base);
175 break;
176 case S2_ADDMULTICASTADDRESS:
177 complete = CmdAddMulticastAddresses((APTR)request, base);
178 break;
179 case S2_DELMULTICASTADDRESS:
180 complete = CmdDelMulticastAddresses((APTR)request, base);
181 break;
182 case S2_MULTICAST:
183 complete = CmdWrite((APTR)request, base);
184 break;
185 case S2_BROADCAST:
186 complete = CmdBroadcast((APTR)request, base);
187 break;
188 case S2_TRACKTYPE:
189 complete = CmdTrackType((APTR)request, base);
190 break;
191 case S2_UNTRACKTYPE:
192 complete = CmdUntrackType((APTR)request, base);
193 break;
194 case S2_GETTYPESTATS:
195 complete = CmdGetTypeStats((APTR)request, base);
196 break;
197 case S2_GETSPECIALSTATS:
198 complete = CmdGetSpecialStats((APTR)request, base);
199 break;
200 case S2_GETGLOBALSTATS:
201 complete = CmdGetGlobalStats((APTR)request, base);
202 break;
203 case S2_ONEVENT:
204 complete = CmdOnEvent((APTR)request, base);
205 break;
206 case S2_READORPHAN:
207 complete = CmdReadOrphan((APTR)request, base);
208 break;
209 case S2_ONLINE:
210 complete = CmdOnline((APTR)request, base);
211 break;
212 case S2_OFFLINE:
213 complete = CmdOffline((APTR)request, base);
214 break;
215 case NSCMD_DEVICEQUERY:
216 complete = CmdDeviceQuery((APTR)request, base);
217 break;
218 case S2_ADDMULTICASTADDRESSES:
219 complete = CmdAddMulticastAddresses((APTR)request, base);
220 break;
221 case S2_DELMULTICASTADDRESSES:
222 complete = CmdDelMulticastAddresses((APTR)request, base);
223 break;
224 default:
225 complete = CmdInvalid((APTR)request, base);
228 if(complete && (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
229 ReplyMsg((APTR)request);
231 ReleaseSemaphore(&((struct DevUnit *)request->ios2_Req.io_Unit)->
232 access_lock);
233 return;
238 /****i* etherlink3.device/CMD_INVALID **************************************
240 * NAME
241 * CMD_INVALID -- Reject invalid commands.
243 * FUNCTION
245 * INPUTS
246 * None.
248 * RESULTS
249 * io_Error - IOERR_NOCMD.
251 * EXAMPLE
253 * NOTES
255 * BUGS
257 * SEE ALSO
259 ****************************************************************************
263 static BOOL CmdInvalid(struct IOSana2Req *request, struct DevBase *base)
265 request->ios2_Req.io_Error = IOERR_NOCMD;
266 request->ios2_WireError = S2WERR_GENERIC_ERROR;
268 return TRUE;
273 /****** etherlink3.device/CMD_READ *****************************************
275 * NAME
276 * CMD_READ -- Read data.
278 * FUNCTION
280 * INPUTS
281 * io_Flags
282 * ios2_PacketType
283 * ios2_Data
285 * RESULTS
286 * io_Flags
287 * io_Error
288 * ios2_WireError
289 * ios2_SrcAddr
290 * ios2_DstAddr
291 * ios2_DataLength
292 * ios2_Data
294 * EXAMPLE
296 * NOTES
298 * BUGS
300 * SEE ALSO
302 ****************************************************************************
306 static BOOL CmdRead(struct IOSana2Req *request, struct DevBase *base)
308 struct DevUnit *unit;
309 struct Opener *opener;
310 BOOL complete = FALSE;
312 unit = (APTR)request->ios2_Req.io_Unit;
314 if((unit->flags & UNITF_ONLINE) != 0)
316 opener = request->ios2_BufferManagement;
317 PutRequest(&opener->read_port, (APTR)request, base);
319 else
321 request->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
322 request->ios2_WireError = S2WERR_UNIT_OFFLINE;
323 complete = TRUE;
326 /* Return */
328 return complete;
333 /****** etherlink3.device/CMD_WRITE ****************************************
335 * NAME
336 * CMD_WRITE -- Write data.
338 * FUNCTION
340 * INPUTS
341 * io_Flags
342 * ios2_DstAddr
343 * ios2_PacketType
344 * ios2_DataLength
345 * ios2_Data
347 * RESULTS
348 * io_Error
349 * ios2_WireError
351 * EXAMPLE
353 * NOTES
355 * BUGS
357 * SEE ALSO
359 ****************************************************************************
363 /****** etherlink3.device/S2_MULTICAST *************************************
365 * NAME
366 * S2_MULTICAST --
368 * FUNCTION
370 * INPUTS
371 * io_Flags
372 * ios2_DstAddr - multicast address.
373 * ios2_PacketType
374 * ios2_DataLength
375 * ios2_Data
377 * RESULTS
378 * io_Error
379 * ios2_WireError
381 * EXAMPLE
383 * NOTES
385 * BUGS
387 * SEE ALSO
389 ****************************************************************************
393 static BOOL CmdWrite(struct IOSana2Req *request, struct DevBase *base)
395 struct DevUnit *unit;
396 BYTE error = 0;
397 ULONG wire_error;
398 BOOL complete = FALSE;
400 /* Check request is valid */
402 unit = (APTR)request->ios2_Req.io_Unit;
403 if((unit->flags & UNITF_ONLINE) == 0)
405 error = S2ERR_OUTOFSERVICE;
406 wire_error = S2WERR_UNIT_OFFLINE;
408 else if((request->ios2_Req.io_Command == S2_MULTICAST) &&
409 ((request->ios2_DstAddr[0] & 0x1) == 0))
411 error = S2ERR_BAD_ADDRESS;
412 wire_error = S2WERR_BAD_MULTICAST;
415 /* Queue request for sending */
417 if(error == 0)
418 PutRequest(unit->request_ports[WRITE_QUEUE], (APTR)request, base);
419 else
421 request->ios2_Req.io_Error = error;
422 request->ios2_WireError = wire_error;
423 complete = TRUE;
426 /* Return */
428 return complete;
433 /****** etherlink3.device/CMD_FLUSH ****************************************
435 * NAME
436 * CMD_FLUSH -- .
438 * FUNCTION
440 * INPUTS
441 * None.
443 * RESULTS
444 * io_Error
446 * EXAMPLE
448 * NOTES
450 * BUGS
452 * SEE ALSO
454 ****************************************************************************
458 static BOOL CmdFlush(struct IORequest *request, struct DevBase *base)
460 FlushUnit((APTR)request->io_Unit, EVENT_QUEUE, IOERR_ABORTED, base);
462 return TRUE;
467 /****** etherlink3.device/S2_DEVICEQUERY ***********************************
469 * NAME
470 * S2_DEVICEQUERY -- Query device capabilities.
472 * FUNCTION
474 * INPUTS
475 * ios2_StatData - Pointer to Sana2DeviceQuery structure.
477 * RESULTS
478 * io_Error
479 * ios2_WireError
481 * EXAMPLE
483 * NOTES
485 * BUGS
487 * SEE ALSO
489 ****************************************************************************
493 static BOOL CmdS2DeviceQuery(struct IOSana2Req *request,
494 struct DevBase *base)
496 struct DevUnit *unit;
497 struct Sana2DeviceQuery *info;
498 ULONG size_available, size;
500 /* Copy device info */
502 unit = (APTR)request->ios2_Req.io_Unit;
503 info = request->ios2_StatData;
504 size = size_available = info->SizeAvailable;
505 if(size > sizeof(struct Sana2DeviceQuery))
506 size = sizeof(struct Sana2DeviceQuery);
508 CopyMem(&sana2_info, info, size);
509 info->BPS = unit->speed;
510 info->SizeAvailable = size_available;
511 info->SizeSupplied = size;
513 /* Return */
515 return TRUE;
520 /****** etherlink3.device/S2_GETSTATIONADDDRESS ****************************
522 * NAME
523 * S2_GETSTATIONADDDRESS --
525 * FUNCTION
527 * INPUTS
528 * None.
530 * RESULTS
531 * io_Error
532 * ios2_WireError
533 * ios2_SrcAddr - current address.
534 * ios2_DstAddr - default address (zero if none?).
536 * EXAMPLE
538 * NOTES
540 * BUGS
542 * SEE ALSO
544 ****************************************************************************
548 static BOOL CmdGetStationAddress(struct IOSana2Req *request,
549 struct DevBase *base)
551 struct DevUnit *unit;
553 /* Copy addresses */
555 unit = (APTR)request->ios2_Req.io_Unit;
556 CopyMem(unit->address, request->ios2_SrcAddr, ETH_ADDRESSSIZE);
557 CopyMem(unit->default_address, request->ios2_DstAddr, ETH_ADDRESSSIZE);
559 /* Return */
561 return TRUE;
566 /****** etherlink3.device/S2_CONFIGINTERFACE *******************************
568 * NAME
569 * S2_CONFIGINTERFACE --
571 * FUNCTION
573 * INPUTS
574 * ios2_SrcAddr - address to use.
576 * RESULTS
577 * io_Error
578 * ios2_WireError
579 * ios2_SrcAddr - address used.
581 * EXAMPLE
583 * NOTES
585 * BUGS
587 * SEE ALSO
589 ****************************************************************************
593 static BOOL CmdConfigInterface(struct IOSana2Req *request,
594 struct DevBase *base)
596 struct DevUnit *unit;
598 /* Configure adapter */
600 unit = (APTR)request->ios2_Req.io_Unit;
601 if((unit->flags & UNITF_CONFIGURED) == 0)
603 CopyMem(request->ios2_SrcAddr, unit->address, ETH_ADDRESSSIZE);
604 if((unit->flags & UNITF_HAVEADAPTER) != 0)
605 ConfigureAdapter(unit, base);
606 unit->flags |= UNITF_CONFIGURED;
608 else
610 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
611 request->ios2_WireError = S2WERR_IS_CONFIGURED;
614 /* Return */
616 return TRUE;
621 /****** etherlink3.device/S2_BROADCAST *************************************
623 * NAME
624 * S2_BROADCAST --
626 * FUNCTION
628 * INPUTS
629 * io_Flags
630 * ios2_PacketType
631 * ios2_DataLength
632 * ios2_Data
634 * RESULTS
635 * io_Error
636 * ios2_WireError
638 * EXAMPLE
640 * NOTES
642 * BUGS
644 * SEE ALSO
646 ****************************************************************************
650 static BOOL CmdBroadcast(struct IOSana2Req *request,
651 struct DevBase *base)
653 /* Fill in the broadcast address as destination */
655 *((ULONG *)request->ios2_DstAddr) = 0xffffffff;
656 *((UWORD *)(request->ios2_DstAddr + 4)) = 0xffff;
658 /* Queue the write as normal */
660 return CmdWrite(request, base);
665 /****** etherlink3.device/S2_TRACKTYPE *************************************
667 * NAME
668 * S2_TRACKTYPE --
670 * FUNCTION
672 * INPUTS
673 * ios2_PacketType - packet type to start tracking.
675 * RESULTS
676 * io_Error
677 * ios2_WireError
679 * EXAMPLE
681 * NOTES
683 * BUGS
685 * SEE ALSO
687 ****************************************************************************
691 static BOOL CmdTrackType(struct IOSana2Req *request,
692 struct DevBase *base)
694 struct DevUnit *unit;
695 struct Opener *opener;
696 ULONG packet_type, wire_error;
697 struct TypeTracker *tracker;
698 struct TypeStats *initial_stats;
699 BYTE error = 0;
701 unit = (APTR)request->ios2_Req.io_Unit;
702 packet_type = request->ios2_PacketType;
704 /* Get global tracker */
706 tracker = (struct TypeTracker *)
707 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
709 if(tracker != NULL)
710 tracker->user_count++;
711 else
713 tracker =
714 AllocMem(sizeof(struct TypeTracker), MEMF_PUBLIC | MEMF_CLEAR);
715 if(tracker != NULL)
717 tracker->packet_type = packet_type;
718 tracker->user_count = 1;
720 Disable();
721 AddTail((APTR)&unit->type_trackers, (APTR)tracker);
722 Enable();
726 /* Store initial figures for this opener */
728 opener = request->ios2_BufferManagement;
729 initial_stats = FindTypeStats(unit, &opener->initial_stats, packet_type,
730 base);
732 if(initial_stats != NULL)
734 error = S2ERR_BAD_STATE;
735 wire_error = S2WERR_ALREADY_TRACKED;
738 if(error == 0)
740 initial_stats = AllocMem(sizeof(struct TypeStats), MEMF_PUBLIC);
741 if(initial_stats == NULL)
743 error = S2ERR_NO_RESOURCES;
744 wire_error = S2WERR_GENERIC_ERROR;
748 if(error == 0)
750 CopyMem(tracker, initial_stats, sizeof(struct TypeStats));
751 AddTail((APTR)&opener->initial_stats, (APTR)initial_stats);
754 /* Return */
756 request->ios2_Req.io_Error = error;
757 request->ios2_WireError = wire_error;
758 return TRUE;
763 /****** etherlink3.device/S2_UNTRACKTYPE ***********************************
765 * NAME
766 * S2_UNTRACKTYPE --
768 * FUNCTION
770 * INPUTS
771 * ios2_PacketType - packet type to stop tracking.
773 * RESULTS
774 * io_Error
775 * ios2_WireError
777 * EXAMPLE
779 * NOTES
781 * BUGS
783 * SEE ALSO
785 ****************************************************************************
789 static BOOL CmdUntrackType(struct IOSana2Req *request,
790 struct DevBase *base)
792 struct DevUnit *unit;
793 struct Opener *opener;
794 ULONG packet_type;
795 struct TypeTracker *tracker;
796 struct TypeStats *initial_stats;
798 unit = (APTR)request->ios2_Req.io_Unit;
799 packet_type = request->ios2_PacketType;
801 /* Get global tracker and initial figures */
803 tracker = (struct TypeTracker *)
804 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
805 opener = request->ios2_BufferManagement;
806 initial_stats = FindTypeStats(unit, &opener->initial_stats, packet_type,
807 base);
809 /* Decrement tracker usage and free unused structures */
811 if(initial_stats != NULL)
813 if((--tracker->user_count) == 0)
815 Disable();
816 Remove((APTR)tracker);
817 Enable();
818 FreeMem(tracker, sizeof(struct TypeTracker));
821 Remove((APTR)initial_stats);
822 FreeMem(initial_stats, sizeof(struct TypeStats));
824 else
826 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
827 request->ios2_WireError = S2WERR_NOT_TRACKED;
830 /* Return */
832 return TRUE;
837 /****** etherlink3.device/S2_GETTYPESTATS **********************************
839 * NAME
840 * S2_GETTYPESTATS --
842 * FUNCTION
844 * INPUTS
845 * ios2_PacketType - packet type to get statistics on.
846 * ios2_StatData - pointer to a Sana2PacketTypeStats structure.
848 * RESULTS
849 * io_Error
850 * ios2_WireError
852 * EXAMPLE
854 * NOTES
856 * BUGS
858 * SEE ALSO
860 ****************************************************************************
864 static BOOL CmdGetTypeStats(struct IOSana2Req *request,
865 struct DevBase *base)
867 struct DevUnit *unit;
868 struct Opener *opener;
869 ULONG packet_type;
870 struct TypeStats *initial_stats, *tracker;
871 struct Sana2PacketTypeStats *stats;
873 unit = (APTR)request->ios2_Req.io_Unit;
874 packet_type = request->ios2_PacketType;
876 /* Get global tracker and initial figures */
878 tracker = FindTypeStats(unit, &unit->type_trackers, packet_type, base);
879 opener = request->ios2_BufferManagement;
880 initial_stats = FindTypeStats(unit, &opener->initial_stats, packet_type,
881 base);
883 /* Copy and adjust figures */
885 if(initial_stats != NULL)
887 stats = request->ios2_StatData;
888 CopyMem(&tracker->stats, stats, sizeof(struct Sana2PacketTypeStats));
889 stats->PacketsSent -= initial_stats->stats.PacketsSent;
890 stats->PacketsReceived -= initial_stats->stats.PacketsReceived;
891 stats->BytesSent -= initial_stats->stats.BytesSent;
892 stats->BytesReceived -= initial_stats->stats.BytesReceived;
893 stats->PacketsDropped -= initial_stats->stats.PacketsDropped;
895 else
897 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
898 request->ios2_WireError = S2WERR_NOT_TRACKED;
901 /* Return */
903 return TRUE;
908 /****** etherlink3.device/S2_GETSPECIALSTATS *******************************
910 * NAME
911 * S2_GETSPECIALSTATS --
913 * FUNCTION
915 * INPUTS
916 * ios2_StatData - Pointer to Sana2SpecialStatHeader structure.
918 * RESULTS
919 * io_Error
920 * ios2_WireError
922 * EXAMPLE
924 * NOTES
926 * BUGS
928 * SEE ALSO
930 ****************************************************************************
934 static BOOL CmdGetSpecialStats(struct IOSana2Req *request,
935 struct DevBase *base)
937 struct DevUnit *unit;
938 UWORD i, stat_count;
939 struct Sana2SpecialStatHeader *header;
940 struct Sana2SpecialStatRecord *record;
942 /* Fill in stats */
944 unit = (APTR)request->ios2_Req.io_Unit;
945 header = request->ios2_StatData;
946 record = (APTR)(header + 1);
948 stat_count = header->RecordCountMax;
949 if(stat_count > STAT_COUNT)
950 stat_count = STAT_COUNT;
952 for(i = 0; i < stat_count; i++)
954 record->Type = (S2WireType_Ethernet << 16) + i;
955 record->Count = unit->special_stats[i];
956 record->String = special_stat_names[i];
957 record++;
960 header->RecordCountSupplied = stat_count;
962 /* Return */
964 return TRUE;
969 /****** etherlink3.device/S2_GETGLOBALSTATS ********************************
971 * NAME
972 * S2_GETGLOBALSTATS --
974 * FUNCTION
976 * INPUTS
977 * ios2_StatData - Pointer to Sana2DeviceStats structure.
979 * RESULTS
980 * io_Error
981 * ios2_WireError
983 * EXAMPLE
985 * NOTES
987 * BUGS
989 * SEE ALSO
991 ****************************************************************************
995 static BOOL CmdGetGlobalStats(struct IOSana2Req *request,
996 struct DevBase *base)
998 struct DevUnit *unit;
1000 /* Update and copy stats */
1002 unit = (APTR)request->ios2_Req.io_Unit;
1003 Disable();
1004 UpdateStats(unit, base);
1005 Enable();
1006 CopyMem(&unit->stats, request->ios2_StatData,
1007 sizeof(struct Sana2DeviceStats));
1009 /* Return */
1011 return TRUE;
1016 /****** etherlink3.device/S2_ONEVENT ***************************************
1018 * NAME
1019 * S2_ONEVENT --
1021 * FUNCTION
1023 * INPUTS
1024 * ios2_WireError
1026 * RESULTS
1027 * io_Error
1028 * ios2_WireError
1030 * EXAMPLE
1032 * NOTES
1034 * BUGS
1036 * SEE ALSO
1038 ****************************************************************************
1042 static BOOL CmdOnEvent(struct IOSana2Req *request, struct DevBase *base)
1044 struct DevUnit *unit;
1045 ULONG events, wanted_events;
1046 BOOL complete = FALSE;
1048 /* Check if we understand the event types */
1050 unit = (APTR)request->ios2_Req.io_Unit;
1051 wanted_events = request->ios2_WireError;
1052 if((wanted_events & ~KNOWN_EVENTS) != 0)
1054 request->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
1055 events = S2WERR_BAD_EVENT;
1057 else
1059 if((unit->flags & UNITF_ONLINE) != 0)
1060 events = S2EVENT_ONLINE;
1061 else
1062 events = S2EVENT_OFFLINE;
1064 events &= wanted_events;
1067 /* Reply request if a wanted event has already occurred */
1069 if(events != 0)
1071 request->ios2_WireError = events;
1072 complete = TRUE;
1074 else
1075 PutRequest(unit->request_ports[EVENT_QUEUE], (APTR)request, base);
1077 /* Return */
1079 return complete;
1084 /****** etherlink3.device/S2_READORPHAN ************************************
1086 * NAME
1087 * S2_READORPHAN --
1089 * FUNCTION
1091 * INPUTS
1092 * io_Flags
1093 * ios2_Data
1095 * RESULTS
1096 * io_Flags
1097 * io_Error
1098 * ios2_WireError
1099 * ios2_PacketType - A copy of the packet's type field.
1100 * ios2_SrcAddr
1101 * ios2_DstAddr
1102 * ios2_DataLength
1103 * ios2_Data
1106 * EXAMPLE
1108 * NOTES
1110 * BUGS
1112 * SEE ALSO
1114 ****************************************************************************
1118 static BOOL CmdReadOrphan(struct IOSana2Req *request,
1119 struct DevBase *base)
1121 struct DevUnit *unit;
1122 BYTE error = 0;
1123 ULONG wire_error;
1124 BOOL complete = FALSE;
1126 /* Check request is valid */
1128 unit = (APTR)request->ios2_Req.io_Unit;
1129 if((unit->flags & UNITF_ONLINE) == 0)
1131 error = S2ERR_OUTOFSERVICE;
1132 wire_error = S2WERR_UNIT_OFFLINE;
1135 /* Queue request */
1137 if(error == 0)
1138 PutRequest(unit->request_ports[ADOPT_QUEUE], (APTR)request, base);
1139 else
1141 request->ios2_Req.io_Error = error;
1142 request->ios2_WireError = wire_error;
1143 complete = TRUE;
1146 /* Return */
1148 return complete;
1153 /****** etherlink3.device/S2_ONLINE ****************************************
1155 * NAME
1156 * S2_ONLINE --
1158 * FUNCTION
1160 * INPUTS
1161 * None.
1163 * RESULTS
1164 * io_Error
1165 * ios2_WireError
1167 * EXAMPLE
1169 * NOTES
1171 * BUGS
1173 * SEE ALSO
1175 ****************************************************************************
1179 static BOOL CmdOnline(struct IOSana2Req *request, struct DevBase *base)
1181 struct DevUnit *unit;
1182 BYTE error = 0;
1183 ULONG wire_error;
1184 UWORD i;
1186 /* Check request is valid */
1188 unit = (APTR)request->ios2_Req.io_Unit;
1189 if((unit->flags & UNITF_CONFIGURED) == 0)
1191 error = S2ERR_BAD_STATE;
1192 wire_error = S2WERR_NOT_CONFIGURED;
1194 if((unit->flags & UNITF_HAVEADAPTER) == 0)
1196 error = S2ERR_OUTOFSERVICE;
1197 wire_error = S2WERR_RCVREL_HDW_ERR;
1200 /* Clear global and special stats and put adapter back online */
1202 if(error == 0 && (unit->flags & UNITF_ONLINE) == 0)
1204 unit->stats.PacketsReceived = 0;
1205 unit->stats.PacketsSent = 0;
1206 unit->stats.BadData = 0;
1207 unit->stats.Overruns = 0;
1208 unit->stats.UnknownTypesReceived = 0;
1209 unit->stats.Reconfigurations = 0;
1211 for(i = 0; i < STAT_COUNT; i++)
1212 unit->special_stats[i] = 0;
1214 GoOnline(unit, base);
1217 /* Return */
1219 request->ios2_Req.io_Error = error;
1220 request->ios2_WireError = wire_error;
1221 return TRUE;
1226 /****** etherlink3.device/S2_OFFLINE ***************************************
1228 * NAME
1229 * S2_OFFLINE --
1231 * FUNCTION
1233 * INPUTS
1234 * None.
1236 * RESULTS
1237 * io_Error
1238 * ios2_WireError
1240 * EXAMPLE
1242 * NOTES
1244 * BUGS
1246 * SEE ALSO
1248 ****************************************************************************
1252 static BOOL CmdOffline(struct IOSana2Req *request, struct DevBase *base)
1254 struct DevUnit *unit;
1256 /* Put adapter offline */
1258 unit = (APTR)request->ios2_Req.io_Unit;
1259 if((unit->flags & UNITF_ONLINE) != 0)
1260 GoOffline(unit, base);
1262 /* Return */
1264 return TRUE;
1269 /****** etherlink3.device/NSCMD_DEVICEQUERY ********************************
1271 * NAME
1272 * NSCMD_DEVICEQUERY -- Query device capabilities.
1274 * FUNCTION
1276 * INPUTS
1277 * io_Length - ???.
1278 * io_Data - pointer to NSDeviceQueryResult structure.
1280 * RESULTS
1281 * io_Error
1282 * io_Actual - size of structure device can handle.
1284 * EXAMPLE
1286 * NOTES
1288 * BUGS
1290 * SEE ALSO
1292 ****************************************************************************
1294 * Note that we have to pretend the request structure is an IOStdReq.
1298 static BOOL CmdDeviceQuery(struct IOStdReq *request,
1299 struct DevBase *base)
1301 struct NSDeviceQueryResult *info;
1303 /* Set structure size twice */
1305 info = request->io_Data;
1306 request->io_Actual = info->SizeAvailable =
1307 (ULONG)OFFSET(NSDeviceQueryResult, SupportedCommands) + sizeof(APTR);
1309 /* Report device details */
1311 info->DeviceType = NSDEVTYPE_SANA2;
1312 info->DeviceSubType = 0;
1314 info->SupportedCommands = (APTR)supported_commands;
1316 /* Return */
1318 return TRUE;
1323 /****** etherlink3.device/S2_ADDMULTICASTADDRESS ***************************
1325 * NAME
1326 * S2_ADDMULTICASTADDRESS --
1328 * FUNCTION
1330 * INPUTS
1331 * ios2_SrcAddr - multicast address.
1333 * RESULTS
1334 * io_Error
1335 * ios2_WireError
1337 * EXAMPLE
1339 * NOTES
1341 * BUGS
1343 * SEE ALSO
1345 ****************************************************************************
1349 /****** etherlink3.device/S2_ADDMULTICASTADDRESSES *************************
1351 * NAME
1352 * S2_ADDMULTICASTADDRESSES --
1354 * FUNCTION
1356 * INPUTS
1357 * ios2_SrcAddr - lower bound.
1358 * ios2_DstAddr - upper bound.
1360 * RESULTS
1361 * io_Error
1362 * ios2_WireError
1364 * EXAMPLE
1366 * NOTES
1368 * BUGS
1370 * SEE ALSO
1372 ****************************************************************************
1376 static BOOL CmdAddMulticastAddresses(struct IOSana2Req *request,
1377 struct DevBase *base)
1379 struct DevUnit *unit;
1380 UBYTE *lower_bound, *upper_bound;
1382 unit = (APTR)request->ios2_Req.io_Unit;
1384 lower_bound = request->ios2_SrcAddr;
1385 if(request->ios2_Req.io_Command == S2_ADDMULTICASTADDRESS)
1386 upper_bound = lower_bound;
1387 else
1388 upper_bound = request->ios2_DstAddr;
1390 if(!AddMulticastRange(unit, lower_bound, upper_bound, base))
1392 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1393 request->ios2_WireError = S2WERR_GENERIC_ERROR;
1396 /* Return */
1398 return TRUE;
1403 /****** etherlink3.device/S2_DELMULTICASTADDRESS ***************************
1405 * NAME
1406 * S2_DELMULTICASTADDRESS --
1408 * FUNCTION
1410 * INPUTS
1411 * ios2_SrcAddr - multicast address.
1413 * RESULTS
1414 * io_Error
1415 * ios2_WireError
1417 * EXAMPLE
1419 * NOTES
1421 * BUGS
1423 * SEE ALSO
1425 ****************************************************************************
1429 /****** etherlink3.device/S2_DELMULTICASTADDRESSES *************************
1431 * NAME
1432 * S2_DELMULTICASTADDRESSES --
1434 * FUNCTION
1436 * INPUTS
1437 * ios2_SrcAddr - lower bound.
1438 * ios2_DstAddr - upper bound.
1440 * RESULTS
1441 * io_Error
1442 * ios2_WireError
1444 * EXAMPLE
1446 * NOTES
1448 * BUGS
1450 * SEE ALSO
1452 ****************************************************************************
1456 static BOOL CmdDelMulticastAddresses(struct IOSana2Req *request,
1457 struct DevBase *base)
1459 struct DevUnit *unit;
1460 UBYTE *lower_bound, *upper_bound;
1462 unit = (APTR)request->ios2_Req.io_Unit;
1464 lower_bound = request->ios2_SrcAddr;
1465 if(request->ios2_Req.io_Command == S2_DELMULTICASTADDRESS)
1466 upper_bound = lower_bound;
1467 else
1468 upper_bound = request->ios2_DstAddr;
1470 if(!RemMulticastRange(unit, lower_bound, upper_bound, base))
1472 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
1473 request->ios2_WireError = S2WERR_BAD_MULTICAST;
1476 /* Return */
1478 return TRUE;
1483 /****i* etherlink3.device/PutRequest ***************************************
1485 * NAME
1486 * PutRequest -- .
1488 * SYNOPSIS
1489 * PutRequest(port, request)
1491 * VOID PutRequest(struct MsgPort *, struct IORequest *);
1493 * FUNCTION
1495 * INPUTS
1496 * port
1497 * request
1499 * RESULT
1500 * None.
1502 * EXAMPLE
1504 * NOTES
1506 * BUGS
1508 * SEE ALSO
1510 ****************************************************************************
1514 VOID PutRequest(struct MsgPort *port, struct IORequest *request,
1515 struct DevBase *base)
1517 request->io_Flags &= ~IOF_QUICK;
1518 PutMsg(port, (APTR)request);
1520 return;