/* * * =================================== * 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. * * @(#) $FreeBSD: src/sys/dev/hfa/fore_intr.c,v 1.3 1999/08/28 00:41:50 peter Exp $ * @(#) $DragonFly: src/sys/dev/atm/hfa/fore_intr.c,v 1.4 2003/08/07 21:16:49 dillon Exp $ */ /* * FORE Systems 200-Series Adapter Support * --------------------------------------- * * Interrupt processing * */ #include "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 default: panic("fore_intr: unknown device type"); } 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; }