2 *----------------------------------------------------------------------------
3 * moschipeth class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "moschipeth.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! moschipeth.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 * ***********************************************************************
124 /* /// "usbAttemptDeviceBinding()" */
125 struct NepClassEth
* usbAttemptDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
131 KPRINTF(1, ("nepEthAttemptDeviceBinding(%08lx)\n", pd
));
133 if((ps
= OpenLibrary("poseidon.library", 4)))
135 psdGetAttrs(PGA_DEVICE
, pd
,
136 DA_VendorID
, &vendid
,
137 DA_ProductID
, &prodid
,
140 if((vendid
== 0x9710) && (prodid
== 0x7830))
142 return(usbForceDeviceBinding(nh
, pd
));
149 /* /// "usbForceDeviceBinding()" */
150 struct NepClassEth
* usbForceDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
154 struct NepClassEth
*ncp
;
155 struct NepClassEth
*tmpncp
;
156 struct ClsDevCfg
*cdc
;
164 struct Task
*tmptask
;
166 KPRINTF(1, ("nepEthForceDeviceBinding(%08lx)\n", pd
));
168 if((ps
= OpenLibrary("poseidon.library", 4)))
170 psdGetAttrs(PGA_DEVICE
, pd
,
171 DA_ProductID
, &prodid
,
172 DA_VendorID
, &vendid
,
173 DA_ProductName
, &devname
,
174 DA_IDString
, &devidstr
,
180 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
181 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
183 if(!strcmp(ncp
->ncp_DevIDString
, devidstr
))
185 unitno
= ncp
->ncp_UnitNo
;
189 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
193 /* as units are freed in the expunge-vector, the memory is
194 outside the scope of the poseidon library */
195 if(!(ncp
= AllocVec(sizeof(struct NepClassEth
), MEMF_PUBLIC
|MEMF_CLEAR
)))
201 ncp
->ncp_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
209 /* IORequests may be queued even if the task is gone. */
210 ncp
->ncp_UnitNo
= (ULONG
) -1;
211 NewList(&ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
);
212 NewList(&ncp
->ncp_OrphanQueue
);
213 NewList(&ncp
->ncp_WriteQueue
);
214 NewList(&ncp
->ncp_BufManList
);
215 NewList(&ncp
->ncp_EventList
);
216 NewList(&ncp
->ncp_TrackList
);
217 NewList(&ncp
->ncp_Multicasts
);
218 strncpy(ncp
->ncp_DevIDString
, devidstr
, 127);
219 AddTail(&nh
->nh_Units
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
);
221 ncp
->ncp_ClsBase
= nh
;
222 ncp
->ncp_Device
= pd
;
223 ncp
->ncp_UnitProdID
= prodid
;
224 ncp
->ncp_UnitVendorID
= vendid
;
226 nLoadBindingConfig(ncp
);
228 /* Find next free unit number */
229 if(unitno
== (ULONG
) -1)
231 unitno
= ncp
->ncp_CDC
->cdc_DefaultUnit
;
232 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
233 while(tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
235 if(tmpncp
->ncp_UnitNo
== unitno
)
238 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
240 tmpncp
= (struct NepClassEth
*) tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
244 ncp
->ncp_UnitNo
= unitno
;
247 psdSafeRawDoFmt(buf
, 64, "moschipeth.class<%08lx>", ncp
);
248 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
249 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
250 SetSignal(0, SIGF_SINGLE
);
251 if((tmptask
= psdSpawnSubTask(buf
, nEthTask
, ncp
)))
253 psdBorrowLocksWait(tmptask
, 1L<<ncp
->ncp_ReadySignal
);
254 //Wait(1L<<ncp->ncp_ReadySignal);
257 ncp
->ncp_ReadySigTask
= NULL
;
258 //FreeSignal(ncp->ncp_ReadySignal);
259 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
260 "Ethereal moss '%s' on %s unit %ld!",
261 devname
, nh
->nh_DevBase
->np_Library
.lib_Node
.ln_Name
,
268 ncp
->ncp_ReadySigTask
= NULL
;
269 //FreeSignal(ncp->ncp_ReadySignal);
270 /* Get rid of unit structure */
272 Remove((struct Node *) ncp);
273 FreeVec(ncp->ncp_CDC);
282 /* /// "usbReleaseDeviceBinding()" */
283 void usbReleaseDeviceBinding(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
287 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp
));
289 if((ps
= OpenLibrary("poseidon.library", 4)))
292 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
293 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
296 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
301 Wait(1L<<ncp
->ncp_ReadySignal
);
303 //FreeSignal(ncp->ncp_ReadySignal);
304 psdGetAttrs(PGA_DEVICE
, ncp
->ncp_Device
, DA_ProductName
, &devname
, TAG_END
);
305 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
306 "Not much moss of '%s' left.",
314 /* /// "usbGetAttrsA()" */
315 AROS_LH3(LONG
, usbGetAttrsA
,
316 AROS_LHA(ULONG
, type
, D0
),
317 AROS_LHA(APTR
, usbstruct
, A0
),
318 AROS_LHA(struct TagItem
*, tags
, A1
),
319 LIBBASETYPEPTR
, nh
, 5, nep
)
326 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
330 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
332 *((SIPTR
*) ti
->ti_Data
) = 0;
335 if((ti
= FindTagItem(UCCA_Description
, tags
)))
337 *((STRPTR
*) ti
->ti_Data
) = "Ethernet SANA driver for MosChip MCS7830 chipset via usbmoschipeth.device";
340 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
342 *((IPTR
*) ti
->ti_Data
) = TRUE
;
345 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
347 *((IPTR
*) ti
->ti_Data
) = TRUE
;
350 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
352 *((IPTR
*) ti
->ti_Data
) = FALSE
;
355 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
357 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCP
.ncp_UsingDefaultCfg
;
363 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
365 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassEth
*) usbstruct
)->ncp_UsingDefaultCfg
;
375 /* /// "usbSetAttrsA()" */
376 AROS_LH3(LONG
, usbSetAttrsA
,
377 AROS_LHA(ULONG
, type
, D0
),
378 AROS_LHA(APTR
, usbstruct
, A0
),
379 AROS_LHA(struct TagItem
*, tags
, A1
),
380 LIBBASETYPEPTR
, nh
, 6, nep
)
388 /* /// "usbDoMethodA()" */
389 AROS_LH2(IPTR
, usbDoMethodA
,
390 AROS_LHA(ULONG
, methodid
, D0
),
391 AROS_LHA(IPTR
*, methoddata
, A1
),
392 LIBBASETYPEPTR
, nh
, 7, nep
)
396 struct NepClassEth
*ncp
;
398 KPRINTF(10, ("Do Method %ld\n", methodid
));
401 case UCM_AttemptDeviceBinding
:
402 return((IPTR
) usbAttemptDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
404 case UCM_ForceDeviceBinding
:
405 return((IPTR
) usbForceDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
407 case UCM_ReleaseDeviceBinding
:
408 usbReleaseDeviceBinding(nh
, (struct NepClassEth
*) methoddata
[0]);
411 case UCM_OpenCfgWindow
:
412 return(nOpenBindingCfgWindow(nh
, &nh
->nh_DummyNCP
));
414 case UCM_OpenBindingCfgWindow
:
415 return(nOpenBindingCfgWindow(nh
, (struct NepClassEth
*) methoddata
[0]));
417 case UCM_ConfigChangedEvent
:
418 nLoadClassConfig(nh
);
420 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
421 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
423 nLoadBindingConfig(ncp
);
424 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
437 /* /// "nLoadClassConfig()" */
438 BOOL
nLoadClassConfig(struct NepEthBase
*nh
)
440 struct NepClassEth
*ncp
= &nh
->nh_DummyNCP
;
442 struct ClsDevCfg
*cdc
;
443 struct PsdIFFContext
*pic
;
445 KPRINTF(10, ("Loading Class Config...\n"));
450 if(!(ps
= OpenLibrary("poseidon.library", 4)))
456 /* Create default config */
458 cdc
->cdc_ChunkID
= AROS_LONG2BE(MAKE_ID('M','O','S','E'));
459 cdc
->cdc_Length
= AROS_LONG2BE(sizeof(struct ClsDevCfg
)-8);
460 cdc
->cdc_DefaultUnit
= 0;
461 cdc
->cdc_MediaType
= 0;
462 ncp
->ncp_UsingDefaultCfg
= TRUE
;
463 /* try to load default config */
464 pic
= psdGetClsCfg(libname
);
467 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
470 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
472 ncp
->ncp_UsingDefaultCfg
= FALSE
;
481 /* /// "nLoadBindingConfig()" */
482 BOOL
nLoadBindingConfig(struct NepClassEth
*ncp
)
484 struct NepEthBase
*nh
= ncp
->ncp_ClsBase
;
486 struct ClsDevCfg
*cdc
;
487 struct PsdIFFContext
*pic
;
489 KPRINTF(10, ("Loading Binding Config...\n"));
494 //nLoadClassConfig(nh);
495 *ncp
->ncp_CDC
= *nh
->nh_DummyNCP
.ncp_CDC
;
496 ncp
->ncp_UsingDefaultCfg
= TRUE
;
498 if(!(ps
= OpenLibrary("poseidon.library", 4)))
505 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
508 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
511 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
513 ncp
->ncp_UsingDefaultCfg
= FALSE
;
522 /* /// "nOpenBindingCfgWindow()" */
523 LONG
nOpenBindingCfgWindow(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
526 KPRINTF(10, ("Opening GUI...\n"));
527 if(!(ps
= OpenLibrary("poseidon.library", 4)))
532 if(!ncp
->ncp_GUITask
)
534 if((ncp
->ncp_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", nGUITask
, ncp
)))
547 /**************************************************************************/
550 #define ps ncp->ncp_Base
552 static char *MediaTypeStrings
[] =
555 "10Base-T Half Duplex",
556 "10Base-T Full Duplex",
557 "100Base-TX Half Duplex",
558 "100Base-TX Full Duplex",
562 /* /// "nEthTask()" */
563 AROS_UFH0(void, nEthTask
)
567 struct NepClassEth
*ncp
;
578 struct IOSana2Req
*ioreq
;
580 if((ncp
= nAllocEth()))
583 if(ncp
->ncp_ReadySigTask
)
585 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
589 if(nReadEEPROMMAC(ncp
, ncp
->ncp_ROMAddress
))
591 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
593 // don't overwrite previously configured MAC Address
594 CopyMem(ncp
->ncp_ROMAddress
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
);
597 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
598 "Couldn't read EEPROM for MAC Address, using preset one.");
599 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
601 // don't overwrite previously configured MAC Address
602 CopyMem(ncp
->ncp_ROMAddress
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
);
605 KPRINTF(10, ("MAC Address in EEPROM %02lx:%02lx:%02lx:%02lx:%02lx:%02lx\n",
606 ncp
->ncp_MacAddress
[0],
607 ncp
->ncp_MacAddress
[1],
608 ncp
->ncp_MacAddress
[2],
609 ncp
->ncp_MacAddress
[3],
610 ncp
->ncp_MacAddress
[4],
611 ncp
->ncp_MacAddress
[5]));
613 //if((!(ncp->ncp_StateFlags & DDF_OFFLINE)))// && (ncp->ncp_StateFlags & DDF_CONFIGURED))
615 /* Record start time_of_day */
616 //GetSysTime(&ncp->ncp_DeviceStats.LastStart);
621 sigmask
= (1L<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
)|(1L<<ncp
->ncp_TaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
624 // start transmitting read request if online...
625 if((ncp
->ncp_StateFlags
& DDF_ONLINE
) && (ncp
->ncp_ReadPending
== NULL
))
627 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
628 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, ETHER_MAX_LEN
);
629 ncp
->ncp_ReadBufNum
^= 1;
631 while((pp
= (struct PsdPipe
*) GetMsg(ncp
->ncp_TaskMsgPort
)))
633 KPRINTF(1, ("Pipe back %08lx\n", pp
));
634 for(cnt
= 0; cnt
< 2; cnt
++)
636 if(pp
== ncp
->ncp_EPOutPipe
[cnt
])
638 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
640 ioerr
= psdGetPipeError(pp
);
643 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
644 "Eth transmit failed: %s (%ld)",
645 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
647 /* Trigger any tx or generic error events */
648 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
650 /* Set error code and terminate the iorequest.
651 NOTE: Can't use RC_* or deverror() this is not
652 called from devBeginIO()!
654 ioreq
->ios2_DataLength
= 0;
655 ioreq
->ios2_Req
.io_Error
= S2ERR_TX_FAILURE
;
656 ioreq
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
659 ReplyMsg((struct Message
*) ioreq
);
660 ncp
->ncp_WritePending
[cnt
] = NULL
;
665 if(pp
== ncp
->ncp_EPInPipe
)
667 if((pktptr
= ncp
->ncp_ReadPending
))
669 ioerr
= psdGetPipeError(pp
);
670 pktlen
= psdGetPipeActual(pp
);
671 KPRINTF(1, ("ReadBack with %ld bytes (%ld).\n", pktlen
, ioerr
));
672 // interleave next packet reading ASAP.
673 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
675 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
676 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, ETHER_MAX_LEN
);
677 ncp
->ncp_ReadBufNum
^= 1;
679 ncp
->ncp_ReadPending
= NULL
;
683 if(lastioerr
!= ioerr
)
685 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
686 "Eth receive failed: %s (%ld)",
687 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
693 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
,
694 "That's it, that device pissed me off long enough!");
695 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
702 KPRINTF(1, ("Pkt %ld received\n", pktlen
));
703 DB(dumpmem(pktptr
, pktlen
));
704 nReadPacket(ncp
, pktptr
, pktlen
);
710 while((ioreq
= (struct IOSana2Req
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
712 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
713 ioreq
, ioreq
->ios2_Req
.io_Command
, ioreq
->ios2_DataLength
));
714 switch(ioreq
->ios2_Req
.io_Command
)
716 case S2_CONFIGINTERFACE
:
717 //nWritePegRegs(ncp, ncp->ncp_MacAddress, ETHER_ADDR_SIZE, PEGREG_ETH_ID);
719 ncp
->ncp_StateFlags
|= DDF_CONFIGURED
;
720 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
724 ReplyMsg((struct Message
*) ioreq
);
727 case S2_ADDMULTICASTADDRESS
:
728 case S2_DELMULTICASTADDRESS
:
729 case S2_ADDMULTICASTADDRESSES
:
730 case S2_DELMULTICASTADDRESSES
:
732 ReplyMsg((struct Message
*) ioreq
);
737 ReplyMsg((struct Message
*) ioreq
);
741 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, BMCR_PDOWN
);
742 ReplyMsg((struct Message
*) ioreq
);
746 ioreq
->ios2_Req
.io_Error
= IOERR_NOCMD
;
747 ReplyMsg((struct Message
*) ioreq
);
752 while((!ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
]) && ncp
->ncp_WriteQueue
.lh_Head
->ln_Succ
)
754 ioreq
= (struct IOSana2Req
*) RemHead(&ncp
->ncp_WriteQueue
);
756 nWritePacket(ncp
, ioreq
);
760 sigs
= Wait(sigmask
);
761 } while(!(sigs
& SIGBREAKF_CTRL_C
));
764 /* Now remove all requests still pending *anywhere* */
765 //ncp->ncp_DenyRequests = TRUE;
766 /* Current transfers */
767 for(cnt
= 0; cnt
< 2; cnt
++)
769 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
771 KPRINTF(1, ("Aborting pending write...\n"));
772 psdAbortPipe(ncp
->ncp_EPOutPipe
[cnt
]);
773 psdWaitPipe(ncp
->ncp_EPOutPipe
[cnt
]);
774 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
775 ReplyMsg((struct Message
*) ioreq
);
776 ncp
->ncp_WritePending
[cnt
] = NULL
;
779 if(ncp
->ncp_ReadPending
)
781 KPRINTF(1, ("Aborting pending read...\n"));
782 psdAbortPipe(ncp
->ncp_EPInPipe
);
783 psdWaitPipe(ncp
->ncp_EPInPipe
);
784 ncp
->ncp_ReadPending
= NULL
;
787 /*while(ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort))
789 KPRINTF(1, ("Aborting pending requests...\n"));
790 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
791 ReplyMsg((struct Message *) ioreq);
795 nDoEvent(ncp
, S2EVENT_OFFLINE
);
797 KPRINTF(20, ("Going down the river!\n"));
805 /* /// "nAllocEth()" */
806 struct NepClassEth
* nAllocEth(void)
808 struct Task
*thistask
;
809 struct NepClassEth
*ncp
;
811 thistask
= FindTask(NULL
);
814 ncp
= thistask
->tc_UserData
;
815 if(!(ncp
->ncp_Base
= OpenLibrary("poseidon.library", 4)))
821 ncp
->ncp_Interface
= psdFindInterface(ncp
->ncp_Device
, NULL
,
824 if(!ncp
->ncp_Interface
)
826 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "No interface?");
830 ncp
->ncp_EPIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
832 EA_TransferType
, USEAF_BULK
,
834 ncp
->ncp_EPOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
836 EA_TransferType
, USEAF_BULK
,
838 if(!(ncp
->ncp_EPIn
&& ncp
->ncp_EPOut
))
840 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
844 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPOut
,
845 EA_MaxPktSize
, &ncp
->ncp_EPOutMaxPktSize
,
848 ncp
->ncp_ReadPending
= NULL
;
849 ncp
->ncp_WritePending
[0] = NULL
;
850 ncp
->ncp_WritePending
[1] = NULL
;
851 if(!(ncp
->ncp_ReadBuffer
[0] = AllocVec(ETHER_MAX_LEN
* 4, MEMF_PUBLIC
|MEMF_CLEAR
)))
853 KPRINTF(1, ("Out of memory for read buffer\n"));
856 ncp
->ncp_ReadBuffer
[1] = ncp
->ncp_ReadBuffer
[0] + ETHER_MAX_LEN
;
857 ncp
->ncp_WriteBuffer
[0] = ncp
->ncp_ReadBuffer
[1] + ETHER_MAX_LEN
;
858 ncp
->ncp_WriteBuffer
[1] = ncp
->ncp_WriteBuffer
[0] + ETHER_MAX_LEN
;
859 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
860 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
861 ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
862 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
864 if((ncp
->ncp_TaskMsgPort
= CreateMsgPort()))
866 if((ncp
->ncp_EP0Pipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, NULL
)))
868 if((ncp
->ncp_EPOutPipe
[0] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
870 /* Turn off short packets */
871 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[0],
872 PPA_NoShortPackets
, FALSE
,
873 PPA_NakTimeout
, TRUE
,
874 PPA_NakTimeoutTime
, 5000,
876 if((ncp
->ncp_EPOutPipe
[1] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
878 /* Turn off short packets */
879 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[1],
880 PPA_NoShortPackets
, FALSE
,
881 PPA_NakTimeout
, TRUE
,
882 PPA_NakTimeoutTime
, 5000,
884 if((ncp
->ncp_EPInPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPIn
)))
886 /* Turn off short packets */
887 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPInPipe
,
888 PPA_NakTimeout
, FALSE
,
889 PPA_NakTimeoutTime
, 5000,
890 PPA_AllowRuntPackets
, TRUE
,
892 ncp
->ncp_Task
= thistask
;
898 psdFreePipe(ncp
->ncp_EPInPipe
);
900 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
902 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
904 psdFreePipe(ncp
->ncp_EP0Pipe
);
906 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
908 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
910 if(ncp
->ncp_ReadBuffer
[0])
912 FreeVec(ncp
->ncp_ReadBuffer
[0]);
913 ncp
->ncp_ReadBuffer
[0] = NULL
;
915 CloseLibrary(ncp
->ncp_Base
);
917 ncp
->ncp_Task
= NULL
;
918 if(ncp
->ncp_ReadySigTask
)
920 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
926 /* /// "nFreeEth()" */
927 void nFreeEth(struct NepClassEth
*ncp
)
929 struct IOSana2Req
*ioreq
;
931 /* Disable the message port, messages may still be queued */
932 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
933 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
934 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
935 // get rid of all messages that still have appeared here
936 while((ioreq
= (struct IOSana2Req
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
938 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
939 ReplyMsg((struct Message
*) ioreq
);
943 psdFreePipe(ncp
->ncp_EPInPipe
);
944 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
945 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
946 psdFreePipe(ncp
->ncp_EP0Pipe
);
948 if(ncp
->ncp_ReadBuffer
[0])
950 FreeVec(ncp
->ncp_ReadBuffer
[0]);
951 ncp
->ncp_ReadBuffer
[0] = NULL
;
954 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
955 CloseLibrary(ncp
->ncp_Base
);
957 ncp
->ncp_Task
= NULL
;
958 if(ncp
->ncp_ReadySigTask
)
960 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
965 /* /// "nReadMCReg()" */
966 LONG
nReadMCReg(struct NepClassEth
*ncp
, ULONG reg
)
971 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UMCR_READ_REG
, 0, reg
);
972 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, &result
, 1);
975 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
976 "Reading MC Reg %ld failed: %s (%ld)",
978 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
981 KPRINTF(1, ("MC Reg(%ld)=%02lx (%ld)\n", reg
, result
, result
));
986 /* /// "nReadMCRegs()" */
987 LONG
nReadMCRegs(struct NepClassEth
*ncp
, UBYTE
*data
, ULONG len
, ULONG offset
)
991 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UMCR_READ_REG
, 0, offset
);
992 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, data
, len
);
995 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
996 "Reading MC Regs %ld-%ld failed: %s (%ld)",
997 offset
, offset
+len
-1,
998 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1004 /* /// "nWriteMCReg()" */
1005 LONG
nWriteMCReg(struct NepClassEth
*ncp
, ULONG reg
, ULONG value
)
1011 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UMCR_WRITE_REG
, 0, reg
);
1012 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, buf
, 1);
1015 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1016 "Writing MC Reg %ld with 0x%02lx failed: %s (%ld)",
1018 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1024 /* /// "nWriteMCRegs()" */
1025 LONG
nWriteMCRegs(struct NepClassEth
*ncp
, UBYTE
*data
, ULONG len
, ULONG offset
)
1029 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UMCR_WRITE_REG
, 0, offset
);
1030 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, data
, len
);
1033 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1034 "Writing MC Regs %ld-%ld failed: %s (%ld)",
1035 offset
, offset
+len
-1,
1036 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1042 /* /// "nReadEEPROMMAC()" */
1043 BOOL
nReadEEPROMMAC(struct NepClassEth
*ncp
, UBYTE
*macptr
)
1046 ioerr
= nReadMCRegs(ncp
, macptr
, ETHER_ADDR_SIZE
, MCREG_ETH_ID
);
1049 KPRINTF(10, ("Couldn't read EEPROM %ld\n", ioerr
));
1056 /* /// "nReadPhyWord()" */
1057 LONG
nReadPhyWord(struct NepClassEth
*ncp
, ULONG phyid
, ULONG phyreg
)
1065 phyword
[2] = MCRF_PHY_READ
|phyid
;
1066 phyword
[3] = MCRF_PHY_PENDING
|phyreg
;
1067 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UMCR_WRITE_REG
, 0, MCREG_PHY_DATA_LOW
);
1068 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, phyword
, 4);
1071 KPRINTF(10, ("Error writing PHY control %ld\n", ioerr
));
1078 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UMCR_READ_REG
, 0, MCREG_PHY_DATA_LOW
);
1079 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, phyword
, 4);
1082 KPRINTF(10, ("Error reading PHY data %ld\n", ioerr
));
1085 if(phyword
[3] & MCRF_PHY_READY
)
1087 return(phyword
[0]|(phyword
[1]<<8));
1090 KPRINTF(10, ("Timeout reading PHY data %ld\n", ioerr
));
1095 /* /// "nWritePhyWord()" */
1096 BOOL
nWritePhyWord(struct NepClassEth
*ncp
, ULONG phyid
, ULONG phyreg
, ULONG value
)
1103 phyword
[1] = value
>>8;
1104 phyword
[2] = MCRF_PHY_WRITE
|phyid
;
1105 phyword
[3] = MCRF_PHY_PENDING
|phyreg
;
1106 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UMCR_WRITE_REG
, 0, MCREG_PHY_DATA_LOW
);
1107 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, phyword
, 4);
1110 KPRINTF(10, ("Error writing PHY control %ld\n", ioerr
));
1117 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UMCR_READ_REG
, 0, MCREG_PHY_CTRL
);
1118 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, &phyword
[3], 1);
1121 KPRINTF(10, ("Error reading PHY control %ld\n", ioerr
));
1124 if(phyword
[3] & MCRF_PHY_READY
)
1129 KPRINTF(10, ("Timeout reading PHY control %ld\n", ioerr
));
1134 /* /// "nInitMCS()" */
1135 BOOL
nInitMCS(struct NepClassEth
*ncp
)
1141 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, BMCR_RESET
);
1142 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_ADVERTISE
, ADVERTISE_ALL
|ADVERTISE_CSMA
|ADVERTISE_PAUSE_CAP
);
1146 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
, "Failed to initialize adapter!");
1155 /* /// "nUpdateRXMode()" */
1156 void nUpdateRXMode(struct NepClassEth
*ncp
)
1160 rxmode
= MCRF_CFG_TXEN
;
1161 if(ncp
->ncp_OpenFlags
& SANA2OPF_PROM
)
1163 rxmode
|= MCRF_CFG_PROM
;
1165 if(ncp
->ncp_Multicasts
.lh_Head
->ln_Succ
)
1167 rxmode
|= MCRF_CFG_MCAST
;
1170 if(ncp
->ncp_Multicasts
.lh_Head
->ln_Succ
)
1172 ioerr
= nWriteMCRegs(ncp
, ncp
->ncp_MulticastArray
, 8, MCREG_MCAST_ADDR
);
1175 KPRINTF(10, ("Error writing multicast filter %ld\n", ioerr
));
1178 nWriteMCReg(ncp
, MCREG_CFG
, rxmode
);
1182 /* /// "nSetOnline()" */
1183 void nSetOnline(struct NepClassEth
*ncp
)
1187 BOOL autoneg
= FALSE
;
1188 BOOL linkgood
= FALSE
;
1191 switch(ncp
->ncp_CDC
->cdc_MediaType
)
1194 KPRINTF(10, ("Autonegotiaton!\n"));
1195 bmcr
= BMCR_ANENABLE
|BMCR_ANRESTART
;
1199 case MT_10BASE_T_HALF_DUP
:
1204 case MT_10BASE_T_FULL_DUP
:
1205 bmcr
= BMCR_FULLDPLX
;
1208 case MT_100BASE_TX_HALF_DUP
:
1209 bmcr
= BMCR_SPEED1000
;
1212 case MT_100BASE_TX_FULL_DUP
:
1214 bmcr
= BMCR_SPEED100
|BMCR_FULLDPLX
;
1218 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, bmcr
);
1222 data
= nReadPhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMSR
);
1223 KPRINTF(10, ("Status: %04lx\n", data
));
1230 linkgood
= (data
& BMSR_LSTATUS
);
1231 if((!autoneg
) && linkgood
)
1233 // no need to wait for autonegotiation
1238 if(data
& BMSR_ANEGCOMPLETE
)
1246 STRPTR negstr
= MediaTypeStrings
[MT_100BASE_TX_FULL_DUP
];
1249 KPRINTF(10, ("Auto neg successful!\n"));
1250 data
= nReadPhyWord(ncp
, ncp
->ncp_PhyID
, MII_LPA
);
1251 KPRINTF(10, ("Auto neg state %04lx\n", data
));
1256 if(data
& ADVERTISE_100FULL
)
1258 // 100Base-TX Full Duplex
1259 negstr
= MediaTypeStrings
[MT_100BASE_TX_FULL_DUP
];
1261 else if(data
& ADVERTISE_100HALF
)
1263 // 100Base-TX Half Duplex
1264 negstr
= MediaTypeStrings
[MT_100BASE_TX_HALF_DUP
];
1266 else if(data
& ADVERTISE_10FULL
)
1268 // 10Base-T Full Duplex
1269 negstr
= MediaTypeStrings
[MT_10BASE_T_FULL_DUP
];
1271 else if(data
& ADVERTISE_10HALF
)
1273 // 10Base-T Half Duplex
1274 negstr
= MediaTypeStrings
[MT_10BASE_T_HALF_DUP
];
1281 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
, "Autonegotiation failed! Using %s instead.", negstr
);
1282 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, BMCR_SPEED100
|BMCR_FULLDPLX
);
1284 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
, "Autonegotiation: Using %s.", negstr
);
1289 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
, "No link, check the plug and cable.");
1295 ncp
->ncp_StateFlags
|= DDF_ONLINE
;
1296 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
1297 /* Trigger any ONLINE events */
1298 nDoEvent(ncp
, S2EVENT_ONLINE
);
1302 /* /// "nDoEvent()" */
1303 void nDoEvent(struct NepClassEth
*ncp
, ULONG events
)
1305 struct IOSana2Req
*worknode
, *nextnode
;
1307 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events
));
1310 /* Process pending S2_ONEVENT requests */
1311 worknode
= (struct IOSana2Req
*) ncp
->ncp_EventList
.lh_Head
;
1312 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1314 if(worknode
->ios2_WireError
& events
)
1316 Remove(&worknode
->ios2_Req
.io_Message
.mn_Node
);
1317 worknode
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
1318 KPRINTF(1, ("DoEvent: returned eventreq 0x%08lx\n", worknode
));
1319 ReplyMsg(&worknode
->ios2_Req
.io_Message
);
1321 worknode
= nextnode
;
1327 /* /// "support routines" */
1329 inline void *callcopy(void *routine
,
1334 void * (*call
) (APTR
, APTR
, ULONG
) = routine
;
1336 return (*call
) (from
, to
, len
);
1339 #define callfilter CallHookPkt
1342 /* /// "nWritePacket()" */
1343 BOOL
nWritePacket(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1346 struct EtherPacketHeader
*eph
;
1349 struct BufMan
*bufman
;
1350 struct Sana2PacketTypeStats
*stats
;
1351 UBYTE
*buf
= ncp
->ncp_WriteBuffer
[ncp
->ncp_WriteBufNum
];
1353 packettype
= ioreq
->ios2_PacketType
;
1354 writelen
= ioreq
->ios2_DataLength
;
1355 bufman
= ioreq
->ios2_BufferManagement
;
1357 eph
= (struct EtherPacketHeader
*) buf
;
1360 /* Not a raw packet? */
1361 if(!(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
))
1364 KPRINTF(10, ("RAW WRITE!\n"));
1365 /* The ethernet header isn't included in the data */
1366 /* Build ethernet packet header */
1367 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
1369 eph
->eph_Dest
[cnt
] = ioreq
->ios2_DstAddr
[cnt
];
1370 eph
->eph_Src
[cnt
] = ncp
->ncp_MacAddress
[cnt
];
1372 eph
->eph_Type
= AROS_WORD2BE(packettype
);
1374 /* Packet data is at txbuffer */
1375 copydest
+= sizeof(struct EtherPacketHeader
);
1376 writelen
+= sizeof(struct EtherPacketHeader
);
1379 /* Dma not available, fallback to regular copy */
1380 if(callcopy(bufman
->bm_CopyFromBuf
, copydest
, ioreq
->ios2_Data
, ioreq
->ios2_DataLength
) == NULL
)
1382 KPRINTF(10, ("writepacket: copyfrom returned failure!\n"));
1384 /* Trigger any tx, buff or generic error events */
1385 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
|S2EVENT_BUFF
);
1387 /* Set error code and terminate the iorequest.
1388 NOTE: Can't use RC_* or deverror() this is not
1389 called from devBeginIO()! */
1390 ioreq
->ios2_DataLength
= 0;
1391 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1392 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1396 /* Adjust writelen to legal packet size. */
1397 if(writelen
< ETHER_MIN_LEN
)
1399 memset(buf
+ writelen
, 0, ETHER_MIN_LEN
- writelen
);
1400 writelen
= ETHER_MIN_LEN
;
1402 KPRINTF(20, ("PktOut[%ld] %ld\n", ncp
->ncp_WriteBufNum
, writelen
));
1404 ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
] = ioreq
;
1405 psdSendPipe(ncp
->ncp_EPOutPipe
[ncp
->ncp_WriteBufNum
], buf
, (ULONG
) writelen
);
1406 ncp
->ncp_WriteBufNum
^= 1;
1409 if(AROS_BE2WORD(eph
->eph_Type
) < ETHERPKT_SIZE
)
1411 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx (IEEE802.3) len %lu, %lu bytes\n",
1412 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
1413 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
1414 AROS_BE2WORD(eph
->eph_Type
), writelen
));
1416 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx type %lu, %lu bytes\n",
1417 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
1418 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
1419 AROS_BE2WORD(eph
->eph_Type
), writelen
));
1421 //dumpmem(buf, (ULONG) writelen);
1424 /* Update statistics */
1425 stats
= FindPacketTypeStats(ncp
, packettype
);
1428 stats
->PacketsSent
++;
1429 stats
->BytesSent
+= writelen
;
1431 ncp
->ncp_DeviceStats
.PacketsSent
++;
1437 /* /// "nReadIOReq()" */
1438 UWORD
nReadIOReq(struct NepClassEth
*ncp
, struct EtherPacketHeader
*eph
, UWORD datasize
, struct IOSana2Req
*ioreq
, UWORD flags
)
1440 LIBBASETYPEPTR nh
= ncp
->ncp_ClsBase
;
1444 /* Handle RAW read */
1445 if(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
)
1447 /* ShapeShifter won't work with `sizeof(struct etherpacket_hdr)'
1448 here. This is most likely because it want the RAW ethernet
1449 packet checksum size (4) added to the packet size. */
1450 copyfrom
= (UBYTE
*) eph
;
1451 datasize
+= sizeof(struct EtherPacketHeader
) + 4;
1453 copyfrom
= (UBYTE
*) (eph
+ 1);
1456 /* Build up the ios2 structure enough so we can call the packet filter. */
1457 ioreq
->ios2_PacketType
= AROS_BE2WORD(eph
->eph_Type
);
1458 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
1460 ioreq
->ios2_SrcAddr
[cnt
] = eph
->eph_Src
[cnt
];
1461 ioreq
->ios2_DstAddr
[cnt
] = eph
->eph_Dest
[cnt
];
1463 ioreq
->ios2_DataLength
= datasize
;
1464 /* Call the packet filter, if available. */
1465 if((flags
& PACKETFILTER
) &&
1466 (((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
) &&
1467 (!callfilter(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
,
1470 /* This packet got dropped! */
1471 KPRINTF(7, ("readioreq: packet type %lu for ioreq 0x%08lx dropped\n",
1472 AROS_BE2WORD(eph
->eph_Type
), ioreq
));
1477 /* Ok, the packet didn't get dropped, set the BCAST and MCAST
1478 flags according to dstaddr. */
1480 /* Address == Multicast? */
1481 if(ioreq
->ios2_DstAddr
[0] & 1)
1483 /* Address == Broadcast? */
1484 static const UBYTE bcast
[ETHER_ADDR_SIZE
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1485 if(memcmp(bcast
, ioreq
->ios2_DstAddr
, ETHER_ADDR_SIZE
) == 0)
1487 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1489 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1493 /* Finally copy the packet data! */
1494 if(callcopy(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_CopyToBuf
,
1495 ioreq
->ios2_Data
, copyfrom
, ioreq
->ios2_DataLength
))
1498 KPRINTF(5, ("readioreq: copytobuffed packet ior 0x%08lx, %04lx%08lx < %04lx%08lx, type %lu, %lu bytes, %s%s%s\n",
1500 *((UWORD
*) ioreq
->ios2_DstAddr
), *((ULONG
*) (ioreq
->ios2_DstAddr
+ 2)),
1501 *((UWORD
*) ioreq
->ios2_SrcAddr
), *((ULONG
*) (ioreq
->ios2_SrcAddr
+ 2)),
1502 ioreq
->ios2_PacketType
, ioreq
->ios2_DataLength
,
1503 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) ? "RAW " : "",
1504 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_BCAST
) ? "BCAST " : "",
1505 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_MCAST
) ? "MCAST " : ""));
1506 //dumpmem(copyfrom, ioreq->ios2_DataLength);
1509 /* Clear the dropped flag */
1512 KPRINTF(10, ("readioreq: copyto returned failure!\n"));
1514 /* Trigger any rx, buff or generic error events */
1515 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
|S2EVENT_BUFF
);
1518 NOTE: Can't use RC_* or deverror() this is not called from devBeginIO()!
1520 ioreq
->ios2_DataLength
= 0;
1521 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1522 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1525 /* Pull the ioreq off the list & terminate it */
1527 Remove((struct Node
*) ioreq
);
1529 ReplyMsg((struct Message
*) ioreq
);
1534 /* /// "nReadPacket()" */
1535 BOOL
nReadPacket(struct NepClassEth
*ncp
, UBYTE
*pktptr
, ULONG pktlen
)
1537 struct EtherPacketHeader
*eph
;
1538 struct BufMan
*bufman
;
1539 struct IOSana2Req
*worknode
, *nextnode
;
1540 struct Sana2PacketTypeStats
*stats
;
1546 KPRINTF(20, ("PktIn [%ld] %ld\n", ncp
->ncp_ReadBufNum
, pktlen
));
1548 // loop over packet buffer for multiple packets on AX88178 and AX88772
1551 ncp
->ncp_DeviceStats
.BadData
++;
1555 statusbyte
= pktptr
[pktlen
];
1556 ncp
->ncp_DeviceStats
.PacketsReceived
++;
1557 if(statusbyte
!= PKSF_NO_ERROR
)
1559 if(statusbyte
& PKSF_OVERRUN
)
1561 ncp
->ncp_DeviceStats
.Overruns
++;
1563 else if(statusbyte
& (PKSF_UNDERRUN
|PKSF_LENGTH_ERROR
|PKSF_ALIGNMENT_ERROR
|PKSF_CRC_ERROR
))
1565 ncp
->ncp_DeviceStats
.BadData
++;
1567 ncp
->ncp_DeviceStats
.BadData
++;
1570 eph
= (struct EtherPacketHeader
*) pktptr
;
1571 stats
= FindPacketTypeStats(ncp
, (ULONG
) AROS_BE2WORD(eph
->eph_Type
));
1572 flags
= DROPPED
|PACKETFILTER
;
1574 /* Calculate size of the actual data */
1575 datasize
= pktlen
- sizeof(struct EtherPacketHeader
);
1577 /* Is the packet datasize valid? */
1578 if((pktlen
>= ETHER_MIN_LEN
) && (pktlen
<= ETHER_MAX_LEN
))
1580 /* Update the packet statistics */
1583 stats
->PacketsReceived
++;
1584 stats
->BytesReceived
+= datasize
; /* NOTE: don't include headers */
1587 /* For each device user (bufman)
1588 NOTE: We absolutely *MUST* try to offer the packet to *all*
1589 different device users (SANA-II V2 spec requirement). */
1591 bufman
= (struct BufMan
*) ncp
->ncp_BufManList
.lh_Head
;
1592 while(((struct Node
*) bufman
)->ln_Succ
)
1594 /* For each queued read request (ioreq) */
1595 worknode
= (struct IOSana2Req
*) bufman
->bm_RXQueue
.lh_Head
;
1596 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1598 /* Check the packet type. Also handles 802.3 packets. */
1599 if((worknode
->ios2_PacketType
== AROS_BE2WORD(eph
->eph_Type
)) ||
1600 ((AROS_BE2WORD(eph
->eph_Type
) < ETHERPKT_SIZE
) && (worknode
->ios2_PacketType
< ETHERPKT_SIZE
)))
1602 flags
= nReadIOReq(ncp
, eph
, datasize
, worknode
, flags
);
1603 /* Break out - let other callers get the packet too */
1606 worknode
= nextnode
;
1608 bufman
= (struct BufMan
*) (((struct Node
*) bufman
)->ln_Succ
);
1611 /* Now we've tried to give the packet to every CMD_READ caller.
1612 If DROPPED is set at this point no-one wanted this packet. */
1615 /* So there were no outstanding CMD_READs or the packet wasn't
1616 accepted by any of them. Okay, check if we have any pending
1617 S2_READORPHAN ioreq in list and if we have return this packet
1618 with it. Note that packet filter must not be used for this
1621 NOTE: orphanlist is global, ie. only one caller will get the
1622 packet if multiple users have pending S2_READORPHANs.
1625 /* Process pending orphanread iorequs */
1627 worknode
= (struct IOSana2Req
*) ncp
->ncp_OrphanQueue
.lh_Head
;
1628 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1630 nReadIOReq(ncp
, eph
, datasize
, worknode
, 0);
1631 worknode
= nextnode
;
1635 /* Packet not dropped - return ok */
1639 KPRINTF(20, ("Pktlen %ld invalid!\n", pktlen
));
1640 ncp
->ncp_DeviceStats
.BadData
++;
1644 /* Update global dropped packet counter. */
1645 ncp
->ncp_DeviceStats
.UnknownTypesReceived
++;
1647 /* Update dropped packet statistics. */
1650 stats
->PacketsDropped
++;
1652 KPRINTF(9, ("readpacket: packet type %lu dropped\n", AROS_BE2WORD(eph
->eph_Type
)));
1654 /* Trigger any rx or generic error events */
1655 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
);
1662 /**************************************************************************/
1664 /* /// "nGUITask()" */
1665 AROS_UFH0(void, nGUITask
)
1669 struct Task
*thistask
;
1670 struct NepEthBase
*nh
;
1671 struct NepClassEth
*ncp
;
1672 struct PsdIFFContext
*pic
;
1674 thistask
= FindTask(NULL
);
1676 #define ps ncp->ncp_PsdBase
1677 #undef IntuitionBase
1678 #define IntuitionBase ncp->ncp_IntBase
1679 #undef MUIMasterBase
1680 #define MUIMasterBase ncp->ncp_MUIBase
1682 ncp
= thistask
->tc_UserData
;
1683 nh
= ncp
->ncp_ClsBase
;
1685 ++nh
->nh_Library
.lib_OpenCnt
;
1686 if(!(MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MUIMASTER_VMIN
)))
1688 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
1689 nGUITaskCleanup(ncp
);
1693 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
1695 KPRINTF(10, ("Couldn't open intuition.library.\n"));
1696 nGUITaskCleanup(ncp
);
1699 if(!(ps
= OpenLibrary("poseidon.library", 4)))
1701 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
1702 nGUITaskCleanup(ncp
);
1706 ncp
->ncp_App
= ApplicationObject
,
1707 MUIA_Application_Title
, (IPTR
)libname
,
1708 MUIA_Application_Version
, (IPTR
)VERSION_STRING
,
1709 MUIA_Application_Copyright
, (IPTR
)"©2008-2009 Harry Sintonen & Chris Hodges",
1710 MUIA_Application_Author
, (IPTR
)"Harry Sintonen <sintonen@iki.fi> & Chris Hodges <chrisly@platon42.de>",
1711 MUIA_Application_Description
, (IPTR
)"Settings for the moschipeth.class",
1712 MUIA_Application_Base
, (IPTR
)"MOSCHIPETH",
1713 MUIA_Application_HelpFile
, (IPTR
)"HELP:Poseidon.guide",
1714 MUIA_Application_Menustrip
, (IPTR
)MenustripObject
,
1715 Child
, (IPTR
)MenuObjectT((IPTR
)"Project"),
1716 Child
, (IPTR
)(ncp
->ncp_AboutMI
= MenuitemObject
,
1717 MUIA_Menuitem_Title
, (IPTR
)"About...",
1718 MUIA_Menuitem_Shortcut
, (IPTR
)"?",
1721 Child
, (IPTR
)MenuObjectT((IPTR
)"Settings"),
1722 Child
, (IPTR
)(ncp
->ncp_UseMI
= MenuitemObject
,
1723 MUIA_Menuitem_Title
, (IPTR
)"Save",
1724 MUIA_Menuitem_Shortcut
, (IPTR
)"S",
1726 Child
, (IPTR
)(ncp
->ncp_SetDefaultMI
= MenuitemObject
,
1727 MUIA_Menuitem_Title
, (IPTR
)"Set as Default",
1728 MUIA_Menuitem_Shortcut
, (IPTR
)"D",
1730 Child
, (IPTR
)MenuitemObject
,
1731 MUIA_Menuitem_Title
, (IPTR
)NM_BARLABEL
,
1733 Child
, (IPTR
)(ncp
->ncp_MUIPrefsMI
= MenuitemObject
,
1734 MUIA_Menuitem_Title
, (IPTR
)"MUI Settings",
1735 MUIA_Menuitem_Shortcut
, (IPTR
)"M",
1740 SubWindow
, (IPTR
)(ncp
->ncp_MainWindow
= WindowObject
,
1741 MUIA_Window_ID
, MAKE_ID('M','A','I','N'),
1742 MUIA_Window_Title
, (IPTR
)libname
,
1743 MUIA_HelpNode
, (IPTR
)libname
,
1745 WindowContents
, (IPTR
)VGroup
,
1746 Child
, (IPTR
)ColGroup(2), GroupFrameT((IPTR
)(ncp
->ncp_Interface
? "Device Settings" : "Default Device Settings")),
1748 Child
, (IPTR
)Label((IPTR
) "Media Type:"),
1749 Child
, (IPTR
)(ncp
->ncp_MediaTypeObj
= CycleObject
,
1751 MUIA_Cycle_Entries
, (IPTR
)MediaTypeStrings
,
1752 MUIA_Cycle_Active
, ncp
->ncp_CDC
->cdc_MediaType
,
1754 Child
, (IPTR
)Label((IPTR
) "Default " DEVNAME
" Unit:"),
1755 Child
, (IPTR
)(ncp
->ncp_UnitObj
= StringObject
,
1758 MUIA_String_AdvanceOnCR
, TRUE
,
1759 MUIA_String_Integer
, ncp
->ncp_CDC
->cdc_DefaultUnit
,
1760 MUIA_String_Accept
, (IPTR
)"0123456789",
1763 Child
, (IPTR
)VSpace(0),
1764 Child
, (IPTR
)HGroup
,
1765 MUIA_Group_SameWidth
, TRUE
,
1766 Child
, (IPTR
)(ncp
->ncp_UseObj
= TextObject
, ButtonFrame
,
1767 MUIA_ShowMe
, (IPTR
)ncp
->ncp_Interface
,
1768 MUIA_Background
, MUII_ButtonBack
,
1770 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1771 MUIA_Text_Contents
, (IPTR
)"\33c Save ",
1773 Child
, (IPTR
)(ncp
->ncp_SetDefaultObj
= TextObject
, ButtonFrame
,
1774 MUIA_Background
, MUII_ButtonBack
,
1776 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1777 MUIA_Text_Contents
, (IPTR
)(ncp
->ncp_Interface
? "\33c Save as Default " : "\33c Save Defaults "),
1779 Child
, (IPTR
)(ncp
->ncp_CloseObj
= TextObject
, ButtonFrame
,
1780 MUIA_Background
, MUII_ButtonBack
,
1782 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1783 MUIA_Text_Contents
, (IPTR
)"\33c Use ",
1792 KPRINTF(10, ("Couldn't create application\n"));
1793 nGUITaskCleanup(ncp
);
1797 DoMethod(ncp
->ncp_MainWindow
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
1798 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
1799 DoMethod(ncp
->ncp_UseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1800 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
1801 DoMethod(ncp
->ncp_SetDefaultObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1802 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
1803 DoMethod(ncp
->ncp_CloseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1804 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
1806 DoMethod(ncp
->ncp_AboutMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1807 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_ABOUT
);
1808 DoMethod(ncp
->ncp_UseMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1809 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
1810 DoMethod(ncp
->ncp_SetDefaultMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1811 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
1812 DoMethod(ncp
->ncp_MUIPrefsMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1813 ncp
->ncp_App
, 2, MUIM_Application_OpenConfigWindow
, 0);
1821 get(ncp
->ncp_App
, MUIA_Application_Iconified
, &iconify
);
1822 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, TRUE
);
1823 get(ncp
->ncp_MainWindow
, MUIA_Window_Open
, &isopen
);
1824 if(!(isopen
|| iconify
))
1826 nGUITaskCleanup(ncp
);
1832 retid
= DoMethod(ncp
->ncp_App
, MUIM_Application_NewInput
, &sigs
);
1836 case ID_STORE_CONFIG
:
1837 case MUIV_Application_ReturnID_Quit
:
1839 get(ncp
->ncp_UnitObj
, MUIA_String_Integer
, &ncp
->ncp_CDC
->cdc_DefaultUnit
);
1840 get(ncp
->ncp_MediaTypeObj
, MUIA_Cycle_Active
, &ncp
->ncp_CDC
->cdc_MediaType
);
1842 if(retid
== ID_DEF_CONFIG
)
1844 pic
= psdGetClsCfg(libname
);
1847 psdSetClsCfg(libname
, NULL
);
1848 pic
= psdGetClsCfg(libname
);
1852 psdAddCfgEntry(pic
, ncp
->ncp_CDC
);
1853 psdSaveCfgToDisk(NULL
, FALSE
);
1856 if(ncp
->ncp_Interface
)
1858 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
1861 psdSetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
, NULL
);
1862 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
1866 if(psdAddCfgEntry(pic
, ncp
->ncp_CDC
))
1868 if(retid
!= MUIV_Application_ReturnID_Quit
)
1870 psdSaveCfgToDisk(NULL
, FALSE
);
1872 retid
= MUIV_Application_ReturnID_Quit
;
1876 retid
= MUIV_Application_ReturnID_Quit
;
1882 MUI_RequestA(ncp
->ncp_App
, ncp
->ncp_MainWindow
, 0, NULL
, "Groovy!", VERSION_STRING
, NULL
);
1885 if(retid
== MUIV_Application_ReturnID_Quit
)
1891 sigs
= Wait(sigs
|sigmask
|SIGBREAKF_CTRL_C
);
1892 if(sigs
& SIGBREAKF_CTRL_C
)
1898 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, FALSE
);
1900 nGUITaskCleanup(ncp
);
1906 /* /// "nGUITaskCleanup()" */
1907 void nGUITaskCleanup(struct NepClassEth
*ncp
)
1911 MUI_DisposeObject(ncp
->ncp_App
);
1912 ncp
->ncp_App
= NULL
;
1916 CloseLibrary(MUIMasterBase
);
1917 MUIMasterBase
= NULL
;
1921 CloseLibrary(IntuitionBase
);
1922 IntuitionBase
= NULL
;
1930 ncp
->ncp_GUIBinding
= NULL
;
1931 ncp
->ncp_GUITask
= NULL
;
1932 if(ncp
->ncp_ReadySigTask
)
1934 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
1936 --ncp
->ncp_ClsBase
->nh_Library
.lib_OpenCnt
;