2 *----------------------------------------------------------------------------
3 * ethwrap class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "ethwrap.class.h"
13 static const STRPTR libname
= MOD_NAME_STRING
;
16 const APTR DevFuncTable
[] =
18 &AROS_SLIB_ENTRY(devOpen
, dev
, 1),
19 &AROS_SLIB_ENTRY(devClose
, dev
, 2),
20 &AROS_SLIB_ENTRY(devExpunge
, dev
, 3),
21 &AROS_SLIB_ENTRY(devReserved
, dev
, 4),
22 &AROS_SLIB_ENTRY(devBeginIO
, dev
, 5),
23 &AROS_SLIB_ENTRY(devAbortIO
, dev
, 6),
27 static int libInit(LIBBASETYPEPTR nh
)
29 struct NepClassEth
*ncp
;
30 struct NepEthBase
*ret
= NULL
;
32 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh
, SysBase
));
34 nh
->nh_UtilityBase
= OpenLibrary("utility.library", 39);
36 #define UtilityBase nh->nh_UtilityBase
40 NewList(&nh
->nh_Units
);
42 if((nh
->nh_DevBase
= (struct NepEthDevBase
*) MakeLibrary((APTR
) DevFuncTable
, NULL
, (APTR
) devInit
,
43 sizeof(struct NepEthDevBase
), NULL
)))
45 ncp
= &nh
->nh_DummyNCP
;
46 ncp
->ncp_ClsBase
= nh
;
47 ncp
->ncp_Interface
= NULL
;
48 ncp
->ncp_CDC
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
51 nh
->nh_DevBase
->np_ClsBase
= nh
;
53 AddDevice((struct Device
*) nh
->nh_DevBase
);
54 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
++;
59 KPRINTF(20, ("failed to create usbparallel.device\n"));
63 CloseLibrary(UtilityBase
);
66 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
69 KPRINTF(10, ("libInit: Ok\n"));
70 return(ret
? TRUE
: FALSE
);
73 static int libOpen(LIBBASETYPEPTR nh
)
75 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh
));
80 static int libExpunge(LIBBASETYPEPTR nh
)
82 struct NepClassEth
*ncp
;
84 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh
));
86 if(nh
->nh_DevBase
->np_Library
.lib_OpenCnt
== 1)
88 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%08lx\n",
90 CloseLibrary((struct Library
*) UtilityBase
);
92 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
93 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
95 Remove((struct Node
*) ncp
);
96 FreeVec(ncp
->ncp_CDC
);
98 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
101 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
--;
102 RemDevice((struct Device
*) nh
->nh_DevBase
);
104 KPRINTF(5, ("libExpunge: Unloading done! ethwrap.class expunged!\n\n"));
106 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
113 ADD2INITLIB(libInit
, 0)
114 ADD2OPENLIB(libOpen
, 0)
115 ADD2EXPUNGELIB(libExpunge
, 0)
120 * ***********************************************************************
121 * * Library functions *
122 * ***********************************************************************
131 struct AutoBindData ClassBinds
[] =
133 { 0x0402, 0x5632 }, // ALi defaults
134 { 0x050d, 0x0004 }, // Belkin
135 { 0x050f, 0x0190 }, // KC-190
136 { 0x0525, 0x2888 }, // EPSON USB client
137 { 0x0525, 0x9901 }, // Advance USBNET (eTEK)
138 { 0x0547, 0x2720 }, // AnchorChips defaults
139 { 0x0547, 0x2727 }, // Xircom PGUNET
140 { 0x056c, 0x8100 }, // eTEK
144 /* /// "usbAttemptDeviceBinding()" */
145 struct NepClassEth
* usbAttemptDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
148 struct AutoBindData
*abd
= ClassBinds
;
152 KPRINTF(1, ("nepEthAttemptDeviceBinding(%08lx)\n", pd
));
154 if((ps
= OpenLibrary("poseidon.library", 4)))
156 psdGetAttrs(PGA_DEVICE
, pd
,
157 DA_VendorID
, &vendid
,
158 DA_ProductID
, &prodid
,
161 while(abd
->abd_VendID
)
163 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
165 return(usbForceDeviceBinding(nh
, pd
));
174 /* /// "usbForceDeviceBinding()" */
175 struct NepClassEth
* usbForceDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
178 struct NepClassEth
*ncp
;
179 struct NepClassEth
*tmpncp
;
180 struct ClsDevCfg
*cdc
;
189 KPRINTF(1, ("nepEthForceDeviceBinding(%08lx)\n", pd
));
191 if((ps
= OpenLibrary("poseidon.library", 4)))
193 psdGetAttrs(PGA_DEVICE
, pd
,
194 DA_ProductID
, &prodid
,
195 DA_VendorID
, &vendid
,
196 DA_ProductName
, &devname
,
197 DA_IDString
, &devidstr
,
203 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
204 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
206 if(!strcmp(ncp
->ncp_DevIDString
, devidstr
))
208 unitno
= ncp
->ncp_UnitNo
;
212 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
216 /* as units are freed in the expunge-vector, the memory is
217 outside the scope of the poseidon library */
218 if(!(ncp
= AllocVec(sizeof(struct NepClassEth
), MEMF_PUBLIC
|MEMF_CLEAR
)))
224 ncp
->ncp_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
232 /* IORequests may be queued even if the task is gone. */
233 ncp
->ncp_UnitNo
= (ULONG
) -1;
234 NewList(&ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
);
235 NewList(&ncp
->ncp_OrphanQueue
);
236 NewList(&ncp
->ncp_WriteQueue
);
237 NewList(&ncp
->ncp_BufManList
);
238 NewList(&ncp
->ncp_EventList
);
239 NewList(&ncp
->ncp_TrackList
);
240 NewList(&ncp
->ncp_Multicasts
);
241 strncpy(ncp
->ncp_DevIDString
, devidstr
, 127);
242 AddTail(&nh
->nh_Units
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
);
244 ncp
->ncp_ClsBase
= nh
;
245 ncp
->ncp_Device
= pd
;
246 ncp
->ncp_UnitProdID
= prodid
;
247 ncp
->ncp_UnitVendorID
= vendid
;
249 nLoadBindingConfig(ncp
);
251 /* Find next free unit number */
252 if(unitno
== (ULONG
) -1)
254 unitno
= ncp
->ncp_CDC
->cdc_DefaultUnit
;
255 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
256 while(tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
258 if(tmpncp
->ncp_UnitNo
== unitno
)
261 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
263 tmpncp
= (struct NepClassEth
*) tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
267 ncp
->ncp_UnitNo
= unitno
;
270 psdSafeRawDoFmt(buf
, 64, "ethwrap.class<%08lx>", ncp
);
271 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
272 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
273 SetSignal(0, SIGF_SINGLE
);
274 if(psdSpawnSubTask(buf
, nEthTask
, ncp
))
276 Wait(1L<<ncp
->ncp_ReadySignal
);
279 ncp
->ncp_ReadySigTask
= NULL
;
280 //FreeSignal(ncp->ncp_ReadySignal);
281 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
282 "Mr. Data linked '%s' to %s unit %ld!",
283 devname
, nh
->nh_DevBase
->np_Library
.lib_Node
.ln_Name
,
290 ncp
->ncp_ReadySigTask
= NULL
;
291 //FreeSignal(ncp->ncp_ReadySignal);
292 /* Get rid of unit structure */
294 Remove((struct Node *) ncp);
295 FreeVec(ncp->ncp_CDC);
304 /* /// "usbReleaseDeviceBinding()" */
305 void usbReleaseDeviceBinding(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
309 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp
));
311 if((ps
= OpenLibrary("poseidon.library", 4)))
314 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
315 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
318 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
323 Wait(1L<<ncp
->ncp_ReadySignal
);
325 //FreeSignal(ncp->ncp_ReadySignal);
326 psdGetAttrs(PGA_DEVICE
, ncp
->ncp_Device
, DA_ProductName
, &devname
, TAG_END
);
327 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
328 "Shrinkwrapped and wasted '%s'.",
336 /* /// "usbGetAttrsA()" */
337 AROS_LH3(LONG
, usbGetAttrsA
,
338 AROS_LHA(ULONG
, type
, D0
),
339 AROS_LHA(APTR
, usbstruct
, A0
),
340 AROS_LHA(struct TagItem
*, tags
, A1
),
341 LIBBASETYPEPTR
, nh
, 5, nep
)
348 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
352 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
354 *((SIPTR
*) ti
->ti_Data
) = -100;
357 if((ti
= FindTagItem(UCCA_Description
, tags
)))
359 *((STRPTR
*) ti
->ti_Data
) = "Ethernet SANA wrapper for simple devices via usbethwrap.device";
362 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
364 *((IPTR
*) ti
->ti_Data
) = TRUE
;
367 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
369 *((IPTR
*) ti
->ti_Data
) = TRUE
;
372 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
374 *((IPTR
*) ti
->ti_Data
) = FALSE
;
377 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
379 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCP
.ncp_UsingDefaultCfg
;
385 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
387 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassEth
*) usbstruct
)->ncp_UsingDefaultCfg
;
397 /* /// "usbSetAttrsA()" */
398 AROS_LH3(LONG
, usbSetAttrsA
,
399 AROS_LHA(ULONG
, type
, D0
),
400 AROS_LHA(APTR
, usbstruct
, A0
),
401 AROS_LHA(struct TagItem
*, tags
, A1
),
402 LIBBASETYPEPTR
, nh
, 6, nep
)
410 /* /// "usbDoMethodA()" */
411 AROS_LH2(IPTR
, usbDoMethodA
,
412 AROS_LHA(ULONG
, methodid
, D0
),
413 AROS_LHA(IPTR
*, methoddata
, A1
),
414 LIBBASETYPEPTR
, nh
, 7, nep
)
418 struct NepClassEth
*ncp
;
420 KPRINTF(10, ("Do Method %ld\n", methodid
));
423 case UCM_AttemptDeviceBinding
:
424 return((IPTR
) usbAttemptDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
426 case UCM_ForceDeviceBinding
:
427 return((IPTR
) usbForceDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
429 case UCM_ReleaseDeviceBinding
:
430 usbReleaseDeviceBinding(nh
, (struct NepClassEth
*) methoddata
[0]);
433 case UCM_OpenCfgWindow
:
434 return(nOpenBindingCfgWindow(nh
, &nh
->nh_DummyNCP
));
436 case UCM_OpenBindingCfgWindow
:
437 return(nOpenBindingCfgWindow(nh
, (struct NepClassEth
*) methoddata
[0]));
439 case UCM_ConfigChangedEvent
:
440 nLoadClassConfig(nh
);
442 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
443 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
445 nLoadBindingConfig(ncp
);
446 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
459 /* /// "nLoadClassConfig()" */
460 BOOL
nLoadClassConfig(struct NepEthBase
*nh
)
462 struct NepClassEth
*ncp
= &nh
->nh_DummyNCP
;
464 struct ClsDevCfg
*cdc
;
465 struct PsdIFFContext
*pic
;
467 KPRINTF(10, ("Loading Class Config...\n"));
472 if(!(ps
= OpenLibrary("poseidon.library", 4)))
478 /* Create default config */
480 cdc
->cdc_ChunkID
= AROS_LONG2BE(MAKE_ID('E','T','H','W'));
481 cdc
->cdc_Length
= AROS_LONG2BE(sizeof(struct ClsDevCfg
)-8);
482 cdc
->cdc_DefaultUnit
= 0;
483 cdc
->cdc_MACAddress
[0] = 0x00;
484 cdc
->cdc_MACAddress
[1] = 0xff;
485 cdc
->cdc_MACAddress
[2] = 0xff;
486 cdc
->cdc_MACAddress
[3] = ((IPTR
) cdc
)>>20;
487 cdc
->cdc_MACAddress
[4] = ((IPTR
) cdc
)>>12;
488 cdc
->cdc_MACAddress
[5] = ((IPTR
) cdc
)>>4;
489 ncp
->ncp_UsingDefaultCfg
= TRUE
;
490 /* try to load default config */
491 pic
= psdGetClsCfg(libname
);
494 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
497 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
499 ncp
->ncp_UsingDefaultCfg
= FALSE
;
508 /* /// "nLoadBindingConfig()" */
509 BOOL
nLoadBindingConfig(struct NepClassEth
*ncp
)
511 struct NepEthBase
*nh
= ncp
->ncp_ClsBase
;
513 struct ClsDevCfg
*cdc
;
514 struct PsdIFFContext
*pic
;
516 KPRINTF(10, ("Loading Binding Config...\n"));
521 //nLoadClassConfig(nh);
522 *ncp
->ncp_CDC
= *nh
->nh_DummyNCP
.ncp_CDC
;
523 ncp
->ncp_UsingDefaultCfg
= TRUE
;
525 if(!(ps
= OpenLibrary("poseidon.library", 4)))
532 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
535 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
538 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
540 ncp
->ncp_UsingDefaultCfg
= FALSE
;
549 /* /// "nOpenBindingCfgWindow()" */
550 LONG
nOpenBindingCfgWindow(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
553 KPRINTF(10, ("Opening GUI...\n"));
554 if(!(ps
= OpenLibrary("poseidon.library", 4)))
559 if(!ncp
->ncp_GUITask
)
561 if((ncp
->ncp_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", nGUITask
, ncp
)))
574 /**************************************************************************/
577 #define ps ncp->ncp_Base
579 /* /// "nEthTask()" */
580 AROS_UFH0(void, nEthTask
)
584 struct NepClassEth
*ncp
;
595 struct IOSana2Req
*ioreq
;
597 if((ncp
= nAllocEth()))
600 if(ncp
->ncp_ReadySigTask
)
602 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
606 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
608 // don't overwrite previously configured MAC Address
609 CopyMem(ncp
->ncp_CDC
->cdc_MACAddress
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
);
612 //if((!(ncp->ncp_StateFlags & DDF_OFFLINE)))// && (ncp->ncp_StateFlags & DDF_CONFIGURED))
614 /* Record start time_of_day */
615 //GetSysTime(&ncp->ncp_DeviceStats.LastStart);
617 ncp
->ncp_StateFlags
|= DDF_ONLINE
;
618 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
619 /* Trigger any ONLINE events */
620 nDoEvent(ncp
, S2EVENT_ONLINE
);
624 sigmask
= (1L<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
)|(1L<<ncp
->ncp_TaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
627 // start transmitting read request if online...
628 if((ncp
->ncp_StateFlags
& DDF_ONLINE
) && (ncp
->ncp_ReadPending
== NULL
))
630 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
631 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, ETHER_MAX_LEN
);
632 ncp
->ncp_ReadBufNum
^= 1;
634 while((pp
= (struct PsdPipe
*) GetMsg(ncp
->ncp_TaskMsgPort
)))
636 KPRINTF(1, ("Pipe back %08lx\n", pp
));
637 for(cnt
= 0; cnt
< 2; cnt
++)
639 if(pp
== ncp
->ncp_EPOutPipe
[cnt
])
641 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
643 ioerr
= psdGetPipeError(pp
);
646 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
647 "Eth transmit failed: %s (%ld)",
648 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
650 /* Trigger any tx or generic error events */
651 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
653 /* Set error code and terminate the iorequest.
654 NOTE: Can't use RC_* or deverror() this is not
655 called from devBeginIO()!
657 ioreq
->ios2_DataLength
= 0;
658 ioreq
->ios2_Req
.io_Error
= S2ERR_TX_FAILURE
;
659 ioreq
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
662 ReplyMsg((struct Message
*) ioreq
);
663 ncp
->ncp_WritePending
[cnt
] = NULL
;
668 if(pp
== ncp
->ncp_EPInPipe
)
670 if((pktptr
= ncp
->ncp_ReadPending
))
672 ioerr
= psdGetPipeError(pp
);
673 pktlen
= psdGetPipeActual(pp
);
674 KPRINTF(1, ("ReadBack with %ld bytes.\n", pktlen
));
675 // interleave next packet reading ASAP.
676 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
678 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
679 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, ETHER_MAX_LEN
);
680 ncp
->ncp_ReadBufNum
^= 1;
682 ncp
->ncp_ReadPending
= NULL
;
686 if(lastioerr
!= ioerr
)
688 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
689 "Eth receive failed: %s (%ld)",
690 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
696 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
,
697 "That's it, that device pissed me off long enough!");
698 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
705 KPRINTF(1, ("Pkt %ld received\n", pktlen
));
706 DB(dumpmem(pktptr
, pktlen
));
707 nReadPacket(ncp
, pktptr
, pktlen
);
714 while((!ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
]) && ncp
->ncp_WriteQueue
.lh_Head
->ln_Succ
)
716 ioreq
= (struct IOSana2Req
*) RemHead(&ncp
->ncp_WriteQueue
);
718 nWritePacket(ncp
, ioreq
);
722 sigs
= Wait(sigmask
);
723 } while(!(sigs
& SIGBREAKF_CTRL_C
));
726 /* Now remove all requests still pending *anywhere* */
727 //ncp->ncp_DenyRequests = TRUE;
728 /* Current transfers */
729 for(cnt
= 0; cnt
< 2; cnt
++)
731 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
733 KPRINTF(1, ("Aborting pending write...\n"));
734 psdAbortPipe(ncp
->ncp_EPOutPipe
[cnt
]);
735 psdWaitPipe(ncp
->ncp_EPOutPipe
[cnt
]);
736 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
737 ReplyMsg((struct Message
*) ioreq
);
738 ncp
->ncp_WritePending
[cnt
] = NULL
;
741 if(ncp
->ncp_ReadPending
)
743 KPRINTF(1, ("Aborting pending read...\n"));
744 psdAbortPipe(ncp
->ncp_EPInPipe
);
745 psdWaitPipe(ncp
->ncp_EPInPipe
);
746 ncp
->ncp_ReadPending
= NULL
;
750 nDoEvent(ncp
, S2EVENT_OFFLINE
);
752 KPRINTF(20, ("Going down the river!\n"));
760 /* /// "nAllocEth()" */
761 struct NepClassEth
* nAllocEth(void)
763 struct Task
*thistask
;
764 struct NepClassEth
*ncp
;
766 thistask
= FindTask(NULL
);
769 ncp
= thistask
->tc_UserData
;
770 if(!(ncp
->ncp_Base
= OpenLibrary("poseidon.library", 4)))
776 ncp
->ncp_Interface
= psdFindInterface(ncp
->ncp_Device
, NULL
,
779 if(!ncp
->ncp_Interface
)
781 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "No interface?");
785 ncp
->ncp_EPIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
787 EA_TransferType
, USEAF_BULK
,
789 ncp
->ncp_EPOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
791 EA_TransferType
, USEAF_BULK
,
793 if(!(ncp
->ncp_EPIn
&& ncp
->ncp_EPOut
))
795 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
799 ncp
->ncp_ReadPending
= NULL
;
800 ncp
->ncp_WritePending
[0] = NULL
;
801 ncp
->ncp_WritePending
[1] = NULL
;
802 if(!(ncp
->ncp_ReadBuffer
[0] = AllocVec(ETHER_MAX_LEN
* 4, MEMF_PUBLIC
|MEMF_CLEAR
)))
804 KPRINTF(1, ("Out of memory for read buffer\n"));
807 ncp
->ncp_ReadBuffer
[1] = ncp
->ncp_ReadBuffer
[0] + ETHER_MAX_LEN
;
808 ncp
->ncp_WriteBuffer
[0] = ncp
->ncp_ReadBuffer
[1] + ETHER_MAX_LEN
;
809 ncp
->ncp_WriteBuffer
[1] = ncp
->ncp_WriteBuffer
[0] + ETHER_MAX_LEN
;
810 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
811 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
812 ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
813 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
815 if((ncp
->ncp_TaskMsgPort
= CreateMsgPort()))
817 if((ncp
->ncp_EP0Pipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, NULL
)))
819 if((ncp
->ncp_EPOutPipe
[0] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
821 /* Turn off short packets */
822 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[0],
823 PPA_NoShortPackets
, FALSE
,
824 PPA_NakTimeout
, TRUE
,
825 PPA_NakTimeoutTime
, 5000,
827 if((ncp
->ncp_EPOutPipe
[1] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
829 /* Turn off short packets */
830 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[1],
831 PPA_NoShortPackets
, FALSE
,
832 PPA_NakTimeout
, TRUE
,
833 PPA_NakTimeoutTime
, 5000,
835 if((ncp
->ncp_EPInPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPIn
)))
837 /* Turn off short packets */
838 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPInPipe
,
839 PPA_NakTimeout
, FALSE
,
840 PPA_NakTimeoutTime
, 5000,
841 PPA_AllowRuntPackets
, TRUE
,
843 ncp
->ncp_Task
= thistask
;
847 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
849 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
851 psdFreePipe(ncp
->ncp_EP0Pipe
);
853 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
855 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
857 if(ncp
->ncp_ReadBuffer
[0])
859 FreeVec(ncp
->ncp_ReadBuffer
[0]);
860 ncp
->ncp_ReadBuffer
[0] = NULL
;
862 CloseLibrary(ncp
->ncp_Base
);
864 ncp
->ncp_Task
= NULL
;
865 if(ncp
->ncp_ReadySigTask
)
867 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
873 /* /// "nFreeEth()" */
874 void nFreeEth(struct NepClassEth
*ncp
)
876 struct IOSana2Req
*ioreq
;
878 /* Disable the message port, messages may still be queued */
879 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
880 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
881 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
882 // get rid of all messages that still have appeared here
883 while((ioreq
= (struct IOSana2Req
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
885 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
886 ReplyMsg((struct Message
*) ioreq
);
890 psdFreePipe(ncp
->ncp_EPInPipe
);
891 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
892 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
893 psdFreePipe(ncp
->ncp_EP0Pipe
);
895 if(ncp
->ncp_ReadBuffer
[0])
897 FreeVec(ncp
->ncp_ReadBuffer
[0]);
898 ncp
->ncp_ReadBuffer
[0] = NULL
;
901 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
902 CloseLibrary(ncp
->ncp_Base
);
904 ncp
->ncp_Task
= NULL
;
905 if(ncp
->ncp_ReadySigTask
)
907 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
912 /* /// "nDoEvent()" */
913 void nDoEvent(struct NepClassEth
*ncp
, ULONG events
)
915 struct IOSana2Req
*worknode
, *nextnode
;
917 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events
));
920 /* Process pending S2_ONEVENT requests */
921 worknode
= (struct IOSana2Req
*) ncp
->ncp_EventList
.lh_Head
;
922 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
924 if(worknode
->ios2_WireError
& events
)
926 Remove(&worknode
->ios2_Req
.io_Message
.mn_Node
);
927 worknode
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
928 KPRINTF(1, ("DoEvent: returned eventreq 0x%08lx\n", worknode
));
929 ReplyMsg(&worknode
->ios2_Req
.io_Message
);
937 /* /// "support routines" */
939 inline void *callcopy(void *routine
,
944 void * (*call
) (APTR
, APTR
, ULONG
) = routine
;
946 return (*call
) (from
, to
, len
);
949 #define callfilter CallHookPkt
952 /* /// "nWritePacket()" */
953 BOOL
nWritePacket(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
956 struct EtherPacketHeader
*eph
;
959 struct BufMan
*bufman
;
960 struct Sana2PacketTypeStats
*stats
;
961 UBYTE
*buf
= ncp
->ncp_WriteBuffer
[ncp
->ncp_WriteBufNum
];
963 packettype
= ioreq
->ios2_PacketType
;
964 // the first two bytes are the length
965 eph
= (struct EtherPacketHeader
*) buf
;
967 writelen
= ioreq
->ios2_DataLength
;
968 bufman
= ioreq
->ios2_BufferManagement
;
970 /* Not a raw packet? */
971 if(!(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
))
974 KPRINTF(10, ("RAW WRITE!\n"));
975 /* The ethernet header isn't included in the data */
976 /* Build ethernet packet header */
977 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
979 eph
->eph_Dest
[cnt
] = ioreq
->ios2_DstAddr
[cnt
];
980 eph
->eph_Src
[cnt
] = ncp
->ncp_MacAddress
[cnt
];
982 eph
->eph_Type
= AROS_BE2WORD(packettype
);
984 /* Packet data is at txbuffer */
985 copydest
+= sizeof(struct EtherPacketHeader
);
986 writelen
+= sizeof(struct EtherPacketHeader
);
989 /* Dma not available, fallback to regular copy */
990 if(callcopy(bufman
->bm_CopyFromBuf
, copydest
, ioreq
->ios2_Data
, ioreq
->ios2_DataLength
) == NULL
)
992 KPRINTF(10, ("writepacket: copyfrom returned failure!\n"));
994 /* Trigger any tx, buff or generic error events */
995 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
|S2EVENT_BUFF
);
997 /* Set error code and terminate the iorequest.
998 NOTE: Can't use RC_* or deverror() this is not
999 called from devBeginIO()! */
1000 ioreq
->ios2_DataLength
= 0;
1001 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1002 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1006 KPRINTF(20, ("PktOut[%ld] %ld\n", ncp
->ncp_WriteBufNum
, writelen
));
1008 ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
] = ioreq
;
1009 psdSendPipe(ncp
->ncp_EPOutPipe
[ncp
->ncp_WriteBufNum
], buf
, (ULONG
) writelen
);
1010 ncp
->ncp_WriteBufNum
^= 1;
1013 if(AROS_BE2WORD(eph
->eph_Type
) < 1500)
1015 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx (IEEE802.3) len %lu, %lu bytes\n",
1016 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
1017 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
1018 AROS_BE2WORD(eph
->eph_Type
), writelen
));
1020 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx type %lu, %lu bytes\n",
1021 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
1022 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
1023 AROS_BE2WORD(eph
->eph_Type
), writelen
));
1025 //dumpmem(buf, (ULONG) writelen);
1028 /* Update statistics */
1029 stats
= FindPacketTypeStats(ncp
, packettype
);
1032 stats
->PacketsSent
++;
1033 stats
->BytesSent
+= writelen
;
1035 ncp
->ncp_DeviceStats
.PacketsSent
++;
1041 /* /// "nReadIOReq()" */
1042 UWORD
nReadIOReq(struct NepClassEth
*ncp
, struct EtherPacketHeader
*eph
, UWORD datasize
, struct IOSana2Req
*ioreq
, UWORD flags
)
1044 LIBBASETYPEPTR nh
= ncp
->ncp_ClsBase
;
1048 /* Handle RAW read */
1049 if(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
)
1051 /* ShapeShifter won't work with `sizeof(struct etherpacket_hdr)'
1052 here. This is most likely because it want the RAW ethernet
1053 packet checksum size (4) added to the packet size. */
1054 copyfrom
= (UBYTE
*) eph
;
1055 datasize
+= sizeof(struct EtherPacketHeader
) + 4;
1057 copyfrom
= (UBYTE
*) (eph
+ 1);
1060 /* Build up the ios2 structure enough so we can call the packet filter. */
1061 ioreq
->ios2_PacketType
= AROS_BE2WORD(eph
->eph_Type
);
1062 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
1064 ioreq
->ios2_SrcAddr
[cnt
] = eph
->eph_Src
[cnt
];
1065 ioreq
->ios2_DstAddr
[cnt
] = eph
->eph_Dest
[cnt
];
1067 ioreq
->ios2_DataLength
= datasize
;
1068 /* Call the packet filter, if available. */
1069 if((flags
& PACKETFILTER
) &&
1070 (((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
) &&
1071 (!callfilter(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
,
1074 /* This packet got dropped! */
1075 KPRINTF(7, ("readioreq: packet type %lu for ioreq 0x%08lx dropped\n",
1076 AROS_BE2WORD(eph
->eph_Type
), ioreq
));
1081 /* Ok, the packet didn't get dropped, set the BCAST and MCAST
1082 flags according to dstaddr. */
1084 /* Address == Multicast? */
1085 if(ioreq
->ios2_DstAddr
[0] & 1)
1087 /* Address == Broadcast? */
1088 static const UBYTE bcast
[ETHER_ADDR_SIZE
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1089 if(memcmp(bcast
, ioreq
->ios2_DstAddr
, ETHER_ADDR_SIZE
) == 0)
1091 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1093 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1097 /* Finally copy the packet data! */
1098 if(callcopy(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_CopyToBuf
,
1099 ioreq
->ios2_Data
, copyfrom
, ioreq
->ios2_DataLength
))
1102 KPRINTF(5, ("readioreq: copytobuffed packet ior 0x%08lx, %04lx%08lx < %04lx%08lx, type %lu, %lu bytes, %s%s%s\n",
1104 *((UWORD
*) ioreq
->ios2_DstAddr
), *((ULONG
*) (ioreq
->ios2_DstAddr
+ 2)),
1105 *((UWORD
*) ioreq
->ios2_SrcAddr
), *((ULONG
*) (ioreq
->ios2_SrcAddr
+ 2)),
1106 ioreq
->ios2_PacketType
, ioreq
->ios2_DataLength
,
1107 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) ? "RAW " : "",
1108 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_BCAST
) ? "BCAST " : "",
1109 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_MCAST
) ? "MCAST " : ""));
1110 //dumpmem(copyfrom, ioreq->ios2_DataLength);
1113 /* Clear the dropped flag */
1116 KPRINTF(10, ("readioreq: copyto returned failure!\n"));
1118 /* Trigger any rx, buff or generic error events */
1119 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
|S2EVENT_BUFF
);
1122 NOTE: Can't use RC_* or deverror() this is not called from devBeginIO()!
1124 ioreq
->ios2_DataLength
= 0;
1125 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1126 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1129 /* Pull the ioreq off the list & terminate it */
1131 Remove((struct Node
*) ioreq
);
1133 ReplyMsg((struct Message
*) ioreq
);
1138 /* /// "nReadPacket()" */
1139 BOOL
nReadPacket(struct NepClassEth
*ncp
, UBYTE
*pktptr
, ULONG pktlen
)
1141 struct EtherPacketHeader
*eph
;
1142 struct BufMan
*bufman
;
1143 struct IOSana2Req
*worknode
, *nextnode
;
1144 struct Sana2PacketTypeStats
*stats
;
1148 KPRINTF(20, ("PktIn [%ld] %ld\n", ncp
->ncp_ReadBufNum
, pktlen
));
1152 ncp
->ncp_DeviceStats
.BadData
++;
1155 ncp
->ncp_DeviceStats
.PacketsReceived
++;
1157 eph
= (struct EtherPacketHeader
*) pktptr
;
1158 stats
= FindPacketTypeStats(ncp
, (ULONG
) AROS_BE2WORD(eph
->eph_Type
));
1159 flags
= DROPPED
|PACKETFILTER
;
1161 /* Calculate size of the actual data */
1162 datasize
= pktlen
- sizeof(struct EtherPacketHeader
);
1164 /* Is the packet datasize valid? */
1165 if(pktlen
<= ETHER_MAX_LEN
)
1167 /* Update the packet statistics */
1170 stats
->PacketsReceived
++;
1171 stats
->BytesReceived
+= datasize
; /* NOTE: don't include headers */
1174 /* For each device user (bufman)
1175 NOTE: We absolutely *MUST* try to offer the packet to *all*
1176 different device users (SANA-II V2 spec requirement). */
1178 bufman
= (struct BufMan
*) ncp
->ncp_BufManList
.lh_Head
;
1179 while(((struct Node
*) bufman
)->ln_Succ
)
1181 /* For each queued read request (ioreq) */
1182 worknode
= (struct IOSana2Req
*) bufman
->bm_RXQueue
.lh_Head
;
1183 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1185 /* Check the packet type. Also handles 802.3 packets. */
1186 if((worknode
->ios2_PacketType
== AROS_BE2WORD(eph
->eph_Type
)) ||
1187 ((AROS_BE2WORD(eph
->eph_Type
) < 1500) && (worknode
->ios2_PacketType
< 1500)))
1189 flags
= nReadIOReq(ncp
, eph
, datasize
, worknode
, flags
);
1190 /* Break out - let other callers get the packet too */
1193 worknode
= nextnode
;
1195 bufman
= (struct BufMan
*) (((struct Node
*) bufman
)->ln_Succ
);
1198 /* Now we've tried to give the packet to every CMD_READ caller.
1199 If DROPPED is set at this point no-one wanted this packet. */
1202 /* So there were no outstanding CMD_READs or the packet wasn't
1203 accepted by any of them. Okay, check if we have any pending
1204 S2_READORPHAN ioreq in list and if we have return this packet
1205 with it. Note that packet filter must not be used for this
1208 NOTE: orphanlist is global, ie. only one caller will get the
1209 packet if multiple users have pending S2_READORPHANs.
1212 /* Process pending orphanread iorequs */
1214 worknode
= (struct IOSana2Req
*) ncp
->ncp_OrphanQueue
.lh_Head
;
1215 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1217 nReadIOReq(ncp
, eph
, datasize
, worknode
, 0);
1218 worknode
= nextnode
;
1222 /* Packet not dropped - return ok */
1226 KPRINTF(20, ("Pktlen %ld invalid!\n", pktlen
));
1227 ncp
->ncp_DeviceStats
.BadData
++;
1229 /* Update global dropped packet counter. */
1230 ncp
->ncp_DeviceStats
.UnknownTypesReceived
++;
1232 /* Update dropped packet statistics. */
1235 stats
->PacketsDropped
++;
1237 KPRINTF(9, ("readpacket: packet type %lu dropped\n", AROS_BE2WORD(eph
->eph_Type
)));
1239 /* Trigger any rx or generic error events */
1240 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
);
1245 /**************************************************************************/
1247 /* /// "nGetMACAddress()" */
1248 void nGetMACAddress(UBYTE
*macaddr
, CONST_STRPTR tmpstr
)
1254 while((ch
= *tmpstr
++))
1256 if((ch
>= '0') && (ch
<= '9'))
1259 macbyte
+= ch
- '0';
1261 else if((ch
>= 'a') && (ch
<= 'f'))
1264 macbyte
+= ch
- 'a' + 10;
1266 else if((ch
>= 'A') && (ch
<= 'F'))
1269 macbyte
+= ch
- 'A' + 10;
1277 macaddr
[cnt
] = macbyte
;
1282 macaddr
[cnt
] = macbyte
;
1286 /* /// "nGUITask()" */
1287 AROS_UFH0(void, nGUITask
)
1291 struct Task
*thistask
;
1292 struct NepEthBase
*nh
;
1293 struct NepClassEth
*ncp
;
1294 struct PsdIFFContext
*pic
;
1297 thistask
= FindTask(NULL
);
1299 #define ps ncp->ncp_PsdBase
1300 #undef IntuitionBase
1301 #define IntuitionBase ncp->ncp_IntBase
1302 #undef MUIMasterBase
1303 #define MUIMasterBase ncp->ncp_MUIBase
1305 ncp
= thistask
->tc_UserData
;
1306 nh
= ncp
->ncp_ClsBase
;
1308 ++nh
->nh_Library
.lib_OpenCnt
;
1309 if(!(MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MUIMASTER_VMIN
)))
1311 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
1312 nGUITaskCleanup(ncp
);
1316 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
1318 KPRINTF(10, ("Couldn't open intuition.library.\n"));
1319 nGUITaskCleanup(ncp
);
1322 if(!(ps
= OpenLibrary("poseidon.library", 4)))
1324 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
1325 nGUITaskCleanup(ncp
);
1329 psdSafeRawDoFmt(macaddr
, 20, "%02lx:%02lx:%02lx:%02lx:%02lx:%02lx",
1330 ncp
->ncp_CDC
->cdc_MACAddress
[0],
1331 ncp
->ncp_CDC
->cdc_MACAddress
[1],
1332 ncp
->ncp_CDC
->cdc_MACAddress
[2],
1333 ncp
->ncp_CDC
->cdc_MACAddress
[3],
1334 ncp
->ncp_CDC
->cdc_MACAddress
[4],
1335 ncp
->ncp_CDC
->cdc_MACAddress
[5]);
1337 ncp
->ncp_App
= ApplicationObject
,
1338 MUIA_Application_Title
, (IPTR
)libname
,
1339 MUIA_Application_Version
, (IPTR
)VERSION_STRING
,
1340 MUIA_Application_Copyright
, (IPTR
)"©2006-2007 Harry Sintonen & Chris Hodges",
1341 MUIA_Application_Author
, (IPTR
)"Harry Sintonen <sintonen@iki.fi> & Chris Hodges <chrisly@platon42.de>",
1342 MUIA_Application_Description
, (IPTR
)"Settings for the ethwrap.class",
1343 MUIA_Application_Base
, (IPTR
)"ETHWRAP",
1344 MUIA_Application_HelpFile
, (IPTR
)"HELP:Poseidon.guide",
1345 MUIA_Application_Menustrip
, (IPTR
)MenustripObject
,
1346 Child
, (IPTR
)MenuObjectT((IPTR
)"Project"),
1347 Child
, (IPTR
)(ncp
->ncp_AboutMI
= MenuitemObject
,
1348 MUIA_Menuitem_Title
, (IPTR
)"About...",
1349 MUIA_Menuitem_Shortcut
, (IPTR
)"?",
1352 Child
, (IPTR
)MenuObjectT((IPTR
)"Settings"),
1353 Child
, (IPTR
)(ncp
->ncp_UseMI
= MenuitemObject
,
1354 MUIA_Menuitem_Title
, (IPTR
)"Save",
1355 MUIA_Menuitem_Shortcut
, (IPTR
)"S",
1357 Child
, (IPTR
)(ncp
->ncp_SetDefaultMI
= MenuitemObject
,
1358 MUIA_Menuitem_Title
, (IPTR
)"Set as Default",
1359 MUIA_Menuitem_Shortcut
, (IPTR
)"D",
1361 Child
, (IPTR
)MenuitemObject
,
1362 MUIA_Menuitem_Title
, (IPTR
)NM_BARLABEL
,
1364 Child
, (IPTR
)(ncp
->ncp_MUIPrefsMI
= MenuitemObject
,
1365 MUIA_Menuitem_Title
, (IPTR
)"MUI Settings",
1366 MUIA_Menuitem_Shortcut
, (IPTR
)"M",
1371 SubWindow
, (IPTR
)(ncp
->ncp_MainWindow
= WindowObject
,
1372 MUIA_Window_ID
, MAKE_ID('M','A','I','N'),
1373 MUIA_Window_Title
, (IPTR
)libname
,
1374 MUIA_HelpNode
, (IPTR
)libname
,
1376 WindowContents
, (IPTR
)VGroup
,
1377 Child
, (IPTR
)ColGroup(2), GroupFrameT(ncp
->ncp_Interface
? "Device Settings" : "Default Device Settings"),
1379 Child
, (IPTR
)Label((IPTR
) "Default MAC Address:"),
1380 Child
, (IPTR
)(ncp
->ncp_MACAddressObj
= StringObject
,
1383 MUIA_String_AdvanceOnCR
, TRUE
,
1384 MUIA_String_Contents
, (IPTR
)macaddr
,
1385 MUIA_String_MaxLen
, 18,
1386 MUIA_String_Accept
, (IPTR
)"0123456789abcdefABCDEF:",
1388 Child
, (IPTR
)Label((IPTR
) "Default " DEVNAME
" Unit:"),
1389 Child
, (IPTR
)(ncp
->ncp_UnitObj
= StringObject
,
1392 MUIA_String_AdvanceOnCR
, TRUE
,
1393 MUIA_String_Integer
, ncp
->ncp_CDC
->cdc_DefaultUnit
,
1394 MUIA_String_Accept
, (IPTR
)"0123456789",
1397 Child
, (IPTR
)VSpace(0),
1398 Child
, (IPTR
)HGroup
,
1399 MUIA_Group_SameWidth
, TRUE
,
1400 Child
, (IPTR
)(ncp
->ncp_UseObj
= TextObject
, ButtonFrame
,
1401 MUIA_ShowMe
, (IPTR
)ncp
->ncp_Interface
,
1402 MUIA_Background
, MUII_ButtonBack
,
1404 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1405 MUIA_Text_Contents
, (IPTR
)"\33c Save ",
1407 Child
, (IPTR
)(ncp
->ncp_SetDefaultObj
= TextObject
, ButtonFrame
,
1408 MUIA_Background
, MUII_ButtonBack
,
1410 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1411 MUIA_Text_Contents
, (IPTR
)(ncp
->ncp_Interface
? "\33c Save as Default " : "\33c Save Defaults "),
1413 Child
, (IPTR
)(ncp
->ncp_CloseObj
= TextObject
, ButtonFrame
,
1414 MUIA_Background
, MUII_ButtonBack
,
1416 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1417 MUIA_Text_Contents
, (IPTR
)"\33c Use ",
1426 KPRINTF(10, ("Couldn't create application\n"));
1427 nGUITaskCleanup(ncp
);
1431 DoMethod(ncp
->ncp_MainWindow
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
1432 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
1433 DoMethod(ncp
->ncp_UseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1434 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
1435 DoMethod(ncp
->ncp_SetDefaultObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1436 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
1437 DoMethod(ncp
->ncp_CloseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1438 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
1440 DoMethod(ncp
->ncp_AboutMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1441 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_ABOUT
);
1442 DoMethod(ncp
->ncp_UseMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1443 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
1444 DoMethod(ncp
->ncp_SetDefaultMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1445 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
1446 DoMethod(ncp
->ncp_MUIPrefsMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1447 ncp
->ncp_App
, 2, MUIM_Application_OpenConfigWindow
, 0);
1455 get(ncp
->ncp_App
, MUIA_Application_Iconified
, &iconify
);
1456 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, TRUE
);
1457 get(ncp
->ncp_MainWindow
, MUIA_Window_Open
, &isopen
);
1458 if(!(isopen
|| iconify
))
1460 nGUITaskCleanup(ncp
);
1466 retid
= DoMethod(ncp
->ncp_App
, MUIM_Application_NewInput
, &sigs
);
1470 case ID_STORE_CONFIG
:
1471 case MUIV_Application_ReturnID_Quit
:
1473 CONST_STRPTR tmpstr
= "";
1474 get(ncp
->ncp_UnitObj
, MUIA_String_Integer
, &ncp
->ncp_CDC
->cdc_DefaultUnit
);
1475 get(ncp
->ncp_MACAddressObj
, MUIA_String_Contents
, &tmpstr
);
1477 nGetMACAddress(ncp
->ncp_CDC
->cdc_MACAddress
, tmpstr
);
1479 if(retid
== ID_DEF_CONFIG
)
1481 pic
= psdGetClsCfg(libname
);
1484 psdSetClsCfg(libname
, NULL
);
1485 pic
= psdGetClsCfg(libname
);
1489 psdAddCfgEntry(pic
, ncp
->ncp_CDC
);
1490 psdSaveCfgToDisk(NULL
, FALSE
);
1493 if(ncp
->ncp_Interface
)
1495 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
1498 psdSetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
, NULL
);
1499 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
1503 if(psdAddCfgEntry(pic
, ncp
->ncp_CDC
))
1505 if(retid
!= MUIV_Application_ReturnID_Quit
)
1507 psdSaveCfgToDisk(NULL
, FALSE
);
1509 retid
= MUIV_Application_ReturnID_Quit
;
1513 retid
= MUIV_Application_ReturnID_Quit
;
1519 MUI_RequestA(ncp
->ncp_App
, ncp
->ncp_MainWindow
, 0, NULL
, "Phat!", VERSION_STRING
, NULL
);
1522 if(retid
== MUIV_Application_ReturnID_Quit
)
1528 sigs
= Wait(sigs
|sigmask
|SIGBREAKF_CTRL_C
);
1529 if(sigs
& SIGBREAKF_CTRL_C
)
1535 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, FALSE
);
1537 nGUITaskCleanup(ncp
);
1543 /* /// "nGUITaskCleanup()" */
1544 void nGUITaskCleanup(struct NepClassEth
*ncp
)
1548 MUI_DisposeObject(ncp
->ncp_App
);
1549 ncp
->ncp_App
= NULL
;
1553 CloseLibrary(MUIMasterBase
);
1554 MUIMasterBase
= NULL
;
1558 CloseLibrary(IntuitionBase
);
1559 IntuitionBase
= NULL
;
1567 ncp
->ncp_GUIBinding
= NULL
;
1568 ncp
->ncp_GUITask
= NULL
;
1569 if(ncp
->ncp_ReadySigTask
)
1571 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
1573 --ncp
->ncp_ClsBase
->nh_Library
.lib_OpenCnt
;