void
sscom_shutdown(struct sscom_softc *sc)
{
#ifdef notyet
	struct tty *tp = sc->sc_tty;
	int s;

	s = splserial();
	SSCOM_LOCK(sc);	

	/* If we were asserting flow control, then deassert it. */
	SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
	sscom_hwiflow(sc);

	/* Clear any break condition set with TIOCSBRK. */
	sscom_break(sc, 0);

	/*
	 * Hang up if necessary.  Wait a bit, so the other side has time to
	 * notice even if we immediately open the port again.
	 * Avoid tsleeping above splhigh().
	 */
	if (ISSET(tp->t_cflag, HUPCL)) {
		sscom_modem(sc, 0);
		SSCOM_UNLOCK(sc);
		splx(s);
		/* XXX tsleep will only timeout */
		(void) tsleep(sc, TTIPRI, ttclos, hz);
		s = splserial();
		SSCOM_LOCK(sc);	
	}

	if (ISSET(sc->sc_hwflags, SSCOM_HW_CONSOLE))
		/* interrupt on break */
		sc->sc_ucon = UCON_DEBUGPORT;
	else
		sc->sc_ucon = 0;
	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSCOM_UCON, sc->sc_ucon);

#ifdef DIAGNOSTIC
	if (!sc->enabled)
		panic("sscom_shutdown: not enabled?");
#endif
	sc->enabled = 0;
	SSCOM_UNLOCK(sc);
	splx(s);
#endif
}
integrate void
sscom_stsoft(struct sscom_softc *sc, struct tty *tp)
{
	u_char msr, delta;
	int s;

	s = splserial();
	SSCOM_LOCK(sc);
	msr = sc->sc_msts;
	delta = sc->sc_msr_delta;
	sc->sc_msr_delta = 0;
	SSCOM_UNLOCK(sc);	
	splx(s);

	if (ISSET(delta, sc->sc_msr_dcd)) {
		/*
		 * Inform the tty layer that carrier detect changed.
		 */
		(void) (*tp->t_linesw->l_modem)(tp, ISSET(msr, MSTS_DCD));
	}

	if (ISSET(delta, sc->sc_msr_cts)) {
		/* Block or unblock output according to flow control. */
		if (ISSET(msr, sc->sc_msr_cts)) {
			sc->sc_tx_stopped = 0;
			(*tp->t_linesw->l_start)(tp);
		} else {
			sc->sc_tx_stopped = 1;
		}
	}

	if (sscom_debug)
		sscomstatus(sc, "sscom_stsoft");
}
Exemple #3
0
/*
 * Configure.  This should be the first thing that the SPI driver
 * should do, to configure which mode (e.g. SPI_MODE_0, which is the
 * same as Philips Microwire mode), and speed.  If the bus driver
 * cannot run fast enough, then it should just configure the fastest
 * mode that it can support.  If the bus driver cannot run slow
 * enough, then the device is incompatible and an error should be
 * returned.
 */
int
spi_configure(struct spi_handle *sh, int mode, int speed)
{
	int			s, rv;
	struct spi_softc	*sc = sh->sh_sc;
	struct spi_controller	*tag = sh->sh_controller;

	/* ensure that request is compatible with other devices on the bus */
	if ((sc->sc_mode >= 0) && (sc->sc_mode != mode))
		return EINVAL;

	s = splserial();
	/* pick lowest configured speed */
	if (speed == 0)
		speed = sc->sc_speed;
	if (sc->sc_speed)
		speed = min(sc->sc_speed, speed);

	rv = (*tag->sct_configure)(tag->sct_cookie, sh->sh_slave,
	    mode, speed);

	if (rv == 0) {
		sc->sc_mode = mode;
		sc->sc_speed = speed;
	}
	splx(s);
	return rv;
}
static int
sscomhwiflow(struct tty *tp, int block)
{
	struct sscom_softc *sc = device_lookup_private(&sscom_cd, SSCOMUNIT(tp->t_dev));
	int s;

	if (SSCOM_ISALIVE(sc) == 0)
		return 0;

	if (sc->sc_mcr_rts == 0)
		return 0;

	s = splserial();
	SSCOM_LOCK(sc);
	
	if (block) {
		if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
			SET(sc->sc_rx_flags, RX_TTY_BLOCKED);
			sscom_hwiflow(sc);
		}
	} else {
		if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
			CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
			sscom_schedrx(sc);
		}
		if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
			CLR(sc->sc_rx_flags, RX_TTY_BLOCKED);
			sscom_hwiflow(sc);
		}
	}

	SSCOM_UNLOCK(sc);
	splx(s);
	return 1;
}
Exemple #5
0
int
sacom_activate(struct device *self, enum devact act)
{
    struct sacom_softc *sc = (struct sacom_softc *)self;
    int s, rv = 0;

    s = splserial();
    COM_LOCK(sc);
    switch (act) {
    case DVACT_ACTIVATE:
        rv = EOPNOTSUPP;
        break;

    case DVACT_DEACTIVATE:
        if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) {
            rv = EBUSY;
            break;
        }

        if (sc->disable != NULL && sc->enabled != 0) {
            (*sc->disable)(sc);
            sc->enabled = 0;
        }
        break;
    }

    COM_UNLOCK(sc);
    splx(s);
    return rv;
}
Exemple #6
0
static void mpcsa_leds_timer(void *aux)
{
	int n, s;
	struct mpcsa_leds_softc *sc = aux;
	u_int16_t pins;

	callout_schedule(&sc->sc_c, mstohz(LEDS_UPDATE_INTERVAL));

	s = splserial();
	if (!(sc->sc_spi_transfer.st_flags & SPI_F_DONE)) {
		splx(s);
		return;
	}


	pins = be16toh(sc->sc_pinstate);

	for (n = 0; n < MPCSA_LEDS_NPINS; n++) {
		switch (sc->sc_leds[n].l_mode) {
		default:
			continue;

		case LMODE_COMM:
			if (sc->sc_leds[n].l_comm_cnt > 0) {
				if (sc->sc_leds[n].l_comm_cnt < INFINITE_BLINK)
					sc->sc_leds[n].l_comm_cnt--;
				else
					sc->sc_leds[n].l_comm_cnt ^= 1;
			}
			if ((sc->sc_leds[n].l_conn_cnt > 0) ^ (sc->sc_leds[n].l_comm_cnt & 1))
				pins &= ~(1U << n);
			else
				pins |= (1U << n);
			break;

		case LMODE_BLINK:
			if (--sc->sc_leds[n].l_blink_cnt <= 0) {
				pins ^= (1U << n);
				sc->sc_leds[n].l_blink_cnt = sc->sc_leds[n].l_blink_int;
			}
			break;
		}
	}

	HTOBE16(pins);
	sc->sc_pinstate = pins;
	splx(s);

	spi_transfer_init(&sc->sc_spi_transfer);
	spi_chunk_init(&sc->sc_spi_chunk, 2, (const void *)&sc->sc_pinstate, NULL);
	spi_transfer_add(&sc->sc_spi_transfer, &sc->sc_spi_chunk);
	if (spi_transfer(sc->sc_sh, &sc->sc_spi_transfer) != 0) {
		/* an error occurred! */
	}
}
Exemple #7
0
void
sacom_shutdown(struct sacom_softc *sc)
{
    struct tty *tp = sc->sc_tty;
    int s;

    s = splserial();
    COM_LOCK(sc);

    /* Clear any break condition set with TIOCSBRK. */
    sacom_break(sc, 0);

    /*
     * Hang up if necessary.  Wait a bit, so the other side has time to
     * notice even if we immediately open the port again.
     * Avoid tsleeping above splhigh().
     */
    if (ISSET(tp->t_cflag, HUPCL)) {
        sacom_modem(sc, 0);
        COM_UNLOCK(sc);
        splx(s);
        /* XXX tsleep will only timeout */
        (void) tsleep(sc, TTIPRI, ttclos, hz);
        s = splserial();
        COM_LOCK(sc);
    }

    /* Turn off interrupts. */
    sc->sc_cr3 = 0;
    bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACOM_CR3, sc->sc_cr3);

    if (sc->disable) {
#ifdef DIAGNOSTIC
        if (!sc->enabled)
            panic("sacom_shutdown: not enabled?");
#endif
        (*sc->disable)(sc);
        sc->enabled = 0;
    }
    COM_UNLOCK(sc);
    splx(s);
}
Exemple #8
0
int
at91dbgu_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	struct at91dbgu_softc *sc = device_lookup_private(&at91dbgu_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;
	int error;
	int s;

	if (COM_ISALIVE(sc) == 0)
		return (EIO);

	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
	if (error != EPASSTHROUGH)
		return (error);

	error = ttioctl(tp, cmd, data, flag, l);
	if (error != EPASSTHROUGH)
		return (error);

	error = 0;

	s = splserial();

	switch (cmd) {
	case TIOCSBRK:
		at91dbgu_break(sc, 1);
		break;

	case TIOCCBRK:
		at91dbgu_break(sc, 0);
		break;

	case TIOCGFLAGS:
		*(int *)data = sc->sc_swflags;
		break;

	case TIOCSFLAGS:
		error = kauth_authorize_device_tty(l->l_cred,
		    KAUTH_DEVICE_TTY_PRIVSET, tp); 
		if (error)
			break;
		sc->sc_swflags = *(int *)data;
		break;

	default:
		error = EPASSTHROUGH;
		break;
	}

	splx(s);

	return (error);
}
Exemple #9
0
void
at91dbgu_cn_putc(dev_t dev, int c)
{
#if 0
	bus_space_tag_t		iot = dbgu_cn_sc.sc_iot;
	bus_space_handle_t	ioh = dbgu_cn_sc.sc_ioh;
#endif
	DBGU_PUTC(c);

#ifdef DEBUG
	if (c == '\r') {
		int s = splserial();
		while((DBGUREG(DBGU_SR) & DBGU_SR_TXEMPTY) == 0) {
			splx(s);
			s = splserial();
		}
		splx(s);
	}
#endif

}
/*ARGSUSED*/
static int
scimci_card_detect(sdmmc_chipset_handle_t sch)
{
	uint8_t reg;
	int s;

	s = splserial();
	CSR_SET_2(SH7709_PGCR, PGCR_EJECT, 0);
	reg = _reg_read_1(SH7709_PGDR);
	splx(s);

	return !(reg & PGDR_EJECT);
}
Exemple #11
0
void
spi_wait(struct spi_transfer *st)
{
	int	s;

	s = splserial();
	simple_lock(&st->st_lock);
	while (!st->st_flags & SPI_F_DONE) {
		ltsleep(st, PWAIT, "spi_wait", 0, &st->st_lock);
	}
	simple_unlock(&st->st_lock);
	splx(s);
}
/*ARGSUSED*/
static void
scimci_spi_initialize(sdmmc_chipset_handle_t sch)
{
	int i, s;

	s = splserial();
	CSR_SET_1(SH7709_SCPDR, SCPDR_CS, 0);
	for (i = 0; i < 20; i++)
		scimci_putc(0xff);
	scimci_putc_sw();
	CSR_CLR_1(SH7709_SCPDR, SCPDR_CS);
	splx(s);
}
Exemple #13
0
static void
sacom_enable_debugport(struct sacom_softc *sc)
{
    bus_space_tag_t iot = sc->sc_iot;
    bus_space_handle_t ioh = sc->sc_ioh;
    int s;

    s = splserial();
    COM_LOCK(sc);
    sc->sc_cr3 = CR3_RXE | CR3_TXE;
    bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
    COM_UNLOCK(sc);
    splx(s);
}
Exemple #14
0
void
sacomstart(struct tty *tp)
{
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev));
    bus_space_tag_t iot = sc->sc_iot;
    bus_space_handle_t ioh = sc->sc_ioh;
    int s;

    if (COM_ISALIVE(sc) == 0)
        return;

    s = spltty();
    if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
        goto out;
    if (!ttypull(tp))
        goto out;

    /* Grab the first contiguous region of buffer space. */
    {
        u_char *tba;
        int tbc;

        tba = tp->t_outq.c_cf;
        tbc = ndqb(&tp->t_outq, 0);

        (void)splserial();
        COM_LOCK(sc);

        sc->sc_tba = tba;
        sc->sc_tbc = tbc;
    }

    SET(tp->t_state, TS_BUSY);
    sc->sc_tx_busy = 1;

    /* Enable transmit completion interrupts if necessary. */
    if (!ISSET(sc->sc_cr3, CR3_TIE)) {
        SET(sc->sc_cr3, CR3_TIE);
        bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
    }

    /* Output the first chunk of the contiguous buffer. */
    sacom_filltx(sc);

    COM_UNLOCK(sc);
out:
    splx(s);
    return;
}
Exemple #15
0
void
sbscn_shutdown(struct sbscn_channel *ch)
{
	struct tty *tp = ch->ch_tty;
	int s;

	s = splserial();

	/* If we were asserting flow control, then deassert it. */
	SET(ch->ch_rx_flags, RX_IBUF_BLOCKED);
	sbscn_dohwiflow(ch);

	/* Clear any break condition set with TIOCSBRK. */
	sbscn_break(ch, 0);

	/*
	 * Hang up if necessary.  Wait a bit, so the other side has time to
	 * notice even if we immediately open the port again.
	 * Avoid tsleeping above splhigh().
	 */
	if (ISSET(tp->t_cflag, HUPCL)) {
		sbscn_modem(ch, 0);
		splx(s);
		/* XXX tsleep will only timeout */
		(void) tsleep(ch, TTIPRI, ttclos, hz);
		s = splserial();
	}

	/* Turn off interrupts. */
#ifdef DDB
	if (ISSET(ch->ch_hwflags, SBSCN_HW_CONSOLE))
#if 0	/* DO NOT turn on break interrupt at this time. */
		ch->ch_imr = 0x04; /* interrupt on break */
#else
		ch->ch_imr = 0x00;
#endif
	else
Exemple #16
0
int
at91dbgu_cn_getc(dev_t dev)
{
	int			c, sr;
	int			s;
#if 0
	bus_space_tag_t		iot = dbgu_cn_sc.sc_iot;
	bus_space_handle_t	ioh = dbgu_cn_sc.sc_ioh;
#endif

        s = splserial();

	while ((c = DBGU_PEEKC()) == -1) {
	  splx(s);
	  s = splserial();
	}
		;
	sr = DBGUREG(DBGU_SR);
	if (ISSET(sr, DBGU_SR_FRAME) && c == 0) {
		DBGUREG(DBGU_CR) = DBGU_CR_RSTSTA;	// reset status bits
		c = CNC_BREAK;
	}
#ifdef DDB
	extern int db_active;
	if (!db_active)
#endif
	{
		int cn_trapped = 0; /* unused */

		cn_check_magic(dev, c, at91dbgu_cnm_state);
	}
	splx(s);

	c &= 0xff;

	return (c);
}
Exemple #17
0
void
cpu_configure(void)
{

	splhigh();
	splserial();

	config_hook_init();

	if (config_rootfound("mainbus", NULL) == NULL)
		panic("no mainbus found");

	/* Configuration is finished, turn on interrupts. */
	spl0();
}
/*
 * void cpu_configure()
 *
 * Configure all the root devices
 * The root devices are expected to configure their own children
 */
void
cpu_configure(void)
{
	struct mainbus_attach_args maa;

	(void) splhigh();
	(void) splserial();	/* XXX need an splextreme() */

	maa.ma_name = "mainbus";

	config_rootfound("mainbus", &maa);

	/* Time to start taking interrupts so lets open the flood gates .... */
	spl0();
}
Exemple #19
0
/*
 * Stop output on a line.
 */
void
at91dbgu_stop(struct tty *tp, int flag)
{
	struct at91dbgu_softc *sc
		= device_lookup_private(&at91dbgu_cd, COMUNIT(tp->t_dev));
	int s;

	s = splserial();
	if (ISSET(tp->t_state, TS_BUSY)) {
		/* Stop transmitting at the next chunk. */
		sc->sc_tbc = 0;
		if (!ISSET(tp->t_state, TS_TTSTOP))
			SET(tp->t_state, TS_FLUSH);
	}
	splx(s);
}
Exemple #20
0
integrate void
clmpcc_enable_transmitter(struct clmpcc_chan *ch)
{
	u_int old;
	int s;

	old = clmpcc_select_channel(ch->ch_sc, ch->ch_car);

	s = splserial();
	clmpcc_wrreg(ch->ch_sc, CLMPCC_REG_IER,
		clmpcc_rdreg(ch->ch_sc, CLMPCC_REG_IER) | CLMPCC_IER_TX_EMPTY);
	SET(ch->ch_tty->t_state, TS_BUSY);
	splx(s);

	clmpcc_select_channel(ch->ch_sc, old);
}
Exemple #21
0
void mpcsa_blink_led(int num, int interval)
{
	struct mpcsa_leds_softc *sc = mpcsa_leds_sc;
	if (!sc || num < 1 || num > MPCSA_LEDS_NPINS) {
		return;
	}
	interval = (interval + LEDS_UPDATE_INTERVAL + 1) / LEDS_UPDATE_INTERVAL;
	num--;
	int s = splserial();
	if (sc->sc_leds[num].l_mode != LMODE_COMM) {
		sc->sc_leds[num].l_mode = LMODE_BLINK;
		sc->sc_leds[num].l_blink_cnt = interval;
	}
	sc->sc_leds[num].l_blink_int = interval;
	splx(s);
}
void
sscomstart(struct tty *tp)
{
	struct sscom_softc *sc = device_lookup_private(&sscom_cd, SSCOMUNIT(tp->t_dev));
	int s;

	if (SSCOM_ISALIVE(sc) == 0)
		return;

	s = spltty();
	if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
		goto out;
	if (sc->sc_tx_stopped)
		goto out;
	if (!ttypull(tp))
		goto out;

	/* Grab the first contiguous region of buffer space. */
	{
		u_char *tba;
		int tbc;

		tba = tp->t_outq.c_cf;
		tbc = ndqb(&tp->t_outq, 0);

		(void)splserial();
		SSCOM_LOCK(sc);

		sc->sc_tba = tba;
		sc->sc_tbc = tbc;
	}

	SET(tp->t_state, TS_BUSY);
	sc->sc_tx_busy = 1;

	/* Output the first chunk of the contiguous buffer. */
	sscom_output_chunk(sc);

	/* Enable transmit completion interrupts if necessary. */
	if ((sc->sc_hwflags & SSCOM_HW_TXINT) == 0)
		sscom_enable_txint(sc);

	SSCOM_UNLOCK(sc);
out:
	splx(s);
	return;
}
/*
 * Console kernel output character routine.
 */
void
sscomcnputc(dev_t dev, int c)
{
	int s = splserial();
	int timo;

	int cin;
	int __attribute__((__unused__)) stat;
	if (sscom_readaheadcount < MAX_READAHEAD && 
	    sscom_rxrdy(sscomconstag, sscomconsioh)) {
	    
		int __attribute__((__unused__))cn_trapped = 0;
		cin = sscom_getc(sscomconstag, sscomconsioh);
		stat = sscom_geterr(sscomconstag, sscomconsioh);
		cn_check_magic(dev, cin, sscom_cnm_state);
		sscom_readahead[sscom_readaheadcount++] = cin;
	}
Exemple #24
0
/*
 * Stop output on a line.
 */
void
clmpccstop(struct tty *tp, int flag)
{
	struct clmpcc_softc *sc =
	    device_lookup_private(&clmpcc_cd, CLMPCCUNIT(tp->t_dev));
	struct clmpcc_chan *ch = &sc->sc_chans[CLMPCCCHAN(tp->t_dev)];
	int s;

	s = splserial();

	if ( ISSET(tp->t_state, TS_BUSY) ) {
		if ( ISCLR(tp->t_state, TS_TTSTOP) )
			SET(tp->t_state, TS_FLUSH);
		ch->ch_obuf_size = 0;
	}
	splx(s);
}
static void
sscom_enable_debugport(struct sscom_softc *sc)
{
	int s;

	/* Turn on line break interrupt, set carrier. */
	s = splserial();
	SSCOM_LOCK(sc);
	sc->sc_ucon = UCON_DEBUGPORT;
	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSCOM_UCON, sc->sc_ucon);
	sc->sc_umcon = UMCON_RTS|UMCON_DTR;
	sc->sc_set_modem_control(sc);
	sscom_enable_rxint(sc);
	sscom_disable_txint(sc);
	SSCOM_UNLOCK(sc);
	splx(s);
}
Exemple #26
0
static void
at91dbgu_start(struct tty *tp)
{
	struct at91dbgu_softc *sc
		= device_lookup_private(&at91dbgu_cd, COMUNIT(tp->t_dev));
	int s;

	if (COM_ISALIVE(sc) == 0)
		return;

	s = spltty();
	if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
		goto out;
	if (sc->sc_tx_stopped)
		goto out;
	if (!ttypull(tp))
		goto out;

	/* Grab the first contiguous region of buffer space. */
	{
		u_char *tba;
		int tbc;

		tba = tp->t_outq.c_cf;
		tbc = ndqb(&tp->t_outq, 0);

		(void)splserial();

		sc->sc_tba = tba;
		sc->sc_tbc = tbc;
	}

	SET(tp->t_state, TS_BUSY);
	sc->sc_tx_busy = 1;

	/* Output the first chunk of the contiguous buffer. */
	at91dbgu_filltx(sc);

	SET(sc->sc_ier, DBGU_INT_TXRDY);
	DBGUREG(DBGU_IER) = DBGU_INT_TXRDY;

out:
	splx(s);
	return;
}
Exemple #27
0
void mpcsa_conn_led(int num, int ok)
{
	struct mpcsa_leds_softc *sc = mpcsa_leds_sc;
	if (!sc || num < 1 || num > MPCSA_LEDS_NPINS)
		return;
	num--;
	int s = splserial();
	if (sc->sc_leds[num].l_mode != LMODE_COMM) {
		sc->sc_leds[num].l_mode = LMODE_COMM;
		sc->sc_leds[num].l_conn_cnt = 0;
		sc->sc_leds[num].l_comm_cnt = 0;
	}
	if (ok)
		sc->sc_leds[num].l_conn_cnt++;
	else
		sc->sc_leds[num].l_conn_cnt--;
	splx(s);
}
/*
 * Stop output on a line.
 */
void
sscomstop(struct tty *tp, int flag)
{
	struct sscom_softc *sc = device_lookup_private(&sscom_cd, SSCOMUNIT(tp->t_dev));
	int s;

	s = splserial();
	SSCOM_LOCK(sc);
	if (ISSET(tp->t_state, TS_BUSY)) {
		/* Stop transmitting at the next chunk. */
		sc->sc_tbc = 0;
		sc->sc_heldtbc = 0;
		if (!ISSET(tp->t_state, TS_TTSTOP))
			SET(tp->t_state, TS_FLUSH);
	}
	SSCOM_UNLOCK(sc);	
	splx(s);
}
Exemple #29
0
static void
sbscn_enable_debugport(struct sbscn_channel *ch)
{
	int s;

	/* Turn on line break interrupt, set carrier. */
	s = splserial();

#if 0	/* DO NOT turn on break interrupt at this time. */
	ch->ch_imr = 0x04;
#else
	ch->ch_imr = 0x00;
#endif
	WRITE_REG(ch->ch_imr_base, ch->ch_imr);
	SET(ch->ch_oports, ch->ch_o_dtr | ch->ch_o_rts);
	SET_OUTPUT_SIGNALS(ch, ch->ch_oports);

	splx(s);
}
Exemple #30
0
void mpcsa_comm_led(int num, int count)
{
	struct mpcsa_leds_softc *sc = mpcsa_leds_sc;
	if (!sc || num < 1 || num > MPCSA_LEDS_NPINS) {
		return;
	}
	num--;
	count *= 2;
	int s = splserial();
	if (sc->sc_leds[num].l_mode != LMODE_COMM) {
		sc->sc_leds[num].l_mode = LMODE_COMM;
		sc->sc_leds[num].l_conn_cnt = 0;
		sc->sc_leds[num].l_comm_cnt = 0;
	}
	if (sc->sc_leds[num].l_comm_cnt < (count * 2 - 1))
		sc->sc_leds[num].l_comm_cnt += count;
	else if ((count * 2) < sc->sc_leds[num].l_comm_cnt)
		sc->sc_leds[num].l_comm_cnt = count * 2 - 2 - (sc->sc_leds[num].l_comm_cnt % 2);
	splx(s);
}