2 Copyright © 2013-2015, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
9 #include <proto/exec.h>
10 #include <proto/kernel.h>
11 #include <proto/utility.h>
13 #include <proto/alib.h>
15 #include "usb2otg_intern.h"
17 #define DEVNAME "usb2otg.device"
19 const char devname
[] = MOD_NAME_STRING
;
21 AROS_INTP(FNAME_DEV(PendingInt
));
22 AROS_INTP(FNAME_DEV(NakTimeoutInt
));
24 IPTR __arm_periiobase
__attribute__((used
)) = 0 ;
26 static void GlobalIRQHandler(struct USB2OTGUnit
*USBUnit
, struct ExecBase
*SysBase
)
28 D(bug("[USB2OTG] %s: Received USB interrupt for Unit @ 0x%p\n",
29 __PRETTY_FUNCTION__
, USBUnit
));
33 *===========================================================
35 *===========================================================
37 static int FNAME_DEV(Init
)(LIBBASETYPEPTR USB2OTGBase
)
39 volatile unsigned int *pmmailbox
;
40 volatile unsigned int otg_RegVal
;
41 unsigned int otg_OperatingMode
= 0, pmres
;
43 KernelBase
= OpenResource("kernel.resource");
45 __arm_periiobase
= KrnGetSystemAttr(KATTR_PeripheralBase
);
47 pmmailbox
= (volatile unsigned int *)(ARM_PERIIOBASE
+ 0xB880);
49 D(bug("[USB2OTG] %s: USB2OTGBase @ 0x%p, SysBase @ 0x%p\n",
50 __PRETTY_FUNCTION__
, USB2OTGBase
, SysBase
));
52 otg_RegVal
= *((volatile unsigned int *)USB2OTG_VENDORID
);
54 if ((otg_RegVal
& 0xFFFFF000) != 0x4F542000)
56 bug("[USB2OTG] Unsupported HS OTG USB Core Found\n");
57 bug("[USB2OTG] Hardware: %c%c%x.%x%x%x\n",
58 ((otg_RegVal
>> 24) & 0xFF), ((otg_RegVal
>> 16) & 0xFF),
59 ((otg_RegVal
>> 12) & 0xF), ((otg_RegVal
>> 8) & 0xF), ((otg_RegVal
>> 4) & 0xF), (otg_RegVal
& 0xF)
66 USB2OTGBase
->hd_KernelBase
= OpenResource("kernel.resource");
67 D(bug("[USB2OTG] %s: kernel.resource opened @ 0x%p\n",
68 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_KernelBase
));
70 if((USB2OTGBase
->hd_MsgPort
= CreateMsgPort()))
72 if((USB2OTGBase
->hd_TimerReq
= (struct timerequest
*) CreateIORequest(USB2OTGBase
->hd_MsgPort
, sizeof(struct timerequest
))))
74 if(!OpenDevice("timer.device", UNIT_MICROHZ
, (struct IORequest
*) USB2OTGBase
->hd_TimerReq
, 0))
76 USB2OTGBase
->hd_TimerReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "USB2OTG Timer";
77 USB2OTGBase
->hd_TimerReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
78 D(bug("[USB2OTG] %s: timer.device opened\n",
79 __PRETTY_FUNCTION__
));
81 bug("[USB2OTG] HS OTG Core Release: %c%c%x.%x%x%x\n",
82 ((otg_RegVal
>> 24) & 0xFF), ((otg_RegVal
>> 16) & 0xFF),
83 ((otg_RegVal
>> 12) & 0xF), ((otg_RegVal
>> 8) & 0xF), ((otg_RegVal
>> 4) & 0xF), (otg_RegVal
& 0xF)
86 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
87 bug("[USB2OTG] Architecture: %d - ", ((otg_RegVal
& (3 << 3)) >> 3));
88 switch (((otg_RegVal
& (3 << 3)) >> 3))
91 bug("Internal DMA\n");
94 bug("External DMA\n");
101 D(bug("[USB2OTG] %s: Disabling USB Interrupts (Globaly)..\n", __PRETTY_FUNCTION__
));
102 otg_RegVal
= *((volatile unsigned int *)USB2OTG_AHB
);
103 otg_RegVal
&= ~USB2OTG_AHB_INTENABLE
;
104 *((volatile unsigned int *)USB2OTG_INTRMASK
) = 0;
105 *((volatile unsigned int *)USB2OTG_AHB
) = otg_RegVal
;
107 while (pmmailbox
[6] & 0x80000000);
110 while (pmmailbox
[6] & 0x40000000);
111 } while (((pmres
= pmmailbox
[0]) & 0xf) != 0);
114 bug("[USB2OTG] Failed to power on controller\n");
115 //USB2OTGBase->hd_TimerReq
116 //USB2OTGBase->hd_MsgPort
121 if ((USB2OTGBase
->hd_UtilityBase
= (APTR
)OpenLibrary("utility.library", 39)) != NULL
)
123 USB2OTGBase
->hd_MemPool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
| MEMF_SEM_PROTECTED
, 16384, 4096);
124 if (USB2OTGBase
->hd_MemPool
)
128 D(bug("[USB2OTG] %s: Allocated MemPool @ 0x%p\n",
129 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_MemPool
));
134 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE
);
135 bug("[USB2OTG] %s: HWConfig: %08x-", __PRETTY_FUNCTION__
, otg_RegVal
);
136 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
137 bug("%08x-", otg_RegVal
);
138 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE3
);
139 bug("%08x-", otg_RegVal
);
140 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE4
);
141 bug("%08x\n", otg_RegVal
);
144 if ((USB2OTGBase
->hd_Unit
= AllocPooled(USB2OTGBase
->hd_MemPool
, sizeof(struct USB2OTGUnit
))) != NULL
)
146 D(bug("[USB2OTG] %s: Unit Allocated at 0x%p\n",
147 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
));
149 NewList(&USB2OTGBase
->hd_Unit
->hu_IOPendingQueue
);
151 NewList(&USB2OTGBase
->hd_Unit
->hu_CtrlXFerQueue
);
152 NewList(&USB2OTGBase
->hd_Unit
->hu_IntXFerQueue
);
153 NewList(&USB2OTGBase
->hd_Unit
->hu_IsoXFerQueue
);
154 NewList(&USB2OTGBase
->hd_Unit
->hu_BulkXFerQueue
);
155 NewList(&USB2OTGBase
->hd_Unit
->hu_TDQueue
);
156 NewList(&USB2OTGBase
->hd_Unit
->hu_AbortQueue
);
157 NewList(&USB2OTGBase
->hd_Unit
->hu_PeriodicTDQueue
);
159 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Type
= NT_INTERRUPT
;
160 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Name
= "OTG2USB Pending Work Interrupt";
161 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Pri
= 0;
162 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Data
= USB2OTGBase
->hd_Unit
;
163 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Code
= (VOID_FUNC
)FNAME_DEV(PendingInt
);
165 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Type
= NT_INTERRUPT
;
166 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Name
= "OTG2USB NakTimeout Interrupt";
167 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Pri
= -16;
168 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Data
= USB2OTGBase
->hd_Unit
;
169 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Code
= (VOID_FUNC
)FNAME_DEV(NakTimeoutInt
);
171 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
172 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_Flags
= PA_SOFTINT
;
173 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_SigTask
= &USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
;
174 NewList(&USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_MsgList
);
176 CopyMem(USB2OTGBase
->hd_TimerReq
, &USB2OTGBase
->hd_Unit
->hu_NakTimeoutReq
, sizeof(struct timerequest
));
177 USB2OTGBase
->hd_Unit
->hu_NakTimeoutReq
.tr_node
.io_Message
.mn_ReplyPort
= &USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
;
179 USB2OTGBase
->hd_Unit
->hu_HubPortChanged
= FALSE
;
181 USB2OTGBase
->hd_Unit
->hu_OperatingMode
= (otg_OperatingMode
== (USB2OTG_USBHOSTMODE
|USB2OTG_USBDEVICEMODE
)) ? 0 : otg_OperatingMode
;
184 D(bug("[USB2OTG] %s: Unit Mode %d\n",
185 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
->hu_OperatingMode
));
187 USB2OTGBase
->hd_Unit
->hu_GlobalIRQHandle
= KrnAddIRQHandler(IRQ_VC_USB
, GlobalIRQHandler
, USB2OTGBase
->hd_Unit
, SysBase
);
189 D(bug("[USB2OTG] %s: Installed Global IRQ Handler [handle @ 0x%p] for IRQ #%ld\n",
190 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
->hu_GlobalIRQHandle
, IRQ_HOSTPORT
));
192 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
193 otg_RegVal
&= ~(USB2OTG_USB_ULPIDRIVEEXTERNALVBUS
|USB2OTG_USB_TSDLINEPULSEENABLE
);
194 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
196 D(bug("[USB2OTG] %s: Reseting Controller ..\n", __PRETTY_FUNCTION__
));
197 *((volatile unsigned int *)USB2OTG_RESET
) = USB2OTG_RESET_CORESOFT
;
198 for (ns
= 0; ns
< 10000; ns
++) { asm volatile("mov r0, r0\n"); } // Wait 10ms
199 if ((*((volatile unsigned int *)USB2OTG_RESET
) & USB2OTG_RESET_CORESOFT
) != 0)
200 bug("[USB2OTG] %s: Reset Timed-Out!\n", __PRETTY_FUNCTION__
);
202 D(bug("[USB2OTG] %s: Initialising PHY ..\n", __PRETTY_FUNCTION__
));
203 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
204 otg_RegVal
&= ~USB2OTG_USB_PHYINTERFACE
;
205 otg_RegVal
&= ~USB2OTG_USB_MODESELECT_UTMI
;
206 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
209 D(bug("[USB2OTG] %s: Reseting Controller ..\n", __PRETTY_FUNCTION__
));
210 *((volatile unsigned int *)USB2OTG_RESET
) = USB2OTG_RESET_CORESOFT
;
211 for (ns
= 0; ns
< 10000; ns
++) { asm volatile("mov r0, r0\n"); } // Wait 10ms
212 if ((*((volatile unsigned int *)USB2OTG_RESET
) & USB2OTG_RESET_CORESOFT
) != 0)
213 bug("[USB2OTG] %s: Reset Timed-Out!\n", __PRETTY_FUNCTION__
);
216 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
217 if (((otg_RegVal
& (3 << 6) >> 6) == 2) && ((otg_RegVal
& (3 << 8) >> 8) == 1))
219 D(bug("[USB2OTG] %s: ULPI FSLS configuration: enabled.\n", __PRETTY_FUNCTION__
));
220 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
221 otg_RegVal
|= (USB2OTG_USB_ULPIFSLS
|USB2OTG_USB_ULPI_CLK_SUS_M
);
222 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
224 D(bug("[USB2OTG] %s: ULPI FSLS configuration: disabled.\n", __PRETTY_FUNCTION__
));
225 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
226 otg_RegVal
&= ~(USB2OTG_USB_ULPIFSLS
|USB2OTG_USB_ULPI_CLK_SUS_M
);
227 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
230 D(bug("[USB2OTG] %s: Enabling DMA configuration..\n", __PRETTY_FUNCTION__
));
231 otg_RegVal
= *((volatile unsigned int *)USB2OTG_AHB
);
232 otg_RegVal
&= ~(1 << USB2OTG_AHB_DMAREMAINDERMODE
);
233 otg_RegVal
|= (USB2OTG_AHB_DMAENABLE
|USB2OTG_AHB_DMAREMAINDERMODE_INCR
);
234 *((volatile unsigned int *)USB2OTG_AHB
) = otg_RegVal
;
237 D(bug("[USB2OTG] %s: Operating Mode: ", __PRETTY_FUNCTION__
));
238 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
239 switch (otg_RegVal
& 7)
243 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
244 otg_RegVal
|= (USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
245 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
251 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
252 otg_RegVal
&= ~USB2OTG_USB_HNPCAPABLE
;
253 otg_RegVal
|= USB2OTG_USB_SRPCAPABLE
;
254 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
259 D(bug("No HNP or SRP\n"));
260 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
261 otg_RegVal
&= ~(USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
262 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
266 D(bug("Disable HNP/SRP\n"));
267 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
268 otg_RegVal
&= ~(USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
269 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
272 bug("[USB2OTG] HS OTG USB Driver Initialised\n");
278 D(bug("[USB2OTG] %s: Failed to Create MemPool\n",
279 __PRETTY_FUNCTION__
));
281 CloseLibrary((struct Library
*) UtilityBase
);
287 D(bug("[USB2OTG] %s: OpenLibrary(\"utility.library\", 39) failed!\n",
288 __PRETTY_FUNCTION__
));
295 D(bug("[USB2OTG] %s: OpenDevice(\"timer.device\") failed!\n",
296 __PRETTY_FUNCTION__
));
303 D(bug("[USB2OTG] %s: Failed to allocate timer IORequest\n",
304 __PRETTY_FUNCTION__
));
311 D(bug("[USB2OTG] %s: Failed to create MsgPort\n",
312 __PRETTY_FUNCTION__
));
318 return USB2OTGBase
? TRUE
: FALSE
;
322 *===========================================================
323 * Open(ioreq, unit, flags, base)
324 *===========================================================
326 * This is the the DEV_OPEN function.
329 static int FNAME_DEV(Open
)(LIBBASETYPEPTR USB2OTGBase
, struct IOUsbHWReq
*ioreq
, ULONG otg_Unit
, ULONG flags
)
331 D(bug("[USB2OTG] %s: IOReq @ 0x%p, unit #%ld, flags = 0x%08lx, USB2OTGBase @ 0x%p\n",
332 __PRETTY_FUNCTION__
, ioreq
, otg_Unit
, flags
, USB2OTGBase
));
334 D(bug("[USB2OTG] %s: openCnt = %ld\n",
335 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Library
.lib_OpenCnt
));
337 if (ioreq
->iouh_Req
.io_Message
.mn_Length
< sizeof(struct IOUsbHWReq
))
339 D(bug("[USB2OTG] %s: invalid MN_LENGTH!\n",
340 __PRETTY_FUNCTION__
));
342 ioreq
->iouh_Req
.io_Error
= IOERR_BADLENGTH
;
346 ioreq
->iouh_Req
.io_Error
= IOERR_OPENFAIL
;
348 ioreq
->iouh_Req
.io_Unit
= FNAME_DEV(OpenUnit
)(ioreq
, otg_Unit
, USB2OTGBase
);
349 if (!(ioreq
->iouh_Req
.io_Unit
))
351 D(bug("[USB2OTG] %s: could not open unit!\n",
352 __PRETTY_FUNCTION__
));
357 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
358 ioreq
->iouh_Req
.io_Error
= 0;
369 *===========================================================
371 *===========================================================
373 * This is the the DEV_EXPUNGE function.
376 static int FNAME_DEV(Close
)(LIBBASETYPEPTR USB2OTGBase
, struct IOUsbHWReq
*ioreq
)
378 D(bug("[USB2OTG] %s: IOReq @ 0x%p, USB2OTGBase @ 0x%p\n",
379 __PRETTY_FUNCTION__
, ioreq
, USB2OTGBase
));
381 FNAME_DEV(CloseUnit
)(ioreq
, (struct USB2OTGUnit
*) ioreq
->iouh_Req
.io_Unit
, USB2OTGBase
);
383 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
384 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
388 static int FNAME_DEV(Expunge
)(LIBBASETYPEPTR USB2OTGBase
)
390 DeletePool(USB2OTGBase
->hd_MemPool
);
392 D(bug("[USB2OTG] %s: closing utility.library @ 0x%p\n",
393 __PRETTY_FUNCTION__
, UtilityBase
));
395 CloseLibrary((struct Library
*) UtilityBase
);
399 ADD2INITLIB(FNAME_DEV(Init
), 0)
400 ADD2OPENDEV(FNAME_DEV(Open
), 0)
401 ADD2CLOSEDEV(FNAME_DEV(Close
), 0)
402 ADD2EXPUNGELIB(FNAME_DEV(Expunge
), 0)
405 *===========================================================
406 * BeginIO(ioreq, base)
407 *===========================================================
409 * This is the DEV_BEGINIO vector of the device.
412 AROS_LH1(void, FNAME_DEV(BeginIO
),
413 AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
),
414 LIBBASETYPEPTR
, USB2OTGBase
, 5, usb2otg
)
418 struct USB2OTGUnit
*otg_Unit
= (struct USB2OTGUnit
*) ioreq
->iouh_Req
.io_Unit
;
421 D(bug("[USB2OTG] %s: IOReq @ 0x%08lx, USB2OTGBase @ 0x%08lx [cmd:%lu]\n",
422 __PRETTY_FUNCTION__
, ioreq
, USB2OTGBase
, ioreq
->iouh_Req
.io_Command
));
424 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
425 ioreq
->iouh_Req
.io_Error
= UHIOERR_NO_ERROR
;
427 if (ioreq
->iouh_Req
.io_Command
< NSCMD_DEVICEQUERY
)
429 switch (ioreq
->iouh_Req
.io_Command
)
432 ret
= FNAME_DEV(cmdReset
)(ioreq
, otg_Unit
, USB2OTGBase
);
436 ret
= FNAME_DEV(cmdFlush
)(ioreq
, otg_Unit
, USB2OTGBase
);
439 case UHCMD_QUERYDEVICE
:
440 ret
= FNAME_DEV(cmdQueryDevice
)(ioreq
, otg_Unit
, USB2OTGBase
);
444 ret
= FNAME_DEV(cmdUsbReset
)(ioreq
, otg_Unit
, USB2OTGBase
);
447 case UHCMD_USBRESUME
:
448 ret
= FNAME_DEV(cmdUsbResume
)(ioreq
, otg_Unit
, USB2OTGBase
);
451 case UHCMD_USBSUSPEND
:
452 ret
= FNAME_DEV(cmdUsbSuspend
)(ioreq
, otg_Unit
, USB2OTGBase
);
456 ret
= FNAME_DEV(cmdUsbOper
)(ioreq
, otg_Unit
, USB2OTGBase
);
459 case UHCMD_CONTROLXFER
:
460 ret
= FNAME_DEV(cmdControlXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
464 ret
= FNAME_DEV(cmdBulkXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
468 ret
= FNAME_DEV(cmdIntXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
472 ret
= FNAME_DEV(cmdIsoXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
482 switch(ioreq
->iouh_Req
.io_Command
)
484 case NSCMD_DEVICEQUERY
:
485 ret
= FNAME_DEV(cmdNSDeviceQuery
)((struct IOStdReq
*) ioreq
, otg_Unit
, USB2OTGBase
);
494 if (ret
!= RC_DONTREPLY
)
496 D(bug("[USB2OTG] %s: Terminating I/O..\n",
497 __PRETTY_FUNCTION__
));
501 ioreq
->iouh_Req
.io_Error
= ret
& 0xff;
503 FNAME_DEV(TermIO
)(ioreq
, USB2OTGBase
);
510 *===========================================================
511 * AbortIO(ioreq, base)
512 *===========================================================
514 * This is the DEV_ABORTIO vector of the device. It abort
515 * the given iorequest, and set
518 AROS_LH1(LONG
, FNAME_DEV(AbortIO
),
519 AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
),
520 LIBBASETYPEPTR
, USB2OTGBase
, 6, usb2otg
)
524 D(bug("[USB2OTG] %s: IOReq @ 0x%p, command %ld, status %ld\n",
525 __PRETTY_FUNCTION__
, ioreq
, ioreq
->iouh_Req
.io_Command
, ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
));
528 if (ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
530 // if (FNAME_DEV(cmdAbortIO)(ioreq, USB2OTGBase))
540 void FNAME_DEV(Cause
)(LIBBASETYPEPTR USB2OTGBase
, struct Interrupt
*interrupt
)
542 /* this is a workaround for the original Cause() function missing tailed calls */
545 if((interrupt
->is_Node
.ln_Type
== NT_SOFTINT
) || (interrupt
->is_Node
.ln_Type
== NT_USER
))
547 // signal tailed call
548 interrupt
->is_Node
.ln_Type
= NT_USER
;
552 interrupt
->is_Node
.ln_Type
= NT_SOFTINT
;
553 Forbid(); // make sure code is not interrupted by other tasks
555 AROS_INTC1(interrupt
->is_Code
, interrupt
->is_Data
);
558 } while(interrupt
->is_Node
.ln_Type
!= NT_SOFTINT
);
559 interrupt
->is_Node
.ln_Type
= NT_INTERRUPT
;