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,
26 #include <exec/types.h>
27 #include <exec/resident.h>
29 #include <exec/ports.h>
30 #include <exec/errors.h>
32 #include <aros/debug.h>
34 #include <devices/sana2.h>
35 #include <devices/sana2specialstats.h>
36 #include <devices/newstyle.h>
38 #include <utility/utility.h>
39 #include <utility/tagitem.h>
40 #include <utility/hooks.h>
42 #include <proto/exec.h>
43 #include <proto/dos.h>
44 #include <proto/battclock.h>
50 #include LC_LIBDEFS_FILE
52 #define KNOWN_EVENTS \
53 (S2EVENT_ERROR | S2EVENT_TX | S2EVENT_RX | S2EVENT_ONLINE \
54 | S2EVENT_OFFLINE | S2EVENT_BUFF | S2EVENT_HARDWARE | S2EVENT_SOFTWARE)
56 static BOOL
CmdInvalid(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
57 static BOOL
CmdRead(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
58 static BOOL
CmdWrite(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
59 static BOOL
CmdFlush(LIBBASETYPEPTR LIBBASE
, struct IORequest
*request
);
60 static BOOL
CmdS2DeviceQuery(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
61 static BOOL
CmdGetStationAddress(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
62 static BOOL
CmdConfigInterface(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
63 static BOOL
CmdBroadcast(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
64 static BOOL
CmdTrackType(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
65 static BOOL
CmdUntrackType(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
66 static BOOL
CmdGetTypeStats(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
67 static BOOL
CmdGetGlobalStats(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
68 static BOOL
CmdDeviceQuery(LIBBASETYPEPTR LIBBASE
, struct IOStdReq
*request
);
69 static BOOL
CmdOnEvent(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
70 static BOOL
CmdReadOrphan(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
71 static BOOL
CmdOnline(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
72 static BOOL
CmdOffline(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
73 static BOOL
CmdAddMulticastAddresses(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
74 static BOOL
CmdDelMulticastAddresses(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
);
76 static const UWORD supported_commands
[] =
84 S2_ADDMULTICASTADDRESS
,
85 S2_DELMULTICASTADDRESS
,
91 // S2_GETSPECIALSTATS,
98 S2_ADDMULTICASTADDRESSES
,
99 S2_DELMULTICASTADDRESSES
,
103 void handle_request(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
107 switch(request
->ios2_Req
.io_Command
)
110 complete
= CmdRead(LIBBASE
, request
);
115 complete
= CmdWrite(LIBBASE
, request
);
119 complete
= CmdFlush(LIBBASE
, (struct IORequest
*)request
);
123 complete
= CmdS2DeviceQuery(LIBBASE
, request
);
126 case S2_GETSTATIONADDRESS
:
127 complete
= CmdGetStationAddress(LIBBASE
, request
);
130 case S2_CONFIGINTERFACE
:
131 complete
= CmdConfigInterface(LIBBASE
, request
);
135 complete
= CmdBroadcast(LIBBASE
, request
);
139 complete
= CmdTrackType(LIBBASE
, request
);
143 complete
= CmdUntrackType(LIBBASE
, request
);
146 case S2_GETTYPESTATS
:
147 complete
= CmdGetTypeStats(LIBBASE
, request
);
150 case S2_GETGLOBALSTATS
:
151 complete
= CmdGetGlobalStats(LIBBASE
, request
);
155 complete
= CmdOnEvent(LIBBASE
, request
);
159 complete
= CmdReadOrphan(LIBBASE
, request
);
163 complete
= CmdOnline(LIBBASE
, request
);
167 complete
= CmdOffline(LIBBASE
, request
);
170 case S2_ADDMULTICASTADDRESS
:
171 case S2_ADDMULTICASTADDRESSES
:
172 complete
= CmdAddMulticastAddresses(LIBBASE
, request
);
175 case S2_DELMULTICASTADDRESS
:
176 case S2_DELMULTICASTADDRESSES
:
177 complete
= CmdDelMulticastAddresses(LIBBASE
, request
);
180 case NSCMD_DEVICEQUERY
:
181 complete
= CmdDeviceQuery(LIBBASE
, (struct IOStdReq
*)request
);
185 complete
= CmdInvalid(LIBBASE
, request
);
188 if(complete
&& (request
->ios2_Req
.io_Flags
& IOF_QUICK
) == 0)
189 ReplyMsg((APTR
)request
);
191 ReleaseSemaphore(&((struct NFUnit
*)request
->ios2_Req
.io_Unit
)->unit_lock
);
194 static BOOL
CmdInvalid(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
196 request
->ios2_Req
.io_Error
= IOERR_NOCMD
;
197 request
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
202 static BOOL
CmdRead(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
205 struct Opener
*opener
;
206 BOOL complete
= FALSE
;
208 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
210 if((unit
->flags
& IFF_UP
) != 0)
212 opener
= request
->ios2_BufferManagement
;
213 request
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
214 PutMsg(&opener
->read_port
, (struct Message
*)request
);
218 request
->ios2_Req
.io_Error
= S2ERR_OUTOFSERVICE
;
219 request
->ios2_WireError
= S2WERR_UNIT_OFFLINE
;
228 static BOOL
CmdWrite(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
233 BOOL complete
= FALSE
;
235 /* Check request is valid */
237 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
238 if((unit
->flags
& IFF_UP
) == 0)
240 error
= S2ERR_OUTOFSERVICE
;
241 wire_error
= S2WERR_UNIT_OFFLINE
;
243 else if((request
->ios2_Req
.io_Command
== S2_MULTICAST
) &&
244 ((request
->ios2_DstAddr
[0] & 0x1) == 0))
246 error
= S2ERR_BAD_ADDRESS
;
247 wire_error
= S2WERR_BAD_MULTICAST
;
250 /* Queue request for sending */
253 request
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
254 PutMsg(unit
->request_ports
[WRITE_QUEUE
], (APTR
)request
);
258 request
->ios2_Req
.io_Error
= error
;
259 request
->ios2_WireError
= wire_error
;
268 static BOOL
CmdFlush(LIBBASETYPEPTR LIBBASE
, struct IORequest
*request
)
270 FlushUnit(LIBBASE
, (APTR
)request
->io_Unit
, EVENT_QUEUE
, IOERR_ABORTED
);
274 static BOOL
CmdS2DeviceQuery(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
276 struct NFUnit
*unit
= (APTR
)request
->ios2_Req
.io_Unit
;
277 struct fe_priv
*np
= unit
->nu_fe_priv
;
278 struct Sana2DeviceQuery
*info
;
279 ULONG size_available
, size
;
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
->nf_Sana2Info
, info
, size
);
290 if ((np
->linkspeed
& NVREG_LINKSPEED_MASK
) == NVREG_LINKSPEED_100
)
291 info
->BPS
= 100000000;
292 else if ((np
->linkspeed
& NVREG_LINKSPEED_MASK
) == NVREG_LINKSPEED_1000
)
293 info
->BPS
= 1000000000;
295 info
->BPS
= 10000000;
297 info
->SizeAvailable
= size_available
;
298 info
->SizeSupplied
= size
;
305 static BOOL
CmdGetStationAddress(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
311 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
312 CopyMem(unit
->dev_addr
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
313 CopyMem(unit
->org_addr
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
320 static BOOL
CmdConfigInterface(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
324 /* Configure adapter */
326 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
327 if((unit
->flags
& IFF_CONFIGURED
) == 0)
329 CopyMem(request
->ios2_SrcAddr
, unit
->dev_addr
, ETH_ADDRESSSIZE
);
330 unit
->set_mac_address(unit
);
331 unit
->flags
|= IFF_CONFIGURED
;
335 request
->ios2_Req
.io_Error
= S2ERR_BAD_STATE
;
336 request
->ios2_WireError
= S2WERR_IS_CONFIGURED
;
344 static BOOL
CmdBroadcast(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
346 /* Fill in the broadcast address as destination */
348 memset(request
->ios2_DstAddr
, 0xff, 6);
350 /* Queue the write as normal */
352 return CmdWrite(LIBBASE
, request
);
355 static BOOL
CmdTrackType(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
358 struct Opener
*opener
;
359 ULONG packet_type
, wire_error
=0;
360 struct TypeTracker
*tracker
;
361 struct TypeStats
*initial_stats
;
364 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
365 packet_type
= request
->ios2_PacketType
;
367 /* Get global tracker */
369 tracker
= (struct TypeTracker
*)
370 FindTypeStats(LIBBASE
, unit
, &unit
->type_trackers
, packet_type
);
373 tracker
->user_count
++;
377 AllocMem(sizeof(struct TypeTracker
), MEMF_PUBLIC
|MEMF_CLEAR
);
380 tracker
->packet_type
= packet_type
;
381 tracker
->user_count
= 1;
384 AddTail((APTR
)&unit
->type_trackers
, (APTR
)tracker
);
389 /* Store initial figures for this opener */
391 opener
= request
->ios2_BufferManagement
;
392 initial_stats
= FindTypeStats(LIBBASE
, unit
, &opener
->initial_stats
, packet_type
);
394 if(initial_stats
!= NULL
)
396 error
= S2ERR_BAD_STATE
;
397 wire_error
= S2WERR_ALREADY_TRACKED
;
402 initial_stats
= AllocMem(sizeof(struct TypeStats
), MEMF_PUBLIC
);
403 if(initial_stats
== NULL
)
405 error
= S2ERR_NO_RESOURCES
;
406 wire_error
= S2WERR_GENERIC_ERROR
;
412 CopyMem(tracker
, initial_stats
, sizeof(struct TypeStats
));
413 AddTail((APTR
)&opener
->initial_stats
, (APTR
)initial_stats
);
418 request
->ios2_Req
.io_Error
= error
;
419 request
->ios2_WireError
= wire_error
;
423 static BOOL
CmdUntrackType(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
426 struct Opener
*opener
;
428 struct TypeTracker
*tracker
;
429 struct TypeStats
*initial_stats
;
431 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
432 packet_type
= request
->ios2_PacketType
;
434 /* Get global tracker and initial figures */
436 tracker
= (struct TypeTracker
*)
437 FindTypeStats(LIBBASE
, unit
, &unit
->type_trackers
, packet_type
);
438 opener
= request
->ios2_BufferManagement
;
439 initial_stats
= FindTypeStats(LIBBASE
, unit
, &opener
->initial_stats
, packet_type
);
441 /* Decrement tracker usage and free unused structures */
443 if(initial_stats
!= NULL
)
445 if((--tracker
->user_count
) == 0)
448 Remove((APTR
)tracker
);
450 FreeMem(tracker
, sizeof(struct TypeTracker
));
453 Remove((APTR
)initial_stats
);
454 FreeMem(initial_stats
, sizeof(struct TypeStats
));
458 request
->ios2_Req
.io_Error
= S2ERR_BAD_STATE
;
459 request
->ios2_WireError
= S2WERR_NOT_TRACKED
;
467 static BOOL
CmdGetTypeStats(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
470 struct Opener
*opener
;
472 struct TypeStats
*initial_stats
, *tracker
;
473 struct Sana2PacketTypeStats
*stats
;
475 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
476 packet_type
= request
->ios2_PacketType
;
478 /* Get global tracker and initial figures */
480 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->type_trackers
, packet_type
);
481 opener
= request
->ios2_BufferManagement
;
482 initial_stats
= FindTypeStats(LIBBASE
, unit
, &opener
->initial_stats
, packet_type
);
484 /* Copy and adjust figures */
485 if(initial_stats
!= NULL
)
487 stats
= request
->ios2_StatData
;
488 CopyMem(&tracker
->stats
, stats
, sizeof(struct Sana2PacketTypeStats
));
489 stats
->PacketsSent
-= initial_stats
->stats
.PacketsSent
;
490 stats
->PacketsReceived
-= initial_stats
->stats
.PacketsReceived
;
491 stats
->BytesSent
-= initial_stats
->stats
.BytesSent
;
492 stats
->BytesReceived
-= initial_stats
->stats
.BytesReceived
;
493 stats
->PacketsDropped
-= initial_stats
->stats
.PacketsDropped
;
497 request
->ios2_Req
.io_Error
= S2ERR_BAD_STATE
;
498 request
->ios2_WireError
= S2WERR_NOT_TRACKED
;
506 static BOOL
CmdGetGlobalStats(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
510 /* Update and copy stats */
512 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
513 CopyMem(&unit
->stats
, request
->ios2_StatData
,
514 sizeof(struct Sana2DeviceStats
));
521 static BOOL
CmdDeviceQuery(LIBBASETYPEPTR LIBBASE
, 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
;
543 static BOOL
CmdOnEvent(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
546 ULONG events
, wanted_events
;
547 BOOL complete
= FALSE
;
549 /* Check if we understand the event types */
551 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
552 wanted_events
= request
->ios2_WireError
;
553 if((wanted_events
& ~KNOWN_EVENTS
) != 0)
555 request
->ios2_Req
.io_Error
= S2ERR_NOT_SUPPORTED
;
556 events
= S2WERR_BAD_EVENT
;
560 if((unit
->flags
& IFF_UP
) != 0)
561 events
= S2EVENT_ONLINE
;
563 events
= S2EVENT_OFFLINE
;
565 events
&= wanted_events
;
568 /* Reply request if a wanted event has already occurred */
572 request
->ios2_WireError
= events
;
577 request
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
578 PutMsg(unit
->request_ports
[EVENT_QUEUE
], (APTR
)request
);
586 static BOOL
CmdReadOrphan(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
591 BOOL complete
= FALSE
;
593 /* Check request is valid */
595 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
596 if((unit
->flags
& IFF_UP
) == 0)
598 error
= S2ERR_OUTOFSERVICE
;
599 wire_error
= S2WERR_UNIT_OFFLINE
;
606 request
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
607 PutMsg(unit
->request_ports
[ADOPT_QUEUE
], (struct Message
*)request
);
611 request
->ios2_Req
.io_Error
= error
;
612 request
->ios2_WireError
= wire_error
;
621 static BOOL
CmdOnline(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
623 struct NFUnit
*unit
= (struct NFUnit
*)request
->ios2_Req
.io_Unit
;
625 ULONG wire_error
= 0;
628 /* Check request is valid */
629 if((unit
->flags
& IFF_CONFIGURED
) == 0)
631 error
= S2ERR_BAD_STATE
;
632 wire_error
= S2WERR_NOT_CONFIGURED
;
635 /* Clear global and special stats and put adapter back online */
637 if((error
== 0) && ((unit
->flags
& IFF_UP
) == 0))
639 unit
->stats
.PacketsReceived
= 0;
640 unit
->stats
.PacketsSent
= 0;
641 unit
->stats
.BadData
= 0;
642 unit
->stats
.Overruns
= 0;
643 unit
->stats
.UnknownTypesReceived
= 0;
644 unit
->stats
.Reconfigurations
= 0;
646 for(i
= 0; i
< STAT_COUNT
; i
++)
647 unit
->special_stats
[i
] = 0;
649 if (unit
->start(unit
))
651 error
= S2ERR_OUTOFSERVICE
;
652 wire_error
= S2WERR_GENERIC_ERROR
;
658 request
->ios2_Req
.io_Error
= error
;
659 request
->ios2_WireError
= wire_error
;
663 static BOOL
CmdOffline(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
667 /* Put adapter offline */
669 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
670 if((unit
->flags
& IFF_UP
) != 0)
677 static BOOL
CmdAddMulticastAddresses(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
680 UBYTE
*lower_bound
, *upper_bound
;
682 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
684 lower_bound
= request
->ios2_SrcAddr
;
685 if(request
->ios2_Req
.io_Command
== S2_ADDMULTICASTADDRESS
)
686 upper_bound
= lower_bound
;
688 upper_bound
= request
->ios2_DstAddr
;
690 if(!AddMulticastRange(LIBBASE
, unit
, lower_bound
, upper_bound
))
692 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
693 request
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
701 static BOOL
CmdDelMulticastAddresses(LIBBASETYPEPTR LIBBASE
, struct IOSana2Req
*request
)
704 UBYTE
*lower_bound
, *upper_bound
;
706 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
708 lower_bound
= request
->ios2_SrcAddr
;
709 if(request
->ios2_Req
.io_Command
== S2_DELMULTICASTADDRESS
)
710 upper_bound
= lower_bound
;
712 upper_bound
= request
->ios2_DstAddr
;
714 if(!RemMulticastRange(LIBBASE
, unit
, lower_bound
, upper_bound
))
716 request
->ios2_Req
.io_Error
= S2ERR_BAD_STATE
;
717 request
->ios2_WireError
= S2WERR_BAD_MULTICAST
;