1 /* dev.c - usbethwrap.device by Chris Hodges
6 #include "ethwrap.class.h"
8 AROS_UFH3(DEVBASETYPEPTR
, devInit
,
9 AROS_UFHA(DEVBASETYPEPTR
, base
, D0
),
10 AROS_UFHA(BPTR
, seglist
, A0
),
11 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
15 KPRINTF(10, ("devInit base: 0x%08lx seglist: 0x%08lx SysBase: 0x%08lx\n",
16 base
, seglist
, SysBase
));
18 base
->np_Library
.lib_Node
.ln_Type
= NT_DEVICE
;
19 base
->np_Library
.lib_Node
.ln_Name
= DEVNAME
;
20 base
->np_Library
.lib_Flags
= LIBF_SUMUSED
|LIBF_CHANGED
;
21 base
->np_Library
.lib_Version
= VERSION_NUMBER
;
22 base
->np_Library
.lib_Revision
= REVISION_NUMBER
;
23 base
->np_Library
.lib_IdString
= VERSION_STRING
;
26 base
->np_SegList
= seglist
;
28 if((base
->np_UtilityBase
= OpenLibrary("utility.library", 0)))
30 KPRINTF(10, ("devInit: Ok\n"));
31 KPRINTF(10, ("devInit: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
44 #define UtilityBase base->np_UtilityBase
46 AROS_LH3(DEVBASETYPEPTR
, devOpen
,
47 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
48 AROS_LHA(ULONG
, unit
, D0
),
49 AROS_LHA(ULONG
, flags
, D1
),
50 DEVBASETYPEPTR
, base
, 1, dev
)
54 struct NepClassEth
*ncp
;
55 struct TagItem
*taglist
;
57 KPRINTF(10, ("devOpen ioreq: 0x%08lx unit: %ld flags: 0x%08lx base: 0x%08lx\n",
58 ioreq
, unit
, flags
, base
));
60 ++base
->np_Library
.lib_OpenCnt
;
61 base
->np_Library
.lib_Flags
&= ~LIBF_DELEXP
;
63 KPRINTF(10, ("devOpen: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
64 /* Damn f*cking programs which leave this field to zero! */
65 if(ioreq
->ios2_Req
.io_Message
.mn_Length
&& (ioreq
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
)))
67 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
68 ioreq
->ios2_Req
.io_Message
.mn_Length
, sizeof(struct IOSana2Req
)));
70 ioreq
->ios2_Req
.io_Error
= IOERR_BADLENGTH
;
72 /* Default to open failure. */
73 ioreq
->ios2_Req
.io_Error
= IOERR_OPENFAIL
;
75 ioreq
->ios2_Req
.io_Unit
= NULL
;
76 ncp
= (struct NepClassEth
*) base
->np_ClsBase
->nh_Units
.lh_Head
;
77 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
79 if(ncp
->ncp_UnitNo
== unit
)
81 if(ncp
->ncp_OpenFlags
& SANA2OPF_MINE
)
83 ioreq
->ios2_Req
.io_Error
= IOERR_UNITBUSY
;
85 ioreq
->ios2_Req
.io_Unit
= (struct Unit
*) ncp
;
89 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
92 if(!ioreq
->ios2_Req
.io_Unit
)
94 ioreq
->ios2_Req
.io_Error
= IOERR_OPENFAIL
;
95 KPRINTF(20, ("devOpen: could not open unit!\n"));
97 ncp
->ncp_OpenFlags
|= flags
;
99 /* Got taglist? (don't fail if not available!) */
100 taglist
= (struct TagItem
*) ioreq
->ios2_BufferManagement
;
103 struct BufMan
*bufman
;
105 bufman
= (struct BufMan
*) AllocVec(sizeof(struct BufMan
), MEMF_CLEAR
|MEMF_PUBLIC
);
108 /* Get copyfrom routines */
109 bufman
->bm_CopyFromBuf
= (APTR
) GetTagData(S2_CopyFromBuff
, (IPTR
) NULL
, taglist
);
110 bufman
->bm_CopyToBuf
= (APTR
) GetTagData(S2_CopyToBuff
, (IPTR
) NULL
, taglist
);
112 /* This is new SANA-II V2 addition */
113 bufman
->bm_PacketFilter
= (APTR
) GetTagData(S2_PacketFilter
, (IPTR
) NULL
, taglist
);
115 /* These are new SANA-II V3 addition */
116 bufman
->bm_DMACopyFromBuf32
= (APTR
) GetTagData(S2_DMACopyFromBuff32
, (IPTR
) NULL
, taglist
);
117 bufman
->bm_DMACopyToBuf32
= (APTR
) GetTagData(S2_DMACopyToBuff32
, (IPTR
) NULL
, taglist
);
119 /* Init the list for CMD_READ requests */
120 NewList((struct List
*) &bufman
->bm_RXQueue
);
122 /* Add the new bufman to global bufmanlist */
123 KPRINTF(5, ("Open_Unit: added bufman at 0x%08lx\n", bufman
));
125 AddHead((struct List
*) &ncp
->ncp_BufManList
, (struct Node
*) bufman
);
128 ioreq
->ios2_BufferManagement
= bufman
;
130 KPRINTF(5, ("Open_Unit:\n"
131 "copyfrombuf: 0x%08lx copytobuf: 0x%08lx packetfilter: 0x%08lx\n"
132 "dmacopyfrombuf32: 0x%08lx dmacopytobuf32: 0x%08lx\n",
133 bufman
->bm_CopyFromBuf
, bufman
->bm_CopyToBuf
, bufman
->bm_PacketFilter
,
134 bufman
->bm_DMACopyFromBuf32
, bufman
->bm_DMACopyToBuf32
));
137 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
138 ioreq
->ios2_Req
.io_Error
= 0;
139 ioreq
->ios2_Req
.io_Unit
->unit_OpenCnt
++;
142 //ncp->ncp_DenyRequests = FALSE;
148 ioreq
->ios2_Req
.io_Unit
= (APTR
) -1;
149 ioreq
->ios2_Req
.io_Device
= (APTR
) -1;
150 base
->np_Library
.lib_OpenCnt
--;
158 AROS_LH1(BPTR
, devClose
,
159 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
160 DEVBASETYPEPTR
, base
, 2, dev
)
165 struct NepClassEth
*ncp
= (struct NepClassEth
*) ioreq
->ios2_Req
.io_Unit
;
166 struct BufMan
*bufman
;
168 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
172 //ncp->ncp_DenyRequests = TRUE;
174 ncp
->ncp_Unit
.unit_OpenCnt
--;
175 if(ncp
->ncp_Unit
.unit_OpenCnt
== 1)
177 ncp
->ncp_OpenFlags
= 0; // clear all flags, if all units are closed
180 ioreq
->ios2_Req
.io_Unit
= (APTR
) -1;
181 ioreq
->ios2_Req
.io_Device
= (APTR
) -1;
183 bufman
= ioreq
->ios2_BufferManagement
;
186 KPRINTF(5, ("Close_Unit: remove bufman at 0x%08lx\n", bufman
));
187 ioreq
->ios2_BufferManagement
= NULL
;
190 Remove((struct Node
*) bufman
);
195 if(--base
->np_Library
.lib_OpenCnt
== 0)
197 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
199 KPRINTF(5, ("devClose: calling expunge...\n"));
200 ret
= AROS_LC1(BPTR
, devExpunge
,
201 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
202 DEVBASETYPEPTR
, base
, 3, dev
);
206 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
214 AROS_LH1(BPTR
, devExpunge
,
215 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
216 DEVBASETYPEPTR
, base
, 3, dev
)
222 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
226 if(base
->np_Library
.lib_OpenCnt
== 0)
228 KPRINTF(5, ("devExpunge: Unloading...\n"));
230 CloseLibrary(base
->np_UtilityBase
);
232 ret
= base
->np_SegList
;
234 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
235 &base
->np_Library
.lib_Node
));
236 Remove(&base
->np_Library
.lib_Node
);
238 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
239 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
240 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
242 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
248 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
249 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
257 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
258 DEVBASETYPEPTR
, base
, 4, dev
)
267 *======================================================================
268 * cmdRead(ioreq, base)
269 *======================================================================
271 * This is the device CMD_READ routine.
273 * First it check if nic is in proper state and if user passed arguments
274 * are valid. If everything is ok, the request is linked to queue of
275 * pending read requests.
277 * The request is replied only when packet matching it's ios2_PacketType
278 * arrive, or if user abort the request with AbortIO().
282 WORD
cmdRead(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
284 struct BufMan
*bufman
;
285 KPRINTF(1, ("CMD_READ ioreq: 0x%08lx type: %lu\n", ioreq
, ioreq
->ios2_PacketType
));
288 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
290 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
294 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
296 return deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
);
299 /* Valid bufman? Got copytobuf routine? */
300 bufman
= ioreq
->ios2_BufferManagement
;
301 if((!bufman
) || (!bufman
->bm_CopyToBuf
))
303 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
307 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
309 /* Add to this ioreq's bufman rxqueue */
311 AddTail((struct List
*) &bufman
->bm_RXQueue
, (struct Node
*) ioreq
);
313 /* Don't reply the ioreq, it's pending
320 *======================================================================
321 * cmdWrite(ioreq, base)
322 *======================================================================
324 * This is the device CMD_WRITE routine.
326 * First it check if nic is in proper state and if user passed arguments
327 * are valid. If everything is ok, the request is linked to queue of
328 * pending write requests.
330 * The request is replied as soon as the write has been processed or if
331 * user abort the request with AbortIO().
335 WORD
cmdWrite(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
337 struct BufMan
*bufman
;
340 KPRINTF(1, ("CMD_WRITE ioreq: 0x%08lx type: %lu len: %lu\n",
341 ioreq
, ioreq
->ios2_PacketType
, ioreq
->ios2_DataLength
));
344 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
346 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
350 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
352 return deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
);
355 /* Valid bufman? got copyfrombuf routine? */
356 bufman
= ioreq
->ios2_BufferManagement
;
357 if((!bufman
) || (!bufman
->bm_CopyFromBuf
))
359 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
362 /* Check packet size */
363 size
= (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) ? RAWPKT_SIZE
: ETHERPKT_SIZE
;
364 if(ioreq
->ios2_DataLength
> size
)
366 /* Trigger any tx or generic error events */
367 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
368 return deverror(S2ERR_MTU_EXCEEDED
, S2WERR_GENERIC_ERROR
);
372 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
374 AddTail(&ncp
->ncp_WriteQueue
, &ioreq
->ios2_Req
.io_Message
.mn_Node
);
375 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
377 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
380 /* Don't reply the ioreq, it's pending */
386 *======================================================================
387 * cmdFlush(ioreq, base)
388 *======================================================================
390 * This is the device CMD_FLUSH routine.
392 * This routine abort all pending read, write and event requests.
396 WORD
cmdFlush(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
398 struct BufMan
*bufman
;
400 KPRINTF(1, ("CMD_FLUSH ioreq: 0x%08lx\n", ioreq
));
402 bufman
= ioreq
->ios2_BufferManagement
;
406 AbortRW(ncp
, bufman
, deverror(IOERR_ABORTED
, S2WERR_GENERIC_ERROR
));
407 AbortList(ncp
, &ncp
->ncp_EventList
, bufman
, deverror(IOERR_ABORTED
, S2WERR_GENERIC_ERROR
));
417 *======================================================================
418 * cmdDeviceQuery(ioreq, base)
419 *======================================================================
421 * This is the device S2_DEVICEQUERY routine.
423 * This routine return various parameters for this network interface.
428 const struct Sana2DeviceQuery DeviceQueryBlock
[] =
431 sizeof(struct Sana2DeviceQuery
), sizeof(struct Sana2DeviceQuery
),
441 WORD
cmdDeviceQuery(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
443 struct Sana2DeviceQuery
*query
;
445 KPRINTF(1, ("S2_DEVICEQUERY ioreq: 0x%08lx\n", ioreq
));
448 query
= (struct Sana2DeviceQuery
*) ioreq
->ios2_StatData
;
451 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
454 /* Enough space to store the info ? */
455 if(query
->SizeAvailable
< sizeof(struct Sana2DeviceQuery
))
457 KPRINTF(1, ("S2_DEVICEQUERY: too small buffer supplied! (%lu / %lu)\n",
458 query
->SizeAvailable
, sizeof(struct Sana2DeviceQuery
)));
460 query
->SizeSupplied
= 0;
461 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_BAD_STATDATA
);
464 CopyMem(&((struct Sana2DeviceQuery
*) DeviceQueryBlock
)->SizeSupplied
, &query
->SizeSupplied
, sizeof(struct Sana2DeviceQuery
) - sizeof(ULONG
));
471 *======================================================================
472 * cmdGetStationAddress(ioreq, base)
473 *======================================================================
475 * This is the device S2_GETSTATIONADDRESS routine.
477 * This routine return current and default interface hardware addresses.
481 WORD
cmdGetStationAddress(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
485 KPRINTF(1, ("S2_GETSTATIONADDRESS ioreq: 0x%08lx\n", ioreq
));
487 /* Source address = current station address
488 Dest address = default station address
490 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
492 ioreq
->ios2_SrcAddr
[cnt
] = ncp
->ncp_MacAddress
[cnt
];
493 ioreq
->ios2_DstAddr
[cnt
] = ncp
->ncp_ROMAddress
[cnt
];
497 for(; cnt
< SANA2_MAX_ADDR_BYTES
; cnt
++)
499 ioreq
->ios2_SrcAddr
[cnt
] = 0;
500 ioreq
->ios2_DstAddr
[cnt
] = 0;
507 WORD
cmdConfigInterface(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
511 KPRINTF(1, ("S2_CONFIGINTERFACE ioreq: 0x%08lx\n", ioreq
));
513 /* This stuff must be atomic */
515 if(ncp
->ncp_StateFlags
& DDF_CONFIGURED
)
518 /* Error, already configured */
519 return deverror(S2ERR_BAD_STATE
, S2WERR_IS_CONFIGURED
);
522 /* Check for valid address */
523 if(ioreq
->ios2_SrcAddr
[0] & 0x80)
526 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_SRC_ADDRESS
);
529 /* Copy the address */
530 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
532 ncp
->ncp_MacAddress
[cnt
] = ioreq
->ios2_SrcAddr
[cnt
];
535 ncp
->ncp_StateFlags
|= DDF_CONFIGURED
;
536 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
538 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
544 WORD
cmdAddMulticastAddress(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
547 KPRINTF(1, ("S2_ADDMULTICASTADDRESS 0x%08lx%04lx\n",
548 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2]));
550 return AddMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_SrcAddr
);
553 WORD
cmdDelMulticastAddress(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
555 KPRINTF(1, ("S2_DELMULTICASTADDRESS 0x%08lx%04lx\n",
556 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2]));
558 return DelMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_SrcAddr
);
561 WORD
cmdAddMulticastAddresses(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
563 KPRINTF(1, ("S2_ADDMULTICASTADDRESSES 0x%08lx%04lx - 0x%08lx%04lx\n",
564 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2],
565 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
567 return AddMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_DstAddr
);
570 WORD
cmdDelMulticastAddresses(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
572 KPRINTF(1, ("S2_DELMULTICASTADDRESSES 0x%08lx%04lx - 0x%08lx%04lx\n",
573 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2],
574 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
576 return DelMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_DstAddr
);
579 #define mcmp(a,b) (memcmp(a,b,ETHER_ADDR_SIZE)==0)
581 WORD
AddMCastRange(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
, UBYTE
*lower
, UBYTE
*upper
)
583 struct MulticastAddressRange
*mar
;
586 /* Valid multicast addresses? */
587 if(((lower
[0] & 1) == 0) || ((upper
[0] & 1) == 0))
589 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_BAD_MULTICAST
);
592 /* Lock access to list */
595 /* Find matching node */
596 mar
= (struct MulticastAddressRange
*) ncp
->ncp_Multicasts
.lh_Head
;
597 while(mar
->mar_Node
.ln_Succ
)
599 if(mcmp(lower
, mar
->mar_LowerAddr
) &&
600 mcmp(upper
, mar
->mar_UpperAddr
))
604 mar
= (struct MulticastAddressRange
*) mar
->mar_Node
.ln_Succ
;
607 if(!mar
->mar_Node
.ln_Succ
)
610 mar
= AllocVec(sizeof(struct MulticastAddressRange
), MEMF_CLEAR
|MEMF_PUBLIC
);
614 return deverror(S2ERR_NO_RESOURCES
, S2WERR_GENERIC_ERROR
);
616 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
618 mar
->mar_LowerAddr
[cnt
] = *lower
++;
619 mar
->mar_UpperAddr
[cnt
] = *upper
++;
621 mar
->mar_UseCount
= 1;
622 AddTail(&ncp
->ncp_Multicasts
, (struct Node
*) mar
);
635 WORD
DelMCastRange(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
, UBYTE
*lower
, UBYTE
*upper
)
637 struct MulticastAddressRange
*mar
;
639 /* Lock access to list */
642 /* Find matching node */
643 mar
= (struct MulticastAddressRange
*) ncp
->ncp_Multicasts
.lh_Head
;
644 while(mar
->mar_Node
.ln_Succ
)
646 if(mcmp(lower
, mar
->mar_LowerAddr
) &&
647 mcmp(upper
, mar
->mar_UpperAddr
))
649 if(!--mar
->mar_UseCount
)
651 Remove((struct Node
*) mar
);
660 mar
= (struct MulticastAddressRange
*) mar
->mar_Node
.ln_Succ
;
664 /* Return with failure */
665 return deverror(S2ERR_BAD_STATE
, S2WERR_BAD_MULTICAST
);
668 WORD
cmdMulticast(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
670 KPRINTF(1, ("S2_MULTICAST ioreq: 0x%08lx to: 0x%08lx%04lx\n",
672 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
674 /* Is dest a multicast address? */
675 if(ioreq
->ios2_DstAddr
[0] & 1)
677 return cmdWrite(ncp
, ioreq
);
680 /* Trigger any tx or generic error events */
681 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
683 /* Wasn't a multicast addr */
684 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_BAD_MULTICAST
);
687 WORD
cmdBroadcast(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
690 KPRINTF(1, ("S2_BROADCAST ioreq: 0x%08lx\n", ioreq
));
692 /* Dest address = broadcast */
693 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
695 ioreq
->ios2_DstAddr
[cnt
] = 0xff;
697 return cmdWrite(ncp
, ioreq
);
701 WORD
cmdTrackType(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
703 struct PacketTypeStats
*pts
;
705 KPRINTF(1, ("S2_TRACKTYPE ioreq: 0x%08lx type: %lu\n",
706 ioreq
, ioreq
->ios2_PacketType
));
709 /* Find matching node */
710 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
711 while(pts
->pts_Node
.ln_Succ
)
713 /* Our packet type? */
714 if(pts
->pts_PacketType
== ioreq
->ios2_PacketType
)
717 return deverror(S2ERR_BAD_STATE
, S2WERR_ALREADY_TRACKED
);
719 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;
722 /* Alloc tracking node */
723 pts
= (struct PacketTypeStats
*) AllocVec(sizeof(struct PacketTypeStats
), MEMF_CLEAR
|MEMF_PUBLIC
);
726 return deverror(S2ERR_NO_RESOURCES
, S2WERR_NOT_TRACKED
);
728 /* Set up tracking node */
729 pts
->pts_PacketType
= ioreq
->ios2_PacketType
;
731 /* Add the new node to tracklist */
732 AddTail((struct List
*) &ncp
->ncp_TrackList
, (struct Node
*) pts
);
734 if(pts
->pts_PacketType
== 2048)
736 ncp
->ncp_TypeStats2048
= &pts
->pts_Stats
;
738 else if(pts
->pts_PacketType
== 2054)
740 ncp
->ncp_TypeStats2054
= &pts
->pts_Stats
;
749 WORD
cmdUntrackType(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
751 struct PacketTypeStats
*pts
;
752 KPRINTF(1, ("S2_UNTRACKTYPE ioreq: 0x%08lx type: %lu\n",
753 ioreq
, ioreq
->ios2_PacketType
));
756 /* Find matching node */
757 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
758 while(pts
->pts_Node
.ln_Succ
)
760 /* Our packet type? */
761 if(pts
->pts_PacketType
== ioreq
->ios2_PacketType
)
763 Remove(&pts
->pts_Node
);
765 if(pts
->pts_PacketType
== 2048)
767 ncp
->ncp_TypeStats2048
= NULL
;
769 else if(pts
->pts_PacketType
== 2054)
771 ncp
->ncp_TypeStats2054
= NULL
;
778 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;
782 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_TRACKED
);
786 WORD
cmdGetTypeStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
788 struct Sana2PacketTypeStats
*tostats
;
789 struct Sana2PacketTypeStats
*fromstats
;
791 KPRINTF(1, ("S2_GETTYPESTATS ioreq: 0x%08lx type: %lu\n",
792 ioreq
, ioreq
->ios2_PacketType
));
795 tostats
= (struct Sana2PacketTypeStats
*) ioreq
->ios2_StatData
;
798 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
802 fromstats
= FindPacketTypeStats(ncp
, ioreq
->ios2_PacketType
);
806 CopyMem(fromstats
, tostats
, sizeof(struct Sana2PacketTypeStats
));
815 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_TRACKED
);
819 WORD
cmdGetSpecialStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
821 struct Sana2SpecialStatHeader
*stats
;
822 struct Sana2SpecialStatRecord
*record
;
825 KPRINTF(1, ("S2_GETSPECIALSTATS ioreq: 0x%08lx\n", ioreq
));
828 stats
= (struct Sana2SpecialStatHeader
*) ioreq
->ios2_StatData
;
831 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
834 stats
->RecordCountSupplied
= 0;
835 maxcount
= stats
->RecordCountMax
;
836 record
= (struct Sana2SpecialStatRecord
*) (stats
+ 1);
840 stats
->RecordCountSupplied
++;
842 record
->Type
= S2SS_ETHERNET_BADMULTICAST
;
843 record
->Count
= ncp
->ncp_BadMulticasts
;
844 record
->String
= "bad multicasts";
849 stats
->RecordCountSupplied
++;
851 record
->Type
= S2SS_ETHERNET_RETRIES
;
852 record
->Count
= ncp
->ncp_Retries
;
853 record
->String
= "retries";
863 WORD
cmdGetGlobalStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
865 struct Sana2DeviceStats
*stats
;
867 KPRINTF(1, ("S2_GETGLOBALSTATS ioreq: 0x%08lx\n", ioreq
));
870 stats
= (struct Sana2DeviceStats
*) ioreq
->ios2_StatData
;
873 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
876 CopyMem(&ncp
->ncp_DeviceStats
, stats
, sizeof(struct Sana2DeviceStats
));
883 #define KNOWN_EVENTS (S2EVENT_ERROR | \
891 WORD
cmdOnEvent(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
893 KPRINTF(1, ("S2_ONEVENT ioreq: 0x%08lx mask: 0x%08lx\n", ioreq
,
894 ioreq
->ios2_WireError
));
896 /* Do we know the requested events? */
897 if(ioreq
->ios2_WireError
& (~KNOWN_EVENTS
))
899 return deverror(S2ERR_NOT_SUPPORTED
, S2WERR_BAD_EVENT
);
902 /* If online return S2EVENT_ONLINE immediately
903 If offline return S2EVENT_OFFLINE immediately. */
904 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
906 if(ioreq
->ios2_WireError
& S2EVENT_ONLINE
)
908 ioreq
->ios2_WireError
= S2EVENT_ONLINE
;
914 if(ioreq
->ios2_WireError
& S2EVENT_OFFLINE
)
916 ioreq
->ios2_WireError
= S2EVENT_OFFLINE
;
924 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
926 /* Queue the ioreq */
928 AddTail((struct List
*) &ncp
->ncp_EventList
, (struct Node
*) ioreq
);
931 /* Don't reply the ioreq, it's pending */
936 WORD
cmdReadOrphan(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
938 struct BufMan
*bufman
;
940 KPRINTF(1, ("S2_READORPHAN ioreq: 0x%08lx type: %lu\n", ioreq
,
941 ioreq
->ios2_PacketType
));
944 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
946 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
950 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
952 return deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
);
955 /* Valid bufman? got copytobuf routine? */
956 bufman
= ioreq
->ios2_BufferManagement
;
957 if((!bufman
) || (!bufman
->bm_CopyToBuf
))
959 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
963 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
965 /* Queue the ioreq */
967 AddTail((struct List
*) &ncp
->ncp_OrphanQueue
, (struct Node
*) ioreq
);
970 /* Don't reply the ioreq, it's pending */
975 WORD
cmdOnline(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
977 KPRINTF(1, ("S2_ONLINE ioreq: 0x%08lx\n", ioreq
));
980 /* Already online? */
981 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
984 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
987 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
990 /* Mark no longer offline */
991 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
993 /* Mark being online */
994 ncp
->ncp_StateFlags
|= DDF_ONLINE
;
995 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
997 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
1001 /* Trigger any ONLINE events */
1002 nDoEvent(ncp
, S2EVENT_ONLINE
);
1008 /* Return success */
1013 WORD
cmdOffline(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1016 KPRINTF(1, ("S2_OFFLINE ioreq: 0x%08lx\n", ioreq
));
1019 /* Mark being offline */
1020 ncp
->ncp_StateFlags
|= DDF_OFFLINE
;
1022 /* Already offline? */
1023 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
1025 /* Mark no longer online */
1026 ncp
->ncp_StateFlags
&= ~DDF_ONLINE
;
1027 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
1029 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
1033 /* *DO NOT* abort pending read & write requests.
1034 Miami dies a horrible death if this is enabled!
1036 if(ioreq
->ios2_BufferManagement
)
1038 AbortRW(ncp
, ioreq
->ios2_BufferManagement
, deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
));
1041 /* Trigger any OFFLINE events */
1042 nDoEvent(ncp
, S2EVENT_OFFLINE
);
1044 /* Don't reply the ioreq, it's pending */
1049 /* Return success */
1054 AROS_LH1(void, devBeginIO
,
1055 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
1056 DEVBASETYPEPTR
, base
, 5, dev
)
1060 struct NepClassEth
*ncp
= (struct NepClassEth
*) ioreq
->ios2_Req
.io_Unit
;
1061 WORD ret
= IOERR_NOCMD
;
1063 KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq
, base
, ioreq
->ios2_Req
.io_Command
));
1065 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
1066 ioreq
->ios2_Req
.io_Error
= 0;
1068 if(ioreq
->ios2_Req
.io_Command
< NSCMD_DEVICEQUERY
)
1070 switch(ioreq
->ios2_Req
.io_Command
)
1073 ret
= cmdRead(ncp
, ioreq
);
1077 ret
= cmdFlush(ncp
, ioreq
);
1081 ret
= cmdWrite(ncp
, ioreq
);
1084 case S2_GETSTATIONADDRESS
:
1085 ret
= cmdGetStationAddress(ncp
, ioreq
);
1088 case S2_DEVICEQUERY
:
1089 ret
= cmdDeviceQuery(ncp
, ioreq
);
1092 case S2_CONFIGINTERFACE
:
1093 ret
= cmdConfigInterface(ncp
, ioreq
);
1096 case S2_ADDMULTICASTADDRESS
:
1097 ret
= cmdAddMulticastAddress(ncp
, ioreq
);
1100 case S2_DELMULTICASTADDRESS
:
1101 ret
= cmdDelMulticastAddress(ncp
, ioreq
);
1105 ret
= cmdMulticast(ncp
, ioreq
);
1109 ret
= cmdBroadcast(ncp
, ioreq
);
1113 ret
= cmdTrackType(ncp
, ioreq
);
1116 case S2_UNTRACKTYPE
:
1117 ret
= cmdUntrackType(ncp
, ioreq
);
1120 case S2_GETTYPESTATS
:
1121 ret
= cmdGetTypeStats(ncp
, ioreq
);
1124 case S2_GETSPECIALSTATS
:
1125 ret
= cmdGetSpecialStats(ncp
, ioreq
);
1128 case S2_GETGLOBALSTATS
:
1129 ret
= cmdGetGlobalStats(ncp
, ioreq
);
1133 ret
= cmdOnEvent(ncp
, ioreq
);
1137 ret
= cmdReadOrphan(ncp
, ioreq
);
1141 ret
= cmdOnline(ncp
, ioreq
);
1145 ret
= cmdOffline(ncp
, ioreq
);
1153 switch(ioreq
->ios2_Req
.io_Command
)
1155 case NSCMD_DEVICEQUERY
:
1156 ret
= cmdNSDeviceQuery(ncp
, (struct IOStdReq
*) ioreq
);
1159 case S2_ADDMULTICASTADDRESSES
:
1160 ret
= cmdAddMulticastAddresses(ncp
, ioreq
);
1163 case S2_DELMULTICASTADDRESSES
:
1164 ret
= cmdDelMulticastAddresses(ncp
, ioreq
);
1173 if(ret
!= RC_DONTREPLY
)
1175 KPRINTF(1, ("TermIO\n"));
1178 /* Set error codes */
1179 ioreq
->ios2_Req
.io_Error
= ret
& 0xff;
1181 /* Terminate the iorequest */
1188 AROS_LH1(LONG
, devAbortIO
,
1189 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
1190 DEVBASETYPEPTR
, base
, 6, dev
)
1194 struct NepClassEth
*ncp
= (struct NepClassEth
*) ioreq
->ios2_Req
.io_Unit
;
1195 struct BufMan
*worknode
, *nextnode
;
1197 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
1199 /* Is it pending? */
1201 if(ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
1204 switch (ioreq
->ios2_Req
.io_Command
)
1207 /* Check all nodes in dd_bufmanlist until we succeed to abort or run out of nodes. */
1208 worknode
= (struct BufMan
*) ncp
->ncp_BufManList
.lh_Head
;
1209 while((nextnode
= (struct BufMan
*) (((struct Node
*) worknode
)->ln_Succ
)))
1211 if(AbortReq(ncp
, &worknode
->bm_RXQueue
, ioreq
) == S2ERR_NO_ERROR
)
1213 /* Success, break out */
1216 worknode
= nextnode
;
1221 AbortReq(ncp
, &ncp
->ncp_OrphanQueue
, ioreq
);
1227 AbortReq(ncp
, &ncp
->ncp_WriteQueue
, ioreq
);
1230 // these commands may dispatch their ioreq to the USB task; catch from the message port
1233 case S2_CONFIGINTERFACE
:
1234 case S2_ADDMULTICASTADDRESS
:
1235 case S2_DELMULTICASTADDRESS
:
1236 case S2_ADDMULTICASTADDRESSES
:
1237 case S2_DELMULTICASTADDRESSES
:
1238 AbortReq(ncp
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
, ioreq
);
1242 AbortReq(ncp
, &ncp
->ncp_EventList
, ioreq
);
1246 KPRINTF(1, ("devAbortIO: not READ, READORPHAN, WRITE, MULTICAST, BROADCAST or ONEVENT\n"));
1260 const UWORD NSDSupported
[] =
1262 CMD_FLUSH
, CMD_READ
, CMD_WRITE
,
1264 S2_GETSTATIONADDRESS
,
1266 S2_ADDMULTICASTADDRESS
, S2_DELMULTICASTADDRESS
,
1267 S2_MULTICAST
, S2_BROADCAST
,
1268 S2_TRACKTYPE
, S2_UNTRACKTYPE
,
1269 S2_GETTYPESTATS
, S2_GETSPECIALSTATS
, S2_GETGLOBALSTATS
,
1272 S2_ONLINE
, S2_OFFLINE
,
1274 S2_ADDMULTICASTADDRESSES
, S2_DELMULTICASTADDRESSES
,
1278 WORD
cmdNSDeviceQuery(struct NepClassEth
*ncp
, struct IOStdReq
*ioreq
)
1280 struct my_NSDeviceQueryResult
*query
;
1282 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
1284 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
1291 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
1292 (query
->DevQueryFormat
!= 0) ||
1293 (query
->SizeAvailable
!= 0))
1295 /* Return error. This is special handling, since iorequest is only
1296 guaranteed to be sizeof(struct IOStdReq). If we'd let our
1297 devBeginIO dispatcher return the error, it would trash some
1298 memory past end of the iorequest (ios2_WireError field).
1300 ioreq
->io_Error
= IOERR_NOCMD
;
1301 TermIO(ncp
, (struct IOSana2Req
*) ioreq
);
1303 /* Don't reply, we already did.
1305 return RC_DONTREPLY
;
1308 ioreq
->io_Actual
= query
->SizeAvailable
1309 = sizeof(struct my_NSDeviceQueryResult
);
1310 query
->DeviceType
= NSDEVTYPE_SANA2
;
1311 query
->DeviceSubType
= 0;
1312 query
->SupportedCommands
= NSDSupported
;
1314 /* Return success (note that this will NOT poke ios2_WireError).
1320 *======================================================================
1321 * AbortReq(list, ioreq, base)
1322 *======================================================================
1324 * Locate an IO request in a linked list and abort it if found.
1328 LONG
AbortReq(struct NepClassEth
*ncp
, struct List
*list
, struct IOSana2Req
*ioreq
)
1332 for(node
= list
->lh_Head
; node
->ln_Succ
; node
= node
->ln_Succ
)
1334 if(node
== (struct Node
*) ioreq
)
1336 //KPRINTF(1, ("AbortReq: aborted 0x%08lx\n", ioreq));
1338 Remove(&ioreq
->ios2_Req
.io_Message
.mn_Node
);
1339 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
1340 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
1341 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1343 return S2ERR_NO_ERROR
;
1347 return S2ERR_BAD_STATE
;
1353 *===========================================================
1354 * TermIO(ioreq, base)
1355 *===========================================================
1357 * Return completed ioreq to sender.
1361 void TermIO(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1363 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1365 /* If not quick I/O, reply the message
1367 if(!(ioreq
->ios2_Req
.io_Flags
& IOF_QUICK
))
1369 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1374 *======================================================================
1375 * AbortList(list, bufman, error, base)
1376 *======================================================================
1378 * Aborts all pending ioreqs in given list with io_Error & ios2_WireError
1381 * error is deverror() macro packed error number.
1385 void AbortList(struct NepClassEth
*ncp
, struct List
*list
, struct BufMan
*bufman
, WORD error
)
1387 struct IOSana2Req
*ioreq
, *nextioreq
;
1391 for(ioreq
= (struct IOSana2Req
*) list
->lh_Head
;
1392 (nextioreq
= (struct IOSana2Req
*) ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
);
1395 if(ioreq
->ios2_BufferManagement
== bufman
)
1397 Remove(&ioreq
->ios2_Req
.io_Message
.mn_Node
);
1398 /*ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;*/
1399 ioreq
->ios2_Req
.io_Error
= error
& 0xff;
1400 ioreq
->ios2_WireError
= error
>> 8;
1401 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1407 while((ioreq
= (struct IOSana2Req
*) RemHead(list
)))
1409 /* ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;*/
1410 ioreq
->ios2_Req
.io_Error
= error
& 0xff;
1411 ioreq
->ios2_WireError
= error
>> 8;
1412 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1419 *======================================================================
1420 * AbortRW(bufman, error, base)
1421 *======================================================================
1423 * Aborts all pending reads and writes with io_Error & ios2_WireError
1426 * error is deverror() macro packed error number.
1430 void AbortRW(struct NepClassEth
*ncp
, struct BufMan
*bufman
, WORD error
)
1432 AbortList(ncp
, &bufman
->bm_RXQueue
, NULL
, error
);
1433 AbortList(ncp
, &ncp
->ncp_OrphanQueue
, bufman
, error
);
1434 AbortList(ncp
, &ncp
->ncp_WriteQueue
, bufman
, error
);
1437 struct Sana2PacketTypeStats
* FindPacketTypeStats(struct NepClassEth
*ncp
, ULONG packettype
)
1439 struct PacketTypeStats
*pts
;
1444 return ncp
->ncp_TypeStats2048
;
1448 return ncp
->ncp_TypeStats2054
;
1452 /* Find matching node - slowly */
1453 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
1454 while(pts
->pts_Node
.ln_Succ
)
1456 /* Our packet type? */
1457 if(pts
->pts_PacketType
== packettype
)
1459 return &pts
->pts_Stats
;
1461 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;