place-holder for restructure
[AROS.git] / arch / arm-raspi / usb / usb2otg / usb2otg_device.c
blobfd63bff4cc440ffcc02bb29cde46ea0640a2d3ac
1 /*
2 Copyright © 2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 1
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 <asm/bcm2835.h>
16 #include <hardware/usb2otg.h>
18 #include "usb2otg_intern.h"
20 #define DEVNAME "usb2otg.device"
22 const char devname[] = MOD_NAME_STRING;
24 AROS_INTP(FNAME_DEV(PendingInt));
25 AROS_INTP(FNAME_DEV(NakTimeoutInt));
27 static void GlobalIRQHandler(struct USB2OTGUnit *USBUnit, struct ExecBase *SysBase)
29 D(bug("[USB2OTG] %s: Received USB interrupt for Unit @ 0x%p\n",
30 __PRETTY_FUNCTION__, USBUnit));
34 *===========================================================
35 * Init(base)
36 *===========================================================
38 static int FNAME_DEV(Init)(LIBBASETYPEPTR USB2OTGBase)
40 volatile unsigned int *pmmailbox = (ARM_PERIIOBASE + 0xB880);
41 volatile unsigned int otg_RegVal;
42 unsigned int otg_OperatingMode = 0, pmres;
44 D(bug("[USB2OTG] %s: USB2OTGBase @ 0x%p, SysBase @ 0x%p\n",
45 __PRETTY_FUNCTION__, USB2OTGBase, SysBase));
47 otg_RegVal = *((volatile unsigned int *)USB2OTG_VENDORID);
49 if ((otg_RegVal & 0xFFFFF000) != 0x4F542000)
51 bug("[USB2OTG] Unsupported HS OTG USB Core Found\n");
52 bug("[USB2OTG] Hardware: %c%c%x.%x%x%x\n",
53 ((otg_RegVal >> 24) & 0xFF), ((otg_RegVal >> 16) & 0xFF),
54 ((otg_RegVal >> 12) & 0xF), ((otg_RegVal >> 8) & 0xF), ((otg_RegVal >> 4) & 0xF), (otg_RegVal & 0xF)
57 USB2OTGBase = NULL;
59 else
61 USB2OTGBase->hd_KernelBase = OpenResource("kernel.resource");
62 D(bug("[USB2OTG] %s: kernel.resource opened @ 0x%p\n",
63 __PRETTY_FUNCTION__, USB2OTGBase->hd_KernelBase));
65 if((USB2OTGBase->hd_MsgPort = CreateMsgPort()))
67 if((USB2OTGBase->hd_TimerReq = (struct timerequest *) CreateIORequest(USB2OTGBase->hd_MsgPort, sizeof(struct timerequest))))
69 if(!OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *) USB2OTGBase->hd_TimerReq, 0))
71 USB2OTGBase->hd_TimerReq->tr_node.io_Message.mn_Node.ln_Name = "USB2OTG Timer";
72 USB2OTGBase->hd_TimerReq->tr_node.io_Command = TR_ADDREQUEST;
73 D(bug("[USB2OTG] %s: timer.device opened\n",
74 __PRETTY_FUNCTION__));
76 bug("[USB2OTG] HS OTG Core Release: %c%c%x.%x%x%x\n",
77 ((otg_RegVal >> 24) & 0xFF), ((otg_RegVal >> 16) & 0xFF),
78 ((otg_RegVal >> 12) & 0xF), ((otg_RegVal >> 8) & 0xF), ((otg_RegVal >> 4) & 0xF), (otg_RegVal & 0xF)
81 otg_RegVal = *((volatile unsigned int *)USB2OTG_HARDWARE2);
82 bug("[USB2OTG] Architecture: %d - ", ((otg_RegVal & (3 << 3)) >> 3));
83 switch (((otg_RegVal & (3 << 3)) >> 3))
85 case 2:
86 bug("Internal DMA\n");
87 break;
88 case 1:
89 bug("External DMA\n");
90 break;
91 default:
92 bug("Slave Only\n");
93 break;
96 D(bug("[USB2OTG] %s: Disabling USB Interrupts (Globaly)..\n", __PRETTY_FUNCTION__));
97 otg_RegVal = *((volatile unsigned int *)USB2OTG_AHB);
98 otg_RegVal &= ~USB2OTG_AHB_INTENABLE;
99 *((volatile unsigned int *)USB2OTG_INTRMASK) = 0;
100 *((volatile unsigned int *)USB2OTG_AHB) = otg_RegVal;
102 while (pmmailbox[6] & 0x80000000);
103 pmmailbox[8] = 0x80;
104 do {
105 while (pmmailbox[6] & 0x40000000);
106 } while (((pmres = pmmailbox[0]) & 0xf) != 0);
107 if (pmres != 0x80)
109 bug("[USB2OTG] Failed to power on controller\n");
110 //USB2OTGBase->hd_TimerReq
111 //USB2OTGBase->hd_MsgPort
112 USB2OTGBase = NULL;
113 return FALSE;
116 if ((USB2OTGBase->hd_UtilityBase = (APTR)OpenLibrary("utility.library", 39)) != NULL)
118 USB2OTGBase->hd_MemPool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR | MEMF_SEM_PROTECTED, 16384, 4096);
119 if (USB2OTGBase->hd_MemPool)
121 int ns;
123 D(bug("[USB2OTG] %s: Allocated MemPool @ 0x%p\n",
124 __PRETTY_FUNCTION__, USB2OTGBase->hd_MemPool));
126 if (USB2OTGBase)
129 otg_RegVal = *((volatile unsigned int *)USB2OTG_HARDWARE);
130 bug("[USB2OTG] %s: HWConfig: %08x-", __PRETTY_FUNCTION__, otg_RegVal);
131 otg_RegVal = *((volatile unsigned int *)USB2OTG_HARDWARE2);
132 bug("%08x-", otg_RegVal);
133 otg_RegVal = *((volatile unsigned int *)USB2OTG_HARDWARE3);
134 bug("%08x-", otg_RegVal);
135 otg_RegVal = *((volatile unsigned int *)USB2OTG_HARDWARE4);
136 bug("%08x\n", otg_RegVal);
139 otg_RegVal = *((volatile unsigned int *)USB2OTG_USB);
140 otg_RegVal &= ~(USB2OTG_USB_ULPIDRIVEEXTERNALVBUS|USB2OTG_USB_TSDLINEPULSEENABLE);
141 *((volatile unsigned int *)USB2OTG_USB) = otg_RegVal;
143 D(bug("[USB2OTG] %s: Reseting Controller ..\n", __PRETTY_FUNCTION__));
144 *((volatile unsigned int *)USB2OTG_RESET) = USB2OTG_RESET_CORESOFT;
145 for (ns = 0; ns < 10000; ns++) { asm volatile("mov r0, r0\n"); } // Wait 10ms
146 if ((*((volatile unsigned int *)USB2OTG_RESET) & USB2OTG_RESET_CORESOFT) != 0)
147 bug("[USB2OTG] %s: Reset Timed-Out!\n", __PRETTY_FUNCTION__);
149 if ((USB2OTGBase->hd_Unit = AllocPooled(USB2OTGBase->hd_MemPool, sizeof(struct USB2OTGUnit))) != NULL)
151 D(bug("[USB2OTG] %s: Unit Allocated at 0x%p\n",
152 __PRETTY_FUNCTION__, USB2OTGBase->hd_Unit));
154 NewList(&USB2OTGBase->hd_Unit->hu_IOPendingQueue);
156 NewList(&USB2OTGBase->hd_Unit->hu_CtrlXFerQueue);
157 NewList(&USB2OTGBase->hd_Unit->hu_IntXFerQueue);
158 NewList(&USB2OTGBase->hd_Unit->hu_IsoXFerQueue);
159 NewList(&USB2OTGBase->hd_Unit->hu_BulkXFerQueue);
160 NewList(&USB2OTGBase->hd_Unit->hu_TDQueue);
161 NewList(&USB2OTGBase->hd_Unit->hu_AbortQueue);
162 NewList(&USB2OTGBase->hd_Unit->hu_PeriodicTDQueue);
164 USB2OTGBase->hd_Unit->hu_PendingInt.is_Node.ln_Type = NT_INTERRUPT;
165 USB2OTGBase->hd_Unit->hu_PendingInt.is_Node.ln_Name = "OTG2USB Pending Work Interrupt";
166 USB2OTGBase->hd_Unit->hu_PendingInt.is_Node.ln_Pri = 0;
167 USB2OTGBase->hd_Unit->hu_PendingInt.is_Data = USB2OTGBase->hd_Unit;
168 USB2OTGBase->hd_Unit->hu_PendingInt.is_Code = (VOID_FUNC)FNAME_DEV(PendingInt);
170 USB2OTGBase->hd_Unit->hu_NakTimeoutInt.is_Node.ln_Type = NT_INTERRUPT;
171 USB2OTGBase->hd_Unit->hu_NakTimeoutInt.is_Node.ln_Name = "OTG2USB NakTimeout Interrupt";
172 USB2OTGBase->hd_Unit->hu_NakTimeoutInt.is_Node.ln_Pri = -16;
173 USB2OTGBase->hd_Unit->hu_NakTimeoutInt.is_Data = USB2OTGBase->hd_Unit;
174 USB2OTGBase->hd_Unit->hu_NakTimeoutInt.is_Code = (VOID_FUNC)FNAME_DEV(NakTimeoutInt);
176 USB2OTGBase->hd_Unit->hu_NakTimeoutMsgPort.mp_Node.ln_Type = NT_MSGPORT;
177 USB2OTGBase->hd_Unit->hu_NakTimeoutMsgPort.mp_Flags = PA_SOFTINT;
178 USB2OTGBase->hd_Unit->hu_NakTimeoutMsgPort.mp_SigTask = &USB2OTGBase->hd_Unit->hu_NakTimeoutInt;
179 NewList(&USB2OTGBase->hd_Unit->hu_NakTimeoutMsgPort.mp_MsgList);
181 CopyMem(USB2OTGBase->hd_TimerReq, &USB2OTGBase->hd_Unit->hu_NakTimeoutReq, sizeof(struct timerequest));
182 USB2OTGBase->hd_Unit->hu_NakTimeoutReq.tr_node.io_Message.mn_ReplyPort = &USB2OTGBase->hd_Unit->hu_NakTimeoutMsgPort;
184 USB2OTGBase->hd_Unit->hu_HubPortChanged = FALSE;
186 USB2OTGBase->hd_Unit->hu_OperatingMode = (otg_OperatingMode == (USB2OTG_USBHOSTMODE|USB2OTG_USBDEVICEMODE)) ? 0 : otg_OperatingMode;
188 #if (0)
189 D(bug("[USB2OTG] %s: Unit Mode %d\n",
190 __PRETTY_FUNCTION__, USB2OTGBase->hd_Unit->hu_OperatingMode));
191 #endif
192 USB2OTGBase->hd_Unit->hu_GlobalIRQHandle = KrnAddIRQHandler(IRQ_HOSTPORT, GlobalIRQHandler, USB2OTGBase->hd_Unit, SysBase);
194 D(bug("[USB2OTG] %s: Installed Global IRQ Handler [handle @ 0x%p] for IRQ #%ld\n",
195 __PRETTY_FUNCTION__, USB2OTGBase->hd_Unit->hu_GlobalIRQHandle, IRQ_HOSTPORT));
197 D(bug("[USB2OTG] %s: Initialising PHY ..\n", __PRETTY_FUNCTION__));
198 otg_RegVal = *((volatile unsigned int *)USB2OTG_USB);
199 otg_RegVal &= ~USB2OTG_USB_PHYINTERFACE;
200 otg_RegVal |= USB2OTG_USB_MODESELECT_UTMI;
201 *((volatile unsigned int *)USB2OTG_USB) = otg_RegVal;
203 D(bug("[USB2OTG] %s: Reseting Controller ..\n", __PRETTY_FUNCTION__));
204 *((volatile unsigned int *)USB2OTG_RESET) = USB2OTG_RESET_CORESOFT;
205 for (ns = 0; ns < 10000; ns++) { asm volatile("mov r0, r0\n"); } // Wait 10ms
206 if ((*((volatile unsigned int *)USB2OTG_RESET) & USB2OTG_RESET_CORESOFT) != 0)
207 bug("[USB2OTG] %s: Reset Timed-Out!\n", __PRETTY_FUNCTION__);
209 otg_RegVal = *((volatile unsigned int *)USB2OTG_HARDWARE2);
210 if (((otg_RegVal & (3 << 6) >> 6) == 2) && ((otg_RegVal & (3 << 8) >> 8) == 1))
212 D(bug("[USB2OTG] %s: ULPI FSLS configuration: enabled.\n", __PRETTY_FUNCTION__));
213 otg_RegVal = *((volatile unsigned int *)USB2OTG_USB);
214 otg_RegVal |= (USB2OTG_USB_ULPIFSLS|USB2OTG_USB_ULPI_CLK_SUS_M);
215 *((volatile unsigned int *)USB2OTG_USB) = otg_RegVal;
216 } else {
217 D(bug("[USB2OTG] %s: ULPI FSLS configuration: disabled.\n", __PRETTY_FUNCTION__));
218 otg_RegVal = *((volatile unsigned int *)USB2OTG_USB);
219 otg_RegVal &= ~(USB2OTG_USB_ULPIFSLS|USB2OTG_USB_ULPI_CLK_SUS_M);
220 *((volatile unsigned int *)USB2OTG_USB) = otg_RegVal;
223 D(bug("[USB2OTG] %s: Enabling DMA configuration..\n", __PRETTY_FUNCTION__));
224 otg_RegVal = *((volatile unsigned int *)USB2OTG_AHB);
225 otg_RegVal &= ~(1 << USB2OTG_AHB_DMAREMAINDERMODE);
226 otg_RegVal |= (USB2OTG_AHB_DMAENABLE|USB2OTG_AHB_DMAREMAINDERMODE_INCR);
227 *((volatile unsigned int *)USB2OTG_AHB) = otg_RegVal;
229 D(bug("[USB2OTG] %s: Operating Mode: ", __PRETTY_FUNCTION__));
230 otg_RegVal = *((volatile unsigned int *)USB2OTG_HARDWARE2);
231 switch (otg_RegVal & 7)
233 case 0:
234 D(bug("HNP/SRP\n"));
235 otg_RegVal = *((volatile unsigned int *)USB2OTG_USB);
236 otg_RegVal |= (USB2OTG_USB_HNPCAPABLE|USB2OTG_USB_SRPCAPABLE);
237 *((volatile unsigned int *)USB2OTG_USB) = otg_RegVal;
238 break;
239 case 1:
240 case 3:
241 case 5:
242 D(bug("SRP\n"));
243 otg_RegVal = *((volatile unsigned int *)USB2OTG_USB);
244 otg_RegVal &= ~USB2OTG_USB_HNPCAPABLE;
245 otg_RegVal |= USB2OTG_USB_SRPCAPABLE;
246 *((volatile unsigned int *)USB2OTG_USB) = otg_RegVal;
247 break;
248 case 2:
249 case 4:
250 case 6:
251 D(bug("No HNP or SRP\n"));
252 otg_RegVal = *((volatile unsigned int *)USB2OTG_USB);
253 otg_RegVal &= ~(USB2OTG_USB_HNPCAPABLE|USB2OTG_USB_SRPCAPABLE);
254 *((volatile unsigned int *)USB2OTG_USB) = otg_RegVal;
255 break;
258 bug("[USB2OTG] HS OTG USB Driver Initialised\n");
262 else
264 D(bug("[USB2OTG] %s: Failed to Create MemPool\n",
265 __PRETTY_FUNCTION__));
267 CloseLibrary((struct Library *) UtilityBase);
268 USB2OTGBase = NULL;
271 else
273 D(bug("[USB2OTG] %s: OpenLibrary(\"utility.library\", 39) failed!\n",
274 __PRETTY_FUNCTION__));
276 USB2OTGBase = NULL;
279 else
281 D(bug("[USB2OTG] %s: OpenDevice(\"timer.device\") failed!\n",
282 __PRETTY_FUNCTION__));
284 USB2OTGBase = NULL;
287 else
289 D(bug("[USB2OTG] %s: Failed to allocate timer IORequest\n",
290 __PRETTY_FUNCTION__));
292 USB2OTGBase = NULL;
295 else
297 D(bug("[USB2OTG] %s: Failed to create MsgPort\n",
298 __PRETTY_FUNCTION__));
300 USB2OTGBase = NULL;
304 return USB2OTGBase ? TRUE : FALSE;
308 *===========================================================
309 * Open(ioreq, unit, flags, base)
310 *===========================================================
312 * This is the the DEV_OPEN function.
315 static int FNAME_DEV(Open)(LIBBASETYPEPTR USB2OTGBase, struct IOUsbHWReq *ioreq, ULONG otg_Unit, ULONG flags)
317 D(bug("[USB2OTG] %s: IOReq @ 0x%p, unit #%ld, flags = 0x%08lx, USB2OTGBase @ 0x%p\n",
318 __PRETTY_FUNCTION__, ioreq, otg_Unit, flags, USB2OTGBase));
320 D(bug("[USB2OTG] %s: openCnt = %ld\n",
321 __PRETTY_FUNCTION__, USB2OTGBase->hd_Library.lib_OpenCnt));
323 if (ioreq->iouh_Req.io_Message.mn_Length < sizeof(struct IOUsbHWReq))
325 D(bug("[USB2OTG] %s: invalid MN_LENGTH!\n",
326 __PRETTY_FUNCTION__));
328 ioreq->iouh_Req.io_Error = IOERR_BADLENGTH;
330 else
332 ioreq->iouh_Req.io_Error = IOERR_OPENFAIL;
334 ioreq->iouh_Req.io_Unit = FNAME_DEV(OpenUnit)(ioreq, otg_Unit, USB2OTGBase);
335 if (!(ioreq->iouh_Req.io_Unit))
337 D(bug("[USB2OTG] %s: could not open unit!\n",
338 __PRETTY_FUNCTION__));
341 else
343 ioreq->iouh_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
344 ioreq->iouh_Req.io_Error = 0;
346 return TRUE;
350 return FALSE;
355 *===========================================================
356 * Close(ioreq, base)
357 *===========================================================
359 * This is the the DEV_EXPUNGE function.
362 static int FNAME_DEV(Close)(LIBBASETYPEPTR USB2OTGBase, struct IOUsbHWReq *ioreq)
364 D(bug("[USB2OTG] %s: IOReq @ 0x%p, USB2OTGBase @ 0x%p\n",
365 __PRETTY_FUNCTION__, ioreq, USB2OTGBase));
367 FNAME_DEV(CloseUnit)(ioreq, (struct USB2OTGUnit *) ioreq->iouh_Req.io_Unit, USB2OTGBase);
369 ioreq->iouh_Req.io_Unit = (APTR) -1;
370 ioreq->iouh_Req.io_Device = (APTR) -1;
371 return TRUE;
374 static int FNAME_DEV(Expunge)(LIBBASETYPEPTR USB2OTGBase)
376 DeletePool(USB2OTGBase->hd_MemPool);
378 D(bug("[USB2OTG] %s: closing utility.library @ 0x%p\n",
379 __PRETTY_FUNCTION__, UtilityBase));
381 CloseLibrary((struct Library *) UtilityBase);
382 return TRUE;
385 ADD2INITLIB(FNAME_DEV(Init), 0)
386 ADD2OPENDEV(FNAME_DEV(Open), 0)
387 ADD2CLOSEDEV(FNAME_DEV(Close), 0)
388 ADD2EXPUNGELIB(FNAME_DEV(Expunge), 0)
391 *===========================================================
392 * BeginIO(ioreq, base)
393 *===========================================================
395 * This is the DEV_BEGINIO vector of the device.
398 AROS_LH1(void, FNAME_DEV(BeginIO),
399 AROS_LHA(struct IOUsbHWReq *, ioreq, A1),
400 LIBBASETYPEPTR, USB2OTGBase, 5, usb2otg)
402 AROS_LIBFUNC_INIT
404 struct USB2OTGUnit *otg_Unit = (struct USB2OTGUnit *) ioreq->iouh_Req.io_Unit;
405 WORD ret;
407 D(bug("[USB2OTG] %s: IOReq @ 0x%08lx, USB2OTGBase @ 0x%08lx [cmd:%lu]\n",
408 __PRETTY_FUNCTION__, ioreq, USB2OTGBase, ioreq->iouh_Req.io_Command));
410 ioreq->iouh_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
411 ioreq->iouh_Req.io_Error = UHIOERR_NO_ERROR;
413 if (ioreq->iouh_Req.io_Command < NSCMD_DEVICEQUERY)
415 switch (ioreq->iouh_Req.io_Command)
417 case CMD_RESET:
418 ret = FNAME_DEV(cmdReset)(ioreq, otg_Unit, USB2OTGBase);
419 break;
421 case CMD_FLUSH:
422 ret = FNAME_DEV(cmdFlush)(ioreq, otg_Unit, USB2OTGBase);
423 break;
425 case UHCMD_QUERYDEVICE:
426 ret = FNAME_DEV(cmdQueryDevice)(ioreq, otg_Unit, USB2OTGBase);
427 break;
429 case UHCMD_USBRESET:
430 ret = FNAME_DEV(cmdUsbReset)(ioreq, otg_Unit, USB2OTGBase);
431 break;
433 case UHCMD_USBRESUME:
434 ret = FNAME_DEV(cmdUsbResume)(ioreq, otg_Unit, USB2OTGBase);
435 break;
437 case UHCMD_USBSUSPEND:
438 ret = FNAME_DEV(cmdUsbSuspend)(ioreq, otg_Unit, USB2OTGBase);
439 break;
441 case UHCMD_USBOPER:
442 ret = FNAME_DEV(cmdUsbOper)(ioreq, otg_Unit, USB2OTGBase);
443 break;
445 case UHCMD_CONTROLXFER:
446 ret = FNAME_DEV(cmdControlXFer)(ioreq, otg_Unit, USB2OTGBase);
447 break;
449 case UHCMD_BULKXFER:
450 ret = FNAME_DEV(cmdBulkXFer)(ioreq, otg_Unit, USB2OTGBase);
451 break;
453 case UHCMD_INTXFER:
454 ret = FNAME_DEV(cmdIntXFer)(ioreq, otg_Unit, USB2OTGBase);
455 break;
457 case UHCMD_ISOXFER:
458 ret = FNAME_DEV(cmdIsoXFer)(ioreq, otg_Unit, USB2OTGBase);
459 break;
461 default:
462 ret = IOERR_NOCMD;
463 break;
466 else
468 switch(ioreq->iouh_Req.io_Command)
470 case NSCMD_DEVICEQUERY:
471 ret = FNAME_DEV(cmdNSDeviceQuery)((struct IOStdReq *) ioreq, otg_Unit, USB2OTGBase);
472 break;
474 default:
475 ret = IOERR_NOCMD;
476 break;
480 if (ret != RC_DONTREPLY)
482 D(bug("[USB2OTG] %s: Terminating I/O..\n",
483 __PRETTY_FUNCTION__));
485 if (ret != RC_OK)
487 ioreq->iouh_Req.io_Error = ret & 0xff;
489 FNAME_DEV(TermIO)(ioreq, USB2OTGBase);
492 AROS_LIBFUNC_EXIT
496 *===========================================================
497 * AbortIO(ioreq, base)
498 *===========================================================
500 * This is the DEV_ABORTIO vector of the device. It abort
501 * the given iorequest, and set
504 AROS_LH1(LONG, FNAME_DEV(AbortIO),
505 AROS_LHA(struct IOUsbHWReq *, ioreq, A1),
506 LIBBASETYPEPTR, USB2OTGBase, 6, usb2otg)
508 AROS_LIBFUNC_INIT
510 D(bug("[USB2OTG] %s: IOReq @ 0x%p, command %ld, status %ld\n",
511 __PRETTY_FUNCTION__, ioreq, ioreq->iouh_Req.io_Command, ioreq->iouh_Req.io_Message.mn_Node.ln_Type));
513 /* Is it pending? */
514 if (ioreq->iouh_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
516 // if (FNAME_DEV(cmdAbortIO)(ioreq, USB2OTGBase))
517 // {
518 // return(0);
519 // }
521 return(-1);
523 AROS_LIBFUNC_EXIT
526 void FNAME_DEV(Cause)(LIBBASETYPEPTR USB2OTGBase, struct Interrupt *interrupt)
528 /* this is a workaround for the original Cause() function missing tailed calls */
529 Disable();
531 if((interrupt->is_Node.ln_Type == NT_SOFTINT) || (interrupt->is_Node.ln_Type == NT_USER))
533 // signal tailed call
534 interrupt->is_Node.ln_Type = NT_USER;
535 } else {
538 interrupt->is_Node.ln_Type = NT_SOFTINT;
539 Forbid(); // make sure code is not interrupted by other tasks
540 Enable();
541 AROS_INTC1(interrupt->is_Code, interrupt->is_Data);
542 Disable();
543 Permit();
544 } while(interrupt->is_Node.ln_Type != NT_SOFTINT);
545 interrupt->is_Node.ln_Type = NT_INTERRUPT;
547 Enable();