Example #1
0
File: zs.c Project: MarginC/kame
static void
zsttystart(struct tty *tp)
{
	struct zstty_softc *sc;
	uint8_t c;

	sc = tp->t_dev->si_drv1;

	if ((tp->t_state & TS_TBLOCK) != 0)
		/* XXX clear RTS */;
	else
		/* XXX set RTS */;

	if ((tp->t_state & (TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) != 0) {
		ttwwakeup(tp);
		return;
	}

	if (tp->t_outq.c_cc <= tp->t_olowat) {
		if ((tp->t_state & TS_SO_OLOWAT) != 0) {
			tp->t_state &= ~TS_SO_OLOWAT;
			wakeup(TSA_OLOWAT(tp));
		}
		selwakeup(&tp->t_wsel);
		if (tp->t_outq.c_cc == 0) {
			if ((tp->t_state & (TS_BUSY | TS_SO_OCOMPLETE)) ==
			    TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
				tp->t_state &= ~TS_SO_OCOMPLETE;
				wakeup(TSA_OCOMPLETE(tp));
			}
			return;
		}
	}

	sc->sc_ocnt = q_to_b(&tp->t_outq, sc->sc_obuf, sizeof(sc->sc_obuf));
	if (sc->sc_ocnt == 0)
		return;
	c = sc->sc_obuf[0];
	sc->sc_oget = sc->sc_obuf + 1;
	sc->sc_ocnt--;

	tp->t_state |= TS_BUSY;
	sc->sc_tx_busy = 1;

	/*
	 * Enable transmit interrupts if necessary and send the first
	 * character to start up the transmitter.
	 */
	if ((sc->sc_preg[1] & ZSWR1_TIE) == 0) {
		sc->sc_preg[1] |= ZSWR1_TIE;
		sc->sc_creg[1] = sc->sc_preg[1];
		ZS_WRITE_REG(sc, 1, sc->sc_creg[1]);
	}
	ZS_WRITE(sc, sc->sc_data, c);

	ttwwakeup(tp);
}
Example #2
0
File: zs.c Project: MarginC/kame
static void
zstty_cnputc(struct zstty_softc *sc, int c)
{

	zstty_cnopen(sc);
	while ((ZS_READ(sc, sc->sc_csr) & ZSRR0_TX_READY) == 0)
		;
	ZS_WRITE(sc, sc->sc_data, c);
	zstty_cnclose(sc);
}
Example #3
0
File: zs.c Project: MarginC/kame
static void
zstty_flush(struct zstty_softc *sc)
{
	uint8_t rr0;
	uint8_t rr1;
	uint8_t c;

	for (;;) {
		rr0 = ZS_READ(sc, sc->sc_csr);
		if ((rr0 & ZSRR0_RX_READY) == 0)
			break;

		rr1 = ZS_READ_REG(sc, 1);
		c = ZS_READ(sc, sc->sc_data);

		if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE))
			ZS_WRITE(sc, sc->sc_data, ZSWR0_RESET_ERRORS);
	}
}
Example #4
0
File: zs.c Project: MarginC/kame
static void
zstty_load_regs(struct zstty_softc *sc)
{

	/*
	 * If the transmitter may be active, just hold the change and do it
	 * in the tx interrupt handler.  Changing the registers while tx is
	 * active may hang the chip.
	 */
	if (sc->sc_tx_busy != 0) {
		sc->sc_preg_held = 1;
		return;
	}

	/* If the regs are the same do nothing. */
	if (bcmp(sc->sc_preg, sc->sc_creg, 16) == 0)
		return;

	bcopy(sc->sc_preg, sc->sc_creg, 16);

	/* XXX: reset error condition */
	ZS_WRITE(sc, sc->sc_csr, ZSM_RESET_ERR);

	/* disable interrupts */
	ZS_WRITE_REG(sc, 1, sc->sc_creg[1] & ~ZSWR1_IMASK);

	/* baud clock divisor, stop bits, parity */
	ZS_WRITE_REG(sc, 4, sc->sc_creg[4]);

	/* misc. TX/RX control bits */
	ZS_WRITE_REG(sc, 10, sc->sc_creg[10]);

	/* char size, enable (RX/TX) */
	ZS_WRITE_REG(sc, 3, sc->sc_creg[3] & ~ZSWR3_RX_ENABLE);
	ZS_WRITE_REG(sc, 5, sc->sc_creg[5] & ~ZSWR5_TX_ENABLE);

	/* Shut down the BRG */
	ZS_WRITE_REG(sc, 14, sc->sc_creg[14] & ~ZSWR14_BAUD_ENA);

	/* clock mode control */
	ZS_WRITE_REG(sc, 11, sc->sc_creg[11]);

	/* baud rate (lo/hi) */
	ZS_WRITE_REG(sc, 12, sc->sc_creg[12]);
	ZS_WRITE_REG(sc, 13, sc->sc_creg[13]);

	/* Misc. control bits */
	ZS_WRITE_REG(sc, 14, sc->sc_creg[14]);

	/* which lines cause status interrupts */
	ZS_WRITE_REG(sc, 15, sc->sc_creg[15]);

	/*
	 * Zilog docs recommend resetting external status twice at this
	 * point. Mainly as the status bits are latched, and the first
	 * interrupt clear might unlatch them to new values, generating
	 * a second interrupt request.
	 */
	ZS_WRITE(sc, sc->sc_csr, ZSM_RESET_STINT);
	ZS_WRITE(sc, sc->sc_csr, ZSM_RESET_STINT);

	/* char size, enable (RX/TX)*/
	ZS_WRITE_REG(sc, 3, sc->sc_creg[3]);
	ZS_WRITE_REG(sc, 5, sc->sc_creg[5]);

	/* interrupt enables: RX, TX, STATUS */
	ZS_WRITE_REG(sc, 1, sc->sc_creg[1]);
}
Example #5
0
File: zs.c Project: MarginC/kame
/*
 * Note that the rr3 value is shifted so the channel a status bits are in the
 * channel b bit positions, which makes the bit positions uniform for both
 * channels.
 */
static int
zstty_intr(struct zstty_softc *sc, uint8_t rr3)
{
	int needsoft;
	uint8_t rr0;
	uint8_t rr1;
	uint8_t c;
	int brk;

	ZSTTY_LOCK(sc);

	ZS_WRITE(sc, sc->sc_csr, ZSWR0_CLR_INTR);

	brk = 0;
	needsoft = 0;
	if ((rr3 & ZSRR3_IP_B_RX) != 0) {
		needsoft = 1;
		do {
			/*
			 * First read the status, because reading the received
			 * char destroys the status of this char.
			 */
			rr1 = ZS_READ_REG(sc, 1);
			c = ZS_READ(sc, sc->sc_data);

			if ((rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) != 0)
				ZS_WRITE(sc, sc->sc_csr, ZSWR0_RESET_ERRORS);
#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER)
			if (sc->sc_console != 0)
				brk = db_alt_break(c, &sc->sc_alt_break_state);
#endif
			*sc->sc_iput++ = c;
			*sc->sc_iput++ = rr1;
			if (sc->sc_iput == sc->sc_ibuf + sizeof(sc->sc_ibuf))
				sc->sc_iput = sc->sc_ibuf;
		} while ((ZS_READ(sc, sc->sc_csr) & ZSRR0_RX_READY) != 0);
	}

	if ((rr3 & ZSRR3_IP_B_STAT) != 0) {
		rr0 = ZS_READ(sc, sc->sc_csr);
		ZS_WRITE(sc, sc->sc_csr, ZSWR0_RESET_STATUS);
#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
		if (sc->sc_console != 0 && (rr0 & ZSRR0_BREAK) != 0)
			brk = 1;
#endif
		/* XXX do something about flow control */
	}

	if ((rr3 & ZSRR3_IP_B_TX) != 0) {
		/*
		 * If we've delayed a paramter change, do it now.
		 */
		if (sc->sc_preg_held) {
			sc->sc_preg_held = 0;
			zstty_load_regs(sc);
		}
		if (sc->sc_ocnt > 0) {
			ZS_WRITE(sc, sc->sc_data, *sc->sc_oget++);
			sc->sc_ocnt--;
		} else {
			/*
			 * Disable transmit completion interrupts if
			 * necessary.
			 */
			if ((sc->sc_preg[1] & ZSWR1_TIE) != 0) {
				sc->sc_preg[1] &= ~ZSWR1_TIE;
				sc->sc_creg[1] = sc->sc_preg[1];
				ZS_WRITE_REG(sc, 1, sc->sc_creg[1]);
			}
			sc->sc_tx_done = 1;
			sc->sc_tx_busy = 0;
			needsoft = 1;
		}
	}

	ZSTTY_UNLOCK(sc);

	if (brk != 0)
		breakpoint();

	return (needsoft);
}
Example #6
0
/*
 * Attach a found zs.
 */
static void
zsattach(device_t parent, device_t self, void *aux)
{
	struct zs_softc *sc;
	struct zsdevice *zs;
	struct zschan *zc;
	struct zs_chanstate *cs;
	int channel;

	sc = device_private(self);
	sc->sc_dev = self;

	printf(": serial2 on channel a and modem2 on channel b\n");

	zs = (struct zsdevice *)AD_SCC;

	for (channel = 0; channel < 2; channel++) {
		cs = &sc->sc_cs_store[channel];
		sc->sc_cs[channel] = cs;

		cs->cs_unit = channel;
		cs->cs_zc = zc =
		    (channel == 0) ?  &zs->zs_chan_a : &zs->zs_chan_b;
		/*
		 * Get the command register into a known state.
		 */
		(void)zc->zc_csr;
		(void)zc->zc_csr;

		/*
		 * Do a hardware reset.
		 */
		if (channel == 0) {
			ZS_WRITE(zc, 9, ZSWR9_HARD_RESET);
			delay(50000);	/* enough ? */
			ZS_WRITE(zc, 9, 0);
		}

		/*
		 * Initialize channel
		 */
		zs_loadchannelregs(zc, zs_init_regs);
	}

	if (machineid & ATARI_TT) {
		/*
		 * ininitialise TT-MFP timer C: 307200Hz
		 * timer C and D share one control register:
		 *	bits 0-2 control timer D
		 *	bits 4-6 control timer C
		 */
		int cr = MFP2->mf_tcdcr & 7;
		MFP2->mf_tcdcr = cr;		/* stop timer C  */
		MFP2->mf_tcdr  = 1;		/* counter 1     */
		cr |= T_Q004 << 4;		/* divisor 4     */
		MFP2->mf_tcdcr = cr;		/* start timer C */
		/*
		 * enable scc related interrupts
		 */
		SCU->vme_mask |= SCU_SCC;

		zs_frequencies = zs_freqs_tt;
	} else if (machineid & ATARI_FALCON) {
		zs_frequencies = zs_freqs_falcon;
	} else if (machineid & ATARI_HADES) {
		zs_frequencies = zs_freqs_hades;
	} else {
		zs_frequencies = zs_freqs_generic;
	}

	if (intr_establish(36, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
		aprint_error_dev(self,
		    "Can't establish interrupt (Rx chan B)\n");
	if (intr_establish(32, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
		aprint_error_dev(self,
		    "Can't establish interrupt (Tx empty chan B)\n");
	if (intr_establish(34, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
		aprint_error_dev(self,
		    "Can't establish interrupt (Ext./Status chan B)\n");
	if (intr_establish(38, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
		aprint_error_dev(self,
		    "Can't establish interrupt (Special Rx cond. chan B)\n");
	if (intr_establish(44, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
		aprint_error_dev(self,
		    "Can't establish interrupt (Rx chan A)\n");
	if (intr_establish(40, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
		aprint_error_dev(self,
		    "Can't establish interrupt (Tx empty chan A)\n");
	if (intr_establish(42, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
		aprint_error_dev(self,
		    "Can't establish interrupt (Ext./Status chan A)\n");
	if (intr_establish(46, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
		aprint_error_dev(self,
		    "Can't establish interrupt (Special Rx cond. chan A)\n");

	sc->sc_sicookie = softint_establish(SOFTINT_SERIAL,
	    (void (*)(void *))zssoft, sc);
}