2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
5 * NBMK Encryption Technologies provides no support of any kind for
6 * this software. Questions or concerns about it may be addressed to
7 * the members of the relevant open-source community at
8 * <tech-crypto@netbsd.org>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 static char const n8_id
[] = "$Id: irq.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
38 * @brief NSP2000 Device Driver interrupt handling functions
40 * This file contains all secondary interrupt handling routines for the
41 * NSP2000 Device Driver.
43 *****************************************************************************/
45 /*****************************************************************************
47 * 01/06/04 brr Clear the PKH & CCH status register prior to reading queue
48 * pointer register to ensure write completes before exiting the
49 * interrupt handler. Only write AMBA status register on AMBA
50 * timer interrupts. (Bug 995)
51 * 07/15/03 brr Moved CCH processing to a Linux tasklet.
52 * 07/01/03 brr Clear CCH interrupts before reenabling the core.
53 * 05/15/03 brr Enable RNG interrupt, remove references to duplicate register
54 * definitions in irq.h
55 * 04/08/03 brr Bypass AMBA mirror registers.
56 * 04/03/03 brr Minor modifications to improve performance.
57 * 04/01/03 brr Reverted N8_WaitOnRequest to accept timeout parameter.
58 * 03/31/03 brr Do not rely on atomic_inc_and_test.
59 * 03/24/03 brr Fix race condition when conditionally resetting AMBA timer.
60 * 03/21/03 brr Only check for completed EA commands on AMBA timer interrupt.
61 * 03/19/03 brr Added Interrupt statistics and display function, eliminating
62 * IRQ prints. Added reload_AMBA_timer function in order support
63 * running AMBA timer only when there are requests queued.
64 * Modified and moved N8_WaitOnRequest to QMGR.
65 * 03/18/03 brr Do not read PKH/CCH status register if no errors are reported
66 * in the AMBA status registers, assume command complete.
67 * 02/02/03 brr Updated command completion determination to use the number
68 * of commands completed instead of queue position. This
69 * elimated the need for forceCheck & relying on the request
70 * state to avoid prematurely marking a command complete.
71 * 12/09/02 brr Remove duplicate read in of read index in CCHInterrupt.
72 * 11/01/02 brr Reinstate forceCheck.
73 * 10/23/02 brr Remove forceCheck since interrupts are now disabled during
74 * the queue operation.
75 * 10/25/02 brr Clean up function prototypes & include files.
76 * 10/11/02 brr Added timeout parameter to N8_WaitOnRequest.
77 * 09/18/02 brr Added N8_WaitOnRequest & modified ISR to keep track of the
78 * number of requests completed.
79 * 09/10/02 brr Modified PKH & CCH interrupt service routines to handle the
80 * command completion interrupt.
81 * 06/10/02 brr Call QMgrCheckQueue if forceCheck is set.
82 * 06/05/02 mmd Eliminated unused debug messages, and ensured that when
83 * waitOnInterrupt is called with interruptible == FALSE,
84 * that AMBAbitmask is updated with the specified bitmask.
85 * 05/30/02 brr Enable interrupts for error conditions and handle them in the
87 * 05/20/02 brr Revert to a single AMBA wait queue.
88 * 04/30/02 brr Minor revisions to improve performance & incorporate comments
90 * 04/17/02 msz Don't call QMgr if there is nothing new done.
91 * 04/15/02 hml Added a call to N8_DOWN_KERNELSEM when we get an AMBA
92 * interrupt in kernel mode.
93 * 04/11/02 brr Pass parameter to waitOnInterrupt to indicate whether
94 * sleep should be interruptable.
95 * 04/03/02 brr Fix spurious interrupt by clearing the interrupt before
96 * reading the amba_pci_control.
97 * 03/19/02 msz Shadow memory is now called shared memory.
98 * 02/26/02 brr Modified the timer interrupt to update the queue pointers
99 * and complete the API requests.
100 * 02/27/02 msz Fixes for N8_WaitOnInterrupt support.
101 * 02/22/02 spm Converted printk's to DBG's. Added #include of n8_OS_intf.h
102 * 02/22/02 brr Removed references to qmgrData.
103 * 02/22/02 msz Fix for BUG 620, CCH should be using the EAshadow_p
104 * 02/15/02 brr Removed FPGA references.
105 * 02/06/02 msz Moved where we set shadow hw status.
106 * 01/31/02 brr On error, save status to shared memory.
107 * 01/15/02 msz Support for array of AMBA wait blocks. Also we now always
108 * do the wakeup call for AMBA interrupts once something has
109 * waited on an AMBA interrupt.
110 * 01/03/02 brr Reset bridge timer upon expiration.
111 * 01/16/02 brr Removed FPGA support.
112 * 12/03/01 mmd Accidentally always performing 11-12 PCI accesses when using
113 * ASIC, regardless of whether or not we have an IRQ.
114 * 11/30/01 mmd Forgot to wrap LCR manipulation with check for FPGA.
115 * 11/27/01 mmd Eliminated N8_EnableInterrupts. Modified
116 * n8_MainInterruptHandler to only bother with PLX if FPGA.
117 * Beyond that, everything is and should be treated identically.
118 * Renamed from simon_irq.c.
119 * 11/10/01 brr Modified to support static allocations of persistant data
121 * 10/17/01 mmd Revised all debug messages to use N8_IRQprint/N8_IRQPRINT
122 * except for N8_EnableInterrupts and n8_WaitOnInterrupt,
123 * neither of which are called from Interrupt time.
124 * 10/12/01 mmd In n8_WaitOnInterrupt, corrected handling of return values
125 * from N8_BlockWithTimeout.
126 * 09/24/01 mmd Added support in n8_WaitOnInterrupt and
127 * N8_MainInterruptHandler for AMBA interrupts, and adjusted
128 * return values for n8_WaitOnInterrupt. Corrected bug where
129 * the return code from N8_BlockWithTimeout was being
130 * misinterpreted. Updated call to N8_BlockWithTimeout, when
131 * passing a wait_queue_head_t* type.
132 * 09/20/01 mmd Implemented N8_MainInterruptHandler.
133 * 09/07/01 mmd Cleanup and revision of WaitOnInterrupt routine.
134 * 08/16/01 mmd No longer includes n8_types.h.
135 * 08/16/01 mmd Now includes nsp2000_regs.h instead of simon.h..
136 * 08/08/01 brr Moved all OS kernel specific macros to helper.h.
137 * 08/02/01 brr Fixed debug statements in WaitOn functions.
138 * 07/31/01 mmd Added SIMON_EnableInterrupts call.
139 * 06/27/01 jke added to debug print statements. Changed logic of if state-
140 * ments in IRQs to handle non-debug-execution
141 * 06/21/01 jke added use of BSDIDRIVER and WakeUp macro, altered N8_dbgPrt
142 * macro to encorporate "if (N8_IRQ_Debug_g)", making the
143 * resulting source more readable and compact.
144 * 06/12/01 jke altered to run under BSDi
145 * 05/29/01 mmd Incorporated suggestions from code review.
146 * 05/17/01 mmd Original version.
147 ****************************************************************************/
148 /** @defgroup NSP2000Driver NSP2000 Device Driver
153 #include "n8_driver_main.h"
154 #include "n8_driver_api.h"
156 #include "nsp2000_regs.h"
157 #include "nsp_ioctl.h"
158 #include "n8_OS_intf.h"
160 #include "n8_ea_common.h"
161 #include "n8_pk_common.h"
162 #include <sys/proc.h>
164 /* FORWARD PROTOTYPES */
165 void N8_PKHInterruptHandler ( NspInstance_t
*NSPinstance_p
,
167 void N8_RNHInterruptHandler ( NspInstance_t
*NSPinstance_p
);
168 void N8_CCHInterruptHandler ( NspInstance_t
*NSPinstance_p
,
171 /* INSTANCE, INDEXED BY MINOR NUMBER */
172 extern NspInstance_t NSPDeviceTable_g
[DEF_MAX_SIMON_INSTANCES
];
174 /* NSPcount_g MAINTAINS THE NUMBER OF DETECTED HARDWARE INSTANCES */
175 extern int NSPcount_g
;
176 extern wait_queue_head_t requestBlock
;
179 static int n8_IRQs_g
= 0;
180 static int n8_AMBA_IRQs_g
= 0;
181 static int n8_CCH_IRQs_g
= 0;
182 static int n8_PKH_IRQs_g
= 0;
183 int ambaTimerActive
= FALSE
;
185 #define N8_RELOAD_AMBA_MASK (AMBAIRQ_PKP | AMBAIRQ_CCH | AMBAIRQ_RNG | \
186 AMBAIRQ_Timer | AMBA_Timer_Reload)
188 void cch_do_tasklet (unsigned long unused
);
190 DECLARE_TASKLET(cch_tasklet
, cch_do_tasklet
, 0);
193 void cch_do_tasklet (unsigned long unused
)
196 NSP2000REGS_t
*nspRegPtr
;
197 NspInstance_t
*localNSPinstance_p
;
198 int eaReqsComplete
= 0;
200 uint16_t newReadIndex
;
201 uint16_t cmdsComplete
;
203 /* The bridge timer interrupt is only enabled for the first */
204 /* NSP, so when it fires, update the read pointer for each */
205 /* device installed in the system. */
206 for (nspIdx
= 0; nspIdx
< NSPcount_g
; nspIdx
++)
208 localNSPinstance_p
= &NSPDeviceTable_g
[nspIdx
];
209 nspRegPtr
= (NSP2000REGS_t
*)localNSPinstance_p
->NSPregs_p
;
211 /* Read & store the read pointers on each timer interrupt. */
212 cch_read
= (nspRegPtr
->cch_q_ptr
>>16);
214 /* Check for completed EA command blocks on */
215 /* the AMBA timer interrupt */
216 newReadIndex
= cch_read
;
217 if (newReadIndex
!= localNSPinstance_p
->EAreadIndex
)
219 cmdsComplete
= (newReadIndex
- localNSPinstance_p
->EAreadIndex
) &
220 (localNSPinstance_p
->EAqueue_size
-1);
221 localNSPinstance_p
->EAreadIndex
= newReadIndex
;
222 eaReqsComplete
+= QMgrCheckQueue(N8_EA
, nspIdx
, cmdsComplete
);
226 /* Reload the AMBA timer only if there were */
227 /* outstanding EA requests */
228 if ((eaReqsComplete
) || QMgrCount(N8_EA
))
230 ambaTimerActive
= TRUE
;
231 localNSPinstance_p
= &NSPDeviceTable_g
[N8_AMBA_TIMER_CHIP
];
232 nspRegPtr
= (NSP2000REGS_t
*)localNSPinstance_p
->NSPregs_p
;
233 nspRegPtr
->amba_pci_control
= N8_RELOAD_AMBA_MASK
;
238 WakeUp(&requestBlock
);
244 /*****************************************************************************
245 * N8_MainInterruptHandler
246 *****************************************************************************/
247 /** @ingroup NSP2000Driver
248 * @brief Main NSP2000 interrupt handler.
250 * This routine performs the main interrupt handling of the NSP2000.
252 * @param NSPinstance_p RO: Pointer to the information structure for an
253 * NSP2000 hardware instance, containing a
254 * pointer to its control register set.
255 * @param debug RO: Specifies whether debug messages are enabled.
261 * See return section for error information.
264 * We are assuming that AMBA interrupts are used the same way in
265 * each user process that might use them.
267 *****************************************************************************/
269 #define DEF_NSP_IRQ_ACTIVE (AMBAIRQ_PKP | AMBAIRQ_CCH | AMBAIRQ_RNG | \
270 AMBAIRQ_Bridge | AMBAIRQ_Timer)
272 void n8_MainInterruptHandler(NspInstance_t
*NSPinstance_p
)
274 NSP2000REGS_t
*nsp
= (NSP2000REGS_t
*)NSPinstance_p
->NSPregs_p
;
275 uint32_t reg_amba
= nsp
->amba_pci_status
;
281 /* CHECK FOR ACTIVE NSP2000 INTERRUPT */
282 if (reg_amba
& DEF_NSP_IRQ_ACTIVE
)
285 /* Count the receipt of interrupt */
290 /* If this interrupt is from the Bridge Timer, reload it */
291 if (reg_amba
& AMBAIRQ_Timer
)
293 /* Clear the AMBA timer interrupt */
294 nsp
->amba_pci_status
= reg_amba
;
299 ambaTimerActive
= FALSE
;
301 tasklet_schedule(&cch_tasklet
);
302 /* Ensure PCI write completes by reading register */
303 /* before exiting the ISR. */
304 temp
= nsp
->amba_pci_status
;
306 cch_do_tasklet(n8_IRQs_g
);
310 /* IF APPROPRIATE, RELEASE ANYONE BLOCKED ON AMBA INTERRUPTS */
312 /* Note that usage of a single AMBAbitmask doesn't allow for */
313 /* different processes to wait on different masks. However, */
314 /* we only use the AMBA timer, and all processes that wait on */
315 /* AMBA interrupts are just waiting on the timer. */
316 if (NSPinstance_p
->AMBAbitmask
& reg_amba
)
318 /* RELEASE BLOCKED CALL */
319 /* We are using the timer of the AMBA to generate a */
320 /* periodic interrupt. */
321 WakeUp( &NSPinstance_p
->AMBAblock
);
324 /* HANDLE ANY RNG/PKE/EA INTERRUPTS */
325 if (reg_amba
& AMBAIRQ_PKP
)
330 N8_PKHInterruptHandler(NSPinstance_p
, reg_amba
);
332 if (reg_amba
& AMBAIRQ_CCH
)
337 N8_CCHInterruptHandler(NSPinstance_p
, reg_amba
);
339 if (reg_amba
& AMBAIRQ_RNG
)
341 N8_RNHInterruptHandler(NSPinstance_p
);
352 /*****************************************************************************
353 * N8_PKHInterruptHandler
354 *****************************************************************************/
355 /** @ingroup NSP2000Driver
356 * @brief PKH interrupt handler.
358 * This routine is called by the main interrupt handler to handle PKH
359 * interrupts. It first samples the PKH control/status register for future
360 * reference. It then clears all active bits, to handle all active interrupts.
361 * If debug messages are enabled, it also translates the meaning of each
364 * Bits 0-17 indicate PKH interrupts. An active bit is cleared by writing 1
367 * @param NSPinstance_p RO: Pointer to the information structure for an
368 * NSP2000 hardware instance, containing a
369 * pointer to its control register set.
370 * @param reg_amba RO: Value reported in the AMBA Bridge Status Register
373 * PKHIRQ_* RO: #define - Constants that identify each bit of the <BR>
374 * PKH Control/Status register.
380 * See return section for error information.
381 *****************************************************************************/
383 void N8_PKHInterruptHandler(NspInstance_t
*NSPinstance_p
,
387 unsigned long reg
, newreg
;
389 uint16_t cmdsComplete
;
390 int reqsComplete
= 0;
392 nsp
= (NSP2000REGS_t
*)NSPinstance_p
->NSPregs_p
;
394 /* Check for an error */
395 if (reg_amba
& AMBAPKH_Error
)
397 /* An error has been detected, read and save PKH status register */
398 reg
= (unsigned long)nsp
->pkh_control_status
;
399 NSPinstance_p
->PKHirqstatus
= reg
;
401 if (reg
& PK_Status_Any_Error_Mask
)
403 /* CLEAR PKH ENABLE TO ALLOW PKE TO STOP */
404 nsp
->pkh_control_status
= 0;
405 while (nsp
->pkh_control_status
& PK_Status_PKH_Busy
)
407 /* WAITING FOR PKE_BUSY TO CLEAR */
410 /* CLEAR ALL SIGNALLING IRQS AND DISABLE PKH */
411 newreg
= reg
& PK_Enable_All_Enable_Mask
;
413 /* If it is a problem with the command, call the QMgr to noop command blocks */
414 if (reg
& PK_Status_Cmd_Error_Mask
)
416 NSPinstance_p
->PKHcmderrors
++;
418 /* Read & store the current read pointer. */
419 readIndx
= nsp
->pkh_q_ptr
>>16;
421 /* Check for completed PK command blocks */
422 if (readIndx
!= NSPinstance_p
->PKreadIndex
)
424 cmdsComplete
= (readIndx
- NSPinstance_p
->PKreadIndex
) &
425 (NSPinstance_p
->PKqueue_size
-1);
426 NSPinstance_p
->PKreadIndex
= readIndx
;
427 /* Process any completed commands */
428 reqsComplete
= QMgrCheckQueue(N8_PKP
, NSPinstance_p
->chip
,
432 /* Process the errored command */
433 QMgrCmdError(N8_PKP
, NSPinstance_p
->chip
, readIndx
, reg
);
436 /* Bus errors require no QMgr action, just update counter */
437 else if (reg
& PK_Status_Bus_Error_Mask
)
439 NSPinstance_p
->PKHbuserrors
++;
442 /* update register & reenable the PKH */
443 nsp
->pkh_control_status
= newreg
| PK_Status_PKH_Enable
;
445 /* IF APPROPRIATE, RELEASE ANYONE BLOCKED ON PKH INTERRUPTS */
446 if (NSPinstance_p
->PKHbitmask
& reg
)
448 /* RELEASE BLOCKED CALL */
449 WakeUp(&(NSPinstance_p
->PKHblock
));
451 /* PREVENT REENTRY OF THE BLOCKING FUNCTIONALITY */
452 NSPinstance_p
->PKHbitmask
= 0;
456 else /* No Errors, this is a command complete interrupt */
458 /* Clear the command complete bit */
459 nsp
->pkh_control_status
= PK_Enable_PKH_Enable
|
460 PK_Enable_Cmd_Complete_Enable
;
462 /* Read & store the current read pointer. */
463 readIndx
= nsp
->pkh_q_ptr
>>16;
465 /* Process the completed PK command blocks */
466 cmdsComplete
= (readIndx
- NSPinstance_p
->PKreadIndex
) &
467 (NSPinstance_p
->PKqueue_size
-1);
468 NSPinstance_p
->PKreadIndex
= readIndx
;
469 reqsComplete
= QMgrCheckQueue(N8_PKP
, NSPinstance_p
->chip
, cmdsComplete
);
474 WakeUp(&requestBlock
);
480 /*****************************************************************************
481 * N8_RNHInterruptHandler
482 *****************************************************************************/
483 /** @ingroup NSP2000Driver
484 * @brief RNH interrupt handler.
486 * This routine is called by the main interrupt handler to handle RNH
487 * interrupts. It first samples the RNH control/status register for future
488 * reference. It then clears all active bits, to handle all active interrupts.
489 * If debug messages are enabled, it also translates the meaning of each
492 * Bits 20-23 indicate RNH interrupts. An active bit is cleared by writing 1
495 * @param NSPinstance_p RO: Pointer to the information structure for an
496 * NSP2000 hardware instance, containing a
497 * pointer to its control register set.
500 * RNHIRQ_* RO: #define - Constants that identify each bit of the <BR>
501 * RNH Control/Status register.
507 * See return section for error information.
508 *****************************************************************************/
510 void N8_RNHInterruptHandler(NspInstance_t
*NSPinstance_p
)
513 unsigned long reg
, newreg
;
514 unsigned char reenable
= 1;
516 /* READ AND SAVE RNH STATUS REGISTER */
517 nsp
= (NSP2000REGS_t
*)NSPinstance_p
->NSPregs_p
;
518 reg
= (unsigned long)nsp
->rnh_control_status
;
519 NSPinstance_p
->RNHirqstatus
= reg
;
521 /* CLEAR RNH ENABLE TO ALLOW RNG TO STOP */
522 nsp
->rnh_control_status
= 0;
523 while (nsp
->rnh_control_status
& RNH_Status_Transfer_Busy
)
525 /* WAITING FOR XFER_BUSY TO CLEAR */
528 /* CLEAR ALL SIGNALLING IRQS AND RE-ENABLE RNH */
529 newreg
= reg
& RNH_Status_Any_Condition_Mask
;
531 /* DISABLE RNH IF BIG ERROR */
532 if (reg
& DEF_RNH_BIGERROR_IRQ_BITS
)
534 /* IRQPRINT(("NSP2000: Serious error - RNG execution halted.\n")); */
538 /* Record the bus error */
539 else if (reg
& RNH_Status_Bus_Error
)
541 NSPinstance_p
->RNHbuserrors
++;
544 /* UPDATE REGISTER */
545 nsp
->rnh_control_status
= newreg
;
548 nsp
->rnh_control_status
= RNH_Status_Transfer_Enable
;
551 /* IF APPROPRIATE, RELEASE ANYONE BLOCKED ON RNH INTERRUPTS */
552 if (NSPinstance_p
->RNHbitmask
& reg
)
554 /* RELEASE BLOCKED CALL */
555 WakeUp(&(NSPinstance_p
->RNHblock
));
557 /* PREVENT REENTRY OF THE BLOCKING FUNCTIONALITY */
558 NSPinstance_p
->RNHbitmask
= 0;
565 /*****************************************************************************
566 * N8_CCHInterruptHandler
567 *****************************************************************************/
568 /** @ingroup NSP2000Driver
569 * @brief CCH interrupt handler.
571 * This routine is called by the main interrupt handler to handle CCH
572 * interrupts. It first samples the CCH control/status register for future
573 * reference. It then clears all active bits, to handle all active interrupts.
574 * If debug messages are enabled, it also translates the meaning of each
577 * Bits 0-15 indicate CCH interrupts. An active bit is cleared by writing 1
580 * @param NSPinstance_p RO: Pointer to the information structure for an
581 * NSP2000 hardware instance, containing a
582 * pointer to its control register set.
583 * @param reg_amba RO: Value reported in the AMBA Bridge Status Register
586 * CCHIRQ_* RO: #define - Constants that identify each bit of the <BR>
587 * CCH Control/Status register.
593 * See return section for error information.
594 *****************************************************************************/
596 void N8_CCHInterruptHandler(NspInstance_t
*NSPinstance_p
,
602 uint16_t cmdsComplete
;
604 nsp
= (NSP2000REGS_t
*)NSPinstance_p
->NSPregs_p
;
606 /* Check for an error */
607 if (reg_amba
& AMBACCH_Error
)
609 /* An error has been detected, read and save CCH status register */
610 reg
= (unsigned long)nsp
->cch_control_status
;
611 NSPinstance_p
->CCHirqstatus
= reg
;
613 if (reg
& EA_Status_Any_Error_Mask
)
615 /* CLEAR CCH ENABLE TO ALLOW CC TO STOP */
616 nsp
->cch_control_status
= 0;
617 while (nsp
->cch_control_status
& EA_Status_Module_Busy
)
619 /* WAITING FOR CCH_BUSY TO CLEAR */
622 /* Clear all outstanding IRQS */
623 nsp
->cch_control_status
= reg
& EA_Status_Any_Condition_Mask
;
625 /* If it is a problem with the command, call the QMgr to noop command blocks */
626 if (reg
& EA_Status_Cmd_Error_Mask
)
628 NSPinstance_p
->CCHcmderrors
++;
629 /* Read & store the current read pointer. */
630 readIndx
= nsp
->cch_q_ptr
>> 16;
632 /* Check for completed EA command blocks */
633 if (readIndx
!= NSPinstance_p
->EAreadIndex
)
635 cmdsComplete
= (readIndx
- NSPinstance_p
->EAreadIndex
) &
636 (NSPinstance_p
->EAqueue_size
-1);
637 NSPinstance_p
->EAreadIndex
= readIndx
;
638 /* Process any completed commands */
639 QMgrCheckQueue(N8_EA
, NSPinstance_p
->chip
, cmdsComplete
);
642 /* Process the errored command */
643 QMgrCmdError(N8_EA
, NSPinstance_p
->chip
, readIndx
, reg
);
646 /* Bus errors require no QMgr action, just update counter */
647 else if (reg
& EA_Status_Bus_Error_Mask
)
649 NSPinstance_p
->CCHbuserrors
++;
652 /* Reenable the CCH */
653 nsp
->cch_control_status
= EA_Enable_Module_Enable
;
655 /* IF APPROPRIATE, RELEASE ANYONE BLOCKED ON CCH INTERRUPTS */
656 if (NSPinstance_p
->CCHbitmask
& reg
)
658 /* RELEASE BLOCKED CALL */
659 WakeUp(&(NSPinstance_p
->CCHblock
));
661 /* PREVENT REENTRY OF THE BLOCKING FUNCTIONALITY */
662 NSPinstance_p
->CCHbitmask
= 0;
666 else /* No Errors, this is a command complete interrupt */
668 /* Clear the command complete bit */
669 nsp
->cch_control_status
= EA_Enable_Module_Enable
|
670 EA_Enable_Cmd_Complete_Enable
;
672 /* Read & store the current read pointer. */
673 readIndx
= nsp
->cch_q_ptr
>> 16;
675 /* Process the completed EA command blocks */
676 cmdsComplete
= (readIndx
- NSPinstance_p
->EAreadIndex
) &
677 (NSPinstance_p
->EAqueue_size
-1);
678 NSPinstance_p
->EAreadIndex
= readIndx
;
679 QMgrCheckQueue(N8_EA
, NSPinstance_p
->chip
, cmdsComplete
);
687 /*****************************************************************************
689 *****************************************************************************/
690 /** @ingroup NSP2000Driver
691 * @brief Interrupt notification routine.
693 * This routine allows a process to block for interrupt notification for the
694 * PKE, EA, RNG, or AMBA. This routine initializes a wait queue and blocks on
695 * it with a timeout value. If the specified execution core signals an IRQ that
696 * matches one of the set bits in the bitmask, the IRQ handler will release
697 * this blocked process for completion. Otherwise, if no satisfactory IRQ is
698 * received, this routine will time out and return with appropriate error code.
700 * @param NSPinstance_p RO: Pointer to the information structure for an
701 * NSP2000 hardware instance, containing a
702 * pointer to its control register set.
703 * @param bitmask RO: Bitmask to filter received interrupts.
704 * @param coretype RO: Specifies which execution core to monitor.
705 * @param timeout RO: Timeout value for blocking, in seconds.
706 * @param debug RO: Specifies whether debug messages are enabled.
707 * @param interruptable RO: Specifies whether the wait should be interruptable
710 * N8_DAPI_* RO: #define - Constants to specify an execution core.
713 * -EINVAL Invalid core specified.
714 * 0 Timeout - interrupt not received.
715 * 1 Success - interrupt received.
718 * See return section for error information.
719 *****************************************************************************/
721 int waitOnInterrupt ( N8_Unit_t chip
,
722 unsigned char coretype
,
723 unsigned long bitmask
,
724 unsigned long timeout
,
728 unsigned char debug
= 0; /* was passed from DEBUG_IRQ in nsp_ioctl.c */
729 NspInstance_t
*NSPinstance_p
= &NSPDeviceTable_g
[chip
];
731 if (interruptable
== FALSE
)
733 if (coretype
== N8_DAPI_AMBA
)
735 NSPinstance_p
->AMBAbitmask
= bitmask
;
743 if (coretype
== N8_DAPI_PKE
)
745 NSPinstance_p
->PKHbitmask
= bitmask
;
746 rc
= N8_BlockWithTimeout(&(NSPinstance_p
->PKHblock
),
749 else if (coretype
== N8_DAPI_RNG
)
751 NSPinstance_p
->RNHbitmask
= bitmask
;
752 rc
= N8_BlockWithTimeout(&(NSPinstance_p
->RNHblock
),
755 else if (coretype
== N8_DAPI_EA
)
757 NSPinstance_p
->CCHbitmask
= bitmask
;
758 rc
= N8_BlockWithTimeout(&(NSPinstance_p
->CCHblock
),
761 else if (coretype
== N8_DAPI_AMBA
)
763 NSPinstance_p
->AMBAbitmask
= bitmask
;
765 /* We are using the timer of the AMBA to generate a */
766 /* periodic interrupt. */
767 rc
= N8_BlockWithTimeout(
768 &(NSPinstance_p
->AMBAblock
),
772 /* Note that the AMBAbitmask will not be cleared. */
773 /* There is no hard (other than some amount of overhead) */
774 /* of doing extra wake-ups. If we do clear the bitmask */
775 /* then it would need to be on a per process basis, */
776 /* because otherwise, one process could starting to do a */
777 /* block, while the other is doing a clear. Then the */
778 /* wake up will never occur, as the bitmask is 0. */
779 /* NSPinstance_p->AMBAbitmask = 0; */
781 /* The advance to the next wait block occurs in the isr. */
794 /*****************************************************************************
796 *****************************************************************************/
797 /** @ingroup NSP2000Driver
798 * @brief Interrupt notification routine.
800 * This routine allows a process to block for interrupt notification for the
801 * PKE, EA, RNG, or AMBA. This routine initializes a wait queue and blocks on
802 * it with a timeout value. If the specified execution core signals an IRQ that
803 * matches one of the set bits in the bitmask, the IRQ handler will release
804 * this blocked process for completion. Otherwise, if no satisfactory IRQ is
805 * received, this routine will time out and return with appropriate error code.
807 * @param NSPinstance_p RO: Pointer to the information structure for an
808 * NSP2000 hardware instance, containing a
809 * pointer to its control register set.
810 * @param bitmask RO: Bitmask to filter received interrupts.
811 * @param coretype RO: Specifies which execution core to monitor.
812 * @param timeout RO: Timeout value for blocking, in seconds.
813 * @param debug RO: Specifies whether debug messages are enabled.
816 * N8_DAPI_* RO: #define - Constants to specify an execution core.
819 * -EINVAL Invalid core specified.
820 * 0 Timeout - interrupt not received.
821 * 1 Success - interrupt received.
824 * See return section for error information.
825 *****************************************************************************/
827 N8_Status_t
N8_WaitOnInterrupt ( N8_Unit_t chip
,
828 unsigned char coretype
,
829 unsigned long bitmask
,
830 unsigned long timeout
)
832 return waitOnInterrupt(chip
, coretype
, bitmask
, timeout
, FALSE
);
836 N8_Status_t
N8_WaitOnRequest ( int timeout
)
839 if (N8_BlockWithTimeout(&requestBlock
, timeout
, 0))
841 return (N8_STATUS_OK
);
849 /*****************************************************************************
851 *****************************************************************************/
852 /** @ingroup NSP2000Driver
853 * @brief This function reloads the AMBA timer.
860 *****************************************************************************/
861 void reload_AMBA_timer(void)
863 NspInstance_t
*NSPinstance_p
;
864 NSP2000REGS_t
*nspRegPtr
;
866 if (ambaTimerActive
== FALSE
)
868 NSPinstance_p
= &NSPDeviceTable_g
[N8_AMBA_TIMER_CHIP
];
869 nspRegPtr
= (NSP2000REGS_t
*)NSPinstance_p
->NSPregs_p
;
870 ambaTimerActive
= TRUE
;
871 nspRegPtr
->amba_pci_control
= N8_RELOAD_AMBA_MASK
;
876 /*****************************************************************************
878 *****************************************************************************/
879 /** @ingroup NSP2000Driver
880 * @brief Displays the IRQ statistics
882 * This routine displays the NSP2000's IRQ statistics to the
883 * kernel log. This routine is intended for debugging purposes.
889 * See return section for error information.
890 *****************************************************************************/
891 void n8_DisplayIRQ(void)
894 NspInstance_t
*NSPinstance_p
;
896 N8_PRINT(KERN_CRIT
"\n");
897 N8_PRINT(KERN_CRIT
"NSP2000: Displaying IRQ statistics:\n\n");
899 N8_PRINT(KERN_CRIT
" AMBA IRQ's = %d\n", n8_AMBA_IRQs_g
);
900 N8_PRINT(KERN_CRIT
" CCH IRQ's = %d\n", n8_CCH_IRQs_g
);
901 N8_PRINT(KERN_CRIT
" PKH IRQ's = %d\n", n8_PKH_IRQs_g
);
902 N8_PRINT(KERN_CRIT
" Total IRQ's = %d\n", n8_IRQs_g
);
904 for (nspIdx
= 0; nspIdx
< NSPcount_g
; nspIdx
++)
906 NSPinstance_p
= &NSPDeviceTable_g
[nspIdx
];
908 N8_PRINT(KERN_CRIT
"\n");
909 N8_PRINT(KERN_CRIT
"NSP2000: Displaying IRQ statistics for chip %d:\n",
910 NSPinstance_p
->chip
);
911 N8_PRINT(KERN_CRIT
" CCH Bus errors = %d\n", NSPinstance_p
->CCHbuserrors
);
912 N8_PRINT(KERN_CRIT
" PKH Bus errors = %d\n", NSPinstance_p
->PKHbuserrors
);
913 N8_PRINT(KERN_CRIT
" CCH Cmd errors = %d\n", NSPinstance_p
->CCHcmderrors
);
914 N8_PRINT(KERN_CRIT
" PKH Cmd errors = %d\n", NSPinstance_p
->PKHcmderrors
);