Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / e1000 / handler.c
blobc25b21a87a84a2b9683ded014357ce59f7a51f4a
1 /*
2 * $Id$
3 */
4 /*
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.
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 "e1000_osdep.h"
42 #include "e1000.h"
43 #include "e1000_defines.h"
44 #include "e1000_api.h"
46 #include "unit.h"
47 #include LC_LIBDEFS_FILE
49 #define KNOWN_EVENTS \
50 (S2EVENT_ERROR | S2EVENT_TX | S2EVENT_RX | S2EVENT_ONLINE \
51 | S2EVENT_OFFLINE | S2EVENT_BUFF | S2EVENT_HARDWARE | S2EVENT_SOFTWARE)
53 static BOOL CmdInvalid(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
54 static BOOL CmdRead(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
55 static BOOL CmdWrite(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
56 static BOOL CmdFlush(LIBBASETYPEPTR LIBBASE, struct IORequest *request);
57 static BOOL CmdS2DeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
58 static BOOL CmdGetStationAddress(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
59 static BOOL CmdConfigInterface(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
60 static BOOL CmdBroadcast(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
61 static BOOL CmdTrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
62 static BOOL CmdUntrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
63 static BOOL CmdGetTypeStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
64 static BOOL CmdGetGlobalStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
65 static BOOL CmdDeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOStdReq *request);
66 static BOOL CmdOnEvent(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
67 static BOOL CmdReadOrphan(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
68 static BOOL CmdOnline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
69 static BOOL CmdOffline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
70 static BOOL CmdAddMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
71 static BOOL CmdDelMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request);
73 static const UWORD supported_commands[] =
75 CMD_READ,
76 CMD_WRITE,
77 CMD_FLUSH,
78 S2_DEVICEQUERY,
79 S2_GETSTATIONADDRESS,
80 S2_CONFIGINTERFACE,
81 S2_ADDMULTICASTADDRESS,
82 S2_DELMULTICASTADDRESS,
83 S2_MULTICAST,
84 S2_BROADCAST,
85 S2_TRACKTYPE,
86 S2_UNTRACKTYPE,
87 S2_GETTYPESTATS,
88 // S2_GETSPECIALSTATS,
89 S2_GETGLOBALSTATS,
90 S2_ONEVENT,
91 S2_READORPHAN,
92 S2_ONLINE,
93 S2_OFFLINE,
94 NSCMD_DEVICEQUERY,
95 S2_ADDMULTICASTADDRESSES,
96 S2_DELMULTICASTADDRESSES,
100 void handle_request(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
102 BOOL complete;
104 switch(request->ios2_Req.io_Command)
106 case CMD_READ:
107 complete = CmdRead(LIBBASE, request);
108 break;
110 case CMD_WRITE:
111 case S2_MULTICAST:
112 complete = CmdWrite(LIBBASE, request);
113 break;
115 case CMD_FLUSH:
116 complete = CmdFlush(LIBBASE, (struct IORequest *)request);
117 break;
119 case S2_DEVICEQUERY:
120 complete = CmdS2DeviceQuery(LIBBASE, request);
121 break;
123 case S2_GETSTATIONADDRESS:
124 complete = CmdGetStationAddress(LIBBASE, request);
125 break;
127 case S2_CONFIGINTERFACE:
128 complete = CmdConfigInterface(LIBBASE, request);
129 break;
131 case S2_BROADCAST:
132 complete = CmdBroadcast(LIBBASE, request);
133 break;
135 case S2_TRACKTYPE:
136 complete = CmdTrackType(LIBBASE, request);
137 break;
139 case S2_UNTRACKTYPE:
140 complete = CmdUntrackType(LIBBASE, request);
141 break;
143 case S2_GETTYPESTATS:
144 complete = CmdGetTypeStats(LIBBASE, request);
145 break;
147 case S2_GETGLOBALSTATS:
148 complete = CmdGetGlobalStats(LIBBASE, request);
149 break;
151 case S2_ONEVENT:
152 complete = CmdOnEvent(LIBBASE, request);
153 break;
155 case S2_READORPHAN:
156 complete = CmdReadOrphan(LIBBASE, request);
157 break;
159 case S2_ONLINE:
160 complete = CmdOnline(LIBBASE, request);
161 break;
163 case S2_OFFLINE:
164 complete = CmdOffline(LIBBASE, request);
165 break;
167 case S2_ADDMULTICASTADDRESS:
168 case S2_ADDMULTICASTADDRESSES:
169 complete = CmdAddMulticastAddresses(LIBBASE, request);
170 break;
172 case S2_DELMULTICASTADDRESS:
173 case S2_DELMULTICASTADDRESSES:
174 complete = CmdDelMulticastAddresses(LIBBASE, request);
175 break;
177 case NSCMD_DEVICEQUERY:
178 complete = CmdDeviceQuery(LIBBASE, (struct IOStdReq *)request);
179 break;
181 default:
182 complete = CmdInvalid(LIBBASE, request);
185 if(complete && (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
186 ReplyMsg((APTR)request);
188 ReleaseSemaphore(&((struct e1000Unit *)request->ios2_Req.io_Unit)->e1ku_unit_lock);
191 static BOOL CmdInvalid(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
193 request->ios2_Req.io_Error = IOERR_NOCMD;
194 request->ios2_WireError = S2WERR_GENERIC_ERROR;
196 return TRUE;
199 static BOOL CmdRead(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
201 struct e1000Unit *unit;
202 struct Opener *opener;
203 BOOL complete = FALSE;
205 unit = (APTR)request->ios2_Req.io_Unit;
207 D(bug("[%s]: CmdRead()\n", unit->e1ku_name));
209 if((unit->e1ku_ifflags & IFF_UP) != 0)
211 opener = request->ios2_BufferManagement;
212 request->ios2_Req.io_Flags &= ~IOF_QUICK;
213 PutMsg(&opener->read_port, (struct Message *)request);
215 else
217 request->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
218 request->ios2_WireError = S2WERR_UNIT_OFFLINE;
219 complete = TRUE;
222 /* Return */
224 return complete;
227 static BOOL CmdWrite(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
229 struct e1000Unit *unit;
230 BYTE error = 0;
231 ULONG wire_error = S2WERR_GENERIC_ERROR;
232 BOOL complete = FALSE;
234 /* Check request is valid */
236 unit = (APTR)request->ios2_Req.io_Unit;
238 D(bug("[%s]: CmdWrite()\n", unit->e1ku_name));
240 if((unit->e1ku_ifflags & IFF_UP) == 0)
242 error = S2ERR_OUTOFSERVICE;
243 wire_error = S2WERR_UNIT_OFFLINE;
245 else if((request->ios2_Req.io_Command == S2_MULTICAST) &&
246 ((request->ios2_DstAddr[0] & 0x1) == 0))
248 error = S2ERR_BAD_ADDRESS;
249 wire_error = S2WERR_BAD_MULTICAST;
252 /* Queue request for sending */
254 if(error == 0) {
255 request->ios2_Req.io_Flags &= ~IOF_QUICK;
256 PutMsg(unit->e1ku_request_ports[WRITE_QUEUE], (APTR)request);
258 else
260 request->ios2_Req.io_Error = error;
261 request->ios2_WireError = wire_error;
262 complete = TRUE;
265 /* Return */
267 return complete;
270 static BOOL CmdFlush(LIBBASETYPEPTR LIBBASE, struct IORequest *request)
272 FlushUnit(LIBBASE, (APTR)request->io_Unit, EVENT_QUEUE, IOERR_ABORTED);
273 return TRUE;
276 static BOOL CmdS2DeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
278 struct e1000Unit *unit = (APTR)request->ios2_Req.io_Unit;
279 struct Sana2DeviceQuery *info;
280 ULONG size_available, size;
281 UWORD lnk_speed = 0, lnk_duplex = 0;
282 D(bug("[%s]: CmdS2DeviceQuery()\n", unit->e1ku_name));
284 /* Copy device info */
285 info = request->ios2_StatData;
286 size = size_available = info->SizeAvailable;
287 if(size > sizeof(struct Sana2DeviceQuery))
288 size = sizeof(struct Sana2DeviceQuery);
290 CopyMem(&unit->e1ku_Sana2Info, info, size);
292 e1000_get_speed_and_duplex((struct e1000_hw *)unit->e1ku_Private00, &lnk_speed, &lnk_duplex);
294 info->BPS = (1000000 * lnk_speed);
295 info->MTU = unit->e1ku_mtu;
296 info->HardwareType = S2WireType_Ethernet;
297 info->SizeAvailable = size_available;
298 info->SizeSupplied = size;
300 /* Return */
302 return TRUE;
305 static BOOL CmdGetStationAddress(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
307 struct e1000Unit *unit;
309 /* Copy addresses */
311 unit = (APTR)request->ios2_Req.io_Unit;
313 D(bug("[%s]: CmdGetStationAddress()\n", unit->e1ku_name));
315 CopyMem(unit->e1ku_dev_addr, request->ios2_SrcAddr, ETH_ADDRESSSIZE);
316 CopyMem(unit->e1ku_org_addr, request->ios2_DstAddr, ETH_ADDRESSSIZE);
318 /* Return */
320 return TRUE;
323 static BOOL CmdConfigInterface(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
325 struct e1000Unit *unit;
327 /* Configure adapter */
329 unit = (APTR)request->ios2_Req.io_Unit;
331 D(bug("[%s]: CmdConfigInterface()\n", unit->e1ku_name));
333 if((unit->e1ku_ifflags & IFF_CONFIGURED) == 0)
335 CopyMem(request->ios2_SrcAddr, unit->e1ku_dev_addr, ETH_ADDRESSSIZE);
336 e1000func_set_mac(unit);
337 unit->e1ku_ifflags |= IFF_CONFIGURED;
339 else
341 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
342 request->ios2_WireError = S2WERR_IS_CONFIGURED;
345 /* Return */
347 return TRUE;
350 static BOOL CmdBroadcast(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
352 /* Fill in the broadcast address as destination */
354 *((ULONG *)request->ios2_DstAddr) = 0xffffffff;
355 *((UWORD *)(request->ios2_DstAddr + 4)) = 0xffff;
357 /* Queue the write as normal */
359 return CmdWrite(LIBBASE, request);
362 static BOOL CmdTrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
364 struct e1000Unit *unit;
365 struct Opener *opener;
366 ULONG packet_type, wire_error=0;
367 struct TypeTracker *tracker;
368 struct TypeStats *initial_stats;
369 BYTE error = 0;
371 unit = (APTR)request->ios2_Req.io_Unit;
373 D(bug("[%s]: CmdTrackType()\n", unit->e1ku_name));
375 packet_type = request->ios2_PacketType;
377 /* Get global tracker */
379 tracker = (struct TypeTracker *)
380 FindTypeStats(LIBBASE, unit, &unit->e1ku_type_trackers, packet_type);
382 if(tracker != NULL)
383 tracker->user_count++;
384 else
386 tracker =
387 AllocMem(sizeof(struct TypeTracker), MEMF_PUBLIC|MEMF_CLEAR);
388 if(tracker != NULL)
390 tracker->packet_type = packet_type;
391 tracker->user_count = 1;
393 Disable();
394 AddTail((APTR)&unit->e1ku_type_trackers, (APTR)tracker);
395 Enable();
399 /* Store initial figures for this opener */
401 opener = request->ios2_BufferManagement;
402 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
404 if(initial_stats != NULL)
406 error = S2ERR_BAD_STATE;
407 wire_error = S2WERR_ALREADY_TRACKED;
410 if(error == 0)
412 initial_stats = AllocMem(sizeof(struct TypeStats), MEMF_PUBLIC);
413 if(initial_stats == NULL)
415 error = S2ERR_NO_RESOURCES;
416 wire_error = S2WERR_GENERIC_ERROR;
420 if(error == 0)
422 CopyMem(tracker, initial_stats, sizeof(struct TypeStats));
423 AddTail((APTR)&opener->initial_stats, (APTR)initial_stats);
426 /* Return */
428 request->ios2_Req.io_Error = error;
429 request->ios2_WireError = wire_error;
430 return TRUE;
433 static BOOL CmdUntrackType(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
435 struct e1000Unit *unit;
436 struct Opener *opener;
437 ULONG packet_type;
438 struct TypeTracker *tracker;
439 struct TypeStats *initial_stats;
441 unit = (APTR)request->ios2_Req.io_Unit;
443 D(bug("[%s]: CmdUntrackType()\n", unit->e1ku_name));
445 packet_type = request->ios2_PacketType;
447 /* Get global tracker and initial figures */
449 tracker = (struct TypeTracker *)
450 FindTypeStats(LIBBASE, unit, &unit->e1ku_type_trackers, packet_type);
451 opener = request->ios2_BufferManagement;
452 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
454 /* Decrement tracker usage and free unused structures */
456 if(initial_stats != NULL)
458 if((--tracker->user_count) == 0)
460 Disable();
461 Remove((APTR)tracker);
462 Enable();
463 FreeMem(tracker, sizeof(struct TypeTracker));
466 Remove((APTR)initial_stats);
467 FreeMem(initial_stats, sizeof(struct TypeStats));
469 else
471 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
472 request->ios2_WireError = S2WERR_NOT_TRACKED;
475 /* Return */
477 return TRUE;
480 static BOOL CmdGetTypeStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
482 struct e1000Unit *unit;
483 struct Opener *opener;
484 ULONG packet_type;
485 struct TypeStats *initial_stats, *tracker;
486 struct Sana2PacketTypeStats *stats;
488 unit = (APTR)request->ios2_Req.io_Unit;
490 D(bug("[%s]: CmdGetTypeStats()\n", unit->e1ku_name));
492 packet_type = request->ios2_PacketType;
494 /* Get global tracker and initial figures */
496 tracker = FindTypeStats(LIBBASE, unit, &unit->e1ku_type_trackers, packet_type);
497 opener = request->ios2_BufferManagement;
498 initial_stats = FindTypeStats(LIBBASE, unit, &opener->initial_stats, packet_type);
500 /* Copy and adjust figures */
501 if(initial_stats != NULL)
503 stats = request->ios2_StatData;
504 CopyMem(&tracker->stats, stats, sizeof(struct Sana2PacketTypeStats));
505 stats->PacketsSent -= initial_stats->stats.PacketsSent;
506 stats->PacketsReceived -= initial_stats->stats.PacketsReceived;
507 stats->BytesSent -= initial_stats->stats.BytesSent;
508 stats->BytesReceived -= initial_stats->stats.BytesReceived;
509 stats->PacketsDropped -= initial_stats->stats.PacketsDropped;
511 else
513 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
514 request->ios2_WireError = S2WERR_NOT_TRACKED;
517 /* Return */
519 return TRUE;
522 static BOOL CmdGetGlobalStats(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
524 struct e1000Unit *unit;
526 /* Update and copy stats */
528 unit = (APTR)request->ios2_Req.io_Unit;
530 D(bug("[%s]: CmdGetGlobalStats()\n", unit->e1ku_name));
532 CopyMem(&unit->e1ku_stats, request->ios2_StatData,
533 sizeof(struct Sana2DeviceStats));
535 /* Return */
537 return TRUE;
540 static BOOL CmdDeviceQuery(LIBBASETYPEPTR LIBBASE, struct IOStdReq *request)
542 struct NSDeviceQueryResult *info;
544 /* Set structure size twice */
546 info = request->io_Data;
547 request->io_Actual = info->SizeAvailable =
548 offsetof(struct NSDeviceQueryResult, SupportedCommands) + sizeof(APTR);
550 /* Report device details */
552 info->DeviceType = NSDEVTYPE_SANA2;
553 info->DeviceSubType = 0;
555 info->SupportedCommands = (APTR)supported_commands;
557 /* Return */
559 return TRUE;
562 static BOOL CmdOnEvent(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
564 struct e1000Unit *unit;
565 ULONG events, wanted_events;
566 BOOL complete = FALSE;
568 /* Check if we understand the event types */
570 unit = (APTR)request->ios2_Req.io_Unit;
572 D(bug("[%s]: CmdOnEvent()\n", unit->e1ku_name));
574 wanted_events = request->ios2_WireError;
575 if((wanted_events & ~KNOWN_EVENTS) != 0)
577 request->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
578 events = S2WERR_BAD_EVENT;
580 else
582 if((unit->e1ku_ifflags & IFF_UP) != 0)
583 events = S2EVENT_ONLINE;
584 else
585 events = S2EVENT_OFFLINE;
587 events &= wanted_events;
590 /* Reply request if a wanted event has already occurred */
592 if(events != 0)
594 request->ios2_WireError = events;
595 complete = TRUE;
597 else
599 request->ios2_Req.io_Flags &= ~IOF_QUICK;
600 PutMsg(unit->e1ku_request_ports[EVENT_QUEUE], (APTR)request);
603 /* Return */
605 return complete;
608 static BOOL CmdReadOrphan(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
610 struct e1000Unit *unit;
611 BYTE error = 0;
612 ULONG wire_error;
613 BOOL complete = FALSE;
615 /* Check request is valid */
617 unit = (APTR)request->ios2_Req.io_Unit;
618 D(bug("[%s]: CmdReadOrphan()\n", unit->e1ku_name));
620 if((unit->e1ku_ifflags & IFF_UP) == 0)
622 error = S2ERR_OUTOFSERVICE;
623 wire_error = S2WERR_UNIT_OFFLINE;
626 /* Queue request */
628 if(error == 0)
630 request->ios2_Req.io_Flags &= ~IOF_QUICK;
631 PutMsg(unit->e1ku_request_ports[ADOPT_QUEUE], (struct Message *)request);
633 else
635 request->ios2_Req.io_Error = error;
636 request->ios2_WireError = wire_error;
637 complete = TRUE;
640 /* Return */
642 return complete;
645 static BOOL CmdOnline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
647 struct e1000Unit *unit = (struct e1000Unit *)request->ios2_Req.io_Unit;
648 ULONG wire_error = 0, rctl, tctl;
649 int i;
650 BYTE error = 0;
652 D(bug("[%s]: CmdOnline()\n", unit->e1ku_name));
654 /* Check request is valid */
655 if((unit->e1ku_ifflags & IFF_CONFIGURED) == 0)
657 error = S2ERR_BAD_STATE;
658 wire_error = S2WERR_NOT_CONFIGURED;
661 /* Clear global and special stats and put adapter back online */
663 if((error == 0) && ((unit->e1ku_ifflags & IFF_UP) == 0))
665 unit->e1ku_stats.PacketsReceived = 0;
666 unit->e1ku_stats.PacketsSent = 0;
667 unit->e1ku_stats.BadData = 0;
668 unit->e1ku_stats.Overruns = 0;
669 unit->e1ku_stats.UnknownTypesReceived = 0;
670 unit->e1ku_stats.Reconfigurations = 0;
672 for(i = 0; i < SANA2_SPECIAL_STAT_COUNT; i++)
673 unit->e1ku_special_stats[i] = 0;
675 tctl = E1000_READ_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_TCTL);
676 tctl |= E1000_TCTL_EN;
677 E1000_WRITE_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_TCTL, tctl);
679 rctl = E1000_READ_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_RCTL);
680 rctl |= E1000_RCTL_EN;
681 E1000_WRITE_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_RCTL, rctl);
683 e1000func_irq_enable(unit);
685 /* fire a link status change interrupt to start the watchdog */
686 E1000_WRITE_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_ICS, E1000_ICS_LSC);
688 unit->e1ku_ifflags |= IFF_UP;
689 ReportEvents(LIBBASE, unit, S2EVENT_ONLINE);
692 /* Return */
694 request->ios2_Req.io_Error = error;
695 request->ios2_WireError = wire_error;
696 return TRUE;
699 static BOOL CmdOffline(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
701 struct e1000Unit *unit;
702 ULONG rctl, tctl;
703 /* Put adapter offline */
705 unit = (APTR)request->ios2_Req.io_Unit;
707 D(bug("[%s]: CmdOffline()\n", unit->e1ku_name));
709 if((unit->e1ku_ifflags & IFF_UP) != 0)
711 unit->e1ku_ifflags &= ~IFF_UP;
713 tctl = E1000_READ_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_TCTL);
714 tctl &= ~E1000_TCTL_EN;
715 E1000_WRITE_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_TCTL, tctl);
717 rctl = E1000_READ_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_RCTL);
718 rctl &= ~E1000_RCTL_EN;
719 E1000_WRITE_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_RCTL, rctl);
721 e1000func_irq_disable(unit);
723 ReportEvents(LIBBASE, unit, S2EVENT_OFFLINE);
726 /* Return */
727 return TRUE;
730 static BOOL CmdAddMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
732 struct e1000Unit *unit;
733 UBYTE *lower_bound, *upper_bound;
735 unit = (APTR)request->ios2_Req.io_Unit;
737 D(bug("[%s]: CmdAddMulticastAddresses()\n", unit->e1ku_name));
739 lower_bound = request->ios2_SrcAddr;
740 if(request->ios2_Req.io_Command == S2_ADDMULTICASTADDRESS)
741 upper_bound = lower_bound;
742 else
743 upper_bound = request->ios2_DstAddr;
745 if(!AddMulticastRange(LIBBASE, unit, lower_bound, upper_bound))
747 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
748 request->ios2_WireError = S2WERR_GENERIC_ERROR;
751 /* Return */
753 return TRUE;
756 static BOOL CmdDelMulticastAddresses(LIBBASETYPEPTR LIBBASE, struct IOSana2Req *request)
758 struct e1000Unit *unit;
759 UBYTE *lower_bound, *upper_bound;
761 unit = (APTR)request->ios2_Req.io_Unit;
763 D(bug("[%s]: CmdDelMulticastAddresses()\n", unit->e1ku_name));
765 lower_bound = request->ios2_SrcAddr;
766 if(request->ios2_Req.io_Command == S2_DELMULTICASTADDRESS)
767 upper_bound = lower_bound;
768 else
769 upper_bound = request->ios2_DstAddr;
771 if(!RemMulticastRange(LIBBASE, unit, lower_bound, upper_bound))
773 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
774 request->ios2_WireError = S2WERR_BAD_MULTICAST;
777 /* Return */
779 return TRUE;