Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / emac / handler.c
blob6c40a59ae674c481c38e5125c458a58c4e1e4d56
1 /*
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful, but
8 WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
15 MA 02111-1307, USA.
18 #define DEBUG 1
19 #include <aros/debug.h>
21 #include <exec/types.h>
22 #include <exec/resident.h>
23 #include <exec/io.h>
24 #include <exec/ports.h>
25 #include <exec/errors.h>
27 #include <devices/sana2.h>
28 #include <devices/sana2specialstats.h>
29 #include <devices/newstyle.h>
31 #include <utility/utility.h>
32 #include <utility/tagitem.h>
33 #include <utility/hooks.h>
35 #include <proto/exec.h>
36 #include <proto/dos.h>
37 #include <proto/battclock.h>
39 #include <stdlib.h>
41 #include "emac.h"
42 #include LC_LIBDEFS_FILE
44 #define KNOWN_EVENTS \
45 (S2EVENT_ERROR | S2EVENT_TX | S2EVENT_RX | S2EVENT_ONLINE \
46 | S2EVENT_OFFLINE | S2EVENT_BUFF | S2EVENT_HARDWARE | S2EVENT_SOFTWARE)
48 static BOOL CmdInvalid(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
49 static BOOL CmdRead(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
50 static BOOL CmdWrite(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
51 static BOOL CmdFlush(LIBBASETYPEPTR LIBBASE, struct IORequest *request);
52 static BOOL CmdS2DeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
53 static BOOL CmdGetStationAddress(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
54 static BOOL CmdConfigInterface(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
55 static BOOL CmdBroadcast(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
56 static BOOL CmdTrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
57 static BOOL CmdUntrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
58 static BOOL CmdGetTypeStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
59 static BOOL CmdGetGlobalStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
60 static BOOL CmdDeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOStdReq *request);
61 static BOOL CmdOnEvent(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
62 static BOOL CmdReadOrphan(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
63 static BOOL CmdOnline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
64 static BOOL CmdOffline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
65 static BOOL CmdAddMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
66 static BOOL CmdDelMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
68 static const UWORD supported_commands[] =
70 CMD_READ,
71 CMD_WRITE,
72 CMD_FLUSH,
73 S2_DEVICEQUERY,
74 S2_GETSTATIONADDRESS,
75 S2_CONFIGINTERFACE,
76 S2_ADDMULTICASTADDRESS,
77 S2_DELMULTICASTADDRESS,
78 S2_MULTICAST,
79 S2_BROADCAST,
80 S2_TRACKTYPE,
81 S2_UNTRACKTYPE,
82 S2_GETTYPESTATS,
83 // S2_GETSPECIALSTATS,
84 S2_GETGLOBALSTATS,
85 S2_ONEVENT,
86 S2_READORPHAN,
87 S2_ONLINE,
88 S2_OFFLINE,
89 NSCMD_DEVICEQUERY,
90 S2_ADDMULTICASTADDRESSES,
91 S2_DELMULTICASTADDRESSES,
95 void handle_request(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
97 BOOL complete;
99 switch(request->ios2_Req.io_Command)
101 case CMD_READ:
102 complete = CmdRead(LIBBASE, request);
103 break;
105 case CMD_WRITE:
106 case S2_MULTICAST:
107 complete = CmdWrite(LIBBASE, request);
108 break;
110 case CMD_FLUSH:
111 complete = CmdFlush(LIBBASE, (struct IORequest *)request);
112 break;
114 case S2_DEVICEQUERY:
115 complete = CmdS2DeviceQuery(LIBBASE, request);
116 break;
118 case S2_GETSTATIONADDRESS:
119 complete = CmdGetStationAddress(LIBBASE, request);
120 break;
122 case S2_CONFIGINTERFACE:
123 complete = CmdConfigInterface(LIBBASE, request);
124 break;
126 case S2_BROADCAST:
127 complete = CmdBroadcast(LIBBASE, request);
128 break;
130 case S2_TRACKTYPE:
131 complete = CmdTrackType(LIBBASE, request);
132 break;
134 case S2_UNTRACKTYPE:
135 complete = CmdUntrackType(LIBBASE, request);
136 break;
138 case S2_GETTYPESTATS:
139 complete = CmdGetTypeStats(LIBBASE, request);
140 break;
142 case S2_GETGLOBALSTATS:
143 complete = CmdGetGlobalStats(LIBBASE, request);
144 break;
146 case S2_ONEVENT:
147 complete = CmdOnEvent(LIBBASE, request);
148 break;
150 case S2_READORPHAN:
151 complete = CmdReadOrphan(LIBBASE, request);
152 break;
154 case S2_ONLINE:
155 complete = CmdOnline(LIBBASE, request);
156 break;
158 case S2_OFFLINE:
159 complete = CmdOffline(LIBBASE, request);
160 break;
162 case S2_ADDMULTICASTADDRESS:
163 case S2_ADDMULTICASTADDRESSES:
164 complete = CmdAddMulticastAddresses(LIBBASE, request);
165 break;
167 case S2_DELMULTICASTADDRESS:
168 case S2_DELMULTICASTADDRESSES:
169 complete = CmdDelMulticastAddresses(LIBBASE, request);
170 break;
172 case NSCMD_DEVICEQUERY:
173 complete = CmdDeviceQuery(LIBBASE, (struct IOStdReq *)request);
174 break;
176 default:
177 complete = CmdInvalid(LIBBASE, request);
180 if(complete && (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
181 ReplyMsg((APTR)request);
183 ReleaseSemaphore(&((struct EMACUnit *)request->ios2_Req.io_Unit)->eu_Lock);
186 static BOOL CmdInvalid(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
188 request->ios2_Req.io_Error = IOERR_NOCMD;
189 request->ios2_WireError = S2WERR_GENERIC_ERROR;
191 return TRUE;
194 static BOOL CmdRead(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
196 struct EMACUnit *unit;
197 struct Opener *opener;
198 BOOL complete = FALSE;
200 unit = (APTR)request->ios2_Req.io_Unit;
202 D(bug("[EMAC%d] S2CmdRead()\n", unit->eu_UnitNum));
204 if((unit->eu_Flags & IFF_UP) != 0)
206 opener = request->ios2_BufferManagement;
207 request->ios2_Req.io_Flags &= ~IOF_QUICK;
208 PutMsg(&opener->read_port, (struct Message *)request);
210 else
212 request->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
213 request->ios2_WireError = S2WERR_UNIT_OFFLINE;
214 complete = TRUE;
217 /* Return */
219 return complete;
222 static BOOL CmdWrite(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
224 struct EMACUnit *unit;
225 BYTE error = 0;
226 ULONG wire_error = S2WERR_GENERIC_ERROR;
227 BOOL complete = FALSE;
229 /* Check request is valid */
231 unit = (APTR)request->ios2_Req.io_Unit;
233 D(bug("[EMAC%d] S2CmdWrite()\n", unit->eu_UnitNum));
235 if((unit->eu_Flags & IFF_UP) == 0)
237 error = S2ERR_OUTOFSERVICE;
238 wire_error = S2WERR_UNIT_OFFLINE;
240 else if((request->ios2_Req.io_Command == S2_MULTICAST) &&
241 ((request->ios2_DstAddr[0] & 0x1) == 0))
243 error = S2ERR_BAD_ADDRESS;
244 wire_error = S2WERR_BAD_MULTICAST;
247 /* Queue request for sending */
249 if(error == 0) {
250 request->ios2_Req.io_Flags &= ~IOF_QUICK;
251 PutMsg(unit->eu_RequestPorts[WRITE_QUEUE], (APTR)request);
253 else
255 request->ios2_Req.io_Error = error;
256 request->ios2_WireError = wire_error;
257 complete = TRUE;
260 /* Return */
262 return complete;
265 static BOOL CmdFlush(LIBBASETYPEPTR LIBBASE, struct IORequest *request)
267 // TODO: Implement CmdFlush!!!!!!!!!
268 // FlushUnit(LIBBASE, (APTR)request->io_Unit, EVENT_QUEUE, IOERR_ABORTED);
269 return TRUE;
272 static BOOL CmdS2DeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
274 struct EMACUnit *unit = (APTR)request->ios2_Req.io_Unit;
275 //struct fe_priv *np = unit->pcnu_fe_priv;
276 struct Sana2DeviceQuery *info;
277 ULONG size_available, size;
279 D(bug("[EMAC%d] S2CmdDeviceQuery()\n", unit->eu_UnitNum));
281 /* Copy device info */
283 info = request->ios2_StatData;
284 size = size_available = info->SizeAvailable;
285 if(size > sizeof(struct Sana2DeviceQuery))
286 size = sizeof(struct Sana2DeviceQuery);
288 CopyMem(&LIBBASE->emb_Sana2Info, info, size);
290 info->BPS = 100000000;
291 info->MTU = ETH_MTU;
292 info->HardwareType = S2WireType_Ethernet;
293 info->SizeAvailable = size_available;
294 info->SizeSupplied = size;
296 /* Return */
298 return TRUE;
301 static BOOL CmdGetStationAddress(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
303 struct EMACUnit *unit;
305 /* Copy addresses */
307 unit = (APTR)request->ios2_Req.io_Unit;
309 D(bug("[EMAC%d] S2CmdGetStationAddress()\n", unit->eu_UnitNum));
311 CopyMem(unit->eu_DevAddr, request->ios2_SrcAddr, ETH_ADDRESSSIZE);
312 CopyMem(unit->eu_OrgAddr, request->ios2_DstAddr, ETH_ADDRESSSIZE);
314 /* Return */
316 return TRUE;
319 static BOOL CmdConfigInterface(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
321 struct EMACUnit *unit;
323 /* Configure adapter */
325 unit = (APTR)request->ios2_Req.io_Unit;
327 D(bug("[EMAC%d] S2CmdConfigInterface()\n", unit->eu_UnitNum));
329 if((unit->eu_Flags & IFF_CONFIGURED) == 0)
331 CopyMem(request->ios2_SrcAddr, unit->eu_DevAddr, ETH_ADDRESSSIZE);
332 unit->set_mac_address(unit);
333 unit->eu_Flags |= IFF_CONFIGURED;
335 else
337 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
338 request->ios2_WireError = S2WERR_IS_CONFIGURED;
341 /* Return */
343 return TRUE;
346 static BOOL CmdBroadcast(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
348 /* Fill in the broadcast address as destination */
350 *((ULONG *)request->ios2_DstAddr) = 0xffffffff;
351 *((UWORD *)(request->ios2_DstAddr + 4)) = 0xffff;
353 /* Queue the write as normal */
355 return CmdWrite(LIBBASE, request);
358 static BOOL CmdTrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
360 struct EMACUnit *unit;
361 struct Opener *opener;
362 ULONG packet_type, wire_error=0;
363 struct TypeTracker *tracker;
364 struct TypeStats *initial_stats;
365 BYTE error = 0;
367 unit = (APTR)request->ios2_Req.io_Unit;
369 D(bug("[EMAC%d] S2CmdTrackType(%d)\n", unit->eu_UnitNum, request->ios2_PacketType));
371 packet_type = request->ios2_PacketType;
373 /* Get global tracker */
374 tracker = (struct TypeTracker *)
375 FindTypeStats(LIBBASE, unit, &unit->eu_TypeTrackers, packet_type);
377 if(tracker != NULL)
378 tracker->user_count++;
379 else
381 tracker =
382 AllocMem(sizeof(struct TypeTracker), MEMF_PUBLIC|MEMF_CLEAR);
383 if(tracker != NULL)
385 tracker->packet_type = packet_type;
386 tracker->user_count = 1;
388 Disable();
389 AddTail((APTR)&unit->eu_TypeTrackers, (APTR)tracker);
390 Enable();
394 /* Store initial figures for this opener */
396 opener = request->ios2_BufferManagement;
397 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
398 if(initial_stats != NULL)
400 error = S2ERR_BAD_STATE;
401 wire_error = S2WERR_ALREADY_TRACKED;
404 if(error == 0)
406 initial_stats = AllocMem(sizeof(struct TypeStats), MEMF_PUBLIC);
407 if(initial_stats == NULL)
409 error = S2ERR_NO_RESOURCES;
410 wire_error = S2WERR_GENERIC_ERROR;
414 if(error == 0)
416 CopyMem(tracker, initial_stats, sizeof(struct TypeStats));
417 AddTail((APTR)&opener->initial_stats, (APTR)initial_stats);
420 /* Return */
422 request->ios2_Req.io_Error = error;
423 request->ios2_WireError = wire_error;
424 return TRUE;
427 static BOOL CmdUntrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
429 struct EMACUnit *unit;
430 struct Opener *opener;
431 ULONG packet_type;
432 struct TypeTracker *tracker;
433 struct TypeStats *initial_stats;
435 unit = (APTR)request->ios2_Req.io_Unit;
437 D(bug("[EMAC%d] S2CmdUntrackType()\n", unit->eu_UnitNum));
439 packet_type = request->ios2_PacketType;
441 /* Get global tracker and initial figures */
443 tracker = (struct TypeTracker *)
444 FindTypeStats(LIBBASE, unit, &unit->eu_TypeTrackers, packet_type);
445 opener = request->ios2_BufferManagement;
446 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
448 /* Decrement tracker usage and free unused structures */
450 if(initial_stats != NULL)
452 if((--tracker->user_count) == 0)
454 Disable();
455 Remove((APTR)tracker);
456 Enable();
457 FreeMem(tracker, sizeof(struct TypeTracker));
460 Remove((APTR)initial_stats);
461 FreeMem(initial_stats, sizeof(struct TypeStats));
463 else
465 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
466 request->ios2_WireError = S2WERR_NOT_TRACKED;
469 /* Return */
471 return TRUE;
474 static BOOL CmdGetTypeStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
476 struct EMACUnit *unit;
477 struct Opener *opener;
478 ULONG packet_type;
479 struct TypeStats *initial_stats, *tracker;
480 struct Sana2PacketTypeStats *stats;
482 unit = (APTR)request->ios2_Req.io_Unit;
484 D(bug("[EMAC%d] S2CmdGetTypeStats()\n", unit->eu_UnitNum));
486 packet_type = request->ios2_PacketType;
488 /* Get global tracker and initial figures */
490 tracker = FindTypeStats(LIBBASE, unit, &unit->eu_TypeTrackers, packet_type);
491 opener = request->ios2_BufferManagement;
492 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
494 /* Copy and adjust figures */
495 if(initial_stats != NULL)
497 stats = request->ios2_StatData;
498 CopyMem(&tracker->stats, stats, sizeof(struct Sana2PacketTypeStats));
499 stats->PacketsSent -= initial_stats->stats.PacketsSent;
500 stats->PacketsReceived -= initial_stats->stats.PacketsReceived;
501 stats->BytesSent -= initial_stats->stats.BytesSent;
502 stats->BytesReceived -= initial_stats->stats.BytesReceived;
503 stats->PacketsDropped -= initial_stats->stats.PacketsDropped;
505 else
507 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
508 request->ios2_WireError = S2WERR_NOT_TRACKED;
511 /* Return */
513 return TRUE;
516 static BOOL CmdGetGlobalStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
518 struct EMACUnit *unit;
520 /* Update and copy stats */
522 unit = (APTR)request->ios2_Req.io_Unit;
524 D(bug("[EMAC%d] S2CmdGetGlobalStats()\n", unit->eu_UnitNum));
526 CopyMem(&unit->eu_Stats, request->ios2_StatData,
527 sizeof(struct Sana2DeviceStats));
529 /* Return */
531 return TRUE;
534 static BOOL CmdDeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOStdReq *request)
536 struct NSDeviceQueryResult *info;
538 /* Set structure size twice */
540 info = request->io_Data;
541 request->io_Actual = info->SizeAvailable =
542 offsetof(struct NSDeviceQueryResult, SupportedCommands) + sizeof(APTR);
544 /* Report device details */
546 info->DeviceType = NSDEVTYPE_SANA2;
547 info->DeviceSubType = 0;
549 info->SupportedCommands = (APTR)supported_commands;
551 /* Return */
553 return TRUE;
557 static BOOL CmdOnEvent(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
559 struct EMACUnit *unit;
560 ULONG events, wanted_events;
561 BOOL complete = FALSE;
563 /* Check if we understand the event types */
565 unit = (struct EMACUnit *)request->ios2_Req.io_Unit;
567 D(bug("[EMAC%d] S2CmdOnEvent()\n", unit->eu_UnitNum));
569 wanted_events = request->ios2_WireError;
570 if((wanted_events & ~KNOWN_EVENTS) != 0)
572 request->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
573 events = S2WERR_BAD_EVENT;
575 else
577 if((unit->eu_Flags & IFF_UP) != 0)
578 events = S2EVENT_ONLINE;
579 else
580 events = S2EVENT_OFFLINE;
582 events &= wanted_events;
585 /* Reply request if a wanted event has already occurred */
587 if(events != 0)
589 request->ios2_WireError = events;
590 complete = TRUE;
592 else
594 request->ios2_Req.io_Flags &= ~IOF_QUICK;
595 PutMsg(unit->eu_RequestPorts[EVENT_QUEUE], (APTR)request);
598 /* Return */
600 return complete;
603 static BOOL CmdReadOrphan(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
605 struct EMACUnit *unit;
606 BYTE error = 0;
607 ULONG wire_error;
608 BOOL complete = FALSE;
610 /* Check request is valid */
612 unit = (struct EMACUnit *)request->ios2_Req.io_Unit;
614 D(bug("[EMAC%d] S2CmdReadOrphan()\n", unit->eu_UnitNum));
616 if((unit->eu_Flags & IFF_UP) == 0)
618 error = S2ERR_OUTOFSERVICE;
619 wire_error = S2WERR_UNIT_OFFLINE;
622 /* Queue request */
624 if(error == 0)
626 request->ios2_Req.io_Flags &= ~IOF_QUICK;
627 PutMsg(unit->eu_RequestPorts[ADOPT_QUEUE], (struct Message *)request);
629 else
631 request->ios2_Req.io_Error = error;
632 request->ios2_WireError = wire_error;
633 complete = TRUE;
636 /* Return */
638 return complete;
641 static BOOL CmdOnline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
643 struct EMACUnit *unit = (struct EMACUnit *)request->ios2_Req.io_Unit;
644 BYTE error = 0;
645 ULONG wire_error = 0;
646 UWORD i;
648 D(bug("[EMAC%d] S2CmdOnline()\n", unit->eu_UnitNum));
650 /* Check request is valid */
651 if((unit->eu_Flags & IFF_CONFIGURED) == 0)
653 error = S2ERR_BAD_STATE;
654 wire_error = S2WERR_NOT_CONFIGURED;
657 /* Clear global and special stats and put adapter back online */
659 if((error == 0) && ((unit->eu_Flags & IFF_UP) == 0))
661 unit->eu_Stats.PacketsReceived = 0;
662 unit->eu_Stats.PacketsSent = 0;
663 unit->eu_Stats.BadData = 0;
664 unit->eu_Stats.Overruns = 0;
665 unit->eu_Stats.UnknownTypesReceived = 0;
666 unit->eu_Stats.Reconfigurations = 0;
668 for(i = 0; i < STAT_COUNT; i++)
669 unit->eu_SpecialStats[i] = 0;
671 if (unit->start(unit)) {
672 error = S2ERR_OUTOFSERVICE;
673 wire_error = S2WERR_GENERIC_ERROR;
677 /* Return */
679 request->ios2_Req.io_Error = error;
680 request->ios2_WireError = wire_error;
681 return TRUE;
684 static BOOL CmdOffline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
686 struct EMACUnit *unit;
688 /* Put adapter offline */
690 unit = (APTR)request->ios2_Req.io_Unit;
692 D(bug("[EMAC%d] S2CmdOffline()\n", unit->eu_UnitNum));
694 if((unit->eu_Flags & IFF_UP) != 0)
695 unit->stop(unit);
697 /* Return */
698 return TRUE;
701 static BOOL CmdAddMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
703 struct EMACUnit *unit;
704 UBYTE *lower_bound, *upper_bound;
706 unit = (APTR)request->ios2_Req.io_Unit;
708 D(bug("[EMAC%d] S2CmdAddMulticastAddresses()\n", unit->eu_UnitNum));
710 lower_bound = request->ios2_SrcAddr;
711 if(request->ios2_Req.io_Command == S2_ADDMULTICASTADDRESS)
712 upper_bound = lower_bound;
713 else
714 upper_bound = request->ios2_DstAddr;
716 if(!AddMulticastRange(LIBBASE, unit, lower_bound, upper_bound))
718 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
719 request->ios2_WireError = S2WERR_GENERIC_ERROR;
722 /* Return */
724 return TRUE;
728 static BOOL CmdDelMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
730 struct EMACUnit *unit;
731 UBYTE *lower_bound, *upper_bound;
733 unit = (APTR)request->ios2_Req.io_Unit;
735 D(bug("[EMAC%d] S2CmdDelMulticastAddresses()\n", unit->eu_UnitNum));
737 lower_bound = request->ios2_SrcAddr;
738 if(request->ios2_Req.io_Command == S2_DELMULTICASTADDRESS)
739 upper_bound = lower_bound;
740 else
741 upper_bound = request->ios2_DstAddr;
743 if(!RemMulticastRange(LIBBASE, unit, lower_bound, upper_bound))
745 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
746 request->ios2_WireError = S2WERR_BAD_MULTICAST;
749 /* Return */
751 return TRUE;