revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / fec / fec_handler.c
blobe22469ee44faa55d2d3557c945b0981c715351ef
1 /*
2 * fec_handler.c
4 * Created on: May 18, 2009
5 * Author: misc
6 */
8 #define DEBUG 1
9 #include <aros/debug.h>
10 #include <aros/libcall.h>
11 #include <aros/asmcall.h>
12 #include <aros/symbolsets.h>
14 #include <exec/memory.h>
15 #include <exec/errors.h>
17 #include <devices/newstyle.h>
18 #include <devices/sana2.h>
19 #include <devices/sana2specialstats.h>
21 #include <proto/openfirmware.h>
22 #include <proto/exec.h>
23 #include <proto/dos.h>
25 #include <inttypes.h>
27 #include "fec.h"
29 #define KNOWN_EVENTS \
30 (S2EVENT_ERROR | S2EVENT_TX | S2EVENT_RX | S2EVENT_ONLINE \
31 | S2EVENT_OFFLINE | S2EVENT_BUFF | S2EVENT_HARDWARE | S2EVENT_SOFTWARE)
33 static BOOL CmdInvalid(struct FECBase *FECBase, struct IOSana2Req *request);
34 static BOOL CmdRead(struct FECBase *FECBase, struct IOSana2Req *request);
35 static BOOL CmdWrite(struct FECBase *FECBase, struct IOSana2Req *request);
36 static BOOL CmdFlush(struct FECBase *FECBase, struct IORequest *request);
37 static BOOL CmdS2DeviceQuery(struct FECBase *FECBase, struct IOSana2Req *request);
38 static BOOL CmdGetStationAddress(struct FECBase *FECBase, struct IOSana2Req *request);
39 static BOOL CmdConfigInterface(struct FECBase *FECBase, struct IOSana2Req *request);
40 static BOOL CmdBroadcast(struct FECBase *FECBase, struct IOSana2Req *request);
41 static BOOL CmdTrackType(struct FECBase *FECBase, struct IOSana2Req *request);
42 static BOOL CmdUntrackType(struct FECBase *FECBase, struct IOSana2Req *request);
43 static BOOL CmdGetTypeStats(struct FECBase *FECBase, struct IOSana2Req *request);
44 static BOOL CmdGetGlobalStats(struct FECBase *FECBase, struct IOSana2Req *request);
45 static BOOL CmdDeviceQuery(struct FECBase *FECBase, struct IOStdReq *request);
46 static BOOL CmdOnEvent(struct FECBase *FECBase, struct IOSana2Req *request);
47 static BOOL CmdReadOrphan(struct FECBase *FECBase, struct IOSana2Req *request);
48 static BOOL CmdOnline(struct FECBase *FECBase, struct IOSana2Req *request);
49 static BOOL CmdOffline(struct FECBase *FECBase, struct IOSana2Req *request);
50 static BOOL CmdAddMulticastAddresses(struct FECBase *FECBase, struct IOSana2Req *request);
51 static BOOL CmdDelMulticastAddresses(struct FECBase *FECBase, struct IOSana2Req *request);
53 static const uint16_t supported_commands[] =
55 CMD_READ,
56 CMD_WRITE,
57 CMD_FLUSH,
58 S2_DEVICEQUERY,
59 S2_GETSTATIONADDRESS,
60 S2_CONFIGINTERFACE,
61 S2_ADDMULTICASTADDRESS,
62 S2_DELMULTICASTADDRESS,
63 S2_MULTICAST,
64 S2_BROADCAST,
65 S2_TRACKTYPE,
66 S2_UNTRACKTYPE,
67 S2_GETTYPESTATS,
68 // S2_GETSPECIALSTATS,
69 S2_GETGLOBALSTATS,
70 S2_ONEVENT,
71 S2_READORPHAN,
72 S2_ONLINE,
73 S2_OFFLINE,
74 NSCMD_DEVICEQUERY,
75 S2_ADDMULTICASTADDRESSES,
76 S2_DELMULTICASTADDRESSES,
80 void handle_request(struct FECBase *FECBase, struct IOSana2Req *request)
82 D(bug("[FEC] handle_request\n"));
84 BOOL complete;
86 switch(request->ios2_Req.io_Command)
88 case CMD_READ:
89 complete = CmdRead(FECBase, request);
90 break;
92 case CMD_WRITE:
93 case S2_MULTICAST:
94 complete = CmdWrite(FECBase, request);
95 break;
97 case CMD_FLUSH:
98 complete = CmdFlush(FECBase, (struct IORequest *)request);
99 break;
101 case S2_DEVICEQUERY:
102 complete = CmdS2DeviceQuery(FECBase, request);
103 break;
105 case S2_GETSTATIONADDRESS:
106 complete = CmdGetStationAddress(FECBase, request);
107 break;
109 case S2_CONFIGINTERFACE:
110 complete = CmdConfigInterface(FECBase, request);
111 break;
113 case S2_BROADCAST:
114 complete = CmdBroadcast(FECBase, request);
115 break;
117 case S2_TRACKTYPE:
118 complete = CmdTrackType(FECBase, request);
119 break;
121 case S2_UNTRACKTYPE:
122 complete = CmdUntrackType(FECBase, request);
123 break;
125 case S2_GETTYPESTATS:
126 complete = CmdGetTypeStats(FECBase, request);
127 break;
129 case S2_GETGLOBALSTATS:
130 complete = CmdGetGlobalStats(FECBase, request);
131 break;
133 case S2_ONEVENT:
134 complete = CmdOnEvent(FECBase, request);
135 break;
137 case S2_READORPHAN:
138 complete = CmdReadOrphan(FECBase, request);
139 break;
141 case S2_ONLINE:
142 complete = CmdOnline(FECBase, request);
143 break;
145 case S2_OFFLINE:
146 complete = CmdOffline(FECBase, request);
147 break;
149 case S2_ADDMULTICASTADDRESS:
150 case S2_ADDMULTICASTADDRESSES:
151 complete = CmdAddMulticastAddresses(FECBase, request);
152 break;
154 case S2_DELMULTICASTADDRESS:
155 case S2_DELMULTICASTADDRESSES:
156 complete = CmdDelMulticastAddresses(FECBase, request);
157 break;
159 case NSCMD_DEVICEQUERY:
160 complete = CmdDeviceQuery(FECBase, (struct IOStdReq *)request);
161 break;
163 default:
164 complete = CmdInvalid(FECBase, request);
167 if(complete && (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
168 ReplyMsg((APTR)request);
170 ReleaseSemaphore(&((struct FECUnit *)request->ios2_Req.io_Unit)->feu_Lock);
174 static BOOL CmdInvalid(struct FECBase *FECBase, struct IOSana2Req *request)
176 request->ios2_Req.io_Error = IOERR_NOCMD;
177 request->ios2_WireError = S2WERR_GENERIC_ERROR;
179 return TRUE;
182 static BOOL CmdRead(struct FECBase *FECBase, struct IOSana2Req *request)
184 struct FECUnit *unit;
185 struct Opener *opener;
186 BOOL complete = FALSE;
188 unit = (APTR)request->ios2_Req.io_Unit;
190 D(bug("[FEC] S2CmdRead()\n"));
192 if((unit->feu_Flags & IFF_UP) != 0)
194 opener = request->ios2_BufferManagement;
195 request->ios2_Req.io_Flags &= ~IOF_QUICK;
196 PutMsg(&opener->read_port, (struct Message *)request);
198 else
200 request->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
201 request->ios2_WireError = S2WERR_UNIT_OFFLINE;
202 complete = TRUE;
205 /* Return */
207 return complete;
210 static BOOL CmdWrite(struct FECBase *FECBase, struct IOSana2Req *request)
212 struct FECUnit *unit;
213 BYTE error = 0;
214 ULONG wire_error = S2WERR_GENERIC_ERROR;
215 BOOL complete = FALSE;
217 /* Check request is valid */
219 unit = (APTR)request->ios2_Req.io_Unit;
221 D(bug("[FEC] S2CmdWrite()\n"));
223 if((unit->feu_Flags & IFF_UP) == 0)
225 error = S2ERR_OUTOFSERVICE;
226 wire_error = S2WERR_UNIT_OFFLINE;
228 else if((request->ios2_Req.io_Command == S2_MULTICAST) &&
229 ((request->ios2_DstAddr[0] & 0x1) == 0))
231 error = S2ERR_BAD_ADDRESS;
232 wire_error = S2WERR_BAD_MULTICAST;
235 /* Queue request for sending */
237 if(error == 0) {
238 request->ios2_Req.io_Flags &= ~IOF_QUICK;
239 PutMsg(unit->feu_RequestPorts[WRITE_QUEUE], (APTR)request);
241 else
243 request->ios2_Req.io_Error = error;
244 request->ios2_WireError = wire_error;
245 complete = TRUE;
248 /* Return */
249 return complete;
252 static BOOL CmdFlush(struct FECBase *FECBase, struct IORequest *request)
254 #warning TODO: Implement CmdFlush!!!!!!!!!
255 // FlushUnit(LIBBASE, (APTR)request->io_Unit, EVENT_QUEUE, IOERR_ABORTED);
256 return TRUE;
259 static BOOL CmdS2DeviceQuery(struct FECBase *FECBase, struct IOSana2Req *request)
261 struct FECUnit *unit = (APTR)request->ios2_Req.io_Unit;
262 //struct fe_priv *np = unit->pcnu_fe_priv;
263 struct Sana2DeviceQuery *info;
264 ULONG size_available, size;
266 D(bug("[FEC] S2CmdDeviceQuery()\n"));
268 /* Copy device info */
270 info = request->ios2_StatData;
271 size = size_available = info->SizeAvailable;
272 if(size > sizeof(struct Sana2DeviceQuery))
273 size = sizeof(struct Sana2DeviceQuery);
275 CopyMem(&FECBase->feb_Sana2Info, info, size);
277 info->BPS = unit->feu_speed * 1000000;
278 info->MTU = ETH_MTU;
279 info->HardwareType = S2WireType_Ethernet;
280 info->SizeAvailable = size_available;
281 info->SizeSupplied = size;
283 /* Return */
285 return TRUE;
288 static BOOL CmdGetStationAddress(struct FECBase *FECBase, struct IOSana2Req *request)
290 struct FECUnit *unit;
292 /* Copy addresses */
294 unit = (APTR)request->ios2_Req.io_Unit;
296 D(bug("[FEC] S2CmdGetStationAddress()\n"));
298 CopyMem(unit->feu_DevAddr, request->ios2_SrcAddr, ETH_ADDRESSSIZE);
299 CopyMem(unit->feu_OrgAddr, request->ios2_DstAddr, ETH_ADDRESSSIZE);
301 /* Return */
303 return TRUE;
306 static BOOL CmdConfigInterface(struct FECBase *FECBase, struct IOSana2Req *request)
308 struct FECUnit *unit;
310 /* Configure adapter */
312 unit = (APTR)request->ios2_Req.io_Unit;
314 D(bug("[FEC] S2CmdConfigInterface()\n"));
316 if((unit->feu_Flags & IFF_CONFIGURED) == 0)
318 CopyMem(request->ios2_SrcAddr, unit->feu_DevAddr, ETH_ADDRESSSIZE);
319 unit->set_mac_address(unit);
320 unit->feu_Flags |= IFF_CONFIGURED;
322 else
324 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
325 request->ios2_WireError = S2WERR_IS_CONFIGURED;
328 /* Return */
330 return TRUE;
333 static BOOL CmdBroadcast(struct FECBase *FECBase, struct IOSana2Req *request)
335 UWORD i;
337 /* Fill in the broadcast address as destination */
339 for(i = 0; i < ETH_ADDRESSSIZE; i++)
340 request->ios2_DstAddr[i] = 0xff;
342 /* Queue the write as normal */
344 return CmdWrite(FECBase, request);
347 static BOOL CmdTrackType(struct FECBase *FECBase, struct IOSana2Req *request)
349 struct FECUnit *unit;
350 struct Opener *opener;
351 ULONG packet_type, wire_error=0;
352 struct TypeTracker *tracker;
353 struct TypeStats *initial_stats;
354 BYTE error = 0;
356 unit = (APTR)request->ios2_Req.io_Unit;
358 D(bug("[FEC] S2CmdTrackType(%d)\n", request->ios2_PacketType));
360 packet_type = request->ios2_PacketType;
362 /* Get global tracker */
363 tracker = (struct TypeTracker *)
364 FindTypeStats(FECBase, unit, &unit->feu_TypeTrackers, packet_type);
366 if(tracker != NULL)
367 tracker->user_count++;
368 else
370 tracker =
371 AllocMem(sizeof(struct TypeTracker), MEMF_PUBLIC|MEMF_CLEAR);
372 if(tracker != NULL)
374 tracker->packet_type = packet_type;
375 tracker->user_count = 1;
377 Disable();
378 AddTail((APTR)&unit->feu_TypeTrackers, (APTR)tracker);
379 Enable();
383 /* Store initial figures for this opener */
385 opener = request->ios2_BufferManagement;
386 initial_stats = FindTypeStats(FECBase, unit, &opener->initial_stats, packet_type);
387 if(initial_stats != NULL)
389 error = S2ERR_BAD_STATE;
390 wire_error = S2WERR_ALREADY_TRACKED;
393 if(error == 0)
395 initial_stats = AllocMem(sizeof(struct TypeStats), MEMF_PUBLIC);
396 if(initial_stats == NULL)
398 error = S2ERR_NO_RESOURCES;
399 wire_error = S2WERR_GENERIC_ERROR;
403 if(error == 0)
405 CopyMem(tracker, initial_stats, sizeof(struct TypeStats));
406 AddTail((APTR)&opener->initial_stats, (APTR)initial_stats);
409 /* Return */
411 request->ios2_Req.io_Error = error;
412 request->ios2_WireError = wire_error;
413 return TRUE;
416 static BOOL CmdUntrackType(struct FECBase *FECBase, struct IOSana2Req *request)
418 struct FECUnit *unit;
419 struct Opener *opener;
420 ULONG packet_type;
421 struct TypeTracker *tracker;
422 struct TypeStats *initial_stats;
424 unit = (APTR)request->ios2_Req.io_Unit;
426 D(bug("[FEC] S2CmdUntrackType()\n"));
428 packet_type = request->ios2_PacketType;
430 /* Get global tracker and initial figures */
432 tracker = (struct TypeTracker *)
433 FindTypeStats(FECBase, unit, &unit->feu_TypeTrackers, packet_type);
434 opener = request->ios2_BufferManagement;
435 initial_stats = FindTypeStats(FECBase, unit, &opener->initial_stats, packet_type);
437 /* Decrement tracker usage and free unused structures */
439 if(initial_stats != NULL)
441 if((--tracker->user_count) == 0)
443 Disable();
444 Remove((APTR)tracker);
445 Enable();
446 FreeMem(tracker, sizeof(struct TypeTracker));
449 Remove((APTR)initial_stats);
450 FreeMem(initial_stats, sizeof(struct TypeStats));
452 else
454 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
455 request->ios2_WireError = S2WERR_NOT_TRACKED;
458 /* Return */
460 return TRUE;
463 static BOOL CmdGetTypeStats(struct FECBase *FECBase, struct IOSana2Req *request)
465 struct FECUnit *unit;
466 struct Opener *opener;
467 ULONG packet_type;
468 struct TypeStats *initial_stats, *tracker;
469 struct Sana2PacketTypeStats *stats;
471 unit = (APTR)request->ios2_Req.io_Unit;
473 D(bug("[FEC] S2CmdGetTypeStats()\n"));
475 packet_type = request->ios2_PacketType;
477 /* Get global tracker and initial figures */
479 tracker = FindTypeStats(FECBase, unit, &unit->feu_TypeTrackers, packet_type);
480 opener = request->ios2_BufferManagement;
481 initial_stats = FindTypeStats(FECBase, unit, &opener->initial_stats, packet_type);
483 /* Copy and adjust figures */
484 if(initial_stats != NULL)
486 stats = request->ios2_StatData;
487 CopyMem(&tracker->stats, stats, sizeof(struct Sana2PacketTypeStats));
488 stats->PacketsSent -= initial_stats->stats.PacketsSent;
489 stats->PacketsReceived -= initial_stats->stats.PacketsReceived;
490 stats->BytesSent -= initial_stats->stats.BytesSent;
491 stats->BytesReceived -= initial_stats->stats.BytesReceived;
492 stats->PacketsDropped -= initial_stats->stats.PacketsDropped;
494 else
496 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
497 request->ios2_WireError = S2WERR_NOT_TRACKED;
500 /* Return */
502 return TRUE;
505 static BOOL CmdGetGlobalStats(struct FECBase *FECBase, struct IOSana2Req *request)
507 struct FECUnit *unit;
509 /* Update and copy stats */
511 unit = (APTR)request->ios2_Req.io_Unit;
513 D(bug("[FEC] S2CmdGetGlobalStats()\n"));
515 CopyMem(&unit->feu_Stats, request->ios2_StatData,
516 sizeof(struct Sana2DeviceStats));
518 /* Return */
520 return TRUE;
523 static BOOL CmdDeviceQuery(struct FECBase *FECBase, struct IOStdReq *request)
525 struct NSDeviceQueryResult *info;
527 /* Set structure size twice */
529 info = request->io_Data;
530 request->io_Actual = info->SizeAvailable =
531 offsetof(struct NSDeviceQueryResult, SupportedCommands) + sizeof(APTR);
533 /* Report device details */
535 info->DeviceType = NSDEVTYPE_SANA2;
536 info->DeviceSubType = 0;
538 info->SupportedCommands = (APTR)supported_commands;
540 /* Return */
542 return TRUE;
545 static BOOL CmdOnEvent(struct FECBase *FECBase, struct IOSana2Req *request)
547 struct FECUnit *unit;
548 ULONG events, wanted_events;
549 BOOL complete = FALSE;
551 /* Check if we understand the event types */
553 unit = (struct FECUnit *)request->ios2_Req.io_Unit;
555 D(bug("[FEC] S2CmdOnEvent()\n"));
557 wanted_events = request->ios2_WireError;
558 if((wanted_events & ~KNOWN_EVENTS) != 0)
560 request->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
561 events = S2WERR_BAD_EVENT;
563 else
565 if((unit->feu_Flags & IFF_UP) != 0)
566 events = S2EVENT_ONLINE;
567 else
568 events = S2EVENT_OFFLINE;
570 events &= wanted_events;
573 /* Reply request if a wanted event has already occurred */
574 if(events != 0)
576 request->ios2_WireError = events;
577 complete = TRUE;
579 else
581 request->ios2_Req.io_Flags &= ~IOF_QUICK;
582 PutMsg(unit->feu_RequestPorts[EVENT_QUEUE], (APTR)request);
585 /* Return */
587 return complete;
590 static BOOL CmdReadOrphan(struct FECBase *FECBase, struct IOSana2Req *request)
592 struct FECUnit *unit;
593 BYTE error = 0;
594 ULONG wire_error;
595 BOOL complete = FALSE;
597 /* Check request is valid */
599 unit = (struct FECUnit *)request->ios2_Req.io_Unit;
601 D(bug("[FEC] S2CmdReadOrphan()\n"));
603 if((unit->feu_Flags & IFF_UP) == 0)
605 error = S2ERR_OUTOFSERVICE;
606 wire_error = S2WERR_UNIT_OFFLINE;
609 /* Queue request */
611 if(error == 0)
613 request->ios2_Req.io_Flags &= ~IOF_QUICK;
614 PutMsg(unit->feu_RequestPorts[ADOPT_QUEUE], (struct Message *)request);
616 else
618 request->ios2_Req.io_Error = error;
619 request->ios2_WireError = wire_error;
620 complete = TRUE;
623 /* Return */
625 return complete;
628 static BOOL CmdOnline(struct FECBase *FECBase, struct IOSana2Req *request)
630 struct FECUnit *unit = (struct FECUnit *)request->ios2_Req.io_Unit;
631 BYTE error = 0;
632 ULONG wire_error = 0;
633 UWORD i;
635 D(bug("[FEC] S2CmdOnline()\n"));
637 /* Check request is valid */
638 if((unit->feu_Flags & IFF_CONFIGURED) == 0)
640 error = S2ERR_BAD_STATE;
641 wire_error = S2WERR_NOT_CONFIGURED;
644 /* Clear global and special stats and put adapter back online */
646 if((error == 0) && ((unit->feu_Flags & IFF_UP) == 0))
648 unit->feu_Stats.PacketsReceived = 0;
649 unit->feu_Stats.PacketsSent = 0;
650 unit->feu_Stats.BadData = 0;
651 unit->feu_Stats.Overruns = 0;
652 unit->feu_Stats.UnknownTypesReceived = 0;
653 unit->feu_Stats.Reconfigurations = 0;
655 for(i = 0; i < STAT_COUNT; i++)
656 unit->feu_SpecialStats[i] = 0;
658 if (unit->start(unit)) {
659 error = S2ERR_OUTOFSERVICE;
660 wire_error = S2WERR_GENERIC_ERROR;
664 /* Return */
665 request->ios2_Req.io_Error = error;
666 request->ios2_WireError = wire_error;
667 return TRUE;
670 static BOOL CmdOffline(struct FECBase *FECBase, struct IOSana2Req *request)
672 struct FECUnit *unit;
674 /* Put adapter offline */
676 unit = (APTR)request->ios2_Req.io_Unit;
678 D(bug("[FEC] S2CmdOffline()\n"));
680 if((unit->feu_Flags & IFF_UP) != 0)
681 unit->stop(unit);
683 /* Return */
684 return TRUE;
687 static BOOL CmdAddMulticastAddresses(struct FECBase *FECBase, struct IOSana2Req *request)
689 struct FECUnit *unit;
690 UBYTE *lower_bound, *upper_bound;
692 unit = (APTR)request->ios2_Req.io_Unit;
694 D(bug("[FEC] S2CmdAddMulticastAddresses()\n"));
696 lower_bound = request->ios2_SrcAddr;
697 if(request->ios2_Req.io_Command == S2_ADDMULTICASTADDRESS)
698 upper_bound = lower_bound;
699 else
700 upper_bound = request->ios2_DstAddr;
702 if(!AddMulticastRange(FECBase, unit, lower_bound, upper_bound))
704 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
705 request->ios2_WireError = S2WERR_GENERIC_ERROR;
708 /* Return */
710 return TRUE;
713 static BOOL CmdDelMulticastAddresses(struct FECBase *FECBase, struct IOSana2Req *request)
715 struct FECUnit *unit;
716 UBYTE *lower_bound, *upper_bound;
718 unit = (APTR)request->ios2_Req.io_Unit;
720 D(bug("[FEC] S2CmdDelMulticastAddresses()\n"));
722 lower_bound = request->ios2_SrcAddr;
723 if(request->ios2_Req.io_Command == S2_DELMULTICASTADDRESS)
724 upper_bound = lower_bound;
725 else
726 upper_bound = request->ios2_DstAddr;
728 if(!RemMulticastRange(FECBase, unit, lower_bound, upper_bound))
730 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
731 request->ios2_WireError = S2WERR_BAD_MULTICAST;
734 /* Return */
736 return TRUE;