2 *----------------------------------------------------------------------------
3 * pegasus class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "pegasus.class.h"
13 static const STRPTR libname
= MOD_NAME_STRING
;
16 const APTR DevFuncTable
[] =
18 &AROS_SLIB_ENTRY(devOpen
, dev
, 1),
19 &AROS_SLIB_ENTRY(devClose
, dev
, 2),
20 &AROS_SLIB_ENTRY(devExpunge
, dev
, 3),
21 &AROS_SLIB_ENTRY(devReserved
, dev
, 4),
22 &AROS_SLIB_ENTRY(devBeginIO
, dev
, 5),
23 &AROS_SLIB_ENTRY(devAbortIO
, dev
, 6),
27 static int libInit(LIBBASETYPEPTR nh
)
29 struct NepClassEth
*ncp
;
30 struct NepEthBase
*ret
= NULL
;
32 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh
, SysBase
));
34 nh
->nh_UtilityBase
= OpenLibrary("utility.library", 39);
36 #define UtilityBase nh->nh_UtilityBase
40 NewList(&nh
->nh_Units
);
42 if((nh
->nh_DevBase
= (struct NepEthDevBase
*) MakeLibrary((APTR
) DevFuncTable
, NULL
, (APTR
) devInit
,
43 sizeof(struct NepEthDevBase
), NULL
)))
45 ncp
= &nh
->nh_DummyNCP
;
46 ncp
->ncp_ClsBase
= nh
;
47 ncp
->ncp_Interface
= NULL
;
48 ncp
->ncp_CDC
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
51 nh
->nh_DevBase
->np_ClsBase
= nh
;
53 AddDevice((struct Device
*) nh
->nh_DevBase
);
54 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
++;
59 KPRINTF(20, ("failed to create usbparallel.device\n"));
63 CloseLibrary(UtilityBase
);
66 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
69 KPRINTF(10, ("libInit: Ok\n"));
70 return(ret
? TRUE
: FALSE
);
73 static int libOpen(LIBBASETYPEPTR nh
)
75 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh
));
80 static int libExpunge(LIBBASETYPEPTR nh
)
82 struct NepClassEth
*ncp
;
84 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh
));
86 if(nh
->nh_DevBase
->np_Library
.lib_OpenCnt
== 1)
88 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%08lx\n",
90 CloseLibrary((struct Library
*) UtilityBase
);
92 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
93 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
95 Remove((struct Node
*) ncp
);
96 FreeVec(ncp
->ncp_CDC
);
98 ncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
101 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
--;
102 RemDevice((struct Device
*) nh
->nh_DevBase
);
104 KPRINTF(5, ("libExpunge: Unloading done! pegasus.class expunged!\n\n"));
106 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
113 ADD2INITLIB(libInit
, 0)
114 ADD2OPENLIB(libOpen
, 0)
115 ADD2EXPUNGELIB(libExpunge
, 0)
119 * ***********************************************************************
120 * * Library functions *
121 * ***********************************************************************
128 UWORD abd_PatchFlags
;
131 struct AutoBindData ClassBinds
[] =
133 { 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
207 /* /// "usbAttemptDeviceBinding()" */
208 struct NepClassEth
* usbAttemptDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
211 struct AutoBindData
*abd
= ClassBinds
;
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
,
224 while(abd
->abd_VendID
)
226 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
228 return(usbForceDeviceBinding(nh
, pd
));
237 /* /// "usbForceDeviceBinding()" */
238 struct NepClassEth
* usbForceDeviceBinding(struct NepEthBase
*nh
, struct PsdDevice
*pd
)
241 struct NepClassEth
*ncp
;
242 struct NepClassEth
*tmpncp
;
243 struct ClsDevCfg
*cdc
;
244 struct AutoBindData
*abd
= ClassBinds
;
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
,
267 while(abd
->abd_VendID
)
269 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
271 patchflags
= abd
->abd_PatchFlags
;
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
;
288 ncp
= (struct NepClassEth
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
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
)))
300 ncp
->ncp_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
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
)
338 tmpncp
= (struct NepClassEth
*) nh
->nh_Units
.lh_Head
;
340 tmpncp
= (struct NepClassEth
*) tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
344 ncp
->ncp_UnitNo
= unitno
;
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
);
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
,
367 ncp
->ncp_ReadySigTask
= NULL
;
368 //FreeSignal(ncp->ncp_ReadySignal);
369 /* Get rid of unit structure */
371 Remove((struct Node *) ncp);
372 FreeVec(ncp->ncp_CDC);
381 /* /// "usbReleaseDeviceBinding()" */
382 void usbReleaseDeviceBinding(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
386 KPRINTF(1, ("nepEthReleaseDeviceBinding(%08lx)\n", ncp
));
388 if((ps
= OpenLibrary("poseidon.library", 4)))
391 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
392 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
395 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
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.",
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
)
425 KPRINTF(1, ("nepEthGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
429 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
431 *((SIPTR
*) ti
->ti_Data
) = 0;
434 if((ti
= FindTagItem(UCCA_Description
, tags
)))
436 *((STRPTR
*) ti
->ti_Data
) = "Ethernet SANA driver for Pegasus chipsets via usbpegasus.device";
439 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
441 *((IPTR
*) ti
->ti_Data
) = TRUE
;
444 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
446 *((IPTR
*) ti
->ti_Data
) = TRUE
;
449 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
451 *((IPTR
*) ti
->ti_Data
) = FALSE
;
454 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
456 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCP
.ncp_UsingDefaultCfg
;
462 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
464 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassEth
*) usbstruct
)->ncp_UsingDefaultCfg
;
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
)
487 /* /// "usbDoMethodA()" */
488 AROS_LH2(IPTR
, usbDoMethodA
,
489 AROS_LHA(ULONG
, methodid
, D0
),
490 AROS_LHA(IPTR
*, methoddata
, A1
),
491 LIBBASETYPEPTR
, nh
, 7, nep
)
495 struct NepClassEth
*ncp
;
497 KPRINTF(10, ("Do Method %ld\n", 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]);
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
);
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
;
536 /* /// "nLoadClassConfig()" */
537 BOOL
nLoadClassConfig(struct NepEthBase
*nh
)
539 struct NepClassEth
*ncp
= &nh
->nh_DummyNCP
;
541 struct ClsDevCfg
*cdc
;
542 struct PsdIFFContext
*pic
;
544 KPRINTF(10, ("Loading Class Config...\n"));
549 if(!(ps
= OpenLibrary("poseidon.library", 4)))
555 /* Create default config */
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
);
566 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
569 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
571 ncp
->ncp_UsingDefaultCfg
= FALSE
;
580 /* /// "nLoadBindingConfig()" */
581 BOOL
nLoadBindingConfig(struct NepClassEth
*ncp
)
583 struct NepEthBase
*nh
= ncp
->ncp_ClsBase
;
585 struct ClsDevCfg
*cdc
;
586 struct PsdIFFContext
*pic
;
588 KPRINTF(10, ("Loading Binding Config...\n"));
593 //nLoadClassConfig(nh);
594 *ncp
->ncp_CDC
= *nh
->nh_DummyNCP
.ncp_CDC
;
595 ncp
->ncp_UsingDefaultCfg
= TRUE
;
597 if(!(ps
= OpenLibrary("poseidon.library", 4)))
604 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
607 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
610 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
612 ncp
->ncp_UsingDefaultCfg
= FALSE
;
621 /* /// "nOpenBindingCfgWindow()" */
622 LONG
nOpenBindingCfgWindow(struct NepEthBase
*nh
, struct NepClassEth
*ncp
)
625 KPRINTF(10, ("Opening GUI...\n"));
626 if(!(ps
= OpenLibrary("poseidon.library", 4)))
631 if(!ncp
->ncp_GUITask
)
633 if((ncp
->ncp_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", nGUITask
, ncp
)))
646 /**************************************************************************/
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
)
658 struct NepClassEth
*ncp
;
669 struct IOSana2Req
*ioreq
;
671 if((ncp
= nAllocEth()))
674 if(ncp
->ncp_ReadySigTask
)
676 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
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
);
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
);
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);
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
);
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
;
754 ReplyMsg((struct Message
*) ioreq
);
755 ncp
->ncp_WritePending
[cnt
] = NULL
;
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;
774 ncp
->ncp_ReadPending
= NULL
;
778 if(lastioerr
!= ioerr
)
780 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
781 "Eth receive failed: %s (%ld)",
782 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
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
);
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
);
816 ncp
->ncp_StateFlags
|= DDF_CONFIGURED
;
817 if(!(ncp
->ncp_StateFlags
& DDF_ONLINE
))
821 ReplyMsg((struct Message
*) ioreq
);
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
;
833 ncp
->ncp_EthCtrl
[0] &= ~RX_MULTICAST
;
835 nWritePegReg(ncp
, PEGREG_ETH_CTRL0
, (ULONG
) ncp
->ncp_EthCtrl
[0]);
836 ReplyMsg((struct Message
*) ioreq
);
841 ReplyMsg((struct Message
*) ioreq
);
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
);
854 ioreq
->ios2_Req
.io_Error
= IOERR_NOCMD
;
855 ReplyMsg((struct Message
*) ioreq
);
860 while((!ncp
->ncp_WritePending
[ncp
->ncp_WriteBufNum
]) && ncp
->ncp_WriteQueue
.lh_Head
->ln_Succ
)
862 ioreq
= (struct IOSana2Req
*) RemHead(&ncp
->ncp_WriteQueue
);
864 nWritePacket(ncp
, ioreq
);
868 sigs
= Wait(sigmask
);
869 } while(!(sigs
& SIGBREAKF_CTRL_C
));
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
;
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);
903 nDoEvent(ncp
, S2EVENT_OFFLINE
);
905 KPRINTF(20, ("Going down the river!\n"));
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)))
929 ncp
->ncp_Interface
= psdFindInterface(ncp
->ncp_Device
, NULL
,
932 if(!ncp
->ncp_Interface
)
934 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "No interface?");
938 ncp
->ncp_EPIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
940 EA_TransferType
, USEAF_BULK
,
942 ncp
->ncp_EPOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
944 EA_TransferType
, USEAF_BULK
,
946 if(!(ncp
->ncp_EPIn
&& ncp
->ncp_EPOut
))
948 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
952 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPOut
,
953 EA_MaxPktSize
, &ncp
->ncp_EPOutMaxPktSize
,
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"));
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,
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,
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
,
1000 ncp
->ncp_Task
= thistask
;
1002 if(nInitPegasus(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
);
1018 if(ncp
->ncp_ReadBuffer
[0])
1020 FreeVec(ncp
->ncp_ReadBuffer
[0]);
1021 ncp
->ncp_ReadBuffer
[0] = NULL
;
1023 CloseLibrary(ncp
->ncp_Base
);
1025 ncp
->ncp_Task
= NULL
;
1026 if(ncp
->ncp_ReadySigTask
)
1028 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
1034 /* /// "nFreeEth()" */
1035 void nFreeEth(struct NepClassEth
*ncp
)
1037 struct IOSana2Req
*ioreq
;
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
);
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
);
1065 ncp
->ncp_Task
= NULL
;
1066 if(ncp
->ncp_ReadySigTask
)
1068 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
1073 /* /// "nReadPegReg()" */
1074 LONG
nReadPegReg(struct NepClassEth
*ncp
, ULONG reg
)
1079 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UPGR_GET_REGS
, 0, reg
);
1080 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, &result
, 1);
1083 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1084 "Reading Peg Reg %ld failed: %s (%ld)",
1086 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1093 /* /// "nReadPegRegs()" */
1094 LONG
nReadPegRegs(struct NepClassEth
*ncp
, UBYTE
*data
, ULONG len
, ULONG offset
)
1098 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_DEVICE
|URTF_VENDOR
, UPGR_GET_REGS
, 0, offset
);
1099 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, data
, len
);
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
);
1111 /* /// "nWritePegReg()" */
1112 LONG
nWritePegReg(struct NepClassEth
*ncp
, ULONG reg
, ULONG value
)
1114 UBYTE byteval
= value
;
1117 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UPGR_SET_REGS
, value
, reg
);
1118 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, &byteval
, 1);
1121 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1122 "Writing Peg Reg %ld with 0x%02lx failed: %s (%ld)",
1124 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1130 /* /// "nWritePegRegs()" */
1131 LONG
nWritePegRegs(struct NepClassEth
*ncp
, UBYTE
*data
, ULONG len
, ULONG offset
)
1135 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_OUT
|URTF_DEVICE
|URTF_VENDOR
, UPGR_SET_REGS
, 0, offset
);
1136 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, data
, len
);
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
);
1148 /* /// "nReadEEPROMMAC()" */
1149 BOOL
nReadEEPROMMAC(struct NepClassEth
*ncp
, UBYTE
*macptr
)
1157 for(cnt
= 0; cnt
< 3; cnt
++)
1159 ioerr
= nWritePegReg(ncp
, PEGREG_EEPROM_CTRL
, 0x00);
1162 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1163 "Writing eeprom ctrl %ld = 0 failed: %s (%ld)",
1165 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1168 ioerr
= nWritePegReg(ncp
, PEGREG_EEPROM_OFFSET
, cnt
);
1171 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1172 "Writing eeprom offset %ld failed: %s (%ld)",
1174 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1177 ioerr
= nWritePegReg(ncp
, PEGREG_EEPROM_CTRL
, EEPROM_READ
);
1180 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1181 "Writing eeprom ctrl %ld read failed: %s (%ld)",
1183 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1190 data
= nReadPegReg(ncp
, PEGREG_EEPROM_CTRL
);
1195 if(data
& EEPROM_DONE
)
1203 KPRINTF(20, ("Timeout waiting for EEPROM to respond (word %ld)!\n", cnt
));
1206 ioerr
= nReadPegRegs(ncp
, eeword
, 2, PEGREG_EEPROM_DATA_LOW
);
1209 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
1210 "Reading eeprom data low %ld failed: %s (%ld)",
1212 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1215 *macptr
++ = eeword
[0];
1216 *macptr
++ = eeword
[1];
1223 /* /// "nReadPhyWord()" */
1224 LONG
nReadPhyWord(struct NepClassEth
*ncp
, ULONG phyid
, ULONG phyreg
)
1231 ioerr
= nWritePegReg(ncp
, PEGREG_PHY_CTRL
, 0x00);
1236 ioerr
= nWritePegReg(ncp
, PEGREG_PHY_ADDR
, phyid
);
1241 ioerr
= nWritePegReg(ncp
, PEGREG_PHY_CTRL
, PHY_READ
|phyreg
);
1250 data
= nReadPegReg(ncp
, PEGREG_PHY_CTRL
);
1263 KPRINTF(20, ("Timeout waiting for PHY %ld to respond (read reg %ld)!\n", phyid
, phyreg
));
1266 ioerr
= nReadPegRegs(ncp
, phyword
, 2, PEGREG_PHY_DATA_LOW
);
1271 return(phyword
[0]|(phyword
[1]<<8));
1275 /* /// "nWritePhyWord()" */
1276 BOOL
nWritePhyWord(struct NepClassEth
*ncp
, ULONG phyid
, ULONG phyreg
, ULONG value
)
1286 row
[3] = PHY_WRITE
|phyreg
;
1288 ioerr
= nWritePegReg(ncp
, PEGREG_PHY_CTRL
, 0x00);
1293 ioerr
= nWritePegRegs(ncp
, row
, 4, PEGREG_PHY_ADDR
);
1302 data
= nReadPegReg(ncp
, PEGREG_PHY_CTRL
);
1315 KPRINTF(20, ("Timeout waiting for PHY %ld to respond (write reg %ld=%04lx)!\n", phyid
, phyreg
, value
));
1322 /* /// "nInitPegasus()" */
1323 BOOL
nInitPegasus(struct NepClassEth
*ncp
)
1329 ioerr
= nWritePegReg(ncp
, PEGREG_ETH_CTRL1
, 0x08);
1337 data
= nReadPegReg(ncp
, PEGREG_ETH_CTRL1
);
1348 KPRINTF(10, ("Time %ld\n", timeout
));
1351 KPRINTF(20, ("Timeout waiting for reset to be released.\n"));
1354 ioerr
= nWritePegReg(ncp
, PEGREG_GPIO1
, DEFAULT_GPIO_SET
);
1360 //ioerr = nWritePegReg(ncp, PEGREG_GPIO0, DEFAULT_GPIO_RESET);
1361 ioerr
= nWritePegReg(ncp
, PEGREG_GPIO0
, 0x06);
1366 ioerr
= nWritePegReg(ncp
, PEGREG_GPIO0
, DEFAULT_GPIO_SET
);
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
);
1382 if(ncp
->ncp_PatchFlags
& PF_PEG2
)
1384 KPRINTF(10, ("Pegasus II setup...\n"));
1385 ioerr
= nWritePegReg(ncp
, PEGREG_REG_1D
, 0x00);
1391 ioerr
= nWritePegReg(ncp
, PEGREG_REG_7B
, 0x01);
1399 ioerr
= nWritePegReg(ncp
, PEGREG_REG_7B
, 0x02);
1405 // detect 8513 chipset
1406 ioerr
= nWritePegReg(ncp
, PEGREG_REG_83
, 0xa5);
1411 data
= nReadPegReg(ncp
, PEGREG_REG_83
);
1418 KPRINTF(10, ("Chipset is 8513!\n"));
1419 ncp
->ncp_PatchFlags
|= PF_CHIP_8513
;
1422 ioerr
= nWritePegReg(ncp
, PEGREG_REG_80
, 0xc0);
1427 ioerr
= nWritePegReg(ncp
, PEGREG_REG_83
, 0xff);
1432 ioerr
= nWritePegReg(ncp
, PEGREG_REG_84
, 0x01);
1437 ioerr
= nWritePegReg(ncp
, PEGREG_REG_81
, 0x02);
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
))
1454 if(ncp
->ncp_PhyID
== 32)
1456 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
, "Couldn't identify PHY, using 1 as default.");
1464 /* /// "nSetOnline()" */
1465 void nSetOnline(struct NepClassEth
*ncp
)
1469 BOOL autoneg
= FALSE
;
1470 BOOL linkgood
= FALSE
;
1473 switch(ncp
->ncp_CDC
->cdc_MediaType
)
1476 KPRINTF(10, ("Autonegotiaton!\n"));
1477 bmcr
= BMCR_ANENABLE
|BMCR_ANRESTART
;
1481 case MT_10BASE_T_HALF_DUP
:
1483 ncp
->ncp_EthCtrl
[1] = 0x00;
1486 case MT_10BASE_T_FULL_DUP
:
1487 bmcr
= BMCR_FULLDPLX
;
1488 ncp
->ncp_EthCtrl
[1] = 0x20;
1491 case MT_100BASE_TX_HALF_DUP
:
1492 bmcr
= BMCR_SPEED100
;
1493 ncp
->ncp_EthCtrl
[1] = 0x10;
1496 case MT_100BASE_TX_FULL_DUP
:
1498 bmcr
= BMCR_SPEED100
|BMCR_FULLDPLX
;
1499 ncp
->ncp_EthCtrl
[1] = 0x30;
1503 nWritePhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMCR
, bmcr
);
1507 data
= nReadPhyWord(ncp
, ncp
->ncp_PhyID
, MII_BMSR
);
1508 KPRINTF(10, ("Status: %04lx\n", data
));
1515 linkgood
= (data
& BMSR_LSTATUS
);
1516 if((!autoneg
) && linkgood
)
1518 // no need to wait for autonegotiation
1523 if(data
& BMSR_ANEGCOMPLETE
)
1531 STRPTR negstr
= NULL
;
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
));
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
];
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;
1575 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
, "Autonegotiation: Using %s.", negstr
);
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);
1602 ncp
->ncp_StateFlags
|= DDF_ONLINE
;
1603 ncp
->ncp_StateFlags
&= ~DDF_OFFLINE
;
1604 /* Trigger any ONLINE events */
1605 nDoEvent(ncp
, S2EVENT_ONLINE
);
1609 /* /// "nDoEvent()" */
1610 void nDoEvent(struct NepClassEth
*ncp
, ULONG events
)
1612 struct IOSana2Req
*worknode
, *nextnode
;
1614 KPRINTF(1, ("DoEvent events: 0x%08lx\n", events
));
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
;
1634 /* /// "support routines" */
1636 inline void *callcopy(void *routine
,
1641 void * (*call
) (APTR
, APTR
, ULONG
) = routine
;
1643 return (*call
) (from
, to
, len
);
1646 #define callfilter CallHookPkt
1649 /* /// "nWritePacket()" */
1650 BOOL
nWritePacket(struct NepClassEth
*ncp
, struct IOSana2Req
*ioreq
)
1653 struct EtherPacketHeader
*eph
;
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];
1664 writelen
= ioreq
->ios2_DataLength
;
1665 bufman
= ioreq
->ios2_BufferManagement
;
1667 /* Not a raw packet? */
1668 if(!(ioreq
->ios2_Req
.io_Flags
& SANA2IOF_RAW
))
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
;
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
;
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)))
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
));
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
);
1749 stats
->PacketsSent
++;
1750 stats
->BytesSent
+= writelen
;
1752 ncp
->ncp_DeviceStats
.PacketsSent
++;
1758 /* /// "nReadIOReq()" */
1759 UWORD
nReadIOReq(struct NepClassEth
*ncp
, struct EtherPacketHeader
*eph
, UWORD datasize
, struct IOSana2Req
*ioreq
, UWORD flags
)
1761 LIBBASETYPEPTR nh
= ncp
->ncp_ClsBase
;
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;
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
,
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
));
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
;
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",
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 */
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
);
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 */
1848 Remove((struct Node
*) ioreq
);
1850 ReplyMsg((struct Message
*) ioreq
);
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
;
1867 KPRINTF(10, ("PktIn [%ld] %ld\n", ncp
->ncp_ReadBufNum
, len
));
1871 ncp
->ncp_DeviceStats
.BadData
++;
1874 if(ncp
->ncp_PatchFlags
& PF_CHIP_8513
)
1876 // this chipset has the length at the beginning instead of the end
1878 pktlen
+= (*pktptr
++ & 0x0f)<<8;
1880 pktlen
= pktptr
[len
-4]|((pktptr
[len
-3] & 0x0f)<<8);
1883 ncp
->ncp_DeviceStats
.BadData
++;
1888 status
= pktptr
[len
-2]|(pktptr
[len
-1]<<8);
1891 KPRINTF(20, ("Error %02lx\n", status
));
1894 ncp
->ncp_DeviceStats
.Overruns
++;
1898 ncp
->ncp_DeviceStats
.BadData
++;
1902 if(len
!= pktlen
+ 8)
1904 KPRINTF(20, ("Pktlen %ld != len %ld\n", pktlen
+ 8, len
));
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 */
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). */
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 */
1945 worknode
= nextnode
;
1947 bufman
= (struct BufMan
*) (((struct Node
*) bufman
)->ln_Succ
);
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. */
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
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 */
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
;
1974 /* Packet not dropped - return ok */
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. */
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
);
1997 /**************************************************************************/
1999 /* /// "nGUITask()" */
2000 AROS_UFH0(void, nGUITask
)
2004 struct Task
*thistask
;
2005 struct NepEthBase
*nh
;
2006 struct NepClassEth
*ncp
;
2007 struct PsdIFFContext
*pic
;
2009 thistask
= FindTask(NULL
);
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
);
2028 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
2030 KPRINTF(10, ("Couldn't open intuition.library.\n"));
2031 nGUITaskCleanup(ncp
);
2034 if(!(ps
= OpenLibrary("poseidon.library", 4)))
2036 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
2037 nGUITaskCleanup(ncp
);
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
)"?",
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",
2061 Child
, (IPTR
)(ncp
->ncp_SetDefaultMI
= MenuitemObject
,
2062 MUIA_Menuitem_Title
, (IPTR
)"Set as Default",
2063 MUIA_Menuitem_Shortcut
, (IPTR
)"D",
2065 Child
, (IPTR
)MenuitemObject
,
2066 MUIA_Menuitem_Title
, (IPTR
)NM_BARLABEL
,
2068 Child
, (IPTR
)(ncp
->ncp_MUIPrefsMI
= MenuitemObject
,
2069 MUIA_Menuitem_Title
, (IPTR
)"MUI Settings",
2070 MUIA_Menuitem_Shortcut
, (IPTR
)"M",
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
,
2086 MUIA_Cycle_Entries
, (IPTR
)MediaTypeStrings
,
2087 MUIA_Cycle_Active
, ncp
->ncp_CDC
->cdc_MediaType
,
2089 Child
, (IPTR
)Label((IPTR
) "Default " DEVNAME
" Unit:"),
2090 Child
, (IPTR
)(ncp
->ncp_UnitObj
= StringObject
,
2093 MUIA_String_AdvanceOnCR
, TRUE
,
2094 MUIA_String_Integer
, ncp
->ncp_CDC
->cdc_DefaultUnit
,
2095 MUIA_String_Accept
, (IPTR
)"0123456789",
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
,
2105 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
2106 MUIA_Text_Contents
, (IPTR
)"\33c Save ",
2108 Child
, (IPTR
)(ncp
->ncp_SetDefaultObj
= TextObject
, ButtonFrame
,
2109 MUIA_Background
, MUII_ButtonBack
,
2111 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
2112 MUIA_Text_Contents
, (IPTR
)(ncp
->ncp_Interface
? "\33c Save as Default " : "\33c Save Defaults "),
2114 Child
, (IPTR
)(ncp
->ncp_CloseObj
= TextObject
, ButtonFrame
,
2115 MUIA_Background
, MUII_ButtonBack
,
2117 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
2118 MUIA_Text_Contents
, (IPTR
)"\33c Use ",
2127 KPRINTF(10, ("Couldn't create application\n"));
2128 nGUITaskCleanup(ncp
);
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);
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
);
2167 retid
= DoMethod(ncp
->ncp_App
, MUIM_Application_NewInput
, &sigs
);
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
);
2182 psdSetClsCfg(libname
, NULL
);
2183 pic
= psdGetClsCfg(libname
);
2187 psdAddCfgEntry(pic
, ncp
->ncp_CDC
);
2188 psdSaveCfgToDisk(NULL
, FALSE
);
2191 if(ncp
->ncp_Interface
)
2193 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
2196 psdSetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
, NULL
);
2197 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, NULL
);
2201 if(psdAddCfgEntry(pic
, ncp
->ncp_CDC
))
2203 if(retid
!= MUIV_Application_ReturnID_Quit
)
2205 psdSaveCfgToDisk(NULL
, FALSE
);
2207 retid
= MUIV_Application_ReturnID_Quit
;
2211 retid
= MUIV_Application_ReturnID_Quit
;
2217 MUI_RequestA(ncp
->ncp_App
, ncp
->ncp_MainWindow
, 0, NULL
, "Phat!", VERSION_STRING
, NULL
);
2220 if(retid
== MUIV_Application_ReturnID_Quit
)
2226 sigs
= Wait(sigs
|sigmask
|SIGBREAKF_CTRL_C
);
2227 if(sigs
& SIGBREAKF_CTRL_C
)
2233 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, FALSE
);
2235 nGUITaskCleanup(ncp
);
2241 /* /// "nGUITaskCleanup()" */
2242 void nGUITaskCleanup(struct NepClassEth
*ncp
)
2246 MUI_DisposeObject(ncp
->ncp_App
);
2247 ncp
->ncp_App
= NULL
;
2251 CloseLibrary(MUIMasterBase
);
2252 MUIMasterBase
= NULL
;
2256 CloseLibrary(IntuitionBase
);
2257 IntuitionBase
= NULL
;
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
;