FreeBSD/sys/dev/wl/if_wl.c
/*
 * wlintr:
 *
 *	This function is the interrupt handler for the WaveLAN
 *	board.  This routine will be called whenever either a packet
 *	is received, or a packet has successfully been transferred and
 *	the unit is ready to transmit another packet.
 *
 * input	: board number that interrupted
 * output	: either a packet is received, or a packet is transferred
 *
 */
This function is the interrupt handler for the WaveLAN
board.  This routine will be called whenever either a packet
is received, or a packet has successfully been transferred and
the unit is ready to transmit another packet.

input        : board number that interrupted
output       : either a packet is received, or a packet is transferred
This function is the interrupt handler for the WaveLAN board . This routine will be called whenever either a packet is received or a packet has successfully been transferred and the unit is ready to transmit another packet . input : board number that interrupted output : either a packet is received or a packet is transferred
static void
wlintr(void *arg)
{
    struct wl_softc	*sc = (struct wl_softc *)arg;
    int			ac_status;
    u_short		int_type, int_type1;
    WL_LOCK(sc);
#ifdef WLDEBUG
    if (sc->ifp->if_flags & IFF_DEBUG)
	if_printf(sc->ifp, "wlintr() called\n");
#endif
    if ((int_type = WL_READ_2(sc, HASR)) & HASR_MMC_INTR) {
	(void) wlmmcread(sc, MMC_DCE_STATUS); 
    }
    if (!(int_type & HASR_INTR)){	
	WL_UNLOCK(sc);
	return;
    }
    if (gathersnr)
	getsnr(sc);
    for (;;) {
	WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 0);	
	int_type = (WL_READ_2(sc, PIOP0) & SCB_SW_INT);
	if (int_type == 0)			
	    break;
	int_type1 = wlack(sc);		
	if ((int_type & int_type1) != int_type)
	    printf("wlack() int bits disappeared : %04x != int_type %04x\n",
		   int_type1, int_type);
	int_type = int_type1;			
	if (int_type & SCB_SW_FR) {
	    if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1);
	    wlrcv(sc);
	}
	if (int_type & SCB_SW_RNR) {
	    if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
#ifdef	WLDEBUG
	    if (sc->ifp->if_flags & IFF_DEBUG)
		if_printf(sc->ifp, "intr(): receiver overrun! begin_fd = %x\n",
		       sc->begin_fd);
#endif
	    wlrustrt(sc);
	}
	if (int_type & SCB_SW_CNA) {
	}
	if (int_type & SCB_SW_CX) {
	    WL_WRITE_2(sc, PIOR1, OFFSET_CU);	
	    ac_status = WL_READ_2(sc, PIOP1);
	    if (xmt_watch) {			
		if (sc->tbusy == 0) {
		    if_printf(sc->ifp, "xmt intr but not busy, CU %04x\n",
			   ac_status);
		}
		if (ac_status == 0) {
		    if_printf(sc->ifp, "xmt intr but ac_status == 0\n");
		}
		if (ac_status & AC_SW_A) {
		    if_printf(sc->ifp, "xmt aborted\n");
		}
#ifdef	notdef
		if (ac_status & TC_CARRIER) {
		    if_printf(sc->ifp, "no carrier\n");
		}
#endif	
		if (ac_status & TC_CLS) {
		    if_printf(sc->ifp, "no CTS\n");
		}
		if (ac_status & TC_DMA) {
		    if_printf(sc->ifp, "DMA underrun\n");
		}
		if (ac_status & TC_DEFER) {
		    if_printf(sc->ifp, "xmt deferred\n");
		}
		if (ac_status & TC_SQE) {
		    if_printf(sc->ifp, "heart beat\n");
		}
		if (ac_status & TC_COLLISION) {
		    if_printf(sc->ifp, "too many collisions\n");
		}
	    }
	    if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) {
		if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) {
		    if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
		}
		if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, (ac_status & 0xf));
		if ((ac_status & 0x20) == 0x20) {
		    if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, 0x10);
		}
	    }
	    sc->tbusy = 0;
	    callout_stop(&sc->watchdog_timer);
	    sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
	    wlstart_locked(sc->ifp);
	}
    }
    WL_UNLOCK(sc);
    return;
}
static void wlintr ( void * arg ) { struct wl_softc * sc = ( struct wl_softc * ) arg ; int ac_status ; u_short int_type , int_type1 ; WL_LOCK ( sc ) ; #ifdef WLDEBUG if ( sc -> ifp -> if_flags & IFF_DEBUG ) if_printf ( sc -> ifp , " \n " ) ; #endif if ( ( int_type = WL_READ_2 ( sc , HASR ) ) & HASR_MMC_INTR ) { ( void ) wlmmcread ( sc , MMC_DCE_STATUS ) ; } if ( ! ( int_type & HASR_INTR ) ) { WL_UNLOCK ( sc ) ; return ; } if ( gathersnr ) getsnr ( sc ) ; for ( ; ; ) { WL_WRITE_2 ( sc , PIOR0 , OFFSET_SCB + 0 ) ; int_type = ( WL_READ_2 ( sc , PIOP0 ) & SCB_SW_INT ) ; if ( int_type == 0 ) break ; int_type1 = wlack ( sc ) ; if ( ( int_type & int_type1 ) != int_type ) printf ( " \n " , int_type1 , int_type ) ; int_type = int_type1 ; if ( int_type & SCB_SW_FR ) { if_inc_counter ( sc -> ifp , IFCOUNTER_IPACKETS , 1 ) ; wlrcv ( sc ) ; } if ( int_type & SCB_SW_RNR ) { if_inc_counter ( sc -> ifp , IFCOUNTER_IERRORS , 1 ) ; #ifdef WLDEBUG if ( sc -> ifp -> if_flags & IFF_DEBUG ) if_printf ( sc -> ifp , " \n " , sc -> begin_fd ) ; #endif wlrustrt ( sc ) ; } if ( int_type & SCB_SW_CNA ) { } if ( int_type & SCB_SW_CX ) { WL_WRITE_2 ( sc , PIOR1 , OFFSET_CU ) ; ac_status = WL_READ_2 ( sc , PIOP1 ) ; if ( xmt_watch ) { if ( sc -> tbusy == 0 ) { if_printf ( sc -> ifp , " \n " , ac_status ) ; } if ( ac_status == 0 ) { if_printf ( sc -> ifp , " \n " ) ; } if ( ac_status & AC_SW_A ) { if_printf ( sc -> ifp , " \n " ) ; } #ifdef notdef if ( ac_status & TC_CARRIER ) { if_printf ( sc -> ifp , " \n " ) ; } #endif if ( ac_status & TC_CLS ) { if_printf ( sc -> ifp , " \n " ) ; } if ( ac_status & TC_DMA ) { if_printf ( sc -> ifp , " \n " ) ; } if ( ac_status & TC_DEFER ) { if_printf ( sc -> ifp , " \n " ) ; } if ( ac_status & TC_SQE ) { if_printf ( sc -> ifp , " \n " ) ; } if ( ac_status & TC_COLLISION ) { if_printf ( sc -> ifp , " \n " ) ; } } if ( ( ! ( ac_status & AC_SW_OK ) ) || ( ac_status & 0xfff ) ) { if ( ac_status & ( TC_COLLISION | TC_CLS | TC_DMA ) ) { if_inc_counter ( sc -> ifp , IFCOUNTER_OERRORS , 1 ) ; } if_inc_counter ( sc -> ifp , IFCOUNTER_COLLISIONS , ( ac_status & 0xf ) ) ; if ( ( ac_status & 0x20 ) == 0x20 ) { if_inc_counter ( sc -> ifp , IFCOUNTER_COLLISIONS , 0x10 ) ; } } sc -> tbusy = 0 ; callout_stop ( & sc -> watchdog_timer ) ; sc -> ifp -> if_drv_flags &= ~ IFF_DRV_OACTIVE ; wlstart_locked ( sc -> ifp ) ; } } WL_UNLOCK ( sc ) ; return ; }
wlintr:
      This function is the interrupt handler for the WaveLAN
      board.
wlintr : This function is the interrupt handler for the WaveLAN board .
/* handle interrupt from the modem management controller */ /* This will clear the interrupt condition */ /* ignored for now */ /* return if no interrupt from 82586 */ /* commented out. jrb.  it happens when reinit occurs
	   printf("wlintr: int_type %x, dump follows\n", int_type);
	   wldump(sc);
	   */ /* get scb status */ /* no interrupts left */ /* acknowledge interrupt(s) */ /* make sure no bits disappeared (others may appear) */ /* go with the new status */ /* 
	 * incoming packet
	 */ /*
	 * receiver not ready
	 */ /*
	 * CU not ready
	 */ /*
	     * At present, we don't care about CNA's.  We
	     * believe they are a side effect of XMT.
	     */ /*
	     * At present, we only request Interrupt for
	     * XMT.
	     */ /* get command status */ /* report some anomalies */ /* notdef */ /* if the transmit actually failed, or returned some status */ /* count collisions */ /* if TC_COLLISION set and collision count zero, 16 collisions */