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 __arm_periiobase
= KrnGetSystemAttr(KATTR_PeripheralBase
);
45 pmmailbox
= (volatile unsigned int *)(ARM_PERIIOBASE
+ 0xB880);
47 D(bug("[USB2OTG] %s: USB2OTGBase @ 0x%p, SysBase @ 0x%p\n",
48 __PRETTY_FUNCTION__
, USB2OTGBase
, SysBase
));
50 otg_RegVal
= *((volatile unsigned int *)USB2OTG_VENDORID
);
52 if ((otg_RegVal
& 0xFFFFF000) != 0x4F542000)
54 bug("[USB2OTG] Unsupported HS OTG USB Core Found\n");
55 bug("[USB2OTG] Hardware: %c%c%x.%x%x%x\n",
56 ((otg_RegVal
>> 24) & 0xFF), ((otg_RegVal
>> 16) & 0xFF),
57 ((otg_RegVal
>> 12) & 0xF), ((otg_RegVal
>> 8) & 0xF), ((otg_RegVal
>> 4) & 0xF), (otg_RegVal
& 0xF)
64 USB2OTGBase
->hd_KernelBase
= OpenResource("kernel.resource");
65 D(bug("[USB2OTG] %s: kernel.resource opened @ 0x%p\n",
66 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_KernelBase
));
68 if((USB2OTGBase
->hd_MsgPort
= CreateMsgPort()))
70 if((USB2OTGBase
->hd_TimerReq
= (struct timerequest
*) CreateIORequest(USB2OTGBase
->hd_MsgPort
, sizeof(struct timerequest
))))
72 if(!OpenDevice("timer.device", UNIT_MICROHZ
, (struct IORequest
*) USB2OTGBase
->hd_TimerReq
, 0))
74 USB2OTGBase
->hd_TimerReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "USB2OTG Timer";
75 USB2OTGBase
->hd_TimerReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
76 D(bug("[USB2OTG] %s: timer.device opened\n",
77 __PRETTY_FUNCTION__
));
79 bug("[USB2OTG] HS OTG Core Release: %c%c%x.%x%x%x\n",
80 ((otg_RegVal
>> 24) & 0xFF), ((otg_RegVal
>> 16) & 0xFF),
81 ((otg_RegVal
>> 12) & 0xF), ((otg_RegVal
>> 8) & 0xF), ((otg_RegVal
>> 4) & 0xF), (otg_RegVal
& 0xF)
84 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
85 bug("[USB2OTG] Architecture: %d - ", ((otg_RegVal
& (3 << 3)) >> 3));
86 switch (((otg_RegVal
& (3 << 3)) >> 3))
89 bug("Internal DMA\n");
92 bug("External DMA\n");
99 D(bug("[USB2OTG] %s: Disabling USB Interrupts (Globaly)..\n", __PRETTY_FUNCTION__
));
100 otg_RegVal
= *((volatile unsigned int *)USB2OTG_AHB
);
101 otg_RegVal
&= ~USB2OTG_AHB_INTENABLE
;
102 *((volatile unsigned int *)USB2OTG_INTRMASK
) = 0;
103 *((volatile unsigned int *)USB2OTG_AHB
) = otg_RegVal
;
105 while (pmmailbox
[6] & 0x80000000);
108 while (pmmailbox
[6] & 0x40000000);
109 } while (((pmres
= pmmailbox
[0]) & 0xf) != 0);
112 bug("[USB2OTG] Failed to power on controller\n");
113 //USB2OTGBase->hd_TimerReq
114 //USB2OTGBase->hd_MsgPort
119 if ((USB2OTGBase
->hd_UtilityBase
= (APTR
)OpenLibrary("utility.library", 39)) != NULL
)
121 USB2OTGBase
->hd_MemPool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
| MEMF_SEM_PROTECTED
, 16384, 4096);
122 if (USB2OTGBase
->hd_MemPool
)
126 D(bug("[USB2OTG] %s: Allocated MemPool @ 0x%p\n",
127 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_MemPool
));
132 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE
);
133 bug("[USB2OTG] %s: HWConfig: %08x-", __PRETTY_FUNCTION__
, otg_RegVal
);
134 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
135 bug("%08x-", otg_RegVal
);
136 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE3
);
137 bug("%08x-", otg_RegVal
);
138 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE4
);
139 bug("%08x\n", otg_RegVal
);
142 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
143 otg_RegVal
&= ~(USB2OTG_USB_ULPIDRIVEEXTERNALVBUS
|USB2OTG_USB_TSDLINEPULSEENABLE
);
144 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
146 D(bug("[USB2OTG] %s: Reseting Controller ..\n", __PRETTY_FUNCTION__
));
147 *((volatile unsigned int *)USB2OTG_RESET
) = USB2OTG_RESET_CORESOFT
;
148 for (ns
= 0; ns
< 10000; ns
++) { asm volatile("mov r0, r0\n"); } // Wait 10ms
149 if ((*((volatile unsigned int *)USB2OTG_RESET
) & USB2OTG_RESET_CORESOFT
) != 0)
150 bug("[USB2OTG] %s: Reset Timed-Out!\n", __PRETTY_FUNCTION__
);
152 if ((USB2OTGBase
->hd_Unit
= AllocPooled(USB2OTGBase
->hd_MemPool
, sizeof(struct USB2OTGUnit
))) != NULL
)
154 D(bug("[USB2OTG] %s: Unit Allocated at 0x%p\n",
155 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
));
157 NewList(&USB2OTGBase
->hd_Unit
->hu_IOPendingQueue
);
159 NewList(&USB2OTGBase
->hd_Unit
->hu_CtrlXFerQueue
);
160 NewList(&USB2OTGBase
->hd_Unit
->hu_IntXFerQueue
);
161 NewList(&USB2OTGBase
->hd_Unit
->hu_IsoXFerQueue
);
162 NewList(&USB2OTGBase
->hd_Unit
->hu_BulkXFerQueue
);
163 NewList(&USB2OTGBase
->hd_Unit
->hu_TDQueue
);
164 NewList(&USB2OTGBase
->hd_Unit
->hu_AbortQueue
);
165 NewList(&USB2OTGBase
->hd_Unit
->hu_PeriodicTDQueue
);
167 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Type
= NT_INTERRUPT
;
168 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Name
= "OTG2USB Pending Work Interrupt";
169 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Pri
= 0;
170 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Data
= USB2OTGBase
->hd_Unit
;
171 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Code
= (VOID_FUNC
)FNAME_DEV(PendingInt
);
173 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Type
= NT_INTERRUPT
;
174 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Name
= "OTG2USB NakTimeout Interrupt";
175 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Pri
= -16;
176 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Data
= USB2OTGBase
->hd_Unit
;
177 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Code
= (VOID_FUNC
)FNAME_DEV(NakTimeoutInt
);
179 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
180 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_Flags
= PA_SOFTINT
;
181 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_SigTask
= &USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
;
182 NewList(&USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_MsgList
);
184 CopyMem(USB2OTGBase
->hd_TimerReq
, &USB2OTGBase
->hd_Unit
->hu_NakTimeoutReq
, sizeof(struct timerequest
));
185 USB2OTGBase
->hd_Unit
->hu_NakTimeoutReq
.tr_node
.io_Message
.mn_ReplyPort
= &USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
;
187 USB2OTGBase
->hd_Unit
->hu_HubPortChanged
= FALSE
;
189 USB2OTGBase
->hd_Unit
->hu_OperatingMode
= (otg_OperatingMode
== (USB2OTG_USBHOSTMODE
|USB2OTG_USBDEVICEMODE
)) ? 0 : otg_OperatingMode
;
192 D(bug("[USB2OTG] %s: Unit Mode %d\n",
193 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
->hu_OperatingMode
));
195 USB2OTGBase
->hd_Unit
->hu_GlobalIRQHandle
= KrnAddIRQHandler(IRQ_HOSTPORT
, GlobalIRQHandler
, USB2OTGBase
->hd_Unit
, SysBase
);
197 D(bug("[USB2OTG] %s: Installed Global IRQ Handler [handle @ 0x%p] for IRQ #%ld\n",
198 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
->hu_GlobalIRQHandle
, IRQ_HOSTPORT
));
200 D(bug("[USB2OTG] %s: Initialising PHY ..\n", __PRETTY_FUNCTION__
));
201 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
202 otg_RegVal
&= ~USB2OTG_USB_PHYINTERFACE
;
203 otg_RegVal
|= USB2OTG_USB_MODESELECT_UTMI
;
204 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
206 D(bug("[USB2OTG] %s: Reseting Controller ..\n", __PRETTY_FUNCTION__
));
207 *((volatile unsigned int *)USB2OTG_RESET
) = USB2OTG_RESET_CORESOFT
;
208 for (ns
= 0; ns
< 10000; ns
++) { asm volatile("mov r0, r0\n"); } // Wait 10ms
209 if ((*((volatile unsigned int *)USB2OTG_RESET
) & USB2OTG_RESET_CORESOFT
) != 0)
210 bug("[USB2OTG] %s: Reset Timed-Out!\n", __PRETTY_FUNCTION__
);
212 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
213 if (((otg_RegVal
& (3 << 6) >> 6) == 2) && ((otg_RegVal
& (3 << 8) >> 8) == 1))
215 D(bug("[USB2OTG] %s: ULPI FSLS configuration: enabled.\n", __PRETTY_FUNCTION__
));
216 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
217 otg_RegVal
|= (USB2OTG_USB_ULPIFSLS
|USB2OTG_USB_ULPI_CLK_SUS_M
);
218 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
220 D(bug("[USB2OTG] %s: ULPI FSLS configuration: disabled.\n", __PRETTY_FUNCTION__
));
221 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
222 otg_RegVal
&= ~(USB2OTG_USB_ULPIFSLS
|USB2OTG_USB_ULPI_CLK_SUS_M
);
223 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
226 D(bug("[USB2OTG] %s: Enabling DMA configuration..\n", __PRETTY_FUNCTION__
));
227 otg_RegVal
= *((volatile unsigned int *)USB2OTG_AHB
);
228 otg_RegVal
&= ~(1 << USB2OTG_AHB_DMAREMAINDERMODE
);
229 otg_RegVal
|= (USB2OTG_AHB_DMAENABLE
|USB2OTG_AHB_DMAREMAINDERMODE_INCR
);
230 *((volatile unsigned int *)USB2OTG_AHB
) = otg_RegVal
;
232 D(bug("[USB2OTG] %s: Operating Mode: ", __PRETTY_FUNCTION__
));
233 otg_RegVal
= *((volatile unsigned int *)USB2OTG_HARDWARE2
);
234 switch (otg_RegVal
& 7)
238 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
239 otg_RegVal
|= (USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
240 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
246 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
247 otg_RegVal
&= ~USB2OTG_USB_HNPCAPABLE
;
248 otg_RegVal
|= USB2OTG_USB_SRPCAPABLE
;
249 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
254 D(bug("No HNP or SRP\n"));
255 otg_RegVal
= *((volatile unsigned int *)USB2OTG_USB
);
256 otg_RegVal
&= ~(USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
257 *((volatile unsigned int *)USB2OTG_USB
) = otg_RegVal
;
261 bug("[USB2OTG] HS OTG USB Driver Initialised\n");
267 D(bug("[USB2OTG] %s: Failed to Create MemPool\n",
268 __PRETTY_FUNCTION__
));
270 CloseLibrary((struct Library
*) UtilityBase
);
276 D(bug("[USB2OTG] %s: OpenLibrary(\"utility.library\", 39) failed!\n",
277 __PRETTY_FUNCTION__
));
284 D(bug("[USB2OTG] %s: OpenDevice(\"timer.device\") failed!\n",
285 __PRETTY_FUNCTION__
));
292 D(bug("[USB2OTG] %s: Failed to allocate timer IORequest\n",
293 __PRETTY_FUNCTION__
));
300 D(bug("[USB2OTG] %s: Failed to create MsgPort\n",
301 __PRETTY_FUNCTION__
));
307 return USB2OTGBase
? TRUE
: FALSE
;
311 *===========================================================
312 * Open(ioreq, unit, flags, base)
313 *===========================================================
315 * This is the the DEV_OPEN function.
318 static int FNAME_DEV(Open
)(LIBBASETYPEPTR USB2OTGBase
, struct IOUsbHWReq
*ioreq
, ULONG otg_Unit
, ULONG flags
)
320 D(bug("[USB2OTG] %s: IOReq @ 0x%p, unit #%ld, flags = 0x%08lx, USB2OTGBase @ 0x%p\n",
321 __PRETTY_FUNCTION__
, ioreq
, otg_Unit
, flags
, USB2OTGBase
));
323 D(bug("[USB2OTG] %s: openCnt = %ld\n",
324 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Library
.lib_OpenCnt
));
326 if (ioreq
->iouh_Req
.io_Message
.mn_Length
< sizeof(struct IOUsbHWReq
))
328 D(bug("[USB2OTG] %s: invalid MN_LENGTH!\n",
329 __PRETTY_FUNCTION__
));
331 ioreq
->iouh_Req
.io_Error
= IOERR_BADLENGTH
;
335 ioreq
->iouh_Req
.io_Error
= IOERR_OPENFAIL
;
337 ioreq
->iouh_Req
.io_Unit
= FNAME_DEV(OpenUnit
)(ioreq
, otg_Unit
, USB2OTGBase
);
338 if (!(ioreq
->iouh_Req
.io_Unit
))
340 D(bug("[USB2OTG] %s: could not open unit!\n",
341 __PRETTY_FUNCTION__
));
346 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
347 ioreq
->iouh_Req
.io_Error
= 0;
358 *===========================================================
360 *===========================================================
362 * This is the the DEV_EXPUNGE function.
365 static int FNAME_DEV(Close
)(LIBBASETYPEPTR USB2OTGBase
, struct IOUsbHWReq
*ioreq
)
367 D(bug("[USB2OTG] %s: IOReq @ 0x%p, USB2OTGBase @ 0x%p\n",
368 __PRETTY_FUNCTION__
, ioreq
, USB2OTGBase
));
370 FNAME_DEV(CloseUnit
)(ioreq
, (struct USB2OTGUnit
*) ioreq
->iouh_Req
.io_Unit
, USB2OTGBase
);
372 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
373 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
377 static int FNAME_DEV(Expunge
)(LIBBASETYPEPTR USB2OTGBase
)
379 DeletePool(USB2OTGBase
->hd_MemPool
);
381 D(bug("[USB2OTG] %s: closing utility.library @ 0x%p\n",
382 __PRETTY_FUNCTION__
, UtilityBase
));
384 CloseLibrary((struct Library
*) UtilityBase
);
388 ADD2INITLIB(FNAME_DEV(Init
), 0)
389 ADD2OPENDEV(FNAME_DEV(Open
), 0)
390 ADD2CLOSEDEV(FNAME_DEV(Close
), 0)
391 ADD2EXPUNGELIB(FNAME_DEV(Expunge
), 0)
394 *===========================================================
395 * BeginIO(ioreq, base)
396 *===========================================================
398 * This is the DEV_BEGINIO vector of the device.
401 AROS_LH1(void, FNAME_DEV(BeginIO
),
402 AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
),
403 LIBBASETYPEPTR
, USB2OTGBase
, 5, usb2otg
)
407 struct USB2OTGUnit
*otg_Unit
= (struct USB2OTGUnit
*) ioreq
->iouh_Req
.io_Unit
;
410 D(bug("[USB2OTG] %s: IOReq @ 0x%08lx, USB2OTGBase @ 0x%08lx [cmd:%lu]\n",
411 __PRETTY_FUNCTION__
, ioreq
, USB2OTGBase
, ioreq
->iouh_Req
.io_Command
));
413 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
414 ioreq
->iouh_Req
.io_Error
= UHIOERR_NO_ERROR
;
416 if (ioreq
->iouh_Req
.io_Command
< NSCMD_DEVICEQUERY
)
418 switch (ioreq
->iouh_Req
.io_Command
)
421 ret
= FNAME_DEV(cmdReset
)(ioreq
, otg_Unit
, USB2OTGBase
);
425 ret
= FNAME_DEV(cmdFlush
)(ioreq
, otg_Unit
, USB2OTGBase
);
428 case UHCMD_QUERYDEVICE
:
429 ret
= FNAME_DEV(cmdQueryDevice
)(ioreq
, otg_Unit
, USB2OTGBase
);
433 ret
= FNAME_DEV(cmdUsbReset
)(ioreq
, otg_Unit
, USB2OTGBase
);
436 case UHCMD_USBRESUME
:
437 ret
= FNAME_DEV(cmdUsbResume
)(ioreq
, otg_Unit
, USB2OTGBase
);
440 case UHCMD_USBSUSPEND
:
441 ret
= FNAME_DEV(cmdUsbSuspend
)(ioreq
, otg_Unit
, USB2OTGBase
);
445 ret
= FNAME_DEV(cmdUsbOper
)(ioreq
, otg_Unit
, USB2OTGBase
);
448 case UHCMD_CONTROLXFER
:
449 ret
= FNAME_DEV(cmdControlXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
453 ret
= FNAME_DEV(cmdBulkXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
457 ret
= FNAME_DEV(cmdIntXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
461 ret
= FNAME_DEV(cmdIsoXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
471 switch(ioreq
->iouh_Req
.io_Command
)
473 case NSCMD_DEVICEQUERY
:
474 ret
= FNAME_DEV(cmdNSDeviceQuery
)((struct IOStdReq
*) ioreq
, otg_Unit
, USB2OTGBase
);
483 if (ret
!= RC_DONTREPLY
)
485 D(bug("[USB2OTG] %s: Terminating I/O..\n",
486 __PRETTY_FUNCTION__
));
490 ioreq
->iouh_Req
.io_Error
= ret
& 0xff;
492 FNAME_DEV(TermIO
)(ioreq
, USB2OTGBase
);
499 *===========================================================
500 * AbortIO(ioreq, base)
501 *===========================================================
503 * This is the DEV_ABORTIO vector of the device. It abort
504 * the given iorequest, and set
507 AROS_LH1(LONG
, FNAME_DEV(AbortIO
),
508 AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
),
509 LIBBASETYPEPTR
, USB2OTGBase
, 6, usb2otg
)
513 D(bug("[USB2OTG] %s: IOReq @ 0x%p, command %ld, status %ld\n",
514 __PRETTY_FUNCTION__
, ioreq
, ioreq
->iouh_Req
.io_Command
, ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
));
517 if (ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
519 // if (FNAME_DEV(cmdAbortIO)(ioreq, USB2OTGBase))
529 void FNAME_DEV(Cause
)(LIBBASETYPEPTR USB2OTGBase
, struct Interrupt
*interrupt
)
531 /* this is a workaround for the original Cause() function missing tailed calls */
534 if((interrupt
->is_Node
.ln_Type
== NT_SOFTINT
) || (interrupt
->is_Node
.ln_Type
== NT_USER
))
536 // signal tailed call
537 interrupt
->is_Node
.ln_Type
= NT_USER
;
541 interrupt
->is_Node
.ln_Type
= NT_SOFTINT
;
542 Forbid(); // make sure code is not interrupted by other tasks
544 AROS_INTC1(interrupt
->is_Code
, interrupt
->is_Data
);
547 } while(interrupt
->is_Node
.ln_Type
!= NT_SOFTINT
);
548 interrupt
->is_Node
.ln_Type
= NT_INTERRUPT
;