Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / fec / fec_handler.c
blob941520f3f0ebcf1353a8d8d8680eeaea84ca2909
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 /* Fill in the broadcast address as destination */
337 *((ULONG *)request->ios2_DstAddr) = 0xffffffff;
338 *((UWORD *)(request->ios2_DstAddr + 4)) = 0xffff;
340 /* Queue the write as normal */
342 return CmdWrite(FECBase, request);
345 static BOOL CmdTrackType(struct FECBase *FECBase, struct IOSana2Req *request)
347 struct FECUnit *unit;
348 struct Opener *opener;
349 ULONG packet_type, wire_error=0;
350 struct TypeTracker *tracker;
351 struct TypeStats *initial_stats;
352 BYTE error = 0;
354 unit = (APTR)request->ios2_Req.io_Unit;
356 D(bug("[FEC] S2CmdTrackType(%d)\n", request->ios2_PacketType));
358 packet_type = request->ios2_PacketType;
360 /* Get global tracker */
361 tracker = (struct TypeTracker *)
362 FindTypeStats(FECBase, unit, &unit->feu_TypeTrackers, packet_type);
364 if(tracker != NULL)
365 tracker->user_count++;
366 else
368 tracker =
369 AllocMem(sizeof(struct TypeTracker), MEMF_PUBLIC|MEMF_CLEAR);
370 if(tracker != NULL)
372 tracker->packet_type = packet_type;
373 tracker->user_count = 1;
375 Disable();
376 AddTail((APTR)&unit->feu_TypeTrackers, (APTR)tracker);
377 Enable();
381 /* Store initial figures for this opener */
383 opener = request->ios2_BufferManagement;
384 initial_stats = FindTypeStats(FECBase, unit, &opener->initial_stats, packet_type);
385 if(initial_stats != NULL)
387 error = S2ERR_BAD_STATE;
388 wire_error = S2WERR_ALREADY_TRACKED;
391 if(error == 0)
393 initial_stats = AllocMem(sizeof(struct TypeStats), MEMF_PUBLIC);
394 if(initial_stats == NULL)
396 error = S2ERR_NO_RESOURCES;
397 wire_error = S2WERR_GENERIC_ERROR;
401 if(error == 0)
403 CopyMem(tracker, initial_stats, sizeof(struct TypeStats));
404 AddTail((APTR)&opener->initial_stats, (APTR)initial_stats);
407 /* Return */
409 request->ios2_Req.io_Error = error;
410 request->ios2_WireError = wire_error;
411 return TRUE;
414 static BOOL CmdUntrackType(struct FECBase *FECBase, struct IOSana2Req *request)
416 struct FECUnit *unit;
417 struct Opener *opener;
418 ULONG packet_type;
419 struct TypeTracker *tracker;
420 struct TypeStats *initial_stats;
422 unit = (APTR)request->ios2_Req.io_Unit;
424 D(bug("[FEC] S2CmdUntrackType()\n"));
426 packet_type = request->ios2_PacketType;
428 /* Get global tracker and initial figures */
430 tracker = (struct TypeTracker *)
431 FindTypeStats(FECBase, unit, &unit->feu_TypeTrackers, packet_type);
432 opener = request->ios2_BufferManagement;
433 initial_stats = FindTypeStats(FECBase, unit, &opener->initial_stats, packet_type);
435 /* Decrement tracker usage and free unused structures */
437 if(initial_stats != NULL)
439 if((--tracker->user_count) == 0)
441 Disable();
442 Remove((APTR)tracker);
443 Enable();
444 FreeMem(tracker, sizeof(struct TypeTracker));
447 Remove((APTR)initial_stats);
448 FreeMem(initial_stats, sizeof(struct TypeStats));
450 else
452 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
453 request->ios2_WireError = S2WERR_NOT_TRACKED;
456 /* Return */
458 return TRUE;
461 static BOOL CmdGetTypeStats(struct FECBase *FECBase, struct IOSana2Req *request)
463 struct FECUnit *unit;
464 struct Opener *opener;
465 ULONG packet_type;
466 struct TypeStats *initial_stats, *tracker;
467 struct Sana2PacketTypeStats *stats;
469 unit = (APTR)request->ios2_Req.io_Unit;
471 D(bug("[FEC] S2CmdGetTypeStats()\n"));
473 packet_type = request->ios2_PacketType;
475 /* Get global tracker and initial figures */
477 tracker = FindTypeStats(FECBase, unit, &unit->feu_TypeTrackers, packet_type);
478 opener = request->ios2_BufferManagement;
479 initial_stats = FindTypeStats(FECBase, unit, &opener->initial_stats, packet_type);
481 /* Copy and adjust figures */
482 if(initial_stats != NULL)
484 stats = request->ios2_StatData;
485 CopyMem(&tracker->stats, stats, sizeof(struct Sana2PacketTypeStats));
486 stats->PacketsSent -= initial_stats->stats.PacketsSent;
487 stats->PacketsReceived -= initial_stats->stats.PacketsReceived;
488 stats->BytesSent -= initial_stats->stats.BytesSent;
489 stats->BytesReceived -= initial_stats->stats.BytesReceived;
490 stats->PacketsDropped -= initial_stats->stats.PacketsDropped;
492 else
494 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
495 request->ios2_WireError = S2WERR_NOT_TRACKED;
498 /* Return */
500 return TRUE;
503 static BOOL CmdGetGlobalStats(struct FECBase *FECBase, struct IOSana2Req *request)
505 struct FECUnit *unit;
507 /* Update and copy stats */
509 unit = (APTR)request->ios2_Req.io_Unit;
511 D(bug("[FEC] S2CmdGetGlobalStats()\n"));
513 CopyMem(&unit->feu_Stats, request->ios2_StatData,
514 sizeof(struct Sana2DeviceStats));
516 /* Return */
518 return TRUE;
521 static BOOL CmdDeviceQuery(struct FECBase *FECBase, struct IOStdReq *request)
523 struct NSDeviceQueryResult *info;
525 /* Set structure size twice */
527 info = request->io_Data;
528 request->io_Actual = info->SizeAvailable =
529 offsetof(struct NSDeviceQueryResult, SupportedCommands) + sizeof(APTR);
531 /* Report device details */
533 info->DeviceType = NSDEVTYPE_SANA2;
534 info->DeviceSubType = 0;
536 info->SupportedCommands = (APTR)supported_commands;
538 /* Return */
540 return TRUE;
543 static BOOL CmdOnEvent(struct FECBase *FECBase, struct IOSana2Req *request)
545 struct FECUnit *unit;
546 ULONG events, wanted_events;
547 BOOL complete = FALSE;
549 /* Check if we understand the event types */
551 unit = (struct FECUnit *)request->ios2_Req.io_Unit;
553 D(bug("[FEC] S2CmdOnEvent()\n"));
555 wanted_events = request->ios2_WireError;
556 if((wanted_events & ~KNOWN_EVENTS) != 0)
558 request->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
559 events = S2WERR_BAD_EVENT;
561 else
563 if((unit->feu_Flags & IFF_UP) != 0)
564 events = S2EVENT_ONLINE;
565 else
566 events = S2EVENT_OFFLINE;
568 events &= wanted_events;
571 /* Reply request if a wanted event has already occurred */
572 if(events != 0)
574 request->ios2_WireError = events;
575 complete = TRUE;
577 else
579 request->ios2_Req.io_Flags &= ~IOF_QUICK;
580 PutMsg(unit->feu_RequestPorts[EVENT_QUEUE], (APTR)request);
583 /* Return */
585 return complete;
588 static BOOL CmdReadOrphan(struct FECBase *FECBase, struct IOSana2Req *request)
590 struct FECUnit *unit;
591 BYTE error = 0;
592 ULONG wire_error;
593 BOOL complete = FALSE;
595 /* Check request is valid */
597 unit = (struct FECUnit *)request->ios2_Req.io_Unit;
599 D(bug("[FEC] S2CmdReadOrphan()\n"));
601 if((unit->feu_Flags & IFF_UP) == 0)
603 error = S2ERR_OUTOFSERVICE;
604 wire_error = S2WERR_UNIT_OFFLINE;
607 /* Queue request */
609 if(error == 0)
611 request->ios2_Req.io_Flags &= ~IOF_QUICK;
612 PutMsg(unit->feu_RequestPorts[ADOPT_QUEUE], (struct Message *)request);
614 else
616 request->ios2_Req.io_Error = error;
617 request->ios2_WireError = wire_error;
618 complete = TRUE;
621 /* Return */
623 return complete;
626 static BOOL CmdOnline(struct FECBase *FECBase, struct IOSana2Req *request)
628 struct FECUnit *unit = (struct FECUnit *)request->ios2_Req.io_Unit;
629 BYTE error = 0;
630 ULONG wire_error = 0;
631 UWORD i;
633 D(bug("[FEC] S2CmdOnline()\n"));
635 /* Check request is valid */
636 if((unit->feu_Flags & IFF_CONFIGURED) == 0)
638 error = S2ERR_BAD_STATE;
639 wire_error = S2WERR_NOT_CONFIGURED;
642 /* Clear global and special stats and put adapter back online */
644 if((error == 0) && ((unit->feu_Flags & IFF_UP) == 0))
646 unit->feu_Stats.PacketsReceived = 0;
647 unit->feu_Stats.PacketsSent = 0;
648 unit->feu_Stats.BadData = 0;
649 unit->feu_Stats.Overruns = 0;
650 unit->feu_Stats.UnknownTypesReceived = 0;
651 unit->feu_Stats.Reconfigurations = 0;
653 for(i = 0; i < STAT_COUNT; i++)
654 unit->feu_SpecialStats[i] = 0;
656 if (unit->start(unit)) {
657 error = S2ERR_OUTOFSERVICE;
658 wire_error = S2WERR_GENERIC_ERROR;
662 /* Return */
663 request->ios2_Req.io_Error = error;
664 request->ios2_WireError = wire_error;
665 return TRUE;
668 static BOOL CmdOffline(struct FECBase *FECBase, struct IOSana2Req *request)
670 struct FECUnit *unit;
672 /* Put adapter offline */
674 unit = (APTR)request->ios2_Req.io_Unit;
676 D(bug("[FEC] S2CmdOffline()\n"));
678 if((unit->feu_Flags & IFF_UP) != 0)
679 unit->stop(unit);
681 /* Return */
682 return TRUE;
685 static BOOL CmdAddMulticastAddresses(struct FECBase *FECBase, struct IOSana2Req *request)
687 struct FECUnit *unit;
688 UBYTE *lower_bound, *upper_bound;
690 unit = (APTR)request->ios2_Req.io_Unit;
692 D(bug("[FEC] S2CmdAddMulticastAddresses()\n"));
694 lower_bound = request->ios2_SrcAddr;
695 if(request->ios2_Req.io_Command == S2_ADDMULTICASTADDRESS)
696 upper_bound = lower_bound;
697 else
698 upper_bound = request->ios2_DstAddr;
700 if(!AddMulticastRange(FECBase, unit, lower_bound, upper_bound))
702 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
703 request->ios2_WireError = S2WERR_GENERIC_ERROR;
706 /* Return */
708 return TRUE;
711 static BOOL CmdDelMulticastAddresses(struct FECBase *FECBase, struct IOSana2Req *request)
713 struct FECUnit *unit;
714 UBYTE *lower_bound, *upper_bound;
716 unit = (APTR)request->ios2_Req.io_Unit;
718 D(bug("[FEC] S2CmdDelMulticastAddresses()\n"));
720 lower_bound = request->ios2_SrcAddr;
721 if(request->ios2_Req.io_Command == S2_DELMULTICASTADDRESS)
722 upper_bound = lower_bound;
723 else
724 upper_bound = request->ios2_DstAddr;
726 if(!RemMulticastRange(FECBase, unit, lower_bound, upper_bound))
728 request->ios2_Req.io_Error = S2ERR_BAD_STATE;
729 request->ios2_WireError = S2WERR_BAD_MULTICAST;
732 /* Return */
734 return TRUE;