1 /* dev.c - usbmoschipeth.device by Chris Hodges
6 #include "moschipeth.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 /* Copy the address (reverse direction) */
519 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
521 ioreq
->ios2_SrcAddr
[cnt
] = ncp
->ncp_MacAddress
[cnt
];
523 /* Error, already configured */
524 return deverror(S2ERR_BAD_STATE
, S2WERR_IS_CONFIGURED
);
527 /* Check for valid address */
528 if(ioreq
->ios2_SrcAddr
[0] & 0x80)
531 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_SRC_ADDRESS
);
534 /* Copy the address */
535 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
537 ncp
->ncp_MacAddress
[cnt
] = ioreq
->ios2_SrcAddr
[cnt
];
541 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
542 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
544 /* Don't reply the ioreq, it's pending */
549 WORD
cmdAddMulticastAddress(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
552 KPRINTF(1, ("S2_ADDMULTICASTADDRESS 0x%08lx%04lx\n",
553 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2]));
555 return AddMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_SrcAddr
);
558 WORD
cmdDelMulticastAddress(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
560 KPRINTF(1, ("S2_DELMULTICASTADDRESS 0x%08lx%04lx\n",
561 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2]));
563 return DelMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_SrcAddr
);
566 WORD
cmdAddMulticastAddresses(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
568 KPRINTF(1, ("S2_ADDMULTICASTADDRESSES 0x%08lx%04lx - 0x%08lx%04lx\n",
569 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2],
570 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
572 return AddMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_DstAddr
);
575 WORD
cmdDelMulticastAddresses(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
577 KPRINTF(1, ("S2_DELMULTICASTADDRESSES 0x%08lx%04lx - 0x%08lx%04lx\n",
578 ((ULONG
*) ioreq
->ios2_SrcAddr
)[0], ((UWORD
*) ioreq
->ios2_SrcAddr
)[2],
579 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
581 return DelMCastRange(ncp
, ioreq
, ioreq
->ios2_SrcAddr
, ioreq
->ios2_DstAddr
);
584 #define mcmp(a,b) (memcmp(a,b,ETHER_ADDR_SIZE)==0)
586 WORD
AddMCastRange(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
, UBYTE
*lower
, UBYTE
*upper
)
588 struct MulticastAddressRange
*mar
;
591 /* Valid multicast addresses? */
592 if(((lower
[0] & 1) == 0) || ((upper
[0] & 1) == 0))
594 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_BAD_MULTICAST
);
597 /* Lock access to list */
600 /* Find matching node */
601 mar
= (struct MulticastAddressRange
*) ncp
->ncp_Multicasts
.lh_Head
;
602 while(mar
->mar_Node
.ln_Succ
)
604 if(mcmp(lower
, mar
->mar_LowerAddr
) &&
605 mcmp(upper
, mar
->mar_UpperAddr
))
609 mar
= (struct MulticastAddressRange
*) mar
->mar_Node
.ln_Succ
;
612 if(!mar
->mar_Node
.ln_Succ
)
615 mar
= AllocVec(sizeof(struct MulticastAddressRange
), MEMF_CLEAR
|MEMF_PUBLIC
);
619 return deverror(S2ERR_NO_RESOURCES
, S2WERR_GENERIC_ERROR
);
621 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
623 mar
->mar_LowerAddr
[cnt
] = *lower
++;
624 mar
->mar_UpperAddr
[cnt
] = *upper
++;
626 mar
->mar_UseCount
= 1;
627 AddTail(&ncp
->ncp_Multicasts
, (struct Node
*) mar
);
631 UpdateMulticastHash(ncp
);
634 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
635 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
637 /* Don't reply the ioreq, it's pending */
647 WORD
DelMCastRange(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
, UBYTE
*lower
, UBYTE
*upper
)
649 struct MulticastAddressRange
*mar
;
651 /* Lock access to list */
654 /* Find matching node */
655 mar
= (struct MulticastAddressRange
*) ncp
->ncp_Multicasts
.lh_Head
;
656 while(mar
->mar_Node
.ln_Succ
)
658 if(mcmp(lower
, mar
->mar_LowerAddr
) &&
659 mcmp(upper
, mar
->mar_UpperAddr
))
661 if(!--mar
->mar_UseCount
)
663 Remove((struct Node
*) mar
);
667 UpdateMulticastHash(ncp
);
669 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
670 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
672 /* Don't reply the ioreq, it's pending */
678 mar
= (struct MulticastAddressRange
*) mar
->mar_Node
.ln_Succ
;
682 /* Return with failure */
683 return deverror(S2ERR_BAD_STATE
, S2WERR_BAD_MULTICAST
);
687 *===========================================================================
688 * Calculate 32 bit crc
689 *===========================================================================
691 * - for each bit: if (crcbit=1 XOR databit=1) then crc=(crc XOR polynomial).
692 * - polynomial is correct when data bits range 0-x, crc bits range 31-0.
693 * - crc wraps at 32 bits.
695 * crc = calc_crc(addr)
698 #define CRC_MASK 0x04c11db7U
700 ULONG
ether_crc(LONG length
, UBYTE
*data
)
713 for(bit
= 0; bit
< 8; bit
++, c
>>= 1)
715 crc
= (crc
<< 1) ^ (((crc
< 0) ^ (c
& 1)) ? CRC_MASK
: 0);
723 *================================================================
725 *================================================================
727 * calculate multicast hash table and send it to nic
730 * as of 1.2beta4 multicasts can be a address range, also single
731 * addresses are defined with lower = upper.
733 * multicasts list must be locked!
735 *==============================================================
736 * hash multicast address
737 *==============================================================
738 * The nic does not compare multicast addresses directly, but
739 * instead uses a bitfield of 64 bits - each bit corresponds
740 * to a 6 bit hash code for the multicast address. If the bit
741 * is set then any multicast address that matches the hash code
744 * The hash code is generated by taking the upper 6 bits of the
745 * 32 bit crc of the multicast address.
748 void UpdateMulticastHash(struct NepClassEth
*ncp
)
750 struct MulticastAddressRange
*mar
;
751 UBYTE addr
[ETHER_ADDR_SIZE
];
753 KPRINTF(1, ("nic_update_multicasts\n"));
755 /* Is promiscuous mode? */
756 if(ncp
->ncp_OpenFlags
& SANA2OPF_PROM
)
758 /* "Promiscuous Physical." ... "In addition, the multicast hashing
759 array must be set to all 1's so that all multicast addresses are
761 memset(ncp
->ncp_MulticastArray
, 0xff, sizeof(ncp
->ncp_MulticastArray
));
763 /* Clear all multicast bits */
764 memset(ncp
->ncp_MulticastArray
, 0x00, sizeof(ncp
->ncp_MulticastArray
));
765 mar
= (struct MulticastAddressRange
*) ncp
->ncp_Multicasts
.lh_Head
;
766 while(mar
->mar_Node
.ln_Succ
)
768 memcpy(addr
, mar
->mar_LowerAddr
, ETHER_ADDR_SIZE
);
772 hash
= ether_crc(ETHER_ADDR_SIZE
, addr
) >> 26;
773 ncp
->ncp_MulticastArray
[hash
>>3] |= 1<<(hash
& 7);
774 if(mcmp(addr
, mar
->mar_UpperAddr
))
785 mar
= (struct MulticastAddressRange
*) mar
->mar_Node
.ln_Succ
;
790 WORD
cmdMulticast(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
792 KPRINTF(1, ("S2_MULTICAST ioreq: 0x%08lx to: 0x%08lx%04lx\n",
794 ((ULONG
*) ioreq
->ios2_DstAddr
)[0], ((UWORD
*) ioreq
->ios2_DstAddr
)[2]));
796 /* Is dest a multicast address? */
797 if(ioreq
->ios2_DstAddr
[0] & 1)
799 return cmdWrite(ncp
, ioreq
);
802 /* Trigger any tx or generic error events */
803 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
805 /* Wasn't a multicast addr */
806 return deverror(S2ERR_BAD_ADDRESS
, S2WERR_BAD_MULTICAST
);
809 WORD
cmdBroadcast(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
812 KPRINTF(1, ("S2_BROADCAST ioreq: 0x%08lx\n", ioreq
));
814 /* Dest address = broadcast */
815 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
817 ioreq
->ios2_DstAddr
[cnt
] = 0xff;
819 return cmdWrite(ncp
, ioreq
);
823 WORD
cmdTrackType(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
825 struct PacketTypeStats
*pts
;
827 KPRINTF(1, ("S2_TRACKTYPE ioreq: 0x%08lx type: %lu\n",
828 ioreq
, ioreq
->ios2_PacketType
));
831 /* Find matching node */
832 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
833 while(pts
->pts_Node
.ln_Succ
)
835 /* Our packet type? */
836 if(pts
->pts_PacketType
== ioreq
->ios2_PacketType
)
839 return deverror(S2ERR_BAD_STATE
, S2WERR_ALREADY_TRACKED
);
841 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;
844 /* Alloc tracking node */
845 pts
= (struct PacketTypeStats
*) AllocVec(sizeof(struct PacketTypeStats
), MEMF_CLEAR
|MEMF_PUBLIC
);
848 return deverror(S2ERR_NO_RESOURCES
, S2WERR_NOT_TRACKED
);
850 /* Set up tracking node */
851 pts
->pts_PacketType
= ioreq
->ios2_PacketType
;
853 /* Add the new node to tracklist */
854 AddTail((struct List
*) &ncp
->ncp_TrackList
, (struct Node
*) pts
);
856 if(pts
->pts_PacketType
== 2048)
858 ncp
->ncp_TypeStats2048
= &pts
->pts_Stats
;
860 else if(pts
->pts_PacketType
== 2054)
862 ncp
->ncp_TypeStats2054
= &pts
->pts_Stats
;
871 WORD
cmdUntrackType(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
873 struct PacketTypeStats
*pts
;
874 KPRINTF(1, ("S2_UNTRACKTYPE ioreq: 0x%08lx type: %lu\n",
875 ioreq
, ioreq
->ios2_PacketType
));
878 /* Find matching node */
879 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
880 while(pts
->pts_Node
.ln_Succ
)
882 /* Our packet type? */
883 if(pts
->pts_PacketType
== ioreq
->ios2_PacketType
)
885 Remove(&pts
->pts_Node
);
887 if(pts
->pts_PacketType
== 2048)
889 ncp
->ncp_TypeStats2048
= NULL
;
891 else if(pts
->pts_PacketType
== 2054)
893 ncp
->ncp_TypeStats2054
= NULL
;
900 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;
904 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_TRACKED
);
908 WORD
cmdGetTypeStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
910 struct Sana2PacketTypeStats
*tostats
;
911 struct Sana2PacketTypeStats
*fromstats
;
913 KPRINTF(1, ("S2_GETTYPESTATS ioreq: 0x%08lx type: %lu\n",
914 ioreq
, ioreq
->ios2_PacketType
));
917 tostats
= (struct Sana2PacketTypeStats
*) ioreq
->ios2_StatData
;
920 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
924 fromstats
= FindPacketTypeStats(ncp
, ioreq
->ios2_PacketType
);
928 CopyMem(fromstats
, tostats
, sizeof(struct Sana2PacketTypeStats
));
937 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_TRACKED
);
941 WORD
cmdGetSpecialStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
943 struct Sana2SpecialStatHeader
*stats
;
944 struct Sana2SpecialStatRecord
*record
;
947 KPRINTF(1, ("S2_GETSPECIALSTATS ioreq: 0x%08lx\n", ioreq
));
950 stats
= (struct Sana2SpecialStatHeader
*) ioreq
->ios2_StatData
;
953 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
956 stats
->RecordCountSupplied
= 0;
957 maxcount
= stats
->RecordCountMax
;
958 record
= (struct Sana2SpecialStatRecord
*) (stats
+ 1);
962 stats
->RecordCountSupplied
++;
964 record
->Type
= S2SS_ETHERNET_BADMULTICAST
;
965 record
->Count
= ncp
->ncp_BadMulticasts
;
966 record
->String
= "bad multicasts";
971 stats
->RecordCountSupplied
++;
973 record
->Type
= S2SS_ETHERNET_RETRIES
;
974 record
->Count
= ncp
->ncp_Retries
;
975 record
->String
= "retries";
985 WORD
cmdGetGlobalStats(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
987 struct Sana2DeviceStats
*stats
;
989 KPRINTF(1, ("S2_GETGLOBALSTATS ioreq: 0x%08lx\n", ioreq
));
992 stats
= (struct Sana2DeviceStats
*) ioreq
->ios2_StatData
;
995 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
998 CopyMem(&ncp
->ncp_DeviceStats
, stats
, sizeof(struct Sana2DeviceStats
));
1000 /* Return success */
1005 #define KNOWN_EVENTS (S2EVENT_ERROR | \
1013 WORD
cmdOnEvent(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1015 KPRINTF(1, ("S2_ONEVENT ioreq: 0x%08lx mask: 0x%08lx\n", ioreq
,
1016 ioreq
->ios2_WireError
));
1018 /* Do we know the requested events? */
1019 if(ioreq
->ios2_WireError
& (~KNOWN_EVENTS
))
1021 return deverror(S2ERR_NOT_SUPPORTED
, S2WERR_BAD_EVENT
);
1024 /* If online return S2EVENT_ONLINE immediately
1025 If offline return S2EVENT_OFFLINE immediately. */
1026 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
1028 if(ioreq
->ios2_WireError
& S2EVENT_ONLINE
)
1030 ioreq
->ios2_WireError
= S2EVENT_ONLINE
;
1032 /* Return success */
1036 if(ioreq
->ios2_WireError
& S2EVENT_OFFLINE
)
1038 ioreq
->ios2_WireError
= S2EVENT_OFFLINE
;
1040 /* Return success */
1045 /* Must be queued */
1046 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
1048 /* Queue the ioreq */
1050 AddTail((struct List
*) &ncp
->ncp_EventList
, (struct Node
*) ioreq
);
1053 /* Don't reply the ioreq, it's pending */
1054 return RC_DONTREPLY
;
1058 WORD
cmdReadOrphan(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1060 struct BufMan
*bufman
;
1062 KPRINTF(1, ("S2_READORPHAN ioreq: 0x%08lx type: %lu\n", ioreq
,
1063 ioreq
->ios2_PacketType
));
1066 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
1068 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
1072 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
1074 return deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
);
1077 /* Valid bufman? got copytobuf routine? */
1078 bufman
= ioreq
->ios2_BufferManagement
;
1079 if((!bufman
) || (!bufman
->bm_CopyToBuf
))
1081 return deverror(S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
1084 /* Must be queued */
1085 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
1087 /* Queue the ioreq */
1089 AddTail((struct List
*) &ncp
->ncp_OrphanQueue
, (struct Node
*) ioreq
);
1092 /* Don't reply the ioreq, it's pending */
1093 return RC_DONTREPLY
;
1097 WORD
cmdOnline(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1099 KPRINTF(1, ("S2_ONLINE ioreq: 0x%08lx\n", ioreq
));
1102 /* Already online? */
1103 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
1106 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
1109 return deverror(S2ERR_BAD_STATE
, S2WERR_NOT_CONFIGURED
);
1112 /* Mark no longer offline */
1113 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
1115 /* Must be queued */
1116 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
1117 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
1120 /* Don't reply the ioreq, it's pending */
1121 return RC_DONTREPLY
;
1125 /* Return success */
1130 WORD
cmdOffline(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1133 KPRINTF(1, ("S2_OFFLINE ioreq: 0x%08lx\n", ioreq
));
1136 /* Mark being offline */
1137 ncp
->ncp_StateFlags
|= DDF_OFFLINE
;
1139 /* Already offline? */
1140 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
1142 /* Mark no longer online */
1143 ncp
->ncp_StateFlags
&= ~DDF_ONLINE
;
1145 /* *DO NOT* abort pending read & write requests.
1146 Miami dies a horrible death if this is enabled!
1148 if(ioreq
->ios2_BufferManagement
)
1150 AbortRW(ncp
, ioreq
->ios2_BufferManagement
, deverror(S2ERR_OUTOFSERVICE
, S2WERR_UNIT_OFFLINE
));
1153 /* Trigger any OFFLINE events */
1154 nDoEvent(ncp
, S2EVENT_OFFLINE
);
1156 /* Must be queued */
1157 ioreq
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
1158 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
1160 /* Don't reply the ioreq, it's pending */
1161 return RC_DONTREPLY
;
1165 /* Return success */
1170 AROS_LH1(void, devBeginIO
,
1171 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
1172 DEVBASETYPEPTR
, base
, 5, dev
)
1176 struct NepClassEth
*ncp
= (struct NepClassEth
*) ioreq
->ios2_Req
.io_Unit
;
1177 WORD ret
= IOERR_NOCMD
;
1179 KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq
, base
, ioreq
->ios2_Req
.io_Command
));
1181 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
1182 ioreq
->ios2_Req
.io_Error
= 0;
1184 if(ioreq
->ios2_Req
.io_Command
< NSCMD_DEVICEQUERY
)
1186 switch(ioreq
->ios2_Req
.io_Command
)
1189 ret
= cmdRead(ncp
, ioreq
);
1193 ret
= cmdFlush(ncp
, ioreq
);
1197 ret
= cmdWrite(ncp
, ioreq
);
1200 case S2_GETSTATIONADDRESS
:
1201 ret
= cmdGetStationAddress(ncp
, ioreq
);
1204 case S2_DEVICEQUERY
:
1205 ret
= cmdDeviceQuery(ncp
, ioreq
);
1208 case S2_CONFIGINTERFACE
:
1209 ret
= cmdConfigInterface(ncp
, ioreq
);
1212 case S2_ADDMULTICASTADDRESS
:
1213 ret
= cmdAddMulticastAddress(ncp
, ioreq
);
1216 case S2_DELMULTICASTADDRESS
:
1217 ret
= cmdDelMulticastAddress(ncp
, ioreq
);
1221 ret
= cmdMulticast(ncp
, ioreq
);
1225 ret
= cmdBroadcast(ncp
, ioreq
);
1229 ret
= cmdTrackType(ncp
, ioreq
);
1232 case S2_UNTRACKTYPE
:
1233 ret
= cmdUntrackType(ncp
, ioreq
);
1236 case S2_GETTYPESTATS
:
1237 ret
= cmdGetTypeStats(ncp
, ioreq
);
1240 case S2_GETSPECIALSTATS
:
1241 ret
= cmdGetSpecialStats(ncp
, ioreq
);
1244 case S2_GETGLOBALSTATS
:
1245 ret
= cmdGetGlobalStats(ncp
, ioreq
);
1249 ret
= cmdOnEvent(ncp
, ioreq
);
1253 ret
= cmdReadOrphan(ncp
, ioreq
);
1257 ret
= cmdOnline(ncp
, ioreq
);
1261 ret
= cmdOffline(ncp
, ioreq
);
1269 switch(ioreq
->ios2_Req
.io_Command
)
1271 case NSCMD_DEVICEQUERY
:
1272 ret
= cmdNSDeviceQuery(ncp
, (struct IOStdReq
*) ioreq
);
1275 case S2_ADDMULTICASTADDRESSES
:
1276 ret
= cmdAddMulticastAddresses(ncp
, ioreq
);
1279 case S2_DELMULTICASTADDRESSES
:
1280 ret
= cmdDelMulticastAddresses(ncp
, ioreq
);
1289 if(ret
!= RC_DONTREPLY
)
1291 KPRINTF(1, ("TermIO\n"));
1294 /* Set error codes */
1295 ioreq
->ios2_Req
.io_Error
= ret
& 0xff;
1296 ioreq
->ios2_WireError
= ret
>>8;
1298 /* Terminate the iorequest */
1305 AROS_LH1(LONG
, devAbortIO
,
1306 AROS_LHA(struct IOSana2Req
*, ioreq
, A1
),
1307 DEVBASETYPEPTR
, base
, 6, dev
)
1311 struct NepClassEth
*ncp
= (struct NepClassEth
*) ioreq
->ios2_Req
.io_Unit
;
1312 struct BufMan
*worknode
, *nextnode
;
1314 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
1316 /* Is it pending? */
1318 if(ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
1321 switch (ioreq
->ios2_Req
.io_Command
)
1324 /* Check all nodes in dd_bufmanlist until we succeed to abort or run out of nodes. */
1325 worknode
= (struct BufMan
*) ncp
->ncp_BufManList
.lh_Head
;
1326 while((nextnode
= (struct BufMan
*) (((struct Node
*) worknode
)->ln_Succ
)))
1328 if(AbortReq(ncp
, &worknode
->bm_RXQueue
, ioreq
) == S2ERR_NO_ERROR
)
1330 /* Success, break out */
1333 worknode
= nextnode
;
1338 AbortReq(ncp
, &ncp
->ncp_OrphanQueue
, ioreq
);
1344 AbortReq(ncp
, &ncp
->ncp_WriteQueue
, ioreq
);
1347 // these commands may dispatch their ioreq to the USB task; catch from the message port
1350 case S2_CONFIGINTERFACE
:
1351 case S2_ADDMULTICASTADDRESS
:
1352 case S2_DELMULTICASTADDRESS
:
1353 case S2_ADDMULTICASTADDRESSES
:
1354 case S2_DELMULTICASTADDRESSES
:
1355 AbortReq(ncp
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
, ioreq
);
1359 AbortReq(ncp
, &ncp
->ncp_EventList
, ioreq
);
1363 KPRINTF(1, ("devAbortIO: not READ, READORPHAN, WRITE, MULTICAST, BROADCAST or ONEVENT\n"));
1377 const UWORD NSDSupported
[] =
1379 CMD_FLUSH
, CMD_READ
, CMD_WRITE
,
1381 S2_GETSTATIONADDRESS
,
1383 S2_ADDMULTICASTADDRESS
, S2_DELMULTICASTADDRESS
,
1384 S2_MULTICAST
, S2_BROADCAST
,
1385 S2_TRACKTYPE
, S2_UNTRACKTYPE
,
1386 S2_GETTYPESTATS
, S2_GETSPECIALSTATS
, S2_GETGLOBALSTATS
,
1389 S2_ONLINE
, S2_OFFLINE
,
1391 S2_ADDMULTICASTADDRESSES
, S2_DELMULTICASTADDRESSES
,
1395 WORD
cmdNSDeviceQuery(struct NepClassEth
*ncp
, struct IOStdReq
*ioreq
)
1397 struct my_NSDeviceQueryResult
*query
;
1399 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
1401 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
1408 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
1409 (query
->DevQueryFormat
!= 0) ||
1410 (query
->SizeAvailable
!= 0))
1412 /* Return error. This is special handling, since iorequest is only
1413 guaranteed to be sizeof(struct IOStdReq). If we'd let our
1414 devBeginIO dispatcher return the error, it would trash some
1415 memory past end of the iorequest (ios2_WireError field).
1417 ioreq
->io_Error
= IOERR_NOCMD
;
1418 TermIO(ncp
, (struct IOSana2Req
*) ioreq
);
1420 /* Don't reply, we already did.
1422 return RC_DONTREPLY
;
1425 ioreq
->io_Actual
= query
->SizeAvailable
1426 = sizeof(struct my_NSDeviceQueryResult
);
1427 query
->DeviceType
= NSDEVTYPE_SANA2
;
1428 query
->DeviceSubType
= 0;
1429 query
->SupportedCommands
= NSDSupported
;
1431 /* Return success (note that this will NOT poke ios2_WireError).
1437 *======================================================================
1438 * AbortReq(list, ioreq, base)
1439 *======================================================================
1441 * Locate an IO request in a linked list and abort it if found.
1445 LONG
AbortReq(struct NepClassEth
*ncp
, struct List
*list
, struct IOSana2Req
*ioreq
)
1449 for(node
= list
->lh_Head
; node
->ln_Succ
; node
= node
->ln_Succ
)
1451 if(node
== (struct Node
*) ioreq
)
1453 //KPRINTF(1, ("AbortReq: aborted 0x%08lx\n", ioreq));
1455 Remove(&ioreq
->ios2_Req
.io_Message
.mn_Node
);
1456 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
1457 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
1458 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1460 return S2ERR_NO_ERROR
;
1464 return S2ERR_BAD_STATE
;
1470 *===========================================================
1471 * TermIO(ioreq, base)
1472 *===========================================================
1474 * Return completed ioreq to sender.
1478 void TermIO(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1480 ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1482 /* If not quick I/O, reply the message
1484 if(!(ioreq
->ios2_Req
.io_Flags
& IOF_QUICK
))
1486 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1491 *======================================================================
1492 * AbortList(list, bufman, error, base)
1493 *======================================================================
1495 * Aborts all pending ioreqs in given list with io_Error & ios2_WireError
1498 * error is deverror() macro packed error number.
1502 void AbortList(struct NepClassEth
*ncp
, struct List
*list
, struct BufMan
*bufman
, WORD error
)
1504 struct IOSana2Req
*ioreq
, *nextioreq
;
1508 for(ioreq
= (struct IOSana2Req
*) list
->lh_Head
;
1509 (nextioreq
= (struct IOSana2Req
*) ioreq
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
);
1512 if(ioreq
->ios2_BufferManagement
== bufman
)
1514 Remove(&ioreq
->ios2_Req
.io_Message
.mn_Node
);
1515 /*ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;*/
1516 ioreq
->ios2_Req
.io_Error
= error
& 0xff;
1517 ioreq
->ios2_WireError
= error
>> 8;
1518 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1524 while((ioreq
= (struct IOSana2Req
*) RemHead(list
)))
1526 /* ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;*/
1527 ioreq
->ios2_Req
.io_Error
= error
& 0xff;
1528 ioreq
->ios2_WireError
= error
>> 8;
1529 ReplyMsg(&ioreq
->ios2_Req
.io_Message
);
1536 *======================================================================
1537 * AbortRW(bufman, error, base)
1538 *======================================================================
1540 * Aborts all pending reads and writes with io_Error & ios2_WireError
1543 * error is deverror() macro packed error number.
1547 void AbortRW(struct NepClassEth
*ncp
, struct BufMan
*bufman
, WORD error
)
1549 AbortList(ncp
, &bufman
->bm_RXQueue
, NULL
, error
);
1550 AbortList(ncp
, &ncp
->ncp_OrphanQueue
, bufman
, error
);
1551 AbortList(ncp
, &ncp
->ncp_WriteQueue
, bufman
, error
);
1554 struct Sana2PacketTypeStats
* FindPacketTypeStats(struct NepClassEth
*ncp
, ULONG packettype
)
1556 struct PacketTypeStats
*pts
;
1561 return ncp
->ncp_TypeStats2048
;
1565 return ncp
->ncp_TypeStats2054
;
1569 /* Find matching node - slowly */
1570 pts
= (struct PacketTypeStats
*) ncp
->ncp_TrackList
.lh_Head
;
1571 while(pts
->pts_Node
.ln_Succ
)
1573 /* Our packet type? */
1574 if(pts
->pts_PacketType
== packettype
)
1576 return &pts
->pts_Stats
;
1578 pts
= (struct PacketTypeStats
*) pts
->pts_Node
.ln_Succ
;