2 *----------------------------------------------------------------------------
3 * asixeth class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "asixeth.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! asixeth.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 * ***********************************************************************
128 UWORD abd_PatchFlags
;
131 struct AutoBindData ClassBinds
[] =
133 { 0x0411, 0x003d, 0 }, // Buffalo LUA-U2-KTX
134 { 0x04f1, 0x3008, 0 }, // JVC MP-PRX1 Port Replicator
135 { 0x0557, 0x2009, 0 }, // ATEN UC210T
136 { 0x077b, 0x2226, 0 }, // Linksys USB200M
137 { 0x07aa, 0x0017, 0 }, // corega FEther USB2-TX
138 { 0x07b8, 0x420a, PF_HAWKINGGPIO
}, // Hawking UF200, TrendNet TU2-ET100
139 { 0x0846, 0x1040, 0 }, // Netgear FA120
140 { 0x08dd, 0x90ff, 0 }, // Billionton Systems, USB2AR
141 { 0x0b95, 0x1720, 0 }, // Intellinet, ST Lab USB Ethernet
142 { 0x1189, 0x0893, 0 }, // Surecom EP-1427X-2
143 { 0x1631, 0x6200, 0 }, // goodway corp usb gwusb2e
144 { 0x2001, 0x1a00, PF_DLINKGPIO
}, // DLink DUB-E100
145 { 0x6189, 0x182d, 0 }, // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
146 { 0x04bb, 0x0930, PF_AX88178
}, // IO-DATA ETG-US2
147 { 0x0b95, 0x1780, PF_AX88178
}, // ASIX AX88178 10/100/1000
148 { 0x1737, 0x0039, PF_AX88178
}, // Linksys USB1000
149 { 0x050d, 0x5055, PF_AX88178
}, // Belkin F5D5055
150 { 0x0411, 0x006e, PF_AX88178
}, // Buffalo LUA-U2-GT 10/100/1000
151 { 0x07d1, 0x3c05, PF_AX88772
}, // DLink DUB-E100 H/W Ver B1
152 { 0x2001, 0x3c05, PF_AX88772
}, // DLink DUB-E100 H/W Ver B1 Alternate
153 { 0x0b95, 0x7720, PF_AX88772
}, // ASIX AX88772 10/100
154 { 0x13b1, 0x0018, PF_AX88772
}, // Linksys USB200M Rev 2
155 { 0x1557, 0x7720, PF_AX88772
}, // 0Q0 cable ethernet
156 { 0x05ac, 0x1402, PF_AX88772
}, // Apple Adapter
160 /* /// "usbAttemptDeviceBinding()" */
161 struct NepClassEth
* usbAttemptDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
164 struct AutoBindData
*abd
= ClassBinds
;
168 KPRINTF(1, ("nepEthAttemptDeviceBinding(%08lx)\n", pd
));
170 if((ps
= OpenLibrary("poseidon.library", 4)))
172 psdGetAttrs(PGA_DEVICE
, pd
,
173 DA_VendorID
, &vendid
,
174 DA_ProductID
, &prodid
,
177 while(abd
->abd_VendID
)
179 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
181 return(usbForceDeviceBinding(nh
, pd
));
190 /* /// "usbForceDeviceBinding()" */
191 struct NepClassEth
* usbForceDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
194 struct NepClassEth
*ncp
;
195 struct NepClassEth
*tmpncp
;
196 struct ClsDevCfg
*cdc
;
197 struct AutoBindData
*abd
= ClassBinds
;
205 UWORD patchflags
= 0;
206 struct Task
*tmptask
;
208 KPRINTF(1, ("nepEthForceDeviceBinding(%08lx)\n", pd
));
210 if((ps
= OpenLibrary("poseidon.library", 4)))
212 psdGetAttrs(PGA_DEVICE
, pd
,
213 DA_ProductID
, &prodid
,
214 DA_VendorID
, &vendid
,
215 DA_ProductName
, &devname
,
216 DA_IDString
, &devidstr
,
220 while(abd
->abd_VendID
)
222 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
224 patchflags
= abd
->abd_PatchFlags
;
232 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
233 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
235 if(!strcmp(ncp
->ncp_DevIDString
, devidstr
))
237 unitno
= ncp
->ncp_UnitNo
;
241 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
245 /* as units are freed in the expunge-vector, the memory is
246 outside the scope of the poseidon library */
247 if(!(ncp
= AllocVec(sizeof(struct NepClassEth
), MEMF_PUBLIC
|MEMF_CLEAR
)))
253 ncp
->ncp_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
261 /* IORequests may be queued even if the task is gone. */
262 ncp
->ncp_UnitNo
= (ULONG
) -1;
263 NewList(&ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
);
264 NewList(&ncp
->ncp_OrphanQueue
);
265 NewList(&ncp
->ncp_WriteQueue
);
266 NewList(&ncp
->ncp_BufManList
);
267 NewList(&ncp
->ncp_EventList
);
268 NewList(&ncp
->ncp_TrackList
);
269 NewList(&ncp
->ncp_Multicasts
);
270 strncpy(ncp
->ncp_DevIDString
, devidstr
, 127);
271 AddTail(&nh
->nh_Units
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
);
272 ncp
->ncp_PatchFlags
= patchflags
;
274 ncp
->ncp_ClsBase
= nh
;
275 ncp
->ncp_Device
= pd
;
276 ncp
->ncp_UnitProdID
= prodid
;
277 ncp
->ncp_UnitVendorID
= vendid
;
279 nLoadBindingConfig(ncp
);
281 /* Find next free unit number */
282 if(unitno
== (ULONG
) -1)
284 unitno
= ncp
->ncp_CDC
->cdc_DefaultUnit
;
285 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
286 while(tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
288 if(tmpncp
->ncp_UnitNo
== unitno
)
291 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
293 tmpncp
= (struct NepClassEth
*) tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
297 ncp
->ncp_UnitNo
= unitno
;
300 psdSafeRawDoFmt(buf
, 64, "asixeth.class<%08lx>", ncp
);
301 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
302 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
303 SetSignal(0, SIGF_SINGLE
);
304 if((tmptask
= psdSpawnSubTask(buf
, nEthTask
, ncp
)))
306 psdBorrowLocksWait(tmptask
, 1L<<ncp
->ncp_ReadySignal
);
307 //Wait(1L<<ncp->ncp_ReadySignal);
310 ncp
->ncp_ReadySigTask
= NULL
;
311 //FreeSignal(ncp->ncp_ReadySignal);
312 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
313 "A six yards hit by '%s' on %s unit %ld!",
314 devname
, nh
->nh_DevBase
->np_Library
.lib_Node
.ln_Name
,
321 ncp
->ncp_ReadySigTask
= NULL
;
322 //FreeSignal(ncp->ncp_ReadySignal);
323 /* Get rid of unit structure */
325 Remove((struct Node *) ncp);
326 FreeVec(ncp->ncp_CDC);
335 /* /// "usbReleaseDeviceBinding()" */
336 void usbReleaseDeviceBinding(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
340 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp
));
342 if((ps
= OpenLibrary("poseidon.library", 4)))
345 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
346 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
349 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
354 Wait(1L<<ncp
->ncp_ReadySignal
);
356 //FreeSignal(ncp->ncp_ReadySignal);
357 psdGetAttrs(PGA_DEVICE
, ncp
->ncp_Device
, DA_ProductName
, &devname
, TAG_END
);
358 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
367 /* /// "usbGetAttrsA()" */
368 AROS_LH3(LONG
, usbGetAttrsA
,
369 AROS_LHA(ULONG
, type
, D0
),
370 AROS_LHA(APTR
, usbstruct
, A0
),
371 AROS_LHA(struct TagItem
*, tags
, A1
),
372 LIBBASETYPEPTR
, nh
, 5, nep
)
379 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
383 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
385 *((SIPTR
*) ti
->ti_Data
) = 0;
388 if((ti
= FindTagItem(UCCA_Description
, tags
)))
390 *((STRPTR
*) ti
->ti_Data
) = "Ethernet SANA driver for ASIX chipsets via usbasixeth.device";
393 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
395 *((IPTR
*) ti
->ti_Data
) = TRUE
;
398 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
400 *((IPTR
*) ti
->ti_Data
) = TRUE
;
403 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
405 *((IPTR
*) ti
->ti_Data
) = FALSE
;
408 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
410 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCP
.ncp_UsingDefaultCfg
;
416 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
418 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassEth
*) usbstruct
)->ncp_UsingDefaultCfg
;
428 /* /// "usbSetAttrsA()" */
429 AROS_LH3(LONG
, usbSetAttrsA
,
430 AROS_LHA(ULONG
, type
, D0
),
431 AROS_LHA(APTR
, usbstruct
, A0
),
432 AROS_LHA(struct TagItem
*, tags
, A1
),
433 LIBBASETYPEPTR
, nh
, 6, nep
)
441 /* /// "usbDoMethodA()" */
442 AROS_LH2(IPTR
, usbDoMethodA
,
443 AROS_LHA(ULONG
, methodid
, D0
),
444 AROS_LHA(IPTR
*, methoddata
, A1
),
445 LIBBASETYPEPTR
, nh
, 7, nep
)
449 struct NepClassEth
*ncp
;
451 KPRINTF(10, ("Do Method %ld\n", methodid
));
454 case UCM_AttemptDeviceBinding
:
455 return((IPTR
) usbAttemptDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
457 case UCM_ForceDeviceBinding
:
458 return((IPTR
) usbForceDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
460 case UCM_ReleaseDeviceBinding
:
461 usbReleaseDeviceBinding(nh
, (struct NepClassEth
*) methoddata
[0]);
464 case UCM_OpenCfgWindow
:
465 return(nOpenBindingCfgWindow(nh
, &nh
->nh_DummyNCP
));
467 case UCM_OpenBindingCfgWindow
:
468 return(nOpenBindingCfgWindow(nh
, (struct NepClassEth
*) methoddata
[0]));
470 case UCM_ConfigChangedEvent
:
471 nLoadClassConfig(nh
);
473 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
474 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
476 nLoadBindingConfig(ncp
);
477 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
490 /* /// "nLoadClassConfig()" */
491 BOOL
nLoadClassConfig(struct NepEthBase
*nh
)
493 struct NepClassEth
*ncp
= &nh
->nh_DummyNCP
;
495 struct ClsDevCfg
*cdc
;
496 struct PsdIFFContext
*pic
;
498 KPRINTF(10, ("Loading Class Config...\n"));
503 if(!(ps
= OpenLibrary("poseidon.library", 4)))
509 /* Create default config */
511 cdc
->cdc_ChunkID
= AROS_LONG2BE(MAKE_ID('A','S','I','X'));
512 cdc
->cdc_Length
= AROS_LONG2BE(sizeof(struct ClsDevCfg
)-8);
513 cdc
->cdc_DefaultUnit
= 0;
514 cdc
->cdc_MediaType
= 0;
515 ncp
->ncp_UsingDefaultCfg
= TRUE
;
516 /* try to load default config */
517 pic
= psdGetClsCfg(libname
);
520 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
523 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
525 ncp
->ncp_UsingDefaultCfg
= FALSE
;
534 /* /// "nLoadBindingConfig()" */
535 BOOL
nLoadBindingConfig(struct NepClassEth
*ncp
)
537 struct NepEthBase
*nh
= ncp
->ncp_ClsBase
;
539 struct ClsDevCfg
*cdc
;
540 struct PsdIFFContext
*pic
;
542 KPRINTF(10, ("Loading Binding Config...\n"));
547 //nLoadClassConfig(nh);
548 *ncp
->ncp_CDC
= *nh
->nh_DummyNCP
.ncp_CDC
;
549 ncp
->ncp_UsingDefaultCfg
= TRUE
;
551 if(!(ps
= OpenLibrary("poseidon.library", 4)))
558 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
561 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
564 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
566 ncp
->ncp_UsingDefaultCfg
= FALSE
;
575 /* /// "nOpenBindingCfgWindow()" */
576 LONG
nOpenBindingCfgWindow(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
579 KPRINTF(10, ("Opening GUI...\n"));
580 if(!(ps
= OpenLibrary("poseidon.library", 4)))
585 if(!ncp
->ncp_GUITask
)
587 if((ncp
->ncp_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", nGUITask
, ncp
)))
600 /**************************************************************************/
603 #define ps ncp->ncp_Base
605 static char *MediaTypeStrings
[] =
608 "10Base-T Half Duplex",
609 "10Base-T Full Duplex",
610 "100Base-TX Half Duplex",
611 "100Base-TX Full Duplex",
612 "1000Base-TX Half Duplex",
613 "1000Base-TX Full Duplex",
617 /* /// "nEthTask()" */
618 AROS_UFH0(void, nEthTask
)
622 struct NepClassEth
*ncp
;
633 struct IOSana2Req
*ioreq
;
635 if((ncp
= nAllocEth()))
638 if(ncp
->ncp_ReadySigTask
)
640 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
644 if(nReadEEPROMMAC(ncp
, ncp
->ncp_ROMAddress
))
646 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
648 // don't overwrite previously configured MAC Address
649 CopyMem(ncp
->ncp_ROMAddress
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
);
652 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
653 "Couldn't read EEPROM for MAC Address, using preset one.");
654 if(!(ncp
->ncp_StateFlags
& DDF_CONFIGURED
))
656 // don't overwrite previously configured MAC Address
657 CopyMem(ncp
->ncp_ROMAddress
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
);
660 KPRINTF(10, ("MAC Address in EEPROM %02lx:%02lx:%02lx:%02lx:%02lx:%02lx\n",
661 ncp
->ncp_MacAddress
[0],
662 ncp
->ncp_MacAddress
[1],
663 ncp
->ncp_MacAddress
[2],
664 ncp
->ncp_MacAddress
[3],
665 ncp
->ncp_MacAddress
[4],
666 ncp
->ncp_MacAddress
[5]));
668 //if((!(ncp->ncp_StateFlags & DDF_OFFLINE)))// && (ncp->ncp_StateFlags & DDF_CONFIGURED))
670 /* Record start time_of_day */
671 //GetSysTime(&ncp->ncp_DeviceStats.LastStart);
676 sigmask
= (1L<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
)|(1L<<ncp
->ncp_TaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
679 // start transmitting read request if online...
680 if((ncp
->ncp_StateFlags
& DDF_ONLINE
) && (ncp
->ncp_ReadPending
== NULL
))
682 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
683 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, ETHER_MAX_LEN
);
684 ncp
->ncp_ReadBufNum
^= 1;
686 while((pp
= (struct PsdPipe
*) GetMsg(ncp
->ncp_TaskMsgPort
)))
688 KPRINTF(1, ("Pipe back %08lx\n", pp
));
689 for(cnt
= 0; cnt
< 2; cnt
++)
691 if(pp
== ncp
->ncp_EPOutPipe
[cnt
])
693 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
695 ioerr
= psdGetPipeError(pp
);
698 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
699 "Eth transmit failed: %s (%ld)",
700 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
702 /* Trigger any tx or generic error events */
703 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
);
705 /* Set error code and terminate the iorequest.
706 NOTE: Can't use RC_* or deverror() this is not
707 called from devBeginIO()!
709 ioreq
->ios2_DataLength
= 0;
710 ioreq
->ios2_Req
.io_Error
= S2ERR_TX_FAILURE
;
711 ioreq
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
714 ReplyMsg((struct Message
*) ioreq
);
715 ncp
->ncp_WritePending
[cnt
] = NULL
;
720 if(pp
== ncp
->ncp_EPInPipe
)
722 if((pktptr
= ncp
->ncp_ReadPending
))
724 ioerr
= psdGetPipeError(pp
);
725 pktlen
= psdGetPipeActual(pp
);
726 KPRINTF(1, ("ReadBack with %ld bytes (%ld).\n", pktlen
, ioerr
));
727 // interleave next packet reading ASAP.
728 if(ncp
->ncp_StateFlags
& DDF_ONLINE
)
730 ncp
->ncp_ReadPending
= ncp
->ncp_ReadBuffer
[ncp
->ncp_ReadBufNum
];
731 psdSendPipe(ncp
->ncp_EPInPipe
, ncp
->ncp_ReadPending
, ETHER_MAX_LEN
);
732 ncp
->ncp_ReadBufNum
^= 1;
734 ncp
->ncp_ReadPending
= NULL
;
738 if(lastioerr
!= ioerr
)
740 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
741 "Eth receive failed: %s (%ld)",
742 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
748 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
,
749 "That's it, that device pissed me off long enough!");
750 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
757 KPRINTF(1, ("Pkt %ld received\n", pktlen
));
758 DB(dumpmem(pktptr
, pktlen
));
759 nReadPacket(ncp
, pktptr
, pktlen
);
765 while((ioreq
= (struct IOSana2Req
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
767 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
768 ioreq
, ioreq
->ios2_Req
.io_Command
, ioreq
->ios2_DataLength
));
769 switch(ioreq
->ios2_Req
.io_Command
)
771 case S2_CONFIGINTERFACE
:
772 //nWritePegRegs(ncp, ncp->ncp_MacAddress, ETHER_ADDR_SIZE, PEGREG_ETH_ID);
774 ncp
->ncp_StateFlags
|= DDF_CONFIGURED
;
775 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
779 ReplyMsg((struct Message
*) ioreq
);
782 case S2_ADDMULTICASTADDRESS
:
783 case S2_DELMULTICASTADDRESS
:
784 case S2_ADDMULTICASTADDRESSES
:
785 case S2_DELMULTICASTADDRESSES
:
787 ReplyMsg((struct Message
*) ioreq
);
792 ReplyMsg((struct Message
*) ioreq
);
796 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, BMCR_PDOWN
);
797 ReplyMsg((struct Message
*) ioreq
);
801 ioreq
->ios2_Req
.io_Error
= IOERR_NOCMD
;
802 ReplyMsg((struct Message
*) ioreq
);
807 while((!ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
]) && ncp
->ncp_WriteQueue
.lh_Head
->ln_Succ
)
809 ioreq
= (struct IOSana2Req
*) RemHead(&ncp
->ncp_WriteQueue
);
811 nWritePacket(ncp
, ioreq
);
815 sigs
= Wait(sigmask
);
816 } while(!(sigs
& SIGBREAKF_CTRL_C
));
819 /* Now remove all requests still pending *anywhere* */
820 //ncp->ncp_DenyRequests = TRUE;
821 /* Current transfers */
822 for(cnt
= 0; cnt
< 2; cnt
++)
824 if((ioreq
= ncp
->ncp_WritePending
[cnt
]))
826 KPRINTF(1, ("Aborting pending write...\n"));
827 psdAbortPipe(ncp
->ncp_EPOutPipe
[cnt
]);
828 psdWaitPipe(ncp
->ncp_EPOutPipe
[cnt
]);
829 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
830 ReplyMsg((struct Message
*) ioreq
);
831 ncp
->ncp_WritePending
[cnt
] = NULL
;
834 if(ncp
->ncp_ReadPending
)
836 KPRINTF(1, ("Aborting pending read...\n"));
837 psdAbortPipe(ncp
->ncp_EPInPipe
);
838 psdWaitPipe(ncp
->ncp_EPInPipe
);
839 ncp
->ncp_ReadPending
= NULL
;
842 /*while(ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort))
844 KPRINTF(1, ("Aborting pending requests...\n"));
845 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
846 ReplyMsg((struct Message *) ioreq);
850 nDoEvent(ncp
, S2EVENT_OFFLINE
);
852 KPRINTF(20, ("Going down the river!\n"));
860 /* /// "nAllocEth()" */
861 struct NepClassEth
* nAllocEth(void)
863 struct Task
*thistask
;
864 struct NepClassEth
*ncp
;
866 thistask
= FindTask(NULL
);
869 ncp
= thistask
->tc_UserData
;
870 if(!(ncp
->ncp_Base
= OpenLibrary("poseidon.library", 4)))
876 ncp
->ncp_Interface
= psdFindInterface(ncp
->ncp_Device
, NULL
,
879 if(!ncp
->ncp_Interface
)
881 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "No interface?");
885 ncp
->ncp_EPIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
887 EA_TransferType
, USEAF_BULK
,
889 ncp
->ncp_EPOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
891 EA_TransferType
, USEAF_BULK
,
893 if(!(ncp
->ncp_EPIn
&& ncp
->ncp_EPOut
))
895 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
899 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPOut
,
900 EA_MaxPktSize
, &ncp
->ncp_EPOutMaxPktSize
,
903 ncp
->ncp_ReadPending
= NULL
;
904 ncp
->ncp_WritePending
[0] = NULL
;
905 ncp
->ncp_WritePending
[1] = NULL
;
906 if(!(ncp
->ncp_ReadBuffer
[0] = AllocVec(ETHER_MAX_LEN
* 4, MEMF_PUBLIC
|MEMF_CLEAR
)))
908 KPRINTF(1, ("Out of memory for read buffer\n"));
911 ncp
->ncp_ReadBuffer
[1] = ncp
->ncp_ReadBuffer
[0] + ETHER_MAX_LEN
;
912 ncp
->ncp_WriteBuffer
[0] = ncp
->ncp_ReadBuffer
[1] + ETHER_MAX_LEN
;
913 ncp
->ncp_WriteBuffer
[1] = ncp
->ncp_WriteBuffer
[0] + ETHER_MAX_LEN
;
914 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
915 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
916 ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
917 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
919 if((ncp
->ncp_TaskMsgPort
= CreateMsgPort()))
921 if((ncp
->ncp_EP0Pipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, NULL
)))
923 if((ncp
->ncp_EPOutPipe
[0] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
925 /* Turn off short packets */
926 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[0],
927 PPA_NoShortPackets
, FALSE
,
928 PPA_NakTimeout
, TRUE
,
929 PPA_NakTimeoutTime
, 5000,
931 if((ncp
->ncp_EPOutPipe
[1] = psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPOut
)))
933 /* Turn off short packets */
934 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPOutPipe
[1],
935 PPA_NoShortPackets
, FALSE
,
936 PPA_NakTimeout
, TRUE
,
937 PPA_NakTimeoutTime
, 5000,
939 if((ncp
->ncp_EPInPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPIn
)))
941 /* Turn off short packets */
942 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPInPipe
,
943 PPA_NakTimeout
, FALSE
,
944 PPA_NakTimeoutTime
, 5000,
945 PPA_AllowRuntPackets
, TRUE
,
947 ncp
->ncp_Task
= thistask
;
953 psdFreePipe(ncp
->ncp_EPInPipe
);
955 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
957 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
959 psdFreePipe(ncp
->ncp_EP0Pipe
);
961 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
963 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
965 if(ncp
->ncp_ReadBuffer
[0])
967 FreeVec(ncp
->ncp_ReadBuffer
[0]);
968 ncp
->ncp_ReadBuffer
[0] = NULL
;
970 CloseLibrary(ncp
->ncp_Base
);
972 ncp
->ncp_Task
= NULL
;
973 if(ncp
->ncp_ReadySigTask
)
975 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
981 /* /// "nFreeEth()" */
982 void nFreeEth(struct NepClassEth
*ncp
)
984 struct IOSana2Req
*ioreq
;
986 /* Disable the message port, messages may still be queued */
987 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
988 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
989 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
990 // get rid of all messages that still have appeared here
991 while((ioreq
= (struct IOSana2Req
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
993 ioreq
->ios2_Req
.io_Error
= IOERR_ABORTED
;
994 ReplyMsg((struct Message
*) ioreq
);
998 psdFreePipe(ncp
->ncp_EPInPipe
);
999 psdFreePipe(ncp
->ncp_EPOutPipe
[0]);
1000 psdFreePipe(ncp
->ncp_EPOutPipe
[1]);
1001 psdFreePipe(ncp
->ncp_EP0Pipe
);
1003 if(ncp
->ncp_ReadBuffer
[0])
1005 FreeVec(ncp
->ncp_ReadBuffer
[0]);
1006 ncp
->ncp_ReadBuffer
[0] = NULL
;
1009 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
1010 CloseLibrary(ncp
->ncp_Base
);
1012 ncp
->ncp_Task
= NULL
;
1013 if(ncp
->ncp_ReadySigTask
)
1015 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
1020 /* /// "nReadEEPROMMAC()" */
1021 BOOL
nReadEEPROMMAC(struct NepClassEth
*ncp
, UBYTE
*macptr
)
1025 switch(ncp
->ncp_PatchFlags
& 0xf)
1029 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UAXR_READ_NODE_ID
, 0, 0);
1033 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UAXR_READ_NODE_ID_2
, 0, 0);
1036 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, macptr
, 6);
1039 KPRINTF(10, ("Couldn't read EEPROM %ld\n", ioerr
));
1046 /* /// "nReadPhyWord()" */
1047 LONG
nReadPhyWord(struct NepClassEth
*ncp
, ULONG phyid
, ULONG phyreg
)
1052 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_SET_SW_MII
, 0, 0);
1053 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1056 KPRINTF(10, ("Error obtaining PHY control %ld\n", ioerr
));
1059 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UAXR_READ_MII_REG
, phyid
, phyreg
);
1060 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, phyword
, 2);
1063 KPRINTF(10, ("Could not read PHY %ld reg %ld, due to %ld)!\n", phyid
, phyreg
, ioerr
));
1066 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_SET_HW_MII
, 0, 0);
1067 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1070 KPRINTF(10, ("Error releasing PHY control %ld\n", ioerr
));
1074 return(phyword
[0]|(phyword
[1]<<8));
1078 /* /// "nWritePhyWord()" */
1079 BOOL
nWritePhyWord(struct NepClassEth
*ncp
, ULONG phyid
, ULONG phyreg
, ULONG value
)
1083 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_SET_SW_MII
, 0, 0);
1084 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1087 KPRINTF(10, ("Error obtaining PHY control %ld\n", ioerr
));
1092 phyword
[1] = value
>>8;
1094 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_WRITE_MII_REG
, phyid
, phyreg
);
1095 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, phyword
, 2);
1098 KPRINTF(10, ("Could not write PHY %ld reg %ld, due to %ld)!\n", phyid
, phyreg
, ioerr
));
1101 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_SET_HW_MII
, 0, 0);
1102 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1105 KPRINTF(10, ("Error releasing PHY control %ld\n", ioerr
));
1112 /* /// "nWriteRXCtrl()" */
1113 BOOL
nWriteRXCtrl(struct NepClassEth
*ncp
, ULONG mode
)
1116 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_WRITE_RX_CTL
, mode
, 0);
1117 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1120 KPRINTF(10, ("Error writing RX Ctrl %ld\n", ioerr
));
1127 /* /// "nWriteMediumMode()" */
1128 BOOL
nWriteMediumMode(struct NepClassEth
*ncp
, ULONG mode
)
1131 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_WRITE_MEDIUM_MODE
, mode
, 0);
1132 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1135 KPRINTF(10, ("Error writing Medium Mode %ld\n", ioerr
));
1142 /* /// "nSWReset()" */
1143 BOOL
nSWReset(struct NepClassEth
*ncp
, ULONG mode
)
1146 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_SW_RESET
, mode
, 0);
1147 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1150 KPRINTF(10, ("Error writing SW RESET %ld\n", ioerr
));
1158 /* /// "nWriteGPIOs()" */
1159 BOOL
nWriteGPIOs(struct NepClassEth
*ncp
, ULONG value
, ULONG delay
)
1162 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_WRITE_GPIOS
, value
, 0);
1163 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1166 KPRINTF(10, ("Error writing GPIO %ld\n", ioerr
));
1174 /* /// "nGetPhyAddr()" */
1175 UWORD
nGetPhyAddr(struct NepClassEth
*ncp
)
1179 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UAXR_READ_PHY_ID
, 0, 0);
1180 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, phyid
, 2);
1183 KPRINTF(10, ("Error obtaining PHY ADDR %ld\n", ioerr
));
1190 /* /// "nInitASIX()" */
1191 BOOL
nInitASIX(struct NepClassEth
*ncp
)
1199 switch(ncp
->ncp_PatchFlags
& 0xf)
1202 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
, "This adapter uses the AX88178 chipset. This code is untested! Please report, if it works!");
1203 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_WRITE_ENABLE
, 0, 0);
1204 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1207 KPRINTF(10, ("Error writing enable %ld\n", ioerr
));
1211 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UAXR_READ_EEPROM
, 0x0017, 0);
1212 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, buf
, 2);
1215 KPRINTF(10, ("Error read eeprom %ld\n", ioerr
));
1219 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_WRITE_DISABLE
, 0, 0);
1220 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1223 KPRINTF(10, ("Error writing disable %ld\n", ioerr
));
1226 if((buf
[0] != 0xff) || (buf
[1] != 0xff))
1228 ncp
->ncp_PhyMode
= buf
[0] & 7;
1229 ncp
->ncp_LedMode
= buf
[1];
1231 result
&= nWriteGPIOs(ncp
, AX_GPIO_RSE
|AX_GPIO_GPO_1
|AX_GPIO_GPO1EN
, 40);
1234 result
&= nWriteGPIOs(ncp
, AX_GPIO_GPO_1
|AX_GPIO_GPO1EN
|AX_GPIO_GPO_2
|AX_GPIO_GPO2EN
, 30);
1235 result
&= nWriteGPIOs(ncp
, AX_GPIO_GPO_1
|AX_GPIO_GPO1EN
|AX_GPIO_GPO2EN
, 300);
1236 result
&= nWriteGPIOs(ncp
, AX_GPIO_GPO_1
|AX_GPIO_GPO1EN
|AX_GPIO_GPO_2
|AX_GPIO_GPO2EN
, 30);
1238 result
&= nWriteGPIOs(ncp
, AX_GPIO_GPO1EN
, 30);
1239 result
&= nWriteGPIOs(ncp
, AX_GPIO_GPO_1
|AX_GPIO_GPO1EN
, 30);
1242 result
&= nSWReset(ncp
, AX_SWRESET_CLEAR
);
1244 result
&= nSWReset(ncp
, AX_SWRESET_PRL
|AX_SWRESET_IPPD
);
1246 result
&= nWriteRXCtrl(ncp
, 0x0000);
1248 ncp
->ncp_PhyID
= nGetPhyAddr(ncp
);
1249 if(ncp
->ncp_PhyMode
== PHY_MODE_MARVELL
)
1251 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_MARVELL_CTRL
, MARVELL_CTRL_RXDELAY
|MARVELL_CTRL_TXDELAY
);
1252 if(ncp
->ncp_LedMode
)
1255 reg
= nReadPhyWord(ncp
, ncp
->ncp_PhyID
, MII_MARVELL_LED_CTRL
);
1258 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_MARVELL_LED_CTRL
, reg
);
1264 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, BMCR_RESET
|BMCR_ANENABLE
);
1265 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_ADVERTISE
, ADVERTISE_ALL
|ADVERTISE_CSMA
|ADVERTISE_PAUSE_CAP
);
1266 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_CTRL1000
, ADVERTISE_1000FULL
|ADVERTISE_1000HALF
);
1268 result
&= nWriteMediumMode(ncp
, AX88178_MEDIUM_DEFAULT
);
1270 result
&= nWriteRXCtrl(ncp
, AX_DEFAULT_RX_CTL
);
1275 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
, "This adapter uses the AX88772 chipset.");
1276 result
&= nWriteGPIOs(ncp
, AX_GPIO_RSE
|AX_GPIO_GPO_2
|AX_GPIO_GPO2EN
, 5);
1278 ncp
->ncp_PhyID
= nGetPhyAddr(ncp
);
1279 embeddedphy
= ((ncp
->ncp_PhyID
& 0x1f) == 0x10) ? 1 : 0;
1281 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_SW_PHY_SELECT
, (ULONG
) embeddedphy
, 0);
1282 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1285 KPRINTF(10, ("Error selecting PHY %ld\n", ioerr
));
1288 result
&= nSWReset(ncp
, AX_SWRESET_IPPD
|AX_SWRESET_PRL
);
1290 result
&= nSWReset(ncp
, AX_SWRESET_CLEAR
);
1292 result
&= nSWReset(ncp
, (ULONG
) (embeddedphy
? AX_SWRESET_IPRL
: AX_SWRESET_PRTE
));
1294 result
&= nWriteRXCtrl(ncp
, 0x0000);
1296 ncp
->ncp_PhyID
= nGetPhyAddr(ncp
);
1298 result
&= nSWReset(ncp
, AX_SWRESET_PRL
);
1300 result
&= nSWReset(ncp
, AX_SWRESET_IPRL
|AX_SWRESET_PRL
);
1303 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, BMCR_RESET
);
1304 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_ADVERTISE
, ADVERTISE_ALL
|ADVERTISE_CSMA
|ADVERTISE_PAUSE_CAP
);
1306 result
&= nWriteMediumMode(ncp
, AX88772_MEDIUM_DEFAULT
);
1308 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_WRITE_IPG0
, AX88772_IPG0_DEFAULT
|(AX88772_IPG1_DEFAULT
<<8), AX88772_IPG2_DEFAULT
);
1309 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
1312 KPRINTF(10, ("Error writing IPG0-2 %ld\n", ioerr
));
1316 result
&= nWriteRXCtrl(ncp
, AX_DEFAULT_RX_CTL
);
1322 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
, "This adapter uses the AX88172 chipset.");
1324 if(ncp
->ncp_PatchFlags
& PF_DLINKGPIO
)
1328 if(ncp
->ncp_PatchFlags
& PF_HAWKINGGPIO
)
1333 result
&= nWriteGPIOs(ncp
, (data
>>16) & 0xff, 5);
1334 result
&= nWriteGPIOs(ncp
, (data
>>8) & 0xff, 5);
1335 result
&= nWriteGPIOs(ncp
, data
& 0xff, 5);
1337 result
&= nWriteRXCtrl(ncp
, 0x80);
1338 ncp
->ncp_PhyID
= nGetPhyAddr(ncp
);
1340 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, BMCR_RESET
);
1341 result
&= nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_ADVERTISE
, ADVERTISE_ALL
|ADVERTISE_CSMA
|ADVERTISE_PAUSE_CAP
);
1346 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
, "Failed to initialize adapter!");
1353 /* /// "nUpdateRXMode()" */
1354 void nUpdateRXMode(struct NepClassEth
*ncp
)
1358 switch(ncp
->ncp_PatchFlags
& 0xf)
1362 rxmode
= AX_DEFAULT_RX_CTL
;
1363 if(ncp
->ncp_OpenFlags
& SANA2OPF_PROM
)
1365 rxmode
|= AX_RX_CTL_PRO
;
1367 if(ncp
->ncp_Multicasts
.lh_Head
->ln_Succ
)
1369 rxmode
|= AX_RX_CTL_AM
;
1375 if(ncp
->ncp_OpenFlags
& SANA2OPF_PROM
)
1379 if(ncp
->ncp_Multicasts
.lh_Head
->ln_Succ
)
1385 if(ncp
->ncp_Multicasts
.lh_Head
->ln_Succ
)
1387 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UAXR_WRITE_MULTI_FILTER
, 0, 0);
1388 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, ncp
->ncp_MulticastArray
, 8);
1391 KPRINTF(10, ("Error writing multicast filter %ld\n", ioerr
));
1394 nWriteRXCtrl(ncp
, rxmode
);
1398 /* /// "MediaSpeeds" */
1399 static UWORD nAX88178Speeds
[7] =
1401 AX_MEDIUM_PS
|AX_MEDIUM_FD
|AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
|AX_MEDIUM_JFE
,
1402 AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
|AX_MEDIUM_JFE
,
1403 AX_MEDIUM_FD
|AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
|AX_MEDIUM_JFE
,
1404 AX_MEDIUM_PS
| AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
|AX_MEDIUM_JFE
,
1405 AX_MEDIUM_PS
|AX_MEDIUM_FD
|AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
|AX_MEDIUM_JFE
,
1406 AX_MEDIUM_PS
| AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
|AX_MEDIUM_JFE
|AX_MEDIUM_GM
|AX_MEDIUM_ENCK
,
1407 AX_MEDIUM_PS
|AX_MEDIUM_FD
|AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
|AX_MEDIUM_JFE
|AX_MEDIUM_GM
|AX_MEDIUM_ENCK
1410 static UWORD nAX88772Speeds
[7] =
1412 AX_MEDIUM_PS
|AX_MEDIUM_FD
|AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
,
1413 AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
,
1414 AX_MEDIUM_FD
|AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
,
1415 AX_MEDIUM_PS
| AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
,
1416 AX_MEDIUM_PS
|AX_MEDIUM_FD
|AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
,
1417 AX_MEDIUM_PS
| AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
,
1418 AX_MEDIUM_PS
|AX_MEDIUM_FD
|AX_MEDIUM_AC
|AX_MEDIUM_RFC
|AX_MEDIUM_TFC
|AX_MEDIUM_RE
,
1421 static UWORD nAX88172Speeds
[7] =
1423 AX88172_MEDIUM_FD
|AX88172_MEDIUM_FC
|AX88172_MEDIUM_TX
,
1424 AX88172_MEDIUM_FC
|AX88172_MEDIUM_TX
,
1425 AX88172_MEDIUM_FD
|AX88172_MEDIUM_FC
|AX88172_MEDIUM_TX
,
1426 AX88172_MEDIUM_FC
|AX88172_MEDIUM_TX
,
1427 AX88172_MEDIUM_FD
|AX88172_MEDIUM_FC
|AX88172_MEDIUM_TX
,
1428 AX88172_MEDIUM_FC
|AX88172_MEDIUM_TX
,
1429 AX88172_MEDIUM_FD
|AX88172_MEDIUM_FC
|AX88172_MEDIUM_TX
,
1433 /* /// "nSetOnline()" */
1434 void nSetOnline(struct NepClassEth
*ncp
)
1439 BOOL autoneg
= FALSE
;
1440 BOOL linkgood
= FALSE
;
1445 switch(ncp
->ncp_PatchFlags
& 0xf)
1448 mediatable
= nAX88178Speeds
;
1452 mediatable
= nAX88772Speeds
;
1456 mediatable
= nAX88172Speeds
;
1459 mediummode
= mediatable
[ncp
->ncp_CDC
->cdc_MediaType
];
1461 switch(ncp
->ncp_CDC
->cdc_MediaType
)
1464 KPRINTF(10, ("Autonegotiaton!\n"));
1465 bmcr
= BMCR_ANENABLE
|BMCR_ANRESTART
;
1469 case MT_10BASE_T_HALF_DUP
:
1474 case MT_10BASE_T_FULL_DUP
:
1475 bmcr
= BMCR_FULLDPLX
;
1478 case MT_100BASE_TX_HALF_DUP
:
1479 bmcr
= BMCR_SPEED1000
;
1482 case MT_1000BASE_TX_HALF_DUP
:
1483 bmcr
= BMCR_SPEED100
;
1486 case MT_1000BASE_TX_FULL_DUP
:
1487 bmcr
= BMCR_SPEED1000
|BMCR_FULLDPLX
;
1490 case MT_100BASE_TX_FULL_DUP
:
1492 bmcr
= BMCR_SPEED100
|BMCR_FULLDPLX
;
1493 mediummode
= mediatable
[MT_100BASE_TX_FULL_DUP
];
1497 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, bmcr
);
1501 data
= nReadPhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMSR
);
1502 KPRINTF(10, ("Status: %04lx\n", data
));
1509 linkgood
= (data
& BMSR_LSTATUS
);
1510 if((!autoneg
) && linkgood
)
1512 // no need to wait for autonegotiation
1517 if(data
& BMSR_ANEGCOMPLETE
)
1525 STRPTR negstr
= NULL
;
1528 KPRINTF(10, ("Auto neg successful!\n"));
1529 data
= nReadPhyWord(ncp
, ncp
->ncp_PhyID
, MII_LPA
);
1530 KPRINTF(10, ("Auto neg state %04lx\n", data
));
1535 if(ncp
->ncp_PatchFlags
& PF_AX88178
)
1537 data2
= nReadPhyWord(ncp
, ncp
->ncp_PhyID
, MII_STAT1000
);
1538 if(data2
& ADVERTISE_1000FULL
)
1540 negstr
= MediaTypeStrings
[MT_1000BASE_TX_FULL_DUP
];
1541 mediummode
= mediatable
[MT_1000BASE_TX_FULL_DUP
];
1543 else if(data2
& ADVERTISE_1000HALF
)
1545 negstr
= MediaTypeStrings
[MT_1000BASE_TX_HALF_DUP
];
1546 mediummode
= mediatable
[MT_1000BASE_TX_HALF_DUP
];
1551 if(data
& ADVERTISE_100FULL
)
1553 // 100Base-TX Full Duplex
1554 negstr
= MediaTypeStrings
[MT_100BASE_TX_FULL_DUP
];
1555 mediummode
= mediatable
[MT_100BASE_TX_FULL_DUP
];
1557 else if(data
& ADVERTISE_100HALF
)
1559 // 100Base-TX Half Duplex
1560 negstr
= MediaTypeStrings
[MT_100BASE_TX_HALF_DUP
];
1561 mediummode
= mediatable
[MT_100BASE_TX_HALF_DUP
];
1563 else if(data
& ADVERTISE_10FULL
)
1565 // 10Base-T Full Duplex
1566 negstr
= MediaTypeStrings
[MT_10BASE_T_FULL_DUP
];
1567 mediummode
= mediatable
[MT_10BASE_T_FULL_DUP
];
1569 else if(data
& ADVERTISE_10HALF
)
1571 // 10Base-T Half Duplex
1572 negstr
= MediaTypeStrings
[MT_10BASE_T_HALF_DUP
];
1573 mediummode
= mediatable
[MT_10BASE_T_HALF_DUP
];
1581 negstr
= MediaTypeStrings
[MT_100BASE_TX_FULL_DUP
];
1582 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
, "Autonegotiation failed! Using %s instead.", negstr
);
1583 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, BMCR_SPEED100
|BMCR_FULLDPLX
);
1584 mediummode
= mediatable
[MT_100BASE_TX_FULL_DUP
];
1586 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
, "Autonegotiation: Using %s.", negstr
);
1591 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
, "No link, check the plug and cable.");
1594 nWriteMediumMode(ncp
, mediummode
);
1598 ncp
->ncp_StateFlags
|= DDF_ONLINE
;
1599 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
1600 /* Trigger any ONLINE events */
1601 nDoEvent(ncp
, S2EVENT_ONLINE
);
1605 /* /// "nDoEvent()" */
1606 void nDoEvent(struct NepClassEth
*ncp
, ULONG events
)
1608 struct IOSana2Req
*worknode
, *nextnode
;
1610 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events
));
1613 /* Process pending S2_ONEVENT requests */
1614 worknode
= (struct IOSana2Req
*) ncp
->ncp_EventList
.lh_Head
;
1615 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1617 if(worknode
->ios2_WireError
& events
)
1619 Remove(&worknode
->ios2_Req
.io_Message
.mn_Node
);
1620 worknode
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
1621 KPRINTF(1, ("DoEvent: returned eventreq 0x%08lx\n", worknode
));
1622 ReplyMsg(&worknode
->ios2_Req
.io_Message
);
1624 worknode
= nextnode
;
1630 /* /// "support routines" */
1632 inline void *callcopy(void *routine
,
1637 void * (*call
) (APTR
, APTR
, ULONG
) = routine
;
1639 return (*call
) (from
, to
, len
);
1642 #define callfilter CallHookPkt
1645 /* /// "nWritePacket()" */
1646 BOOL
nWritePacket(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1649 struct EtherPacketHeader
*eph
;
1652 struct BufMan
*bufman
;
1653 struct Sana2PacketTypeStats
*stats
;
1654 UBYTE
*buf
= ncp
->ncp_WriteBuffer
[ncp
->ncp_WriteBufNum
];
1656 packettype
= ioreq
->ios2_PacketType
;
1657 writelen
= ioreq
->ios2_DataLength
;
1658 bufman
= ioreq
->ios2_BufferManagement
;
1660 if(ncp
->ncp_PatchFlags
& (PF_AX88178
|PF_AX88772
))
1662 // the first four bytes are the length
1663 eph
= (struct EtherPacketHeader
*) &buf
[4];
1666 eph
= (struct EtherPacketHeader
*) buf
;
1670 /* Not a raw packet? */
1671 if(!(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
))
1674 KPRINTF(10, ("RAW WRITE!\n"));
1675 /* The ethernet header isn't included in the data */
1676 /* Build ethernet packet header */
1677 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
1679 eph
->eph_Dest
[cnt
] = ioreq
->ios2_DstAddr
[cnt
];
1680 eph
->eph_Src
[cnt
] = ncp
->ncp_MacAddress
[cnt
];
1682 eph
->eph_Type
= AROS_WORD2BE(packettype
);
1684 /* Packet data is at txbuffer */
1685 copydest
+= sizeof(struct EtherPacketHeader
);
1686 writelen
+= sizeof(struct EtherPacketHeader
);
1689 //memset(buf + 2, 0x55, writelen);
1691 /* Dma not available, fallback to regular copy */
1692 if(callcopy(bufman
->bm_CopyFromBuf
, copydest
, ioreq
->ios2_Data
, ioreq
->ios2_DataLength
) == NULL
)
1694 KPRINTF(10, ("writepacket: copyfrom returned failure!\n"));
1696 /* Trigger any tx, buff or generic error events */
1697 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_TX
|S2EVENT_BUFF
);
1699 /* Set error code and terminate the iorequest.
1700 NOTE: Can't use RC_* or deverror() this is not
1701 called from devBeginIO()! */
1702 ioreq
->ios2_DataLength
= 0;
1703 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1704 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1708 if(ncp
->ncp_PatchFlags
& (PF_AX88178
|PF_AX88772
))
1711 buf
[1] = writelen
>>8;
1714 /* Adjust writelen to legal packet size. */
1715 if(writelen
< ETHER_MIN_LEN
)
1717 memset(buf
+ writelen
+ 4, 0, ETHER_MIN_LEN
- writelen
);
1718 writelen
= ETHER_MIN_LEN
;
1722 /* Adjust writelen to legal packet size. */
1723 if(writelen
< ETHER_MIN_LEN
)
1725 memset(buf
+ writelen
, 0, ETHER_MIN_LEN
- writelen
);
1726 writelen
= ETHER_MIN_LEN
;
1728 if(!(writelen
& (ncp
->ncp_EPOutMaxPktSize
-1)))
1730 // adjust size to send one extra byte as zero packet termination doesn't seem to work with this adapter
1731 buf
[writelen
++] = 0;
1732 KPRINTF(10, ("Zero Packet adjustment\n"));
1736 KPRINTF(20, ("PktOut[%ld] %ld\n", ncp
->ncp_WriteBufNum
, writelen
));
1738 ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
] = ioreq
;
1739 psdSendPipe(ncp
->ncp_EPOutPipe
[ncp
->ncp_WriteBufNum
], buf
, (ULONG
) writelen
);
1740 ncp
->ncp_WriteBufNum
^= 1;
1743 if(AROS_BE2WORD(eph
->eph_Type
) < ETHERPKT_SIZE
)
1745 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx (IEEE802.3) len %lu, %lu bytes\n",
1746 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
1747 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
1748 AROS_BE2WORD(eph
->eph_Type
), writelen
));
1750 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx type %lu, %lu bytes\n",
1751 *((UWORD
*) eph
->eph_Src
), *((ULONG
*) (eph
->eph_Src
+ 2)),
1752 *((UWORD
*) eph
->eph_Dest
), *((ULONG
*) (eph
->eph_Dest
+ 2)),
1753 AROS_BE2WORD(eph
->eph_Type
), writelen
));
1755 //dumpmem(buf, (ULONG) writelen);
1758 /* Update statistics */
1759 stats
= FindPacketTypeStats(ncp
, packettype
);
1762 stats
->PacketsSent
++;
1763 stats
->BytesSent
+= writelen
;
1765 ncp
->ncp_DeviceStats
.PacketsSent
++;
1771 /* /// "nReadIOReq()" */
1772 UWORD
nReadIOReq(struct NepClassEth
*ncp
, struct EtherPacketHeader
*eph
, UWORD datasize
, struct IOSana2Req
*ioreq
, UWORD flags
)
1774 LIBBASETYPEPTR nh
= ncp
->ncp_ClsBase
;
1778 /* Handle RAW read */
1779 if(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
)
1781 /* ShapeShifter won't work with `sizeof(struct etherpacket_hdr)'
1782 here. This is most likely because it want the RAW ethernet
1783 packet checksum size (4) added to the packet size. */
1784 copyfrom
= (UBYTE
*) eph
;
1785 datasize
+= sizeof(struct EtherPacketHeader
) + 4;
1787 copyfrom
= (UBYTE
*) (eph
+ 1);
1790 /* Build up the ios2 structure enough so we can call the packet filter. */
1791 ioreq
->ios2_PacketType
= AROS_BE2WORD(eph
->eph_Type
);
1792 for(cnt
= 0; cnt
< ETHER_ADDR_SIZE
; cnt
++)
1794 ioreq
->ios2_SrcAddr
[cnt
] = eph
->eph_Src
[cnt
];
1795 ioreq
->ios2_DstAddr
[cnt
] = eph
->eph_Dest
[cnt
];
1797 ioreq
->ios2_DataLength
= datasize
;
1798 /* Call the packet filter, if available. */
1799 if((flags
& PACKETFILTER
) &&
1800 (((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
) &&
1801 (!callfilter(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_PacketFilter
,
1804 /* This packet got dropped! */
1805 KPRINTF(7, ("readioreq: packet type %lu for ioreq 0x%08lx dropped\n",
1806 AROS_BE2WORD(eph
->eph_Type
), ioreq
));
1811 /* Ok, the packet didn't get dropped, set the BCAST and MCAST
1812 flags according to dstaddr. */
1814 /* Address == Multicast? */
1815 if(ioreq
->ios2_DstAddr
[0] & 1)
1817 /* Address == Broadcast? */
1818 const UBYTE broadcast
[ETHER_ADDR_SIZE
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1819 if (memcmp(ioreq
->ios2_DstAddr
, broadcast
, ETHER_ADDR_SIZE
) == 0)
1821 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1823 ioreq
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1827 /* Finally copy the packet data! */
1828 if(callcopy(((struct BufMan
*) ioreq
->ios2_BufferManagement
)->bm_CopyToBuf
,
1829 ioreq
->ios2_Data
, copyfrom
, ioreq
->ios2_DataLength
))
1832 KPRINTF(5, ("readioreq: copytobuffed packet ior 0x%08lx, %04lx%08lx < %04lx%08lx, type %lu, %lu bytes, %s%s%s\n",
1834 *((UWORD
*) ioreq
->ios2_DstAddr
), *((ULONG
*) (ioreq
->ios2_DstAddr
+ 2)),
1835 *((UWORD
*) ioreq
->ios2_SrcAddr
), *((ULONG
*) (ioreq
->ios2_SrcAddr
+ 2)),
1836 ioreq
->ios2_PacketType
, ioreq
->ios2_DataLength
,
1837 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) ? "RAW " : "",
1838 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_BCAST
) ? "BCAST " : "",
1839 (ioreq
->ios2_Req
.io_Flags
& SANA2IOF_MCAST
) ? "MCAST " : ""));
1840 //dumpmem(copyfrom, ioreq->ios2_DataLength);
1843 /* Clear the dropped flag */
1846 KPRINTF(10, ("readioreq: copyto returned failure!\n"));
1848 /* Trigger any rx, buff or generic error events */
1849 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
|S2EVENT_BUFF
);
1852 NOTE: Can't use RC_* or deverror() this is not called from devBeginIO()!
1854 ioreq
->ios2_DataLength
= 0;
1855 ioreq
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1856 ioreq
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1859 /* Pull the ioreq off the list & terminate it */
1861 Remove((struct Node
*) ioreq
);
1863 ReplyMsg((struct Message
*) ioreq
);
1868 /* /// "nReadPacket()" */
1869 BOOL
nReadPacket(struct NepClassEth
*ncp
, UBYTE
*pktptr
, ULONG len
)
1871 struct EtherPacketHeader
*eph
;
1872 struct BufMan
*bufman
;
1873 struct IOSana2Req
*worknode
, *nextnode
;
1874 struct Sana2PacketTypeStats
*stats
;
1880 KPRINTF(20, ("PktIn [%ld] %ld\n", ncp
->ncp_ReadBufNum
, len
));
1882 // loop over packet buffer for multiple packets on AX88178 and AX88772
1883 for(; len
; len
-= pktlen
, pktptr
+= pktlen
)
1885 if(ncp
->ncp_PatchFlags
& (PF_AX88178
|PF_AX88772
))
1889 ncp
->ncp_DeviceStats
.BadData
++;
1892 if((pktptr
[0] + pktptr
[2] != 0xff) || (pktptr
[1] + pktptr
[3] != 0xff))
1894 ncp
->ncp_DeviceStats
.BadData
++;
1895 KPRINTF(20, ("InverseLength mismatch\n"));
1899 pktlen
|= (*pktptr
++)<<8;
1902 if(len
< ((pktlen
+ 1) & ~1))
1904 KPRINTF(20, ("Pktlen %ld < len %ld\n", pktlen
, len
));
1910 ncp
->ncp_DeviceStats
.PacketsReceived
++;
1912 eph
= (struct EtherPacketHeader
*) pktptr
;
1913 stats
= FindPacketTypeStats(ncp
, (ULONG
) AROS_BE2WORD(eph
->eph_Type
));
1914 flags
= DROPPED
|PACKETFILTER
;
1916 /* Calculate size of the actual data */
1917 datasize
= pktlen
- sizeof(struct EtherPacketHeader
);
1919 /* Is the packet datasize valid? */
1920 if((pktlen
>= ETHER_MIN_LEN
) && (pktlen
<= ETHER_MAX_LEN
))
1922 /* Update the packet statistics */
1925 stats
->PacketsReceived
++;
1926 stats
->BytesReceived
+= datasize
; /* NOTE: don't include headers */
1929 /* For each device user (bufman)
1930 NOTE: We absolutely *MUST* try to offer the packet to *all*
1931 different device users (SANA-II V2 spec requirement). */
1933 bufman
= (struct BufMan
*) ncp
->ncp_BufManList
.lh_Head
;
1934 while(((struct Node
*) bufman
)->ln_Succ
)
1936 /* For each queued read request (ioreq) */
1937 worknode
= (struct IOSana2Req
*) bufman
->bm_RXQueue
.lh_Head
;
1938 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1940 /* Check the packet type. Also handles 802.3 packets. */
1941 if((worknode
->ios2_PacketType
== AROS_BE2WORD(eph
->eph_Type
)) ||
1942 ((AROS_BE2WORD(eph
->eph_Type
) < ETHERPKT_SIZE
) && (worknode
->ios2_PacketType
< ETHERPKT_SIZE
)))
1944 flags
= nReadIOReq(ncp
, eph
, datasize
, worknode
, flags
);
1945 /* Break out - let other callers get the packet too */
1948 worknode
= nextnode
;
1950 bufman
= (struct BufMan
*) (((struct Node
*) bufman
)->ln_Succ
);
1953 /* Now we've tried to give the packet to every CMD_READ caller.
1954 If DROPPED is set at this point no-one wanted this packet. */
1957 /* So there were no outstanding CMD_READs or the packet wasn't
1958 accepted by any of them. Okay, check if we have any pending
1959 S2_READORPHAN ioreq in list and if we have return this packet
1960 with it. Note that packet filter must not be used for this
1963 NOTE: orphanlist is global, ie. only one caller will get the
1964 packet if multiple users have pending S2_READORPHANs.
1967 /* Process pending orphanread iorequs */
1969 worknode
= (struct IOSana2Req
*) ncp
->ncp_OrphanQueue
.lh_Head
;
1970 while((nextnode
= (struct IOSana2Req
*) (((struct Node
*) worknode
)->ln_Succ
)))
1972 nReadIOReq(ncp
, eph
, datasize
, worknode
, 0);
1973 worknode
= nextnode
;
1977 /* Packet not dropped - return ok */
1982 KPRINTF(20, ("Pktlen %ld invalid!\n", pktlen
));
1983 ncp
->ncp_DeviceStats
.BadData
++;
1985 /* Update global dropped packet counter. */
1986 ncp
->ncp_DeviceStats
.UnknownTypesReceived
++;
1988 /* Update dropped packet statistics. */
1991 stats
->PacketsDropped
++;
1993 KPRINTF(9, ("readpacket: packet type %lu dropped\n", AROS_BE2WORD(eph
->eph_Type
)));
1995 /* Trigger any rx or generic error events */
1996 nDoEvent(ncp
, S2EVENT_ERROR
|S2EVENT_RX
);
1998 if(!(ncp
->ncp_PatchFlags
& (PF_AX88178
|PF_AX88772
)))
2000 // other chipsets don't support multiple packets in one transfer
2008 /**************************************************************************/
2010 /* /// "nGUITask()" */
2011 AROS_UFH0(void, nGUITask
)
2015 struct Task
*thistask
;
2016 struct NepEthBase
*nh
;
2017 struct NepClassEth
*ncp
;
2018 struct PsdIFFContext
*pic
;
2020 thistask
= FindTask(NULL
);
2022 #define ps ncp->ncp_PsdBase
2023 #undef IntuitionBase
2024 #define IntuitionBase ncp->ncp_IntBase
2025 #undef MUIMasterBase
2026 #define MUIMasterBase ncp->ncp_MUIBase
2028 ncp
= thistask
->tc_UserData
;
2029 nh
= ncp
->ncp_ClsBase
;
2031 ++nh
->nh_Library
.lib_OpenCnt
;
2032 if(!(MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MUIMASTER_VMIN
)))
2034 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
2035 nGUITaskCleanup(ncp
);
2039 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
2041 KPRINTF(10, ("Couldn't open intuition.library.\n"));
2042 nGUITaskCleanup(ncp
);
2045 if(!(ps
= OpenLibrary("poseidon.library", 4)))
2047 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
2048 nGUITaskCleanup(ncp
);
2052 ncp
->ncp_App
= ApplicationObject
,
2053 MUIA_Application_Title
, (IPTR
)libname
,
2054 MUIA_Application_Version
, (IPTR
)VERSION_STRING
,
2055 MUIA_Application_Copyright
, (IPTR
)"©2007-2009 Harry Sintonen & Chris Hodges",
2056 MUIA_Application_Author
, (IPTR
)"Harry Sintonen <sintonen@iki.fi> & Chris Hodges <chrisly@platon42.de>",
2057 MUIA_Application_Description
, (IPTR
)"Settings for the asixeth.class",
2058 MUIA_Application_Base
, (IPTR
)"ASIXETH",
2059 MUIA_Application_HelpFile
, (IPTR
)"HELP:Poseidon.guide",
2060 MUIA_Application_Menustrip
, (IPTR
)MenustripObject
,
2061 Child
, (IPTR
)MenuObjectT((IPTR
)"Project"),
2062 Child
, (IPTR
)(ncp
->ncp_AboutMI
= MenuitemObject
,
2063 MUIA_Menuitem_Title
, (IPTR
)"About...",
2064 MUIA_Menuitem_Shortcut
, (IPTR
)"?",
2067 Child
, (IPTR
)MenuObjectT((IPTR
)"Settings"),
2068 Child
, (IPTR
)(ncp
->ncp_UseMI
= MenuitemObject
,
2069 MUIA_Menuitem_Title
, (IPTR
)"Save",
2070 MUIA_Menuitem_Shortcut
, (IPTR
)"S",
2072 Child
, (IPTR
)(ncp
->ncp_SetDefaultMI
= MenuitemObject
,
2073 MUIA_Menuitem_Title
, (IPTR
)"Set as Default",
2074 MUIA_Menuitem_Shortcut
, (IPTR
)"D",
2076 Child
, (IPTR
)(MenuitemObject
,
2077 MUIA_Menuitem_Title
, (IPTR
)NM_BARLABEL
,
2079 Child
, (IPTR
)(ncp
->ncp_MUIPrefsMI
= MenuitemObject
,
2080 MUIA_Menuitem_Title
, (IPTR
)"MUI Settings",
2081 MUIA_Menuitem_Shortcut
, (IPTR
)"M",
2086 SubWindow
, (IPTR
)(ncp
->ncp_MainWindow
= WindowObject
,
2087 MUIA_Window_ID
, MAKE_ID('M','A','I','N'),
2088 MUIA_Window_Title
, (IPTR
)libname
,
2089 MUIA_HelpNode
, (IPTR
)libname
,
2091 WindowContents
, (IPTR
)VGroup
,
2092 Child
, (IPTR
)ColGroup(2), GroupFrameT((IPTR
)(ncp
->ncp_Interface
? "Device Settings" : "Default Device Settings")),
2094 Child
, (IPTR
)Label((IPTR
) "Media Type:"),
2095 Child
, (IPTR
)(ncp
->ncp_MediaTypeObj
= CycleObject
,
2097 MUIA_Cycle_Entries
, (IPTR
)MediaTypeStrings
,
2098 MUIA_Cycle_Active
, ncp
->ncp_CDC
->cdc_MediaType
,
2100 Child
, (IPTR
)Label((IPTR
) "Default " DEVNAME
" Unit:"),
2101 Child
, (IPTR
)(ncp
->ncp_UnitObj
= StringObject
,
2104 MUIA_String_AdvanceOnCR
, TRUE
,
2105 MUIA_String_Integer
, ncp
->ncp_CDC
->cdc_DefaultUnit
,
2106 MUIA_String_Accept
, (IPTR
)"0123456789",
2109 Child
, (IPTR
)VSpace(0),
2110 Child
, (IPTR
)HGroup
,
2111 MUIA_Group_SameWidth
, TRUE
,
2112 Child
, (IPTR
)(ncp
->ncp_UseObj
= TextObject
, ButtonFrame
,
2113 MUIA_ShowMe
, (IPTR
)ncp
->ncp_Interface
,
2114 MUIA_Background
, MUII_ButtonBack
,
2116 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
2117 MUIA_Text_Contents
, (IPTR
)"\33c Save ",
2119 Child
, (IPTR
)(ncp
->ncp_SetDefaultObj
= TextObject
, ButtonFrame
,
2120 MUIA_Background
, MUII_ButtonBack
,
2122 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
2123 MUIA_Text_Contents
, (IPTR
)(ncp
->ncp_Interface
? "\33c Save as Default " : "\33c Save Defaults "),
2125 Child
, (IPTR
)(ncp
->ncp_CloseObj
= TextObject
, ButtonFrame
,
2126 MUIA_Background
, MUII_ButtonBack
,
2128 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
2129 MUIA_Text_Contents
, (IPTR
)"\33c Use ",
2138 KPRINTF(10, ("Couldn't create application\n"));
2139 nGUITaskCleanup(ncp
);
2143 DoMethod(ncp
->ncp_MainWindow
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
2144 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
2145 DoMethod(ncp
->ncp_UseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
2146 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
2147 DoMethod(ncp
->ncp_SetDefaultObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
2148 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
2149 DoMethod(ncp
->ncp_CloseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
2150 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
2152 DoMethod(ncp
->ncp_AboutMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
2153 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_ABOUT
);
2154 DoMethod(ncp
->ncp_UseMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
2155 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
2156 DoMethod(ncp
->ncp_SetDefaultMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
2157 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
2158 DoMethod(ncp
->ncp_MUIPrefsMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
2159 ncp
->ncp_App
, 2, MUIM_Application_OpenConfigWindow
, 0);
2167 get(ncp
->ncp_App
, MUIA_Application_Iconified
, &iconify
);
2168 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, TRUE
);
2169 get(ncp
->ncp_MainWindow
, MUIA_Window_Open
, &isopen
);
2170 if(!(isopen
|| iconify
))
2172 nGUITaskCleanup(ncp
);
2178 retid
= DoMethod(ncp
->ncp_App
, MUIM_Application_NewInput
, &sigs
);
2182 case ID_STORE_CONFIG
:
2183 case MUIV_Application_ReturnID_Quit
:
2185 get(ncp
->ncp_UnitObj
, MUIA_String_Integer
, &ncp
->ncp_CDC
->cdc_DefaultUnit
);
2186 get(ncp
->ncp_MediaTypeObj
, MUIA_Cycle_Active
, &ncp
->ncp_CDC
->cdc_MediaType
);
2188 if(retid
== ID_DEF_CONFIG
)
2190 pic
= psdGetClsCfg(libname
);
2193 psdSetClsCfg(libname
, NULL
);
2194 pic
= psdGetClsCfg(libname
);
2198 psdAddCfgEntry(pic
, ncp
->ncp_CDC
);
2199 psdSaveCfgToDisk(NULL
, FALSE
);
2202 if(ncp
->ncp_Interface
)
2204 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
2207 psdSetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
, NULL
);
2208 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
2212 if(psdAddCfgEntry(pic
, ncp
->ncp_CDC
))
2214 if(retid
!= MUIV_Application_ReturnID_Quit
)
2216 psdSaveCfgToDisk(NULL
, FALSE
);
2218 retid
= MUIV_Application_ReturnID_Quit
;
2222 retid
= MUIV_Application_ReturnID_Quit
;
2228 MUI_RequestA(ncp
->ncp_App
, ncp
->ncp_MainWindow
, 0, NULL
, "Phat!", VERSION_STRING
, NULL
);
2231 if(retid
== MUIV_Application_ReturnID_Quit
)
2237 sigs
= Wait(sigs
|sigmask
|SIGBREAKF_CTRL_C
);
2238 if(sigs
& SIGBREAKF_CTRL_C
)
2244 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, FALSE
);
2246 nGUITaskCleanup(ncp
);
2252 /* /// "nGUITaskCleanup()" */
2253 void nGUITaskCleanup(struct NepClassEth
*ncp
)
2257 MUI_DisposeObject(ncp
->ncp_App
);
2258 ncp
->ncp_App
= NULL
;
2262 CloseLibrary(MUIMasterBase
);
2263 MUIMasterBase
= NULL
;
2267 CloseLibrary(IntuitionBase
);
2268 IntuitionBase
= NULL
;
2276 ncp
->ncp_GUIBinding
= NULL
;
2277 ncp
->ncp_GUITask
= NULL
;
2278 if(ncp
->ncp_ReadySigTask
)
2280 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
2282 --ncp
->ncp_ClsBase
->nh_Library
.lib_OpenCnt
;