diff options
Diffstat (limited to 'sys/dev/hfa/fore_intr.c')
-rw-r--r-- | sys/dev/hfa/fore_intr.c | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/sys/dev/hfa/fore_intr.c b/sys/dev/hfa/fore_intr.c new file mode 100644 index 000000000000..f295b6267e39 --- /dev/null +++ b/sys/dev/hfa/fore_intr.c @@ -0,0 +1,268 @@ +/* + * + * =================================== + * HARP | Host ATM Research Platform + * =================================== + * + * + * This Host ATM Research Platform ("HARP") file (the "Software") is + * made available by Network Computing Services, Inc. ("NetworkCS") + * "AS IS". NetworkCS does not provide maintenance, improvements or + * support of any kind. + * + * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, + * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE + * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE. + * In no event shall NetworkCS be responsible for any damages, including + * but not limited to consequential damages, arising from or relating to + * any use of the Software or related support. + * + * Copyright 1994-1998 Network Computing Services, Inc. + * + * Copies of this Software may be made, however, the above copyright + * notice must be reproduced on all copies. + * + * @(#) $Id: fore_intr.c,v 1.7 1997/05/06 22:09:48 mks Exp $ + * + */ + +/* + * FORE Systems 200-Series Adapter Support + * --------------------------------------- + * + * Interrupt processing + * + */ + +#ifndef lint +static char *RCSid = "@(#) $Id: fore_intr.c,v 1.7 1997/05/06 22:09:48 mks Exp $"; +#endif + +#include <dev/hfa/fore_include.h> + +#if defined(sun) +/* + * Polling interrupt routine + * + * Polling interrupts are handled by calling all interrupt service + * routines for a given level until someone claims to have "handled" the + * interrupt. + * + * Called at interrupt level. + * + * Arguments: + * none + * + * Returns: + * 1 an interrupt has been serviced + * 0 no interrupts serviced + * + */ +int +fore_poll() +{ + int serviced = 0; + int unit; + + /* + * See if any of our devices are interrupting + */ + for ( unit = 0; unit < fore_nunits; unit++ ) + { + Fore_unit *fup = fore_units[unit]; + + if (fup == NULL) + continue; + + serviced += fore_intr((void *)fup); + } + + /* + * Indicate if we handled an interrupt + */ + return (serviced ? 1 : 0); +} +#endif /* defined(sun) */ + + +/* + * Device interrupt routine + * + * Called at interrupt level. + * + * Arguments: + * arg pointer to device unit structure + * + * Returns: + * 1 device interrupt was serviced + * 0 no interrupts serviced + * + */ +#if (defined(BSD) && (BSD <= 199306)) +int +#else +void +#endif +fore_intr(arg) + void *arg; +{ + Fore_unit *fup = arg; + Aali *aap; +#if (defined(BSD) && (BSD <= 199306)) + int serviced = 0; +#endif + + /* + * Try to prevent stuff happening after we've paniced + */ + if (panicstr) { + goto done; + } + + /* + * Get to the microcode shared memory interface + */ + if ((aap = fup->fu_aali) == NULL) + goto done; + + /* + * Has this card issued an interrupt?? + */ +#ifdef FORE_PCI + if (*fup->fu_psr) { +#else + if (aap->aali_intr_sent) { +#endif + + /* + * Indicate that we've serviced an interrupt. + */ +#if (defined(BSD) && (BSD <= 199306)) + serviced = 1; +#endif + + /* + * Clear the device interrupt + */ + switch (fup->fu_config.ac_device) { + +#ifdef FORE_SBUS + case DEV_FORE_SBA200E: + SBA200E_HCR_SET(*fup->fu_ctlreg, SBA200E_CLR_SBUS_INTR); + break; + + case DEV_FORE_SBA200: + *fup->fu_ctlreg = SBA200_CLR_SBUS_INTR; + break; +#endif +#ifdef FORE_PCI + case DEV_FORE_PCA200E: + PCA200E_HCR_SET(*fup->fu_ctlreg, PCA200E_CLR_HBUS_INT); + break; +#endif + + } + aap->aali_intr_sent = CP_WRITE(0); + + /* + * Reset the watchdog timer + */ + fup->fu_timer = FORE_WATCHDOG; + + /* + * Device initialization handled separately + */ + if ((fup->fu_flags & CUF_INITED) == 0) { + + /* + * We're just initializing device now, so see if + * the initialization command has completed + */ + if (CP_READ(aap->aali_init.init_status) & + QSTAT_COMPLETED) + fore_initialize_complete(fup); + + /* + * If we're still not inited, none of the host + * queues are setup yet + */ + if ((fup->fu_flags & CUF_INITED) == 0) + goto done; + } + + /* + * Drain the queues of completed work + */ + fore_cmd_drain(fup); + fore_recv_drain(fup); + fore_xmit_drain(fup); + + /* + * Supply more buffers to the CP + */ + fore_buf_supply(fup); + } + +done: +#if (defined(BSD) && (BSD <= 199306)) + return(serviced); +#else + return; +#endif +} + + +/* + * Watchdog timeout routine + * + * Called when we haven't heard from the card in a while. Just in case + * we missed an interrupt, we'll drain the queues and try to resupply the + * CP with more receive buffers. If the CP is partially wedged, hopefully + * this will be enough to get it going again. + * + * Called with interrupts locked out. + * + * Arguments: + * fup pointer to device unit structure + * + * Returns: + * none + * + */ +void +fore_watchdog(fup) + Fore_unit *fup; +{ + /* + * Try to prevent stuff happening after we've paniced + */ + if (panicstr) { + return; + } + + /* + * Reset the watchdog timer + */ + fup->fu_timer = FORE_WATCHDOG; + + /* + * If the device is initialized, nudge it (wink, wink) + */ + if (fup->fu_flags & CUF_INITED) { + + /* + * Drain the queues of completed work + */ + fore_cmd_drain(fup); + fore_recv_drain(fup); + fore_xmit_drain(fup); + + /* + * Supply more buffers to the CP + */ + fore_buf_supply(fup); + } + + return; +} |