Ejemplo n.º 1
0
static void 
txp_intr(void *vsc)
{
	struct txp_softc *sc = vsc;
	struct txp_hostvar *hv = sc->sc_hostvar;
	u_int32_t isr;

	/* mask all interrupts */
	WRITE_REG(sc, TXP_IMR, TXP_INT_RESERVED | TXP_INT_SELF |
	    TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
	    TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0 |
	    TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
	    TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |  TXP_INT_LATCH);

	isr = READ_REG(sc, TXP_ISR);
	while (isr) {
		WRITE_REG(sc, TXP_ISR, isr);

		if ((*sc->sc_rxhir.r_roff) != (*sc->sc_rxhir.r_woff))
			txp_rx_reclaim(sc, &sc->sc_rxhir);
		if ((*sc->sc_rxlor.r_roff) != (*sc->sc_rxlor.r_woff))
			txp_rx_reclaim(sc, &sc->sc_rxlor);

		if (hv->hv_rx_buf_write_idx == hv->hv_rx_buf_read_idx)
			txp_rxbuf_reclaim(sc);

		if (sc->sc_txhir.r_cnt && (sc->sc_txhir.r_cons !=
		    TXP_OFFSET2IDX(*(sc->sc_txhir.r_off))))
			txp_tx_reclaim(sc, &sc->sc_txhir);

		if (sc->sc_txlor.r_cnt && (sc->sc_txlor.r_cons !=
		    TXP_OFFSET2IDX(*(sc->sc_txlor.r_off))))
			txp_tx_reclaim(sc, &sc->sc_txlor);

		isr = READ_REG(sc, TXP_ISR);
	}

	/* unmask all interrupts */
	WRITE_REG(sc, TXP_IMR, TXP_INT_A2H_3);

	if_devstart(&sc->sc_arpcom.ac_if);
}
Ejemplo n.º 2
0
static void
ep_if_watchdog(struct ifnet *ifp)
{
    struct ep_softc *sc = ifp->if_softc;

    /*
    if_printf(ifp, "watchdog\n");

    log(LOG_ERR, "%s: watchdog\n", ifp->if_xname);
    ifp->if_oerrors++;
    */

    if (sc->gone) {
	return;
    }

    ifq_clr_oactive(&ifp->if_snd);
    if_devstart(ifp);
    ep_intr(ifp->if_softc);
}
Ejemplo n.º 3
0
static int
wi_pci_resume(device_t dev)
{
	struct wi_softc	*sc = device_get_softc(dev);
	struct ifnet *ifp = sc->sc_ifp;

	wlan_serialize_enter();
	if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
		wlan_serialize_exit();
		return (0);
	}

	if (ifp->if_flags & IFF_UP) {
		ifp->if_init(ifp->if_softc);
		if (ifp->if_flags & IFF_RUNNING)
			if_devstart(ifp);
	}
	wlan_serialize_exit();

	return (0);
}
Ejemplo n.º 4
0
void
sn_intr(void *arg)
{
	int             status, interrupts;
	struct sn_softc *sc = (struct sn_softc *) arg;
	struct ifnet   *ifp = &sc->arpcom.ac_if;

	/*
	 * Chip state registers
	 */
	u_char          mask;
	u_char          packet_no;
	u_short         tx_status;
	u_short         card_stats;

	/*
	 * Clear the watchdog.
	 */
	ifp->if_timer = 0;

	SMC_SELECT_BANK(2);

	/*
	 * Obtain the current interrupt mask and clear the hardware mask
	 * while servicing interrupts.
	 */
	mask = inb(BASE + INTR_MASK_REG_B);
	outb(BASE + INTR_MASK_REG_B, 0x00);

	/*
	 * Get the set of interrupts which occurred and eliminate any which
	 * are masked.
	 */
	interrupts = inb(BASE + INTR_STAT_REG_B);
	status = interrupts & mask;

	/*
	 * Now, process each of the interrupt types.
	 */

	/*
	 * Receive Overrun.
	 */
	if (status & IM_RX_OVRN_INT) {

		/*
		 * Acknowlege Interrupt
		 */
		SMC_SELECT_BANK(2);
		outb(BASE + INTR_ACK_REG_B, IM_RX_OVRN_INT);

		IFNET_STAT_INC(&sc->arpcom.ac_if, ierrors, 1);
	}
	/*
	 * Got a packet.
	 */
	if (status & IM_RCV_INT) {
#if 1
		int             packet_number;

		SMC_SELECT_BANK(2);
		packet_number = inw(BASE + FIFO_PORTS_REG_W);

		if (packet_number & FIFO_REMPTY) {

			/*
			 * we got called , but nothing was on the FIFO
			 */
			kprintf("sn: Receive interrupt with nothing on FIFO\n");

			goto out;
		}
#endif
		snread(ifp);
	}
	/*
	 * An on-card memory allocation came through.
	 */
	if (status & IM_ALLOC_INT) {

		/*
		 * Disable this interrupt.
		 */
		mask &= ~IM_ALLOC_INT;
		ifq_clr_oactive(&sc->arpcom.ac_if.if_snd);
		snresume(&sc->arpcom.ac_if);
	}
	/*
	 * TX Completion.  Handle a transmit error message. This will only be
	 * called when there is an error, because of the AUTO_RELEASE mode.
	 */
	if (status & IM_TX_INT) {

		/*
		 * Acknowlege Interrupt
		 */
		SMC_SELECT_BANK(2);
		outb(BASE + INTR_ACK_REG_B, IM_TX_INT);

		packet_no = inw(BASE + FIFO_PORTS_REG_W);
		packet_no &= FIFO_TX_MASK;

		/*
		 * select this as the packet to read from
		 */
		outb(BASE + PACKET_NUM_REG_B, packet_no);

		/*
		 * Position the pointer to the first word from this packet
		 */
		outw(BASE + POINTER_REG_W, PTR_AUTOINC | PTR_READ | 0x0000);

		/*
		 * Fetch the TX status word.  The value found here will be a
		 * copy of the EPH_STATUS_REG_W at the time the transmit
		 * failed.
		 */
		tx_status = inw(BASE + DATA_REG_W);

		if (tx_status & EPHSR_TX_SUC) {
			device_printf(sc->dev, 
			    "Successful packet caused interrupt\n");
		} else {
			IFNET_STAT_INC(&sc->arpcom.ac_if, oerrors, 1);
		}

		if (tx_status & EPHSR_LATCOL)
			IFNET_STAT_INC(&sc->arpcom.ac_if, collisions, 1);

		/*
		 * Some of these errors will have disabled transmit.
		 * Re-enable transmit now.
		 */
		SMC_SELECT_BANK(0);

#ifdef SW_PAD
		outw(BASE + TXMIT_CONTROL_REG_W, TCR_ENABLE);
#else
		outw(BASE + TXMIT_CONTROL_REG_W, TCR_ENABLE | TCR_PAD_ENABLE);
#endif	/* SW_PAD */

		/*
		 * kill the failed packet. Wait for the MMU to be un-busy.
		 */
		SMC_SELECT_BANK(2);
		while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
			;
		outw(BASE + MMU_CMD_REG_W, MMUCR_FREEPKT);

		/*
		 * Attempt to queue more transmits.
		 */
		ifq_clr_oactive(&sc->arpcom.ac_if.if_snd);
		if_devstart(&sc->arpcom.ac_if);
	}
	/*
	 * Transmit underrun.  We use this opportunity to update transmit
	 * statistics from the card.
	 */
	if (status & IM_TX_EMPTY_INT) {

		/*
		 * Acknowlege Interrupt
		 */
		SMC_SELECT_BANK(2);
		outb(BASE + INTR_ACK_REG_B, IM_TX_EMPTY_INT);

		/*
		 * Disable this interrupt.
		 */
		mask &= ~IM_TX_EMPTY_INT;

		SMC_SELECT_BANK(0);
		card_stats = inw(BASE + COUNTER_REG_W);

		/*
		 * Single collisions
		 */
		IFNET_STAT_INC(&sc->arpcom.ac_if, collisions,
		    card_stats & ECR_COLN_MASK);

		/*
		 * Multiple collisions
		 */
		IFNET_STAT_INC(&sc->arpcom.ac_if, collisions,
		    (card_stats & ECR_MCOLN_MASK) >> 4);

		SMC_SELECT_BANK(2);

		/*
		 * Attempt to enqueue some more stuff.
		 */
		ifq_clr_oactive(&sc->arpcom.ac_if.if_snd);
		if_devstart(&sc->arpcom.ac_if);
	}
Ejemplo n.º 5
0
/* Resume a packet transmit operation after a memory allocation
 * has completed.
 *
 * This is basically a hacked up copy of snstart() which handles
 * a completed memory allocation the same way snstart() does.
 * It then passes control to snstart to handle any other queued
 * packets.
 */
static void
snresume(struct ifnet *ifp)
{
	struct sn_softc *sc = ifp->if_softc;
	u_int  len;
	struct mbuf *m;
	struct mbuf    *top;
	int             pad;
	int             mask;
	u_short         length;
	u_short         numPages;
	u_short         pages_wanted;
	u_char          packet_no;

	if (sc->pages_wanted < 0)
		return;

	pages_wanted = sc->pages_wanted;
	sc->pages_wanted = -1;

	/*
	 * Sneak a peek at the next packet
	 */
	m = ifq_dequeue(&ifp->if_snd);
	if (m == NULL) {
		kprintf("%s: snresume() with nothing to send\n",
			ifp->if_xname);
		return;
	}

	/*
	 * Compute the frame length and set pad to give an overall even
	 * number of bytes.  Below we assume that the packet length is even.
	 */
	for (len = 0, top = m; m; m = m->m_next)
		len += m->m_len;

	pad = (len & 1);

	/*
	 * We drop packets that are too large. Perhaps we should truncate
	 * them instead?
	 */
	if (len + pad > ETHER_MAX_LEN - ETHER_CRC_LEN) {
		kprintf("%s: large packet discarded (B)\n", ifp->if_xname);
		IFNET_STAT_INC(ifp, oerrors, 1);
		m_freem(top);
		return;
	}
#ifdef SW_PAD

	/*
	 * If HW padding is not turned on, then pad to ETHER_MIN_LEN.
	 */
	if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
		pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;

#endif	/* SW_PAD */

	length = pad + len;


	/*
	 * The MMU wants the number of pages to be the number of 256 byte
	 * 'pages', minus 1 (A packet can't ever have 0 pages. We also
	 * include space for the status word, byte count and control bytes in
	 * the allocation request.
	 */
	numPages = (length + 6) >> 8;


	SMC_SELECT_BANK(2);

	/*
	 * The memory allocation completed.  Check the results. If it failed,
	 * we simply set a watchdog timer and hope for the best.
	 */
	packet_no = inb(BASE + ALLOC_RESULT_REG_B);
	if (packet_no & ARR_FAILED) {
		kprintf("%s: Memory allocation failed.  Weird.\n", ifp->if_xname);
		ifp->if_timer = 1;
		ifq_prepend(&ifp->if_snd, top);
		goto try_start;
	}
	/*
	 * We have a packet number, so tell the card to use it.
	 */
	outb(BASE + PACKET_NUM_REG_B, packet_no);

	/*
	 * Now, numPages should match the pages_wanted recorded when the
	 * memory allocation was initiated.
	 */
	if (pages_wanted != numPages) {
		kprintf("%s: memory allocation wrong size.  Weird.\n", ifp->if_xname);
		/*
		 * If the allocation was the wrong size we simply release the
		 * memory once it is granted. Wait for the MMU to be un-busy.
		 */
		while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
			;
		outw(BASE + MMU_CMD_REG_W, MMUCR_FREEPKT);

		ifq_prepend(&ifp->if_snd, top);
		return;
	}
	/*
	 * Point to the beginning of the packet
	 */
	outw(BASE + POINTER_REG_W, PTR_AUTOINC | 0x0000);

	/*
	 * Send the packet length (+6 for status, length and control byte)
	 * and the status word (set to zeros)
	 */
	outw(BASE + DATA_REG_W, 0);
	outb(BASE + DATA_REG_B, (length + 6) & 0xFF);
	outb(BASE + DATA_REG_B, (length + 6) >> 8);

	/*
	 * Push out the data to the card.
	 */
	for (m = top; m != NULL; m = m->m_next) {

		/*
		 * Push out words.
		 */
		outsw(BASE + DATA_REG_W, mtod(m, caddr_t), m->m_len / 2);

		/*
		 * Push out remaining byte.
		 */
		if (m->m_len & 1)
			outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1));
	}

	/*
	 * Push out padding.
	 */
	while (pad > 1) {
		outw(BASE + DATA_REG_W, 0);
		pad -= 2;
	}
	if (pad)
		outb(BASE + DATA_REG_B, 0);

	/*
	 * Push out control byte and unused packet byte The control byte is 0
	 * meaning the packet is even lengthed and no special CRC handling is
	 * desired.
	 */
	outw(BASE + DATA_REG_W, 0);

	/*
	 * Enable the interrupts and let the chipset deal with it Also set a
	 * watchdog in case we miss the interrupt.
	 */
	mask = inb(BASE + INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT);
	outb(BASE + INTR_MASK_REG_B, mask);
	sc->intr_mask = mask;
	outw(BASE + MMU_CMD_REG_W, MMUCR_ENQUEUE);

	BPF_MTAP(ifp, top);

	IFNET_STAT_INC(ifp, opackets, 1);
	m_freem(top);

try_start:

	/*
	 * Now pass control to snstart() to queue any additional packets
	 */
	ifq_clr_oactive(&ifp->if_snd);
	if_devstart(ifp);

	/*
	 * We've sent something, so we're active.  Set a watchdog in case the
	 * TX_EMPTY interrupt is lost.
	 */
	ifq_set_oactive(&ifp->if_snd);
	ifp->if_timer = 1;
}
Ejemplo n.º 6
0
/*
 * Reset and initialize the chip
 */
void
sninit(void *xsc)
{
	struct sn_softc *sc = xsc;
	struct ifnet *ifp = &sc->arpcom.ac_if;
	int             flags;
	int             mask;

	/*
	 * This resets the registers mostly to defaults, but doesn't affect
	 * EEPROM.  After the reset cycle, we pause briefly for the chip to
	 * be happy.
	 */
	SMC_SELECT_BANK(0);
	outw(BASE + RECV_CONTROL_REG_W, RCR_SOFTRESET);
	SMC_DELAY();
	outw(BASE + RECV_CONTROL_REG_W, 0x0000);
	SMC_DELAY();
	SMC_DELAY();

	outw(BASE + TXMIT_CONTROL_REG_W, 0x0000);

	/*
	 * Set the control register to automatically release succesfully
	 * transmitted packets (making the best use out of our limited
	 * memory) and to enable the EPH interrupt on certain TX errors.
	 */
	SMC_SELECT_BANK(1);
	outw(BASE + CONTROL_REG_W, (CTR_AUTO_RELEASE | CTR_TE_ENABLE |
				    CTR_CR_ENABLE | CTR_LE_ENABLE));

	/* Set squelch level to 240mV (default 480mV) */
	flags = inw(BASE + CONFIG_REG_W);
	flags |= CR_SET_SQLCH;
	outw(BASE + CONFIG_REG_W, flags);

	/*
	 * Reset the MMU and wait for it to be un-busy.
	 */
	SMC_SELECT_BANK(2);
	outw(BASE + MMU_CMD_REG_W, MMUCR_RESET);
	while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
		;

	/*
	 * Disable all interrupts
	 */
	outb(BASE + INTR_MASK_REG_B, 0x00);

	sn_setmcast(sc);

	/*
	 * Set the transmitter control.  We want it enabled.
	 */
	flags = TCR_ENABLE;

#ifndef SW_PAD
	/*
	 * I (GB) have been unlucky getting this to work.
	 */
	flags |= TCR_PAD_ENABLE;
#endif	/* SW_PAD */

	outw(BASE + TXMIT_CONTROL_REG_W, flags);


	/*
	 * Now, enable interrupts
	 */
	SMC_SELECT_BANK(2);

	mask = IM_EPH_INT |
		IM_RX_OVRN_INT |
		IM_RCV_INT |
		IM_TX_INT;

	outb(BASE + INTR_MASK_REG_B, mask);
	sc->intr_mask = mask;
	sc->pages_wanted = -1;


	/*
	 * Mark the interface running but not active.
	 */
	ifp->if_flags |= IFF_RUNNING;
	ifq_clr_oactive(&ifp->if_snd);

	/*
	 * Attempt to push out any waiting packets.
	 */
	if_devstart(ifp);
}
Ejemplo n.º 7
0
void
ep_intr(void *arg)
{
    struct ep_softc *sc = arg;
    struct ifnet *ifp = &sc->arpcom.ac_if;
    int status;

     /*
      * quick fix: Try to detect an interrupt when the card goes away.
      */
    if (sc->gone || inw(BASE + EP_STATUS) == 0xffff) {
	    return;
    }

    outw(BASE + EP_COMMAND, SET_INTR_MASK); /* disable all Ints */

rescan:

    while ((status = inw(BASE + EP_STATUS)) & S_5_INTS) {

	/* first acknowledge all interrupt sources */
	outw(BASE + EP_COMMAND, ACK_INTR | (status & S_MASK));

	if (status & (S_RX_COMPLETE | S_RX_EARLY))
	    epread(sc);
	if (status & S_TX_AVAIL) {
	    /* we need ACK */
	    ifp->if_timer = 0;
	    ifq_clr_oactive(&ifp->if_snd);
	    GO_WINDOW(1);
	    inw(BASE + EP_W1_FREE_TX);
	    if_devstart(ifp);
	}
	if (status & S_CARD_FAILURE) {
	    ifp->if_timer = 0;
#ifdef EP_LOCAL_STATS
	    kprintf("\n");
	    if_printf(ifp, "\n\tStatus: %x\n", status);
	    GO_WINDOW(4);
	    kprintf("\tFIFO Diagnostic: %x\n", inw(BASE + EP_W4_FIFO_DIAG));
	    kprintf("\tStat: %x\n", sc->stat);
	    kprintf("\tIpackets=%d, Opackets=%d\n",
		ifp->if_ipackets, ifp->if_opackets);
	    kprintf("\tNOF=%d, NOMB=%d, RXOF=%d, RXOL=%d, TXU=%d\n",
		   sc->rx_no_first, sc->rx_no_mbuf, sc->rx_overrunf,
		   sc->rx_overrunl, sc->tx_underrun);
#else

#ifdef DIAGNOSTIC
	    if_printf(ifp, "Status: %x (input buffer overflow)\n", status);
#else
	    IFNET_STAT_INC(ifp, ierrors, 1);
#endif

#endif
	    ep_if_init(sc);
	    return;
	}
	if (status & S_TX_COMPLETE) {
	    ifp->if_timer = 0;
	    /* we  need ACK. we do it at the end */
	    /*
	     * We need to read TX_STATUS until we get a 0 status in order to
	     * turn off the interrupt flag.
	     */
	    while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
		if (status & TXS_SUCCES_INTR_REQ);
		else if (status & (TXS_UNDERRUN | TXS_JABBER | TXS_MAX_COLLISION)) {
		    outw(BASE + EP_COMMAND, TX_RESET);
		    if (status & TXS_UNDERRUN) {
#ifdef EP_LOCAL_STATS
			sc->tx_underrun++;
#endif
		    } else {
			if (status & TXS_JABBER);
			else	/* TXS_MAX_COLLISION - we shouldn't get here */
			    IFNET_STAT_INC(ifp, collisions, 1);
		    }
		    IFNET_STAT_INC(ifp, oerrors, 1);
		    outw(BASE + EP_COMMAND, TX_ENABLE);
		    /*
		     * To have a tx_avail_int but giving the chance to the
		     * Reception
		     */
		    if (!ifq_is_empty(&ifp->if_snd))
			outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
		}
		outb(BASE + EP_W1_TX_STATUS, 0x0);	/* pops up the next
							 * status */
	    }			/* while */
	    ifq_clr_oactive(&ifp->if_snd);
	    GO_WINDOW(1);
	    inw(BASE + EP_W1_FREE_TX);
	    if_devstart(ifp);
	}			/* end TX_COMPLETE */
    }

    outw(BASE + EP_COMMAND, C_INTR_LATCH);	/* ACK int Latch */

    if ((status = inw(BASE + EP_STATUS)) & S_5_INTS)
	goto rescan;

    /* re-enable Ints */
    outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
}
Ejemplo n.º 8
0
/*
 * The order in here seems important. Otherwise we may not receive
 * interrupts. ?!
 */
static void
ep_if_init(void *xsc)
{
    struct ep_softc *sc = xsc;
    struct ifnet *ifp = &sc->arpcom.ac_if;
    int i;

    if (sc->gone)
	return;

    crit_enter();

    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);

    GO_WINDOW(0);
    outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
    GO_WINDOW(4);
    outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP);
    GO_WINDOW(0);

    /* Disable the card */
    outw(BASE + EP_W0_CONFIG_CTRL, 0);

    /* Enable the card */
    outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);

    GO_WINDOW(2);

    /* Reload the ether_addr. */
    for (i = 0; i < 6; i++)
	outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);

    outw(BASE + EP_COMMAND, RX_RESET);
    outw(BASE + EP_COMMAND, TX_RESET);
    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);

    /* Window 1 is operating window */
    GO_WINDOW(1);
    for (i = 0; i < 31; i++)
	inb(BASE + EP_W1_TX_STATUS);

    /* get rid of stray intr's */
    outw(BASE + EP_COMMAND, ACK_INTR | 0xff);

    outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS);

    outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);

    if (ifp->if_flags & IFF_PROMISC)
	outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
	 FIL_GROUP | FIL_BRDCST | FIL_ALL);
    else
	outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
	 FIL_GROUP | FIL_BRDCST);

    if (!sc->epb.mii_trans) {
	ep_ifmedia_upd(ifp);
    }

    outw(BASE + EP_COMMAND, RX_ENABLE);
    outw(BASE + EP_COMMAND, TX_ENABLE);

    ifp->if_flags |= IFF_RUNNING;
    ifq_clr_oactive(&ifp->if_snd);	/* just in case */

#ifdef EP_LOCAL_STATS
    sc->rx_no_first = sc->rx_no_mbuf =
	sc->rx_overrunf = sc->rx_overrunl = sc->tx_underrun = 0;
#endif
    EP_FSET(sc, F_RX_FIRST);
    if (sc->top) {
	m_freem(sc->top);
	sc->top = sc->mcur = 0;
    }
    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
    outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16);

    /*
     * Store up a bunch of mbuf's for use later. (MAX_MBS). First we free up
     * any that we had in case we're being called from intr or somewhere
     * else.
     */

    GO_WINDOW(1);

    if_devstart(ifp);

    crit_exit();
}