Documented GVF_SAVE_VAR alongside other flags, and removed a query/doubt
[AROS.git] / rom / usb / classes / rndis / dev.c
blobbb6a5ca9c86314297423fe2c9a089136da1295dc
1 /*
2 * $Id$
3 */
5 #include "debug.h"
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))
14 AROS_USERFUNC_INIT
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;
26 /* Store segment */
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));
33 return(base);
35 else
37 return(NULL);
39 return(base);
41 AROS_USERFUNC_EXIT
44 #undef UtilityBase
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)
53 AROS_LIBFUNC_INIT
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;
72 } else {
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;
85 } else {
86 ioreq->ios2_Req.io_Unit = (struct Unit *) ncp;
88 break;
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"));
97 } else {
98 ncp->ncp_OpenFlags |= flags;
100 /* Got taglist? (don't fail if not available!) */
101 taglist = (struct TagItem *) ioreq->ios2_BufferManagement;
102 if(taglist)
104 struct BufMan *bufman;
106 bufman = (struct BufMan *) AllocVec(sizeof(struct BufMan), MEMF_CLEAR|MEMF_PUBLIC);
107 if(bufman)
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));
125 Forbid();
126 AddHead((struct List *) &ncp->ncp_BufManList, (struct Node *) bufman);
127 Permit();
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));
137 /* Opended ok! */
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++;
142 /* Allow queuing */
143 //ncp->ncp_DenyRequests = FALSE;
145 return base;
149 ioreq->ios2_Req.io_Unit = (APTR) -1;
150 ioreq->ios2_Req.io_Device = (APTR) -1;
151 base->np_Library.lib_OpenCnt--;
153 return(NULL);
155 AROS_LIBFUNC_EXIT
159 AROS_LH1(BPTR, devClose,
160 AROS_LHA(struct IOSana2Req *, ioreq, A1),
161 DEVBASETYPEPTR, base, 2, dev)
163 AROS_LIBFUNC_INIT
165 BPTR ret;
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));
171 ret = BNULL;
172 /* Allow queuing */
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;
185 if(bufman)
187 KPRINTF(5, ("Close_Unit: remove bufman at 0x%08lx\n", bufman));
188 ioreq->ios2_BufferManagement = NULL;
190 Forbid();
191 Remove((struct Node *) bufman);
192 Permit();
193 FreeVec(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));
209 return(ret);
211 AROS_LIBFUNC_EXIT
215 AROS_LH1(BPTR, devExpunge,
216 AROS_LHA(DEVBASETYPEPTR, extralh, D0),
217 DEVBASETYPEPTR, base, 3, dev)
219 AROS_LIBFUNC_INIT
221 BPTR ret;
223 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base));
225 ret = BNULL;
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"));
245 return(ret);
247 else
249 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
250 base->np_Library.lib_Flags |= LIBF_DELEXP;
253 return(BNULL);
255 AROS_LIBFUNC_EXIT
258 AROS_LH0(DEVBASETYPEPTR, devReserved,
259 DEVBASETYPEPTR, base, 4, dev)
261 AROS_LIBFUNC_INIT
262 return NULL;
263 AROS_LIBFUNC_EXIT
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));
288 /* Configured? */
289 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
291 return deverror(S2ERR_BAD_STATE, S2WERR_NOT_CONFIGURED);
294 /* Online? */
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);
307 /* Must be queued */
308 ioreq->ios2_Req.io_Flags &= ~IOF_QUICK;
310 /* Add to this ioreq's bufman rxqueue */
311 Forbid();
312 AddTail((struct List *) &bufman->bm_RXQueue, (struct Node *) ioreq);
313 Permit();
314 /* Don't reply the ioreq, it's pending
316 return RC_DONTREPLY;
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;
339 int size;
341 KPRINTF(1, ("CMD_WRITE ioreq: 0x%08lx type: %lu len: %lu\n",
342 ioreq, ioreq->ios2_PacketType, ioreq->ios2_DataLength));
344 /* Configured? */
345 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
347 return deverror(S2ERR_BAD_STATE, S2WERR_NOT_CONFIGURED);
350 /* Online? */
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);
372 /* Must be queued */
373 ioreq->ios2_Req.io_Flags &= ~IOF_QUICK;
374 Forbid();
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));
380 Permit();
381 /* Don't reply the ioreq, it's pending */
382 return RC_DONTREPLY;
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;
404 if(bufman)
406 Forbid();
407 AbortRW(ncp, bufman, deverror(IOERR_ABORTED, S2WERR_GENERIC_ERROR));
408 AbortList(ncp, &ncp->ncp_EventList, bufman, deverror(IOERR_ABORTED, S2WERR_GENERIC_ERROR));
409 Permit();
412 /* Return success */
413 return RC_OK;
418 *======================================================================
419 * cmdDeviceQuery(ioreq, base)
420 *======================================================================
422 * This is the device S2_DEVICEQUERY routine.
424 * This routine return various parameters for this network interface.
428 static
429 const struct Sana2DeviceQuery DeviceQueryBlock[] =
432 sizeof(struct Sana2DeviceQuery), sizeof(struct Sana2DeviceQuery),
433 0, 0,
434 ETHER_ADDR_SIZE * 8,
435 ETHERPKT_SIZE,
436 10000000,
437 S2WireType_Ethernet
442 WORD cmdDeviceQuery(struct NepClassEth *ncp, struct IOSana2Req *ioreq)
444 struct Sana2DeviceQuery *query;
446 KPRINTF(1, ("S2_DEVICEQUERY ioreq: 0x%08lx\n", ioreq));
448 /* NULL ptr? */
449 query = (struct Sana2DeviceQuery *) ioreq->ios2_StatData;
450 if(!query)
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));
467 /* Return success */
468 return RC_OK;
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)
484 UWORD cnt;
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];
497 /* Clear the rest */
498 for(; cnt < SANA2_MAX_ADDR_BYTES; cnt++)
500 ioreq->ios2_SrcAddr[cnt] = 0;
501 ioreq->ios2_DstAddr[cnt] = 0;
504 /* Return success */
505 return(RC_OK);
508 WORD cmdConfigInterface(struct NepClassEth *ncp, struct IOSana2Req *ioreq)
510 #if 0
511 UWORD cnt;
512 #endif
514 KPRINTF(1, ("S2_CONFIGINTERFACE ioreq: 0x%08lx\n", ioreq));
516 /* This stuff must be atomic */
517 Forbid();
518 #if 0
519 if(ncp->ncp_StateFlags & DDF_CONFIGURED)
521 Permit();
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)
529 Permit();
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];
538 #endif
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));
544 Permit();
545 KPRINTF(1, ("S2_CONFIGINTERFACE ok/n"));
547 return(RC_OK);
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;
590 WORD cnt;
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 */
599 Forbid();
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))
608 break;
610 mar = (struct MulticastAddressRange *) mar->mar_Node.ln_Succ;
613 if(!mar->mar_Node.ln_Succ)
615 /* Add new node */
616 mar = AllocVec(sizeof(struct MulticastAddressRange), MEMF_CLEAR|MEMF_PUBLIC);
617 if(!mar)
619 Permit();
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);
630 Permit();
632 return RC_OK;
634 mar->mar_UseCount++;
635 Permit();
637 /* Return success */
638 return RC_OK;
641 WORD DelMCastRange(struct NepClassEth *ncp, struct IOSana2Req *ioreq, UBYTE *lower, UBYTE *upper)
643 struct MulticastAddressRange *mar;
645 /* Lock access to list */
646 Forbid();
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);
658 Permit();
659 FreeVec(mar);
661 return RC_OK;
663 Permit();
664 return RC_OK;
666 mar = (struct MulticastAddressRange *) mar->mar_Node.ln_Succ;
668 Permit();
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",
677 ioreq,
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)
695 UWORD cnt;
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));
714 Forbid();
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)
722 Permit();
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);
730 if(!pts)
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);
739 // caching
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;
748 Permit();
750 /* Return success */
751 return RC_OK;
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));
761 Forbid();
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);
770 // caching
771 if(pts->pts_PacketType == 2048)
773 ncp->ncp_TypeStats2048 = NULL;
775 else if(pts->pts_PacketType == 2054)
777 ncp->ncp_TypeStats2054 = NULL;
779 Permit();
780 FreeVec(pts);
781 return RC_OK;
784 pts = (struct PacketTypeStats *) pts->pts_Node.ln_Succ;
786 Permit();
787 /* Return failure */
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));
800 /* NULL ptr? */
801 tostats = (struct Sana2PacketTypeStats *) ioreq->ios2_StatData;
802 if(!tostats)
804 return deverror(S2ERR_BAD_ARGUMENT, S2WERR_NULL_POINTER);
807 Forbid();
808 fromstats = FindPacketTypeStats(ncp, ioreq->ios2_PacketType);
809 if(fromstats)
811 /* Copy the stats */
812 CopyMem(fromstats, tostats, sizeof(struct Sana2PacketTypeStats));
813 Permit();
815 /* Return success */
816 return RC_OK;
818 Permit();
820 /* Return error */
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;
829 ULONG maxcount;
831 KPRINTF(1, ("S2_GETSPECIALSTATS ioreq: 0x%08lx\n", ioreq));
833 /* NULL ptr? */
834 stats = (struct Sana2SpecialStatHeader *) ioreq->ios2_StatData;
835 if(!stats)
837 return deverror(S2ERR_BAD_ARGUMENT, S2WERR_NULL_POINTER);
840 stats->RecordCountSupplied = 0;
841 maxcount = stats->RecordCountMax;
842 record = (struct Sana2SpecialStatRecord *) (stats + 1);
844 if(maxcount--)
846 stats->RecordCountSupplied++;
848 record->Type = S2SS_ETHERNET_BADMULTICAST;
849 record->Count = ncp->ncp_BadMulticasts;
850 record->String = "bad multicasts";
851 record++;
853 if(maxcount--)
855 stats->RecordCountSupplied++;
857 record->Type = S2SS_ETHERNET_RETRIES;
858 record->Count = ncp->ncp_Retries;
859 record->String = "retries";
860 //record++;
864 /* Return success */
865 return RC_OK;
869 WORD cmdGetGlobalStats(struct NepClassEth *ncp, struct IOSana2Req *ioreq)
871 struct Sana2DeviceStats *stats;
873 KPRINTF(1, ("S2_GETGLOBALSTATS ioreq: 0x%08lx\n", ioreq));
875 /* NULL ptr? */
876 stats = (struct Sana2DeviceStats *) ioreq->ios2_StatData;
877 if(!stats)
879 return deverror(S2ERR_BAD_ARGUMENT, S2WERR_NULL_POINTER);
882 CopyMem(&ncp->ncp_DeviceStats, stats, sizeof(struct Sana2DeviceStats));
884 /* Return success */
885 return RC_OK;
889 #define KNOWN_EVENTS (S2EVENT_ERROR | \
890 S2EVENT_TX | \
891 S2EVENT_RX | \
892 S2EVENT_ONLINE | \
893 S2EVENT_OFFLINE | \
894 S2EVENT_BUFF | \
895 S2EVENT_HARDWARE)
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;
916 /* Return success */
917 return RC_OK;
919 } else {
920 if(ioreq->ios2_WireError & S2EVENT_OFFLINE)
922 ioreq->ios2_WireError = S2EVENT_OFFLINE;
924 /* Return success */
925 return RC_OK;
929 /* Must be queued */
930 ioreq->ios2_Req.io_Flags &= ~IOF_QUICK;
932 /* Queue the ioreq */
933 Forbid();
934 AddTail((struct List *) &ncp->ncp_EventList, (struct Node *) ioreq);
935 Permit();
937 /* Don't reply the ioreq, it's pending */
938 return RC_DONTREPLY;
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));
949 /* Configured? */
950 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
952 return deverror(S2ERR_BAD_STATE, S2WERR_NOT_CONFIGURED);
955 /* Online? */
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);
968 /* Must be queued */
969 ioreq->ios2_Req.io_Flags &= ~IOF_QUICK;
971 /* Queue the ioreq */
972 Forbid();
973 AddTail((struct List *) &ncp->ncp_OrphanQueue, (struct Node *) ioreq);
974 Permit();
976 /* Don't reply the ioreq, it's pending */
977 return RC_DONTREPLY;
981 WORD cmdOnline(struct NepClassEth *ncp, struct IOSana2Req *ioreq)
983 KPRINTF(1, ("S2_ONLINE ioreq: 0x%08lx\n", ioreq));
985 Forbid();
986 /* Already online? */
987 if(!(ncp->ncp_StateFlags & DDF_ONLINE))
989 /* Configured? */
990 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
992 Permit();
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));
1005 Permit();
1007 /* Trigger any ONLINE events */
1008 nDoEvent(ncp, S2EVENT_ONLINE);
1010 return RC_OK;
1013 Permit();
1014 /* Return success */
1015 return RC_OK;
1019 WORD cmdOffline(struct NepClassEth *ncp, struct IOSana2Req *ioreq)
1022 KPRINTF(1, ("S2_OFFLINE ioreq: 0x%08lx\n", ioreq));
1024 Forbid();
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));
1037 Permit();
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 */
1051 return RC_OK;
1053 Permit();
1055 /* Return success */
1056 return RC_OK;
1060 AROS_LH1(void, devBeginIO,
1061 AROS_LHA(struct IOSana2Req *, ioreq, A1),
1062 DEVBASETYPEPTR, base, 5, dev)
1064 AROS_LIBFUNC_INIT
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)
1078 case CMD_READ:
1079 ret = cmdRead(ncp, ioreq);
1080 break;
1082 case CMD_FLUSH:
1083 ret = cmdFlush(ncp, ioreq);
1084 break;
1086 case CMD_WRITE:
1087 ret = cmdWrite(ncp, ioreq);
1088 break;
1090 case S2_GETSTATIONADDRESS:
1091 ret = cmdGetStationAddress(ncp, ioreq);
1092 break;
1094 case S2_DEVICEQUERY:
1095 ret = cmdDeviceQuery(ncp, ioreq);
1096 break;
1098 case S2_CONFIGINTERFACE:
1099 ret = cmdConfigInterface(ncp, ioreq);
1100 break;
1102 case S2_ADDMULTICASTADDRESS:
1103 ret = cmdAddMulticastAddress(ncp, ioreq);
1104 break;
1106 case S2_DELMULTICASTADDRESS:
1107 ret = cmdDelMulticastAddress(ncp, ioreq);
1108 break;
1110 case S2_MULTICAST:
1111 ret = cmdMulticast(ncp, ioreq);
1112 break;
1114 case S2_BROADCAST:
1115 ret = cmdBroadcast(ncp, ioreq);
1116 break;
1118 case S2_TRACKTYPE:
1119 ret = cmdTrackType(ncp, ioreq);
1120 break;
1122 case S2_UNTRACKTYPE:
1123 ret = cmdUntrackType(ncp, ioreq);
1124 break;
1126 case S2_GETTYPESTATS:
1127 ret = cmdGetTypeStats(ncp, ioreq);
1128 break;
1130 case S2_GETSPECIALSTATS:
1131 ret = cmdGetSpecialStats(ncp, ioreq);
1132 break;
1134 case S2_GETGLOBALSTATS:
1135 ret = cmdGetGlobalStats(ncp, ioreq);
1136 break;
1138 case S2_ONEVENT:
1139 ret = cmdOnEvent(ncp, ioreq);
1140 break;
1142 case S2_READORPHAN:
1143 ret = cmdReadOrphan(ncp, ioreq);
1144 break;
1146 case S2_ONLINE:
1147 ret = cmdOnline(ncp, ioreq);
1148 break;
1150 case S2_OFFLINE:
1151 ret = cmdOffline(ncp, ioreq);
1152 break;
1154 default:
1155 ret = IOERR_NOCMD;
1156 break;
1158 } else {
1159 switch(ioreq->ios2_Req.io_Command)
1161 case NSCMD_DEVICEQUERY:
1162 ret = cmdNSDeviceQuery(ncp, (struct IOStdReq *) ioreq);
1163 break;
1165 case S2_ADDMULTICASTADDRESSES:
1166 ret = cmdAddMulticastAddresses(ncp, ioreq);
1167 break;
1169 case S2_DELMULTICASTADDRESSES:
1170 ret = cmdDelMulticastAddresses(ncp, ioreq);
1171 break;
1173 default:
1174 ret = IOERR_NOCMD;
1175 break;
1179 if(ret != RC_DONTREPLY)
1181 KPRINTF(1, ("TermIO\n"));
1182 if (ret != RC_OK)
1184 /* Set error codes */
1185 ioreq->ios2_Req.io_Error = ret & 0xff;
1187 /* Terminate the iorequest */
1188 TermIO(ncp, ioreq);
1191 AROS_LIBFUNC_EXIT
1194 AROS_LH1(LONG, devAbortIO,
1195 AROS_LHA(struct IOSana2Req *, ioreq, A1),
1196 DEVBASETYPEPTR, base, 6, dev)
1198 AROS_LIBFUNC_INIT
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? */
1206 Forbid();
1207 if(ioreq->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
1210 switch (ioreq->ios2_Req.io_Command)
1212 case CMD_READ:
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 */
1220 break;
1222 worknode = nextnode;
1224 break;
1226 case S2_READORPHAN:
1227 AbortReq(ncp, &ncp->ncp_OrphanQueue, ioreq);
1228 break;
1230 case CMD_WRITE:
1231 case S2_MULTICAST:
1232 case S2_BROADCAST:
1233 AbortReq(ncp, &ncp->ncp_WriteQueue, ioreq);
1234 break;
1236 // these commands may dispatch their ioreq to the USB task; catch from the message port
1237 case S2_ONLINE:
1238 case S2_OFFLINE:
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);
1245 break;
1247 case S2_ONEVENT:
1248 AbortReq(ncp, &ncp->ncp_EventList, ioreq);
1249 break;
1251 default:
1252 KPRINTF(1, ("devAbortIO: not READ, READORPHAN, WRITE, MULTICAST, BROADCAST or ONEVENT\n"));
1253 break;
1256 Permit();
1257 return(-1);
1259 AROS_LIBFUNC_EXIT
1262 /* NSD stuff
1265 static
1266 const UWORD NSDSupported[] =
1268 CMD_FLUSH, CMD_READ, CMD_WRITE,
1269 S2_DEVICEQUERY,
1270 S2_GETSTATIONADDRESS,
1271 S2_CONFIGINTERFACE,
1272 S2_ADDMULTICASTADDRESS, S2_DELMULTICASTADDRESS,
1273 S2_MULTICAST, S2_BROADCAST,
1274 S2_TRACKTYPE, S2_UNTRACKTYPE,
1275 S2_GETTYPESTATS, S2_GETSPECIALSTATS, S2_GETGLOBALSTATS,
1276 S2_ONEVENT,
1277 S2_READORPHAN,
1278 S2_ONLINE, S2_OFFLINE,
1279 NSCMD_DEVICEQUERY,
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));
1292 /* NULL ptr?
1293 Enough data?
1294 Valid request?
1296 if((!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).
1322 return RC_OK;
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)
1336 struct Node *node;
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
1385 * set.
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;
1395 if(bufman)
1397 for(ioreq = (struct IOSana2Req *) list->lh_Head;
1398 (nextioreq = (struct IOSana2Req *) ioreq->ios2_Req.io_Message.mn_Node.ln_Succ);
1399 ioreq = nextioreq)
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);
1411 else
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
1430 * set.
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;
1447 switch(packettype)
1449 case 2048:
1450 return ncp->ncp_TypeStats2048;
1451 break;
1453 case 2054:
1454 return ncp->ncp_TypeStats2054;
1455 break;
1457 default:
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;
1469 break;
1472 return NULL;