Documented GVF_SAVE_VAR alongside other flags, and removed a query/doubt
[AROS.git] / rom / usb / classes / moschipeth / moschipeth.class.c
blob2a15aa9a7b6912ab831949f7cdf8afc49fb0e635
1 /*
2 *----------------------------------------------------------------------------
3 * moschipeth class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "moschipeth.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! moschipeth.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 /* /// "usbAttemptDeviceBinding()" */
125 struct NepClassEth * usbAttemptDeviceBinding(struct NepEthBase *nh, struct PsdDevice *pd)
127 struct Library *ps;
128 IPTR prodid;
129 IPTR vendid;
131 KPRINTF(1, ("nepEthAttemptDeviceBinding(%08lx)\n", pd));
133 if((ps = OpenLibrary("poseidon.library", 4)))
135 psdGetAttrs(PGA_DEVICE, pd,
136 DA_VendorID, &vendid,
137 DA_ProductID, &prodid,
138 TAG_END);
139 CloseLibrary(ps);
140 if((vendid == 0x9710) && (prodid == 0x7830))
142 return(usbForceDeviceBinding(nh, pd));
145 return(NULL);
147 /* \\\ */
149 /* /// "usbForceDeviceBinding()" */
150 struct NepClassEth * usbForceDeviceBinding(struct NepEthBase *nh, struct PsdDevice *pd)
153 struct Library *ps;
154 struct NepClassEth *ncp;
155 struct NepClassEth *tmpncp;
156 struct ClsDevCfg *cdc;
157 STRPTR devname;
158 STRPTR devidstr;
159 IPTR prodid;
160 IPTR vendid;
161 ULONG unitno;
162 BOOL unitfound;
163 UBYTE buf[64];
164 struct Task *tmptask;
166 KPRINTF(1, ("nepEthForceDeviceBinding(%08lx)\n", pd));
168 if((ps = OpenLibrary("poseidon.library", 4)))
170 psdGetAttrs(PGA_DEVICE, pd,
171 DA_ProductID, &prodid,
172 DA_VendorID, &vendid,
173 DA_ProductName, &devname,
174 DA_IDString, &devidstr,
175 TAG_END);
176 Forbid();
178 unitfound = FALSE;
179 unitno = (ULONG) -1;
180 ncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
181 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
183 if(!strcmp(ncp->ncp_DevIDString, devidstr))
185 unitno = ncp->ncp_UnitNo;
186 unitfound = TRUE;
187 break;
189 ncp = (struct NepClassEth *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
191 if(!unitfound)
193 /* as units are freed in the expunge-vector, the memory is
194 outside the scope of the poseidon library */
195 if(!(ncp = AllocVec(sizeof(struct NepClassEth), MEMF_PUBLIC|MEMF_CLEAR)))
197 Permit();
198 CloseLibrary(ps);
199 return(NULL);
201 ncp->ncp_CDC = cdc = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
202 if(!cdc)
204 Permit();
205 FreeVec(ncp);
206 CloseLibrary(ps);
207 return(NULL);
209 /* IORequests may be queued even if the task is gone. */
210 ncp->ncp_UnitNo = (ULONG) -1;
211 NewList(&ncp->ncp_Unit.unit_MsgPort.mp_MsgList);
212 NewList(&ncp->ncp_OrphanQueue);
213 NewList(&ncp->ncp_WriteQueue);
214 NewList(&ncp->ncp_BufManList);
215 NewList(&ncp->ncp_EventList);
216 NewList(&ncp->ncp_TrackList);
217 NewList(&ncp->ncp_Multicasts);
218 strncpy(ncp->ncp_DevIDString, devidstr, 127);
219 AddTail(&nh->nh_Units, &ncp->ncp_Unit.unit_MsgPort.mp_Node);
221 ncp->ncp_ClsBase = nh;
222 ncp->ncp_Device = pd;
223 ncp->ncp_UnitProdID = prodid;
224 ncp->ncp_UnitVendorID = vendid;
226 nLoadBindingConfig(ncp);
228 /* Find next free unit number */
229 if(unitno == (ULONG) -1)
231 unitno = ncp->ncp_CDC->cdc_DefaultUnit;
232 tmpncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
233 while(tmpncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
235 if(tmpncp->ncp_UnitNo == unitno)
237 unitno++;
238 tmpncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
239 } else {
240 tmpncp = (struct NepClassEth *) tmpncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
244 ncp->ncp_UnitNo = unitno;
245 Permit();
247 psdSafeRawDoFmt(buf, 64, "moschipeth.class<%08lx>", ncp);
248 ncp->ncp_ReadySignal = SIGB_SINGLE;
249 ncp->ncp_ReadySigTask = FindTask(NULL);
250 SetSignal(0, SIGF_SINGLE);
251 if((tmptask = psdSpawnSubTask(buf, nEthTask, ncp)))
253 psdBorrowLocksWait(tmptask, 1L<<ncp->ncp_ReadySignal);
254 //Wait(1L<<ncp->ncp_ReadySignal);
255 if(ncp->ncp_Task)
257 ncp->ncp_ReadySigTask = NULL;
258 //FreeSignal(ncp->ncp_ReadySignal);
259 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
260 "Ethereal moss '%s' on %s unit %ld!",
261 devname, nh->nh_DevBase->np_Library.lib_Node.ln_Name,
262 ncp->ncp_UnitNo);
264 CloseLibrary(ps);
265 return(ncp);
268 ncp->ncp_ReadySigTask = NULL;
269 //FreeSignal(ncp->ncp_ReadySignal);
270 /* Get rid of unit structure */
271 /*Forbid();
272 Remove((struct Node *) ncp);
273 FreeVec(ncp->ncp_CDC);
274 FreeVec(ncp);
275 Permit();*/
276 CloseLibrary(ps);
278 return(NULL);
280 /* \\\ */
282 /* /// "usbReleaseDeviceBinding()" */
283 void usbReleaseDeviceBinding(struct NepEthBase *nh, struct NepClassEth *ncp)
285 struct Library *ps;
286 STRPTR devname;
287 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp));
289 if((ps = OpenLibrary("poseidon.library", 4)))
291 Forbid();
292 ncp->ncp_ReadySignal = SIGB_SINGLE;
293 ncp->ncp_ReadySigTask = FindTask(NULL);
294 if(ncp->ncp_Task)
296 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
298 Permit();
299 while(ncp->ncp_Task)
301 Wait(1L<<ncp->ncp_ReadySignal);
303 //FreeSignal(ncp->ncp_ReadySignal);
304 psdGetAttrs(PGA_DEVICE, ncp->ncp_Device, DA_ProductName, &devname, TAG_END);
305 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
306 "Not much moss of '%s' left.",
307 devname);
308 /*psdFreeVec(ncp);*/
309 CloseLibrary(ps);
312 /* \\\ */
314 /* /// "usbGetAttrsA()" */
315 AROS_LH3(LONG, usbGetAttrsA,
316 AROS_LHA(ULONG, type, D0),
317 AROS_LHA(APTR, usbstruct, A0),
318 AROS_LHA(struct TagItem *, tags, A1),
319 LIBBASETYPEPTR, nh, 5, nep)
321 AROS_LIBFUNC_INIT
323 struct TagItem *ti;
324 LONG count = 0;
326 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
327 switch(type)
329 case UGA_CLASS:
330 if((ti = FindTagItem(UCCA_Priority, tags)))
332 *((SIPTR *) ti->ti_Data) = 0;
333 count++;
335 if((ti = FindTagItem(UCCA_Description, tags)))
337 *((STRPTR *) ti->ti_Data) = "Ethernet SANA driver for MosChip MCS7830 chipset via usbmoschipeth.device";
338 count++;
340 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
342 *((IPTR *) ti->ti_Data) = TRUE;
343 count++;
345 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
347 *((IPTR *) ti->ti_Data) = TRUE;
348 count++;
350 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
352 *((IPTR *) ti->ti_Data) = FALSE;
353 count++;
355 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
357 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCP.ncp_UsingDefaultCfg;
358 count++;
360 break;
362 case UGA_BINDING:
363 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
365 *((IPTR *) ti->ti_Data) = ((struct NepClassEth *) usbstruct)->ncp_UsingDefaultCfg;
366 count++;
368 break;
370 return(count);
371 AROS_LIBFUNC_EXIT
373 /* \\\ */
375 /* /// "usbSetAttrsA()" */
376 AROS_LH3(LONG, usbSetAttrsA,
377 AROS_LHA(ULONG, type, D0),
378 AROS_LHA(APTR, usbstruct, A0),
379 AROS_LHA(struct TagItem *, tags, A1),
380 LIBBASETYPEPTR, nh, 6, nep)
382 AROS_LIBFUNC_INIT
383 return(0);
384 AROS_LIBFUNC_EXIT
386 /* \\\ */
388 /* /// "usbDoMethodA()" */
389 AROS_LH2(IPTR, usbDoMethodA,
390 AROS_LHA(ULONG, methodid, D0),
391 AROS_LHA(IPTR *, methoddata, A1),
392 LIBBASETYPEPTR, nh, 7, nep)
394 AROS_LIBFUNC_INIT
396 struct NepClassEth *ncp;
398 KPRINTF(10, ("Do Method %ld\n", methodid));
399 switch(methodid)
401 case UCM_AttemptDeviceBinding:
402 return((IPTR) usbAttemptDeviceBinding(nh, (struct PsdDevice *) methoddata[0]));
404 case UCM_ForceDeviceBinding:
405 return((IPTR) usbForceDeviceBinding(nh, (struct PsdDevice *) methoddata[0]));
407 case UCM_ReleaseDeviceBinding:
408 usbReleaseDeviceBinding(nh, (struct NepClassEth *) methoddata[0]);
409 return(TRUE);
411 case UCM_OpenCfgWindow:
412 return(nOpenBindingCfgWindow(nh, &nh->nh_DummyNCP));
414 case UCM_OpenBindingCfgWindow:
415 return(nOpenBindingCfgWindow(nh, (struct NepClassEth *) methoddata[0]));
417 case UCM_ConfigChangedEvent:
418 nLoadClassConfig(nh);
419 Forbid();
420 ncp = (struct NepClassEth *) nh->nh_Units.lh_Head;
421 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
423 nLoadBindingConfig(ncp);
424 ncp = (struct NepClassEth *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
426 Permit();
427 return(TRUE);
429 default:
430 break;
432 AROS_LIBFUNC_EXIT
433 return(0);
435 /* \\\ */
437 /* /// "nLoadClassConfig()" */
438 BOOL nLoadClassConfig(struct NepEthBase *nh)
440 struct NepClassEth *ncp = &nh->nh_DummyNCP;
441 struct Library *ps;
442 struct ClsDevCfg *cdc;
443 struct PsdIFFContext *pic;
445 KPRINTF(10, ("Loading Class Config...\n"));
446 if(ncp->ncp_GUITask)
448 return(FALSE);
450 if(!(ps = OpenLibrary("poseidon.library", 4)))
452 return(FALSE);
455 Forbid();
456 /* Create default config */
457 cdc = ncp->ncp_CDC;
458 cdc->cdc_ChunkID = AROS_LONG2BE(MAKE_ID('M','O','S','E'));
459 cdc->cdc_Length = AROS_LONG2BE(sizeof(struct ClsDevCfg)-8);
460 cdc->cdc_DefaultUnit = 0;
461 cdc->cdc_MediaType = 0;
462 ncp->ncp_UsingDefaultCfg = TRUE;
463 /* try to load default config */
464 pic = psdGetClsCfg(libname);
465 if(pic)
467 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncp->ncp_CDC->cdc_ChunkID));
468 if(cdc)
470 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
471 psdFreeVec(cdc);
472 ncp->ncp_UsingDefaultCfg = FALSE;
475 Permit();
476 CloseLibrary(ps);
477 return(FALSE);
479 /* \\\ */
481 /* /// "nLoadBindingConfig()" */
482 BOOL nLoadBindingConfig(struct NepClassEth *ncp)
484 struct NepEthBase *nh = ncp->ncp_ClsBase;
485 struct Library *ps;
486 struct ClsDevCfg *cdc;
487 struct PsdIFFContext *pic;
489 KPRINTF(10, ("Loading Binding Config...\n"));
490 if(ncp->ncp_GUITask)
492 return(FALSE);
494 //nLoadClassConfig(nh);
495 *ncp->ncp_CDC = *nh->nh_DummyNCP.ncp_CDC;
496 ncp->ncp_UsingDefaultCfg = TRUE;
498 if(!(ps = OpenLibrary("poseidon.library", 4)))
500 return(FALSE);
503 Forbid();
504 /* Load config */
505 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
506 if(pic)
508 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncp->ncp_CDC->cdc_ChunkID));
509 if(cdc)
511 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
512 psdFreeVec(cdc);
513 ncp->ncp_UsingDefaultCfg = FALSE;
516 Permit();
517 CloseLibrary(ps);
518 return(FALSE);
520 /* \\\ */
522 /* /// "nOpenBindingCfgWindow()" */
523 LONG nOpenBindingCfgWindow(struct NepEthBase *nh, struct NepClassEth *ncp)
525 struct Library *ps;
526 KPRINTF(10, ("Opening GUI...\n"));
527 if(!(ps = OpenLibrary("poseidon.library", 4)))
529 return(FALSE);
531 Forbid();
532 if(!ncp->ncp_GUITask)
534 if((ncp->ncp_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", nGUITask, ncp)))
536 Permit();
537 CloseLibrary(ps);
538 return(TRUE);
541 Permit();
542 CloseLibrary(ps);
543 return(FALSE);
545 /* \\\ */
547 /**************************************************************************/
549 #undef ps
550 #define ps ncp->ncp_Base
552 static char *MediaTypeStrings[] =
554 "Auto negotiation",
555 "10Base-T Half Duplex",
556 "10Base-T Full Duplex",
557 "100Base-TX Half Duplex",
558 "100Base-TX Full Duplex",
559 NULL
562 /* /// "nEthTask()" */
563 AROS_UFH0(void, nEthTask)
565 AROS_USERFUNC_INIT
567 struct NepClassEth *ncp;
568 struct PsdPipe *pp;
569 ULONG sigmask;
570 ULONG sigs;
571 LONG ioerr;
572 UBYTE *pktptr;
573 ULONG pktlen;
574 UWORD cnt;
575 LONG lastioerr = 0;
576 ULONG errcount = 0;
578 struct IOSana2Req *ioreq;
580 if((ncp = nAllocEth()))
582 Forbid();
583 if(ncp->ncp_ReadySigTask)
585 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
587 Permit();
589 if(nReadEEPROMMAC(ncp, ncp->ncp_ROMAddress))
591 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
593 // don't overwrite previously configured MAC Address
594 CopyMem(ncp->ncp_ROMAddress, ncp->ncp_MacAddress, ETHER_ADDR_SIZE);
596 } else {
597 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
598 "Couldn't read EEPROM for MAC Address, using preset one.");
599 if(!(ncp->ncp_StateFlags & DDF_CONFIGURED))
601 // don't overwrite previously configured MAC Address
602 CopyMem(ncp->ncp_ROMAddress, ncp->ncp_MacAddress, ETHER_ADDR_SIZE);
605 KPRINTF(10, ("MAC Address in EEPROM %02lx:%02lx:%02lx:%02lx:%02lx:%02lx\n",
606 ncp->ncp_MacAddress[0],
607 ncp->ncp_MacAddress[1],
608 ncp->ncp_MacAddress[2],
609 ncp->ncp_MacAddress[3],
610 ncp->ncp_MacAddress[4],
611 ncp->ncp_MacAddress[5]));
613 //if((!(ncp->ncp_StateFlags & DDF_OFFLINE)))// && (ncp->ncp_StateFlags & DDF_CONFIGURED))
615 /* Record start time_of_day */
616 //GetSysTime(&ncp->ncp_DeviceStats.LastStart);
617 nSetOnline(ncp);
620 /* Main task */
621 sigmask = (1L<<ncp->ncp_Unit.unit_MsgPort.mp_SigBit)|(1L<<ncp->ncp_TaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
624 // start transmitting read request if online...
625 if((ncp->ncp_StateFlags & DDF_ONLINE) && (ncp->ncp_ReadPending == NULL))
627 ncp->ncp_ReadPending = ncp->ncp_ReadBuffer[ncp->ncp_ReadBufNum];
628 psdSendPipe(ncp->ncp_EPInPipe, ncp->ncp_ReadPending, ETHER_MAX_LEN);
629 ncp->ncp_ReadBufNum ^= 1;
631 while((pp = (struct PsdPipe *) GetMsg(ncp->ncp_TaskMsgPort)))
633 KPRINTF(1, ("Pipe back %08lx\n", pp));
634 for(cnt = 0; cnt < 2; cnt++)
636 if(pp == ncp->ncp_EPOutPipe[cnt])
638 if((ioreq = ncp->ncp_WritePending[cnt]))
640 ioerr = psdGetPipeError(pp);
641 if(ioerr)
643 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
644 "Eth transmit failed: %s (%ld)",
645 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
647 /* Trigger any tx or generic error events */
648 nDoEvent(ncp, S2EVENT_ERROR|S2EVENT_TX);
650 /* Set error code and terminate the iorequest.
651 NOTE: Can't use RC_* or deverror() this is not
652 called from devBeginIO()!
654 ioreq->ios2_DataLength = 0;
655 ioreq->ios2_Req.io_Error = S2ERR_TX_FAILURE;
656 ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
657 psdDelayMS(50);
659 ReplyMsg((struct Message *) ioreq);
660 ncp->ncp_WritePending[cnt] = NULL;
662 break;
665 if(pp == ncp->ncp_EPInPipe)
667 if((pktptr = ncp->ncp_ReadPending))
669 ioerr = psdGetPipeError(pp);
670 pktlen = psdGetPipeActual(pp);
671 KPRINTF(1, ("ReadBack with %ld bytes (%ld).\n", pktlen, ioerr));
672 // interleave next packet reading ASAP.
673 if(ncp->ncp_StateFlags & DDF_ONLINE)
675 ncp->ncp_ReadPending = ncp->ncp_ReadBuffer[ncp->ncp_ReadBufNum];
676 psdSendPipe(ncp->ncp_EPInPipe, ncp->ncp_ReadPending, ETHER_MAX_LEN);
677 ncp->ncp_ReadBufNum ^= 1;
678 } else {
679 ncp->ncp_ReadPending = NULL;
681 if(ioerr)
683 if(lastioerr != ioerr)
685 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
686 "Eth receive failed: %s (%ld)",
687 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
688 errcount = 0;
689 } else {
690 errcount++;
691 if(errcount > 20)
693 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname,
694 "That's it, that device pissed me off long enough!");
695 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
698 lastioerr = ioerr;
699 psdDelayMS(50);
700 break;
701 } else {
702 KPRINTF(1, ("Pkt %ld received\n", pktlen));
703 DB(dumpmem(pktptr, pktlen));
704 nReadPacket(ncp, pktptr, pktlen);
710 while((ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
712 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
713 ioreq, ioreq->ios2_Req.io_Command, ioreq->ios2_DataLength));
714 switch(ioreq->ios2_Req.io_Command)
716 case S2_CONFIGINTERFACE:
717 //nWritePegRegs(ncp, ncp->ncp_MacAddress, ETHER_ADDR_SIZE, PEGREG_ETH_ID);
718 /* Now configured */
719 ncp->ncp_StateFlags |= DDF_CONFIGURED;
720 if(!(ncp->ncp_StateFlags & DDF_ONLINE))
722 nSetOnline(ncp);
724 ReplyMsg((struct Message *) ioreq);
725 break;
727 case S2_ADDMULTICASTADDRESS:
728 case S2_DELMULTICASTADDRESS:
729 case S2_ADDMULTICASTADDRESSES:
730 case S2_DELMULTICASTADDRESSES:
731 nUpdateRXMode(ncp);
732 ReplyMsg((struct Message *) ioreq);
733 break;
735 case S2_ONLINE:
736 nSetOnline(ncp);
737 ReplyMsg((struct Message *) ioreq);
738 break;
740 case S2_OFFLINE:
741 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, BMCR_PDOWN);
742 ReplyMsg((struct Message *) ioreq);
743 break;
745 default:
746 ioreq->ios2_Req.io_Error = IOERR_NOCMD;
747 ReplyMsg((struct Message *) ioreq);
748 break;
751 Forbid();
752 while((!ncp->ncp_WritePending[ncp->ncp_WriteBufNum]) && ncp->ncp_WriteQueue.lh_Head->ln_Succ)
754 ioreq = (struct IOSana2Req *) RemHead(&ncp->ncp_WriteQueue);
755 Permit();
756 nWritePacket(ncp, ioreq);
757 Forbid();
759 Permit();
760 sigs = Wait(sigmask);
761 } while(!(sigs & SIGBREAKF_CTRL_C));
763 Forbid();
764 /* Now remove all requests still pending *anywhere* */
765 //ncp->ncp_DenyRequests = TRUE;
766 /* Current transfers */
767 for(cnt = 0; cnt < 2; cnt++)
769 if((ioreq = ncp->ncp_WritePending[cnt]))
771 KPRINTF(1, ("Aborting pending write...\n"));
772 psdAbortPipe(ncp->ncp_EPOutPipe[cnt]);
773 psdWaitPipe(ncp->ncp_EPOutPipe[cnt]);
774 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
775 ReplyMsg((struct Message *) ioreq);
776 ncp->ncp_WritePending[cnt] = NULL;
779 if(ncp->ncp_ReadPending)
781 KPRINTF(1, ("Aborting pending read...\n"));
782 psdAbortPipe(ncp->ncp_EPInPipe);
783 psdWaitPipe(ncp->ncp_EPInPipe);
784 ncp->ncp_ReadPending = NULL;
786 /* Command queue */
787 /*while(ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort))
789 KPRINTF(1, ("Aborting pending requests...\n"));
790 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
791 ReplyMsg((struct Message *) ioreq);
793 Permit();
795 nDoEvent(ncp, S2EVENT_OFFLINE);
797 KPRINTF(20, ("Going down the river!\n"));
798 nFreeEth(ncp);
801 AROS_USERFUNC_EXIT
803 /* \\\ */
805 /* /// "nAllocEth()" */
806 struct NepClassEth * nAllocEth(void)
808 struct Task *thistask;
809 struct NepClassEth *ncp;
811 thistask = FindTask(NULL);
814 ncp = thistask->tc_UserData;
815 if(!(ncp->ncp_Base = OpenLibrary("poseidon.library", 4)))
817 Alert(AG_OpenLib);
818 break;
821 ncp->ncp_Interface = psdFindInterface(ncp->ncp_Device, NULL,
822 TAG_END);
824 if(!ncp->ncp_Interface)
826 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "No interface?");
827 break;
830 ncp->ncp_EPIn = psdFindEndpoint(ncp->ncp_Interface, NULL,
831 EA_IsIn, TRUE,
832 EA_TransferType, USEAF_BULK,
833 TAG_END);
834 ncp->ncp_EPOut = psdFindEndpoint(ncp->ncp_Interface, NULL,
835 EA_IsIn, FALSE,
836 EA_TransferType, USEAF_BULK,
837 TAG_END);
838 if(!(ncp->ncp_EPIn && ncp->ncp_EPOut))
840 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "IN or OUT endpoint missing!");
841 break;
844 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPOut,
845 EA_MaxPktSize, &ncp->ncp_EPOutMaxPktSize,
846 TAG_END);
848 ncp->ncp_ReadPending = NULL;
849 ncp->ncp_WritePending[0] = NULL;
850 ncp->ncp_WritePending[1] = NULL;
851 if(!(ncp->ncp_ReadBuffer[0] = AllocVec(ETHER_MAX_LEN * 4, MEMF_PUBLIC|MEMF_CLEAR)))
853 KPRINTF(1, ("Out of memory for read buffer\n"));
854 break;
856 ncp->ncp_ReadBuffer[1] = ncp->ncp_ReadBuffer[0] + ETHER_MAX_LEN;
857 ncp->ncp_WriteBuffer[0] = ncp->ncp_ReadBuffer[1] + ETHER_MAX_LEN;
858 ncp->ncp_WriteBuffer[1] = ncp->ncp_WriteBuffer[0] + ETHER_MAX_LEN;
859 ncp->ncp_Unit.unit_MsgPort.mp_SigBit = AllocSignal(-1);
860 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = thistask;
861 ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
862 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
864 if((ncp->ncp_TaskMsgPort = CreateMsgPort()))
866 if((ncp->ncp_EP0Pipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, NULL)))
868 if((ncp->ncp_EPOutPipe[0] = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPOut)))
870 /* Turn off short packets */
871 psdSetAttrs(PGA_PIPE, ncp->ncp_EPOutPipe[0],
872 PPA_NoShortPackets, FALSE,
873 PPA_NakTimeout, TRUE,
874 PPA_NakTimeoutTime, 5000,
875 TAG_END);
876 if((ncp->ncp_EPOutPipe[1] = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPOut)))
878 /* Turn off short packets */
879 psdSetAttrs(PGA_PIPE, ncp->ncp_EPOutPipe[1],
880 PPA_NoShortPackets, FALSE,
881 PPA_NakTimeout, TRUE,
882 PPA_NakTimeoutTime, 5000,
883 TAG_END);
884 if((ncp->ncp_EPInPipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPIn)))
886 /* Turn off short packets */
887 psdSetAttrs(PGA_PIPE, ncp->ncp_EPInPipe,
888 PPA_NakTimeout, FALSE,
889 PPA_NakTimeoutTime, 5000,
890 PPA_AllowRuntPackets, TRUE,
891 TAG_END);
892 ncp->ncp_Task = thistask;
894 if(nInitMCS(ncp))
896 return(ncp);
898 psdFreePipe(ncp->ncp_EPInPipe);
900 psdFreePipe(ncp->ncp_EPOutPipe[1]);
902 psdFreePipe(ncp->ncp_EPOutPipe[0]);
904 psdFreePipe(ncp->ncp_EP0Pipe);
906 DeleteMsgPort(ncp->ncp_TaskMsgPort);
908 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
909 } while(FALSE);
910 if(ncp->ncp_ReadBuffer[0])
912 FreeVec(ncp->ncp_ReadBuffer[0]);
913 ncp->ncp_ReadBuffer[0] = NULL;
915 CloseLibrary(ncp->ncp_Base);
916 Forbid();
917 ncp->ncp_Task = NULL;
918 if(ncp->ncp_ReadySigTask)
920 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
922 return(NULL);
924 /* \\\ */
926 /* /// "nFreeEth()" */
927 void nFreeEth(struct NepClassEth *ncp)
929 struct IOSana2Req *ioreq;
930 Forbid();
931 /* Disable the message port, messages may still be queued */
932 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = NULL;
933 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
934 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
935 // get rid of all messages that still have appeared here
936 while((ioreq = (struct IOSana2Req *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
938 ioreq->ios2_Req.io_Error = IOERR_ABORTED;
939 ReplyMsg((struct Message *) ioreq);
941 Permit();
943 psdFreePipe(ncp->ncp_EPInPipe);
944 psdFreePipe(ncp->ncp_EPOutPipe[0]);
945 psdFreePipe(ncp->ncp_EPOutPipe[1]);
946 psdFreePipe(ncp->ncp_EP0Pipe);
948 if(ncp->ncp_ReadBuffer[0])
950 FreeVec(ncp->ncp_ReadBuffer[0]);
951 ncp->ncp_ReadBuffer[0] = NULL;
954 DeleteMsgPort(ncp->ncp_TaskMsgPort);
955 CloseLibrary(ncp->ncp_Base);
956 Forbid();
957 ncp->ncp_Task = NULL;
958 if(ncp->ncp_ReadySigTask)
960 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
963 /* \\\ */
965 /* /// "nReadMCReg()" */
966 LONG nReadMCReg(struct NepClassEth *ncp, ULONG reg)
968 UBYTE result;
969 LONG ioerr;
971 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UMCR_READ_REG, 0, reg);
972 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, &result, 1);
973 if(ioerr)
975 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
976 "Reading MC Reg %ld failed: %s (%ld)",
977 reg,
978 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
979 return(-1);
981 KPRINTF(1, ("MC Reg(%ld)=%02lx (%ld)\n", reg, result, result));
982 return(result);
984 /* \\\ */
986 /* /// "nReadMCRegs()" */
987 LONG nReadMCRegs(struct NepClassEth *ncp, UBYTE *data, ULONG len, ULONG offset)
989 LONG ioerr;
991 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UMCR_READ_REG, 0, offset);
992 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, data, len);
993 if(ioerr)
995 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
996 "Reading MC Regs %ld-%ld failed: %s (%ld)",
997 offset, offset+len-1,
998 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1000 return(ioerr);
1002 /* \\\ */
1004 /* /// "nWriteMCReg()" */
1005 LONG nWriteMCReg(struct NepClassEth *ncp, ULONG reg, ULONG value)
1007 LONG ioerr;
1008 UBYTE buf[1];
1009 buf[0] = value;
1011 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UMCR_WRITE_REG, 0, reg);
1012 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, buf, 1);
1013 if(ioerr)
1015 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1016 "Writing MC Reg %ld with 0x%02lx failed: %s (%ld)",
1017 reg, value,
1018 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1020 return(ioerr);
1022 /* \\\ */
1024 /* /// "nWriteMCRegs()" */
1025 LONG nWriteMCRegs(struct NepClassEth *ncp, UBYTE *data, ULONG len, ULONG offset)
1027 LONG ioerr;
1029 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UMCR_WRITE_REG, 0, offset);
1030 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, data, len);
1031 if(ioerr)
1033 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1034 "Writing MC Regs %ld-%ld failed: %s (%ld)",
1035 offset, offset+len-1,
1036 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1038 return(ioerr);
1040 /* \\\ */
1042 /* /// "nReadEEPROMMAC()" */
1043 BOOL nReadEEPROMMAC(struct NepClassEth *ncp, UBYTE *macptr)
1045 LONG ioerr;
1046 ioerr = nReadMCRegs(ncp, macptr, ETHER_ADDR_SIZE, MCREG_ETH_ID);
1047 if(ioerr)
1049 KPRINTF(10, ("Couldn't read EEPROM %ld\n", ioerr));
1050 return(FALSE);
1052 return(TRUE);
1054 /* \\\ */
1056 /* /// "nReadPhyWord()" */
1057 LONG nReadPhyWord(struct NepClassEth *ncp, ULONG phyid, ULONG phyreg)
1059 UBYTE phyword[4];
1060 LONG ioerr;
1061 UWORD cnt;
1063 phyword[0] = 0;
1064 phyword[1] = 0;
1065 phyword[2] = MCRF_PHY_READ|phyid;
1066 phyword[3] = MCRF_PHY_PENDING|phyreg;
1067 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UMCR_WRITE_REG, 0, MCREG_PHY_DATA_LOW);
1068 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, phyword, 4);
1069 if(ioerr)
1071 KPRINTF(10, ("Error writing PHY control %ld\n", ioerr));
1072 return(-1);
1074 cnt = 10;
1077 psdDelayMS(1);
1078 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UMCR_READ_REG, 0, MCREG_PHY_DATA_LOW);
1079 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, phyword, 4);
1080 if(ioerr)
1082 KPRINTF(10, ("Error reading PHY data %ld\n", ioerr));
1083 return(-1);
1085 if(phyword[3] & MCRF_PHY_READY)
1087 return(phyword[0]|(phyword[1]<<8));
1089 } while(--cnt);
1090 KPRINTF(10, ("Timeout reading PHY data %ld\n", ioerr));
1091 return(-1);
1093 /* \\\ */
1095 /* /// "nWritePhyWord()" */
1096 BOOL nWritePhyWord(struct NepClassEth *ncp, ULONG phyid, ULONG phyreg, ULONG value)
1098 UBYTE phyword[4];
1099 LONG ioerr;
1100 UWORD cnt;
1102 phyword[0] = value;
1103 phyword[1] = value>>8;
1104 phyword[2] = MCRF_PHY_WRITE|phyid;
1105 phyword[3] = MCRF_PHY_PENDING|phyreg;
1106 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_OUT|URTF_DEVICE|URTF_VENDOR, UMCR_WRITE_REG, 0, MCREG_PHY_DATA_LOW);
1107 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, phyword, 4);
1108 if(ioerr)
1110 KPRINTF(10, ("Error writing PHY control %ld\n", ioerr));
1111 return(FALSE);
1113 cnt = 10;
1116 psdDelayMS(1);
1117 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_DEVICE|URTF_VENDOR, UMCR_READ_REG, 0, MCREG_PHY_CTRL);
1118 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, &phyword[3], 1);
1119 if(ioerr)
1121 KPRINTF(10, ("Error reading PHY control %ld\n", ioerr));
1122 return(FALSE);
1124 if(phyword[3] & MCRF_PHY_READY)
1126 return(TRUE);
1128 } while(--cnt);
1129 KPRINTF(10, ("Timeout reading PHY control %ld\n", ioerr));
1130 return(FALSE);
1132 /* \\\ */
1134 /* /// "nInitMCS()" */
1135 BOOL nInitMCS(struct NepClassEth *ncp)
1137 BOOL result = TRUE;
1139 ncp->ncp_PhyID = 1;
1141 result &= nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, BMCR_RESET);
1142 result &= nWritePhyWord(ncp, ncp->ncp_PhyID, MII_ADVERTISE, ADVERTISE_ALL|ADVERTISE_CSMA|ADVERTISE_PAUSE_CAP);
1144 if(!result)
1146 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname, "Failed to initialize adapter!");
1149 nUpdateRXMode(ncp);
1151 return(result);
1153 /* \\\ */
1155 /* /// "nUpdateRXMode()" */
1156 void nUpdateRXMode(struct NepClassEth *ncp)
1158 ULONG rxmode;
1159 LONG ioerr;
1160 rxmode = MCRF_CFG_TXEN;
1161 if(ncp->ncp_OpenFlags & SANA2OPF_PROM)
1163 rxmode |= MCRF_CFG_PROM;
1165 if(ncp->ncp_Multicasts.lh_Head->ln_Succ)
1167 rxmode |= MCRF_CFG_MCAST;
1170 if(ncp->ncp_Multicasts.lh_Head->ln_Succ)
1172 ioerr = nWriteMCRegs(ncp, ncp->ncp_MulticastArray, 8, MCREG_MCAST_ADDR);
1173 if(ioerr)
1175 KPRINTF(10, ("Error writing multicast filter %ld\n", ioerr));
1178 nWriteMCReg(ncp, MCREG_CFG, rxmode);
1180 /* \\\ */
1182 /* /// "nSetOnline()" */
1183 void nSetOnline(struct NepClassEth *ncp)
1185 LONG data;
1186 ULONG bmcr;
1187 BOOL autoneg = FALSE;
1188 BOOL linkgood = FALSE;
1189 UWORD timeout = 60;
1191 switch(ncp->ncp_CDC->cdc_MediaType)
1193 case MT_AUTO:
1194 KPRINTF(10, ("Autonegotiaton!\n"));
1195 bmcr = BMCR_ANENABLE|BMCR_ANRESTART;
1196 autoneg = TRUE;
1197 break;
1199 case MT_10BASE_T_HALF_DUP:
1200 bmcr = 0;
1201 //mediummode = 0;
1202 break;
1204 case MT_10BASE_T_FULL_DUP:
1205 bmcr = BMCR_FULLDPLX;
1206 break;
1208 case MT_100BASE_TX_HALF_DUP:
1209 bmcr = BMCR_SPEED1000;
1210 break;
1212 case MT_100BASE_TX_FULL_DUP:
1213 default:
1214 bmcr = BMCR_SPEED100|BMCR_FULLDPLX;
1215 break;
1218 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, bmcr);
1219 while(--timeout)
1221 psdDelayMS(50);
1222 data = nReadPhyWord(ncp, ncp->ncp_PhyID, MII_BMSR);
1223 KPRINTF(10, ("Status: %04lx\n", data));
1224 if(data < 0)
1226 timeout = 0;
1227 break;
1230 linkgood = (data & BMSR_LSTATUS);
1231 if((!autoneg) && linkgood)
1233 // no need to wait for autonegotiation
1234 break;
1237 // complete?
1238 if(data & BMSR_ANEGCOMPLETE)
1240 break;
1244 if(autoneg)
1246 STRPTR negstr = MediaTypeStrings[MT_100BASE_TX_FULL_DUP];
1247 if(timeout)
1249 KPRINTF(10, ("Auto neg successful!\n"));
1250 data = nReadPhyWord(ncp, ncp->ncp_PhyID, MII_LPA);
1251 KPRINTF(10, ("Auto neg state %04lx\n", data));
1252 if(data < 0)
1254 timeout = 0;
1256 if(data & ADVERTISE_100FULL)
1258 // 100Base-TX Full Duplex
1259 negstr = MediaTypeStrings[MT_100BASE_TX_FULL_DUP];
1261 else if(data & ADVERTISE_100HALF)
1263 // 100Base-TX Half Duplex
1264 negstr = MediaTypeStrings[MT_100BASE_TX_HALF_DUP];
1266 else if(data & ADVERTISE_10FULL)
1268 // 10Base-T Full Duplex
1269 negstr = MediaTypeStrings[MT_10BASE_T_FULL_DUP];
1271 else if(data & ADVERTISE_10HALF)
1273 // 10Base-T Half Duplex
1274 negstr = MediaTypeStrings[MT_10BASE_T_HALF_DUP];
1275 } else {
1276 timeout = 0;
1279 if(!timeout)
1281 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname, "Autonegotiation failed! Using %s instead.", negstr);
1282 nWritePhyWord(ncp, ncp->ncp_PhyID, MII_BMCR, BMCR_SPEED100|BMCR_FULLDPLX);
1283 } else {
1284 psdAddErrorMsg(RETURN_OK, (STRPTR) libname, "Autonegotiation: Using %s.", negstr);
1287 if(!linkgood)
1289 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "No link, check the plug and cable.");
1292 nUpdateRXMode(ncp);
1294 /* Now online */
1295 ncp->ncp_StateFlags |= DDF_ONLINE;
1296 ncp->ncp_StateFlags &= ~DDF_OFFLINE;
1297 /* Trigger any ONLINE events */
1298 nDoEvent(ncp, S2EVENT_ONLINE);
1300 /* \\\ */
1302 /* /// "nDoEvent()" */
1303 void nDoEvent(struct NepClassEth *ncp, ULONG events)
1305 struct IOSana2Req *worknode, *nextnode;
1307 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events));
1309 Forbid();
1310 /* Process pending S2_ONEVENT requests */
1311 worknode = (struct IOSana2Req *) ncp->ncp_EventList.lh_Head;
1312 while((nextnode = (struct IOSana2Req *) (((struct Node *) worknode)->ln_Succ)))
1314 if(worknode->ios2_WireError & events)
1316 Remove(&worknode->ios2_Req.io_Message.mn_Node);
1317 worknode->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
1318 KPRINTF(1, ("DoEvent: returned eventreq 0x%08lx\n", worknode));
1319 ReplyMsg(&worknode->ios2_Req.io_Message);
1321 worknode = nextnode;
1323 Permit();
1325 /* \\\ */
1327 /* /// "support routines" */
1328 static
1329 inline void *callcopy(void *routine,
1330 void *from,
1331 void *to,
1332 ULONG len)
1334 void * (*call) (APTR, APTR, ULONG) = routine;
1336 return (*call) (from, to, len);
1339 #define callfilter CallHookPkt
1340 /* \\\ */
1342 /* /// "nWritePacket()" */
1343 BOOL nWritePacket(struct NepClassEth *ncp, struct IOSana2Req *ioreq)
1345 ULONG packettype;
1346 struct EtherPacketHeader *eph;
1347 UBYTE *copydest;
1348 UWORD writelen;
1349 struct BufMan *bufman;
1350 struct Sana2PacketTypeStats *stats;
1351 UBYTE *buf = ncp->ncp_WriteBuffer[ncp->ncp_WriteBufNum];
1353 packettype = ioreq->ios2_PacketType;
1354 writelen = ioreq->ios2_DataLength;
1355 bufman = ioreq->ios2_BufferManagement;
1357 eph = (struct EtherPacketHeader *) buf;
1358 copydest = buf;
1360 /* Not a raw packet? */
1361 if(!(ioreq->ios2_Req.io_Flags & SANA2IOF_RAW))
1363 UWORD cnt;
1364 KPRINTF(10, ("RAW WRITE!\n"));
1365 /* The ethernet header isn't included in the data */
1366 /* Build ethernet packet header */
1367 for(cnt = 0; cnt < ETHER_ADDR_SIZE; cnt++)
1369 eph->eph_Dest[cnt] = ioreq->ios2_DstAddr[cnt];
1370 eph->eph_Src[cnt] = ncp->ncp_MacAddress[cnt];
1372 eph->eph_Type = AROS_WORD2BE(packettype);
1374 /* Packet data is at txbuffer */
1375 copydest += sizeof(struct EtherPacketHeader);
1376 writelen += sizeof(struct EtherPacketHeader);
1379 /* Dma not available, fallback to regular copy */
1380 if(callcopy(bufman->bm_CopyFromBuf, copydest, ioreq->ios2_Data, ioreq->ios2_DataLength) == NULL)
1382 KPRINTF(10, ("writepacket: copyfrom returned failure!\n"));
1384 /* Trigger any tx, buff or generic error events */
1385 nDoEvent(ncp, S2EVENT_ERROR|S2EVENT_TX|S2EVENT_BUFF);
1387 /* Set error code and terminate the iorequest.
1388 NOTE: Can't use RC_* or deverror() this is not
1389 called from devBeginIO()! */
1390 ioreq->ios2_DataLength = 0;
1391 ioreq->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1392 ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
1393 return FALSE;
1396 /* Adjust writelen to legal packet size. */
1397 if(writelen < ETHER_MIN_LEN)
1399 memset(buf + writelen, 0, ETHER_MIN_LEN - writelen);
1400 writelen = ETHER_MIN_LEN;
1402 KPRINTF(20, ("PktOut[%ld] %ld\n", ncp->ncp_WriteBufNum, writelen));
1404 ncp->ncp_WritePending[ncp->ncp_WriteBufNum] = ioreq;
1405 psdSendPipe(ncp->ncp_EPOutPipe[ncp->ncp_WriteBufNum], buf, (ULONG) writelen);
1406 ncp->ncp_WriteBufNum ^= 1;
1409 if(AROS_BE2WORD(eph->eph_Type) < ETHERPKT_SIZE)
1411 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx (IEEE802.3) len %lu, %lu bytes\n",
1412 *((UWORD *) eph->eph_Src), *((ULONG *) (eph->eph_Src + 2)),
1413 *((UWORD *) eph->eph_Dest), *((ULONG *) (eph->eph_Dest + 2)),
1414 AROS_BE2WORD(eph->eph_Type), writelen));
1415 } else {
1416 KPRINTF(5, ("writepacket: %04lx%08lx > %04lx%08lx type %lu, %lu bytes\n",
1417 *((UWORD *) eph->eph_Src), *((ULONG *) (eph->eph_Src + 2)),
1418 *((UWORD *) eph->eph_Dest), *((ULONG *) (eph->eph_Dest + 2)),
1419 AROS_BE2WORD(eph->eph_Type), writelen));
1421 //dumpmem(buf, (ULONG) writelen);
1424 /* Update statistics */
1425 stats = FindPacketTypeStats(ncp, packettype);
1426 if(stats)
1428 stats->PacketsSent++;
1429 stats->BytesSent += writelen;
1431 ncp->ncp_DeviceStats.PacketsSent++;
1433 return TRUE;
1435 /* \\\ */
1437 /* /// "nReadIOReq()" */
1438 UWORD nReadIOReq(struct NepClassEth *ncp, struct EtherPacketHeader *eph, UWORD datasize, struct IOSana2Req *ioreq, UWORD flags)
1440 LIBBASETYPEPTR nh = ncp->ncp_ClsBase;
1441 UBYTE *copyfrom;
1442 UWORD cnt;
1444 /* Handle RAW read */
1445 if(ioreq->ios2_Req.io_Flags & SANA2IOF_RAW)
1447 /* ShapeShifter won't work with `sizeof(struct etherpacket_hdr)'
1448 here. This is most likely because it want the RAW ethernet
1449 packet checksum size (4) added to the packet size. */
1450 copyfrom = (UBYTE *) eph;
1451 datasize += sizeof(struct EtherPacketHeader) + 4;
1452 } else {
1453 copyfrom = (UBYTE *) (eph + 1);
1456 /* Build up the ios2 structure enough so we can call the packet filter. */
1457 ioreq->ios2_PacketType = AROS_BE2WORD(eph->eph_Type);
1458 for(cnt = 0; cnt < ETHER_ADDR_SIZE; cnt++)
1460 ioreq->ios2_SrcAddr[cnt] = eph->eph_Src[cnt];
1461 ioreq->ios2_DstAddr[cnt] = eph->eph_Dest[cnt];
1463 ioreq->ios2_DataLength = datasize;
1464 /* Call the packet filter, if available. */
1465 if((flags & PACKETFILTER) &&
1466 (((struct BufMan *) ioreq->ios2_BufferManagement)->bm_PacketFilter) &&
1467 (!callfilter(((struct BufMan *) ioreq->ios2_BufferManagement)->bm_PacketFilter,
1468 ioreq, copyfrom)))
1470 /* This packet got dropped! */
1471 KPRINTF(7, ("readioreq: packet type %lu for ioreq 0x%08lx dropped\n",
1472 AROS_BE2WORD(eph->eph_Type), ioreq));
1473 return flags;
1477 /* Ok, the packet didn't get dropped, set the BCAST and MCAST
1478 flags according to dstaddr. */
1480 /* Address == Multicast? */
1481 if(ioreq->ios2_DstAddr[0] & 1)
1483 /* Address == Broadcast? */
1484 static const UBYTE bcast[ETHER_ADDR_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1485 if(memcmp(bcast, ioreq->ios2_DstAddr, ETHER_ADDR_SIZE) == 0)
1487 ioreq->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1488 } else {
1489 ioreq->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1493 /* Finally copy the packet data! */
1494 if(callcopy(((struct BufMan *) ioreq->ios2_BufferManagement)->bm_CopyToBuf,
1495 ioreq->ios2_Data, copyfrom, ioreq->ios2_DataLength))
1498 KPRINTF(5, ("readioreq: copytobuffed packet ior 0x%08lx, %04lx%08lx < %04lx%08lx, type %lu, %lu bytes, %s%s%s\n",
1499 ioreq,
1500 *((UWORD *) ioreq->ios2_DstAddr), *((ULONG *) (ioreq->ios2_DstAddr + 2)),
1501 *((UWORD *) ioreq->ios2_SrcAddr), *((ULONG *) (ioreq->ios2_SrcAddr + 2)),
1502 ioreq->ios2_PacketType, ioreq->ios2_DataLength,
1503 (ioreq->ios2_Req.io_Flags & SANA2IOF_RAW) ? "RAW " : "",
1504 (ioreq->ios2_Req.io_Flags & SANA2IOF_BCAST) ? "BCAST " : "",
1505 (ioreq->ios2_Req.io_Flags & SANA2IOF_MCAST) ? "MCAST " : ""));
1506 //dumpmem(copyfrom, ioreq->ios2_DataLength);
1509 /* Clear the dropped flag */
1510 flags &= ~DROPPED;
1511 } else {
1512 KPRINTF(10, ("readioreq: copyto returned failure!\n"));
1514 /* Trigger any rx, buff or generic error events */
1515 nDoEvent(ncp, S2EVENT_ERROR|S2EVENT_RX|S2EVENT_BUFF);
1517 /* Set error code.
1518 NOTE: Can't use RC_* or deverror() this is not called from devBeginIO()!
1520 ioreq->ios2_DataLength = 0;
1521 ioreq->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1522 ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
1525 /* Pull the ioreq off the list & terminate it */
1526 Forbid();
1527 Remove((struct Node *) ioreq);
1528 Permit();
1529 ReplyMsg((struct Message *) ioreq);
1530 return flags;
1532 /* \\\ */
1534 /* /// "nReadPacket()" */
1535 BOOL nReadPacket(struct NepClassEth *ncp, UBYTE *pktptr, ULONG pktlen)
1537 struct EtherPacketHeader *eph;
1538 struct BufMan *bufman;
1539 struct IOSana2Req *worknode, *nextnode;
1540 struct Sana2PacketTypeStats *stats;
1541 UWORD flags;
1542 UWORD datasize;
1543 BOOL ret = FALSE;
1544 UWORD statusbyte;
1546 KPRINTF(20, ("PktIn [%ld] %ld\n", ncp->ncp_ReadBufNum, pktlen));
1548 // loop over packet buffer for multiple packets on AX88178 and AX88772
1549 if(pktlen < 1)
1551 ncp->ncp_DeviceStats.BadData++;
1552 return FALSE;
1554 --pktlen;
1555 statusbyte = pktptr[pktlen];
1556 ncp->ncp_DeviceStats.PacketsReceived++;
1557 if(statusbyte != PKSF_NO_ERROR)
1559 if(statusbyte & PKSF_OVERRUN)
1561 ncp->ncp_DeviceStats.Overruns++;
1563 else if(statusbyte & (PKSF_UNDERRUN|PKSF_LENGTH_ERROR|PKSF_ALIGNMENT_ERROR|PKSF_CRC_ERROR))
1565 ncp->ncp_DeviceStats.BadData++;
1566 } else {
1567 ncp->ncp_DeviceStats.BadData++;
1569 } else {
1570 eph = (struct EtherPacketHeader *) pktptr;
1571 stats = FindPacketTypeStats(ncp, (ULONG) AROS_BE2WORD(eph->eph_Type));
1572 flags = DROPPED|PACKETFILTER;
1574 /* Calculate size of the actual data */
1575 datasize = pktlen - sizeof(struct EtherPacketHeader);
1577 /* Is the packet datasize valid? */
1578 if((pktlen >= ETHER_MIN_LEN) && (pktlen <= ETHER_MAX_LEN))
1580 /* Update the packet statistics */
1581 if(stats)
1583 stats->PacketsReceived++;
1584 stats->BytesReceived += datasize; /* NOTE: don't include headers */
1587 /* For each device user (bufman)
1588 NOTE: We absolutely *MUST* try to offer the packet to *all*
1589 different device users (SANA-II V2 spec requirement). */
1590 Forbid();
1591 bufman = (struct BufMan *) ncp->ncp_BufManList.lh_Head;
1592 while(((struct Node *) bufman)->ln_Succ)
1594 /* For each queued read request (ioreq) */
1595 worknode = (struct IOSana2Req *) bufman->bm_RXQueue.lh_Head;
1596 while((nextnode = (struct IOSana2Req *) (((struct Node *) worknode)->ln_Succ)))
1598 /* Check the packet type. Also handles 802.3 packets. */
1599 if((worknode->ios2_PacketType == AROS_BE2WORD(eph->eph_Type)) ||
1600 ((AROS_BE2WORD(eph->eph_Type) < ETHERPKT_SIZE) && (worknode->ios2_PacketType < ETHERPKT_SIZE)))
1602 flags = nReadIOReq(ncp, eph, datasize, worknode, flags);
1603 /* Break out - let other callers get the packet too */
1604 break;
1606 worknode = nextnode;
1608 bufman = (struct BufMan *) (((struct Node *) bufman)->ln_Succ);
1610 Permit();
1611 /* Now we've tried to give the packet to every CMD_READ caller.
1612 If DROPPED is set at this point no-one wanted this packet. */
1613 if(flags & DROPPED)
1615 /* So there were no outstanding CMD_READs or the packet wasn't
1616 accepted by any of them. Okay, check if we have any pending
1617 S2_READORPHAN ioreq in list and if we have return this packet
1618 with it. Note that packet filter must not be used for this
1619 time!
1621 NOTE: orphanlist is global, ie. only one caller will get the
1622 packet if multiple users have pending S2_READORPHANs.
1625 /* Process pending orphanread iorequs */
1626 Forbid();
1627 worknode = (struct IOSana2Req *) ncp->ncp_OrphanQueue.lh_Head;
1628 while((nextnode = (struct IOSana2Req *) (((struct Node *) worknode)->ln_Succ)))
1630 nReadIOReq(ncp, eph, datasize, worknode, 0);
1631 worknode = nextnode;
1633 Permit();
1634 } else {
1635 /* Packet not dropped - return ok */
1636 ret = TRUE;
1638 } else {
1639 KPRINTF(20, ("Pktlen %ld invalid!\n", pktlen));
1640 ncp->ncp_DeviceStats.BadData++;
1642 if(!ret)
1644 /* Update global dropped packet counter. */
1645 ncp->ncp_DeviceStats.UnknownTypesReceived++;
1647 /* Update dropped packet statistics. */
1648 if(stats)
1650 stats->PacketsDropped++;
1652 KPRINTF(9, ("readpacket: packet type %lu dropped\n", AROS_BE2WORD(eph->eph_Type)));
1654 /* Trigger any rx or generic error events */
1655 nDoEvent(ncp, S2EVENT_ERROR|S2EVENT_RX);
1658 return ret;
1660 /* \\\ */
1662 /**************************************************************************/
1664 /* /// "nGUITask()" */
1665 AROS_UFH0(void, nGUITask)
1667 AROS_USERFUNC_INIT
1669 struct Task *thistask;
1670 struct NepEthBase *nh;
1671 struct NepClassEth *ncp;
1672 struct PsdIFFContext *pic;
1674 thistask = FindTask(NULL);
1675 #undef ps
1676 #define ps ncp->ncp_PsdBase
1677 #undef IntuitionBase
1678 #define IntuitionBase ncp->ncp_IntBase
1679 #undef MUIMasterBase
1680 #define MUIMasterBase ncp->ncp_MUIBase
1682 ncp = thistask->tc_UserData;
1683 nh = ncp->ncp_ClsBase;
1685 ++nh->nh_Library.lib_OpenCnt;
1686 if(!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
1688 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
1689 nGUITaskCleanup(ncp);
1690 return;
1693 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
1695 KPRINTF(10, ("Couldn't open intuition.library.\n"));
1696 nGUITaskCleanup(ncp);
1697 return;
1699 if(!(ps = OpenLibrary("poseidon.library", 4)))
1701 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
1702 nGUITaskCleanup(ncp);
1703 return;
1706 ncp->ncp_App = ApplicationObject,
1707 MUIA_Application_Title , (IPTR)libname,
1708 MUIA_Application_Version , (IPTR)VERSION_STRING,
1709 MUIA_Application_Copyright , (IPTR)"©2008-2009 Harry Sintonen & Chris Hodges",
1710 MUIA_Application_Author , (IPTR)"Harry Sintonen <sintonen@iki.fi> & Chris Hodges <chrisly@platon42.de>",
1711 MUIA_Application_Description, (IPTR)"Settings for the moschipeth.class",
1712 MUIA_Application_Base , (IPTR)"MOSCHIPETH",
1713 MUIA_Application_HelpFile , (IPTR)"HELP:Poseidon.guide",
1714 MUIA_Application_Menustrip , (IPTR)MenustripObject,
1715 Child, (IPTR)MenuObjectT((IPTR)"Project"),
1716 Child, (IPTR)(ncp->ncp_AboutMI = MenuitemObject,
1717 MUIA_Menuitem_Title, (IPTR)"About...",
1718 MUIA_Menuitem_Shortcut, (IPTR)"?",
1719 End),
1720 End,
1721 Child, (IPTR)MenuObjectT((IPTR)"Settings"),
1722 Child, (IPTR)(ncp->ncp_UseMI = MenuitemObject,
1723 MUIA_Menuitem_Title, (IPTR)"Save",
1724 MUIA_Menuitem_Shortcut, (IPTR)"S",
1725 End),
1726 Child, (IPTR)(ncp->ncp_SetDefaultMI = MenuitemObject,
1727 MUIA_Menuitem_Title, (IPTR)"Set as Default",
1728 MUIA_Menuitem_Shortcut, (IPTR)"D",
1729 End),
1730 Child, (IPTR)MenuitemObject,
1731 MUIA_Menuitem_Title, (IPTR)NM_BARLABEL,
1732 End,
1733 Child, (IPTR)(ncp->ncp_MUIPrefsMI = MenuitemObject,
1734 MUIA_Menuitem_Title, (IPTR)"MUI Settings",
1735 MUIA_Menuitem_Shortcut, (IPTR)"M",
1736 End),
1737 End,
1738 End,
1740 SubWindow, (IPTR)(ncp->ncp_MainWindow = WindowObject,
1741 MUIA_Window_ID , MAKE_ID('M','A','I','N'),
1742 MUIA_Window_Title, (IPTR)libname,
1743 MUIA_HelpNode, (IPTR)libname,
1745 WindowContents, (IPTR)VGroup,
1746 Child, (IPTR)ColGroup(2), GroupFrameT((IPTR)(ncp->ncp_Interface ? "Device Settings" : "Default Device Settings")),
1747 //Child, HSpace(0),
1748 Child, (IPTR)Label((IPTR) "Media Type:"),
1749 Child, (IPTR)(ncp->ncp_MediaTypeObj = CycleObject,
1750 MUIA_CycleChain, 1,
1751 MUIA_Cycle_Entries, (IPTR)MediaTypeStrings,
1752 MUIA_Cycle_Active, ncp->ncp_CDC->cdc_MediaType,
1753 End),
1754 Child, (IPTR)Label((IPTR) "Default " DEVNAME " Unit:"),
1755 Child, (IPTR)(ncp->ncp_UnitObj = StringObject,
1756 StringFrame,
1757 MUIA_CycleChain, 1,
1758 MUIA_String_AdvanceOnCR, TRUE,
1759 MUIA_String_Integer, ncp->ncp_CDC->cdc_DefaultUnit,
1760 MUIA_String_Accept, (IPTR)"0123456789",
1761 End),
1762 End,
1763 Child, (IPTR)VSpace(0),
1764 Child, (IPTR)HGroup,
1765 MUIA_Group_SameWidth, TRUE,
1766 Child, (IPTR)(ncp->ncp_UseObj = TextObject, ButtonFrame,
1767 MUIA_ShowMe, (IPTR)ncp->ncp_Interface,
1768 MUIA_Background, MUII_ButtonBack,
1769 MUIA_CycleChain, 1,
1770 MUIA_InputMode, MUIV_InputMode_RelVerify,
1771 MUIA_Text_Contents, (IPTR)"\33c Save ",
1772 End),
1773 Child, (IPTR)(ncp->ncp_SetDefaultObj = TextObject, ButtonFrame,
1774 MUIA_Background, MUII_ButtonBack,
1775 MUIA_CycleChain, 1,
1776 MUIA_InputMode, MUIV_InputMode_RelVerify,
1777 MUIA_Text_Contents, (IPTR)(ncp->ncp_Interface ? "\33c Save as Default " : "\33c Save Defaults "),
1778 End),
1779 Child, (IPTR)(ncp->ncp_CloseObj = TextObject, ButtonFrame,
1780 MUIA_Background, MUII_ButtonBack,
1781 MUIA_CycleChain, 1,
1782 MUIA_InputMode, MUIV_InputMode_RelVerify,
1783 MUIA_Text_Contents, (IPTR)"\33c Use ",
1784 End),
1785 End,
1786 End,
1787 End),
1788 End;
1790 if(!ncp->ncp_App)
1792 KPRINTF(10, ("Couldn't create application\n"));
1793 nGUITaskCleanup(ncp);
1794 return;
1797 DoMethod(ncp->ncp_MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
1798 ncp->ncp_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
1799 DoMethod(ncp->ncp_UseObj, MUIM_Notify, MUIA_Pressed, FALSE,
1800 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
1801 DoMethod(ncp->ncp_SetDefaultObj, MUIM_Notify, MUIA_Pressed, FALSE,
1802 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
1803 DoMethod(ncp->ncp_CloseObj, MUIM_Notify, MUIA_Pressed, FALSE,
1804 ncp->ncp_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
1806 DoMethod(ncp->ncp_AboutMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1807 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_ABOUT);
1808 DoMethod(ncp->ncp_UseMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1809 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
1810 DoMethod(ncp->ncp_SetDefaultMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1811 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
1812 DoMethod(ncp->ncp_MUIPrefsMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1813 ncp->ncp_App, 2, MUIM_Application_OpenConfigWindow, 0);
1815 IPTR isopen = 0;
1816 IPTR iconify = 0;
1817 ULONG sigs;
1818 ULONG sigmask;
1819 LONG retid;
1821 get(ncp->ncp_App, MUIA_Application_Iconified, &iconify);
1822 set(ncp->ncp_MainWindow, MUIA_Window_Open, TRUE);
1823 get(ncp->ncp_MainWindow, MUIA_Window_Open, &isopen);
1824 if(!(isopen || iconify))
1826 nGUITaskCleanup(ncp);
1827 return;
1829 sigmask = 0;
1832 retid = DoMethod(ncp->ncp_App, MUIM_Application_NewInput, &sigs);
1833 switch(retid)
1835 case ID_DEF_CONFIG:
1836 case ID_STORE_CONFIG:
1837 case MUIV_Application_ReturnID_Quit:
1839 get(ncp->ncp_UnitObj, MUIA_String_Integer, &ncp->ncp_CDC->cdc_DefaultUnit);
1840 get(ncp->ncp_MediaTypeObj, MUIA_Cycle_Active, &ncp->ncp_CDC->cdc_MediaType);
1842 if(retid == ID_DEF_CONFIG)
1844 pic = psdGetClsCfg(libname);
1845 if(!pic)
1847 psdSetClsCfg(libname, NULL);
1848 pic = psdGetClsCfg(libname);
1850 if(pic)
1852 psdAddCfgEntry(pic, ncp->ncp_CDC);
1853 psdSaveCfgToDisk(NULL, FALSE);
1856 if(ncp->ncp_Interface)
1858 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
1859 if(!pic)
1861 psdSetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL, NULL);
1862 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
1864 if(pic)
1866 if(psdAddCfgEntry(pic, ncp->ncp_CDC))
1868 if(retid != MUIV_Application_ReturnID_Quit)
1870 psdSaveCfgToDisk(NULL, FALSE);
1872 retid = MUIV_Application_ReturnID_Quit;
1875 } else {
1876 retid = MUIV_Application_ReturnID_Quit;
1878 break;
1881 case ID_ABOUT:
1882 MUI_RequestA(ncp->ncp_App, ncp->ncp_MainWindow, 0, NULL, "Groovy!", VERSION_STRING, NULL);
1883 break;
1885 if(retid == MUIV_Application_ReturnID_Quit)
1887 break;
1889 if(sigs)
1891 sigs = Wait(sigs|sigmask|SIGBREAKF_CTRL_C);
1892 if(sigs & SIGBREAKF_CTRL_C)
1894 break;
1897 } while(TRUE);
1898 set(ncp->ncp_MainWindow, MUIA_Window_Open, FALSE);
1900 nGUITaskCleanup(ncp);
1902 AROS_USERFUNC_EXIT
1904 /* \\\ */
1906 /* /// "nGUITaskCleanup()" */
1907 void nGUITaskCleanup(struct NepClassEth *ncp)
1909 if(ncp->ncp_App)
1911 MUI_DisposeObject(ncp->ncp_App);
1912 ncp->ncp_App = NULL;
1914 if(MUIMasterBase)
1916 CloseLibrary(MUIMasterBase);
1917 MUIMasterBase = NULL;
1919 if(IntuitionBase)
1921 CloseLibrary(IntuitionBase);
1922 IntuitionBase = NULL;
1924 if(ps)
1926 CloseLibrary(ps);
1927 ps = NULL;
1929 Forbid();
1930 ncp->ncp_GUIBinding = NULL;
1931 ncp->ncp_GUITask = NULL;
1932 if(ncp->ncp_ReadySigTask)
1934 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1936 --ncp->ncp_ClsBase->nh_Library.lib_OpenCnt;
1938 /* \\\ */