Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / sis900 / handler.c
blobe2ecbd249001e5984d1b37ec800f48331759569c
1 /*
2 * $Id$
3 */
5 /*
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 MA 02111-1307, USA.
22 #include <exec/types.h>
23 #include <exec/resident.h>
24 #include <exec/io.h>
25 #include <exec/ports.h>
26 #include <exec/errors.h>
28 #include <devices/sana2.h>
29 #include <devices/sana2specialstats.h>
30 #include <devices/newstyle.h>
32 #include <utility/utility.h>
33 #include <utility/tagitem.h>
34 #include <utility/hooks.h>
36 #include <proto/exec.h>
37 #include <proto/dos.h>
38 #include <proto/battclock.h>
40 #include <stdlib.h>
42 #include "sis900.h"
43 #include "unit.h"
44 #include LC_LIBDEFS_FILE
46 #define KNOWN_EVENTS \
47 (S2EVENT_ERROR | S2EVENT_TX | S2EVENT_RX | S2EVENT_ONLINE \
48 | S2EVENT_OFFLINE | S2EVENT_BUFF | S2EVENT_HARDWARE | S2EVENT_SOFTWARE)
50 static BOOL CmdInvalid(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
51 static BOOL CmdRead(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
52 static BOOL CmdWrite(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
53 static BOOL CmdFlush(LIBBASETYPEPTR LIBBASE, struct IORequest *request);
54 static BOOL CmdS2DeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
55 static BOOL CmdGetStationAddress(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
56 static BOOL CmdConfigInterface(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
57 static BOOL CmdBroadcast(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
58 static BOOL CmdTrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
59 static BOOL CmdUntrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
60 static BOOL CmdGetTypeStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
61 static BOOL CmdGetGlobalStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
62 static BOOL CmdDeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOStdReq *request);
63 static BOOL CmdOnEvent(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
64 static BOOL CmdReadOrphan(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
65 static BOOL CmdOnline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
66 static BOOL CmdOffline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
67 static BOOL CmdAddMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
68 static BOOL CmdDelMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
70 static const UWORD supported_commands[] =
72 CMD_READ,
73 CMD_WRITE,
74 CMD_FLUSH,
75 S2_DEVICEQUERY,
76 S2_GETSTATIONADDRESS,
77 S2_CONFIGINTERFACE,
78 S2_ADDMULTICASTADDRESS,
79 S2_DELMULTICASTADDRESS,
80 S2_MULTICAST,
81 S2_BROADCAST,
82 S2_TRACKTYPE,
83 S2_UNTRACKTYPE,
84 S2_GETTYPESTATS,
85 // S2_GETSPECIALSTATS,
86 S2_GETGLOBALSTATS,
87 S2_ONEVENT,
88 S2_READORPHAN,
89 S2_ONLINE,
90 S2_OFFLINE,
91 NSCMD_DEVICEQUERY,
92 S2_ADDMULTICASTADDRESSES,
93 S2_DELMULTICASTADDRESSES,
97 void handle_request(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
99 BOOL complete;
101 switch(request->ios2_Req.io_Command)
103 case CMD_READ:
104 complete = CmdRead(LIBBASE, request);
105 break;
107 case CMD_WRITE:
108 case S2_MULTICAST:
109 complete = CmdWrite(LIBBASE, request);
110 break;
112 case CMD_FLUSH:
113 complete = CmdFlush(LIBBASE, (struct IORequest *)request);
114 break;
116 case S2_DEVICEQUERY:
117 complete = CmdS2DeviceQuery(LIBBASE, request);
118 break;
120 case S2_GETSTATIONADDRESS:
121 complete = CmdGetStationAddress(LIBBASE, request);
122 break;
124 case S2_CONFIGINTERFACE:
125 complete = CmdConfigInterface(LIBBASE, request);
126 break;
128 case S2_BROADCAST:
129 complete = CmdBroadcast(LIBBASE, request);
130 break;
132 case S2_TRACKTYPE:
133 complete = CmdTrackType(LIBBASE, request);
134 break;
136 case S2_UNTRACKTYPE:
137 complete = CmdUntrackType(LIBBASE, request);
138 break;
140 case S2_GETTYPESTATS:
141 complete = CmdGetTypeStats(LIBBASE, request);
142 break;
144 case S2_GETGLOBALSTATS:
145 complete = CmdGetGlobalStats(LIBBASE, request);
146 break;
148 case S2_ONEVENT:
149 complete = CmdOnEvent(LIBBASE, request);
150 break;
152 case S2_READORPHAN:
153 complete = CmdReadOrphan(LIBBASE, request);
154 break;
156 case S2_ONLINE:
157 complete = CmdOnline(LIBBASE, request);
158 break;
160 case S2_OFFLINE:
161 complete = CmdOffline(LIBBASE, request);
162 break;
164 case S2_ADDMULTICASTADDRESS:
165 case S2_ADDMULTICASTADDRESSES:
166 complete = CmdAddMulticastAddresses(LIBBASE, request);
167 break;
169 case S2_DELMULTICASTADDRESS:
170 case S2_DELMULTICASTADDRESSES:
171 complete = CmdDelMulticastAddresses(LIBBASE, request);
172 break;
174 case NSCMD_DEVICEQUERY:
175 complete = CmdDeviceQuery(LIBBASE, (struct IOStdReq *)request);
176 break;
178 default:
179 complete = CmdInvalid(LIBBASE, request);
182 if(complete && (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
183 ReplyMsg((APTR)request);
185 ReleaseSemaphore(&((struct SiS900Unit *)request->ios2_Req.io_Unit)->sis900u_unit_lock);
188 static BOOL CmdInvalid(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
190 request->ios2_Req.io_Error = IOERR_NOCMD;
191 request->ios2_WireError = S2WERR_GENERIC_ERROR;
193 return TRUE;
196 static BOOL CmdRead(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
198 struct SiS900Unit *unit;
199 struct Opener *opener;
200 BOOL complete = FALSE;
202 unit = (APTR)request->ios2_Req.io_Unit;
204 D(bug("[%s]: S2CmdRead()\n", unit->sis900u_name));
206 if((unit->sis900u_ifflags & IFF_UP) != 0)
208 opener = request->ios2_BufferManagement;
209 request->ios2_Req.io_Flags &= ~IOF_QUICK;
210 PutMsg(&opener->read_port, (struct Message *)request);
212 else
214 request->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
215 request->ios2_WireError = S2WERR_UNIT_OFFLINE;
216 complete = TRUE;
219 /* Return */
221 return complete;
224 static BOOL CmdWrite(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
226 struct SiS900Unit *unit;
227 BYTE error = 0;
228 ULONG wire_error = S2WERR_GENERIC_ERROR;
229 BOOL complete = FALSE;
231 /* Check request is valid */
233 unit = (APTR)request->ios2_Req.io_Unit;
235 D(bug("[%s]: S2CmdWrite()\n", unit->sis900u_name));
237 if((unit->sis900u_ifflags & IFF_UP) == 0)
239 error = S2ERR_OUTOFSERVICE;
240 wire_error = S2WERR_UNIT_OFFLINE;
242 else if((request->ios2_Req.io_Command == S2_MULTICAST) &&
243 ((request->ios2_DstAddr[0] & 0x1) == 0))
245 error = S2ERR_BAD_ADDRESS;
246 wire_error = S2WERR_BAD_MULTICAST;
249 /* Queue request for sending */
251 if(error == 0) {
252 request->ios2_Req.io_Flags &= ~IOF_QUICK;
253 PutMsg(unit->sis900u_request_ports[WRITE_QUEUE], (APTR)request);
255 else
257 request->ios2_Req.io_Error = error;
258 request->ios2_WireError = wire_error;
259 complete = TRUE;
262 /* Return */
264 return complete;
267 static BOOL CmdFlush(LIBBASETYPEPTR LIBBASE, struct IORequest *request)
269 FlushUnit(LIBBASE, (APTR)request->io_Unit, EVENT_QUEUE, IOERR_ABORTED);
270 return TRUE;
273 static BOOL CmdS2DeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
275 struct SiS900Unit *unit = (APTR)request->ios2_Req.io_Unit;
276 // struct fe_priv *np = unit->sis900u_fe_priv;
277 struct Sana2DeviceQuery *info;
278 ULONG size_available, size, status;
279 int i = 0;
281 D(bug("[%s]: S2CmdDeviceQuery()\n", unit->sis900u_name));
283 /* STSOUT register is Latched on Transition, read operation updates it */
284 while (i++ < 2)
285 status = mdio_read(unit, unit->cur_phy, MII_STSOUT);
287 D(bug("[%s]: S2CmdDeviceQuery: PHY status %x\n", unit->sis900u_name, status));
289 /* Copy device info */
290 info = request->ios2_StatData;
291 size = size_available = info->SizeAvailable;
292 if(size > sizeof(struct Sana2DeviceQuery))
293 size = sizeof(struct Sana2DeviceQuery);
295 CopyMem(&unit->sis900u_Sana2Info, info, size);
297 if (status & MII_STSOUT_SPD)
298 info->BPS = 100000000;
299 else
300 info->BPS = 10000000;
302 info->MTU = unit->sis900u_mtu;
303 info->HardwareType = S2WireType_Ethernet;
304 info->SizeAvailable = size_available;
305 info->SizeSupplied = size;
307 /* Return */
309 return TRUE;
312 static BOOL CmdGetStationAddress(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
314 struct SiS900Unit *unit;
316 /* Copy addresses */
318 unit = (APTR)request->ios2_Req.io_Unit;
320 D(bug("[%s]: S2CmdGetStationAddress()\n", unit->sis900u_name));
322 CopyMem(unit->sis900u_dev_addr, request->ios2_SrcAddr, ETH_ADDRESSSIZE);
323 CopyMem(unit->sis900u_org_addr, request->ios2_DstAddr, ETH_ADDRESSSIZE);
325 /* Return */
327 return TRUE;
330 static BOOL CmdConfigInterface(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
332 struct SiS900Unit *unit;
334 /* Configure adapter */
336 unit = (APTR)request->ios2_Req.io_Unit;
338 D(bug("[%s]: S2CmdConfigInterface()\n", unit->sis900u_name));
340 if((unit->sis900u_ifflags & IFF_CONFIGURED) == 0)
342 CopyMem(request->ios2_SrcAddr, unit->sis900u_dev_addr, ETH_ADDRESSSIZE);
343 sis900func_set_mac(unit);
344 unit->sis900u_ifflags |= IFF_CONFIGURED;
346 else
348 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
349 request->ios2_WireError = S2WERR_IS_CONFIGURED;
352 /* Return */
354 return TRUE;
357 static BOOL CmdBroadcast(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
359 /* Fill in the broadcast address as destination */
361 *((ULONG *)request->ios2_DstAddr) = 0xffffffff;
362 *((UWORD *)(request->ios2_DstAddr + 4)) = 0xffff;
364 /* Queue the write as normal */
366 return CmdWrite(LIBBASE, request);
369 static BOOL CmdTrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
371 struct SiS900Unit *unit;
372 struct Opener *opener;
373 ULONG packet_type, wire_error=0;
374 struct TypeTracker *tracker;
375 struct TypeStats *initial_stats;
376 BYTE error = 0;
378 unit = (APTR)request->ios2_Req.io_Unit;
380 D(bug("[%s]: S2CmdTrackType()\n", unit->sis900u_name));
382 packet_type = request->ios2_PacketType;
384 /* Get global tracker */
386 tracker = (struct TypeTracker *)
387 FindTypeStats(LIBBASE, unit, &unit->sis900u_type_trackers, packet_type);
389 if(tracker != NULL)
390 tracker->user_count++;
391 else
393 tracker =
394 AllocMem(sizeof(struct TypeTracker), MEMF_PUBLIC|MEMF_CLEAR);
395 if(tracker != NULL)
397 tracker->packet_type = packet_type;
398 tracker->user_count = 1;
400 Disable();
401 AddTail((APTR)&unit->sis900u_type_trackers, (APTR)tracker);
402 Enable();
406 /* Store initial figures for this opener */
408 opener = request->ios2_BufferManagement;
409 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
411 if(initial_stats != NULL)
413 error = S2ERR_BAD_STATE;
414 wire_error = S2WERR_ALREADY_TRACKED;
417 if(error == 0)
419 initial_stats = AllocMem(sizeof(struct TypeStats), MEMF_PUBLIC);
420 if(initial_stats == NULL)
422 error = S2ERR_NO_RESOURCES;
423 wire_error = S2WERR_GENERIC_ERROR;
427 if(error == 0)
429 CopyMem(tracker, initial_stats, sizeof(struct TypeStats));
430 AddTail((APTR)&opener->initial_stats, (APTR)initial_stats);
433 /* Return */
435 request->ios2_Req.io_Error = error;
436 request->ios2_WireError = wire_error;
437 return TRUE;
440 static BOOL CmdUntrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
442 struct SiS900Unit *unit;
443 struct Opener *opener;
444 ULONG packet_type;
445 struct TypeTracker *tracker;
446 struct TypeStats *initial_stats;
448 unit = (APTR)request->ios2_Req.io_Unit;
450 D(bug("[%s]: S2CmdUntrackType()\n", unit->sis900u_name));
452 packet_type = request->ios2_PacketType;
454 /* Get global tracker and initial figures */
456 tracker = (struct TypeTracker *)
457 FindTypeStats(LIBBASE, unit, &unit->sis900u_type_trackers, packet_type);
458 opener = request->ios2_BufferManagement;
459 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
461 /* Decrement tracker usage and free unused structures */
463 if(initial_stats != NULL)
465 if((--tracker->user_count) == 0)
467 Disable();
468 Remove((APTR)tracker);
469 Enable();
470 FreeMem(tracker, sizeof(struct TypeTracker));
473 Remove((APTR)initial_stats);
474 FreeMem(initial_stats, sizeof(struct TypeStats));
476 else
478 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
479 request->ios2_WireError = S2WERR_NOT_TRACKED;
482 /* Return */
484 return TRUE;
487 static BOOL CmdGetTypeStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
489 struct SiS900Unit *unit;
490 struct Opener *opener;
491 ULONG packet_type;
492 struct TypeStats *initial_stats, *tracker;
493 struct Sana2PacketTypeStats *stats;
495 unit = (APTR)request->ios2_Req.io_Unit;
497 D(bug("[%s]: S2CmdGetTypeStats()\n", unit->sis900u_name));
499 packet_type = request->ios2_PacketType;
501 /* Get global tracker and initial figures */
503 tracker = FindTypeStats(LIBBASE, unit, &unit->sis900u_type_trackers, packet_type);
504 opener = request->ios2_BufferManagement;
505 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
507 /* Copy and adjust figures */
508 if(initial_stats != NULL)
510 stats = request->ios2_StatData;
511 CopyMem(&tracker->stats, stats, sizeof(struct Sana2PacketTypeStats));
512 stats->PacketsSent -= initial_stats->stats.PacketsSent;
513 stats->PacketsReceived -= initial_stats->stats.PacketsReceived;
514 stats->BytesSent -= initial_stats->stats.BytesSent;
515 stats->BytesReceived -= initial_stats->stats.BytesReceived;
516 stats->PacketsDropped -= initial_stats->stats.PacketsDropped;
518 else
520 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
521 request->ios2_WireError = S2WERR_NOT_TRACKED;
524 /* Return */
526 return TRUE;
529 static BOOL CmdGetGlobalStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
531 struct SiS900Unit *unit;
533 /* Update and copy stats */
535 unit = (APTR)request->ios2_Req.io_Unit;
537 D(bug("[%s]: S2CmdGetGlobalStats()\n", unit->sis900u_name));
539 CopyMem(&unit->sis900u_stats, request->ios2_StatData,
540 sizeof(struct Sana2DeviceStats));
542 /* Return */
544 return TRUE;
547 static BOOL CmdDeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOStdReq *request)
549 struct NSDeviceQueryResult *info;
551 /* Set structure size twice */
553 info = request->io_Data;
554 request->io_Actual = info->SizeAvailable =
555 offsetof(struct NSDeviceQueryResult, SupportedCommands) + sizeof(APTR);
557 /* Report device details */
559 info->DeviceType = NSDEVTYPE_SANA2;
560 info->DeviceSubType = 0;
562 info->SupportedCommands = (APTR)supported_commands;
564 /* Return */
566 return TRUE;
569 static BOOL CmdOnEvent(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
571 struct SiS900Unit *unit;
572 ULONG events, wanted_events;
573 BOOL complete = FALSE;
575 /* Check if we understand the event types */
577 unit = (APTR)request->ios2_Req.io_Unit;
579 D(bug("[%s]: S2CmdOnEvent()\n", unit->sis900u_name));
581 wanted_events = request->ios2_WireError;
582 if((wanted_events & ~KNOWN_EVENTS) != 0)
584 request->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
585 events = S2WERR_BAD_EVENT;
587 else
589 if((unit->sis900u_ifflags & IFF_UP) != 0)
590 events = S2EVENT_ONLINE;
591 else
592 events = S2EVENT_OFFLINE;
594 events &= wanted_events;
597 /* Reply request if a wanted event has already occurred */
599 if(events != 0)
601 request->ios2_WireError = events;
602 complete = TRUE;
604 else
606 request->ios2_Req.io_Flags &= ~IOF_QUICK;
607 PutMsg(unit->sis900u_request_ports[EVENT_QUEUE], (APTR)request);
610 /* Return */
612 return complete;
615 static BOOL CmdReadOrphan(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
617 struct SiS900Unit *unit;
618 BYTE error = 0;
619 ULONG wire_error;
620 BOOL complete = FALSE;
622 /* Check request is valid */
624 unit = (APTR)request->ios2_Req.io_Unit;
625 D(bug("[%s]: S2CmdReadOrphan()\n", unit->sis900u_name));
627 if((unit->sis900u_ifflags & IFF_UP) == 0)
629 error = S2ERR_OUTOFSERVICE;
630 wire_error = S2WERR_UNIT_OFFLINE;
633 /* Queue request */
635 if(error == 0)
637 request->ios2_Req.io_Flags &= ~IOF_QUICK;
638 PutMsg(unit->sis900u_request_ports[ADOPT_QUEUE], (struct Message *)request);
640 else
642 request->ios2_Req.io_Error = error;
643 request->ios2_WireError = wire_error;
644 complete = TRUE;
647 /* Return */
649 return complete;
652 static BOOL CmdOnline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
654 struct SiS900Unit *unit = (struct SiS900Unit *)request->ios2_Req.io_Unit;
655 BYTE error = 0;
656 ULONG wire_error = 0;
657 UWORD i;
659 D(bug("[%s]: S2CmdOnline()\n", unit->sis900u_name));
661 /* Check request is valid */
662 if((unit->sis900u_ifflags & IFF_CONFIGURED) == 0)
664 error = S2ERR_BAD_STATE;
665 wire_error = S2WERR_NOT_CONFIGURED;
668 /* Clear global and special stats and put adapter back online */
670 if((error == 0) && ((unit->sis900u_ifflags & IFF_UP) == 0))
672 unit->sis900u_stats.PacketsReceived = 0;
673 unit->sis900u_stats.PacketsSent = 0;
674 unit->sis900u_stats.BadData = 0;
675 unit->sis900u_stats.Overruns = 0;
676 unit->sis900u_stats.UnknownTypesReceived = 0;
677 unit->sis900u_stats.Reconfigurations = 0;
679 for(i = 0; i < SANA2_SPECIAL_STAT_COUNT; i++)
680 unit->sis900u_special_stats[i] = 0;
682 if (sis900func_open(unit)) {
683 error = S2ERR_OUTOFSERVICE;
684 wire_error = S2WERR_GENERIC_ERROR;
688 /* Return */
690 request->ios2_Req.io_Error = error;
691 request->ios2_WireError = wire_error;
692 return TRUE;
695 static BOOL CmdOffline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
697 struct SiS900Unit *unit;
699 /* Put adapter offline */
701 unit = (APTR)request->ios2_Req.io_Unit;
703 D(bug("[%s]: S2CmdOffline()\n", unit->sis900u_name));
705 if((unit->sis900u_ifflags & IFF_UP) != 0)
706 sis900func_close(unit);
708 /* Return */
709 return TRUE;
712 static BOOL CmdAddMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
714 struct SiS900Unit *unit;
715 UBYTE *lower_bound, *upper_bound;
717 unit = (APTR)request->ios2_Req.io_Unit;
719 D(bug("[%s]: S2CmdAddMulticastAddresses()\n", unit->sis900u_name));
721 lower_bound = request->ios2_SrcAddr;
722 if(request->ios2_Req.io_Command == S2_ADDMULTICASTADDRESS)
723 upper_bound = lower_bound;
724 else
725 upper_bound = request->ios2_DstAddr;
727 if(!AddMulticastRange(LIBBASE, unit, lower_bound, upper_bound))
729 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
730 request->ios2_WireError = S2WERR_GENERIC_ERROR;
733 /* Return */
735 return TRUE;
738 static BOOL CmdDelMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
740 struct SiS900Unit *unit;
741 UBYTE *lower_bound, *upper_bound;
743 unit = (APTR)request->ios2_Req.io_Unit;
745 D(bug("[%s]: S2CmdDelMulticastAddresses()\n", unit->sis900u_name));
747 lower_bound = request->ios2_SrcAddr;
748 if(request->ios2_Req.io_Command == S2_DELMULTICASTADDRESS)
749 upper_bound = lower_bound;
750 else
751 upper_bound = request->ios2_DstAddr;
753 if(!RemMulticastRange(LIBBASE, unit, lower_bound, upper_bound))
755 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
756 request->ios2_WireError = S2WERR_BAD_MULTICAST;
759 /* Return */
761 return TRUE;