2 *----------------------------------------------------------------------------
3 * dm9601eth class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "dm9601eth.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 dm9601eth.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! dm9601eth.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)
119 * ***********************************************************************
120 * * Library functions *
121 * ***********************************************************************
130 struct AutoBindData ClassBinds
[] =
132 { 0x07aa, 0x9601 }, /* Corega FEther USB-TXC */
133 { 0x0a46, 0x9601 }, /* Davicom USB-100 */
134 { 0x0a46, 0x6688 }, /* ZT6688 USB NIC */
135 { 0x0a46, 0x0268 }, /* ShanTou ST268 USB NIC */
136 { 0x0a46, 0x8515 }, /* ADMtek ADM8515 USB NIC */
137 { 0x0a47, 0x9601 }, /* Hirose USB-100 */
138 { 0x0fe6, 0x8101 }, /* DM9601 USB to Fast Ethernet Adapter */
142 /* /// "usbAttemptDeviceBinding()" */
143 struct NepClassEth
* usbAttemptDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
146 struct AutoBindData
*abd
= ClassBinds
;
150 KPRINTF(1, ("nepEthAttemptDeviceBinding(%08lx)\n", pd
));
152 if((ps
= OpenLibrary("poseidon.library", 4)))
154 psdGetAttrs(PGA_DEVICE
, pd
,
155 DA_VendorID
, &vendid
,
156 DA_ProductID
, &prodid
,
159 while(abd
->abd_VendID
)
161 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
163 return(usbForceDeviceBinding(nh
, pd
));
172 /* /// "usbForceDeviceBinding()" */
173 struct NepClassEth
* usbForceDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
176 struct NepClassEth
*ncp
;
177 struct NepClassEth
*tmpncp
;
178 struct ClsDevCfg
*cdc
;
179 struct AutoBindData
*abd
= ClassBinds
;
187 struct Task
*tmptask
;
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
,
201 while(abd
->abd_VendID
)
203 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
212 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
213 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
215 if(!strcmp(ncp
->ncp_DevIDString
, devidstr
))
217 unitno
= ncp
->ncp_UnitNo
;
221 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
225 /* as units are freed in the expunge-vector, the memory is
226 outside the scope of the poseidon library */
227 if(!(ncp
= AllocVec(sizeof(struct NepClassEth
), MEMF_PUBLIC
|MEMF_CLEAR
)))
233 ncp
->ncp_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
241 /* IORequests may be queued even if the task is gone. */
242 ncp
->ncp_UnitNo
= (ULONG
) -1;
243 NewList(&ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
);
244 NewList(&ncp
->ncp_OrphanQueue
);
245 NewList(&ncp
->ncp_WriteQueue
);
246 NewList(&ncp
->ncp_BufManList
);
247 NewList(&ncp
->ncp_EventList
);
248 NewList(&ncp
->ncp_TrackList
);
249 NewList(&ncp
->ncp_Multicasts
);
250 strncpy(ncp
->ncp_DevIDString
, devidstr
, 127);
251 AddTail(&nh
->nh_Units
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
);
253 ncp
->ncp_ClsBase
= nh
;
254 ncp
->ncp_Device
= pd
;
255 ncp
->ncp_UnitProdID
= prodid
;
256 ncp
->ncp_UnitVendorID
= vendid
;
258 nLoadBindingConfig(ncp
);
260 /* Find next free unit number */
261 if(unitno
== (ULONG
) -1)
263 unitno
= ncp
->ncp_CDC
->cdc_DefaultUnit
;
264 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
265 while(tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
267 if(tmpncp
->ncp_UnitNo
== unitno
)
270 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
272 tmpncp
= (struct NepClassEth
*) tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
276 ncp
->ncp_UnitNo
= unitno
;
279 psdSafeRawDoFmt(buf
, 64, "dm9601eth.class<%08lx>", ncp
);
280 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
281 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
282 SetSignal(0, SIGF_SINGLE
);
283 if((tmptask
= psdSpawnSubTask(buf
, nEthTask
, ncp
)))
285 psdBorrowLocksWait(tmptask
, 1UL<<ncp
->ncp_ReadySignal
);
288 ncp
->ncp_ReadySigTask
= NULL
;
289 //FreeSignal(ncp->ncp_ReadySignal);
290 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
291 "And Goliath trembled with fear over '%s' on %s unit %ld!",
292 devname
, nh
->nh_DevBase
->np_Library
.lib_Node
.ln_Name
,
299 ncp
->ncp_ReadySigTask
= NULL
;
300 //FreeSignal(ncp->ncp_ReadySignal);
301 /* Get rid of unit structure */
303 Remove((struct Node *) ncp);
304 FreeVec(ncp->ncp_CDC);
313 /* /// "usbReleaseDeviceBinding()" */
314 void usbReleaseDeviceBinding(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
318 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp
));
320 if((ps
= OpenLibrary("poseidon.library", 4)))
323 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
324 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
327 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
332 Wait(1L<<ncp
->ncp_ReadySignal
);
334 //FreeSignal(ncp->ncp_ReadySignal);
335 psdGetAttrs(PGA_DEVICE
, ncp
->ncp_Device
, DA_ProductName
, &devname
, TAG_END
);
336 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
337 "But finally Goliath crushed '%s'.",
345 /* /// "usbGetAttrsA()" */
346 AROS_LH3(LONG
, usbGetAttrsA
,
347 AROS_LHA(ULONG
, type
, D0
),
348 AROS_LHA(APTR
, usbstruct
, A0
),
349 AROS_LHA(struct TagItem
*, tags
, A1
),
350 LIBBASETYPEPTR
, nh
, 5, nep
)
357 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
361 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
363 *((SIPTR
*) ti
->ti_Data
) = 0;
366 if((ti
= FindTagItem(UCCA_Description
, tags
)))
368 *((STRPTR
*) ti
->ti_Data
) = "Ethernet SANA driver for Davicom chipsets via dm9601eth.device";
371 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
373 *((IPTR
*) ti
->ti_Data
) = TRUE
;
376 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
378 *((IPTR
*) ti
->ti_Data
) = TRUE
;
381 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
383 *((IPTR
*) ti
->ti_Data
) = FALSE
;
386 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
388 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCP
.ncp_UsingDefaultCfg
;
394 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
396 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassEth
*) usbstruct
)->ncp_UsingDefaultCfg
;
406 /* /// "usbSetAttrsA()" */
407 AROS_LH3(LONG
, usbSetAttrsA
,
408 AROS_LHA(ULONG
, type
, D0
),
409 AROS_LHA(APTR
, usbstruct
, A0
),
410 AROS_LHA(struct TagItem
*, tags
, A1
),
411 LIBBASETYPEPTR
, nh
, 6, nep
)
419 /* /// "usbDoMethodA()" */
420 AROS_LH2(IPTR
, usbDoMethodA
,
421 AROS_LHA(ULONG
, methodid
, D0
),
422 AROS_LHA(IPTR
*, methoddata
, A1
),
423 LIBBASETYPEPTR
, nh
, 7, nep
)
427 struct NepClassEth
*ncp
;
429 KPRINTF(10, ("Do Method %ld\n", methodid
));
432 case UCM_AttemptDeviceBinding
:
433 return((IPTR
) usbAttemptDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
435 case UCM_ForceDeviceBinding
:
436 return((IPTR
) usbForceDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
438 case UCM_ReleaseDeviceBinding
:
439 usbReleaseDeviceBinding(nh
, (struct NepClassEth
*) methoddata
[0]);
442 case UCM_OpenCfgWindow
:
443 return(nOpenBindingCfgWindow(nh
, &nh
->nh_DummyNCP
));
445 case UCM_OpenBindingCfgWindow
:
446 return(nOpenBindingCfgWindow(nh
, (struct NepClassEth
*) methoddata
[0]));
448 case UCM_ConfigChangedEvent
:
449 nLoadClassConfig(nh
);
451 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
452 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
454 nLoadBindingConfig(ncp
);
455 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
468 /* /// "nLoadClassConfig()" */
469 BOOL
nLoadClassConfig(struct NepEthBase
*nh
)
471 struct NepClassEth
*ncp
= &nh
->nh_DummyNCP
;
473 struct ClsDevCfg
*cdc
;
474 struct PsdIFFContext
*pic
;
476 KPRINTF(10, ("Loading Class Config...\n"));
481 if(!(ps
= OpenLibrary("poseidon.library", 4)))
487 /* Create default config */
489 cdc
->cdc_ChunkID
= AROS_LONG2BE(MAKE_ID('D','M','9','6'));
490 cdc
->cdc_Length
= AROS_LONG2BE(sizeof(struct ClsDevCfg
)-8);
491 cdc
->cdc_DefaultUnit
= 0;
492 cdc
->cdc_MediaType
= 0;
493 ncp
->ncp_UsingDefaultCfg
= TRUE
;
494 /* try to load default config */
495 pic
= psdGetClsCfg(libname
);
498 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
501 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
503 ncp
->ncp_UsingDefaultCfg
= FALSE
;
512 /* /// "nLoadBindingConfig()" */
513 BOOL
nLoadBindingConfig(struct NepClassEth
*ncp
)
515 struct NepEthBase
*nh
= ncp
->ncp_ClsBase
;
517 struct ClsDevCfg
*cdc
;
518 struct PsdIFFContext
*pic
;
520 KPRINTF(10, ("Loading Binding Config...\n"));
525 //nLoadClassConfig(nh);
526 *ncp
->ncp_CDC
= *nh
->nh_DummyNCP
.ncp_CDC
;
527 ncp
->ncp_UsingDefaultCfg
= TRUE
;
529 if(!(ps
= OpenLibrary("poseidon.library", 4)))
536 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
539 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
542 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
544 ncp
->ncp_UsingDefaultCfg
= FALSE
;
553 /* /// "nOpenBindingCfgWindow()" */
554 LONG
nOpenBindingCfgWindow(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
557 KPRINTF(10, ("Opening GUI...\n"));
558 if(!(ps
= OpenLibrary("poseidon.library", 4)))
563 if(!ncp
->ncp_GUITask
)
565 if((ncp
->ncp_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", nGUITask
, ncp
)))
578 /**************************************************************************/
581 #define ps ncp->ncp_Base
583 static char *MediaTypeStrings
[] = { "Auto negotiation", "10Base-T Half Duplex", "10Base-T Full Duplex", "100Base-TX Half Duplex", "100Base-TX Full Duplex", NULL
};
585 /* /// "nEthTask()" */
586 AROS_UFH0(void, nEthTask
)
590 struct NepClassEth
*ncp
;
604 struct IOSana2Req
*ioreq
;
606 if((ncp
= nAllocEth()))
609 if(ncp
->ncp_ReadySigTask
)
611 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
615 /*if(nReadEEPROMMAC(ncp, ncp->ncp_ROMAddress))
617 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
619 // don't overwrite previously configured MAC Address
620 CopyMem(ncp->ncp_ROMAddress, ncp->ncp_MacAddress, ETHER_ADDR_SIZE);
622 nWriteDMRegs(ncp, ncp->ncp_MacAddress, ETHER_ADDR_SIZE, DMREG_ETH_ID);
624 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
625 "Couldn't read EEPROM for MAC Address, using preset one.");*/
626 nReadDMRegs(ncp
, ncp
->ncp_ROMAddress
, ETHER_ADDR_SIZE
, DMREG_ETH_ID
);
627 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
629 // don't overwrite previously configured MAC Address
630 CopyMem(ncp
->ncp_ROMAddress
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
);
632 nWriteDMRegs(ncp
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
, DMREG_ETH_ID
);
635 KPRINTF(10, ("MAC Address in EEPROM %02lx:%02lx:%02lx:%02lx:%02lx:%02lx\n",
636 ncp
->ncp_MacAddress
[0],
637 ncp
->ncp_MacAddress
[1],
638 ncp
->ncp_MacAddress
[2],
639 ncp
->ncp_MacAddress
[3],
640 ncp
->ncp_MacAddress
[4],
641 ncp
->ncp_MacAddress
[5]));
643 //if((!(ncp->ncp_StateFlags & DDF_OFFLINE)))// && (ncp->ncp_StateFlags & DDF_CONFIGURED))
645 /* Record start time_of_day */
646 //GetSysTime(&ncp->ncp_DeviceStats.LastStart);
651 sigmask
= (1L<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
)|(1L<<ncp
->ncp_TaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
653 clearandretry
= TRUE
;
657 // start transmitting read request if online...
658 if((ncp
->ncp_StateFlags
& DDF_ONLINE
) && (ncp
->ncp_ReadPending
== NULL
))
660 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
661 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, ETHER_MAX_LEN
);
662 ncp
->ncp_ReadBufNum
^= 1;
664 while((pp
= (struct PsdPipe
*) GetMsg(ncp
->ncp_TaskMsgPort
)))
666 KPRINTF(1, ("Pipe back %08lx\n", pp
));
667 for(cnt
= 0; cnt
< 2; cnt
++)
669 if(pp
== ncp
->ncp_EPOutPipe
[cnt
])
671 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
673 ioerr
= psdGetPipeError(pp
);
675 if((ioerr
== UHIOERR_STALL
) && clearandretry
)
677 clearandretry
= FALSE
;
678 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
679 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncp
->ncp_EPOutNum
);
680 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
683 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
684 "Clearing OUT-endpoint stall failed: %s (%ld)",
685 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
686 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
687 ioreq
->ios2_DataLength
= 0;
688 ioreq
->ios2_Req
.io_Error
= S2ERR_TX_FAILURE
;
689 ioreq
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
693 ncp
->ncp_WritePending
[cnt
] = NULL
;
696 UBYTE
*buf
= ncp
->ncp_WriteBuffer
[cnt
];
697 psdSendPipe(ncp
->ncp_EPOutPipe
[cnt
], buf
, (ULONG
) (buf
[0]|(buf
[1]<<8)));
698 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
, "Retrying...");
704 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
705 "Eth transmit failed: %s (%ld)",
706 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
708 /* Trigger any tx or generic error events */
709 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
711 /* Set error code and terminate the iorequest.
712 NOTE: Can't use RC_* or deverror() this is not
713 called from devBeginIO()!
715 ioreq
->ios2_DataLength
= 0;
716 ioreq
->ios2_Req
.io_Error
= S2ERR_TX_FAILURE
;
717 ioreq
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
721 clearandretry
= TRUE
;
724 ReplyMsg((struct Message
*) ioreq
);
725 ncp
->ncp_WritePending
[cnt
] = NULL
;
731 if(pp
== ncp
->ncp_EPInPipe
)
733 if((pktptr
= ncp
->ncp_ReadPending
))
735 ioerr
= psdGetPipeError(pp
);
736 pktlen
= psdGetPipeActual(pp
);
737 KPRINTF(1, ("ReadBack with %ld bytes.\n", pktlen
));
738 // interleave next packet reading ASAP.
739 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
741 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
742 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, ETHER_MAX_LEN
);
743 ncp
->ncp_ReadBufNum
^= 1;
745 ncp
->ncp_ReadPending
= NULL
;
749 if(lastioerr
!= ioerr
)
751 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
752 "Eth receive failed: %s (%ld)",
753 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
759 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
,
760 "That's it, that device pissed me off long enough!");
761 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
769 KPRINTF(20, ("%ld\n", pktlen
));
770 KPRINTF(1, ("Pkt %ld received\n", pktlen
));
771 //DB(dumpmem(pktptr, pktlen));
772 nReadPacket(ncp
, pktptr
, pktlen
);
778 while((ioreq
= (struct IOSana2Req
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
780 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
781 ioreq
, ioreq
->ios2_Req
.io_Command
, ioreq
->ios2_DataLength
));
782 switch(ioreq
->ios2_Req
.io_Command
)
784 case S2_CONFIGINTERFACE
:
785 nWriteDMRegs(ncp
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
, DMREG_ETH_ID
);
787 ncp
->ncp_StateFlags
|= DDF_CONFIGURED
;
788 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
792 ReplyMsg((struct Message
*) ioreq
);
795 case S2_ADDMULTICASTADDRESS
:
796 case S2_DELMULTICASTADDRESS
:
797 case S2_ADDMULTICASTADDRESSES
:
798 case S2_DELMULTICASTADDRESSES
:
800 ULONG rxcr
= RX_ENABLE
|RX_ALL_MULTICAST
|RX_DISCARD_LONG
|RX_DISCARD_CRC
;
801 if(ncp
->ncp_OpenFlags
& SANA2OPF_PROM
)
803 rxcr
|= RX_PROMISCUOUS
;
805 if(ncp
->ncp_Multicasts
.lh_Head
->ln_Succ
)
807 rxcr
&= ~RX_ALL_MULTICAST
;
808 nWriteDMRegs(ncp
, ncp
->ncp_MulticastArray
, 8, DMREG_MCAST_ADDR
);
810 nWriteDMReg(ncp
, DMREG_RX_CTRL
, rxcr
);
812 ReplyMsg((struct Message
*) ioreq
);
818 ReplyMsg((struct Message
*) ioreq
);
822 ioerr
= nWriteDMReg(ncp
, DMREG_RX_CTRL
, 0x00);
824 nWritePhyWord(ncp
, MII_BMCR
, BMCR_PDOWN
);
825 ReplyMsg((struct Message
*) ioreq
);
829 ioreq
->ios2_Req
.io_Error
= IOERR_NOCMD
;
830 ReplyMsg((struct Message
*) ioreq
);
835 while((!ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
]) && ncp
->ncp_WriteQueue
.lh_Head
->ln_Succ
)
837 ioreq
= (struct IOSana2Req
*) RemHead(&ncp
->ncp_WriteQueue
);
839 nWritePacket(ncp
, ioreq
);
843 sigs
= Wait(sigmask
);
844 } while(!(sigs
& SIGBREAKF_CTRL_C
));
847 /* Now remove all requests still pending *anywhere* */
848 //ncp->ncp_DenyRequests = TRUE;
849 /* Current transfers */
850 for(cnt
= 0; cnt
< 2; cnt
++)
852 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
854 KPRINTF(1, ("Aborting pending write...\n"));
855 psdAbortPipe(ncp
->ncp_EPOutPipe
[cnt
]);
856 psdWaitPipe(ncp
->ncp_EPOutPipe
[cnt
]);
857 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
858 ReplyMsg((struct Message
*) ioreq
);
859 ncp
->ncp_WritePending
[cnt
] = NULL
;
862 if(ncp
->ncp_ReadPending
)
864 KPRINTF(1, ("Aborting pending read...\n"));
865 psdAbortPipe(ncp
->ncp_EPInPipe
);
866 psdWaitPipe(ncp
->ncp_EPInPipe
);
867 ncp
->ncp_ReadPending
= NULL
;
870 /*while(ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort))
872 KPRINTF(1, ("Aborting pending requests...\n"));
873 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
874 ReplyMsg((struct Message *) ioreq);
878 nDoEvent(ncp
, S2EVENT_OFFLINE
);
880 KPRINTF(20, ("Going down the river!\n"));
888 /* /// "nAllocEth()" */
889 struct NepClassEth
* nAllocEth(void)
891 struct Task
*thistask
;
892 struct NepClassEth
*ncp
;
894 thistask
= FindTask(NULL
);
897 ncp
= thistask
->tc_UserData
;
898 if(!(ncp
->ncp_Base
= OpenLibrary("poseidon.library", 4)))
904 ncp
->ncp_Interface
= psdFindInterface(ncp
->ncp_Device
, NULL
,
907 if(!ncp
->ncp_Interface
)
909 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "No interface?");
913 ncp
->ncp_EPIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
915 EA_TransferType
, USEAF_BULK
,
917 ncp
->ncp_EPOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
919 EA_TransferType
, USEAF_BULK
,
921 if(!(ncp
->ncp_EPIn
&& ncp
->ncp_EPOut
))
923 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
927 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPOut
,
928 EA_MaxPktSize
, &ncp
->ncp_EPOutMaxPktSize
,
929 EA_EndpointNum
, &ncp
->ncp_EPOutNum
,
932 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPIn
,
933 EA_EndpointNum
, &ncp
->ncp_EPInNum
,
936 ncp
->ncp_ReadPending
= NULL
;
937 ncp
->ncp_WritePending
[0] = NULL
;
938 ncp
->ncp_WritePending
[1] = NULL
;
939 if(!(ncp
->ncp_ReadBuffer
[0] = AllocVec(ETHER_MAX_LEN
* 4, MEMF_PUBLIC
|MEMF_CLEAR
)))
941 KPRINTF(1, ("Out of memory for read buffer\n"));
944 ncp
->ncp_ReadBuffer
[1] = ncp
->ncp_ReadBuffer
[0] + ETHER_MAX_LEN
;
945 ncp
->ncp_WriteBuffer
[0] = ncp
->ncp_ReadBuffer
[1] + ETHER_MAX_LEN
;
946 ncp
->ncp_WriteBuffer
[1] = ncp
->ncp_WriteBuffer
[0] + ETHER_MAX_LEN
;
947 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
948 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
949 ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
950 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
952 if((ncp
->ncp_TaskMsgPort
= CreateMsgPort()))
954 if((ncp
->ncp_EP0Pipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, NULL
)))
956 if((ncp
->ncp_EPOutPipe
[0] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
958 /* Turn off short packets */
959 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[0],
960 PPA_NoShortPackets
, FALSE
,
961 PPA_NakTimeout
, TRUE
,
962 PPA_NakTimeoutTime
, 5000,
964 if((ncp
->ncp_EPOutPipe
[1] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
966 /* Turn off short packets */
967 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[1],
968 PPA_NoShortPackets
, FALSE
,
969 PPA_NakTimeout
, TRUE
,
970 PPA_NakTimeoutTime
, 5000,
972 if((ncp
->ncp_EPInPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPIn
)))
974 /* Turn off short packets */
975 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPInPipe
,
976 PPA_NakTimeout
, FALSE
,
977 PPA_NakTimeoutTime
, 5000,
978 PPA_AllowRuntPackets
, TRUE
,
980 ncp
->ncp_Task
= thistask
;
982 if(nInitDavicom(ncp
))
986 psdFreePipe(ncp
->ncp_EPInPipe
);
988 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
990 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
992 psdFreePipe(ncp
->ncp_EP0Pipe
);
994 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
996 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
998 if(ncp
->ncp_ReadBuffer
[0])
1000 FreeVec(ncp
->ncp_ReadBuffer
[0]);
1001 ncp
->ncp_ReadBuffer
[0] = NULL
;
1003 CloseLibrary(ncp
->ncp_Base
);
1005 ncp
->ncp_Task
= NULL
;
1006 if(ncp
->ncp_ReadySigTask
)
1008 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
1014 /* /// "nFreeEth()" */
1015 void nFreeEth(struct NepClassEth
*ncp
)
1017 struct IOSana2Req
*ioreq
;
1019 /* Disable the message port, messages may still be queued */
1020 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
1021 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
1022 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
1023 // get rid of all messages that still have appeared here
1024 while((ioreq
= (struct IOSana2Req
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
1026 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
1027 ReplyMsg((struct Message
*) ioreq
);
1031 psdFreePipe(ncp
->ncp_EPInPipe
);
1032 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
1033 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
1034 psdFreePipe(ncp
->ncp_EP0Pipe
);
1036 if(ncp
->ncp_ReadBuffer
[0])
1038 FreeVec(ncp
->ncp_ReadBuffer
[0]);
1039 ncp
->ncp_ReadBuffer
[0] = NULL
;
1042 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
1043 CloseLibrary(ncp
->ncp_Base
);
1045 ncp
->ncp_Task
= NULL
;
1046 if(ncp
->ncp_ReadySigTask
)
1048 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
1053 /* /// "nReadDMReg()" */
1054 LONG
nReadDMReg(struct NepClassEth
*ncp
, ULONG reg
)
1059 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UDMR_GET_REGS
, 0, reg
);
1060 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, &result
, 1);
1063 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1064 "Reading DM Reg %ld failed: %s (%ld)",
1066 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1069 KPRINTF(1, ("DM Reg(%ld)=%02lx (%ld)\n", reg
, result
, result
));
1074 /* /// "nReadDMRegs()" */
1075 LONG
nReadDMRegs(struct NepClassEth
*ncp
, UBYTE
*data
, ULONG len
, ULONG offset
)
1079 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UDMR_GET_REGS
, 0, offset
);
1080 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, data
, len
);
1083 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1084 "Reading DM Regs %ld-%ld failed: %s (%ld)",
1085 offset
, offset
+len
-1,
1086 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1092 /* /// "nWriteDMReg()" */
1093 LONG
nWriteDMReg(struct NepClassEth
*ncp
, ULONG reg
, ULONG value
)
1097 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UDMR_SET_REG
, value
, reg
);
1098 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1101 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1102 "Writing DM Reg %ld with 0x%02lx failed: %s (%ld)",
1104 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1110 /* /// "nWriteDMRegs()" */
1111 LONG
nWriteDMRegs(struct NepClassEth
*ncp
, UBYTE
*data
, ULONG len
, ULONG offset
)
1115 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UDMR_SET_REGS
, 0, offset
);
1116 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, data
, len
);
1119 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1120 "Writing DM Regs %ld-%ld failed: %s (%ld)",
1121 offset
, offset
+len
-1,
1122 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1128 /* /// "nReadPhyWord()" */
1129 LONG
nReadPhyWord(struct NepClassEth
*ncp
, ULONG phyreg
)
1136 ioerr
= nWriteDMReg(ncp
, DMREG_PHY_ADDR
, phyreg
|0x40);
1141 ioerr
= nWriteDMReg(ncp
, DMREG_PHY_CTRL
, PHY_READ
|PHY_PHYSEL
);
1151 data
= nReadDMReg(ncp
, DMREG_PHY_CTRL
);
1156 if(!(data
& PHY_BUSY
))
1162 ioerr
= nWriteDMReg(ncp
, DMREG_PHY_CTRL
, 0x00);
1169 KPRINTF(20, ("Timeout waiting for PHY to respond (read reg %ld)!\n", phyreg
));
1172 ioerr
= nReadDMRegs(ncp
, phyword
, 2, DMREG_PHY_DATA_LOW
);
1177 return(phyword
[0]|(phyword
[1]<<8));
1181 /* /// "nWritePhyWord()" */
1182 BOOL
nWritePhyWord(struct NepClassEth
*ncp
, ULONG phyreg
, ULONG value
)
1192 ioerr
= nWriteDMRegs(ncp
, val
, 2, DMREG_PHY_DATA_LOW
);
1197 ioerr
= nWriteDMReg(ncp
, DMREG_PHY_ADDR
, phyreg
|0x40);
1203 ioerr
= nWriteDMReg(ncp
, DMREG_PHY_CTRL
, PHY_PHYSEL
|PHY_WRITE
);
1212 data
= nReadDMReg(ncp
, DMREG_PHY_CTRL
);
1217 if(!(data
& PHY_BUSY
))
1223 ioerr
= nWriteDMReg(ncp
, DMREG_PHY_CTRL
, 0x00);
1230 KPRINTF(20, ("Timeout waiting for PHY to respond (write reg %ld=%04lx)!\n", phyreg
, value
));
1237 /* /// "nInitDavicom()" */
1238 BOOL
nInitDavicom(struct NepClassEth
*ncp
)
1243 ioerr
= nWriteDMReg(ncp
, DMREG_NET_CTRL
, 0x01);
1250 ioerr
= nWriteDMReg(ncp
, DMREG_GPR_CTRL
, 0x01);
1255 ioerr
= nWriteDMReg(ncp
, DMREG_GPR_DATA
, 0x00);
1261 data
= nReadPhyWord(ncp
, MII_BMSR
);
1262 KPRINTF(10, ("Phy %04lx\n", data
));
1263 if((data
> 0) && (data
!= 0xffff) && (data
& BMSR_MEDIA
))
1267 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
, "Couldn't identify PHY!");
1272 /* /// "nSetOnline()" */
1273 void nSetOnline(struct NepClassEth
*ncp
)
1277 BOOL autoneg
= FALSE
;
1278 BOOL linkgood
= FALSE
;
1282 switch(ncp
->ncp_CDC
->cdc_MediaType
)
1285 KPRINTF(10, ("Autonegotiation!\n"));
1286 bmcr
= BMCR_ANENABLE
|BMCR_ANRESTART
;
1290 case MT_10BASE_T_HALF_DUP
:
1294 case MT_10BASE_T_FULL_DUP
:
1295 bmcr
= BMCR_FULLDPLX
;
1298 case MT_100BASE_TX_HALF_DUP
:
1299 bmcr
= BMCR_SPEED100
;
1302 case MT_100BASE_TX_FULL_DUP
:
1304 bmcr
= BMCR_SPEED100
|BMCR_FULLDPLX
;
1308 nWritePhyWord(ncp
, MII_BMCR
, bmcr
);
1312 data
= nReadPhyWord(ncp
, MII_BMSR
);
1313 KPRINTF(10, ("Status: %04lx\n", data
));
1320 linkgood
= (data
& BMSR_LSTATUS
);
1321 if((!autoneg
) && linkgood
)
1323 // no need to wait for autonegotiation
1328 if(data
& BMSR_ANEGCOMPLETE
)
1336 STRPTR negstr
= NULL
;
1339 KPRINTF(10, ("Auto neg successful!\n"));
1340 data
= nReadPhyWord(ncp
, MII_LPA
);
1341 KPRINTF(10, ("Auto neg state %04lx\n", data
));
1346 if(data
& ADVERTISE_100FULL
)
1348 // 100Base-TX Full Duplex
1349 negstr
= MediaTypeStrings
[MT_100BASE_TX_FULL_DUP
];
1351 else if(data
& ADVERTISE_100HALF
)
1353 // 100Base-TX Half Duplex
1354 negstr
= MediaTypeStrings
[MT_100BASE_TX_HALF_DUP
];
1356 else if(data
& ADVERTISE_10FULL
)
1358 // 10Base-T Full Duplex
1359 negstr
= MediaTypeStrings
[MT_10BASE_T_FULL_DUP
];
1361 else if(data
& ADVERTISE_10HALF
)
1363 // 10Base-T Half Duplex
1364 negstr
= MediaTypeStrings
[MT_10BASE_T_HALF_DUP
];
1371 negstr
= MediaTypeStrings
[MT_100BASE_TX_FULL_DUP
];
1372 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
, "Autonegotiation failed! Using %s instead.", negstr
);
1373 nWritePhyWord(ncp
, MII_BMCR
, BMCR_SPEED100
|BMCR_FULLDPLX
);
1375 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
, "Autonegotiation: Using %s.", negstr
);
1380 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
, "No link, check the plug and cable.");
1383 rxcr
= RX_ENABLE
|RX_ALL_MULTICAST
|RX_DISCARD_LONG
|RX_DISCARD_CRC
;
1384 nWriteDMRegs(ncp
, ncp
->ncp_MulticastArray
, 8, DMREG_MCAST_ADDR
);
1385 if(ncp
->ncp_OpenFlags
& SANA2OPF_PROM
)
1387 rxcr
|= RX_PROMISCUOUS
;
1389 if(ncp
->ncp_Multicasts
.lh_Head
->ln_Succ
)
1391 rxcr
&= ~RX_ALL_MULTICAST
;
1392 nWriteDMRegs(ncp
, ncp
->ncp_MulticastArray
, 8, DMREG_MCAST_ADDR
);
1394 nWriteDMReg(ncp
, DMREG_RX_CTRL
, rxcr
);
1396 data
= nReadPhyWord(ncp
, MII_TPISTATUS
);
1397 nWritePhyWord(ncp
, MII_TPISTATUS
, data
|4);
1400 ncp
->ncp_StateFlags
|= DDF_ONLINE
;
1401 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
1402 /* Trigger any ONLINE events */
1403 nDoEvent(ncp
, S2EVENT_ONLINE
);
1407 /* /// "nDoEvent()" */
1408 void nDoEvent(struct NepClassEth
*ncp
, ULONG events
)
1410 struct IOSana2Req
*worknode
, *nextnode
;
1412 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events
));
1415 /* Process pending S2_ONEVENT requests */
1416 worknode
= (struct IOSana2Req
*) ncp
->ncp_EventList
.lh_Head
;
1417 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1419 if(worknode
->ios2_WireError
& events
)
1421 Remove(&worknode
->ios2_Req
.io_Message
.mn_Node
);
1422 worknode
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
1423 KPRINTF(1, ("DoEvent: returned eventreq 0x%08lx\n", worknode
));
1424 ReplyMsg(&worknode
->ios2_Req
.io_Message
);
1426 worknode
= nextnode
;
1432 /* /// "support routines" */
1434 inline void *callcopy(void *routine
,
1439 void * (*call
) (APTR
, APTR
, ULONG
) = routine
;
1441 return (*call
) (from
, to
, len
);
1444 #define callfilter CallHookPkt
1447 /* /// "nWritePacket()" */
1448 BOOL
nWritePacket(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1451 struct EtherPacketHeader
*eph
;
1454 struct BufMan
*bufman
;
1455 struct Sana2PacketTypeStats
*stats
;
1456 UBYTE
*buf
= ncp
->ncp_WriteBuffer
[ncp
->ncp_WriteBufNum
];
1458 packettype
= ioreq
->ios2_PacketType
;
1459 // the first two bytes are the length
1460 eph
= (struct EtherPacketHeader
*) &buf
[2];
1462 writelen
= ioreq
->ios2_DataLength
;
1463 bufman
= ioreq
->ios2_BufferManagement
;
1465 /* Not a raw packet? */
1466 if(!(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
))
1469 KPRINTF(10, ("RAW WRITE!\n"));
1470 /* The ethernet header isn't included in the data */
1471 /* Build ethernet packet header */
1472 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
1474 eph
->eph_Dest
[cnt
] = ioreq
->ios2_DstAddr
[cnt
];
1475 eph
->eph_Src
[cnt
] = ncp
->ncp_MacAddress
[cnt
];
1477 eph
->eph_Type
= AROS_WORD2BE(packettype
);
1479 /* Packet data is at txbuffer */
1480 copydest
+= sizeof(struct EtherPacketHeader
);
1481 writelen
+= sizeof(struct EtherPacketHeader
);
1484 //memset(buf + 2, 0x55, writelen);
1486 /* Dma not available, fallback to regular copy */
1487 if(callcopy(bufman
->bm_CopyFromBuf
, copydest
, ioreq
->ios2_Data
, ioreq
->ios2_DataLength
) == NULL
)
1489 KPRINTF(10, ("writepacket: copyfrom returned failure!\n"));
1491 /* Trigger any tx, buff or generic error events */
1492 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
|S2EVENT_BUFF
);
1494 /* Set error code and terminate the iorequest.
1495 NOTE: Can't use RC_* or deverror() this is not
1496 called from devBeginIO()! */
1497 ioreq
->ios2_DataLength
= 0;
1498 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1499 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1503 if(!((writelen
+2) & (ncp
->ncp_EPOutMaxPktSize
-1)))
1505 // adjust size to send one extra byte as zero packet termination doesn't seem to work with this adapter
1506 buf
[writelen
+2] = 0;
1507 KPRINTF(10, ("Zero Packet adjustment\n"));
1512 buf
[1] = writelen
>>8;
1515 KPRINTF(10, ("PktOut[%ld] %ld\n", ncp
->ncp_WriteBufNum
, writelen
));
1516 // unfortunately, it looks like the adapter does not correctly accept
1517 // zero length packets as end of transfer, so make the last packet a
1518 // one byte length one.
1519 if(!(writelen
& (ncp
->ncp_EPOutMaxPktSize
-1)))
1523 ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
] = ioreq
;
1524 psdSendPipe(ncp
->ncp_EPOutPipe
[ncp
->ncp_WriteBufNum
], buf
, (ULONG
) writelen
);
1525 ncp
->ncp_WriteBufNum
^= 1;
1528 if(AROS_BE2WORD(eph
->eph_Type
) < ETHERPKT_SIZE
)
1530 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx (IEEE802.3) len %lu, %lu bytes\n",
1531 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
1532 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
1533 AROS_BE2WORD(eph
->eph_Type
), writelen
));
1535 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx type %lu, %lu bytes\n",
1536 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
1537 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
1538 AROS_BE2WORD(eph
->eph_Type
), writelen
));
1540 //dumpmem(buf, (ULONG) writelen);
1543 /* Update statistics */
1544 stats
= FindPacketTypeStats(ncp
, packettype
);
1547 stats
->PacketsSent
++;
1548 stats
->BytesSent
+= writelen
;
1550 ncp
->ncp_DeviceStats
.PacketsSent
++;
1556 /* /// "nReadIOReq()" */
1557 UWORD
nReadIOReq(struct NepClassEth
*ncp
, struct EtherPacketHeader
*eph
, UWORD datasize
, struct IOSana2Req
*ioreq
, UWORD flags
)
1559 LIBBASETYPEPTR nh
= ncp
->ncp_ClsBase
;
1563 /* Handle RAW read */
1564 if(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
)
1566 /* ShapeShifter won't work with `sizeof(struct etherpacket_hdr)'
1567 here. This is most likely because it wants the RAW ethernet
1568 packet checksum size (4) added to the packet size. */
1569 copyfrom
= (UBYTE
*) eph
;
1570 datasize
+= sizeof(struct EtherPacketHeader
) + 4;
1572 copyfrom
= (UBYTE
*) (eph
+ 1);
1575 /* Build up the ios2 structure enough so we can call the packet filter. */
1576 ioreq
->ios2_PacketType
= AROS_BE2WORD(eph
->eph_Type
);
1577 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
1579 ioreq
->ios2_SrcAddr
[cnt
] = eph
->eph_Src
[cnt
];
1580 ioreq
->ios2_DstAddr
[cnt
] = eph
->eph_Dest
[cnt
];
1582 ioreq
->ios2_DataLength
= datasize
;
1583 /* Call the packet filter, if available. */
1584 if((flags
& PACKETFILTER
) &&
1585 (((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
) &&
1586 (!callfilter(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
,
1589 /* This packet got dropped! */
1590 KPRINTF(7, ("readioreq: packet type %lu for ioreq 0x%08lx dropped\n",
1591 AROS_BE2WORD(eph
->eph_Type
), ioreq
));
1596 /* Ok, the packet didn't get dropped, set the BCAST and MCAST
1597 flags according to dstaddr. */
1599 /* Address == Multicast? */
1600 if(ioreq
->ios2_DstAddr
[0] & 1)
1602 /* Address == Broadcast? */
1603 const UBYTE bcast
[ETHER_ADDR_SIZE
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1604 if(memcmp(bcast
, ioreq
->ios2_DstAddr
, ETHER_ADDR_SIZE
) == 0)
1606 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1608 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1612 /* Finally copy the packet data! */
1613 if(callcopy(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_CopyToBuf
,
1614 ioreq
->ios2_Data
, copyfrom
, ioreq
->ios2_DataLength
))
1617 KPRINTF(5, ("readioreq: copytobuffed packet ior 0x%08lx, %04lx%08lx < %04lx%08lx, type %lu, %lu bytes, %s%s%s\n",
1619 *((UWORD
*) ioreq
->ios2_DstAddr
), *((ULONG
*) (ioreq
->ios2_DstAddr
+ 2)),
1620 *((UWORD
*) ioreq
->ios2_SrcAddr
), *((ULONG
*) (ioreq
->ios2_SrcAddr
+ 2)),
1621 ioreq
->ios2_PacketType
, ioreq
->ios2_DataLength
,
1622 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) ? "RAW " : "",
1623 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_BCAST
) ? "BCAST " : "",
1624 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_MCAST
) ? "MCAST " : ""));
1625 //dumpmem(copyfrom, ioreq->ios2_DataLength);
1628 /* Clear the dropped flag */
1631 KPRINTF(10, ("readioreq: copyto returned failure!\n"));
1633 /* Trigger any rx, buff or generic error events */
1634 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
|S2EVENT_BUFF
);
1637 NOTE: Can't use RC_* or deverror() this is not called from devBeginIO()!
1639 ioreq
->ios2_DataLength
= 0;
1640 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1641 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1644 /* Pull the ioreq off the list & terminate it */
1646 Remove((struct Node
*) ioreq
);
1648 ReplyMsg((struct Message
*) ioreq
);
1653 /* /// "nReadPacket()" */
1654 BOOL
nReadPacket(struct NepClassEth
*ncp
, UBYTE
*pktptr
, ULONG len
)
1656 struct EtherPacketHeader
*eph
;
1657 struct BufMan
*bufman
;
1658 struct IOSana2Req
*worknode
, *nextnode
;
1659 struct Sana2PacketTypeStats
*stats
;
1665 KPRINTF(10, ("PktIn [%ld] %ld\n", ncp
->ncp_ReadBufNum
, len
));
1669 ncp
->ncp_DeviceStats
.BadData
++;
1674 pktlen
+= (*pktptr
++)<<8;
1677 KPRINTF(20, ("Error %02lx\n", status
));
1680 ncp
->ncp_DeviceStats
.Overruns
++;
1682 ncp
->ncp_DeviceStats
.BadData
++;
1686 if(len
!= pktlen
+ 3)
1688 KPRINTF(20, ("Pktlen %ld != len %ld\n", pktlen
+ 3, len
));
1692 ncp
->ncp_DeviceStats
.PacketsReceived
++;
1694 eph
= (struct EtherPacketHeader
*) pktptr
;
1695 stats
= FindPacketTypeStats(ncp
, (ULONG
) AROS_BE2WORD(eph
->eph_Type
));
1696 flags
= DROPPED
|PACKETFILTER
;
1698 /* Calculate size of the actual data */
1699 datasize
= pktlen
- sizeof(struct EtherPacketHeader
);
1701 /* Is the packet datasize valid? */
1702 if((pktlen
>= ETHER_MIN_LEN
) && (pktlen
<= ETHER_MAX_LEN
))
1704 /* Update the packet statistics */
1707 stats
->PacketsReceived
++;
1708 stats
->BytesReceived
+= datasize
; /* NOTE: don't include headers */
1711 /* For each device user (bufman)
1712 NOTE: We absolutely *MUST* try to offer the packet to *all*
1713 different device users (SANA-II V2 spec requirement). */
1715 bufman
= (struct BufMan
*) ncp
->ncp_BufManList
.lh_Head
;
1716 while(((struct Node
*) bufman
)->ln_Succ
)
1718 /* For each queued read request (ioreq) */
1719 worknode
= (struct IOSana2Req
*) bufman
->bm_RXQueue
.lh_Head
;
1720 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1722 /* Check the packet type. Also handles 802.3 packets. */
1723 if((worknode
->ios2_PacketType
== AROS_BE2WORD(eph
->eph_Type
)) ||
1724 ((AROS_BE2WORD(eph
->eph_Type
) < ETHERPKT_SIZE
) && (worknode
->ios2_PacketType
< ETHERPKT_SIZE
)))
1726 flags
= nReadIOReq(ncp
, eph
, datasize
, worknode
, flags
);
1727 /* Break out - let other callers get the packet too */
1730 worknode
= nextnode
;
1732 bufman
= (struct BufMan
*) (((struct Node
*) bufman
)->ln_Succ
);
1735 /* Now we've tried to give the packet to every CMD_READ caller.
1736 If DROPPED is set at this point no-one wanted this packet. */
1739 /* So there were no outstanding CMD_READs or the packet wasn't
1740 accepted by any of them. Okay, check if we have any pending
1741 S2_READORPHAN ioreq in list and if we have return this packet
1742 with it. Note that packet filter must not be used for this
1745 NOTE: orphanlist is global, ie. only one caller will get the
1746 packet if multiple users have pending S2_READORPHANs.
1749 /* Process pending orphanread iorequs */
1751 worknode
= (struct IOSana2Req
*) ncp
->ncp_OrphanQueue
.lh_Head
;
1752 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1754 nReadIOReq(ncp
, eph
, datasize
, worknode
, 0);
1755 worknode
= nextnode
;
1759 /* Packet not dropped - return ok */
1763 KPRINTF(20, ("Pktlen %ld invalid!\n", pktlen
));
1764 ncp
->ncp_DeviceStats
.BadData
++;
1766 /* Update global dropped packet counter. */
1767 ncp
->ncp_DeviceStats
.UnknownTypesReceived
++;
1769 /* Update dropped packet statistics. */
1772 stats
->PacketsDropped
++;
1774 KPRINTF(9, ("readpacket: packet type %lu dropped\n", AROS_BE2WORD(eph
->eph_Type
)));
1776 /* Trigger any rx or generic error events */
1777 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
);
1782 /**************************************************************************/
1784 /* /// "nGUITask()" */
1785 AROS_UFH0(void, nGUITask
)
1789 struct Task
*thistask
;
1790 struct NepEthBase
*nh
;
1791 struct NepClassEth
*ncp
;
1792 struct PsdIFFContext
*pic
;
1794 thistask
= FindTask(NULL
);
1796 #define ps ncp->ncp_PsdBase
1797 #undef IntuitionBase
1798 #define IntuitionBase ncp->ncp_IntBase
1799 #undef MUIMasterBase
1800 #define MUIMasterBase ncp->ncp_MUIBase
1802 ncp
= thistask
->tc_UserData
;
1803 nh
= ncp
->ncp_ClsBase
;
1805 ++nh
->nh_Library
.lib_OpenCnt
;
1806 if(!(MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MUIMASTER_VMIN
)))
1808 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
1809 nGUITaskCleanup(ncp
);
1813 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
1815 KPRINTF(10, ("Couldn't open intuition.library.\n"));
1816 nGUITaskCleanup(ncp
);
1819 if(!(ps
= OpenLibrary("poseidon.library", 4)))
1821 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
1822 nGUITaskCleanup(ncp
);
1826 ncp
->ncp_App
= ApplicationObject
,
1827 MUIA_Application_Title
, (IPTR
)libname
,
1828 MUIA_Application_Version
, (IPTR
)VERSION_STRING
,
1829 MUIA_Application_Copyright
, (IPTR
)"©2006-2009 Harry Sintonen & Chris Hodges",
1830 MUIA_Application_Author
, (IPTR
)"Harry Sintonen <sintonen@iki.fi> & Chris Hodges <chrisly@platon42.de>",
1831 MUIA_Application_Description
, (IPTR
)"Settings for the dm9601eth.class",
1832 MUIA_Application_Base
, (IPTR
)"DM9601ETH",
1833 MUIA_Application_HelpFile
, (IPTR
)"HELP:Poseidon.guide",
1834 MUIA_Application_Menustrip
, (IPTR
)MenustripObject
,
1835 Child
, (IPTR
)MenuObjectT((IPTR
)"Project"),
1836 Child
, (IPTR
)(ncp
->ncp_AboutMI
= MenuitemObject
,
1837 MUIA_Menuitem_Title
, (IPTR
)"About...",
1838 MUIA_Menuitem_Shortcut
, (IPTR
)"?",
1841 Child
, (IPTR
)MenuObjectT((IPTR
)"Settings"),
1842 Child
, (IPTR
)(ncp
->ncp_UseMI
= MenuitemObject
,
1843 MUIA_Menuitem_Title
, (IPTR
) "Save",
1844 MUIA_Menuitem_Shortcut
, (IPTR
) "S",
1846 Child
, (IPTR
)(ncp
->ncp_SetDefaultMI
= MenuitemObject
,
1847 MUIA_Menuitem_Title
, (IPTR
) "Set as Default",
1848 MUIA_Menuitem_Shortcut
, (IPTR
) "D",
1850 Child
, (IPTR
)MenuitemObject
,
1851 MUIA_Menuitem_Title
, (IPTR
)NM_BARLABEL
,
1853 Child
, (IPTR
)(ncp
->ncp_MUIPrefsMI
= MenuitemObject
,
1854 MUIA_Menuitem_Title
, (IPTR
) "MUI Settings",
1855 MUIA_Menuitem_Shortcut
, (IPTR
) "M",
1860 SubWindow
, (IPTR
)(ncp
->ncp_MainWindow
= WindowObject
,
1861 MUIA_Window_ID
, MAKE_ID('M','A','I','N'),
1862 MUIA_Window_Title
, (IPTR
)libname
,
1863 MUIA_HelpNode
, (IPTR
)libname
,
1865 WindowContents
, (IPTR
)VGroup
,
1866 Child
, (IPTR
)ColGroup(2), GroupFrameT((IPTR
)(ncp
->ncp_Interface
? "Device Settings" : "Default Device Settings")),
1868 Child
, (IPTR
)Label((IPTR
) "Media Type:"),
1869 Child
, (IPTR
)(ncp
->ncp_MediaTypeObj
= CycleObject
,
1871 MUIA_Cycle_Entries
, (IPTR
)MediaTypeStrings
,
1872 MUIA_Cycle_Active
, ncp
->ncp_CDC
->cdc_MediaType
,
1874 Child
, (IPTR
)Label((IPTR
) "Default " DEVNAME
" Unit:"),
1875 Child
, (IPTR
)(ncp
->ncp_UnitObj
= StringObject
,
1878 MUIA_String_AdvanceOnCR
, TRUE
,
1879 MUIA_String_Integer
, ncp
->ncp_CDC
->cdc_DefaultUnit
,
1880 MUIA_String_Accept
, (IPTR
)"0123456789",
1883 Child
, (IPTR
)VSpace(0),
1884 Child
, (IPTR
)HGroup
,
1885 MUIA_Group_SameWidth
, TRUE
,
1886 Child
, (IPTR
)(ncp
->ncp_UseObj
= TextObject
, ButtonFrame
,
1887 MUIA_ShowMe
, (IPTR
)ncp
->ncp_Interface
,
1888 MUIA_Background
, MUII_ButtonBack
,
1890 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1891 MUIA_Text_Contents
, (IPTR
)"\33c Save ",
1893 Child
, (IPTR
)(ncp
->ncp_SetDefaultObj
= TextObject
, ButtonFrame
,
1894 MUIA_Background
, MUII_ButtonBack
,
1896 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1897 MUIA_Text_Contents
, (IPTR
)(ncp
->ncp_Interface
? "\33c Save as Default " : "\33c Save Defaults "),
1899 Child
, (IPTR
)(ncp
->ncp_CloseObj
= TextObject
, ButtonFrame
,
1900 MUIA_Background
, MUII_ButtonBack
,
1902 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1903 MUIA_Text_Contents
, (IPTR
)("\33c Use "),
1912 KPRINTF(10, ("Couldn't create application\n"));
1913 nGUITaskCleanup(ncp
);
1917 DoMethod(ncp
->ncp_MainWindow
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
1918 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
1919 DoMethod(ncp
->ncp_UseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1920 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
1921 DoMethod(ncp
->ncp_SetDefaultObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1922 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
1923 DoMethod(ncp
->ncp_CloseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1924 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
1926 DoMethod(ncp
->ncp_AboutMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1927 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_ABOUT
);
1928 DoMethod(ncp
->ncp_UseMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1929 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
1930 DoMethod(ncp
->ncp_SetDefaultMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1931 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
1932 DoMethod(ncp
->ncp_MUIPrefsMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1933 ncp
->ncp_App
, 2, MUIM_Application_OpenConfigWindow
, 0);
1941 get(ncp
->ncp_App
, MUIA_Application_Iconified
, &iconify
);
1942 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, TRUE
);
1943 get(ncp
->ncp_MainWindow
, MUIA_Window_Open
, &isopen
);
1944 if(!(isopen
|| iconify
))
1946 nGUITaskCleanup(ncp
);
1952 retid
= DoMethod(ncp
->ncp_App
, MUIM_Application_NewInput
, &sigs
);
1956 case ID_STORE_CONFIG
:
1957 case MUIV_Application_ReturnID_Quit
:
1959 get(ncp
->ncp_UnitObj
, MUIA_String_Integer
, &ncp
->ncp_CDC
->cdc_DefaultUnit
);
1960 get(ncp
->ncp_MediaTypeObj
, MUIA_Cycle_Active
, &ncp
->ncp_CDC
->cdc_MediaType
);
1962 if(retid
== ID_DEF_CONFIG
)
1964 pic
= psdGetClsCfg(libname
);
1967 psdSetClsCfg(libname
, NULL
);
1968 pic
= psdGetClsCfg(libname
);
1972 psdAddCfgEntry(pic
, ncp
->ncp_CDC
);
1973 psdSaveCfgToDisk(NULL
, FALSE
);
1976 if(ncp
->ncp_Interface
)
1978 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
1981 psdSetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
, NULL
);
1982 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
1986 if(psdAddCfgEntry(pic
, ncp
->ncp_CDC
))
1988 if(retid
!= MUIV_Application_ReturnID_Quit
)
1990 psdSaveCfgToDisk(NULL
, FALSE
);
1992 retid
= MUIV_Application_ReturnID_Quit
;
1996 retid
= MUIV_Application_ReturnID_Quit
;
2002 MUI_RequestA(ncp
->ncp_App
, ncp
->ncp_MainWindow
, 0, NULL
, "Phat!", VERSION_STRING
, NULL
);
2005 if(retid
== MUIV_Application_ReturnID_Quit
)
2011 sigs
= Wait(sigs
|sigmask
|SIGBREAKF_CTRL_C
);
2012 if(sigs
& SIGBREAKF_CTRL_C
)
2018 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, FALSE
);
2020 nGUITaskCleanup(ncp
);
2026 /* /// "nGUITaskCleanup()" */
2027 void nGUITaskCleanup(struct NepClassEth
*ncp
)
2031 MUI_DisposeObject(ncp
->ncp_App
);
2032 ncp
->ncp_App
= NULL
;
2036 CloseLibrary(MUIMasterBase
);
2037 MUIMasterBase
= NULL
;
2041 CloseLibrary(IntuitionBase
);
2042 IntuitionBase
= NULL
;
2050 ncp
->ncp_GUIBinding
= NULL
;
2051 ncp
->ncp_GUITask
= NULL
;
2052 if(ncp
->ncp_ReadySigTask
)
2054 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
2056 --ncp
->ncp_ClsBase
->nh_Library
.lib_OpenCnt
;