7 #include "rndis.class.h"
10 static const STRPTR libname
= MOD_NAME_STRING
;
13 const APTR DevFuncTable
[] =
15 &AROS_SLIB_ENTRY(devOpen
, dev
, 1),
16 &AROS_SLIB_ENTRY(devClose
, dev
, 2),
17 &AROS_SLIB_ENTRY(devExpunge
, dev
, 3),
18 &AROS_SLIB_ENTRY(devReserved
, dev
, 4),
19 &AROS_SLIB_ENTRY(devBeginIO
, dev
, 5),
20 &AROS_SLIB_ENTRY(devAbortIO
, dev
, 6),
24 static int libInit(LIBBASETYPEPTR nh
)
26 struct NepClassEth
*ncp
;
27 struct NepEthBase
*ret
= NULL
;
29 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh
, SysBase
));
31 nh
->nh_UtilityBase
= OpenLibrary("utility.library", 39);
33 #define UtilityBase nh->nh_UtilityBase
37 NewList(&nh
->nh_Units
);
39 if((nh
->nh_DevBase
= (struct NepEthDevBase
*) MakeLibrary((APTR
) DevFuncTable
, NULL
, (APTR
) devInit
,
40 sizeof(struct NepEthDevBase
), NULL
)))
42 ncp
= &nh
->nh_DummyNCP
;
43 ncp
->ncp_ClsBase
= nh
;
44 ncp
->ncp_Interface
= NULL
;
45 ncp
->ncp_CDC
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
48 nh
->nh_DevBase
->np_ClsBase
= nh
;
50 AddDevice((struct Device
*) nh
->nh_DevBase
);
51 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
++;
56 KPRINTF(20, ("failed to create usbrndis.device\n"));
60 CloseLibrary(UtilityBase
);
63 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
66 KPRINTF(10, ("libInit: Ok\n"));
67 return(ret
? TRUE
: FALSE
);
71 static int libExpunge(LIBBASETYPEPTR nh
)
73 struct NepClassEth
*ncp
;
75 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh
));
77 if(nh
->nh_DevBase
->np_Library
.lib_OpenCnt
== 1)
79 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%08lx\n",
81 CloseLibrary((struct Library
*) UtilityBase
);
83 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
84 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
86 Remove((struct Node
*) ncp
);
87 FreeVec(ncp
->ncp_CDC
);
89 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
92 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
--;
93 RemDevice((struct Device
*) nh
->nh_DevBase
);
95 KPRINTF(5, ("libExpunge: Unloading done! rndis.class expunged!\n\n"));
97 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
104 ADD2INITLIB(libInit
, 0)
105 ADD2EXPUNGELIB(libExpunge
, 0)
110 * ***********************************************************************
111 * * Library functions *
112 * ***********************************************************************
122 struct AutoBindData ClassBinds
[] =
124 { 0x0bb4, 0x0ffe }, // HTC , Android phone
125 //{ 0x12d1, 0x1039 }, // Huawei u8800
129 /* /// "usbAttemptDeviceBinding()" */
130 struct NepClassEth
* usbAttemptDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
133 struct AutoBindData
*abd
= ClassBinds
;
134 struct PsdInterface
*pif
;
141 KPRINTF(1, ("nepEthAttemptDeviceBinding(%08lx)\n", pd
));
143 if((ps
= OpenLibrary("poseidon.library", 4)))
145 psdGetAttrs(PGA_DEVICE
, pd
,
146 DA_VendorID
, &vendid
,
147 DA_ProductID
, &prodid
,
150 if( (pif
= psdFindInterface(pd
, NULL
,TAG_END
)) ){
151 psdGetAttrs(PGA_INTERFACE
, pif
,
153 IFA_SubClass
, &subclass
,
154 IFA_Protocol
, &proto
,
157 if (ifclass
== 224 && // WIRELESS
158 subclass
== 1 && // RF
162 return(usbForceDeviceBinding(nh
, pd
));
166 while(abd
->abd_VendID
)
168 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
171 return(usbForceDeviceBinding(nh
, pd
));
181 /* /// "usbForceDeviceBinding()" */
182 struct NepClassEth
* usbForceDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
185 struct NepClassEth
*ncp
;
186 struct NepClassEth
*tmpncp
;
187 struct ClsDevCfg
*cdc
;
196 KPRINTF(1, ("nepEthForceDeviceBinding(%08lx)\n", pd
));
198 if((ps
= OpenLibrary("poseidon.library", 4)))
200 psdGetAttrs(PGA_DEVICE
, pd
,
201 DA_ProductID
, &prodid
,
202 DA_VendorID
, &vendid
,
203 DA_ProductName
, &devname
,
204 DA_IDString
, &devidstr
,
210 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
211 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
213 if(!strcmp(ncp
->ncp_DevIDString
, devidstr
))
215 unitno
= ncp
->ncp_UnitNo
;
219 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
223 /* as units are freed in the expunge-vector, the memory is
224 outside the scope of the poseidon library */
225 if(!(ncp
= AllocVec(sizeof(struct NepClassEth
), MEMF_PUBLIC
|MEMF_CLEAR
)))
231 ncp
->ncp_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
239 /* IORequests may be queued even if the task is gone. */
240 ncp
->ncp_UnitNo
= (ULONG
) -1;
241 NewList(&ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
);
242 NewList(&ncp
->ncp_OrphanQueue
);
243 NewList(&ncp
->ncp_WriteQueue
);
244 NewList(&ncp
->ncp_BufManList
);
245 NewList(&ncp
->ncp_EventList
);
246 NewList(&ncp
->ncp_TrackList
);
247 NewList(&ncp
->ncp_Multicasts
);
248 strncpy(ncp
->ncp_DevIDString
, devidstr
, 127);
249 AddTail(&nh
->nh_Units
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
);
251 ncp
->ncp_ClsBase
= nh
;
252 ncp
->ncp_Device
= pd
;
253 ncp
->ncp_UnitProdID
= prodid
;
254 ncp
->ncp_UnitVendorID
= vendid
;
256 //nLoadBindingConfig(ncp);
258 /* Find next free unit number */
259 if(unitno
== (ULONG
) -1)
261 unitno
= ncp
->ncp_CDC
->cdc_DefaultUnit
;
262 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
263 while(tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
265 if(tmpncp
->ncp_UnitNo
== unitno
)
268 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
270 tmpncp
= (struct NepClassEth
*) tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
274 ncp
->ncp_UnitNo
= unitno
;
277 psdSafeRawDoFmt(buf
, 64, "rndis.class<%08lx>", ncp
);
278 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
279 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
280 SetSignal(0, SIGF_SINGLE
);
281 if(psdSpawnSubTask(buf
, nEthTask
, ncp
))
283 Wait(1L<<ncp
->ncp_ReadySignal
);
286 ncp
->ncp_ReadySigTask
= NULL
;
287 //FreeSignal(ncp->ncp_ReadySignal);
288 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
289 "Mr. Data linked '%s' to %s unit %ld!",
290 devname
, nh
->nh_DevBase
->np_Library
.lib_Node
.ln_Name
,
297 ncp
->ncp_ReadySigTask
= NULL
;
298 //FreeSignal(ncp->ncp_ReadySignal);
299 /* Get rid of unit structure */
301 Remove((struct Node *) ncp);
302 FreeVec(ncp->ncp_CDC);
311 /* /// "usbReleaseDeviceBinding()" */
312 void usbReleaseDeviceBinding(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
316 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp
));
318 if((ps
= OpenLibrary("poseidon.library", 4)))
321 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
322 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
325 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
330 Wait(1L<<ncp
->ncp_ReadySignal
);
332 //FreeSignal(ncp->ncp_ReadySignal);
333 psdGetAttrs(PGA_DEVICE
, ncp
->ncp_Device
, DA_ProductName
, &devname
, TAG_END
);
334 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
335 "Shrinkwrapped and wasted '%s'.",
343 /* /// "usbGetAttrsA()" */
344 AROS_LH3(LONG
, usbGetAttrsA
,
345 AROS_LHA(ULONG
, type
, D0
),
346 AROS_LHA(APTR
, usbstruct
, A0
),
347 AROS_LHA(struct TagItem
*, tags
, A1
),
348 LIBBASETYPEPTR
, nh
, 5, nep
)
355 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
359 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
361 *((SIPTR
*) ti
->ti_Data
) = -100;
364 if((ti
= FindTagItem(UCCA_Description
, tags
)))
366 *((STRPTR
*) ti
->ti_Data
) = "Ethernet SANA wrapper for RNDIS devices via usbrndis.device";
369 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
371 *((IPTR
*) ti
->ti_Data
) = TRUE
;
374 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
376 *((IPTR
*) ti
->ti_Data
) = TRUE
;
379 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
381 *((IPTR
*) ti
->ti_Data
) = FALSE
;
384 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
386 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCP
.ncp_UsingDefaultCfg
;
392 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
394 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassEth
*) usbstruct
)->ncp_UsingDefaultCfg
;
404 /* /// "usbSetAttrsA()" */
405 AROS_LH3(LONG
, usbSetAttrsA
,
406 AROS_LHA(ULONG
, type
, D0
),
407 AROS_LHA(APTR
, usbstruct
, A0
),
408 AROS_LHA(struct TagItem
*, tags
, A1
),
409 LIBBASETYPEPTR
, nh
, 6, nep
)
417 /* /// "usbDoMethodA()" */
418 AROS_LH2(IPTR
, usbDoMethodA
,
419 AROS_LHA(ULONG
, methodid
, D0
),
420 AROS_LHA(IPTR
*, methoddata
, A1
),
421 LIBBASETYPEPTR
, nh
, 7, nep
)
424 KPRINTF(10, ("Do Method %ld\n", methodid
));
427 case UCM_AttemptDeviceBinding
:
428 return((IPTR
) usbAttemptDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
430 case UCM_ForceDeviceBinding
:
431 return((IPTR
) usbForceDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
433 case UCM_ReleaseDeviceBinding
:
434 usbReleaseDeviceBinding(nh
, (struct NepClassEth
*) methoddata
[0]);
445 /**************************************************************************/
448 #define ps ncp->ncp_Base
450 /* /// "nEthTask()" */
451 AROS_UFH0(void, nEthTask
)
455 struct NepClassEth
*ncp
;
466 struct IOSana2Req
*ioreq
;
468 if((ncp
= nAllocEth()))
474 if(ncp
->ncp_ReadySigTask
)
476 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
481 /* Record start time_of_day */
482 //GetSysTime(&ncp->ncp_DeviceStats.LastStart);
484 ncp
->ncp_StateFlags
|= DDF_ONLINE
;
485 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
486 /* Trigger any ONLINE events */
487 nDoEvent(ncp
, S2EVENT_ONLINE
);
491 sigmask
= (1L<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
)|(1L<<ncp
->ncp_TaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
494 // start transmitting read request if online...
495 if((ncp
->ncp_StateFlags
& DDF_ONLINE
) && (ncp
->ncp_ReadPending
== NULL
))
497 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
498 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, RNDIS_BUFSZ
);
499 ncp
->ncp_ReadBufNum
^= 1;
501 while((pp
= (struct PsdPipe
*) GetMsg(ncp
->ncp_TaskMsgPort
)))
503 KPRINTF(1, ("Pipe back %08lx\n", pp
));
504 for(cnt
= 0; cnt
< 2; cnt
++)
506 if(pp
== ncp
->ncp_EPOutPipe
[cnt
])
508 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
510 ioerr
= psdGetPipeError(pp
);
513 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
514 "Eth transmit failed: %s (%ld)",
515 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
517 /* Trigger any tx or generic error events */
518 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
520 /* Set error code and terminate the iorequest.
521 NOTE: Can't use RC_* or deverror() this is not
522 called from devBeginIO()!
524 ioreq
->ios2_DataLength
= 0;
525 ioreq
->ios2_Req
.io_Error
= S2ERR_TX_FAILURE
;
526 ioreq
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
529 ReplyMsg((struct Message
*) ioreq
);
530 ncp
->ncp_WritePending
[cnt
] = NULL
;
536 if(pp
== ncp
->ncp_EPInPipe
)
538 if((pktptr
= ncp
->ncp_ReadPending
))
540 ioerr
= psdGetPipeError(pp
);
541 pktlen
= psdGetPipeActual(pp
);
542 KPRINTF(1, ("ReadBack with %ld bytes.\n", pktlen
));
543 // interleave next packet reading ASAP.
544 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
546 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
547 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, RNDIS_BUFSZ
);
548 ncp
->ncp_ReadBufNum
^= 1;
550 ncp
->ncp_ReadPending
= NULL
;
554 if(lastioerr
!= ioerr
)
556 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
557 "Eth receive failed: %s (%ld)",
558 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
564 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
,
565 "That's it, that device pissed me off long enough!");
566 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
573 KPRINTF(1, ("Pkt %ld received\n", pktlen
));
574 urndis_decap(ncp
, pktptr
, pktlen
);
581 while((!ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
]) && ncp
->ncp_WriteQueue
.lh_Head
->ln_Succ
)
583 ioreq
= (struct IOSana2Req
*) RemHead(&ncp
->ncp_WriteQueue
);
585 nWritePacket(ncp
, ioreq
);
590 sigs
= Wait(sigmask
);
592 } while(!(sigs
& SIGBREAKF_CTRL_C
));
595 /* Now remove all requests still pending *anywhere* */
596 //ncp->ncp_DenyRequests = TRUE;
597 /* Current transfers */
598 for(cnt
= 0; cnt
< 2; cnt
++)
600 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
602 KPRINTF(1, ("Aborting pending write...\n"));
603 psdAbortPipe(ncp
->ncp_EPOutPipe
[cnt
]);
604 psdWaitPipe(ncp
->ncp_EPOutPipe
[cnt
]);
605 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
606 ReplyMsg((struct Message
*) ioreq
);
607 ncp
->ncp_WritePending
[cnt
] = NULL
;
610 if(ncp
->ncp_ReadPending
)
612 KPRINTF(1, ("Aborting pending read...\n"));
613 psdAbortPipe(ncp
->ncp_EPInPipe
);
614 psdWaitPipe(ncp
->ncp_EPInPipe
);
615 ncp
->ncp_ReadPending
= NULL
;
619 nDoEvent(ncp
, S2EVENT_OFFLINE
);
621 KPRINTF(20, ("Going down the river!\n"));
629 /* /// "nAllocEth()" */
630 struct NepClassEth
* nAllocEth(void)
632 struct Task
*thistask
;
633 struct NepClassEth
*ncp
;
635 thistask
= FindTask(NULL
);
638 ncp
= thistask
->tc_UserData
;
639 if(!(ncp
->ncp_Base
= OpenLibrary("poseidon.library", 4)))
645 ncp
->ncp_Interface
= NULL
;
648 ncp
->ncp_Interface
= psdFindInterface(ncp
->ncp_Device
, ncp
->ncp_Interface
,
650 if(!ncp
->ncp_Interface
)
654 ncp
->ncp_EPIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
656 EA_TransferType
, USEAF_BULK
,
658 ncp
->ncp_EPOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
660 EA_TransferType
, USEAF_BULK
,
663 } while(!(ncp
->ncp_EPOut
&& ncp
->ncp_EPIn
));
666 if(!ncp
->ncp_Interface
)
668 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "No interface?");
672 if(!(ncp
->ncp_EPIn
&& ncp
->ncp_EPOut
))
674 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
678 ncp
->ncp_ReadPending
= NULL
;
679 ncp
->ncp_WritePending
[0] = NULL
;
680 ncp
->ncp_WritePending
[1] = NULL
;
681 if(!(ncp
->ncp_ReadBuffer
[0] = AllocVec(ETHER_MAX_LEN
* 4, MEMF_PUBLIC
|MEMF_CLEAR
)))
683 KPRINTF(1, ("Out of memory for read buffer\n"));
686 ncp
->ncp_ReadBuffer
[1] = ncp
->ncp_ReadBuffer
[0] + ETHER_MAX_LEN
;
687 ncp
->ncp_WriteBuffer
[0] = ncp
->ncp_ReadBuffer
[1] + ETHER_MAX_LEN
;
688 ncp
->ncp_WriteBuffer
[1] = ncp
->ncp_WriteBuffer
[0] + ETHER_MAX_LEN
;
689 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
690 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
691 ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
692 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
694 if((ncp
->ncp_TaskMsgPort
= CreateMsgPort()))
696 if((ncp
->ncp_EP0Pipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, NULL
)))
698 if((ncp
->ncp_EPOutPipe
[0] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
700 /* Turn off short packets */
701 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[0],
702 PPA_NoShortPackets
, FALSE
,
703 PPA_NakTimeout
, TRUE
,
704 PPA_NakTimeoutTime
, 5000,
706 if((ncp
->ncp_EPOutPipe
[1] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
708 /* Turn off short packets */
709 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[1],
710 PPA_NoShortPackets
, FALSE
,
711 PPA_NakTimeout
, TRUE
,
712 PPA_NakTimeoutTime
, 5000,
714 if((ncp
->ncp_EPInPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPIn
)))
716 /* Turn off short packets */
717 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPInPipe
,
718 PPA_NakTimeout
, FALSE
,
719 PPA_NakTimeoutTime
, 5000,
720 PPA_AllowRuntPackets
, TRUE
,
722 ncp
->ncp_Task
= thistask
;
726 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
728 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
730 psdFreePipe(ncp
->ncp_EP0Pipe
);
732 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
734 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
736 if(ncp
->ncp_ReadBuffer
[0])
738 FreeVec(ncp
->ncp_ReadBuffer
[0]);
739 ncp
->ncp_ReadBuffer
[0] = NULL
;
741 CloseLibrary(ncp
->ncp_Base
);
743 ncp
->ncp_Task
= NULL
;
744 if(ncp
->ncp_ReadySigTask
)
746 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
752 /* /// "nFreeEth()" */
753 void nFreeEth(struct NepClassEth
*ncp
)
755 struct IOSana2Req
*ioreq
;
757 /* Disable the message port, messages may still be queued */
758 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
759 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
760 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
761 // get rid of all messages that still have appeared here
762 while((ioreq
= (struct IOSana2Req
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
764 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
765 ReplyMsg((struct Message
*) ioreq
);
769 psdFreePipe(ncp
->ncp_EPInPipe
);
770 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
771 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
772 psdFreePipe(ncp
->ncp_EP0Pipe
);
774 if(ncp
->ncp_ReadBuffer
[0])
776 FreeVec(ncp
->ncp_ReadBuffer
[0]);
777 ncp
->ncp_ReadBuffer
[0] = NULL
;
780 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
781 CloseLibrary(ncp
->ncp_Base
);
783 ncp
->ncp_Task
= NULL
;
784 if(ncp
->ncp_ReadySigTask
)
786 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
791 /* /// "nDoEvent()" */
792 void nDoEvent(struct NepClassEth
*ncp
, ULONG events
)
794 struct IOSana2Req
*worknode
, *nextnode
;
796 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events
));
799 /* Process pending S2_ONEVENT requests */
800 worknode
= (struct IOSana2Req
*) ncp
->ncp_EventList
.lh_Head
;
801 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
803 if(worknode
->ios2_WireError
& events
)
805 Remove(&worknode
->ios2_Req
.io_Message
.mn_Node
);
806 worknode
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
807 KPRINTF(1, ("DoEvent: returned eventreq 0x%08lx\n", worknode
));
808 ReplyMsg(&worknode
->ios2_Req
.io_Message
);
816 /* /// "support routines" */
818 inline void *callcopy(void *routine
,
823 void * (*call
) (APTR
, APTR
, ULONG
) = routine
;
825 return (*call
) (from
, to
, len
);
828 #define callfilter CallHookPkt
831 /* /// "nWritePacket()" */
832 BOOL
nWritePacket(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
835 struct EtherPacketHeader
*eph
;
836 // UBYTE *packetdata;
839 struct BufMan
*bufman
;
840 struct Sana2PacketTypeStats
*stats
;
841 UBYTE
*buf
= ncp
->ncp_WriteBuffer
[ncp
->ncp_WriteBufNum
];
844 packettype
= ioreq
->ios2_PacketType
;
846 writelen
= ioreq
->ios2_DataLength
;
847 bufman
= ioreq
->ios2_BufferManagement
;
849 // remove RNDIS header
850 encaplen
= urndis_encap(ncp
, buf
,writelen
+
851 (!(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) ? sizeof(struct EtherPacketHeader
) : 0)
853 copydest
+= encaplen
;
854 writelen
+= encaplen
;
855 eph
= (struct EtherPacketHeader
*)copydest
;
857 /* Not a raw packet? */
858 if(!(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
))
861 KPRINTF(10, ("RAW WRITE!\n"));
862 /* The ethernet header isn't included in the data */
863 /* Build ethernet packet header */
864 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
866 eph
->eph_Dest
[cnt
] = ioreq
->ios2_DstAddr
[cnt
];
867 eph
->eph_Src
[cnt
] = ncp
->ncp_MacAddress
[cnt
];
869 eph
->eph_Type
= AROS_BE2WORD(packettype
);
871 /* Packet data is at txbuffer */
872 copydest
+= sizeof(struct EtherPacketHeader
);
873 writelen
+= sizeof(struct EtherPacketHeader
);
877 /* Dma not available, fallback to regular copy */
878 if(callcopy(bufman
->bm_CopyFromBuf
, copydest
, ioreq
->ios2_Data
, ioreq
->ios2_DataLength
) == NULL
)
880 KPRINTF(10, ("writepacket: copyfrom returned failure!\n"));
882 /* Trigger any tx, buff or generic error events */
883 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
|S2EVENT_BUFF
);
885 /* Set error code and terminate the iorequest.
886 NOTE: Can't use RC_* or deverror() this is not
887 called from devBeginIO()! */
888 ioreq
->ios2_DataLength
= 0;
889 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
890 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
894 //bug("out %d\n",writelen);
895 KPRINTF(20, ("PktOut[%ld] %ld\n", ncp
->ncp_WriteBufNum
, writelen
));
896 //dumpmem(buf, writelen);
898 ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
] = ioreq
;
899 psdSendPipe(ncp
->ncp_EPOutPipe
[ncp
->ncp_WriteBufNum
], buf
, (ULONG
) writelen
);
900 ncp
->ncp_WriteBufNum
^= 1;
903 if(AROS_BE2WORD(eph
->eph_Type
) < 1500)
905 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx (IEEE802.3) len %lu, %lu bytes\n",
906 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
907 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
908 AROS_BE2WORD(eph
->eph_Type
), writelen
));
910 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx type %lu, %lu bytes\n",
911 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
912 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
913 AROS_BE2WORD(eph
->eph_Type
), writelen
));
915 //dumpmem(buf, (ULONG) writelen);
918 /* Update statistics */
919 stats
= FindPacketTypeStats(ncp
, packettype
);
922 stats
->PacketsSent
++;
923 stats
->BytesSent
+= writelen
;
925 ncp
->ncp_DeviceStats
.PacketsSent
++;
931 /* /// "nReadIOReq()" */
932 UWORD
nReadIOReq(struct NepClassEth
*ncp
, struct EtherPacketHeader
*eph
, UWORD datasize
, struct IOSana2Req
*ioreq
, UWORD flags
)
934 LIBBASETYPEPTR nh
= ncp
->ncp_ClsBase
;
938 /* Handle RAW read */
939 if(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
)
941 /* ShapeShifter won't work with `sizeof(struct etherpacket_hdr)'
942 here. This is most likely because it want the RAW ethernet
943 packet checksum size (4) added to the packet size. */
944 copyfrom
= (UBYTE
*) eph
;
945 datasize
+= sizeof(struct EtherPacketHeader
) + 4;
947 copyfrom
= (UBYTE
*) (eph
+ 1);
950 /* Build up the ios2 structure enough so we can call the packet filter. */
951 ioreq
->ios2_PacketType
= AROS_BE2WORD(eph
->eph_Type
);
952 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
954 ioreq
->ios2_SrcAddr
[cnt
] = eph
->eph_Src
[cnt
];
955 ioreq
->ios2_DstAddr
[cnt
] = eph
->eph_Dest
[cnt
];
957 ioreq
->ios2_DataLength
= datasize
;
958 /* Call the packet filter, if available. */
959 if((flags
& PACKETFILTER
) &&
960 (((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
) &&
961 (!callfilter(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
,
964 /* This packet got dropped! */
965 KPRINTF(7, ("readioreq: packet type %lu for ioreq 0x%08lx dropped\n",
966 AROS_BE2WORD(eph
->eph_Type
), ioreq
));
971 /* Ok, the packet didn't get dropped, set the BCAST and MCAST
972 flags according to dstaddr. */
974 /* Address == Multicast? */
975 if(ioreq
->ios2_DstAddr
[0] & 1)
977 /* Address == Broadcast? */
978 static const UBYTE bcast
[ETHER_ADDR_SIZE
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
979 if(memcmp(bcast
, ioreq
->ios2_DstAddr
, ETHER_ADDR_SIZE
)==0)
981 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
983 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
987 /* Finally copy the packet data! */
988 if(callcopy(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_CopyToBuf
,
989 ioreq
->ios2_Data
, copyfrom
, ioreq
->ios2_DataLength
))
992 KPRINTF(5, ("readioreq: copytobuffed packet ior 0x%08lx, %04lx%08lx < %04lx%08lx, type %lu, %lu bytes, %s%s%s\n",
994 *((UWORD
*) ioreq
->ios2_DstAddr
), *((ULONG
*) (ioreq
->ios2_DstAddr
+ 2)),
995 *((UWORD
*) ioreq
->ios2_SrcAddr
), *((ULONG
*) (ioreq
->ios2_SrcAddr
+ 2)),
996 ioreq
->ios2_PacketType
, ioreq
->ios2_DataLength
,
997 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) ? "RAW " : "",
998 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_BCAST
) ? "BCAST " : "",
999 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_MCAST
) ? "MCAST " : ""));
1000 //dumpmem(copyfrom, ioreq->ios2_DataLength);
1003 /* Clear the dropped flag */
1006 KPRINTF(10, ("readioreq: copyto returned failure!\n"));
1008 /* Trigger any rx, buff or generic error events */
1009 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
|S2EVENT_BUFF
);
1012 NOTE: Can't use RC_* or deverror() this is not called from devBeginIO()!
1014 ioreq
->ios2_DataLength
= 0;
1015 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1016 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1019 /* Pull the ioreq off the list & terminate it */
1021 Remove((struct Node
*) ioreq
);
1023 ReplyMsg((struct Message
*) ioreq
);
1028 /* /// "nReadPacket()" */
1029 BOOL
nReadPacket(struct NepClassEth
*ncp
, UBYTE
*pktptr
, ULONG pktlen
)
1031 struct EtherPacketHeader
*eph
;
1032 struct BufMan
*bufman
;
1033 struct IOSana2Req
*worknode
, *nextnode
;
1034 struct Sana2PacketTypeStats
*stats
;
1038 KPRINTF(20, ("PktIn [%ld] %ld\n", ncp
->ncp_ReadBufNum
, pktlen
));
1039 //bug("in %d\n",pktlen);
1043 ncp
->ncp_DeviceStats
.BadData
++;
1047 ncp
->ncp_DeviceStats
.PacketsReceived
++;
1049 eph
= (struct EtherPacketHeader
*) pktptr
;
1050 stats
= FindPacketTypeStats(ncp
, (ULONG
) AROS_BE2WORD(eph
->eph_Type
));
1051 flags
= DROPPED
|PACKETFILTER
;
1053 /* Calculate size of the actual data */
1054 datasize
= pktlen
- sizeof(struct EtherPacketHeader
);
1056 /* Is the packet datasize valid? */
1057 if(pktlen
<= ETHER_MAX_LEN
)
1059 /* Update the packet statistics */
1062 stats
->PacketsReceived
++;
1063 stats
->BytesReceived
+= datasize
; /* NOTE: don't include headers */
1066 /* For each device user (bufman)
1067 NOTE: We absolutely *MUST* try to offer the packet to *all*
1068 different device users (SANA-II V2 spec requirement). */
1070 bufman
= (struct BufMan
*) ncp
->ncp_BufManList
.lh_Head
;
1071 while(((struct Node
*) bufman
)->ln_Succ
)
1073 /* For each queued read request (ioreq) */
1074 worknode
= (struct IOSana2Req
*) bufman
->bm_RXQueue
.lh_Head
;
1075 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1077 /* Check the packet type. Also handles 802.3 packets. */
1078 if((worknode
->ios2_PacketType
== AROS_BE2WORD(eph
->eph_Type
)) ||
1079 ((AROS_BE2WORD(eph
->eph_Type
) < 1500) && (worknode
->ios2_PacketType
< 1500)))
1081 flags
= nReadIOReq(ncp
, eph
, datasize
, worknode
, flags
);
1082 /* Break out - let other callers get the packet too */
1085 worknode
= nextnode
;
1087 bufman
= (struct BufMan
*) (((struct Node
*) bufman
)->ln_Succ
);
1090 /* Now we've tried to give the packet to every CMD_READ caller.
1091 If DROPPED is set at this point no-one wanted this packet. */
1094 /* So there were no outstanding CMD_READs or the packet wasn't
1095 accepted by any of them. Okay, check if we have any pending
1096 S2_READORPHAN ioreq in list and if we have return this packet
1097 with it. Note that packet filter must not be used for this
1100 NOTE: orphanlist is global, ie. only one caller will get the
1101 packet if multiple users have pending S2_READORPHANs.
1104 /* Process pending orphanread iorequs */
1106 worknode
= (struct IOSana2Req
*) ncp
->ncp_OrphanQueue
.lh_Head
;
1107 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1109 nReadIOReq(ncp
, eph
, datasize
, worknode
, 0);
1110 worknode
= nextnode
;
1114 /* Packet not dropped - return ok */
1118 KPRINTF(20, ("Pktlen %ld invalid!\n", pktlen
));
1119 ncp
->ncp_DeviceStats
.BadData
++;
1121 /* Update global dropped packet counter. */
1122 ncp
->ncp_DeviceStats
.UnknownTypesReceived
++;
1124 /* Update dropped packet statistics. */
1127 stats
->PacketsDropped
++;
1129 KPRINTF(9, ("readpacket: packet type %lu dropped\n", AROS_BE2WORD(eph
->eph_Type
)));
1131 /* Trigger any rx or generic error events */
1132 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
);
1137 /**************************************************************************/