revert commit 56204.
[AROS.git] / rom / usb / classes / pegasuseth / pegasus.class.c
blobfa39781e7631419933058837ccf555c429a4c2bb
1 /*
2 *----------------------------------------------------------------------------
3 * pegasus class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "pegasus.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! pegasus.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 { VENDOR_MELCO , 0x0001, 0 }, // MELCO/BUFFALO LUA-TX
134 { VENDOR_ELCON , 0x0002, PF_PEG2|PF_PNA }, // GOLDPFEIL USB Adapter
135 { VENDOR_SMARTBRIDGES, 0x0003, PF_PEG2 }, // smartNIC 2 PnP Adapter
136 { VENDOR_COREGA , 0x0004, 0 }, // Corega FEter USB-TX
137 { VENDOR_MELCO , 0x0005, 0 }, // MELCO/BUFFALO LUA-TX
138 { VENDOR_MELCO , 0x0009, PF_PEG2 }, // MELCO/BUFFALO LUA2-TX
139 { VENDOR_KINGSTON , 0x000a, 0 }, // Kingston KNU101TX Ethernet
140 { VENDOR_COREGA , 0x000d, PF_PEG2 }, // Corega FEter USB-TXS
141 { VENDOR_MICROSOFT , 0x007a, PF_PEG2 }, // Microsoft MN-110
142 { VENDOR_OCT , 0x0109, PF_PEG2 }, // OCT Inc.
143 { VENDOR_BELKIN , 0x0121, PF_PEG2 }, // Belkin F5D5050 USB Ethernet
144 { VENDOR_SMC , 0x0200, 0 }, // SMC 202 USB Ethernet
145 { VENDOR_SMC , 0x0201, PF_PEG2 }, // SMC 2206 USB Ethernet
146 { VENDOR_MOBILITY , 0x0304, 0 }, // EasiDock Ethernet
147 { VENDOR_ADMTEK , 0x07c2, PF_PEG2 }, // ADKtek AN986A USB MAC
148 { VENDOR_LINKSYS2 , 0x08b4, 0 }, // Linksys USBVPN1
149 { VENDOR_OCT , 0x0901, PF_PEG2 }, // OCT Inc.
150 { VENDOR_IODATA , 0x0904, 0 }, // IO DATA USB ET/TX
151 { VENDOR_IODATA , 0x0913, PF_PEG2 }, // IO DATA USB ET/TX-S
152 { VENDOR_BILLIONTON , 0x0986, 0 }, // Billionton USB-100
153 { VENDOR_BILLIONTON , 0x0987, PF_PNA }, // Billionton USBLP-100
154 { VENDOR_BILLIONTON , 0x0988, 0 }, // Billionton USBEL-100
155 { VENDOR_SIEMENS , 0x1001, PF_PEG2 }, // SpeedStream USB 10/100 Ethernet
156 { VENDOR_NETGEAR , 0x1020, PF_PEG2 }, // NETGEAR FA101
157 { VENDOR_ACCTON , 0x1046, 0 }, // Accton USB 10/100 Ethernet Adapter
158 { VENDOR_ABOCOM , 0x110c, PF_PEG2|PF_PNA }, // USB HPNA/Ethernet
159 { VENDOR_AEILAB , 0x1701, PF_PEG2 }, // AEI USB Fast Ethernet Adapter
160 { VENDOR_ATEN , 0x2007, PF_PEG2 }, // ATEN USB Ethernet UC-110T
161 { VENDOR_DLINK , 0x200c, PF_PEG2 }, // D-Link DSB-650TX
162 { VENDOR_LANEED , 0x200c, PF_PEG2 }, // LANEED USB Ethernet LD-USB/TX
163 { VENDOR_ABOCOM , 0x200c, PF_PEG2 }, // USB 10/100 Fast Ethernet
164 { VENDOR_LINKSYS , 0x200c, PF_PEG2 }, // Linksys USB10TX
165 { VENDOR_LINKSYS , 0x2202, 0 }, // Linksys USB10TX
166 { VENDOR_LINKSYS , 0x2203, 0 }, // Linksys USB100TX
167 { VENDOR_LINKSYS , 0x2204, PF_PNA }, // Linksys USB100TX
168 { VENDOR_LINKSYS , 0x2206, PF_PEG2 }, // Linksys USB10T Ethernet Adapter
169 { VENDOR_ELSA , 0x3000, 0 }, // Elsa Micolink USB2Ethernet
170 { VENDOR_DLINK , 0x4001, 0 }, // D-Link DSB-650TX
171 { VENDOR_DLINK , 0x4002, 0 }, // D-Link DSB-650TX
172 { VENDOR_LANEED , 0x4002, 0 }, // LANEED USB Ethernet LD-USB/TX
173 { VENDOR_ABOCOM , 0x4002, 0 }, // USB 10/100 Fast Ethernet
174 { VENDOR_DLINK , 0x4003, PF_PNA }, // D-Link DSB-650TX (PNA)
175 { VENDOR_ABOCOM , 0x4004, PF_PNA }, // USB HPNA/Ethernet
176 { VENDOR_LANEED , 0x4005, PF_PEG2 }, // LANEED USB Ethernet LD-USBL/TX
177 { VENDOR_ABOCOM , 0x4007, PF_PNA }, // USB HPNA/Ethernet
178 { VENDOR_DLINK , 0x400b, PF_PEG2 }, // D-Link DSB-650TX
179 { VENDOR_LANEED , 0x400b, PF_PEG2 }, // LANEED USB Ethernet LD-USB/TX
180 { VENDOR_LINKSYS , 0x400b, PF_PEG2 }, // Linksys USB100TX
181 { VENDOR_ABOCOM , 0x400b, PF_PEG2 }, // USB 10/100 Fast Ethernet
182 { VENDOR_HAWKING , 0x400c, PF_PEG2 }, // Hawking UF100 10/100 Ethernet
183 { VENDOR_ABOCOM , 0x400c, PF_PEG2 }, // USB 10/100 Fast Ethernet
184 { VENDOR_ELECOM , 0x4010, PF_PEG2 }, // ELECOM USB Ethernet LD-USB20
185 { VENDOR_DLINK , 0x4102, PF_PEG2 }, // D-Link DSB-650TX
186 { VENDOR_ABOCOM , 0x4102, PF_PEG2 }, // USB 10/100 Fast Ethernet
187 { VENDOR_ABOCOM , 0x4104, PF_PNA }, // USB HPNA/Ethernet
188 { VENDOR_3COM , 0x4601, PF_PEG2 }, // 3Com USB Ethernet 3C460B
189 { VENDOR_ACCTON , 0x5046, PF_PEG2 }, // SpeedStream USB 10/100 Ethernet
190 { VENDOR_GIGABYTE , 0x8002, 0 }, // GIGABYTE GN-BR402W Wireless Router
191 { VENDOR_HP , 0x811c, PF_PEG2 }, // HP hn210c Ethernet USB
192 { VENDOR_BILLIONTON , 0x8511, PF_PEG2 }, // Billionton USBE-100
193 { VENDOR_COMPAQ , 0x8511, PF_PEG2 }, // iPAQ Networking 10/100 USB
194 { VENDOR_ADMTEK , 0x8511, PF_PEG2|PF_PNA }, // ADMtek ADM8511 'Pegasus II' USB Ethernet
195 { VENDOR_ADMTEK , 0x8513, PF_PEG2 }, // ADMtek ADM8513 'Pegasus II' USB Ethernet
196 { VENDOR_ADMTEK , 0x8515, PF_PEG2 }, // ADMtek ADM8515 'Pegasus II' USB-2.0 Ethernet
197 { VENDOR_SOHOWARE , 0x9100, PF_PEG2 }, // SOHOware NUB100 Ethernet
198 { VENDOR_SOHOWARE , 0x9110, PF_PEG2 }, // SOHOware NUB110 Ethernet
199 { VENDOR_DLINK , 0xabc1, 0 }, // D-Link DSB-650
200 { VENDOR_LANEED , 0xabc1, 0 }, // LANEED USB Ethernet LD-USB/T
201 { VENDOR_ABOCOM , 0xabc1, 0 }, // USB 10/100 Fast Ethernet
202 { VENDOR_ACCTON , 0xb004, PF_PEG2 }, // Philips USB 10/100 Ethernet
203 { VENDOR_ALLIEDTEL , 0xb100, PF_PEG2 }, // Allied Telesyn Int. AT-USB100
204 { 0, 0, 0 }
207 /* /// "usbAttemptDeviceBinding()" */
208 struct NepClassEth * usbAttemptDeviceBinding(struct NepEthBase *nh, struct PsdDevice *pd)
210 struct Library *ps;
211 struct AutoBindData *abd = ClassBinds;
212 IPTR prodid;
213 IPTR vendid;
215 KPRINTF(1, ("nepEthAttemptDeviceBinding(%08lx)\n", pd));
217 if((ps = OpenLibrary("poseidon.library", 4)))
219 psdGetAttrs(PGA_DEVICE, pd,
220 DA_VendorID, &vendid,
221 DA_ProductID, &prodid,
222 TAG_END);
223 CloseLibrary(ps);
224 while(abd->abd_VendID)
226 if((vendid == abd->abd_VendID) && (prodid == abd->abd_ProdID))
228 return(usbForceDeviceBinding(nh, pd));
230 abd++;
233 return(NULL);
235 /* \\\ */
237 /* /// "usbForceDeviceBinding()" */
238 struct NepClassEth * usbForceDeviceBinding(struct NepEthBase *nh, struct PsdDevice *pd)
240 struct Library *ps;
241 struct NepClassEth *ncp;
242 struct NepClassEth *tmpncp;
243 struct ClsDevCfg *cdc;
244 struct AutoBindData *abd = ClassBinds;
245 STRPTR devname;
246 STRPTR devidstr;
247 IPTR prodid;
248 IPTR vendid;
249 ULONG unitno;
250 BOOL unitfound;
251 UBYTE buf[64];
252 UWORD patchflags = PF_PEG2;
253 struct Task *tmptask;
255 KPRINTF(1, ("nepEthForceDeviceBinding(%08lx)\n", pd));
257 if((ps = OpenLibrary("poseidon.library", 4)))
259 psdGetAttrs(PGA_DEVICE, pd,
260 DA_ProductID, &prodid,
261 DA_VendorID, &vendid,
262 DA_ProductName, &devname,
263 DA_IDString, &devidstr,
264 TAG_END);
265 Forbid();
267 while(abd->abd_VendID)
269 if((vendid == abd->abd_VendID) && (prodid == abd->abd_ProdID))
271 patchflags = abd->abd_PatchFlags;
272 break;
274 abd++;
277 unitfound = FALSE;
278 unitno = (ULONG) -1;
279 ncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
280 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
282 if(!strcmp(ncp->ncp_DevIDString, devidstr))
284 unitno = ncp->ncp_UnitNo;
285 unitfound = TRUE;
286 break;
288 ncp = (struct NepClassEth *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
290 if(!unitfound)
292 /* as units are freed in the expunge-vector, the memory is
293 outside the scope of the poseidon library */
294 if(!(ncp = AllocVec(sizeof(struct NepClassEth), MEMF_PUBLIC|MEMF_CLEAR)))
296 Permit();
297 CloseLibrary(ps);
298 return(NULL);
300 ncp->ncp_CDC = cdc = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
301 if(!cdc)
303 Permit();
304 FreeVec(ncp);
305 CloseLibrary(ps);
306 return(NULL);
308 /* IORequests may be queued even if the task is gone. */
309 ncp->ncp_UnitNo = (ULONG) -1;
310 NewList(&ncp->ncp_Unit.unit_MsgPort.mp_MsgList);
311 NewList(&ncp->ncp_OrphanQueue);
312 NewList(&ncp->ncp_WriteQueue);
313 NewList(&ncp->ncp_BufManList);
314 NewList(&ncp->ncp_EventList);
315 NewList(&ncp->ncp_TrackList);
316 NewList(&ncp->ncp_Multicasts);
317 strncpy(ncp->ncp_DevIDString, devidstr, 127);
318 AddTail(&nh->nh_Units, &ncp->ncp_Unit.unit_MsgPort.mp_Node);
319 ncp->ncp_PatchFlags = patchflags;
321 ncp->ncp_ClsBase = nh;
322 ncp->ncp_Device = pd;
323 ncp->ncp_UnitProdID = prodid;
324 ncp->ncp_UnitVendorID = vendid;
326 nLoadBindingConfig(ncp);
328 /* Find next free unit number */
329 if(unitno == (ULONG) -1)
331 unitno = ncp->ncp_CDC->cdc_DefaultUnit;
332 tmpncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
333 while(tmpncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
335 if(tmpncp->ncp_UnitNo == unitno)
337 unitno++;
338 tmpncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
339 } else {
340 tmpncp = (struct NepClassEth *) tmpncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
344 ncp->ncp_UnitNo = unitno;
345 Permit();
347 psdSafeRawDoFmt(buf, 64, "pegasus.class<%08lx>", ncp);
348 ncp->ncp_ReadySignal = SIGB_SINGLE;
349 ncp->ncp_ReadySigTask = FindTask(NULL);
350 SetSignal(0, SIGF_SINGLE);
351 if((tmptask = psdSpawnSubTask(buf, nEthTask, ncp)))
353 psdBorrowLocksWait(tmptask, 1UL<<ncp->ncp_ReadySignal);
354 if(ncp->ncp_Task)
356 ncp->ncp_ReadySigTask = NULL;
357 //FreeSignal(ncp->ncp_ReadySignal);
358 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
359 "Ethereal abduction by '%s' on %s unit %ld!",
360 devname, nh->nh_DevBase->np_Library.lib_Node.ln_Name,
361 ncp->ncp_UnitNo);
363 CloseLibrary(ps);
364 return(ncp);
367 ncp->ncp_ReadySigTask = NULL;
368 //FreeSignal(ncp->ncp_ReadySignal);
369 /* Get rid of unit structure */
370 /*Forbid();
371 Remove((struct Node *) ncp);
372 FreeVec(ncp->ncp_CDC);
373 FreeVec(ncp);
374 Permit();*/
375 CloseLibrary(ps);
377 return(NULL);
379 /* \\\ */
381 /* /// "usbReleaseDeviceBinding()" */
382 void usbReleaseDeviceBinding(struct NepEthBase *nh, struct NepClassEth *ncp)
384 struct Library *ps;
385 STRPTR devname;
386 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp));
388 if((ps = OpenLibrary("poseidon.library", 4)))
390 Forbid();
391 ncp->ncp_ReadySignal = SIGB_SINGLE;
392 ncp->ncp_ReadySigTask = FindTask(NULL);
393 if(ncp->ncp_Task)
395 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
397 Permit();
398 while(ncp->ncp_Task)
400 Wait(1L<<ncp->ncp_ReadySignal);
402 //FreeSignal(ncp->ncp_ReadySignal);
403 psdGetAttrs(PGA_DEVICE, ncp->ncp_Device, DA_ProductName, &devname, TAG_END);
404 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
405 "Pegasus '%s' returned to the stars.",
406 devname);
407 /*psdFreeVec(ncp);*/
408 CloseLibrary(ps);
411 /* \\\ */
413 /* /// "usbGetAttrsA()" */
414 AROS_LH3(LONG, usbGetAttrsA,
415 AROS_LHA(ULONG, type, D0),
416 AROS_LHA(APTR, usbstruct, A0),
417 AROS_LHA(struct TagItem *, tags, A1),
418 LIBBASETYPEPTR, nh, 5, nep)
420 AROS_LIBFUNC_INIT
422 struct TagItem *ti;
423 LONG count = 0;
425 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
426 switch(type)
428 case UGA_CLASS:
429 if((ti = FindTagItem(UCCA_Priority, tags)))
431 *((SIPTR *) ti->ti_Data) = 0;
432 count++;
434 if((ti = FindTagItem(UCCA_Description, tags)))
436 *((STRPTR *) ti->ti_Data) = "Ethernet SANA driver for Pegasus chipsets via usbpegasus.device";
437 count++;
439 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
441 *((IPTR *) ti->ti_Data) = TRUE;
442 count++;
444 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
446 *((IPTR *) ti->ti_Data) = TRUE;
447 count++;
449 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
451 *((IPTR *) ti->ti_Data) = FALSE;
452 count++;
454 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
456 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCP.ncp_UsingDefaultCfg;
457 count++;
459 break;
461 case UGA_BINDING:
462 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
464 *((IPTR *) ti->ti_Data) = ((struct NepClassEth *) usbstruct)->ncp_UsingDefaultCfg;
465 count++;
467 break;
469 return(count);
470 AROS_LIBFUNC_EXIT
472 /* \\\ */
474 /* /// "usbSetAttrsA()" */
475 AROS_LH3(LONG, usbSetAttrsA,
476 AROS_LHA(ULONG, type, D0),
477 AROS_LHA(APTR, usbstruct, A0),
478 AROS_LHA(struct TagItem *, tags, A1),
479 LIBBASETYPEPTR, nh, 6, nep)
481 AROS_LIBFUNC_INIT
482 return(0);
483 AROS_LIBFUNC_EXIT
485 /* \\\ */
487 /* /// "usbDoMethodA()" */
488 AROS_LH2(IPTR, usbDoMethodA,
489 AROS_LHA(ULONG, methodid, D0),
490 AROS_LHA(IPTR *, methoddata, A1),
491 LIBBASETYPEPTR, nh, 7, nep)
493 AROS_LIBFUNC_INIT
495 struct NepClassEth *ncp;
497 KPRINTF(10, ("Do Method %ld\n", methodid));
498 switch(methodid)
500 case UCM_AttemptDeviceBinding:
501 return((IPTR) usbAttemptDeviceBinding(nh, (struct PsdDevice *) methoddata[0]));
503 case UCM_ForceDeviceBinding:
504 return((IPTR) usbForceDeviceBinding(nh, (struct PsdDevice *) methoddata[0]));
506 case UCM_ReleaseDeviceBinding:
507 usbReleaseDeviceBinding(nh, (struct NepClassEth *) methoddata[0]);
508 return(TRUE);
510 case UCM_OpenCfgWindow:
511 return(nOpenBindingCfgWindow(nh, &nh->nh_DummyNCP));
513 case UCM_OpenBindingCfgWindow:
514 return(nOpenBindingCfgWindow(nh, (struct NepClassEth *) methoddata[0]));
516 case UCM_ConfigChangedEvent:
517 nLoadClassConfig(nh);
518 Forbid();
519 ncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
520 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
522 nLoadBindingConfig(ncp);
523 ncp = (struct NepClassEth *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
525 Permit();
526 return(TRUE);
528 default:
529 break;
531 return(0);
532 AROS_LIBFUNC_EXIT
534 /* \\\ */
536 /* /// "nLoadClassConfig()" */
537 BOOL nLoadClassConfig(struct NepEthBase *nh)
539 struct NepClassEth *ncp = &nh->nh_DummyNCP;
540 struct Library *ps;
541 struct ClsDevCfg *cdc;
542 struct PsdIFFContext *pic;
544 KPRINTF(10, ("Loading Class Config...\n"));
545 if(ncp->ncp_GUITask)
547 return(FALSE);
549 if(!(ps = OpenLibrary("poseidon.library", 4)))
551 return(FALSE);
554 Forbid();
555 /* Create default config */
556 cdc = ncp->ncp_CDC;
557 cdc->cdc_ChunkID = AROS_LONG2BE(MAKE_ID('P','E','G','A'));
558 cdc->cdc_Length = AROS_LONG2BE(sizeof(struct ClsDevCfg)-8);
559 cdc->cdc_DefaultUnit = 0;
560 cdc->cdc_MediaType = 0;
561 ncp->ncp_UsingDefaultCfg = TRUE;
562 /* try to load default config */
563 pic = psdGetClsCfg(libname);
564 if(pic)
566 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncp->ncp_CDC->cdc_ChunkID));
567 if(cdc)
569 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
570 psdFreeVec(cdc);
571 ncp->ncp_UsingDefaultCfg = FALSE;
574 Permit();
575 CloseLibrary(ps);
576 return(FALSE);
578 /* \\\ */
580 /* /// "nLoadBindingConfig()" */
581 BOOL nLoadBindingConfig(struct NepClassEth *ncp)
583 struct NepEthBase *nh = ncp->ncp_ClsBase;
584 struct Library *ps;
585 struct ClsDevCfg *cdc;
586 struct PsdIFFContext *pic;
588 KPRINTF(10, ("Loading Binding Config...\n"));
589 if(ncp->ncp_GUITask)
591 return(FALSE);
593 //nLoadClassConfig(nh);
594 *ncp->ncp_CDC = *nh->nh_DummyNCP.ncp_CDC;
595 ncp->ncp_UsingDefaultCfg = TRUE;
597 if(!(ps = OpenLibrary("poseidon.library", 4)))
599 return(FALSE);
602 Forbid();
603 /* Load config */
604 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
605 if(pic)
607 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncp->ncp_CDC->cdc_ChunkID));
608 if(cdc)
610 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
611 psdFreeVec(cdc);
612 ncp->ncp_UsingDefaultCfg = FALSE;
615 Permit();
616 CloseLibrary(ps);
617 return(FALSE);
619 /* \\\ */
621 /* /// "nOpenBindingCfgWindow()" */
622 LONG nOpenBindingCfgWindow(struct NepEthBase *nh, struct NepClassEth *ncp)
624 struct Library *ps;
625 KPRINTF(10, ("Opening GUI...\n"));
626 if(!(ps = OpenLibrary("poseidon.library", 4)))
628 return(FALSE);
630 Forbid();
631 if(!ncp->ncp_GUITask)
633 if((ncp->ncp_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", nGUITask, ncp)))
635 Permit();
636 CloseLibrary(ps);
637 return(TRUE);
640 Permit();
641 CloseLibrary(ps);
642 return(FALSE);
644 /* \\\ */
646 /**************************************************************************/
648 #undef ps
649 #define ps ncp->ncp_Base
651 static char *MediaTypeStrings[] = { "Auto negotiation", "10Base-T Half Duplex", "10Base-T Full Duplex", "100Base-TX Half Duplex", "100Base-TX Full Duplex", NULL };
653 /* /// "nEthTask()" */
654 AROS_UFH0(void, nEthTask)
656 AROS_USERFUNC_INIT
658 struct NepClassEth *ncp;
659 struct PsdPipe *pp;
660 ULONG sigmask;
661 ULONG sigs;
662 LONG ioerr;
663 UBYTE *pktptr;
664 ULONG pktlen;
665 UWORD cnt;
666 LONG lastioerr = 0;
667 ULONG errcount = 0;
669 struct IOSana2Req *ioreq;
671 if((ncp = nAllocEth()))
673 Forbid();
674 if(ncp->ncp_ReadySigTask)
676 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
678 Permit();
680 if(nReadEEPROMMAC(ncp, ncp->ncp_ROMAddress))
682 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
684 // don't overwrite previously configured MAC Address
685 CopyMem(ncp->ncp_ROMAddress, ncp->ncp_MacAddress, ETHER_ADDR_SIZE);
687 nWritePegRegs(ncp, ncp->ncp_MacAddress, ETHER_ADDR_SIZE, PEGREG_ETH_ID);
688 } else {
689 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
690 "Couldn't read EEPROM for MAC Address, using preset one.");
691 nReadPegRegs(ncp, ncp->ncp_ROMAddress, ETHER_ADDR_SIZE, PEGREG_ETH_ID);
692 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
694 // don't overwrite previously configured MAC Address
695 CopyMem(ncp->ncp_ROMAddress, ncp->ncp_MacAddress, ETHER_ADDR_SIZE);
696 } else {
697 nWritePegRegs(ncp, ncp->ncp_MacAddress, ETHER_ADDR_SIZE, PEGREG_ETH_ID);
700 KPRINTF(10, ("MAC Address in EEPROM %02lx:%02lx:%02lx:%02lx:%02lx:%02lx\n",
701 ncp->ncp_MacAddress[0],
702 ncp->ncp_MacAddress[1],
703 ncp->ncp_MacAddress[2],
704 ncp->ncp_MacAddress[3],
705 ncp->ncp_MacAddress[4],
706 ncp->ncp_MacAddress[5]));
708 //if((!(ncp->ncp_StateFlags & DDF_OFFLINE)))// && (ncp->ncp_StateFlags & DDF_CONFIGURED))
710 /* Record start time_of_day */
711 //GetSysTime(&ncp->ncp_DeviceStats.LastStart);
712 nSetOnline(ncp);
715 /* Main task */
716 sigmask = (1L<<ncp->ncp_Unit.unit_MsgPort.mp_SigBit)|(1L<<ncp->ncp_TaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
719 // start transmitting read request if online...
720 if((ncp->ncp_StateFlags & DDF_ONLINE) && (ncp->ncp_ReadPending == NULL))
722 ncp->ncp_ReadPending = ncp->ncp_ReadBuffer[ncp->ncp_ReadBufNum];
723 psdSendPipe(ncp->ncp_EPInPipe, ncp->ncp_ReadPending, ETHER_MAX_LEN);
724 ncp->ncp_ReadBufNum ^= 1;
726 while((pp = (struct PsdPipe *) GetMsg(ncp->ncp_TaskMsgPort)))
728 KPRINTF(1, ("Pipe back %08lx\n", pp));
729 for(cnt = 0; cnt < 2; cnt++)
731 if(pp == ncp->ncp_EPOutPipe[cnt])
733 if((ioreq = ncp->ncp_WritePending[cnt]))
735 ioerr = psdGetPipeError(pp);
736 if(ioerr)
738 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
739 "Eth transmit failed: %s (%ld)",
740 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
742 /* Trigger any tx or generic error events */
743 nDoEvent(ncp, S2EVENT_ERROR|S2EVENT_TX);
745 /* Set error code and terminate the iorequest.
746 NOTE: Can't use RC_* or deverror() this is not
747 called from devBeginIO()!
749 ioreq->ios2_DataLength = 0;
750 ioreq->ios2_Req.io_Error = S2ERR_TX_FAILURE;
751 ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
752 psdDelayMS(50);
754 ReplyMsg((struct Message *) ioreq);
755 ncp->ncp_WritePending[cnt] = NULL;
757 break;
760 if(pp == ncp->ncp_EPInPipe)
762 if((pktptr = ncp->ncp_ReadPending))
764 ioerr = psdGetPipeError(pp);
765 pktlen = psdGetPipeActual(pp);
766 KPRINTF(1, ("ReadBack with %ld bytes.\n", pktlen));
767 // interleave next packet reading ASAP.
768 if(ncp->ncp_StateFlags & DDF_ONLINE)
770 ncp->ncp_ReadPending = ncp->ncp_ReadBuffer[ncp->ncp_ReadBufNum];
771 psdSendPipe(ncp->ncp_EPInPipe, ncp->ncp_ReadPending, ETHER_MAX_LEN);
772 ncp->ncp_ReadBufNum ^= 1;
773 } else {
774 ncp->ncp_ReadPending = NULL;
776 if(ioerr)
778 if(lastioerr != ioerr)
780 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
781 "Eth receive failed: %s (%ld)",
782 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
783 errcount = 0;
784 } else {
785 errcount++;
786 if(errcount > 20)
788 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname,
789 "That's it, that device pissed me off long enough!");
790 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
793 lastioerr = ioerr;
794 psdDelayMS(50);
795 break;
796 } else {
797 lastioerr = 0;
798 KPRINTF(20, ("%ld\n", pktlen));
799 KPRINTF(1, ("Pkt %ld received\n", pktlen));
800 //DB(dumpmem(pktptr, pktlen));
801 nReadPacket(ncp, pktptr, pktlen);
807 while((ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
809 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
810 ioreq, ioreq->ios2_Req.io_Command, ioreq->ios2_DataLength));
811 switch(ioreq->ios2_Req.io_Command)
813 case S2_CONFIGINTERFACE:
814 nWritePegRegs(ncp, ncp->ncp_MacAddress, ETHER_ADDR_SIZE, PEGREG_ETH_ID);
815 /* Now configured */
816 ncp->ncp_StateFlags |= DDF_CONFIGURED;
817 if(!(ncp->ncp_StateFlags & DDF_ONLINE))
819 nSetOnline(ncp);
821 ReplyMsg((struct Message *) ioreq);
822 break;
824 case S2_ADDMULTICASTADDRESS:
825 case S2_DELMULTICASTADDRESS:
826 case S2_ADDMULTICASTADDRESSES:
827 case S2_DELMULTICASTADDRESSES:
828 nWritePegRegs(ncp, ncp->ncp_MulticastArray, 8, PEGREG_MCAST);
829 if(ncp->ncp_Multicasts.lh_Head->ln_Succ)
831 ncp->ncp_EthCtrl[0] |= RX_MULTICAST;
832 } else {
833 ncp->ncp_EthCtrl[0] &= ~RX_MULTICAST;
835 nWritePegReg(ncp, PEGREG_ETH_CTRL0, (ULONG) ncp->ncp_EthCtrl[0]);
836 ReplyMsg((struct Message *) ioreq);
837 break;
839 case S2_ONLINE:
840 nSetOnline(ncp);
841 ReplyMsg((struct Message *) ioreq);
842 break;
844 case S2_OFFLINE:
845 ncp->ncp_EthCtrl[0] = 0x00;
846 ncp->ncp_EthCtrl[1] = 0x00; // media type
847 ioerr = nWritePegRegs(ncp, ncp->ncp_EthCtrl, 2, PEGREG_ETH_CTRL0);
849 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, BMCR_PDOWN);
850 ReplyMsg((struct Message *) ioreq);
851 break;
853 default:
854 ioreq->ios2_Req.io_Error = IOERR_NOCMD;
855 ReplyMsg((struct Message *) ioreq);
856 break;
859 Forbid();
860 while((!ncp->ncp_WritePending[ncp->ncp_WriteBufNum]) && ncp->ncp_WriteQueue.lh_Head->ln_Succ)
862 ioreq = (struct IOSana2Req *) RemHead(&ncp->ncp_WriteQueue);
863 Permit();
864 nWritePacket(ncp, ioreq);
865 Forbid();
867 Permit();
868 sigs = Wait(sigmask);
869 } while(!(sigs & SIGBREAKF_CTRL_C));
871 Forbid();
872 /* Now remove all requests still pending *anywhere* */
873 //ncp->ncp_DenyRequests = TRUE;
874 /* Current transfers */
875 for(cnt = 0; cnt < 2; cnt++)
877 if((ioreq = ncp->ncp_WritePending[cnt]))
879 KPRINTF(1, ("Aborting pending write...\n"));
880 psdAbortPipe(ncp->ncp_EPOutPipe[cnt]);
881 psdWaitPipe(ncp->ncp_EPOutPipe[cnt]);
882 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
883 ReplyMsg((struct Message *) ioreq);
884 ncp->ncp_WritePending[cnt] = NULL;
887 if(ncp->ncp_ReadPending)
889 KPRINTF(1, ("Aborting pending read...\n"));
890 psdAbortPipe(ncp->ncp_EPInPipe);
891 psdWaitPipe(ncp->ncp_EPInPipe);
892 ncp->ncp_ReadPending = NULL;
894 /* Command queue */
895 /*while(ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort))
897 KPRINTF(1, ("Aborting pending requests...\n"));
898 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
899 ReplyMsg((struct Message *) ioreq);
901 Permit();
903 nDoEvent(ncp, S2EVENT_OFFLINE);
905 KPRINTF(20, ("Going down the river!\n"));
906 nFreeEth(ncp);
909 AROS_USERFUNC_EXIT
911 /* \\\ */
913 /* /// "nAllocEth()" */
914 struct NepClassEth * nAllocEth(void)
916 struct Task *thistask;
917 struct NepClassEth *ncp;
919 thistask = FindTask(NULL);
922 ncp = thistask->tc_UserData;
923 if(!(ncp->ncp_Base = OpenLibrary("poseidon.library", 4)))
925 Alert(AG_OpenLib);
926 break;
929 ncp->ncp_Interface = psdFindInterface(ncp->ncp_Device, NULL,
930 TAG_END);
932 if(!ncp->ncp_Interface)
934 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "No interface?");
935 break;
938 ncp->ncp_EPIn = psdFindEndpoint(ncp->ncp_Interface, NULL,
939 EA_IsIn, TRUE,
940 EA_TransferType, USEAF_BULK,
941 TAG_END);
942 ncp->ncp_EPOut = psdFindEndpoint(ncp->ncp_Interface, NULL,
943 EA_IsIn, FALSE,
944 EA_TransferType, USEAF_BULK,
945 TAG_END);
946 if(!(ncp->ncp_EPIn && ncp->ncp_EPOut))
948 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "IN or OUT endpoint missing!");
949 break;
952 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPOut,
953 EA_MaxPktSize, &ncp->ncp_EPOutMaxPktSize,
954 TAG_END);
956 ncp->ncp_ReadPending = NULL;
957 ncp->ncp_WritePending[0] = NULL;
958 ncp->ncp_WritePending[1] = NULL;
959 if(!(ncp->ncp_ReadBuffer[0] = AllocVec(ETHER_MAX_LEN * 4, MEMF_PUBLIC|MEMF_CLEAR)))
961 KPRINTF(1, ("Out of memory for read buffer\n"));
962 break;
964 ncp->ncp_ReadBuffer[1] = ncp->ncp_ReadBuffer[0] + ETHER_MAX_LEN;
965 ncp->ncp_WriteBuffer[0] = ncp->ncp_ReadBuffer[1] + ETHER_MAX_LEN;
966 ncp->ncp_WriteBuffer[1] = ncp->ncp_WriteBuffer[0] + ETHER_MAX_LEN;
967 ncp->ncp_Unit.unit_MsgPort.mp_SigBit = AllocSignal(-1);
968 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = thistask;
969 ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
970 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
972 if((ncp->ncp_TaskMsgPort = CreateMsgPort()))
974 if((ncp->ncp_EP0Pipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, NULL)))
976 if((ncp->ncp_EPOutPipe[0] = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPOut)))
978 /* Turn off short packets */
979 psdSetAttrs(PGA_PIPE, ncp->ncp_EPOutPipe[0],
980 PPA_NoShortPackets, FALSE,
981 PPA_NakTimeout, TRUE,
982 PPA_NakTimeoutTime, 5000,
983 TAG_END);
984 if((ncp->ncp_EPOutPipe[1] = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPOut)))
986 /* Turn off short packets */
987 psdSetAttrs(PGA_PIPE, ncp->ncp_EPOutPipe[1],
988 PPA_NoShortPackets, FALSE,
989 PPA_NakTimeout, TRUE,
990 PPA_NakTimeoutTime, 5000,
991 TAG_END);
992 if((ncp->ncp_EPInPipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPIn)))
994 /* Turn off short packets */
995 psdSetAttrs(PGA_PIPE, ncp->ncp_EPInPipe,
996 PPA_NakTimeout, FALSE,
997 PPA_NakTimeoutTime, 5000,
998 PPA_AllowRuntPackets, TRUE,
999 TAG_END);
1000 ncp->ncp_Task = thistask;
1002 if(nInitPegasus(ncp))
1004 return(ncp);
1006 psdFreePipe(ncp->ncp_EPInPipe);
1008 psdFreePipe(ncp->ncp_EPOutPipe[1]);
1010 psdFreePipe(ncp->ncp_EPOutPipe[0]);
1012 psdFreePipe(ncp->ncp_EP0Pipe);
1014 DeleteMsgPort(ncp->ncp_TaskMsgPort);
1016 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
1017 } while(FALSE);
1018 if(ncp->ncp_ReadBuffer[0])
1020 FreeVec(ncp->ncp_ReadBuffer[0]);
1021 ncp->ncp_ReadBuffer[0] = NULL;
1023 CloseLibrary(ncp->ncp_Base);
1024 Forbid();
1025 ncp->ncp_Task = NULL;
1026 if(ncp->ncp_ReadySigTask)
1028 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1030 return(NULL);
1032 /* \\\ */
1034 /* /// "nFreeEth()" */
1035 void nFreeEth(struct NepClassEth *ncp)
1037 struct IOSana2Req *ioreq;
1038 Forbid();
1039 /* Disable the message port, messages may still be queued */
1040 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = NULL;
1041 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
1042 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
1043 // get rid of all messages that still have appeared here
1044 while((ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
1046 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
1047 ReplyMsg((struct Message *) ioreq);
1049 Permit();
1051 psdFreePipe(ncp->ncp_EPInPipe);
1052 psdFreePipe(ncp->ncp_EPOutPipe[0]);
1053 psdFreePipe(ncp->ncp_EPOutPipe[1]);
1054 psdFreePipe(ncp->ncp_EP0Pipe);
1056 if(ncp->ncp_ReadBuffer[0])
1058 FreeVec(ncp->ncp_ReadBuffer[0]);
1059 ncp->ncp_ReadBuffer[0] = NULL;
1062 DeleteMsgPort(ncp->ncp_TaskMsgPort);
1063 CloseLibrary(ncp->ncp_Base);
1064 Forbid();
1065 ncp->ncp_Task = NULL;
1066 if(ncp->ncp_ReadySigTask)
1068 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1071 /* \\\ */
1073 /* /// "nReadPegReg()" */
1074 LONG nReadPegReg(struct NepClassEth *ncp, ULONG reg)
1076 UBYTE result;
1077 LONG ioerr;
1079 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UPGR_GET_REGS, 0, reg);
1080 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, &result, 1);
1081 if(ioerr)
1083 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1084 "Reading Peg Reg %ld failed: %s (%ld)",
1085 reg,
1086 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1087 return(-1);
1089 return(result);
1091 /* \\\ */
1093 /* /// "nReadPegRegs()" */
1094 LONG nReadPegRegs(struct NepClassEth *ncp, UBYTE *data, ULONG len, ULONG offset)
1096 LONG ioerr;
1098 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UPGR_GET_REGS, 0, offset);
1099 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, data, len);
1100 if(ioerr)
1102 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1103 "Reading Peg Regs %ld-%ld failed: %s (%ld)",
1104 offset, offset+len-1,
1105 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1107 return(ioerr);
1109 /* \\\ */
1111 /* /// "nWritePegReg()" */
1112 LONG nWritePegReg(struct NepClassEth *ncp, ULONG reg, ULONG value)
1114 UBYTE byteval = value;
1115 LONG ioerr;
1117 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UPGR_SET_REGS, value, reg);
1118 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, &byteval, 1);
1119 if(ioerr)
1121 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1122 "Writing Peg Reg %ld with 0x%02lx failed: %s (%ld)",
1123 reg, value,
1124 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1126 return(ioerr);
1128 /* \\\ */
1130 /* /// "nWritePegRegs()" */
1131 LONG nWritePegRegs(struct NepClassEth *ncp, UBYTE *data, ULONG len, ULONG offset)
1133 LONG ioerr;
1135 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UPGR_SET_REGS, 0, offset);
1136 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, data, len);
1137 if(ioerr)
1139 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1140 "Writing Peg Regs %ld-%ld failed: %s (%ld)",
1141 offset, offset+len-1,
1142 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1144 return(ioerr);
1146 /* \\\ */
1148 /* /// "nReadEEPROMMAC()" */
1149 BOOL nReadEEPROMMAC(struct NepClassEth *ncp, UBYTE *macptr)
1151 UBYTE eeword[2];
1152 ULONG cnt;
1153 UWORD timeout;
1154 LONG ioerr;
1155 LONG data;
1157 for(cnt = 0; cnt < 3; cnt++)
1159 ioerr = nWritePegReg(ncp, PEGREG_EEPROM_CTRL, 0x00);
1160 if(ioerr)
1162 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1163 "Writing eeprom ctrl %ld = 0 failed: %s (%ld)",
1164 cnt,
1165 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1166 return(FALSE);
1168 ioerr = nWritePegReg(ncp, PEGREG_EEPROM_OFFSET, cnt);
1169 if(ioerr)
1171 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1172 "Writing eeprom offset %ld failed: %s (%ld)",
1173 cnt,
1174 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1175 return(FALSE);
1177 ioerr = nWritePegReg(ncp, PEGREG_EEPROM_CTRL, EEPROM_READ);
1178 if(ioerr)
1180 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1181 "Writing eeprom ctrl %ld read failed: %s (%ld)",
1182 cnt,
1183 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1184 return(FALSE);
1187 timeout = 10;
1188 while(--timeout)
1190 data = nReadPegReg(ncp, PEGREG_EEPROM_CTRL);
1191 if(data < 0)
1193 return(FALSE);
1195 if(data & EEPROM_DONE)
1197 break;
1199 psdDelayMS(10);
1201 if(!timeout)
1203 KPRINTF(20, ("Timeout waiting for EEPROM to respond (word %ld)!\n", cnt));
1204 return(FALSE);
1206 ioerr = nReadPegRegs(ncp, eeword, 2, PEGREG_EEPROM_DATA_LOW);
1207 if(ioerr)
1209 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1210 "Reading eeprom data low %ld failed: %s (%ld)",
1211 cnt,
1212 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1213 return(FALSE);
1215 *macptr++ = eeword[0];
1216 *macptr++ = eeword[1];
1217 psdDelayMS(500);
1219 return(TRUE);
1221 /* \\\ */
1223 /* /// "nReadPhyWord()" */
1224 LONG nReadPhyWord(struct NepClassEth *ncp, ULONG phyid, ULONG phyreg)
1226 UBYTE phyword[2];
1227 UWORD timeout;
1228 LONG ioerr;
1229 LONG data;
1231 ioerr = nWritePegReg(ncp, PEGREG_PHY_CTRL, 0x00);
1232 if(ioerr)
1234 return(-1);
1236 ioerr = nWritePegReg(ncp, PEGREG_PHY_ADDR, phyid);
1237 if(ioerr)
1239 return(-1);
1241 ioerr = nWritePegReg(ncp, PEGREG_PHY_CTRL, PHY_READ|phyreg);
1242 if(ioerr)
1244 return(-1);
1247 timeout = 10;
1248 while(--timeout)
1250 data = nReadPegReg(ncp, PEGREG_PHY_CTRL);
1251 if(data < 0)
1253 return(-1);
1255 if(data & PHY_DONE)
1257 break;
1259 psdDelayMS(10);
1261 if(!timeout)
1263 KPRINTF(20, ("Timeout waiting for PHY %ld to respond (read reg %ld)!\n", phyid, phyreg));
1264 return(-1);
1266 ioerr = nReadPegRegs(ncp, phyword, 2, PEGREG_PHY_DATA_LOW);
1267 if(ioerr)
1269 return(-1);
1271 return(phyword[0]|(phyword[1]<<8));
1273 /* \\\ */
1275 /* /// "nWritePhyWord()" */
1276 BOOL nWritePhyWord(struct NepClassEth *ncp, ULONG phyid, ULONG phyreg, ULONG value)
1278 UBYTE row[4];
1279 UWORD timeout;
1280 LONG ioerr;
1281 LONG data;
1283 row[0] = phyid;
1284 row[1] = value;
1285 row[2] = value>>8;
1286 row[3] = PHY_WRITE|phyreg;
1288 ioerr = nWritePegReg(ncp, PEGREG_PHY_CTRL, 0x00);
1289 if(ioerr)
1291 return(FALSE);
1293 ioerr = nWritePegRegs(ncp, row, 4, PEGREG_PHY_ADDR);
1294 if(ioerr)
1296 return(FALSE);
1299 timeout = 10;
1300 while(--timeout)
1302 data = nReadPegReg(ncp, PEGREG_PHY_CTRL);
1303 if(data < 0)
1305 return(FALSE);
1307 if(data & PHY_DONE)
1309 break;
1311 psdDelayMS(10);
1313 if(!timeout)
1315 KPRINTF(20, ("Timeout waiting for PHY %ld to respond (write reg %ld=%04lx)!\n", phyid, phyreg, value));
1316 return(FALSE);
1318 return(TRUE);
1320 /* \\\ */
1322 /* /// "nInitPegasus()" */
1323 BOOL nInitPegasus(struct NepClassEth *ncp)
1325 ULONG timeout;
1326 LONG data;
1327 LONG ioerr;
1329 ioerr = nWritePegReg(ncp, PEGREG_ETH_CTRL1, 0x08);
1330 if(ioerr)
1332 return(FALSE);
1334 timeout = 20;
1335 while(--timeout)
1337 data = nReadPegReg(ncp, PEGREG_ETH_CTRL1);
1338 if(data < 0)
1340 return(FALSE);
1342 if(!(data & 0x08))
1344 break;
1346 psdDelayMS(10);
1348 KPRINTF(10, ("Time %ld\n", timeout));
1349 if(!timeout)
1351 KPRINTF(20, ("Timeout waiting for reset to be released.\n"));
1352 return(FALSE);
1354 ioerr = nWritePegReg(ncp, PEGREG_GPIO1, DEFAULT_GPIO_SET);
1355 if(ioerr)
1357 return(FALSE);
1360 //ioerr = nWritePegReg(ncp, PEGREG_GPIO0, DEFAULT_GPIO_RESET);
1361 ioerr = nWritePegReg(ncp, PEGREG_GPIO0, 0x06);
1362 if(ioerr)
1364 return(FALSE);
1366 ioerr = nWritePegReg(ncp, PEGREG_GPIO0, DEFAULT_GPIO_SET);
1367 if(ioerr)
1369 return(FALSE);
1372 ncp->ncp_EthCtrl[0] = 0x08;
1373 ncp->ncp_EthCtrl[1] = 0x00;
1374 ncp->ncp_EthCtrl[2] = 0x03;
1376 ioerr = nWritePegRegs(ncp, ncp->ncp_EthCtrl, 3, PEGREG_ETH_CTRL0);
1377 if(ioerr)
1379 return(FALSE);
1382 if(ncp->ncp_PatchFlags & PF_PEG2)
1384 KPRINTF(10, ("Pegasus II setup...\n"));
1385 ioerr = nWritePegReg(ncp, PEGREG_REG_1D, 0x00);
1386 if(ioerr)
1388 return(FALSE);
1391 ioerr = nWritePegReg(ncp, PEGREG_REG_7B, 0x01);
1392 if(ioerr)
1394 return(FALSE);
1397 psdDelayMS(100);
1399 ioerr = nWritePegReg(ncp, PEGREG_REG_7B, 0x02);
1400 if(ioerr)
1402 return(FALSE);
1405 // detect 8513 chipset
1406 ioerr = nWritePegReg(ncp, PEGREG_REG_83, 0xa5);
1407 if(ioerr)
1409 return(FALSE);
1411 data = nReadPegReg(ncp, PEGREG_REG_83);
1412 if(data < 0)
1414 return(FALSE);
1416 if(data == 0xa5)
1418 KPRINTF(10, ("Chipset is 8513!\n"));
1419 ncp->ncp_PatchFlags |= PF_CHIP_8513;
1422 ioerr = nWritePegReg(ncp, PEGREG_REG_80, 0xc0);
1423 if(ioerr)
1425 return(FALSE);
1427 ioerr = nWritePegReg(ncp, PEGREG_REG_83, 0xff);
1428 if(ioerr)
1430 return(FALSE);
1432 ioerr = nWritePegReg(ncp, PEGREG_REG_84, 0x01);
1433 if(ioerr)
1435 return(FALSE);
1437 ioerr = nWritePegReg(ncp, PEGREG_REG_81, 0x02);
1438 if(ioerr)
1440 return(FALSE);
1444 // detect PHY ID
1445 for(ncp->ncp_PhyID = 0; ncp->ncp_PhyID < 32; ncp->ncp_PhyID++)
1447 data = nReadPhyWord(ncp, ncp->ncp_PhyID, MII_BMSR);
1448 KPRINTF(10, ("Phy %ld: %04lx\n", ncp->ncp_PhyID, data));
1449 if((data > 0) && (data != 0xffff) && (data & BMSR_MEDIA))
1451 break;
1454 if(ncp->ncp_PhyID == 32)
1456 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "Couldn't identify PHY, using 1 as default.");
1457 ncp->ncp_PhyID = 1;
1460 return(TRUE);
1462 /* \\\ */
1464 /* /// "nSetOnline()" */
1465 void nSetOnline(struct NepClassEth *ncp)
1467 LONG data;
1468 ULONG bmcr;
1469 BOOL autoneg = FALSE;
1470 BOOL linkgood = FALSE;
1471 UWORD timeout = 60;
1473 switch(ncp->ncp_CDC->cdc_MediaType)
1475 case MT_AUTO:
1476 KPRINTF(10, ("Autonegotiaton!\n"));
1477 bmcr = BMCR_ANENABLE|BMCR_ANRESTART;
1478 autoneg = TRUE;
1479 break;
1481 case MT_10BASE_T_HALF_DUP:
1482 bmcr = 0;
1483 ncp->ncp_EthCtrl[1] = 0x00;
1484 break;
1486 case MT_10BASE_T_FULL_DUP:
1487 bmcr = BMCR_FULLDPLX;
1488 ncp->ncp_EthCtrl[1] = 0x20;
1489 break;
1491 case MT_100BASE_TX_HALF_DUP:
1492 bmcr = BMCR_SPEED100;
1493 ncp->ncp_EthCtrl[1] = 0x10;
1494 break;
1496 case MT_100BASE_TX_FULL_DUP:
1497 default:
1498 bmcr = BMCR_SPEED100|BMCR_FULLDPLX;
1499 ncp->ncp_EthCtrl[1] = 0x30;
1500 break;
1503 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, bmcr);
1504 while(--timeout)
1506 psdDelayMS(50);
1507 data = nReadPhyWord(ncp, ncp->ncp_PhyID, MII_BMSR);
1508 KPRINTF(10, ("Status: %04lx\n", data));
1509 if(data < 0)
1511 timeout = 0;
1512 break;
1515 linkgood = (data & BMSR_LSTATUS);
1516 if((!autoneg) && linkgood)
1518 // no need to wait for autonegotiation
1519 break;
1522 // complete?
1523 if(data & BMSR_ANEGCOMPLETE)
1525 break;
1529 if(autoneg)
1531 STRPTR negstr = NULL;
1532 if(timeout)
1534 KPRINTF(10, ("Auto neg successful!\n"));
1535 data = nReadPhyWord(ncp, ncp->ncp_PhyID, MII_LPA);
1536 KPRINTF(10, ("Auto neg state %04lx\n", data));
1537 if(data < 0)
1539 timeout = 0;
1541 if(data & ADVERTISE_100FULL)
1543 // 100Base-TX Full Duplex
1544 ncp->ncp_EthCtrl[1] = 0x30;
1545 negstr = MediaTypeStrings[MT_100BASE_TX_FULL_DUP];
1547 else if(data & ADVERTISE_100HALF)
1549 // 100Base-TX Half Duplex
1550 ncp->ncp_EthCtrl[1] = 0x10;
1551 negstr = MediaTypeStrings[MT_100BASE_TX_HALF_DUP];
1553 else if(data & ADVERTISE_10FULL)
1555 // 10Base-T Full Duplex
1556 ncp->ncp_EthCtrl[1] = 0x20;
1557 negstr = MediaTypeStrings[MT_10BASE_T_FULL_DUP];
1559 else if(data & ADVERTISE_10HALF)
1561 // 10Base-T Half Duplex
1562 ncp->ncp_EthCtrl[1] = 0x00;
1563 negstr = MediaTypeStrings[MT_10BASE_T_HALF_DUP];
1564 } else {
1565 timeout = 0;
1568 if(!timeout)
1570 negstr = MediaTypeStrings[MT_100BASE_TX_FULL_DUP];
1571 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname, "Autonegotiation failed! Using %s instead.", negstr);
1572 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, BMCR_SPEED100|BMCR_FULLDPLX);
1573 ncp->ncp_EthCtrl[1] = 0x30;
1574 } else {
1575 psdAddErrorMsg(RETURN_OK, (STRPTR) libname, "Autonegotiation: Using %s.", negstr);
1578 if(!linkgood)
1580 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "No link, check the plug and cable.");
1583 ncp->ncp_EthCtrl[0] = 0xc9;
1584 ncp->ncp_EthCtrl[2] = 0x01;
1585 if(ncp->ncp_OpenFlags & SANA2OPF_PROM)
1587 ncp->ncp_EthCtrl[2] |= RX_PROMISCUOUS;
1589 if(ncp->ncp_Multicasts.lh_Head->ln_Succ)
1591 ncp->ncp_EthCtrl[0] |= RX_MULTICAST;
1594 nWritePegRegs(ncp, ncp->ncp_MulticastArray, 8, PEGREG_MCAST);
1596 nWritePegRegs(ncp, ncp->ncp_EthCtrl, 3, PEGREG_ETH_CTRL0);
1598 data = nReadPhyWord(ncp, ncp->ncp_PhyID, MII_TPISTATUS);
1599 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_TPISTATUS, data|4);
1601 /* Now online */
1602 ncp->ncp_StateFlags |= DDF_ONLINE;
1603 ncp->ncp_StateFlags &= ~DDF_OFFLINE;
1604 /* Trigger any ONLINE events */
1605 nDoEvent(ncp, S2EVENT_ONLINE);
1607 /* \\\ */
1609 /* /// "nDoEvent()" */
1610 void nDoEvent(struct NepClassEth *ncp, ULONG events)
1612 struct IOSana2Req *worknode, *nextnode;
1614 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events));
1616 Forbid();
1617 /* Process pending S2_ONEVENT requests */
1618 worknode = (struct IOSana2Req *) ncp->ncp_EventList.lh_Head;
1619 while((nextnode = (struct IOSana2Req *) (((struct Node *) worknode)->ln_Succ)))
1621 if(worknode->ios2_WireError & events)
1623 Remove(&worknode->ios2_Req.io_Message.mn_Node);
1624 worknode->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
1625 KPRINTF(1, ("DoEvent: returned eventreq 0x%08lx\n", worknode));
1626 ReplyMsg(&worknode->ios2_Req.io_Message);
1628 worknode = nextnode;
1630 Permit();
1632 /* \\\ */
1634 /* /// "support routines" */
1635 static
1636 inline void *callcopy(void *routine,
1637 void *from,
1638 void *to,
1639 ULONG len)
1641 void * (*call) (APTR, APTR, ULONG) = routine;
1643 return (*call) (from, to, len);
1646 #define callfilter CallHookPkt
1647 /* \\\ */
1649 /* /// "nWritePacket()" */
1650 BOOL nWritePacket(struct NepClassEth *ncp, struct IOSana2Req *ioreq)
1652 ULONG packettype;
1653 struct EtherPacketHeader *eph;
1654 UBYTE *copydest;
1655 UWORD writelen;
1656 struct BufMan *bufman;
1657 struct Sana2PacketTypeStats *stats;
1658 UBYTE *buf = ncp->ncp_WriteBuffer[ncp->ncp_WriteBufNum];
1660 packettype = ioreq->ios2_PacketType;
1661 // the first two bytes are the length
1662 eph = (struct EtherPacketHeader *) &buf[2];
1663 copydest = buf + 2;
1664 writelen = ioreq->ios2_DataLength;
1665 bufman = ioreq->ios2_BufferManagement;
1667 /* Not a raw packet? */
1668 if(!(ioreq->ios2_Req.io_Flags & SANA2IOF_RAW))
1670 UWORD cnt;
1671 KPRINTF(10, ("RAW WRITE!\n"));
1672 /* The ethernet header isn't included in the data */
1673 /* Build ethernet packet header */
1674 for(cnt = 0; cnt < ETHER_ADDR_SIZE; cnt++)
1676 eph->eph_Dest[cnt] = ioreq->ios2_DstAddr[cnt];
1677 eph->eph_Src[cnt] = ncp->ncp_MacAddress[cnt];
1679 eph->eph_Type = AROS_WORD2BE(packettype);
1681 /* Packet data is at txbuffer */
1682 copydest += sizeof(struct EtherPacketHeader);
1683 writelen += sizeof(struct EtherPacketHeader);
1686 //memset(buf + 2, 0x55, writelen);
1688 /* Dma not available, fallback to regular copy */
1689 if(callcopy(bufman->bm_CopyFromBuf, copydest, ioreq->ios2_Data, ioreq->ios2_DataLength) == NULL)
1691 KPRINTF(10, ("writepacket: copyfrom returned failure!\n"));
1693 /* Trigger any tx, buff or generic error events */
1694 nDoEvent(ncp, S2EVENT_ERROR|S2EVENT_TX|S2EVENT_BUFF);
1696 /* Set error code and terminate the iorequest.
1697 NOTE: Can't use RC_* or deverror() this is not
1698 called from devBeginIO()! */
1699 ioreq->ios2_DataLength = 0;
1700 ioreq->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1701 ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
1702 return FALSE;
1705 buf[0] = writelen;
1706 buf[1] = writelen>>8;
1708 /* Adjust writelen to legal packet size. */
1709 if(writelen < ETHER_MIN_LEN)
1711 memset(buf + writelen + 2, 0, ETHER_MIN_LEN - writelen);
1712 writelen = ETHER_MIN_LEN;
1715 writelen += 2;
1717 KPRINTF(10, ("PktOut[%ld] %ld\n", ncp->ncp_WriteBufNum, writelen));
1718 // unfortunately, it looks like the adapter does not correctly accepts
1719 // zero length packets as end of transfer, so make the last packet a
1720 // one byte length one.
1721 if(!(writelen & (ncp->ncp_EPOutMaxPktSize-1)))
1723 writelen++;
1725 ncp->ncp_WritePending[ncp->ncp_WriteBufNum] = ioreq;
1726 psdSendPipe(ncp->ncp_EPOutPipe[ncp->ncp_WriteBufNum], buf, (ULONG) writelen);
1727 ncp->ncp_WriteBufNum ^= 1;
1730 if(AROS_BE2WORD(eph->eph_Type) < ETHERPKT_SIZE)
1732 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx (IEEE802.3) len %lu, %lu bytes\n",
1733 *((UWORD *) eph->eph_Src), *((ULONG *) (eph->eph_Src + 2)),
1734 *((UWORD *) eph->eph_Dest), *((ULONG *) (eph->eph_Dest + 2)),
1735 AROS_BE2WORD(eph->eph_Type), writelen));
1736 } else {
1737 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx type %lu, %lu bytes\n",
1738 *((UWORD *) eph->eph_Src), *((ULONG *) (eph->eph_Src + 2)),
1739 *((UWORD *) eph->eph_Dest), *((ULONG *) (eph->eph_Dest + 2)),
1740 AROS_BE2WORD(eph->eph_Type), writelen));
1742 //dumpmem(buf, (ULONG) writelen);
1745 /* Update statistics */
1746 stats = FindPacketTypeStats(ncp, packettype);
1747 if(stats)
1749 stats->PacketsSent++;
1750 stats->BytesSent += writelen;
1752 ncp->ncp_DeviceStats.PacketsSent++;
1754 return TRUE;
1756 /* \\\ */
1758 /* /// "nReadIOReq()" */
1759 UWORD nReadIOReq(struct NepClassEth *ncp, struct EtherPacketHeader *eph, UWORD datasize, struct IOSana2Req *ioreq, UWORD flags)
1761 LIBBASETYPEPTR nh = ncp->ncp_ClsBase;
1762 UBYTE *copyfrom;
1763 UWORD cnt;
1765 /* Handle RAW read */
1766 if(ioreq->ios2_Req.io_Flags & SANA2IOF_RAW)
1768 /* ShapeShifter won't work with `sizeof(struct etherpacket_hdr)'
1769 here. This is most likely because it want the RAW ethernet
1770 packet checksum size (4) added to the packet size. */
1771 copyfrom = (UBYTE *) eph;
1772 datasize += sizeof(struct EtherPacketHeader) + 4;
1773 } else {
1774 copyfrom = (UBYTE *) (eph + 1);
1777 /* Build up the ios2 structure enough so we can call the packet filter. */
1778 ioreq->ios2_PacketType = AROS_BE2WORD(eph->eph_Type);
1779 for(cnt = 0; cnt < ETHER_ADDR_SIZE; cnt++)
1781 ioreq->ios2_SrcAddr[cnt] = eph->eph_Src[cnt];
1782 ioreq->ios2_DstAddr[cnt] = eph->eph_Dest[cnt];
1784 ioreq->ios2_DataLength = datasize;
1785 /* Call the packet filter, if available. */
1786 if((flags & PACKETFILTER) &&
1787 (((struct BufMan *) ioreq->ios2_BufferManagement)->bm_PacketFilter) &&
1788 (!callfilter(((struct BufMan *) ioreq->ios2_BufferManagement)->bm_PacketFilter,
1789 ioreq, copyfrom)))
1791 /* This packet got dropped! */
1792 KPRINTF(7, ("readioreq: packet type %lu for ioreq 0x%08lx dropped\n",
1793 AROS_BE2WORD(eph->eph_Type), ioreq));
1794 return flags;
1798 /* Ok, the packet didn't get dropped, set the BCAST and MCAST
1799 flags according to dstaddr. */
1801 /* Address == Multicast? */
1802 if(ioreq->ios2_DstAddr[0] & 1)
1804 /* Address == Broadcast? */
1805 static const UBYTE bcast[ETHER_ADDR_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1806 if(memcmp(bcast, ioreq->ios2_DstAddr, ETHER_ADDR_SIZE) == 0)
1808 ioreq->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1809 } else {
1810 ioreq->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1814 /* Finally copy the packet data! */
1815 if(callcopy(((struct BufMan *) ioreq->ios2_BufferManagement)->bm_CopyToBuf,
1816 ioreq->ios2_Data, copyfrom, ioreq->ios2_DataLength))
1819 KPRINTF(5, ("readioreq: copytobuffed packet ior 0x%08lx, %04lx%08lx < %04lx%08lx, type %lu, %lu bytes, %s%s%s\n",
1820 ioreq,
1821 *((UWORD *) ioreq->ios2_DstAddr), *((ULONG *) (ioreq->ios2_DstAddr + 2)),
1822 *((UWORD *) ioreq->ios2_SrcAddr), *((ULONG *) (ioreq->ios2_SrcAddr + 2)),
1823 ioreq->ios2_PacketType, ioreq->ios2_DataLength,
1824 (ioreq->ios2_Req.io_Flags & SANA2IOF_RAW) ? "RAW " : "",
1825 (ioreq->ios2_Req.io_Flags & SANA2IOF_BCAST) ? "BCAST " : "",
1826 (ioreq->ios2_Req.io_Flags & SANA2IOF_MCAST) ? "MCAST " : ""));
1827 //dumpmem(copyfrom, ioreq->ios2_DataLength);
1830 /* Clear the dropped flag */
1831 flags &= ~DROPPED;
1832 } else {
1833 KPRINTF(10, ("readioreq: copyto returned failure!\n"));
1835 /* Trigger any rx, buff or generic error events */
1836 nDoEvent(ncp, S2EVENT_ERROR|S2EVENT_RX|S2EVENT_BUFF);
1838 /* Set error code.
1839 NOTE: Can't use RC_* or deverror() this is not called from devBeginIO()!
1841 ioreq->ios2_DataLength = 0;
1842 ioreq->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1843 ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
1846 /* Pull the ioreq off the list & terminate it */
1847 Forbid();
1848 Remove((struct Node *) ioreq);
1849 Permit();
1850 ReplyMsg((struct Message *) ioreq);
1851 return flags;
1853 /* \\\ */
1855 /* /// "nReadPacket()" */
1856 BOOL nReadPacket(struct NepClassEth *ncp, UBYTE *pktptr, ULONG len)
1858 struct EtherPacketHeader *eph;
1859 struct BufMan *bufman;
1860 struct IOSana2Req *worknode, *nextnode;
1861 struct Sana2PacketTypeStats *stats;
1862 UWORD flags;
1863 UWORD datasize;
1864 UWORD status;
1865 UWORD pktlen;
1867 KPRINTF(10, ("PktIn [%ld] %ld\n", ncp->ncp_ReadBufNum, len));
1869 if(len < 4)
1871 ncp->ncp_DeviceStats.BadData++;
1872 return FALSE;
1874 if(ncp->ncp_PatchFlags & PF_CHIP_8513)
1876 // this chipset has the length at the beginning instead of the end
1877 pktlen = *pktptr++;
1878 pktlen += (*pktptr++ & 0x0f)<<8;
1879 } else {
1880 pktlen = pktptr[len-4]|((pktptr[len-3] & 0x0f)<<8);
1881 if(pktlen < 14)
1883 ncp->ncp_DeviceStats.BadData++;
1884 return FALSE;
1886 pktlen -= 8;
1888 status = pktptr[len-2]|(pktptr[len-1]<<8);
1889 if(status & 0x1e)
1891 KPRINTF(20, ("Error %02lx\n", status));
1892 if(status & 0x06)
1894 ncp->ncp_DeviceStats.Overruns++;
1896 if(status & 0x18)
1898 ncp->ncp_DeviceStats.BadData++;
1900 return FALSE;
1902 if(len != pktlen + 8)
1904 KPRINTF(20, ("Pktlen %ld != len %ld\n", pktlen + 8, len));
1905 return FALSE;
1907 ncp->ncp_DeviceStats.PacketsReceived++;
1909 eph = (struct EtherPacketHeader *) pktptr;
1910 stats = FindPacketTypeStats(ncp, (ULONG) AROS_BE2WORD(eph->eph_Type));
1911 flags = DROPPED|PACKETFILTER;
1913 /* Calculate size of the actual data */
1914 datasize = pktlen - sizeof(struct EtherPacketHeader);
1916 /* Is the packet datasize valid? */
1917 if((pktlen >= ETHER_MIN_LEN) && (pktlen <= ETHER_MAX_LEN))
1919 /* Update the packet statistics */
1920 if(stats)
1922 stats->PacketsReceived++;
1923 stats->BytesReceived += datasize; /* NOTE: don't include headers */
1926 /* For each device user (bufman)
1927 NOTE: We absolutely *MUST* try to offer the packet to *all*
1928 different device users (SANA-II V2 spec requirement). */
1929 Forbid();
1930 bufman = (struct BufMan *) ncp->ncp_BufManList.lh_Head;
1931 while(((struct Node *) bufman)->ln_Succ)
1933 /* For each queued read request (ioreq) */
1934 worknode = (struct IOSana2Req *) bufman->bm_RXQueue.lh_Head;
1935 while((nextnode = (struct IOSana2Req *) (((struct Node *) worknode)->ln_Succ)))
1937 /* Check the packet type. Also handles 802.3 packets. */
1938 if((worknode->ios2_PacketType == AROS_BE2WORD(eph->eph_Type)) ||
1939 ((AROS_BE2WORD(eph->eph_Type) < ETHERPKT_SIZE) && (worknode->ios2_PacketType < ETHERPKT_SIZE)))
1941 flags = nReadIOReq(ncp, eph, datasize, worknode, flags);
1942 /* Break out - let other callers get the packet too */
1943 break;
1945 worknode = nextnode;
1947 bufman = (struct BufMan *) (((struct Node *) bufman)->ln_Succ);
1949 Permit();
1950 /* Now we've tried to give the packet to every CMD_READ caller.
1951 If DROPPED is set at this point no-one wanted this packet. */
1952 if(flags & DROPPED)
1954 /* So there were no outstanding CMD_READs or the packet wasn't
1955 accepted by any of them. Okay, check if we have any pending
1956 S2_READORPHAN ioreq in list and if we have return this packet
1957 with it. Note that packet filter must not be used for this
1958 time!
1960 NOTE: orphanlist is global, ie. only one caller will get the
1961 packet if multiple users have pending S2_READORPHANs.
1964 /* Process pending orphanread iorequs */
1965 Forbid();
1966 worknode = (struct IOSana2Req *) ncp->ncp_OrphanQueue.lh_Head;
1967 while((nextnode = (struct IOSana2Req *) (((struct Node *) worknode)->ln_Succ)))
1969 nReadIOReq(ncp, eph, datasize, worknode, 0);
1970 worknode = nextnode;
1972 Permit();
1973 } else {
1974 /* Packet not dropped - return ok */
1975 return TRUE;
1977 } else {
1978 KPRINTF(20, ("Pktlen %ld invalid!\n", pktlen));
1979 ncp->ncp_DeviceStats.BadData++;
1981 /* Update global dropped packet counter. */
1982 ncp->ncp_DeviceStats.UnknownTypesReceived++;
1984 /* Update dropped packet statistics. */
1985 if(stats)
1987 stats->PacketsDropped++;
1989 KPRINTF(9, ("readpacket: packet type %lu dropped\n", AROS_BE2WORD(eph->eph_Type)));
1991 /* Trigger any rx or generic error events */
1992 nDoEvent(ncp, S2EVENT_ERROR|S2EVENT_RX);
1993 return FALSE;
1995 /* \\\ */
1997 /**************************************************************************/
1999 /* /// "nGUITask()" */
2000 AROS_UFH0(void, nGUITask)
2002 AROS_USERFUNC_INIT
2004 struct Task *thistask;
2005 struct NepEthBase *nh;
2006 struct NepClassEth *ncp;
2007 struct PsdIFFContext *pic;
2009 thistask = FindTask(NULL);
2010 #undef ps
2011 #define ps ncp->ncp_PsdBase
2012 #undef IntuitionBase
2013 #define IntuitionBase ncp->ncp_IntBase
2014 #undef MUIMasterBase
2015 #define MUIMasterBase ncp->ncp_MUIBase
2017 ncp = thistask->tc_UserData;
2018 nh = ncp->ncp_ClsBase;
2020 ++nh->nh_Library.lib_OpenCnt;
2021 if(!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
2023 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
2024 nGUITaskCleanup(ncp);
2025 return;
2028 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
2030 KPRINTF(10, ("Couldn't open intuition.library.\n"));
2031 nGUITaskCleanup(ncp);
2032 return;
2034 if(!(ps = OpenLibrary("poseidon.library", 4)))
2036 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
2037 nGUITaskCleanup(ncp);
2038 return;
2041 ncp->ncp_App = ApplicationObject,
2042 MUIA_Application_Title , (IPTR)libname,
2043 MUIA_Application_Version , (IPTR)VERSION_STRING,
2044 MUIA_Application_Copyright , (IPTR)"©2006-2009 Harry Sintonen & Chris Hodges",
2045 MUIA_Application_Author , (IPTR)"Harry Sintonen <sintonen@iki.fi> & Chris Hodges <chrisly@platon42.de>",
2046 MUIA_Application_Description, (IPTR)"Settings for the pegasus.class",
2047 MUIA_Application_Base , (IPTR)"PEGASUS",
2048 MUIA_Application_HelpFile , (IPTR)"HELP:Poseidon.guide",
2049 MUIA_Application_Menustrip , (IPTR)MenustripObject,
2050 Child, (IPTR)MenuObjectT((IPTR)"Project"),
2051 Child, (IPTR)(ncp->ncp_AboutMI = MenuitemObject,
2052 MUIA_Menuitem_Title, (IPTR)"About...",
2053 MUIA_Menuitem_Shortcut, (IPTR)"?",
2054 End),
2055 End,
2056 Child, (IPTR)MenuObjectT((IPTR)"Settings"),
2057 Child, (IPTR)(ncp->ncp_UseMI = MenuitemObject,
2058 MUIA_Menuitem_Title, (IPTR)"Save",
2059 MUIA_Menuitem_Shortcut, (IPTR)"S",
2060 End),
2061 Child, (IPTR)(ncp->ncp_SetDefaultMI = MenuitemObject,
2062 MUIA_Menuitem_Title, (IPTR)"Set as Default",
2063 MUIA_Menuitem_Shortcut, (IPTR)"D",
2064 End),
2065 Child, (IPTR)MenuitemObject,
2066 MUIA_Menuitem_Title, (IPTR)NM_BARLABEL,
2067 End,
2068 Child, (IPTR)(ncp->ncp_MUIPrefsMI = MenuitemObject,
2069 MUIA_Menuitem_Title, (IPTR)"MUI Settings",
2070 MUIA_Menuitem_Shortcut, (IPTR)"M",
2071 End),
2072 End,
2073 End,
2075 SubWindow, (IPTR)(ncp->ncp_MainWindow = WindowObject,
2076 MUIA_Window_ID , MAKE_ID('M','A','I','N'),
2077 MUIA_Window_Title, (IPTR)libname,
2078 MUIA_HelpNode, (IPTR)libname,
2080 WindowContents, (IPTR)VGroup,
2081 Child, (IPTR)ColGroup(2), GroupFrameT((IPTR)(ncp->ncp_Interface ? "Device Settings" : "Default Device Settings")),
2082 //Child, (IPTR)HSpace(0),
2083 Child, (IPTR)Label((IPTR) "Media Type:"),
2084 Child, (IPTR)(ncp->ncp_MediaTypeObj = CycleObject,
2085 MUIA_CycleChain, 1,
2086 MUIA_Cycle_Entries, (IPTR)MediaTypeStrings,
2087 MUIA_Cycle_Active, ncp->ncp_CDC->cdc_MediaType,
2088 End),
2089 Child, (IPTR)Label((IPTR) "Default " DEVNAME " Unit:"),
2090 Child, (IPTR)(ncp->ncp_UnitObj = StringObject,
2091 StringFrame,
2092 MUIA_CycleChain, 1,
2093 MUIA_String_AdvanceOnCR, TRUE,
2094 MUIA_String_Integer, ncp->ncp_CDC->cdc_DefaultUnit,
2095 MUIA_String_Accept, (IPTR)"0123456789",
2096 End),
2097 End,
2098 Child, (IPTR)VSpace(0),
2099 Child, (IPTR)HGroup,
2100 MUIA_Group_SameWidth, TRUE,
2101 Child, (IPTR)(ncp->ncp_UseObj = TextObject, ButtonFrame,
2102 MUIA_ShowMe, (IPTR)ncp->ncp_Interface,
2103 MUIA_Background, MUII_ButtonBack,
2104 MUIA_CycleChain, 1,
2105 MUIA_InputMode, MUIV_InputMode_RelVerify,
2106 MUIA_Text_Contents, (IPTR)"\33c Save ",
2107 End),
2108 Child, (IPTR)(ncp->ncp_SetDefaultObj = TextObject, ButtonFrame,
2109 MUIA_Background, MUII_ButtonBack,
2110 MUIA_CycleChain, 1,
2111 MUIA_InputMode, MUIV_InputMode_RelVerify,
2112 MUIA_Text_Contents, (IPTR)(ncp->ncp_Interface ? "\33c Save as Default " : "\33c Save Defaults "),
2113 End),
2114 Child, (IPTR)(ncp->ncp_CloseObj = TextObject, ButtonFrame,
2115 MUIA_Background, MUII_ButtonBack,
2116 MUIA_CycleChain, 1,
2117 MUIA_InputMode, MUIV_InputMode_RelVerify,
2118 MUIA_Text_Contents, (IPTR)"\33c Use ",
2119 End),
2120 End,
2121 End,
2122 End),
2123 End;
2125 if(!ncp->ncp_App)
2127 KPRINTF(10, ("Couldn't create application\n"));
2128 nGUITaskCleanup(ncp);
2129 return;
2132 DoMethod(ncp->ncp_MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
2133 ncp->ncp_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
2134 DoMethod(ncp->ncp_UseObj, MUIM_Notify, MUIA_Pressed, FALSE,
2135 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
2136 DoMethod(ncp->ncp_SetDefaultObj, MUIM_Notify, MUIA_Pressed, FALSE,
2137 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
2138 DoMethod(ncp->ncp_CloseObj, MUIM_Notify, MUIA_Pressed, FALSE,
2139 ncp->ncp_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
2141 DoMethod(ncp->ncp_AboutMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
2142 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_ABOUT);
2143 DoMethod(ncp->ncp_UseMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
2144 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
2145 DoMethod(ncp->ncp_SetDefaultMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
2146 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
2147 DoMethod(ncp->ncp_MUIPrefsMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
2148 ncp->ncp_App, 2, MUIM_Application_OpenConfigWindow, 0);
2150 IPTR isopen = 0;
2151 IPTR iconify = 0;
2152 ULONG sigs;
2153 ULONG sigmask;
2154 LONG retid;
2156 get(ncp->ncp_App, MUIA_Application_Iconified, &iconify);
2157 set(ncp->ncp_MainWindow, MUIA_Window_Open, TRUE);
2158 get(ncp->ncp_MainWindow, MUIA_Window_Open, &isopen);
2159 if(!(isopen || iconify))
2161 nGUITaskCleanup(ncp);
2162 return;
2164 sigmask = 0;
2167 retid = DoMethod(ncp->ncp_App, MUIM_Application_NewInput, &sigs);
2168 switch(retid)
2170 case ID_DEF_CONFIG:
2171 case ID_STORE_CONFIG:
2172 case MUIV_Application_ReturnID_Quit:
2174 get(ncp->ncp_UnitObj, MUIA_String_Integer, &ncp->ncp_CDC->cdc_DefaultUnit);
2175 get(ncp->ncp_MediaTypeObj, MUIA_Cycle_Active, &ncp->ncp_CDC->cdc_MediaType);
2177 if(retid == ID_DEF_CONFIG)
2179 pic = psdGetClsCfg(libname);
2180 if(!pic)
2182 psdSetClsCfg(libname, NULL);
2183 pic = psdGetClsCfg(libname);
2185 if(pic)
2187 psdAddCfgEntry(pic, ncp->ncp_CDC);
2188 psdSaveCfgToDisk(NULL, FALSE);
2191 if(ncp->ncp_Interface)
2193 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
2194 if(!pic)
2196 psdSetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL, NULL);
2197 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
2199 if(pic)
2201 if(psdAddCfgEntry(pic, ncp->ncp_CDC))
2203 if(retid != MUIV_Application_ReturnID_Quit)
2205 psdSaveCfgToDisk(NULL, FALSE);
2207 retid = MUIV_Application_ReturnID_Quit;
2210 } else {
2211 retid = MUIV_Application_ReturnID_Quit;
2213 break;
2216 case ID_ABOUT:
2217 MUI_RequestA(ncp->ncp_App, ncp->ncp_MainWindow, 0, NULL, "Phat!", VERSION_STRING, NULL);
2218 break;
2220 if(retid == MUIV_Application_ReturnID_Quit)
2222 break;
2224 if(sigs)
2226 sigs = Wait(sigs|sigmask|SIGBREAKF_CTRL_C);
2227 if(sigs & SIGBREAKF_CTRL_C)
2229 break;
2232 } while(TRUE);
2233 set(ncp->ncp_MainWindow, MUIA_Window_Open, FALSE);
2235 nGUITaskCleanup(ncp);
2237 AROS_USERFUNC_EXIT
2239 /* \\\ */
2241 /* /// "nGUITaskCleanup()" */
2242 void nGUITaskCleanup(struct NepClassEth *ncp)
2244 if(ncp->ncp_App)
2246 MUI_DisposeObject(ncp->ncp_App);
2247 ncp->ncp_App = NULL;
2249 if(MUIMasterBase)
2251 CloseLibrary(MUIMasterBase);
2252 MUIMasterBase = NULL;
2254 if(IntuitionBase)
2256 CloseLibrary(IntuitionBase);
2257 IntuitionBase = NULL;
2259 if(ps)
2261 CloseLibrary(ps);
2262 ps = NULL;
2264 Forbid();
2265 ncp->ncp_GUIBinding = NULL;
2266 ncp->ncp_GUITask = NULL;
2267 if(ncp->ncp_ReadySigTask)
2269 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
2271 --ncp->ncp_ClsBase->nh_Library.lib_OpenCnt;
2273 /* \\\ */