Check for SYS/GL during library init. Reason is that
[AROS.git] / rom / usb / classes / stir4200 / stir4200.class.c
blobcc0113297ec9795b29b770bc4b44bb11daf3a91a
1 /*
2 *----------------------------------------------------------------------------
3 * stir4200 class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "stir4200.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 NepClassSTIr4200 *ncp;
30 struct NepSTIr4200Base *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 NepSTIrDevBase *) MakeLibrary((APTR) DevFuncTable, NULL, (APTR) devInit,
43 sizeof(struct NepSTIrDevBase), NULL)))
45 nh->nh_DevBase->np_ClsBase = nh;
46 ncp = &nh->nh_DummyNCP;
47 ncp->ncp_CDC = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
48 if(ncp->ncp_CDC)
50 ncp->ncp_ClsBase = nh;
51 ncp->ncp_Device = NULL;
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 usbstir4200.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 NepClassSTIr4200 *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 NepClassSTIr4200 *) 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 NepClassSTIr4200 *) 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! stir4200.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 NepClassSTIr4200 * usbAttemptDeviceBinding(struct NepSTIr4200Base *nh, struct PsdDevice *pd)
127 struct Library *ps;
128 IPTR prodid;
129 IPTR vendid;
130 KPRINTF(1, ("nepSTIr4200AttemptDeviceBinding(%08lx)\n", pd));
132 if((ps = OpenLibrary("poseidon.library", 4)))
134 psdGetAttrs(PGA_DEVICE, pd,
135 DA_VendorID, &vendid,
136 DA_ProductID, &prodid,
137 TAG_END);
138 CloseLibrary(ps);
139 if((vendid == 0x066F) && (prodid == 0x4200))
141 return(usbForceDeviceBinding(nh, pd));
144 return(NULL);
146 /* \\\ */
148 /* /// "usbForceDeviceBinding()" */
149 struct NepClassSTIr4200 * usbForceDeviceBinding(struct NepSTIr4200Base *nh, struct PsdDevice *pd)
151 struct Library *ps;
152 struct NepClassSTIr4200 *ncp;
153 struct NepClassSTIr4200 *tmpncp;
154 struct ClsDevCfg *cdc;
155 STRPTR devname;
156 STRPTR devidstr;
157 IPTR prodid;
158 IPTR vendid;
159 ULONG unitno;
160 BOOL unitfound;
161 UBYTE buf[64];
162 struct Task *tmptask;
164 KPRINTF(1, ("nepSTIr4200ForceDeviceBinding(%08lx)\n", pd));
166 if((ps = OpenLibrary("poseidon.library", 4)))
168 psdGetAttrs(PGA_DEVICE, pd,
169 DA_ProductID, &prodid,
170 DA_VendorID, &vendid,
171 DA_ProductName, &devname,
172 DA_IDString, &devidstr,
173 TAG_END);
174 Forbid();
175 unitfound = FALSE;
176 unitno = (ULONG) -1;
177 ncp = (struct NepClassSTIr4200 *) nh->nh_Units.lh_Head;
178 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
180 if(!ncp->ncp_Task)
182 unitno = ncp->ncp_UnitNo;
183 unitfound = TRUE;
184 break;
186 ncp = (struct NepClassSTIr4200 *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
188 if(!unitfound)
190 /* as units are freed in the expunge-vector, the memory is
191 outside the scope of the poseidon library */
192 if(!(ncp = AllocVec(sizeof(struct NepClassSTIr4200), MEMF_PUBLIC|MEMF_CLEAR)))
194 Permit();
195 CloseLibrary(ps);
196 return(NULL);
198 ncp->ncp_CDC = cdc = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
199 if(!cdc)
201 Permit();
202 FreeVec(ncp);
203 CloseLibrary(ps);
204 return(NULL);
206 /* IORequests may be queued even if the task is gone. */
207 ncp->ncp_UnitNo = (ULONG) -1;
208 NewList(&ncp->ncp_Unit.unit_MsgPort.mp_MsgList);
209 NewList(&ncp->ncp_ReadQueue);
210 NewList(&ncp->ncp_WriteQueue);
211 AddTail(&nh->nh_Units, &ncp->ncp_Unit.unit_MsgPort.mp_Node);
213 ncp->ncp_ClsBase = nh;
214 ncp->ncp_Device = pd;
215 ncp->ncp_UnitProdID = prodid;
216 ncp->ncp_UnitVendorID = vendid;
217 ncp->ncp_DevIDString = devidstr;
219 nLoadBindingConfig(ncp);
221 /* Find next free unit number */
222 if(unitno == (ULONG) -1)
224 unitno = ncp->ncp_CDC->cdc_DefaultUnit;
225 tmpncp = (struct NepClassSTIr4200 *) nh->nh_Units.lh_Head;
226 while(tmpncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
228 if(tmpncp->ncp_UnitNo == unitno)
230 unitno++;
231 tmpncp = (struct NepClassSTIr4200 *) nh->nh_Units.lh_Head;
232 } else {
233 tmpncp = (struct NepClassSTIr4200 *) tmpncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
237 ncp->ncp_UnitNo = unitno;
238 Permit();
240 psdSafeRawDoFmt(buf, 64, "stir4200.class<%08lx>", ncp);
241 ncp->ncp_ReadySignal = SIGB_SINGLE;
242 ncp->ncp_ReadySigTask = FindTask(NULL);
243 SetSignal(0, SIGF_SINGLE);
244 if((tmptask = psdSpawnSubTask(buf, nSTIr4200Task, ncp)))
246 psdBorrowLocksWait(tmptask, 1UL<<ncp->ncp_ReadySignal);
247 if(ncp->ncp_Task)
249 ncp->ncp_ReadySigTask = NULL;
250 //FreeSignal(ncp->ncp_ReadySignal);
251 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
252 "Look at this infra red face '%s' at %s unit %ld!",
253 devname, nh->nh_DevBase->np_Library.lib_Node.ln_Name,
254 ncp->ncp_UnitNo);
256 CloseLibrary(ps);
257 return(ncp);
260 ncp->ncp_ReadySigTask = NULL;
261 //FreeSignal(ncp->ncp_ReadySignal);
262 /* Get rid of unit structure */
263 /*Forbid();
264 Remove((struct Node *) ncp);
265 FreeVec(ncp->ncp_CDC);
266 FreeVec(ncp);*/
267 Permit();
268 CloseLibrary(ps);
270 return(NULL);
272 /* \\\ */
274 /* /// "usbReleaseDeviceBinding()" */
275 void usbReleaseDeviceBinding(struct NepSTIr4200Base *nh, struct NepClassSTIr4200 *ncp)
277 struct Library *ps;
278 STRPTR devname;
280 KPRINTF(1, ("nepSTIr4200ReleaseDeviceBinding(%08lx)\n", ncp));
281 if((ps = OpenLibrary("poseidon.library", 4)))
283 Forbid();
284 ncp->ncp_ReadySignal = SIGB_SINGLE;
285 ncp->ncp_ReadySigTask = FindTask(NULL);
286 if(ncp->ncp_Task)
288 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
290 Permit();
291 while(ncp->ncp_Task)
293 Wait(1L<<ncp->ncp_ReadySignal);
295 //FreeSignal(ncp->ncp_ReadySignal);
296 psdGetAttrs(PGA_DEVICE, ncp->ncp_Device, DA_ProductName, &devname, TAG_END);
297 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
298 "'%s' turned into a infrared dwarf.",
299 devname);
300 /*psdFreeVec(ncp);*/
301 CloseLibrary(ps);
304 /* \\\ */
306 /* /// "usbGetAttrsA()" */
307 AROS_LH3(LONG, usbGetAttrsA,
308 AROS_LHA(ULONG, type, D0),
309 AROS_LHA(APTR, usbstruct, A0),
310 AROS_LHA(struct TagItem *, tags, A1),
311 LIBBASETYPEPTR, nh, 5, nep)
313 AROS_LIBFUNC_INIT
315 struct TagItem *ti;
316 LONG count = 0;
318 KPRINTF(1, ("nepSTIr4200GetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
319 switch(type)
321 case UGA_CLASS:
322 if((ti = FindTagItem(UCCA_Priority, tags)))
324 *((SIPTR *) ti->ti_Data) = 0;
325 count++;
327 if((ti = FindTagItem(UCCA_Description, tags)))
329 *((STRPTR *) ti->ti_Data) = "IrDA Bridge for STIr4200 chipsets via usbstir4200.device";
330 count++;
332 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
334 *((IPTR *) ti->ti_Data) = TRUE;
335 count++;
337 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
339 *((IPTR *) ti->ti_Data) = TRUE;
340 count++;
342 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
344 *((IPTR *) ti->ti_Data) = FALSE;
345 count++;
347 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
349 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCP.ncp_UsingDefaultCfg;
350 count++;
352 break;
354 case UGA_BINDING:
355 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
357 *((IPTR *) ti->ti_Data) = ((struct NepClassSTIr4200 *) usbstruct)->ncp_UsingDefaultCfg;
358 count++;
360 break;
362 return(count);
363 AROS_LIBFUNC_EXIT
365 /* \\\ */
367 /* /// "usbSetAttrsA()" */
368 AROS_LH3(LONG, usbSetAttrsA,
369 AROS_LHA(ULONG, type, D0),
370 AROS_LHA(APTR, usbstruct, A0),
371 AROS_LHA(struct TagItem *, tags, A1),
372 LIBBASETYPEPTR, nh, 6, nep)
374 AROS_LIBFUNC_INIT
375 return(0);
376 AROS_LIBFUNC_EXIT
378 /* \\\ */
380 /* /// "usbDoMethodA()" */
381 AROS_LH2(IPTR, usbDoMethodA,
382 AROS_LHA(ULONG, methodid, D0),
383 AROS_LHA(IPTR *, methoddata, A1),
384 LIBBASETYPEPTR, nh, 7, nep)
386 AROS_LIBFUNC_INIT
388 struct NepClassSTIr4200 *ncp;
390 KPRINTF(10, ("Do Method %ld\n", methodid));
391 switch(methodid)
393 case UCM_AttemptDeviceBinding:
394 return((IPTR) usbAttemptDeviceBinding(nh, (struct PsdDevice *) methoddata[0]));
396 case UCM_ForceDeviceBinding:
397 return((IPTR) usbForceDeviceBinding(nh, (struct PsdDevice *) methoddata[0]));
399 case UCM_ReleaseDeviceBinding:
400 usbReleaseDeviceBinding(nh, (struct NepClassSTIr4200 *) methoddata[0]);
401 return(TRUE);
403 case UCM_OpenCfgWindow:
404 return(nOpenBindingCfgWindow(nh, &nh->nh_DummyNCP));
406 case UCM_OpenBindingCfgWindow:
407 return(nOpenBindingCfgWindow(nh, (struct NepClassSTIr4200 *) methoddata[0]));
409 case UCM_ConfigChangedEvent:
410 nLoadClassConfig(nh);
411 Forbid();
412 ncp = (struct NepClassSTIr4200 *) nh->nh_Units.lh_Head;
413 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
415 nLoadBindingConfig(ncp);
416 ncp = (struct NepClassSTIr4200 *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
418 Permit();
419 return(TRUE);
421 default:
422 break;
424 return(0);
425 AROS_LIBFUNC_EXIT
427 /* \\\ */
429 /* /// "nLoadClassConfig()" */
430 BOOL nLoadClassConfig(struct NepSTIr4200Base *nh)
432 struct NepClassSTIr4200 *ncp = &nh->nh_DummyNCP;
433 struct Library *ps;
434 struct ClsDevCfg *cdc;
435 struct PsdIFFContext *pic;
437 KPRINTF(10, ("Loading Class Config...\n"));
438 if(ncp->ncp_GUITask)
440 return(FALSE);
442 if(!(ps = OpenLibrary("poseidon.library", 4)))
444 return(FALSE);
447 Forbid();
448 /* Create default config */
449 cdc = ncp->ncp_CDC;
450 cdc->cdc_ChunkID = AROS_LONG2BE(MAKE_ID('S','T','I','R'));
451 cdc->cdc_Length = AROS_LONG2BE(sizeof(struct ClsDevCfg)-8);
452 cdc->cdc_DefaultUnit = 0;
453 cdc->cdc_StackAuto = TRUE;
454 cdc->cdc_TXPower = 0;
455 cdc->cdc_RXSense = 1;
456 ncp->ncp_UsingDefaultCfg = TRUE;
457 /* try to load default config */
458 pic = psdGetClsCfg(libname);
459 if(pic)
461 cdc = psdGetCfgChunk(pic, ncp->ncp_CDC->cdc_ChunkID);
462 if(cdc)
464 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
465 psdFreeVec(cdc);
466 ncp->ncp_UsingDefaultCfg = FALSE;
469 Permit();
470 CloseLibrary(ps);
471 return(FALSE);
473 /* \\\ */
475 /* /// "nLoadBindingConfig()" */
476 BOOL nLoadBindingConfig(struct NepClassSTIr4200 *ncp)
478 struct NepSTIr4200Base *nh = ncp->ncp_ClsBase;
479 struct Library *ps;
480 struct ClsDevCfg *cdc;
481 struct PsdIFFContext *pic;
483 KPRINTF(10, ("Loading Binding Config...\n"));
484 if(ncp->ncp_GUITask)
486 return(FALSE);
488 //nLoadClassConfig(nh);
489 *ncp->ncp_CDC = *nh->nh_DummyNCP.ncp_CDC;
490 ncp->ncp_UsingDefaultCfg = TRUE;
492 if(!(ps = OpenLibrary("poseidon.library", 4)))
494 return(FALSE);
497 Forbid();
498 /* Load config */
499 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
500 if(pic)
502 cdc = psdGetCfgChunk(pic, ncp->ncp_CDC->cdc_ChunkID);
503 if(cdc)
505 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
506 psdFreeVec(cdc);
507 ncp->ncp_UsingDefaultCfg = FALSE;
510 Permit();
511 CloseLibrary(ps);
512 return(FALSE);
514 /* \\\ */
516 /* /// "nOpenBindingCfgWindow()" */
517 LONG nOpenBindingCfgWindow(struct NepSTIr4200Base *nh, struct NepClassSTIr4200 *ncp)
519 struct Library *ps;
520 KPRINTF(10, ("Opening GUI...\n"));
521 if(!(ps = OpenLibrary("poseidon.library", 4)))
523 return(FALSE);
525 Forbid();
526 if(!ncp->ncp_GUITask)
528 if((ncp->ncp_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", nGUITask, ncp)))
530 Permit();
531 CloseLibrary(ps);
532 return(TRUE);
535 Permit();
536 CloseLibrary(ps);
537 return(FALSE);
539 /* \\\ */
541 /**************************************************************************/
543 #undef ps
544 #define ps ncp->ncp_Base
546 /* /// "FCS Checksum tables" */
547 static UWORD FCS16Table[256] =
549 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
550 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
551 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
552 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
553 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
554 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
555 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
556 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
557 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
558 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
559 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
560 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
561 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
562 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
563 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
564 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
565 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
566 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
567 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
568 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
569 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
570 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
571 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
572 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
573 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
574 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
575 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
576 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
577 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
578 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
579 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
580 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
583 static ULONG FCS32Table[256] =
585 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
586 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
587 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
588 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
589 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
590 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
591 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
592 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
593 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
594 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
595 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
596 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
597 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
598 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
599 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
600 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
601 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
602 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
603 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
604 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
605 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
606 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
607 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
608 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
609 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
610 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
611 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
612 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
613 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
614 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
615 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
616 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
617 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
618 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
619 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
620 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
621 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
622 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
623 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
624 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
625 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
626 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
627 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
628 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
629 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
630 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
631 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
632 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
633 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
634 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
635 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
636 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
637 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
638 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
639 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
640 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
641 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
642 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
643 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
644 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
645 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
646 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
647 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
648 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
650 /* \\\ */
652 #if 0
653 /* /// "nCalcFCS16()" */
654 UWORD nCalcFCS16(UBYTE *buf, ULONG len)
656 register UWORD crc = 0;
657 if(len)
661 crc = ((crc>>8) & 0xff) ^ FCS16Table[(crc ^ (*buf++)) & 0xff)];
662 } while(--len);
664 return(crc ^ 0xffff);
666 /* \\\ */
668 /* /// "nCalcFCS32()" */
669 ULONG nCalcFCS16(UBYTE *buf, ULONG len)
671 register ULONG crc = 0;
672 if(len)
676 crc = ((crc>>8) & 0xff) ^ FCS32Table[(crc ^ (*buf++)) & 0xff)];
677 } while(--len);
679 return(crc ^ 0xffffffff);
681 /* \\\ */
683 #define CRC32_POLYNOMIAL 0x04c11db7
685 /* /// "nCalcFCS32()" */
686 ULONG nCalcFCS32(UBYTE *buf, ULONG len)
688 ULONG crc = 0xffffffff;
689 if(len)
693 UBYTE data = *buf++;
694 UWORD cnt;
695 // could be optimized by lookup table.
696 cnt = 8;
699 if(((LONG) (crc ^ (data<<31))) < 0)
701 crc <<= 1;
702 crc ^= CRC32_POLYNOMIAL;
703 } else {
704 crc <<= 1;
706 data >>= 1;
707 } while(--cnt);
708 } while(--len);
710 return(crc);
712 /* \\\ */
713 #endif
715 /* /// "nSetBaudrate()" */
716 BOOL nSetBaudrate(struct NepClassSTIr4200 *ncp, ULONG baudrate)
718 ULONG mode = SMF_FFSPRST|SMF_FASTRXEN;
719 ULONG clk = 0;
720 BOOL res;
721 if(!baudrate)
723 return(FALSE);
726 res = nSetReg(ncp, STREG_CTRL, SCF_SRESET);
727 res &= nSetReg(ncp, STREG_DPLLTUNE, 0x15);
728 ncp->ncp_FIRMode = FALSE;
729 switch(baudrate)
731 case 2400:
732 mode |= SMF_PDCLK8;
733 clk = PDCLK_2400;
734 case 9600:
735 if(!clk) clk = PDCLK_9600;
736 case 19200:
737 if(!clk) clk = PDCLK_19200;
738 case 38400:
739 if(!clk) clk = PDCLK_38400;
740 case 57600:
741 if(!clk) clk = PDCLK_57600;
742 case 115200:
743 if(!clk) clk = PDCLK_115200;
744 KPRINTF(1, ("Setting SIR Mode (%ld baud)!\n", baudrate));
745 nSetReg(ncp, STREG_BAUDRATE, clk);
746 mode |= SMF_SIR;
747 break;
749 case 4000000:
750 KPRINTF(1, ("Setting FIR Mode!\n"));
751 ncp->ncp_FIRMode = TRUE;
752 res &= nSetReg(ncp, STREG_BAUDRATE, PDCLK_4000000);
753 mode |= SMF_FIR|SMF_FASTRSTEN;
754 break;
756 default:
757 KPRINTF(10, ("Unsupported baudrate %ld\n", baudrate));
758 // set 9600 as default
759 nSetReg(ncp, STREG_BAUDRATE, PDCLK_9600);
760 mode |= SMF_SIR;
761 res = FALSE;
762 ncp->ncp_BaudRate = 9600;
764 if(res)
766 ncp->ncp_BaudRate = baudrate;
768 res &= nSetReg(ncp, STREG_MODE, mode);
769 res &= nSetReg(ncp, STREG_CTRL, SCF_SDMODE|SCF_TXPWR_HIGH);
770 res &= nSetReg(ncp, STREG_CTRL, SCF_TXPWR_HIGH);
771 res &= nSetReg(ncp, STREG_SENSITIVITY, 1<<SSB_RXDSNS);
772 return(res);
774 /* \\\ */
776 #define STUFFBYTEFIR(data) \
777 if((data >= 0x7d) && (data <= 0x7f)) \
779 data ^= 0x20; \
780 *buf++ = 0x7d; \
782 *buf++ = data
784 #define STUFFBYTEFIRFCS(data) \
785 crc = ((crc>>8) & 0xff) ^ FCS32Table[(crc ^ data) & 0xff]; \
786 STUFFBYTEFIR(data)
788 #define STUFFBYTESIR(data) \
789 if((data == 0xc0) || (data == 0xc1) || (data == 0x7d)) \
791 data ^= 0x20; \
792 *buf++ = 0x7d; \
794 *buf++ = data
796 #define STUFFBYTESIRFCS(data) \
797 crc = ((crc>>8) & 0xff) ^ FCS16Table[(crc ^ data) & 0xff]; \
798 STUFFBYTESIR(data)
800 /* /// "nSendFrame()" */
801 BOOL nSendFrame(struct NepClassSTIr4200 *ncp, struct IOIrDAReq *ioreq)
803 UBYTE *buf = ncp->ncp_WriteBuffer;
804 ULONG framelen;
805 ULONG datalen = ioreq->ioir_Length;
806 UBYTE *dataptr = ioreq->ioir_Data;
808 if(ncp->ncp_FIRMode)
810 register ULONG crc = 0xffffffff;
811 // maximum size of frame: 2 (header) + 2 (len) + 16 (preamble) + 2 (BOF) + 4 (AC) + 2*datalen + 8 (FCS) + 2 (EOF)
812 if(datalen<<1 > DEFBUFFERSIZE - 36)
814 ioreq->ioir_Req.io_Error = IRIOERR_OUTOFMEMORY;
815 return(FALSE);
817 *buf++ = 0x55; // header
818 *buf++ = 0xaa;
819 buf += 2; // length of frame needs to be filled out later
820 // preamble
821 *((ULONG *) buf) = 0x7f7f7f7f;
822 ((ULONG *) buf)[1] = 0x7f7f7f7f;
823 ((ULONG *) buf)[2] = 0x7f7f7f7f;
824 ((ULONG *) buf)[3] = 0x7f7f7f7f;
825 buf += 16;
826 *buf++ = 0x7e;
827 *buf++ = 0x7e;
828 STUFFBYTEFIRFCS(ioreq->ioir_Address); // address byte
829 STUFFBYTEFIRFCS(ioreq->ioir_Control); // control byte
831 register UBYTE data;
832 if(datalen)
836 data = *dataptr++;
837 STUFFBYTEFIRFCS(data);
838 } while(--datalen);
840 crc ^= 0xffffffff;
841 data = crc;
842 STUFFBYTEFIR(data);
843 crc >>= 8;
844 data = crc;
845 STUFFBYTEFIR(data);
846 crc >>= 8;
847 data = crc;
848 STUFFBYTEFIR(data);
849 crc >>= 8;
850 data = crc;
851 STUFFBYTEFIR(data);
853 *buf++ = 0x7e;
854 *buf++ = 0x7e;
855 } else {
856 register UWORD crc = 0xffff;
857 // maximum size of frame: 2 (header) + 2 (len) + NumBOFs + 4 (AC) + 2*datalen + 4 (FCS) + 1 (EOF)
858 if(datalen<<1 > DEFBUFFERSIZE - 13 - ioreq->ioir_NumBOFs)
860 ioreq->ioir_Req.io_Error = IRIOERR_OUTOFMEMORY;
861 return(FALSE);
863 *buf++ = 0x55; // header
864 *buf++ = 0xaa;
865 buf += 2; // length of frame needs to be filled out later
866 // preamble
867 if((framelen = ioreq->ioir_NumBOFs))
871 *buf++ = 0xc0;
872 } while(--framelen);
874 STUFFBYTESIRFCS(ioreq->ioir_Address); // address byte
875 STUFFBYTESIRFCS(ioreq->ioir_Control); // control byte
877 register UBYTE data;
878 if(datalen)
882 data = *dataptr++;
883 STUFFBYTESIRFCS(data);
884 } while(--datalen);
886 crc ^= 0xffff;
887 data = crc;
888 STUFFBYTESIR(data);
889 crc >>= 8;
890 data = crc;
891 STUFFBYTESIR(data);
893 *buf++ = 0xc1;
895 framelen = ((IPTR) buf) - ((IPTR) &ncp->ncp_WriteBuffer[4]);
896 ncp->ncp_WriteBuffer[2] = framelen;
897 ncp->ncp_WriteBuffer[3] = framelen>>8;
898 KPRINTF(10, ("Sending Frame (%ld bytes)\n", framelen));
899 DB(dumpmem(ncp->ncp_WriteBuffer, framelen+4));
900 psdSendPipe(ncp->ncp_EPOutPipe, ncp->ncp_WriteBuffer, framelen+4);
901 ncp->ncp_WritePending = ioreq;
902 return(TRUE);
904 /* \\\ */
906 /* /// "nReceiveFrame()" */
907 ULONG nReceiveFrame(struct NepClassSTIr4200 *ncp, UBYTE *buf, ULONG len)
909 struct IOIrDAReq *ioreq;
910 UBYTE *dataptr;
911 ULONG datalen;
912 ULONG cnt;
913 UBYTE data;
915 ioreq = (struct IOIrDAReq *) ncp->ncp_ReadQueue.lh_Head;
916 if(!ioreq->ioir_Req.io_Message.mn_Node.ln_Succ)
918 return(len);
920 //KPRINTF(10, ("Receive frame:\n"));
921 //DB(dumpmem(buf, len));
922 if(ncp->ncp_FIRMode)
924 KPRINTF(10, ("FIR Mode not yet implemented\n"));
925 } else {
926 register UWORD crc = 0;
927 if(ncp->ncp_UnescapeFirst)
929 *buf ^= 0x20;
930 ncp->ncp_UnescapeFirst = FALSE;
932 datalen = ioreq->ioir_Length + 2;
936 len--;
937 if(ncp->ncp_FrameStarted)
939 switch(data = *buf++)
941 case 0xc0:
942 if(ioreq->ioir_Actual)
944 KPRINTF(1, ("Unexpected BOF\n"));
945 ioreq->ioir_NumBOFs = 0;
946 } else {
947 KPRINTF(1, ("More BOFs...\n"));
948 ioreq->ioir_NumBOFs++;
950 ioreq->ioir_Actual = 0;
951 crc = 0;
952 break;
954 case 0xc1:
955 KPRINTF(1, ("EOF\n"));
956 ncp->ncp_FrameStarted = FALSE;
957 // frame completed
958 if(ioreq->ioir_Actual > 3) // address+control field+FCS
960 ioreq->ioir_Actual -= 4;
961 crc = 0xff ^ FCS16Table[(0xff ^ ioreq->ioir_Address) & 0xff];
962 crc = ((crc>>8) & 0xff) ^ FCS16Table[(crc ^ ioreq->ioir_Control) & 0xff];
963 cnt = ioreq->ioir_Actual + 2;
964 dataptr = ioreq->ioir_Data;
967 crc = ((crc>>8) & 0xff) ^ FCS16Table[(crc ^ *dataptr++) & 0xff];
968 } while(--cnt);
969 KPRINTF(10, ("CRC=%04lx for %ld bytes (%ld remaining)\n", crc, ioreq->ioir_Actual, len));
970 if(crc != 0xf0b8)
972 KPRINTF(10, ("CRC Error\n"));
973 break;
975 } else {
976 KPRINTF(10, ("Frame too short\n"));
977 break;
979 // reply frame
980 Remove((struct Node *) ioreq);
981 ReplyMsg((struct Message *) ioreq);
982 // is there another request pending?
983 ioreq = (struct IOIrDAReq *) ncp->ncp_ReadQueue.lh_Head;
984 if(ioreq->ioir_Req.io_Message.mn_Node.ln_Succ)
986 // don't try to switch baudrates, if a write request is pending with different baudrate
987 if(ncp->ncp_BaudRate != ioreq->ioir_Baud)
989 KPRINTF(10, ("Baudrate change requested\n"));
990 return(0); // obviously, remaining frames (if any) are discarded
992 datalen = ioreq->ioir_Length + 2;
993 } else {
994 return(len);
996 break;
998 case 0x7d:
999 KPRINTF(1, ("Unescaping\n"));
1000 if(len--)
1002 data = *buf++ ^ 0x20;
1003 if(!((data == 0xc0) || (data == 0xc1) || (data == 0x7d)))
1005 // illegal escaped sequence
1006 KPRINTF(10, ("Illegal escaped code %02lx\n", data));
1007 ncp->ncp_FrameStarted = FALSE;
1008 break;
1010 } else {
1011 KPRINTF(10, ("End of buffer, unescape first set\n"));
1012 ncp->ncp_UnescapeFirst = TRUE;
1013 return(0);
1015 // fall through
1017 default:
1018 if(ioreq->ioir_Actual > 1)
1020 if(ioreq->ioir_Actual < datalen)
1022 ((UBYTE *) ioreq->ioir_Data)[ioreq->ioir_Actual-2] = data;
1023 } else {
1024 KPRINTF(10, ("Buffer overflow!\n"));
1025 ncp->ncp_FrameStarted = FALSE;
1026 ioreq->ioir_Req.io_Error = IRIOERR_OVERFLOW;
1027 ioreq->ioir_Actual -= 2;
1028 Remove((struct Node *) ioreq);
1029 ReplyMsg((struct Message *) ioreq);
1030 return(len);
1032 } else {
1033 if(ioreq->ioir_Actual)
1035 KPRINTF(1, ("Control: %02lx\n", data));
1036 ioreq->ioir_Control = data;
1037 } else {
1038 KPRINTF(1, ("Address: %02lx\n", data));
1039 ioreq->ioir_Address = data;
1042 ioreq->ioir_Actual++;
1043 break;
1045 } else {
1046 if(*buf++ == 0xc0)
1048 KPRINTF(1, ("BOF!\n"));
1049 ncp->ncp_FrameStarted = TRUE;
1050 ioreq->ioir_Actual = 0;
1051 ioreq->ioir_NumBOFs = 1;
1052 crc = 0;
1055 } while(len);
1056 KPRINTF(1, ("Last byte: %02lx\n", buf[-1]));
1058 return(len);
1060 /* \\\ */
1062 /* /// "nSTIr4200Task()" */
1063 AROS_UFH0(void, nSTIr4200Task)
1065 AROS_USERFUNC_INIT
1067 struct NepClassSTIr4200 *ncp;
1068 struct PsdPipe *pp;
1069 ULONG sigmask;
1070 ULONG sigs;
1071 LONG ioerr;
1072 ULONG len;
1073 struct IOIrDAReq *ioreq;
1074 struct IOIrDAReq *ioreq2;
1075 ULONG mediabusycnt = 0;
1077 if((ncp = nAllocSTIr4200()))
1079 Forbid();
1080 if(ncp->ncp_ReadySigTask)
1082 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1084 Permit();
1086 /* Main task */
1087 sigmask = (1L<<ncp->ncp_Unit.unit_MsgPort.mp_SigBit)|(1L<<ncp->ncp_TaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
1090 while((pp = (struct PsdPipe *) GetMsg(ncp->ncp_TaskMsgPort)))
1092 KPRINTF(1, ("Pipe back %08lx\n", pp));
1093 if(pp == ncp->ncp_EPInPipe)
1095 ULONG len;
1096 ioerr = psdGetPipeError(pp);
1097 len = psdGetPipeActual(pp);
1098 KPRINTF(1, ("Len = %ld\n", len));
1099 if(ioerr)
1101 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1102 "STIr4200 receive failed: %s (%ld)",
1103 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1105 if(!len)
1107 psdDelayMS(50);
1108 mediabusycnt++;
1109 } else {
1110 mediabusycnt = 0;
1111 DB(dumpmem(ncp->ncp_ReadBuffer, len));
1112 ncp->ncp_RBufRemain = nReceiveFrame(ncp, ncp->ncp_ReadBuffer, len);
1113 if(ncp->ncp_RBufRemain)
1115 // data not fully read -- wait for next request to arrive
1116 ncp->ncp_RBufOffset = len - ncp->ncp_RBufRemain;
1117 KPRINTF(1, ("%ld Bytes at %ld remaining...\n", ncp->ncp_RBufRemain, ncp->ncp_RBufOffset));
1120 ncp->ncp_ReadPending = NULL;
1122 if(pp == ncp->ncp_EPOutPipe)
1124 if((ioreq = ncp->ncp_WritePending))
1126 ioerr = psdGetPipeError(pp);
1127 if(ioerr)
1129 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1130 "STIr4200 send failed: %s (%ld)",
1131 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1132 ioreq->ioir_Req.io_Error = IRIOERR_HOSTERROR;
1133 ioreq->ioir_Actual = 0;
1134 } else {
1135 ioreq->ioir_Actual = ioreq->ioir_Length;
1137 ReplyMsg((struct Message *) ioreq);
1138 ncp->ncp_WritePending = NULL;
1143 while((ioreq = (struct IOIrDAReq *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
1145 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
1146 ioreq, ioreq->ioir_Req.io_Command, ioreq->ioir_Length));
1147 switch(ioreq->ioir_Req.io_Command)
1149 case CMD_READ:
1150 ioreq->ioir_Actual = 0;
1151 Forbid();
1152 AddTail(&ncp->ncp_ReadQueue, &ioreq->ioir_Req.io_Message.mn_Node);
1153 Permit();
1154 break;
1156 case CMD_WRITE:
1157 ioreq->ioir_Actual = 0;
1158 Forbid();
1159 AddTail(&ncp->ncp_WriteQueue, &ioreq->ioir_Req.io_Message.mn_Node);
1160 Permit();
1161 break;
1163 case CMD_CLEAR:
1164 ReplyMsg((struct Message *) ioreq);
1165 break;
1167 case CMD_RESET:
1168 /* Reset does a flush too */
1169 case CMD_FLUSH:
1170 ioreq2 = (struct IOIrDAReq *) ncp->ncp_ReadQueue.lh_Head;
1171 while(ioreq2->ioir_Req.io_Message.mn_Node.ln_Succ)
1173 Remove((struct Node *) ioreq2);
1174 ioreq2->ioir_Req.io_Error = IOERR_ABORTED;
1175 ReplyMsg((struct Message *) ioreq2);
1176 ioreq2 = (struct IOIrDAReq *) ncp->ncp_ReadQueue.lh_Head;
1178 ioreq2 = (struct IOIrDAReq *) ncp->ncp_WriteQueue.lh_Head;
1179 while(ioreq2->ioir_Req.io_Message.mn_Node.ln_Succ)
1181 Remove((struct Node *) ioreq2);
1182 ioreq2->ioir_Req.io_Error = IOERR_ABORTED;
1183 ReplyMsg((struct Message *) ioreq2);
1184 ioreq2 = (struct IOIrDAReq *) ncp->ncp_WriteQueue.lh_Head;
1186 ReplyMsg((struct Message *) ioreq);
1187 break;
1189 default:
1190 ioreq->ioir_Req.io_Error = IOERR_NOCMD;
1191 ReplyMsg((struct Message *) ioreq);
1192 break;
1195 ioreq = (struct IOIrDAReq *) ncp->ncp_ReadQueue.lh_Head;
1196 while((!ncp->ncp_ReadPending) && ioreq->ioir_Req.io_Message.mn_Node.ln_Succ)
1198 // don't try to switch baudrates, if a write request is pending with different baudrate
1199 if(ncp->ncp_WritePending)
1201 if(ncp->ncp_WritePending->ioir_Baud != ioreq->ioir_Baud)
1203 break;
1206 if(ioreq->ioir_Baud != ncp->ncp_BaudRate)
1208 nSetBaudrate(ncp, ioreq->ioir_Baud);
1210 if(ncp->ncp_RBufRemain)
1212 len = ncp->ncp_RBufRemain;
1213 ncp->ncp_RBufRemain = nReceiveFrame(ncp, &ncp->ncp_ReadBuffer[ncp->ncp_RBufOffset], ncp->ncp_RBufRemain);
1214 if(ncp->ncp_RBufRemain)
1216 // data not fully read -- wait for next request to arrive
1217 ncp->ncp_RBufOffset += len - ncp->ncp_RBufRemain;
1218 break;
1221 KPRINTF(1, ("Sending out read pipe...\n"));
1222 psdSendPipe(ncp->ncp_EPInPipe, ncp->ncp_ReadBuffer, DEFBUFFERSIZE);
1223 ncp->ncp_ReadPending = ioreq;
1224 break;
1226 //if(!ncp->ncp_ReadPending)
1228 mediabusycnt = 10; // avoid infinite waits
1230 ioreq = (struct IOIrDAReq *) ncp->ncp_WriteQueue.lh_Head;
1231 while((mediabusycnt >= 10) && (!ncp->ncp_WritePending) && ioreq->ioir_Req.io_Message.mn_Node.ln_Succ)
1233 // don't try to switch baudrates, if a read request is pending with different baudrate
1234 if(ncp->ncp_ReadPending)
1236 if(ncp->ncp_ReadPending->ioir_Baud != ioreq->ioir_Baud)
1238 break;
1241 Remove((struct Node *) ioreq);
1242 if(ioreq->ioir_Baud != ncp->ncp_BaudRate)
1244 nSetBaudrate(ncp, ioreq->ioir_Baud);
1246 if(!nSendFrame(ncp, ioreq))
1248 // an error occurred!
1249 ReplyMsg((struct Message *) ioreq);
1250 ioreq = (struct IOIrDAReq *) ncp->ncp_WriteQueue.lh_Head;
1251 } else {
1252 break;
1255 sigs = Wait(sigmask);
1256 } while(!(sigs & SIGBREAKF_CTRL_C));
1257 Forbid();
1258 /* Now remove all requests still pending *anywhere* */
1259 ncp->ncp_DenyRequests = TRUE;
1260 /* Current transfers */
1261 if(ncp->ncp_ReadPending)
1263 KPRINTF(1, ("Aborting pending read...\n"));
1264 psdAbortPipe(ncp->ncp_EPInPipe);
1265 psdWaitPipe(ncp->ncp_EPInPipe);
1266 ncp->ncp_ReadPending = NULL;
1268 if((ioreq = ncp->ncp_WritePending))
1270 KPRINTF(1, ("Aborting pending write...\n"));
1271 psdAbortPipe(ncp->ncp_EPOutPipe);
1272 psdWaitPipe(ncp->ncp_EPOutPipe);
1273 ncp->ncp_WritePending = NULL;
1275 /* Read/Write queues */
1276 ioreq = (struct IOIrDAReq *) ncp->ncp_WriteQueue.lh_Head;
1277 while(ioreq->ioir_Req.io_Message.mn_Node.ln_Succ)
1279 KPRINTF(1, ("Removing write request...\n"));
1280 Remove((struct Node *) ioreq);
1281 ioreq->ioir_Req.io_Error = IOERR_ABORTED;
1282 ReplyMsg((struct Message *) ioreq);
1283 ioreq = (struct IOIrDAReq *) ncp->ncp_WriteQueue.lh_Head;
1285 ioreq = (struct IOIrDAReq *) ncp->ncp_ReadQueue.lh_Head;
1286 while(ioreq->ioir_Req.io_Message.mn_Node.ln_Succ)
1288 KPRINTF(1, ("Removing read request...\n"));
1289 Remove((struct Node *) ioreq);
1290 ioreq->ioir_Req.io_Error = IOERR_ABORTED;
1291 ReplyMsg((struct Message *) ioreq);
1292 ioreq = (struct IOIrDAReq *) ncp->ncp_ReadQueue.lh_Head;
1294 /* Command queue */
1295 while((ioreq = (struct IOIrDAReq *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
1297 KPRINTF(1, ("Aborting pending requests...\n"));
1298 ioreq->ioir_Req.io_Error = IOERR_ABORTED;
1299 ReplyMsg((struct Message *) ioreq);
1301 Permit();
1302 KPRINTF(20, ("Going down the river!\n"));
1303 nFreeSTIr4200(ncp);
1306 AROS_USERFUNC_EXIT
1308 /* \\\ */
1310 /* /// "nAllocSTIr4200()" */
1311 struct NepClassSTIr4200 * nAllocSTIr4200(void)
1313 struct Task *thistask;
1314 struct NepClassSTIr4200 *ncp;
1316 thistask = FindTask(NULL);
1319 ncp = thistask->tc_UserData;
1320 if(!(ncp->ncp_Base = OpenLibrary("poseidon.library", 4)))
1322 Alert(AG_OpenLib);
1323 break;
1325 ncp->ncp_Interface = psdFindInterface(ncp->ncp_Device, NULL, TAG_END);
1326 if(!ncp->ncp_Interface)
1328 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "Interface missing!");
1329 break;
1331 ncp->ncp_EPIn = psdFindEndpoint(ncp->ncp_Interface, NULL,
1332 EA_IsIn, TRUE,
1333 EA_TransferType, USEAF_BULK,
1334 TAG_END);
1335 ncp->ncp_EPOut = psdFindEndpoint(ncp->ncp_Interface, NULL,
1336 EA_IsIn, FALSE,
1337 EA_TransferType, USEAF_BULK,
1338 TAG_END);
1339 if(!(ncp->ncp_EPIn && ncp->ncp_EPOut))
1341 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "IN or OUT endpoint missing!");
1342 break;
1345 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPIn,
1346 EA_MaxPktSize, &ncp->ncp_EPInMaxPktSize,
1347 TAG_END);
1349 ncp->ncp_ReadPending = NULL;
1350 ncp->ncp_WritePending = NULL;
1351 if(!(ncp->ncp_ReadBuffer = AllocVec(DEFBUFFERSIZE, MEMF_PUBLIC|MEMF_CLEAR)))
1353 KPRINTF(1, ("Out of memory for read buffer\n"));
1354 break;
1356 if(!(ncp->ncp_WriteBuffer = AllocVec(DEFBUFFERSIZE, MEMF_PUBLIC|MEMF_CLEAR)))
1358 KPRINTF(1, ("Out of memory for read buffer\n"));
1359 break;
1361 ncp->ncp_Unit.unit_MsgPort.mp_SigBit = AllocSignal(-1);
1362 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = thistask;
1363 ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
1364 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
1366 if((ncp->ncp_TaskMsgPort = CreateMsgPort()))
1368 if((ncp->ncp_EP0Pipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, NULL)))
1370 if((ncp->ncp_EPOutPipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPOut)))
1372 /* Turn off short packets */
1373 psdSetAttrs(PGA_PIPE, ncp->ncp_EPOutPipe,
1374 PPA_NoShortPackets, TRUE,
1375 PPA_NakTimeout, TRUE,
1376 PPA_NakTimeoutTime, 1000,
1377 TAG_END);
1378 if((ncp->ncp_EPInPipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPIn)))
1380 /* Turn off short packets */
1381 psdSetAttrs(PGA_PIPE, ncp->ncp_EPInPipe,
1382 PPA_NakTimeout, FALSE,
1383 PPA_AllowRuntPackets, TRUE,
1384 TAG_END);
1386 nSetBaudrate(ncp, 9600);
1388 ncp->ncp_Task = thistask;
1389 return(ncp);
1391 psdFreePipe(ncp->ncp_EPOutPipe);
1393 psdFreePipe(ncp->ncp_EP0Pipe);
1395 DeleteMsgPort(ncp->ncp_TaskMsgPort);
1397 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
1398 } while(FALSE);
1399 CloseLibrary(ncp->ncp_Base);
1400 if(ncp->ncp_ReadBuffer)
1402 FreeVec(ncp->ncp_ReadBuffer);
1403 ncp->ncp_ReadBuffer = NULL;
1405 if(ncp->ncp_WriteBuffer)
1407 FreeVec(ncp->ncp_WriteBuffer);
1408 ncp->ncp_WriteBuffer = NULL;
1410 Forbid();
1411 ncp->ncp_Task = NULL;
1412 if(ncp->ncp_ReadySigTask)
1414 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1416 return(NULL);
1418 /* \\\ */
1420 /* /// "nFreeSTIr4200()" */
1421 void nFreeSTIr4200(struct NepClassSTIr4200 *ncp)
1423 struct IOStdReq *ioreq;
1424 Forbid();
1425 /* Disable the message port, messages may still be queued */
1426 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = NULL;
1427 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
1428 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
1429 // get rid of all messages that still have appeared here
1430 while((ioreq = (struct IOStdReq *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
1432 ioreq->io_Error = IOERR_ABORTED;
1433 ReplyMsg((struct Message *) ioreq);
1435 Permit();
1437 psdFreePipe(ncp->ncp_EPInPipe);
1438 psdFreePipe(ncp->ncp_EPOutPipe);
1439 psdFreePipe(ncp->ncp_EP0Pipe);
1441 if(ncp->ncp_ReadBuffer)
1443 FreeVec(ncp->ncp_ReadBuffer);
1444 ncp->ncp_ReadBuffer = NULL;
1446 if(ncp->ncp_WriteBuffer)
1448 FreeVec(ncp->ncp_WriteBuffer);
1449 ncp->ncp_WriteBuffer = NULL;
1452 DeleteMsgPort(ncp->ncp_TaskMsgPort);
1453 CloseLibrary(ncp->ncp_Base);
1454 Forbid();
1455 ncp->ncp_Task = NULL;
1456 if(ncp->ncp_ReadySigTask)
1458 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1461 /* \\\ */
1463 /* /// "nSetReg()" */
1464 BOOL nSetReg(struct NepClassSTIr4200 *ncp, ULONG reg, ULONG value)
1466 LONG ioerr;
1467 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_VENDOR|URTF_DEVICE,
1468 USTR_WRITE_REG, value, reg);
1469 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
1470 if(ioerr)
1472 KPRINTF(10, ("Writing reg %1lx with %02lx failed: %s (%ld)",
1473 reg, value,
1474 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
1475 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
1476 "Writing reg %1lx with %02lx failed: %s (%ld)",
1477 reg, value,
1478 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1479 return(FALSE);
1481 return(TRUE);
1483 /* \\\ */
1485 /**************************************************************************/
1487 /* /// "nGUITask()" */
1488 AROS_UFH0(void, nGUITask)
1490 AROS_USERFUNC_INIT
1492 struct Task *thistask;
1493 struct NepSTIr4200Base *nh;
1494 struct NepClassSTIr4200 *ncp;
1495 struct PsdIFFContext *pic;
1497 thistask = FindTask(NULL);
1498 #undef ps
1499 #define ps ncp->ncp_PsdBase
1500 #undef IntuitionBase
1501 #define IntuitionBase ncp->ncp_IntBase
1502 #undef MUIMasterBase
1503 #define MUIMasterBase ncp->ncp_MUIBase
1505 ncp = thistask->tc_UserData;
1506 nh = ncp->ncp_ClsBase;
1508 ++nh->nh_Library.lib_OpenCnt;
1509 if(!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
1511 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
1512 nGUITaskCleanup(ncp);
1513 return;
1516 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
1518 KPRINTF(10, ("Couldn't open intuition.library.\n"));
1519 nGUITaskCleanup(ncp);
1520 return;
1522 if(!(ps = OpenLibrary("poseidon.library", 4)))
1524 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
1525 nGUITaskCleanup(ncp);
1526 return;
1529 ncp->ncp_App = ApplicationObject,
1530 MUIA_Application_Title , (IPTR)libname,
1531 MUIA_Application_Version , (IPTR)VERSION_STRING,
1532 MUIA_Application_Copyright , (IPTR)"©2002-2009 Chris Hodges",
1533 MUIA_Application_Author , (IPTR)"Chris Hodges <chrisly@platon42.de>",
1534 MUIA_Application_Description, (IPTR)"Settings for the stir4200.class",
1535 MUIA_Application_Base , (IPTR)"STIR4200",
1536 MUIA_Application_HelpFile , (IPTR)"HELP:Poseidon.guide",
1537 MUIA_Application_Menustrip , (IPTR)MenustripObject,
1538 Child, (IPTR)MenuObjectT((IPTR)"Project"),
1539 Child, (IPTR)(ncp->ncp_AboutMI = MenuitemObject,
1540 MUIA_Menuitem_Title, (IPTR)"About...",
1541 MUIA_Menuitem_Shortcut, (IPTR)"?",
1542 End),
1543 End,
1544 Child, (IPTR)MenuObjectT((IPTR)"Settings"),
1545 Child, (IPTR)(ncp->ncp_UseMI = MenuitemObject,
1546 MUIA_Menuitem_Title, (IPTR)"Save",
1547 MUIA_Menuitem_Shortcut, (IPTR)"S",
1548 End),
1549 Child, (IPTR)(ncp->ncp_SetDefaultMI = MenuitemObject,
1550 MUIA_Menuitem_Title, (IPTR)"Save as Default",
1551 MUIA_Menuitem_Shortcut, (IPTR)"D",
1552 End),
1553 Child, (IPTR)MenuitemObject,
1554 MUIA_Menuitem_Title, (IPTR)NM_BARLABEL,
1555 End,
1556 Child, (IPTR)(ncp->ncp_MUIPrefsMI = MenuitemObject,
1557 MUIA_Menuitem_Title, (IPTR)"MUI Settings",
1558 MUIA_Menuitem_Shortcut, (IPTR)"M",
1559 End),
1560 End,
1561 End,
1563 SubWindow, (IPTR)(ncp->ncp_MainWindow = WindowObject,
1564 MUIA_Window_ID , MAKE_ID('M','A','I','N'),
1565 MUIA_Window_Title, (IPTR)libname,
1566 MUIA_HelpNode, (IPTR)libname,
1568 WindowContents, (IPTR)VGroup,
1569 Child, (IPTR)HGroup, GroupFrameT((IPTR)(ncp->ncp_Device ? "Device Settings" : "Default Device Settings")),
1570 Child, (IPTR)HSpace(0),
1571 Child, (IPTR)ColGroup(2),
1572 Child, (IPTR)Label((IPTR) "Autostart IrDA Stack:"),
1573 Child, (IPTR)HGroup,
1574 Child, (IPTR)(ncp->ncp_StackAutoObj = ImageObject, ImageButtonFrame,
1575 MUIA_Background, MUII_ButtonBack,
1576 MUIA_CycleChain, 1,
1577 MUIA_InputMode, MUIV_InputMode_Toggle,
1578 MUIA_Image_Spec, MUII_CheckMark,
1579 MUIA_Image_FreeVert, TRUE,
1580 MUIA_Selected, ncp->ncp_CDC->cdc_StackAuto,
1581 MUIA_ShowSelState, FALSE,
1582 End),
1583 Child, (IPTR)HSpace(0),
1584 End,
1585 Child, (IPTR)Label((IPTR) "Default " DEVNAME " Unit:"),
1586 Child, (IPTR)(ncp->ncp_UnitObj = StringObject,
1587 StringFrame,
1588 MUIA_CycleChain, 1,
1589 MUIA_String_AdvanceOnCR, TRUE,
1590 MUIA_String_Integer, ncp->ncp_CDC->cdc_DefaultUnit,
1591 MUIA_String_Accept, (IPTR)"0123456789",
1592 End),
1593 End,
1594 //Child, (IPTR)HSpace(0),
1595 End,
1596 Child, (IPTR)VSpace(0),
1597 Child, (IPTR)HGroup,
1598 MUIA_Group_SameWidth, TRUE,
1599 Child, (IPTR)(ncp->ncp_UseObj = TextObject, ButtonFrame,
1600 MUIA_ShowMe, (IPTR)ncp->ncp_Device,
1601 MUIA_Background, MUII_ButtonBack,
1602 MUIA_CycleChain, 1,
1603 MUIA_InputMode, MUIV_InputMode_RelVerify,
1604 MUIA_Text_Contents, (IPTR)"\33c Save ",
1605 End),
1606 Child, (IPTR)(ncp->ncp_SetDefaultObj = TextObject, ButtonFrame,
1607 MUIA_Background, MUII_ButtonBack,
1608 MUIA_CycleChain, 1,
1609 MUIA_InputMode, MUIV_InputMode_RelVerify,
1610 MUIA_Text_Contents, (IPTR)(ncp->ncp_Device ? "\33c Save as Default " : "\33c Save Defaults "),
1611 End),
1612 Child, (IPTR)(ncp->ncp_CloseObj = TextObject, ButtonFrame,
1613 MUIA_Background, MUII_ButtonBack,
1614 MUIA_CycleChain, 1,
1615 MUIA_InputMode, MUIV_InputMode_RelVerify,
1616 MUIA_Text_Contents, (IPTR)"\33c Use ",
1617 End),
1618 End,
1619 End,
1620 End),
1621 End;
1623 if(!ncp->ncp_App)
1625 KPRINTF(10, ("Couldn't create application\n"));
1626 nGUITaskCleanup(ncp);
1627 return;
1630 DoMethod(ncp->ncp_MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
1631 ncp->ncp_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
1632 DoMethod(ncp->ncp_UseObj, MUIM_Notify, MUIA_Pressed, FALSE,
1633 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
1634 DoMethod(ncp->ncp_SetDefaultObj, MUIM_Notify, MUIA_Pressed, FALSE,
1635 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
1636 DoMethod(ncp->ncp_CloseObj, MUIM_Notify, MUIA_Pressed, FALSE,
1637 ncp->ncp_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
1639 DoMethod(ncp->ncp_AboutMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1640 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_ABOUT);
1641 DoMethod(ncp->ncp_UseMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1642 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
1643 DoMethod(ncp->ncp_SetDefaultMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1644 ncp->ncp_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
1645 DoMethod(ncp->ncp_MUIPrefsMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1646 ncp->ncp_App, 2, MUIM_Application_OpenConfigWindow, 0);
1648 IPTR isopen = 0;
1649 IPTR iconify = 0;
1650 ULONG sigs;
1651 ULONG sigmask;
1652 LONG retid;
1654 get(ncp->ncp_App, MUIA_Application_Iconified, &iconify);
1655 set(ncp->ncp_MainWindow, MUIA_Window_Open, TRUE);
1656 get(ncp->ncp_MainWindow, MUIA_Window_Open, &isopen);
1657 if(!(isopen || iconify))
1659 nGUITaskCleanup(ncp);
1660 return;
1662 sigmask = 0;
1665 retid = DoMethod(ncp->ncp_App, MUIM_Application_NewInput, &sigs);
1666 switch(retid)
1668 case ID_DEF_CONFIG:
1669 case ID_STORE_CONFIG:
1670 case MUIV_Application_ReturnID_Quit:
1671 get(ncp->ncp_UnitObj, MUIA_String_Integer, &ncp->ncp_CDC->cdc_DefaultUnit);
1672 get(ncp->ncp_StackAutoObj, MUIA_Selected, &ncp->ncp_CDC->cdc_StackAuto);
1674 if(retid == ID_DEF_CONFIG)
1676 pic = psdGetClsCfg(libname);
1677 if(!pic)
1679 psdSetClsCfg(libname, NULL);
1680 pic = psdGetClsCfg(libname);
1682 if(pic)
1684 if(psdAddCfgEntry(pic, ncp->ncp_CDC))
1686 psdSaveCfgToDisk(NULL, FALSE);
1690 if(ncp->ncp_Device)
1692 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
1693 if(!pic)
1695 psdSetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL, NULL);
1696 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, NULL);
1698 if(pic)
1700 if(psdAddCfgEntry(pic, ncp->ncp_CDC))
1702 if(retid != MUIV_Application_ReturnID_Quit)
1704 psdSaveCfgToDisk(NULL, FALSE);
1706 retid = MUIV_Application_ReturnID_Quit;
1709 } else {
1710 retid = MUIV_Application_ReturnID_Quit;
1712 break;
1714 case ID_ABOUT:
1715 MUI_RequestA(ncp->ncp_App, ncp->ncp_MainWindow, 0, NULL, "Blimey!", VERSION_STRING, NULL);
1716 break;
1718 if(retid == MUIV_Application_ReturnID_Quit)
1720 break;
1722 if(sigs)
1724 sigs = Wait(sigs | sigmask | SIGBREAKF_CTRL_C);
1725 if(sigs & SIGBREAKF_CTRL_C)
1727 break;
1730 } while(TRUE);
1731 set(ncp->ncp_MainWindow, MUIA_Window_Open, FALSE);
1733 nGUITaskCleanup(ncp);
1735 AROS_USERFUNC_EXIT
1737 /* \\\ */
1739 /* /// "nGUITaskCleanup()" */
1740 void nGUITaskCleanup(struct NepClassSTIr4200 *ncp)
1742 if(ncp->ncp_App)
1744 MUI_DisposeObject(ncp->ncp_App);
1745 ncp->ncp_App = NULL;
1747 if(MUIMasterBase)
1749 CloseLibrary(MUIMasterBase);
1750 MUIMasterBase = NULL;
1752 if(IntuitionBase)
1754 CloseLibrary(IntuitionBase);
1755 IntuitionBase = NULL;
1757 if(ps)
1759 CloseLibrary(ps);
1760 ps = NULL;
1762 Forbid();
1763 ncp->ncp_GUIBinding = NULL;
1764 ncp->ncp_GUITask = NULL;
1765 if(ncp->ncp_ReadySigTask)
1767 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1769 --ncp->ncp_ClsBase->nh_Library.lib_OpenCnt;
1771 /* \\\ */