Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / irq.c
blob5985ce871697a88ed1460e0d34171087a593ad57
1 /*-
2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
3 * All rights reserved.
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>.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
12 * met:
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 /*****************************************************************************/
37 /** @file irq.c
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 /*****************************************************************************
46 * Revision history:
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
86 * ISR.
87 * 05/20/02 brr Revert to a single AMBA wait queue.
88 * 04/30/02 brr Minor revisions to improve performance & incorporate comments
89 * from code review.
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
120 * by the driver.
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
152 #include "helper.h"
153 #include "n8_driver_main.h"
154 #include "n8_driver_api.h"
155 #include "irq.h"
156 #include "nsp2000_regs.h"
157 #include "nsp_ioctl.h"
158 #include "n8_OS_intf.h"
159 #include "QMUtil.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,
166 uint32_t reg_amba );
167 void N8_RNHInterruptHandler ( NspInstance_t *NSPinstance_p );
168 void N8_CCHInterruptHandler ( NspInstance_t *NSPinstance_p,
169 uint32_t reg_amba );
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;
178 /* IRQ statistics */
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);
189 #ifdef __linux
190 DECLARE_TASKLET(cch_tasklet, cch_do_tasklet, 0);
191 #endif
193 void cch_do_tasklet (unsigned long unused)
195 int nspIdx;
196 NSP2000REGS_t *nspRegPtr;
197 NspInstance_t *localNSPinstance_p;
198 int eaReqsComplete = 0;
199 uint32_t cch_read;
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;
236 if (eaReqsComplete)
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.
257 * @return
258 * N/A
260 * @par Errors:
261 * See return section for error information.
263 * @par Assumptions:
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;
276 #ifdef __linux
277 uint32_t temp;
278 #endif
281 /* CHECK FOR ACTIVE NSP2000 INTERRUPT */
282 if (reg_amba & DEF_NSP_IRQ_ACTIVE)
285 /* Count the receipt of interrupt */
286 #ifdef N8_IRQ_COUNT
287 n8_IRQs_g++;
288 #endif
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;
296 #ifdef N8_IRQ_COUNT
297 n8_AMBA_IRQs_g++;
298 #endif
299 ambaTimerActive = FALSE;
300 #ifdef __linux
301 tasklet_schedule(&cch_tasklet);
302 /* Ensure PCI write completes by reading register */
303 /* before exiting the ISR. */
304 temp = nsp->amba_pci_status;
305 #else
306 cch_do_tasklet(n8_IRQs_g);
307 #endif
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)
327 #ifdef N8_IRQ_COUNT
328 n8_PKH_IRQs_g++;
329 #endif
330 N8_PKHInterruptHandler(NSPinstance_p, reg_amba);
332 if (reg_amba & AMBAIRQ_CCH)
334 #ifdef N8_IRQ_COUNT
335 n8_CCH_IRQs_g++;
336 #endif
337 N8_CCHInterruptHandler(NSPinstance_p, reg_amba);
339 if (reg_amba & AMBAIRQ_RNG)
341 N8_RNHInterruptHandler(NSPinstance_p);
347 return;
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
362 * active bit.
364 * Bits 0-17 indicate PKH interrupts. An active bit is cleared by writing 1
365 * to it.
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
372 * @par Externals:
373 * PKHIRQ_* RO: #define - Constants that identify each bit of the <BR>
374 * PKH Control/Status register.
376 * @return
377 * N/A
379 * @par Errors:
380 * See return section for error information.
381 *****************************************************************************/
383 void N8_PKHInterruptHandler(NspInstance_t *NSPinstance_p,
384 uint32_t reg_amba)
386 NSP2000REGS_t *nsp;
387 unsigned long reg, newreg;
388 uint16_t readIndx;
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,
429 cmdsComplete);
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);
472 if (reqsComplete)
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
490 * active bit.
492 * Bits 20-23 indicate RNH interrupts. An active bit is cleared by writing 1
493 * to it.
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.
499 * @par Externals:
500 * RNHIRQ_* RO: #define - Constants that identify each bit of the <BR>
501 * RNH Control/Status register.
503 * @return
504 * N/A
506 * @par Errors:
507 * See return section for error information.
508 *****************************************************************************/
510 void N8_RNHInterruptHandler(NspInstance_t *NSPinstance_p)
512 NSP2000REGS_t *nsp;
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")); */
535 reenable = 0;
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;
546 if (reenable)
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;
560 return;
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
575 * active bit.
577 * Bits 0-15 indicate CCH interrupts. An active bit is cleared by writing 1
578 * to it.
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
585 * @par Externals:
586 * CCHIRQ_* RO: #define - Constants that identify each bit of the <BR>
587 * CCH Control/Status register.
589 * @return
590 * N/A
592 * @par Errors:
593 * See return section for error information.
594 *****************************************************************************/
596 void N8_CCHInterruptHandler(NspInstance_t *NSPinstance_p,
597 uint32_t reg_amba)
599 NSP2000REGS_t *nsp;
600 unsigned long reg;
601 uint16_t readIndx;
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);
682 return;
687 /*****************************************************************************
688 * waitOnInterrupt
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
709 * @par Externals:
710 * N8_DAPI_* RO: #define - Constants to specify an execution core.
712 * @return
713 * -EINVAL Invalid core specified.
714 * 0 Timeout - interrupt not received.
715 * 1 Success - interrupt received.
717 * @par Errors:
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,
725 int interruptable )
727 unsigned char rc;
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;
736 return 1;
738 else
740 return -EINVAL;
743 if (coretype == N8_DAPI_PKE)
745 NSPinstance_p->PKHbitmask = bitmask;
746 rc = N8_BlockWithTimeout(&(NSPinstance_p->PKHblock),
747 timeout, debug);
749 else if (coretype == N8_DAPI_RNG)
751 NSPinstance_p->RNHbitmask = bitmask;
752 rc = N8_BlockWithTimeout(&(NSPinstance_p->RNHblock),
753 timeout, debug);
755 else if (coretype == N8_DAPI_EA)
757 NSPinstance_p->CCHbitmask = bitmask;
758 rc = N8_BlockWithTimeout(&(NSPinstance_p->CCHblock),
759 timeout, debug);
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),
769 timeout,
770 debug);
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. */
784 else
786 return -EINVAL;
789 return rc;
794 /*****************************************************************************
795 * n8_WaitOnInterrupt
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.
815 * @par Externals:
816 * N8_DAPI_* RO: #define - Constants to specify an execution core.
818 * @return
819 * -EINVAL Invalid core specified.
820 * 0 Timeout - interrupt not received.
821 * 1 Success - interrupt received.
823 * @par Errors:
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);
843 return (N8_TIMEOUT);
849 /*****************************************************************************
850 * reload_AMBA_timer
851 *****************************************************************************/
852 /** @ingroup NSP2000Driver
853 * @brief This function reloads the AMBA timer.
855 * @return
856 * N/A
858 * @par Errors:
859 * N/A
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 /*****************************************************************************
877 * n8_DisplayIRQ
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.
885 * @return
886 * N/A
888 * @par Errors:
889 * See return section for error information.
890 *****************************************************************************/
891 void n8_DisplayIRQ(void)
893 int nspIdx;
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);