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
;
236 D(bug("[USB2OTG] %s: Operating Mode: ", __PRETTY_FUNCTION__
));
237 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
238 switch (otg_RegVal
& 7)
242 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
243 otg_RegVal
|= (USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
244 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
250 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
251 otg_RegVal
&= ~USB2OTG_USB_HNPCAPABLE
;
252 otg_RegVal
|= USB2OTG_USB_SRPCAPABLE
;
253 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
258 D(bug("No HNP or SRP\n"));
259 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
260 otg_RegVal
&= ~(USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
261 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
265 bug("[USB2OTG] HS OTG USB Driver Initialised\n");
271 D(bug("[USB2OTG] %s: Failed to Create MemPool\n",
272 __PRETTY_FUNCTION__
));
274 CloseLibrary((struct Library
*) UtilityBase
);
280 D(bug("[USB2OTG] %s: OpenLibrary(\"utility.library\", 39) failed!\n",
281 __PRETTY_FUNCTION__
));
288 D(bug("[USB2OTG] %s: OpenDevice(\"timer.device\") failed!\n",
289 __PRETTY_FUNCTION__
));
296 D(bug("[USB2OTG] %s: Failed to allocate timer IORequest\n",
297 __PRETTY_FUNCTION__
));
304 D(bug("[USB2OTG] %s: Failed to create MsgPort\n",
305 __PRETTY_FUNCTION__
));
311 return USB2OTGBase
? TRUE
: FALSE
;
315 *===========================================================
316 * Open(ioreq, unit, flags, base)
317 *===========================================================
319 * This is the the DEV_OPEN function.
322 static int FNAME_DEV(Open
)(LIBBASETYPEPTR USB2OTGBase
, struct IOUsbHWReq
*ioreq
, ULONG otg_Unit
, ULONG flags
)
324 D(bug("[USB2OTG] %s: IOReq @ 0x%p, unit #%ld, flags = 0x%08lx, USB2OTGBase @ 0x%p\n",
325 __PRETTY_FUNCTION__
, ioreq
, otg_Unit
, flags
, USB2OTGBase
));
327 D(bug("[USB2OTG] %s: openCnt = %ld\n",
328 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Library
.lib_OpenCnt
));
330 if (ioreq
->iouh_Req
.io_Message
.mn_Length
< sizeof(struct IOUsbHWReq
))
332 D(bug("[USB2OTG] %s: invalid MN_LENGTH!\n",
333 __PRETTY_FUNCTION__
));
335 ioreq
->iouh_Req
.io_Error
= IOERR_BADLENGTH
;
339 ioreq
->iouh_Req
.io_Error
= IOERR_OPENFAIL
;
341 ioreq
->iouh_Req
.io_Unit
= FNAME_DEV(OpenUnit
)(ioreq
, otg_Unit
, USB2OTGBase
);
342 if (!(ioreq
->iouh_Req
.io_Unit
))
344 D(bug("[USB2OTG] %s: could not open unit!\n",
345 __PRETTY_FUNCTION__
));
350 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
351 ioreq
->iouh_Req
.io_Error
= 0;
362 *===========================================================
364 *===========================================================
366 * This is the the DEV_EXPUNGE function.
369 static int FNAME_DEV(Close
)(LIBBASETYPEPTR USB2OTGBase
, struct IOUsbHWReq
*ioreq
)
371 D(bug("[USB2OTG] %s: IOReq @ 0x%p, USB2OTGBase @ 0x%p\n",
372 __PRETTY_FUNCTION__
, ioreq
, USB2OTGBase
));
374 FNAME_DEV(CloseUnit
)(ioreq
, (struct USB2OTGUnit
*) ioreq
->iouh_Req
.io_Unit
, USB2OTGBase
);
376 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
377 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
381 static int FNAME_DEV(Expunge
)(LIBBASETYPEPTR USB2OTGBase
)
383 DeletePool(USB2OTGBase
->hd_MemPool
);
385 D(bug("[USB2OTG] %s: closing utility.library @ 0x%p\n",
386 __PRETTY_FUNCTION__
, UtilityBase
));
388 CloseLibrary((struct Library
*) UtilityBase
);
392 ADD2INITLIB(FNAME_DEV(Init
), 0)
393 ADD2OPENDEV(FNAME_DEV(Open
), 0)
394 ADD2CLOSEDEV(FNAME_DEV(Close
), 0)
395 ADD2EXPUNGELIB(FNAME_DEV(Expunge
), 0)
398 *===========================================================
399 * BeginIO(ioreq, base)
400 *===========================================================
402 * This is the DEV_BEGINIO vector of the device.
405 AROS_LH1(void, FNAME_DEV(BeginIO
),
406 AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
),
407 LIBBASETYPEPTR
, USB2OTGBase
, 5, usb2otg
)
411 struct USB2OTGUnit
*otg_Unit
= (struct USB2OTGUnit
*) ioreq
->iouh_Req
.io_Unit
;
414 D(bug("[USB2OTG] %s: IOReq @ 0x%08lx, USB2OTGBase @ 0x%08lx [cmd:%lu]\n",
415 __PRETTY_FUNCTION__
, ioreq
, USB2OTGBase
, ioreq
->iouh_Req
.io_Command
));
417 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
418 ioreq
->iouh_Req
.io_Error
= UHIOERR_NO_ERROR
;
420 if (ioreq
->iouh_Req
.io_Command
< NSCMD_DEVICEQUERY
)
422 switch (ioreq
->iouh_Req
.io_Command
)
425 ret
= FNAME_DEV(cmdReset
)(ioreq
, otg_Unit
, USB2OTGBase
);
429 ret
= FNAME_DEV(cmdFlush
)(ioreq
, otg_Unit
, USB2OTGBase
);
432 case UHCMD_QUERYDEVICE
:
433 ret
= FNAME_DEV(cmdQueryDevice
)(ioreq
, otg_Unit
, USB2OTGBase
);
437 ret
= FNAME_DEV(cmdUsbReset
)(ioreq
, otg_Unit
, USB2OTGBase
);
440 case UHCMD_USBRESUME
:
441 ret
= FNAME_DEV(cmdUsbResume
)(ioreq
, otg_Unit
, USB2OTGBase
);
444 case UHCMD_USBSUSPEND
:
445 ret
= FNAME_DEV(cmdUsbSuspend
)(ioreq
, otg_Unit
, USB2OTGBase
);
449 ret
= FNAME_DEV(cmdUsbOper
)(ioreq
, otg_Unit
, USB2OTGBase
);
452 case UHCMD_CONTROLXFER
:
453 ret
= FNAME_DEV(cmdControlXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
457 ret
= FNAME_DEV(cmdBulkXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
461 ret
= FNAME_DEV(cmdIntXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
465 ret
= FNAME_DEV(cmdIsoXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
475 switch(ioreq
->iouh_Req
.io_Command
)
477 case NSCMD_DEVICEQUERY
:
478 ret
= FNAME_DEV(cmdNSDeviceQuery
)((struct IOStdReq
*) ioreq
, otg_Unit
, USB2OTGBase
);
487 if (ret
!= RC_DONTREPLY
)
489 D(bug("[USB2OTG] %s: Terminating I/O..\n",
490 __PRETTY_FUNCTION__
));
494 ioreq
->iouh_Req
.io_Error
= ret
& 0xff;
496 FNAME_DEV(TermIO
)(ioreq
, USB2OTGBase
);
503 *===========================================================
504 * AbortIO(ioreq, base)
505 *===========================================================
507 * This is the DEV_ABORTIO vector of the device. It abort
508 * the given iorequest, and set
511 AROS_LH1(LONG
, FNAME_DEV(AbortIO
),
512 AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
),
513 LIBBASETYPEPTR
, USB2OTGBase
, 6, usb2otg
)
517 D(bug("[USB2OTG] %s: IOReq @ 0x%p, command %ld, status %ld\n",
518 __PRETTY_FUNCTION__
, ioreq
, ioreq
->iouh_Req
.io_Command
, ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
));
521 if (ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
523 // if (FNAME_DEV(cmdAbortIO)(ioreq, USB2OTGBase))
533 void FNAME_DEV(Cause
)(LIBBASETYPEPTR USB2OTGBase
, struct Interrupt
*interrupt
)
535 /* this is a workaround for the original Cause() function missing tailed calls */
538 if((interrupt
->is_Node
.ln_Type
== NT_SOFTINT
) || (interrupt
->is_Node
.ln_Type
== NT_USER
))
540 // signal tailed call
541 interrupt
->is_Node
.ln_Type
= NT_USER
;
545 interrupt
->is_Node
.ln_Type
= NT_SOFTINT
;
546 Forbid(); // make sure code is not interrupted by other tasks
548 AROS_INTC1(interrupt
->is_Code
, interrupt
->is_Data
);
551 } while(interrupt
->is_Node
.ln_Type
!= NT_SOFTINT
);
552 interrupt
->is_Node
.ln_Type
= NT_INTERRUPT
;