revert between 56095 -> 55830 in arch
[AROS.git] / rom / usb / classes / asixeth / asixeth.class.c
blobaed0714020c122a845f78182a3b8f0c29e0267f1
1 /*
2 *----------------------------------------------------------------------------
3 * asixeth class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "asixeth.class.h"
12 /* /// "Lib Stuff" */
13 static const STRPTR libname = MOD_NAME_STRING;
15 static
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),
24 (APTR) -1,
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
38 if(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);
49 if(ncp->ncp_CDC)
51 nh->nh_DevBase->np_ClsBase = nh;
52 Forbid();
53 AddDevice((struct Device *) nh->nh_DevBase);
54 nh->nh_DevBase->np_Library.lib_OpenCnt++;
55 Permit();
56 ret = nh;
58 } else {
59 KPRINTF(20, ("failed to create usbparallel.device\n"));
61 if(!ret)
63 CloseLibrary(UtilityBase);
65 } else {
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));
76 nLoadClassConfig(nh);
77 return(TRUE);
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",
89 UtilityBase));
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);
97 FreeVec(ncp);
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"));
105 } else {
106 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
107 return(FALSE);
110 return(TRUE);
113 ADD2INITLIB(libInit, 0)
114 ADD2OPENLIB(libOpen, 0)
115 ADD2EXPUNGELIB(libExpunge, 0)
116 /* \\\ */
119 * ***********************************************************************
120 * * Library functions *
121 * ***********************************************************************
124 struct AutoBindData
126 UWORD abd_VendID;
127 UWORD abd_ProdID;
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
157 { 0, 0, 0 }
160 /* /// "usbAttemptDeviceBinding()" */
161 struct NepClassEth * usbAttemptDeviceBinding(struct NepEthBase *nh, struct PsdDevice *pd)
163 struct Library *ps;
164 struct AutoBindData *abd = ClassBinds;
165 IPTR prodid;
166 IPTR vendid;
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,
175 TAG_END);
176 CloseLibrary(ps);
177 while(abd->abd_VendID)
179 if((vendid == abd->abd_VendID) && (prodid == abd->abd_ProdID))
181 return(usbForceDeviceBinding(nh, pd));
183 abd++;
186 return(NULL);
188 /* \\\ */
190 /* /// "usbForceDeviceBinding()" */
191 struct NepClassEth * usbForceDeviceBinding(struct NepEthBase *nh, struct PsdDevice *pd)
193 struct Library *ps;
194 struct NepClassEth *ncp;
195 struct NepClassEth *tmpncp;
196 struct ClsDevCfg *cdc;
197 struct AutoBindData *abd = ClassBinds;
198 STRPTR devname;
199 STRPTR devidstr;
200 IPTR prodid;
201 IPTR vendid;
202 ULONG unitno;
203 BOOL unitfound;
204 UBYTE buf[64];
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,
217 TAG_END);
218 Forbid();
220 while(abd->abd_VendID)
222 if((vendid == abd->abd_VendID) && (prodid == abd->abd_ProdID))
224 patchflags = abd->abd_PatchFlags;
225 break;
227 abd++;
230 unitfound = FALSE;
231 unitno = (ULONG) -1;
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;
238 unitfound = TRUE;
239 break;
241 ncp = (struct NepClassEth *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
243 if(!unitfound)
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)))
249 Permit();
250 CloseLibrary(ps);
251 return(NULL);
253 ncp->ncp_CDC = cdc = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
254 if(!cdc)
256 Permit();
257 FreeVec(ncp);
258 CloseLibrary(ps);
259 return(NULL);
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)
290 unitno++;
291 tmpncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
292 } else {
293 tmpncp = (struct NepClassEth *) tmpncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
297 ncp->ncp_UnitNo = unitno;
298 Permit();
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);
308 if(ncp->ncp_Task)
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,
315 ncp->ncp_UnitNo);
317 CloseLibrary(ps);
318 return(ncp);
321 ncp->ncp_ReadySigTask = NULL;
322 //FreeSignal(ncp->ncp_ReadySignal);
323 /* Get rid of unit structure */
324 /*Forbid();
325 Remove((struct Node *) ncp);
326 FreeVec(ncp->ncp_CDC);
327 FreeVec(ncp);
328 Permit();*/
329 CloseLibrary(ps);
331 return(NULL);
333 /* \\\ */
335 /* /// "usbReleaseDeviceBinding()" */
336 void usbReleaseDeviceBinding(struct NepEthBase *nh, struct NepClassEth *ncp)
338 struct Library *ps;
339 STRPTR devname;
340 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp));
342 if((ps = OpenLibrary("poseidon.library", 4)))
344 Forbid();
345 ncp->ncp_ReadySignal = SIGB_SINGLE;
346 ncp->ncp_ReadySigTask = FindTask(NULL);
347 if(ncp->ncp_Task)
349 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
351 Permit();
352 while(ncp->ncp_Task)
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,
359 "A '%s' sucks.",
360 devname);
361 /*psdFreeVec(ncp);*/
362 CloseLibrary(ps);
365 /* \\\ */
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)
374 AROS_LIBFUNC_INIT
376 struct TagItem *ti;
377 LONG count = 0;
379 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
380 switch(type)
382 case UGA_CLASS:
383 if((ti = FindTagItem(UCCA_Priority, tags)))
385 *((SIPTR *) ti->ti_Data) = 0;
386 count++;
388 if((ti = FindTagItem(UCCA_Description, tags)))
390 *((STRPTR *) ti->ti_Data) = "Ethernet SANA driver for ASIX chipsets via usbasixeth.device";
391 count++;
393 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
395 *((IPTR *) ti->ti_Data) = TRUE;
396 count++;
398 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
400 *((IPTR *) ti->ti_Data) = TRUE;
401 count++;
403 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
405 *((IPTR *) ti->ti_Data) = FALSE;
406 count++;
408 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
410 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCP.ncp_UsingDefaultCfg;
411 count++;
413 break;
415 case UGA_BINDING:
416 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
418 *((IPTR *) ti->ti_Data) = ((struct NepClassEth *) usbstruct)->ncp_UsingDefaultCfg;
419 count++;
421 break;
423 return(count);
424 AROS_LIBFUNC_EXIT
426 /* \\\ */
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)
435 AROS_LIBFUNC_INIT
436 return(0);
437 AROS_LIBFUNC_EXIT
439 /* \\\ */
441 /* /// "usbDoMethodA()" */
442 AROS_LH2(IPTR, usbDoMethodA,
443 AROS_LHA(ULONG, methodid, D0),
444 AROS_LHA(IPTR *, methoddata, A1),
445 LIBBASETYPEPTR, nh, 7, nep)
447 AROS_LIBFUNC_INIT
449 struct NepClassEth *ncp;
451 KPRINTF(10, ("Do Method %ld\n", methodid));
452 switch(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]);
462 return(TRUE);
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);
472 Forbid();
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;
479 Permit();
480 return(TRUE);
482 default:
483 break;
485 return(0);
486 AROS_LIBFUNC_EXIT
488 /* \\\ */
490 /* /// "nLoadClassConfig()" */
491 BOOL nLoadClassConfig(struct NepEthBase *nh)
493 struct NepClassEth *ncp = &nh->nh_DummyNCP;
494 struct Library *ps;
495 struct ClsDevCfg *cdc;
496 struct PsdIFFContext *pic;
498 KPRINTF(10, ("Loading Class Config...\n"));
499 if(ncp->ncp_GUITask)
501 return(FALSE);
503 if(!(ps = OpenLibrary("poseidon.library", 4)))
505 return(FALSE);
508 Forbid();
509 /* Create default config */
510 cdc = ncp->ncp_CDC;
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);
518 if(pic)
520 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncp->ncp_CDC->cdc_ChunkID));
521 if(cdc)
523 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
524 psdFreeVec(cdc);
525 ncp->ncp_UsingDefaultCfg = FALSE;
528 Permit();
529 CloseLibrary(ps);
530 return(FALSE);
532 /* \\\ */
534 /* /// "nLoadBindingConfig()" */
535 BOOL nLoadBindingConfig(struct NepClassEth *ncp)
537 struct NepEthBase *nh = ncp->ncp_ClsBase;
538 struct Library *ps;
539 struct ClsDevCfg *cdc;
540 struct PsdIFFContext *pic;
542 KPRINTF(10, ("Loading Binding Config...\n"));
543 if(ncp->ncp_GUITask)
545 return(FALSE);
547 //nLoadClassConfig(nh);
548 *ncp->ncp_CDC = *nh->nh_DummyNCP.ncp_CDC;
549 ncp->ncp_UsingDefaultCfg = TRUE;
551 if(!(ps = OpenLibrary("poseidon.library", 4)))
553 return(FALSE);
556 Forbid();
557 /* Load config */
558 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
559 if(pic)
561 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncp->ncp_CDC->cdc_ChunkID));
562 if(cdc)
564 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
565 psdFreeVec(cdc);
566 ncp->ncp_UsingDefaultCfg = FALSE;
569 Permit();
570 CloseLibrary(ps);
571 return(FALSE);
573 /* \\\ */
575 /* /// "nOpenBindingCfgWindow()" */
576 LONG nOpenBindingCfgWindow(struct NepEthBase *nh, struct NepClassEth *ncp)
578 struct Library *ps;
579 KPRINTF(10, ("Opening GUI...\n"));
580 if(!(ps = OpenLibrary("poseidon.library", 4)))
582 return(FALSE);
584 Forbid();
585 if(!ncp->ncp_GUITask)
587 if((ncp->ncp_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", nGUITask, ncp)))
589 Permit();
590 CloseLibrary(ps);
591 return(TRUE);
594 Permit();
595 CloseLibrary(ps);
596 return(FALSE);
598 /* \\\ */
600 /**************************************************************************/
602 #undef ps
603 #define ps ncp->ncp_Base
605 static char *MediaTypeStrings[] =
607 "Auto negotiation",
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",
614 NULL
617 /* /// "nEthTask()" */
618 AROS_UFH0(void, nEthTask)
620 AROS_USERFUNC_INIT
622 struct NepClassEth *ncp;
623 struct PsdPipe *pp;
624 ULONG sigmask;
625 ULONG sigs;
626 LONG ioerr;
627 UBYTE *pktptr;
628 ULONG pktlen;
629 UWORD cnt;
630 LONG lastioerr = 0;
631 ULONG errcount = 0;
633 struct IOSana2Req *ioreq;
635 if((ncp = nAllocEth()))
637 Forbid();
638 if(ncp->ncp_ReadySigTask)
640 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
642 Permit();
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);
651 } else {
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);
672 nSetOnline(ncp);
675 /* Main task */
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);
696 if(ioerr)
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;
712 psdDelayMS(50);
714 ReplyMsg((struct Message *) ioreq);
715 ncp->ncp_WritePending[cnt] = NULL;
717 break;
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;
733 } else {
734 ncp->ncp_ReadPending = NULL;
736 if(ioerr)
738 if(lastioerr != ioerr)
740 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
741 "Eth receive failed: %s (%ld)",
742 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
743 errcount = 0;
744 } else {
745 errcount++;
746 if(errcount > 20)
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);
753 lastioerr = ioerr;
754 psdDelayMS(50);
755 break;
756 } else {
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);
773 /* Now configured */
774 ncp->ncp_StateFlags |= DDF_CONFIGURED;
775 if(!(ncp->ncp_StateFlags & DDF_ONLINE))
777 nSetOnline(ncp);
779 ReplyMsg((struct Message *) ioreq);
780 break;
782 case S2_ADDMULTICASTADDRESS:
783 case S2_DELMULTICASTADDRESS:
784 case S2_ADDMULTICASTADDRESSES:
785 case S2_DELMULTICASTADDRESSES:
786 nUpdateRXMode(ncp);
787 ReplyMsg((struct Message *) ioreq);
788 break;
790 case S2_ONLINE:
791 nSetOnline(ncp);
792 ReplyMsg((struct Message *) ioreq);
793 break;
795 case S2_OFFLINE:
796 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, BMCR_PDOWN);
797 ReplyMsg((struct Message *) ioreq);
798 break;
800 default:
801 ioreq->ios2_Req.io_Error = IOERR_NOCMD;
802 ReplyMsg((struct Message *) ioreq);
803 break;
806 Forbid();
807 while((!ncp->ncp_WritePending[ncp->ncp_WriteBufNum]) && ncp->ncp_WriteQueue.lh_Head->ln_Succ)
809 ioreq = (struct IOSana2Req *) RemHead(&ncp->ncp_WriteQueue);
810 Permit();
811 nWritePacket(ncp, ioreq);
812 Forbid();
814 Permit();
815 sigs = Wait(sigmask);
816 } while(!(sigs & SIGBREAKF_CTRL_C));
818 Forbid();
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;
841 /* Command queue */
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);
848 Permit();
850 nDoEvent(ncp, S2EVENT_OFFLINE);
852 KPRINTF(20, ("Going down the river!\n"));
853 nFreeEth(ncp);
856 AROS_USERFUNC_EXIT
858 /* \\\ */
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)))
872 Alert(AG_OpenLib);
873 break;
876 ncp->ncp_Interface = psdFindInterface(ncp->ncp_Device, NULL,
877 TAG_END);
879 if(!ncp->ncp_Interface)
881 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "No interface?");
882 break;
885 ncp->ncp_EPIn = psdFindEndpoint(ncp->ncp_Interface, NULL,
886 EA_IsIn, TRUE,
887 EA_TransferType, USEAF_BULK,
888 TAG_END);
889 ncp->ncp_EPOut = psdFindEndpoint(ncp->ncp_Interface, NULL,
890 EA_IsIn, FALSE,
891 EA_TransferType, USEAF_BULK,
892 TAG_END);
893 if(!(ncp->ncp_EPIn && ncp->ncp_EPOut))
895 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "IN or OUT endpoint missing!");
896 break;
899 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPOut,
900 EA_MaxPktSize, &ncp->ncp_EPOutMaxPktSize,
901 TAG_END);
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"));
909 break;
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,
930 TAG_END);
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,
938 TAG_END);
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,
946 TAG_END);
947 ncp->ncp_Task = thistask;
949 if(nInitASIX(ncp))
951 return(ncp);
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);
964 } while(FALSE);
965 if(ncp->ncp_ReadBuffer[0])
967 FreeVec(ncp->ncp_ReadBuffer[0]);
968 ncp->ncp_ReadBuffer[0] = NULL;
970 CloseLibrary(ncp->ncp_Base);
971 Forbid();
972 ncp->ncp_Task = NULL;
973 if(ncp->ncp_ReadySigTask)
975 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
977 return(NULL);
979 /* \\\ */
981 /* /// "nFreeEth()" */
982 void nFreeEth(struct NepClassEth *ncp)
984 struct IOSana2Req *ioreq;
985 Forbid();
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);
996 Permit();
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);
1011 Forbid();
1012 ncp->ncp_Task = NULL;
1013 if(ncp->ncp_ReadySigTask)
1015 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1018 /* \\\ */
1020 /* /// "nReadEEPROMMAC()" */
1021 BOOL nReadEEPROMMAC(struct NepClassEth *ncp, UBYTE *macptr)
1023 LONG ioerr;
1025 switch(ncp->ncp_PatchFlags & 0xf)
1027 case PF_AX88178:
1028 case PF_AX88772:
1029 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UAXR_READ_NODE_ID, 0, 0);
1030 break;
1032 default:
1033 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UAXR_READ_NODE_ID_2, 0, 0);
1034 break;
1036 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, macptr, 6);
1037 if(ioerr)
1039 KPRINTF(10, ("Couldn't read EEPROM %ld\n", ioerr));
1040 return(FALSE);
1042 return(TRUE);
1044 /* \\\ */
1046 /* /// "nReadPhyWord()" */
1047 LONG nReadPhyWord(struct NepClassEth *ncp, ULONG phyid, ULONG phyreg)
1049 UBYTE phyword[2];
1050 LONG ioerr;
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);
1054 if(ioerr)
1056 KPRINTF(10, ("Error obtaining PHY control %ld\n", ioerr));
1057 return(-1);
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);
1061 if(ioerr)
1063 KPRINTF(10, ("Could not read PHY %ld reg %ld, due to %ld)!\n", phyid, phyreg, ioerr));
1064 return(-1);
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);
1068 if(ioerr)
1070 KPRINTF(10, ("Error releasing PHY control %ld\n", ioerr));
1071 return(-1);
1074 return(phyword[0]|(phyword[1]<<8));
1076 /* \\\ */
1078 /* /// "nWritePhyWord()" */
1079 BOOL nWritePhyWord(struct NepClassEth *ncp, ULONG phyid, ULONG phyreg, ULONG value)
1081 UBYTE phyword[2];
1082 LONG ioerr;
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);
1085 if(ioerr)
1087 KPRINTF(10, ("Error obtaining PHY control %ld\n", ioerr));
1088 return(FALSE);
1091 phyword[0] = value;
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);
1096 if(ioerr)
1098 KPRINTF(10, ("Could not write PHY %ld reg %ld, due to %ld)!\n", phyid, phyreg, ioerr));
1099 return(FALSE);
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);
1103 if(ioerr)
1105 KPRINTF(10, ("Error releasing PHY control %ld\n", ioerr));
1106 return(FALSE);
1108 return(TRUE);
1110 /* \\\ */
1112 /* /// "nWriteRXCtrl()" */
1113 BOOL nWriteRXCtrl(struct NepClassEth *ncp, ULONG mode)
1115 LONG ioerr;
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);
1118 if(ioerr)
1120 KPRINTF(10, ("Error writing RX Ctrl %ld\n", ioerr));
1121 return(FALSE);
1123 return(TRUE);
1125 /* \\\ */
1127 /* /// "nWriteMediumMode()" */
1128 BOOL nWriteMediumMode(struct NepClassEth *ncp, ULONG mode)
1130 LONG ioerr;
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);
1133 if(ioerr)
1135 KPRINTF(10, ("Error writing Medium Mode %ld\n", ioerr));
1136 return(FALSE);
1138 return(TRUE);
1140 /* \\\ */
1142 /* /// "nSWReset()" */
1143 BOOL nSWReset(struct NepClassEth *ncp, ULONG mode)
1145 LONG ioerr;
1146 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UAXR_SW_RESET, mode, 0);
1147 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
1148 if(ioerr)
1150 KPRINTF(10, ("Error writing SW RESET %ld\n", ioerr));
1151 return(FALSE);
1153 psdDelayMS(150);
1154 return(TRUE);
1156 /* \\\ */
1158 /* /// "nWriteGPIOs()" */
1159 BOOL nWriteGPIOs(struct NepClassEth *ncp, ULONG value, ULONG delay)
1161 LONG ioerr;
1162 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UAXR_WRITE_GPIOS, value, 0);
1163 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
1164 if(ioerr)
1166 KPRINTF(10, ("Error writing GPIO %ld\n", ioerr));
1167 return(FALSE);
1169 psdDelayMS(delay);
1170 return(TRUE);
1172 /* \\\ */
1174 /* /// "nGetPhyAddr()" */
1175 UWORD nGetPhyAddr(struct NepClassEth *ncp)
1177 UBYTE phyid[2];
1178 LONG ioerr;
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);
1181 if(ioerr)
1183 KPRINTF(10, ("Error obtaining PHY ADDR %ld\n", ioerr));
1184 return(0);
1186 return(phyid[1]);
1188 /* \\\ */
1190 /* /// "nInitASIX()" */
1191 BOOL nInitASIX(struct NepClassEth *ncp)
1193 LONG data;
1194 LONG ioerr;
1195 UWORD embeddedphy;
1196 BOOL result = TRUE;
1197 UBYTE buf[2];
1199 switch(ncp->ncp_PatchFlags & 0xf)
1201 case PF_AX88178:
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);
1205 if(ioerr)
1207 KPRINTF(10, ("Error writing enable %ld\n", ioerr));
1208 return(FALSE);
1211 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UAXR_READ_EEPROM, 0x0017, 0);
1212 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, buf, 2);
1213 if(ioerr)
1215 KPRINTF(10, ("Error read eeprom %ld\n", ioerr));
1216 return(FALSE);
1219 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UAXR_WRITE_DISABLE, 0, 0);
1220 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
1221 if(ioerr)
1223 KPRINTF(10, ("Error writing disable %ld\n", ioerr));
1224 return(FALSE);
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);
1232 if(buf[1] != 0x01)
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);
1237 } else {
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);
1243 psdDelayMS(150);
1244 result &= nSWReset(ncp, AX_SWRESET_PRL|AX_SWRESET_IPPD);
1245 psdDelayMS(150);
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)
1254 ULONG reg;
1255 reg = nReadPhyWord(ncp, ncp->ncp_PhyID, MII_MARVELL_LED_CTRL);
1256 reg &= 0xf8ff;
1257 reg |= 0x0101;
1258 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_MARVELL_LED_CTRL, reg);
1261 psdDelayMS(60);
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);
1271 // RX Size == 2048
1272 break;
1274 case PF_AX88772:
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);
1283 if(ioerr)
1285 KPRINTF(10, ("Error selecting PHY %ld\n", ioerr));
1286 return(FALSE);
1288 result &= nSWReset(ncp, AX_SWRESET_IPPD|AX_SWRESET_PRL);
1289 psdDelayMS(150);
1290 result &= nSWReset(ncp, AX_SWRESET_CLEAR);
1291 psdDelayMS(150);
1292 result &= nSWReset(ncp, (ULONG) (embeddedphy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE));
1293 psdDelayMS(150);
1294 result &= nWriteRXCtrl(ncp, 0x0000);
1296 ncp->ncp_PhyID = nGetPhyAddr(ncp);
1298 result &= nSWReset(ncp, AX_SWRESET_PRL);
1299 psdDelayMS(150);
1300 result &= nSWReset(ncp, AX_SWRESET_IPRL|AX_SWRESET_PRL);
1301 psdDelayMS(150);
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);
1310 if(ioerr)
1312 KPRINTF(10, ("Error writing IPG0-2 %ld\n", ioerr));
1313 return(FALSE);
1316 result &= nWriteRXCtrl(ncp, AX_DEFAULT_RX_CTL);
1317 // RX Size == 2048
1319 break;
1321 default: // AX88172
1322 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "This adapter uses the AX88172 chipset.");
1323 data = 0x130103;
1324 if(ncp->ncp_PatchFlags & PF_DLINKGPIO)
1326 data = 0x9f9d9f;
1328 if(ncp->ncp_PatchFlags & PF_HAWKINGGPIO)
1330 data = 0x1f1d1f;
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);
1342 break;
1344 if(!result)
1346 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname, "Failed to initialize adapter!");
1349 return(result);
1351 /* \\\ */
1353 /* /// "nUpdateRXMode()" */
1354 void nUpdateRXMode(struct NepClassEth *ncp)
1356 ULONG rxmode;
1357 LONG ioerr;
1358 switch(ncp->ncp_PatchFlags & 0xf)
1360 case PF_AX88178:
1361 case PF_AX88772:
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;
1371 break;
1373 default:
1374 rxmode = 0x8c;
1375 if(ncp->ncp_OpenFlags & SANA2OPF_PROM)
1377 rxmode |= 0x01;
1379 if(ncp->ncp_Multicasts.lh_Head->ln_Succ)
1381 rxmode |= 0x10;
1383 break;
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);
1389 if(ioerr)
1391 KPRINTF(10, ("Error writing multicast filter %ld\n", ioerr));
1394 nWriteRXCtrl(ncp, rxmode);
1396 /* \\\ */
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,
1431 /* \\\ */
1433 /* /// "nSetOnline()" */
1434 void nSetOnline(struct NepClassEth *ncp)
1436 LONG data;
1437 LONG data2;
1438 ULONG bmcr;
1439 BOOL autoneg = FALSE;
1440 BOOL linkgood = FALSE;
1441 UWORD timeout = 60;
1442 ULONG mediummode;
1443 UWORD *mediatable;
1445 switch(ncp->ncp_PatchFlags & 0xf)
1447 case PF_AX88178:
1448 mediatable = nAX88178Speeds;
1449 break;
1451 case PF_AX88772:
1452 mediatable = nAX88772Speeds;
1453 break;
1455 default:
1456 mediatable = nAX88172Speeds;
1457 break;
1459 mediummode = mediatable[ncp->ncp_CDC->cdc_MediaType];
1461 switch(ncp->ncp_CDC->cdc_MediaType)
1463 case MT_AUTO:
1464 KPRINTF(10, ("Autonegotiaton!\n"));
1465 bmcr = BMCR_ANENABLE|BMCR_ANRESTART;
1466 autoneg = TRUE;
1467 break;
1469 case MT_10BASE_T_HALF_DUP:
1470 bmcr = 0;
1471 //mediummode = 0;
1472 break;
1474 case MT_10BASE_T_FULL_DUP:
1475 bmcr = BMCR_FULLDPLX;
1476 break;
1478 case MT_100BASE_TX_HALF_DUP:
1479 bmcr = BMCR_SPEED1000;
1480 break;
1482 case MT_1000BASE_TX_HALF_DUP:
1483 bmcr = BMCR_SPEED100;
1484 break;
1486 case MT_1000BASE_TX_FULL_DUP:
1487 bmcr = BMCR_SPEED1000|BMCR_FULLDPLX;
1488 break;
1490 case MT_100BASE_TX_FULL_DUP:
1491 default:
1492 bmcr = BMCR_SPEED100|BMCR_FULLDPLX;
1493 mediummode = mediatable[MT_100BASE_TX_FULL_DUP];
1494 break;
1497 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, bmcr);
1498 while(--timeout)
1500 psdDelayMS(50);
1501 data = nReadPhyWord(ncp, ncp->ncp_PhyID, MII_BMSR);
1502 KPRINTF(10, ("Status: %04lx\n", data));
1503 if(data < 0)
1505 timeout = 0;
1506 break;
1509 linkgood = (data & BMSR_LSTATUS);
1510 if((!autoneg) && linkgood)
1512 // no need to wait for autonegotiation
1513 break;
1516 // complete?
1517 if(data & BMSR_ANEGCOMPLETE)
1519 break;
1523 if(autoneg)
1525 STRPTR negstr = NULL;
1526 if(timeout)
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));
1531 if(data < 0)
1533 timeout = 0;
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];
1549 if(!negstr)
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];
1574 } else {
1575 timeout = 0;
1579 if(!timeout)
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];
1585 } else {
1586 psdAddErrorMsg(RETURN_OK, (STRPTR) libname, "Autonegotiation: Using %s.", negstr);
1589 if(!linkgood)
1591 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "No link, check the plug and cable.");
1594 nWriteMediumMode(ncp, mediummode);
1595 nUpdateRXMode(ncp);
1597 /* Now online */
1598 ncp->ncp_StateFlags |= DDF_ONLINE;
1599 ncp->ncp_StateFlags &= ~DDF_OFFLINE;
1600 /* Trigger any ONLINE events */
1601 nDoEvent(ncp, S2EVENT_ONLINE);
1603 /* \\\ */
1605 /* /// "nDoEvent()" */
1606 void nDoEvent(struct NepClassEth *ncp, ULONG events)
1608 struct IOSana2Req *worknode, *nextnode;
1610 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events));
1612 Forbid();
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;
1626 Permit();
1628 /* \\\ */
1630 /* /// "support routines" */
1631 static
1632 inline void *callcopy(void *routine,
1633 void *from,
1634 void *to,
1635 ULONG len)
1637 void * (*call) (APTR, APTR, ULONG) = routine;
1639 return (*call) (from, to, len);
1642 #define callfilter CallHookPkt
1643 /* \\\ */
1645 /* /// "nWritePacket()" */
1646 BOOL nWritePacket(struct NepClassEth *ncp, struct IOSana2Req *ioreq)
1648 ULONG packettype;
1649 struct EtherPacketHeader *eph;
1650 UBYTE *copydest;
1651 UWORD writelen;
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];
1664 copydest = buf + 4;
1665 } else {
1666 eph = (struct EtherPacketHeader *) buf;
1667 copydest = buf;
1670 /* Not a raw packet? */
1671 if(!(ioreq->ios2_Req.io_Flags & SANA2IOF_RAW))
1673 UWORD cnt;
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;
1705 return FALSE;
1708 if(ncp->ncp_PatchFlags & (PF_AX88178|PF_AX88772))
1710 buf[0] = writelen;
1711 buf[1] = writelen>>8;
1712 buf[2] = ~buf[0];
1713 buf[3] = ~buf[1];
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;
1720 writelen += 4;
1721 } else {
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));
1749 } else {
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);
1760 if(stats)
1762 stats->PacketsSent++;
1763 stats->BytesSent += writelen;
1765 ncp->ncp_DeviceStats.PacketsSent++;
1767 return TRUE;
1769 /* \\\ */
1771 /* /// "nReadIOReq()" */
1772 UWORD nReadIOReq(struct NepClassEth *ncp, struct EtherPacketHeader *eph, UWORD datasize, struct IOSana2Req *ioreq, UWORD flags)
1774 LIBBASETYPEPTR nh = ncp->ncp_ClsBase;
1775 UBYTE *copyfrom;
1776 UWORD cnt;
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;
1786 } else {
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,
1802 ioreq, copyfrom)))
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));
1807 return flags;
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;
1822 } else {
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",
1833 ioreq,
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 */
1844 flags &= ~DROPPED;
1845 } else {
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);
1851 /* Set error code.
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 */
1860 Forbid();
1861 Remove((struct Node *) ioreq);
1862 Permit();
1863 ReplyMsg((struct Message *) ioreq);
1864 return flags;
1866 /* \\\ */
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;
1875 UWORD flags;
1876 UWORD datasize;
1877 UWORD pktlen;
1878 BOOL ret = FALSE;
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))
1887 if(len < 4)
1889 ncp->ncp_DeviceStats.BadData++;
1890 return FALSE;
1892 if((pktptr[0] + pktptr[2] != 0xff) || (pktptr[1] + pktptr[3] != 0xff))
1894 ncp->ncp_DeviceStats.BadData++;
1895 KPRINTF(20, ("InverseLength mismatch\n"));
1896 return FALSE;
1898 pktlen = *pktptr++;
1899 pktlen |= (*pktptr++)<<8;
1900 pktptr += 2;
1901 len -= 4;
1902 if(len < ((pktlen + 1) & ~1))
1904 KPRINTF(20, ("Pktlen %ld < len %ld\n", pktlen, len));
1905 return FALSE;
1907 } else {
1908 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 */
1923 if(stats)
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). */
1932 Forbid();
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 */
1946 break;
1948 worknode = nextnode;
1950 bufman = (struct BufMan *) (((struct Node *) bufman)->ln_Succ);
1952 Permit();
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. */
1955 if(flags & DROPPED)
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
1961 time!
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 */
1968 Forbid();
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;
1975 Permit();
1976 } else {
1977 /* Packet not dropped - return ok */
1978 ret = TRUE;
1979 continue;
1981 } else {
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. */
1989 if(stats)
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
2001 break;
2004 return ret;
2006 /* \\\ */
2008 /**************************************************************************/
2010 /* /// "nGUITask()" */
2011 AROS_UFH0(void, nGUITask)
2013 AROS_USERFUNC_INIT
2015 struct Task *thistask;
2016 struct NepEthBase *nh;
2017 struct NepClassEth *ncp;
2018 struct PsdIFFContext *pic;
2020 thistask = FindTask(NULL);
2021 #undef ps
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);
2036 return;
2039 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
2041 KPRINTF(10, ("Couldn't open intuition.library.\n"));
2042 nGUITaskCleanup(ncp);
2043 return;
2045 if(!(ps = OpenLibrary("poseidon.library", 4)))
2047 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
2048 nGUITaskCleanup(ncp);
2049 return;
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)"?",
2065 End),
2066 End,
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",
2071 End),
2072 Child, (IPTR)(ncp->ncp_SetDefaultMI = MenuitemObject,
2073 MUIA_Menuitem_Title, (IPTR)"Set as Default",
2074 MUIA_Menuitem_Shortcut, (IPTR)"D",
2075 End),
2076 Child, (IPTR)(MenuitemObject,
2077 MUIA_Menuitem_Title, (IPTR)NM_BARLABEL,
2078 End),
2079 Child, (IPTR)(ncp->ncp_MUIPrefsMI = MenuitemObject,
2080 MUIA_Menuitem_Title, (IPTR)"MUI Settings",
2081 MUIA_Menuitem_Shortcut, (IPTR)"M",
2082 End),
2083 End,
2084 End,
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")),
2093 //Child, HSpace(0),
2094 Child, (IPTR)Label((IPTR) "Media Type:"),
2095 Child, (IPTR)(ncp->ncp_MediaTypeObj = CycleObject,
2096 MUIA_CycleChain, 1,
2097 MUIA_Cycle_Entries, (IPTR)MediaTypeStrings,
2098 MUIA_Cycle_Active, ncp->ncp_CDC->cdc_MediaType,
2099 End),
2100 Child, (IPTR)Label((IPTR) "Default " DEVNAME " Unit:"),
2101 Child, (IPTR)(ncp->ncp_UnitObj = StringObject,
2102 StringFrame,
2103 MUIA_CycleChain, 1,
2104 MUIA_String_AdvanceOnCR, TRUE,
2105 MUIA_String_Integer, ncp->ncp_CDC->cdc_DefaultUnit,
2106 MUIA_String_Accept, (IPTR)"0123456789",
2107 End),
2108 End,
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,
2115 MUIA_CycleChain, 1,
2116 MUIA_InputMode, MUIV_InputMode_RelVerify,
2117 MUIA_Text_Contents, (IPTR)"\33c Save ",
2118 End),
2119 Child, (IPTR)(ncp->ncp_SetDefaultObj = TextObject, ButtonFrame,
2120 MUIA_Background, MUII_ButtonBack,
2121 MUIA_CycleChain, 1,
2122 MUIA_InputMode, MUIV_InputMode_RelVerify,
2123 MUIA_Text_Contents, (IPTR)(ncp->ncp_Interface ? "\33c Save as Default " : "\33c Save Defaults "),
2124 End),
2125 Child, (IPTR)(ncp->ncp_CloseObj = TextObject, ButtonFrame,
2126 MUIA_Background, MUII_ButtonBack,
2127 MUIA_CycleChain, 1,
2128 MUIA_InputMode, MUIV_InputMode_RelVerify,
2129 MUIA_Text_Contents, (IPTR)"\33c Use ",
2130 End),
2131 End,
2132 End,
2133 End),
2134 End;
2136 if(!ncp->ncp_App)
2138 KPRINTF(10, ("Couldn't create application\n"));
2139 nGUITaskCleanup(ncp);
2140 return;
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);
2161 IPTR isopen = 0;
2162 IPTR iconify = 0;
2163 ULONG sigs;
2164 ULONG sigmask;
2165 LONG retid;
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);
2173 return;
2175 sigmask = 0;
2178 retid = DoMethod(ncp->ncp_App, MUIM_Application_NewInput, &sigs);
2179 switch(retid)
2181 case ID_DEF_CONFIG:
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);
2191 if(!pic)
2193 psdSetClsCfg(libname, NULL);
2194 pic = psdGetClsCfg(libname);
2196 if(pic)
2198 psdAddCfgEntry(pic, ncp->ncp_CDC);
2199 psdSaveCfgToDisk(NULL, FALSE);
2202 if(ncp->ncp_Interface)
2204 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
2205 if(!pic)
2207 psdSetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL, NULL);
2208 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
2210 if(pic)
2212 if(psdAddCfgEntry(pic, ncp->ncp_CDC))
2214 if(retid != MUIV_Application_ReturnID_Quit)
2216 psdSaveCfgToDisk(NULL, FALSE);
2218 retid = MUIV_Application_ReturnID_Quit;
2221 } else {
2222 retid = MUIV_Application_ReturnID_Quit;
2224 break;
2227 case ID_ABOUT:
2228 MUI_RequestA(ncp->ncp_App, ncp->ncp_MainWindow, 0, NULL, "Phat!", VERSION_STRING, NULL);
2229 break;
2231 if(retid == MUIV_Application_ReturnID_Quit)
2233 break;
2235 if(sigs)
2237 sigs = Wait(sigs|sigmask|SIGBREAKF_CTRL_C);
2238 if(sigs & SIGBREAKF_CTRL_C)
2240 break;
2243 } while(TRUE);
2244 set(ncp->ncp_MainWindow, MUIA_Window_Open, FALSE);
2246 nGUITaskCleanup(ncp);
2248 AROS_USERFUNC_EXIT
2250 /* \\\ */
2252 /* /// "nGUITaskCleanup()" */
2253 void nGUITaskCleanup(struct NepClassEth *ncp)
2255 if(ncp->ncp_App)
2257 MUI_DisposeObject(ncp->ncp_App);
2258 ncp->ncp_App = NULL;
2260 if(MUIMasterBase)
2262 CloseLibrary(MUIMasterBase);
2263 MUIMasterBase = NULL;
2265 if(IntuitionBase)
2267 CloseLibrary(IntuitionBase);
2268 IntuitionBase = NULL;
2270 if(ps)
2272 CloseLibrary(ps);
2273 ps = NULL;
2275 Forbid();
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;
2284 /* \\\ */