7 #include "rndis.class.h"
9 AROS_UFH3(DEVBASETYPEPTR
, devInit
,
10 AROS_UFHA(DEVBASETYPEPTR
, base
, D0
),
11 AROS_UFHA(BPTR
, seglist
, A0
),
12 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
16 KPRINTF(10, ("devInit base: 0x%08lx seglist: 0x%08lx SysBase: 0x%08lx\n",
17 base
, seglist
, SysBase
));
19 base
->np_Library
.lib_Node
.ln_Type
= NT_DEVICE
;
20 base
->np_Library
.lib_Node
.ln_Name
= DEVNAME
;
21 base
->np_Library
.lib_Flags
= LIBF_SUMUSED
|LIBF_CHANGED
;
22 base
->np_Library
.lib_Version
= VERSION_NUMBER
;
23 base
->np_Library
.lib_Revision
= REVISION_NUMBER
;
24 base
->np_Library
.lib_IdString
= VERSION_STRING
;
27 base
->np_SegList
= seglist
;
29 if((base
->np_UtilityBase
= OpenLibrary("utility.library", 0)))
31 KPRINTF(10, ("devInit: Ok\n"));
32 KPRINTF(10, ("devInit: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
45 #define UtilityBase base->np_UtilityBase
47 AROS_LH3(DEVBASETYPEPTR
, devOpen
,
48 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
49 AROS_LHA(ULONG
, unit
, D0
),
50 AROS_LHA(ULONG
, flags
, D1
),
51 DEVBASETYPEPTR
, base
, 1, dev
)
55 struct NepClassEth
*ncp
;
56 struct TagItem
*taglist
;
58 KPRINTF(10, ("devOpen ioreq: 0x%08lx unit: %ld flags: 0x%08lx base: 0x%08lx\n",
59 ioreq
, unit
, flags
, base
));
61 ++base
->np_Library
.lib_OpenCnt
;
62 base
->np_Library
.lib_Flags
&= ~LIBF_DELEXP
;
64 KPRINTF(10, ("devOpen: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
65 /* Damn f*cking programs which leave this field to zero! */
66 if(ioreq
->ios2_Req
.io_Message
.mn_Length
&& (ioreq
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
)))
68 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
69 ioreq
->ios2_Req
.io_Message
.mn_Length
, sizeof(struct IOSana2Req
)));
71 ioreq
->ios2_Req
.io_Error
= IOERR_BADLENGTH
;
73 /* Default to open failure. */
74 ioreq
->ios2_Req
.io_Error
= IOERR_OPENFAIL
;
76 ioreq
->ios2_Req
.io_Unit
= NULL
;
77 ncp
= (struct NepClassEth
*) base
->np_ClsBase
->nh_Units
.lh_Head
;
78 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
80 if(ncp
->ncp_UnitNo
== unit
)
82 if(ncp
->ncp_OpenFlags
& SANA2OPF_MINE
)
84 ioreq
->ios2_Req
.io_Error
= IOERR_UNITBUSY
;
86 ioreq
->ios2_Req
.io_Unit
= (struct Unit
*) ncp
;
90 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
93 if(!ioreq
->ios2_Req
.io_Unit
)
95 ioreq
->ios2_Req
.io_Error
= IOERR_OPENFAIL
;
96 KPRINTF(20, ("devOpen: could not open unit!\n"));
98 ncp
->ncp_OpenFlags
|= flags
;
100 /* Got taglist? (don't fail if not available!) */
101 taglist
= (struct TagItem
*) ioreq
->ios2_BufferManagement
;
104 struct BufMan
*bufman
;
106 bufman
= (struct BufMan
*) AllocVec(sizeof(struct BufMan
), MEMF_CLEAR
|MEMF_PUBLIC
);
109 /* Get copyfrom routines */
110 bufman
->bm_CopyFromBuf
= (APTR
) GetTagData(S2_CopyFromBuff
, (IPTR
) NULL
, taglist
);
111 bufman
->bm_CopyToBuf
= (APTR
) GetTagData(S2_CopyToBuff
, (IPTR
) NULL
, taglist
);
113 /* This is new SANA-II V2 addition */
114 bufman
->bm_PacketFilter
= (APTR
) GetTagData(S2_PacketFilter
, (IPTR
) NULL
, taglist
);
116 /* These are new SANA-II V3 addition */
117 bufman
->bm_DMACopyFromBuf32
= (APTR
) GetTagData(S2_DMACopyFromBuff32
, (IPTR
) NULL
, taglist
);
118 bufman
->bm_DMACopyToBuf32
= (APTR
) GetTagData(S2_DMACopyToBuff32
, (IPTR
) NULL
, taglist
);
120 /* Init the list for CMD_READ requests */
121 NewList((struct List
*) &bufman
->bm_RXQueue
);
123 /* Add the new bufman to global bufmanlist */
124 KPRINTF(5, ("Open_Unit: added bufman at 0x%08lx\n", bufman
));
126 AddHead((struct List
*) &ncp
->ncp_BufManList
, (struct Node
*) bufman
);
129 ioreq
->ios2_BufferManagement
= bufman
;
131 KPRINTF(5, ("Open_Unit:\n"
132 "copyfrombuf: 0x%08lx copytobuf: 0x%08lx packetfilter: 0x%08lx\n"
133 "dmacopyfrombuf32: 0x%08lx dmacopytobuf32: 0x%08lx\n",
134 bufman
->bm_CopyFromBuf
, bufman
->bm_CopyToBuf
, bufman
->bm_PacketFilter
,
135 bufman
->bm_DMACopyFromBuf32
, bufman
->bm_DMACopyToBuf32
));
138 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
139 ioreq
->ios2_Req
.io_Error
= 0;
140 ioreq
->ios2_Req
.io_Unit
->unit_OpenCnt
++;
143 //ncp->ncp_DenyRequests = FALSE;
149 ioreq
->ios2_Req
.io_Unit
= (APTR
) -1;
150 ioreq
->ios2_Req
.io_Device
= (APTR
) -1;
151 base
->np_Library
.lib_OpenCnt
--;
159 AROS_LH1(BPTR
, devClose
,
160 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
161 DEVBASETYPEPTR
, base
, 2, dev
)
166 struct NepClassEth
*ncp
= (struct NepClassEth
*) ioreq
->ios2_Req
.io_Unit
;
167 struct BufMan
*bufman
;
169 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
173 //ncp->ncp_DenyRequests = TRUE;
175 ncp
->ncp_Unit
.unit_OpenCnt
--;
176 if(ncp
->ncp_Unit
.unit_OpenCnt
== 1)
178 ncp
->ncp_OpenFlags
= 0; // clear all flags, if all units are closed
181 ioreq
->ios2_Req
.io_Unit
= (APTR
) -1;
182 ioreq
->ios2_Req
.io_Device
= (APTR
) -1;
184 bufman
= ioreq
->ios2_BufferManagement
;
187 KPRINTF(5, ("Close_Unit: remove bufman at 0x%08lx\n", bufman
));
188 ioreq
->ios2_BufferManagement
= NULL
;
191 Remove((struct Node
*) bufman
);
196 if(--base
->np_Library
.lib_OpenCnt
== 0)
198 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
200 KPRINTF(5, ("devClose: calling expunge...\n"));
201 ret
= AROS_LC1(BPTR
, devExpunge
,
202 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
203 DEVBASETYPEPTR
, base
, 3, dev
);
207 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
215 AROS_LH1(BPTR
, devExpunge
,
216 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
217 DEVBASETYPEPTR
, base
, 3, dev
)
223 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
227 if(base
->np_Library
.lib_OpenCnt
== 0)
229 KPRINTF(5, ("devExpunge: Unloading...\n"));
231 CloseLibrary(base
->np_UtilityBase
);
233 ret
= base
->np_SegList
;
235 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
236 &base
->np_Library
.lib_Node
));
237 Remove(&base
->np_Library
.lib_Node
);
239 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
240 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
241 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
243 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
249 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
250 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
258 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
259 DEVBASETYPEPTR
, base
, 4, dev
)
268 *======================================================================
269 * cmdRead(ioreq, base)
270 *======================================================================
272 * This is the device CMD_READ routine.
274 * First it check if nic is in proper state and if user passed arguments
275 * are valid. If everything is ok, the request is linked to queue of
276 * pending read requests.
278 * The request is replied only when packet matching it's ios2_PacketType
279 * arrive, or if user abort the request with AbortIO().
283 WORD
cmdRead(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
285 struct BufMan
*bufman
;
286 KPRINTF(1, ("CMD_READ ioreq: 0x%08lx type: %lu\n", ioreq
, ioreq
->ios2_PacketType
));
289 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
291 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
295 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
297 return deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
);
300 /* Valid bufman? Got copytobuf routine? */
301 bufman
= ioreq
->ios2_BufferManagement
;
302 if((!bufman
) || (!bufman
->bm_CopyToBuf
))
304 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
308 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
310 /* Add to this ioreq's bufman rxqueue */
312 AddTail((struct List
*) &bufman
->bm_RXQueue
, (struct Node
*) ioreq
);
314 /* Don't reply the ioreq, it's pending
321 *======================================================================
322 * cmdWrite(ioreq, base)
323 *======================================================================
325 * This is the device CMD_WRITE routine.
327 * First it check if nic is in proper state and if user passed arguments
328 * are valid. If everything is ok, the request is linked to queue of
329 * pending write requests.
331 * The request is replied as soon as the write has been processed or if
332 * user abort the request with AbortIO().
336 WORD
cmdWrite(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
338 struct BufMan
*bufman
;
341 KPRINTF(1, ("CMD_WRITE ioreq: 0x%08lx type: %lu len: %lu\n",
342 ioreq
, ioreq
->ios2_PacketType
, ioreq
->ios2_DataLength
));
345 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
347 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
351 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
353 return deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
);
356 /* Valid bufman? got copyfrombuf routine? */
357 bufman
= ioreq
->ios2_BufferManagement
;
358 if((!bufman
) || (!bufman
->bm_CopyFromBuf
))
360 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
363 /* Check packet size */
364 size
= (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) ? RAWPKT_SIZE
: ETHERPKT_SIZE
;
365 if(ioreq
->ios2_DataLength
> size
)
367 /* Trigger any tx or generic error events */
368 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
369 return deverror(S2ERR_MTU_EXCEEDED
, S2WERR_GENERIC_ERROR
);
373 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
375 AddTail(&ncp
->ncp_WriteQueue
, &ioreq
->ios2_Req
.io_Message
.mn_Node
);
376 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
378 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
381 /* Don't reply the ioreq, it's pending */
387 *======================================================================
388 * cmdFlush(ioreq, base)
389 *======================================================================
391 * This is the device CMD_FLUSH routine.
393 * This routine abort all pending read, write and event requests.
397 WORD
cmdFlush(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
399 struct BufMan
*bufman
;
401 KPRINTF(1, ("CMD_FLUSH ioreq: 0x%08lx\n", ioreq
));
403 bufman
= ioreq
->ios2_BufferManagement
;
407 AbortRW(ncp
, bufman
, deverror(IOERR_ABORTED
, S2WERR_GENERIC_ERROR
));
408 AbortList(ncp
, &ncp
->ncp_EventList
, bufman
, deverror(IOERR_ABORTED
, S2WERR_GENERIC_ERROR
));
418 *======================================================================
419 * cmdDeviceQuery(ioreq, base)
420 *======================================================================
422 * This is the device S2_DEVICEQUERY routine.
424 * This routine return various parameters for this network interface.
429 const struct Sana2DeviceQuery DeviceQueryBlock
[] =
432 sizeof(struct Sana2DeviceQuery
), sizeof(struct Sana2DeviceQuery
),
442 WORD
cmdDeviceQuery(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
444 struct Sana2DeviceQuery
*query
;
446 KPRINTF(1, ("S2_DEVICEQUERY ioreq: 0x%08lx\n", ioreq
));
449 query
= (struct Sana2DeviceQuery
*) ioreq
->ios2_StatData
;
452 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
455 /* Enough space to store the info ? */
456 if(query
->SizeAvailable
< sizeof(struct Sana2DeviceQuery
))
458 KPRINTF(1, ("S2_DEVICEQUERY: too small buffer supplied! (%lu / %lu)\n",
459 query
->SizeAvailable
, sizeof(struct Sana2DeviceQuery
)));
461 query
->SizeSupplied
= 0;
462 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_BAD_STATDATA
);
465 CopyMem(&((struct Sana2DeviceQuery
*) DeviceQueryBlock
)->SizeSupplied
, &query
->SizeSupplied
, sizeof(struct Sana2DeviceQuery
) - sizeof(ULONG
));
472 *======================================================================
473 * cmdGetStationAddress(ioreq, base)
474 *======================================================================
476 * This is the device S2_GETSTATIONADDRESS routine.
478 * This routine return current and default interface hardware addresses.
482 WORD
cmdGetStationAddress(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
486 KPRINTF(1, ("S2_GETSTATIONADDRESS ioreq: 0x%08lx\n", ioreq
));
488 /* Source address = current station address
489 Dest address = default station address
491 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
493 ioreq
->ios2_SrcAddr
[cnt
] = ncp
->ncp_MacAddress
[cnt
];
494 ioreq
->ios2_DstAddr
[cnt
] = ncp
->ncp_ROMAddress
[cnt
];
498 for(; cnt
< SANA2_MAX_ADDR_BYTES
; cnt
++)
500 ioreq
->ios2_SrcAddr
[cnt
] = 0;
501 ioreq
->ios2_DstAddr
[cnt
] = 0;
508 WORD
cmdConfigInterface(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
514 KPRINTF(1, ("S2_CONFIGINTERFACE ioreq: 0x%08lx\n", ioreq
));
516 /* This stuff must be atomic */
519 if(ncp
->ncp_StateFlags
& DDF_CONFIGURED
)
522 /* Error, already configured */
523 return deverror(S2ERR_BAD_STATE
, S2WERR_IS_CONFIGURED
);
526 /* Check for valid address */
527 if(*((LONG
*) ioreq
->ios2_SrcAddr
) <= 0)
530 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_SRC_ADDRESS
);
533 /* Copy the address */
534 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
536 ncp
->ncp_MacAddress
[cnt
] = ioreq
->ios2_SrcAddr
[cnt
];
539 ncp
->ncp_StateFlags
|= DDF_CONFIGURED
;
540 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
542 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
545 KPRINTF(1, ("S2_CONFIGINTERFACE ok/n"));
550 WORD
cmdAddMulticastAddress(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
553 KPRINTF(1, ("S2_ADDMULTICASTADDRESS 0x%08lx%04lx\n",
554 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2]));
556 return AddMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_SrcAddr
);
559 WORD
cmdDelMulticastAddress(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
561 KPRINTF(1, ("S2_DELMULTICASTADDRESS 0x%08lx%04lx\n",
562 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2]));
564 return DelMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_SrcAddr
);
567 WORD
cmdAddMulticastAddresses(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
569 KPRINTF(1, ("S2_ADDMULTICASTADDRESSES 0x%08lx%04lx - 0x%08lx%04lx\n",
570 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2],
571 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
573 return AddMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_DstAddr
);
576 WORD
cmdDelMulticastAddresses(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
578 KPRINTF(1, ("S2_DELMULTICASTADDRESSES 0x%08lx%04lx - 0x%08lx%04lx\n",
579 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2],
580 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
582 return DelMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_DstAddr
);
585 #define mcmp(a,b) (memcmp(a,b,ETHER_ADDR_SIZE)==0)
587 WORD
AddMCastRange(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
, UBYTE
*lower
, UBYTE
*upper
)
589 struct MulticastAddressRange
*mar
;
592 /* Valid multicast addresses? */
593 if(((lower
[0] & 1) == 0) || ((upper
[0] & 1) == 0))
595 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_BAD_MULTICAST
);
598 /* Lock access to list */
601 /* Find matching node */
602 mar
= (struct MulticastAddressRange
*) ncp
->ncp_Multicasts
.lh_Head
;
603 while(mar
->mar_Node
.ln_Succ
)
605 if(mcmp(lower
, mar
->mar_LowerAddr
) &&
606 mcmp(upper
, mar
->mar_UpperAddr
))
610 mar
= (struct MulticastAddressRange
*) mar
->mar_Node
.ln_Succ
;
613 if(!mar
->mar_Node
.ln_Succ
)
616 mar
= AllocVec(sizeof(struct MulticastAddressRange
), MEMF_CLEAR
|MEMF_PUBLIC
);
620 return deverror(S2ERR_NO_RESOURCES
, S2WERR_GENERIC_ERROR
);
622 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
624 mar
->mar_LowerAddr
[cnt
] = *lower
++;
625 mar
->mar_UpperAddr
[cnt
] = *upper
++;
627 mar
->mar_UseCount
= 1;
628 AddTail(&ncp
->ncp_Multicasts
, (struct Node
*) mar
);
641 WORD
DelMCastRange(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
, UBYTE
*lower
, UBYTE
*upper
)
643 struct MulticastAddressRange
*mar
;
645 /* Lock access to list */
648 /* Find matching node */
649 mar
= (struct MulticastAddressRange
*) ncp
->ncp_Multicasts
.lh_Head
;
650 while(mar
->mar_Node
.ln_Succ
)
652 if(mcmp(lower
, mar
->mar_LowerAddr
) &&
653 mcmp(upper
, mar
->mar_UpperAddr
))
655 if(!--mar
->mar_UseCount
)
657 Remove((struct Node
*) mar
);
666 mar
= (struct MulticastAddressRange
*) mar
->mar_Node
.ln_Succ
;
670 /* Return with failure */
671 return deverror(S2ERR_BAD_STATE
, S2WERR_BAD_MULTICAST
);
674 WORD
cmdMulticast(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
676 KPRINTF(1, ("S2_MULTICAST ioreq: 0x%08lx to: 0x%08lx%04lx\n",
678 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
680 /* Is dest a multicast address? */
681 if(ioreq
->ios2_DstAddr
[0] & 1)
683 return cmdWrite(ncp
, ioreq
);
686 /* Trigger any tx or generic error events */
687 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
689 /* Wasn't a multicast addr */
690 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_BAD_MULTICAST
);
693 WORD
cmdBroadcast(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
696 KPRINTF(1, ("S2_BROADCAST ioreq: 0x%08lx\n", ioreq
));
698 /* Dest address = broadcast */
699 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
701 ioreq
->ios2_DstAddr
[cnt
] = 0xff;
703 return cmdWrite(ncp
, ioreq
);
707 WORD
cmdTrackType(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
709 struct PacketTypeStats
*pts
;
711 KPRINTF(1, ("S2_TRACKTYPE ioreq: 0x%08lx type: %lu\n",
712 ioreq
, ioreq
->ios2_PacketType
));
715 /* Find matching node */
716 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
717 while(pts
->pts_Node
.ln_Succ
)
719 /* Our packet type? */
720 if(pts
->pts_PacketType
== ioreq
->ios2_PacketType
)
723 return deverror(S2ERR_BAD_STATE
, S2WERR_ALREADY_TRACKED
);
725 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;
728 /* Alloc tracking node */
729 pts
= (struct PacketTypeStats
*) AllocVec(sizeof(struct PacketTypeStats
), MEMF_CLEAR
|MEMF_PUBLIC
);
732 return deverror(S2ERR_NO_RESOURCES
, S2WERR_NOT_TRACKED
);
734 /* Set up tracking node */
735 pts
->pts_PacketType
= ioreq
->ios2_PacketType
;
737 /* Add the new node to tracklist */
738 AddTail((struct List
*) &ncp
->ncp_TrackList
, (struct Node
*) pts
);
740 if(pts
->pts_PacketType
== 2048)
742 ncp
->ncp_TypeStats2048
= &pts
->pts_Stats
;
744 else if(pts
->pts_PacketType
== 2054)
746 ncp
->ncp_TypeStats2054
= &pts
->pts_Stats
;
755 WORD
cmdUntrackType(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
757 struct PacketTypeStats
*pts
;
758 KPRINTF(1, ("S2_UNTRACKTYPE ioreq: 0x%08lx type: %lu\n",
759 ioreq
, ioreq
->ios2_PacketType
));
762 /* Find matching node */
763 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
764 while(pts
->pts_Node
.ln_Succ
)
766 /* Our packet type? */
767 if(pts
->pts_PacketType
== ioreq
->ios2_PacketType
)
769 Remove(&pts
->pts_Node
);
771 if(pts
->pts_PacketType
== 2048)
773 ncp
->ncp_TypeStats2048
= NULL
;
775 else if(pts
->pts_PacketType
== 2054)
777 ncp
->ncp_TypeStats2054
= NULL
;
784 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;
788 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_TRACKED
);
792 WORD
cmdGetTypeStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
794 struct Sana2PacketTypeStats
*tostats
;
795 struct Sana2PacketTypeStats
*fromstats
;
797 KPRINTF(1, ("S2_GETTYPESTATS ioreq: 0x%08lx type: %lu\n",
798 ioreq
, ioreq
->ios2_PacketType
));
801 tostats
= (struct Sana2PacketTypeStats
*) ioreq
->ios2_StatData
;
804 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
808 fromstats
= FindPacketTypeStats(ncp
, ioreq
->ios2_PacketType
);
812 CopyMem(fromstats
, tostats
, sizeof(struct Sana2PacketTypeStats
));
821 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_TRACKED
);
825 WORD
cmdGetSpecialStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
827 struct Sana2SpecialStatHeader
*stats
;
828 struct Sana2SpecialStatRecord
*record
;
831 KPRINTF(1, ("S2_GETSPECIALSTATS ioreq: 0x%08lx\n", ioreq
));
834 stats
= (struct Sana2SpecialStatHeader
*) ioreq
->ios2_StatData
;
837 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
840 stats
->RecordCountSupplied
= 0;
841 maxcount
= stats
->RecordCountMax
;
842 record
= (struct Sana2SpecialStatRecord
*) (stats
+ 1);
846 stats
->RecordCountSupplied
++;
848 record
->Type
= S2SS_ETHERNET_BADMULTICAST
;
849 record
->Count
= ncp
->ncp_BadMulticasts
;
850 record
->String
= "bad multicasts";
855 stats
->RecordCountSupplied
++;
857 record
->Type
= S2SS_ETHERNET_RETRIES
;
858 record
->Count
= ncp
->ncp_Retries
;
859 record
->String
= "retries";
869 WORD
cmdGetGlobalStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
871 struct Sana2DeviceStats
*stats
;
873 KPRINTF(1, ("S2_GETGLOBALSTATS ioreq: 0x%08lx\n", ioreq
));
876 stats
= (struct Sana2DeviceStats
*) ioreq
->ios2_StatData
;
879 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
882 CopyMem(&ncp
->ncp_DeviceStats
, stats
, sizeof(struct Sana2DeviceStats
));
889 #define KNOWN_EVENTS (S2EVENT_ERROR | \
897 WORD
cmdOnEvent(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
899 KPRINTF(1, ("S2_ONEVENT ioreq: 0x%08lx mask: 0x%08lx\n", ioreq
,
900 ioreq
->ios2_WireError
));
902 /* Do we know the requested events? */
903 if(ioreq
->ios2_WireError
& (~KNOWN_EVENTS
))
905 return deverror(S2ERR_NOT_SUPPORTED
, S2WERR_BAD_EVENT
);
908 /* If online return S2EVENT_ONLINE immediately
909 If offline return S2EVENT_OFFLINE immediately. */
910 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
912 if(ioreq
->ios2_WireError
& S2EVENT_ONLINE
)
914 ioreq
->ios2_WireError
= S2EVENT_ONLINE
;
920 if(ioreq
->ios2_WireError
& S2EVENT_OFFLINE
)
922 ioreq
->ios2_WireError
= S2EVENT_OFFLINE
;
930 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
932 /* Queue the ioreq */
934 AddTail((struct List
*) &ncp
->ncp_EventList
, (struct Node
*) ioreq
);
937 /* Don't reply the ioreq, it's pending */
942 WORD
cmdReadOrphan(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
944 struct BufMan
*bufman
;
946 KPRINTF(1, ("S2_READORPHAN ioreq: 0x%08lx type: %lu\n", ioreq
,
947 ioreq
->ios2_PacketType
));
950 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
952 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
956 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
958 return deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
);
961 /* Valid bufman? got copytobuf routine? */
962 bufman
= ioreq
->ios2_BufferManagement
;
963 if((!bufman
) || (!bufman
->bm_CopyToBuf
))
965 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
969 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
971 /* Queue the ioreq */
973 AddTail((struct List
*) &ncp
->ncp_OrphanQueue
, (struct Node
*) ioreq
);
976 /* Don't reply the ioreq, it's pending */
981 WORD
cmdOnline(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
983 KPRINTF(1, ("S2_ONLINE ioreq: 0x%08lx\n", ioreq
));
986 /* Already online? */
987 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
990 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
993 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
996 /* Mark no longer offline */
997 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
999 /* Mark being online */
1000 ncp
->ncp_StateFlags
|= DDF_ONLINE
;
1001 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
1003 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
1007 /* Trigger any ONLINE events */
1008 nDoEvent(ncp
, S2EVENT_ONLINE
);
1014 /* Return success */
1019 WORD
cmdOffline(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1022 KPRINTF(1, ("S2_OFFLINE ioreq: 0x%08lx\n", ioreq
));
1025 /* Mark being offline */
1026 ncp
->ncp_StateFlags
|= DDF_OFFLINE
;
1028 /* Already offline? */
1029 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
1031 /* Mark no longer online */
1032 ncp
->ncp_StateFlags
&= ~DDF_ONLINE
;
1033 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
1035 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
1039 /* *DO NOT* abort pending read & write requests.
1040 Miami dies a horrible death if this is enabled!
1042 if(ioreq
->ios2_BufferManagement
)
1044 AbortRW(ncp
, ioreq
->ios2_BufferManagement
, deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
));
1047 /* Trigger any OFFLINE events */
1048 nDoEvent(ncp
, S2EVENT_OFFLINE
);
1050 /* Don't reply the ioreq, it's pending */
1055 /* Return success */
1060 AROS_LH1(void, devBeginIO
,
1061 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
1062 DEVBASETYPEPTR
, base
, 5, dev
)
1066 struct NepClassEth
*ncp
= (struct NepClassEth
*) ioreq
->ios2_Req
.io_Unit
;
1067 WORD ret
= IOERR_NOCMD
;
1069 KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq
, base
, ioreq
->ios2_Req
.io_Command
));
1071 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
1072 ioreq
->ios2_Req
.io_Error
= 0;
1074 if(ioreq
->ios2_Req
.io_Command
< NSCMD_DEVICEQUERY
)
1076 switch(ioreq
->ios2_Req
.io_Command
)
1079 ret
= cmdRead(ncp
, ioreq
);
1083 ret
= cmdFlush(ncp
, ioreq
);
1087 ret
= cmdWrite(ncp
, ioreq
);
1090 case S2_GETSTATIONADDRESS
:
1091 ret
= cmdGetStationAddress(ncp
, ioreq
);
1094 case S2_DEVICEQUERY
:
1095 ret
= cmdDeviceQuery(ncp
, ioreq
);
1098 case S2_CONFIGINTERFACE
:
1099 ret
= cmdConfigInterface(ncp
, ioreq
);
1102 case S2_ADDMULTICASTADDRESS
:
1103 ret
= cmdAddMulticastAddress(ncp
, ioreq
);
1106 case S2_DELMULTICASTADDRESS
:
1107 ret
= cmdDelMulticastAddress(ncp
, ioreq
);
1111 ret
= cmdMulticast(ncp
, ioreq
);
1115 ret
= cmdBroadcast(ncp
, ioreq
);
1119 ret
= cmdTrackType(ncp
, ioreq
);
1122 case S2_UNTRACKTYPE
:
1123 ret
= cmdUntrackType(ncp
, ioreq
);
1126 case S2_GETTYPESTATS
:
1127 ret
= cmdGetTypeStats(ncp
, ioreq
);
1130 case S2_GETSPECIALSTATS
:
1131 ret
= cmdGetSpecialStats(ncp
, ioreq
);
1134 case S2_GETGLOBALSTATS
:
1135 ret
= cmdGetGlobalStats(ncp
, ioreq
);
1139 ret
= cmdOnEvent(ncp
, ioreq
);
1143 ret
= cmdReadOrphan(ncp
, ioreq
);
1147 ret
= cmdOnline(ncp
, ioreq
);
1151 ret
= cmdOffline(ncp
, ioreq
);
1159 switch(ioreq
->ios2_Req
.io_Command
)
1161 case NSCMD_DEVICEQUERY
:
1162 ret
= cmdNSDeviceQuery(ncp
, (struct IOStdReq
*) ioreq
);
1165 case S2_ADDMULTICASTADDRESSES
:
1166 ret
= cmdAddMulticastAddresses(ncp
, ioreq
);
1169 case S2_DELMULTICASTADDRESSES
:
1170 ret
= cmdDelMulticastAddresses(ncp
, ioreq
);
1179 if(ret
!= RC_DONTREPLY
)
1181 KPRINTF(1, ("TermIO\n"));
1184 /* Set error codes */
1185 ioreq
->ios2_Req
.io_Error
= ret
& 0xff;
1187 /* Terminate the iorequest */
1194 AROS_LH1(LONG
, devAbortIO
,
1195 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
1196 DEVBASETYPEPTR
, base
, 6, dev
)
1200 struct NepClassEth
*ncp
= (struct NepClassEth
*) ioreq
->ios2_Req
.io_Unit
;
1201 struct BufMan
*worknode
, *nextnode
;
1203 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
1205 /* Is it pending? */
1207 if(ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
1210 switch (ioreq
->ios2_Req
.io_Command
)
1213 /* Check all nodes in dd_bufmanlist until we succeed to abort or run out of nodes. */
1214 worknode
= (struct BufMan
*) ncp
->ncp_BufManList
.lh_Head
;
1215 while((nextnode
= (struct BufMan
*) (((struct Node
*) worknode
)->ln_Succ
)))
1217 if(AbortReq(ncp
, &worknode
->bm_RXQueue
, ioreq
) == S2ERR_NO_ERROR
)
1219 /* Success, break out */
1222 worknode
= nextnode
;
1227 AbortReq(ncp
, &ncp
->ncp_OrphanQueue
, ioreq
);
1233 AbortReq(ncp
, &ncp
->ncp_WriteQueue
, ioreq
);
1236 // these commands may dispatch their ioreq to the USB task; catch from the message port
1239 case S2_CONFIGINTERFACE
:
1240 case S2_ADDMULTICASTADDRESS
:
1241 case S2_DELMULTICASTADDRESS
:
1242 case S2_ADDMULTICASTADDRESSES
:
1243 case S2_DELMULTICASTADDRESSES
:
1244 AbortReq(ncp
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
, ioreq
);
1248 AbortReq(ncp
, &ncp
->ncp_EventList
, ioreq
);
1252 KPRINTF(1, ("devAbortIO: not READ, READORPHAN, WRITE, MULTICAST, BROADCAST or ONEVENT\n"));
1266 const UWORD NSDSupported
[] =
1268 CMD_FLUSH
, CMD_READ
, CMD_WRITE
,
1270 S2_GETSTATIONADDRESS
,
1272 S2_ADDMULTICASTADDRESS
, S2_DELMULTICASTADDRESS
,
1273 S2_MULTICAST
, S2_BROADCAST
,
1274 S2_TRACKTYPE
, S2_UNTRACKTYPE
,
1275 S2_GETTYPESTATS
, S2_GETSPECIALSTATS
, S2_GETGLOBALSTATS
,
1278 S2_ONLINE
, S2_OFFLINE
,
1280 S2_ADDMULTICASTADDRESSES
, S2_DELMULTICASTADDRESSES
,
1284 WORD
cmdNSDeviceQuery(struct NepClassEth
*ncp
, struct IOStdReq
*ioreq
)
1286 struct my_NSDeviceQueryResult
*query
;
1288 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
1290 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
1297 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
1298 (query
->DevQueryFormat
!= 0) ||
1299 (query
->SizeAvailable
!= 0))
1301 /* Return error. This is special handling, since iorequest is only
1302 guaranteed to be sizeof(struct IOStdReq). If we'd let our
1303 devBeginIO dispatcher return the error, it would trash some
1304 memory past end of the iorequest (ios2_WireError field).
1306 ioreq
->io_Error
= IOERR_NOCMD
;
1307 TermIO(ncp
, (struct IOSana2Req
*) ioreq
);
1309 /* Don't reply, we already did.
1311 return RC_DONTREPLY
;
1314 ioreq
->io_Actual
= query
->SizeAvailable
1315 = sizeof(struct my_NSDeviceQueryResult
);
1316 query
->DeviceType
= NSDEVTYPE_SANA2
;
1317 query
->DeviceSubType
= 0;
1318 query
->SupportedCommands
= NSDSupported
;
1320 /* Return success (note that this will NOT poke ios2_WireError).
1326 *======================================================================
1327 * AbortReq(list, ioreq, base)
1328 *======================================================================
1330 * Locate an IO request in a linked list and abort it if found.
1334 LONG
AbortReq(struct NepClassEth
*ncp
, struct List
*list
, struct IOSana2Req
*ioreq
)
1338 for(node
= list
->lh_Head
; node
->ln_Succ
; node
= node
->ln_Succ
)
1340 if(node
== (struct Node
*) ioreq
)
1342 //KPRINTF(1, ("AbortReq: aborted 0x%08lx\n", ioreq));
1344 Remove(&ioreq
->ios2_Req
.io_Message
.mn_Node
);
1345 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
1346 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
1347 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1349 return S2ERR_NO_ERROR
;
1353 return S2ERR_BAD_STATE
;
1359 *===========================================================
1360 * TermIO(ioreq, base)
1361 *===========================================================
1363 * Return completed ioreq to sender.
1367 void TermIO(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1369 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1371 /* If not quick I/O, reply the message
1373 if(!(ioreq
->ios2_Req
.io_Flags
& IOF_QUICK
))
1375 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1380 *======================================================================
1381 * AbortList(list, bufman, error, base)
1382 *======================================================================
1384 * Aborts all pending ioreqs in given list with io_Error & ios2_WireError
1387 * error is deverror() macro packed error number.
1391 void AbortList(struct NepClassEth
*ncp
, struct List
*list
, struct BufMan
*bufman
, WORD error
)
1393 struct IOSana2Req
*ioreq
, *nextioreq
;
1397 for(ioreq
= (struct IOSana2Req
*) list
->lh_Head
;
1398 (nextioreq
= (struct IOSana2Req
*) ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
);
1401 if(ioreq
->ios2_BufferManagement
== bufman
)
1403 Remove(&ioreq
->ios2_Req
.io_Message
.mn_Node
);
1404 /*ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;*/
1405 ioreq
->ios2_Req
.io_Error
= error
& 0xff;
1406 ioreq
->ios2_WireError
= error
>> 8;
1407 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1413 while((ioreq
= (struct IOSana2Req
*) RemHead(list
)))
1415 /* ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;*/
1416 ioreq
->ios2_Req
.io_Error
= error
& 0xff;
1417 ioreq
->ios2_WireError
= error
>> 8;
1418 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1425 *======================================================================
1426 * AbortRW(bufman, error, base)
1427 *======================================================================
1429 * Aborts all pending reads and writes with io_Error & ios2_WireError
1432 * error is deverror() macro packed error number.
1436 void AbortRW(struct NepClassEth
*ncp
, struct BufMan
*bufman
, WORD error
)
1438 AbortList(ncp
, &bufman
->bm_RXQueue
, NULL
, error
);
1439 AbortList(ncp
, &ncp
->ncp_OrphanQueue
, bufman
, error
);
1440 AbortList(ncp
, &ncp
->ncp_WriteQueue
, bufman
, error
);
1443 struct Sana2PacketTypeStats
* FindPacketTypeStats(struct NepClassEth
*ncp
, ULONG packettype
)
1445 struct PacketTypeStats
*pts
;
1450 return ncp
->ncp_TypeStats2048
;
1454 return ncp
->ncp_TypeStats2054
;
1458 /* Find matching node - slowly */
1459 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
1460 while(pts
->pts_Node
.ln_Succ
)
1462 /* Our packet type? */
1463 if(pts
->pts_PacketType
== packettype
)
1465 return &pts
->pts_Stats
;
1467 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;