コード例 #1
0
ファイル: z8530tty.c プロジェクト: ajinkya93/OpenBSD
void
zs_shutdown(struct zstty_softc *zst)
{
	struct zs_chanstate *cs = zst->zst_cs;
	struct tty *tp = zst->zst_tty;
	int s;

	s = splzs();

	/* If we were asserting flow control, then deassert it. */
	SET(zst->zst_rx_flags, RX_IBUF_BLOCKED);
	zs_hwiflow(zst);

	/* Clear any break condition set with TIOCSBRK. */
	zs_break(cs, 0);

	/* Turn off PPS capture on last close. */
	zst->zst_ppsmask = 0;

	/*
	 * Hang up if necessary.  Wait a bit, so the other side has time to
	 * notice even if we immediately open the port again.
	 */
	if (ISSET(tp->t_cflag, HUPCL) || ISSET(tp->t_state, TS_WOPEN)) {
		zs_modem(zst, 0);
		/* hold low for 1 second */
		(void)tsleep(cs, TTIPRI, ttclos, hz);
	}

	/* Turn off interrupts if not the console. */
	if (!ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) {
		CLR(cs->cs_preg[1], ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE);
		cs->cs_creg[1] = cs->cs_preg[1];
		zs_write_reg(cs, 1, cs->cs_creg[1]);
	}

	/* Call the power management hook. */
	if (cs->disable) {
#ifdef DIAGNOSTIC
		if (!cs->enabled)
			panic("%s: not enabled?", __func__);
#endif
		(*cs->disable)(zst->zst_cs);
	}

	splx(s);
}
コード例 #2
0
/*
 * Open a zs serial port.
 */
int
zsopen(dev_t dev, int flags, int mode, struct lwp *l)
{
	struct tty *tp;
	struct zs_chanstate *cs;
	struct zs_softc *sc;
	int unit = ZS_UNIT(dev);
	int zs = unit >> 1;
	int error, s;

	sc = device_lookup_private(&zs_cd, zs);
	if (sc == NULL)
		return ENXIO;
	cs = sc->sc_cs[unit & 1];

	/*
	 * When port A (ser02) is selected on the TT, make sure
	 * the port is enabled.
	 */
	if ((machineid & ATARI_TT) && !(unit & 1))
		ym2149_ser2(1);

	if (cs->cs_rbuf == NULL) {
		cs->cs_rbuf = malloc(ZLRB_RING_SIZE * sizeof(int), M_DEVBUF,
		    M_WAITOK);
	}

	tp = cs->cs_ttyp;
	if (tp == NULL) {
		cs->cs_ttyp = tp = tty_alloc();
		tty_attach(tp);
		tp->t_dev   = dev;
		tp->t_oproc = zsstart;
		tp->t_param = zsparam;
	}

	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
		return EBUSY;

	s  = spltty();

	/*
	 * Do the following iff this is a first open.
	 */
	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
		if (tp->t_ispeed == 0) {
			tp->t_iflag = TTYDEF_IFLAG;
			tp->t_oflag = TTYDEF_OFLAG;
			tp->t_cflag = TTYDEF_CFLAG;
			tp->t_lflag = TTYDEF_LFLAG;
			tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
		}
		ttychars(tp);
		ttsetwater(tp);

		(void)zsparam(tp, &tp->t_termios);

		/*
		 * Turn on DTR.  We must always do this, even if carrier is not
		 * present, because otherwise we'd have to use TIOCSDTR
		 * immediately after setting CLOCAL, which applications do not
		 * expect.  We always assert DTR while the device is open
		 * unless explicitly requested to deassert it.
		 */
		zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR, DMSET);
		/* May never get a status intr. if DCD already on. -gwr */
		if (((cs->cs_rr0 = cs->cs_zc->zc_csr) & ZSRR0_DCD) != 0)
			tp->t_state |= TS_CARR_ON;
		if (cs->cs_softcar)
			tp->t_state |= TS_CARR_ON;
	}

	splx(s);

	error = ttyopen(tp, ZS_DIALOUT(dev), (flags & O_NONBLOCK));
	if (error)
		goto bad;
	
	error = tp->t_linesw->l_open(dev, tp);
	if (error)
		goto bad;
	return 0;

bad:
	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		zs_shutdown(cs);
	}
	return error;
}
コード例 #3
0
ファイル: z8530tty.c プロジェクト: ajinkya93/OpenBSD
int
zsioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
	struct zstty_softc *zst = zs_device_lookup(&zstty_cd, ZSUNIT(dev));
	struct zs_chanstate *cs = zst->zst_cs;
	struct tty *tp = zst->zst_tty;
	int error;
	int s;

	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
	if (error >= 0)
		return (error);

	error = ttioctl(tp, cmd, data, flag, p);
	if (error >= 0)
		return (error);

#ifdef	ZS_MD_IOCTL
	error = ZS_MD_IOCTL;
	if (error >= 0)
		return (error);
#endif	/* ZS_MD_IOCTL */

	error = 0;

	s = splzs();

	switch (cmd) {
	case TIOCSBRK:
		zs_break(cs, 1);
		break;

	case TIOCCBRK:
		zs_break(cs, 0);
		break;

	case TIOCGFLAGS:
		*(int *)data = zst->zst_swflags;
		break;

	case TIOCSFLAGS:
		error = suser(p, 0);
		if (error)
			break;
		zst->zst_swflags = *(int *)data;
		if (ISSET(zst->zst_hwflags, ZS_HWFLAG_NO_DCD))
			SET(zst->zst_swflags, TIOCFLAG_SOFTCAR);
		break;

	case TIOCSDTR:
		zs_modem(zst, 1);
		break;

	case TIOCCDTR:
		zs_modem(zst, 0);
		break;

	case TIOCMSET:
	case TIOCMBIS:
	case TIOCMBIC:
		tiocm_to_zs(zst, cmd, *(int *)data);
		break;

	case TIOCMGET:
		*(int *)data = zs_to_tiocm(zst);
		break;

	default:
		error = ENOTTY;
		break;
	}

	splx(s);

	return (error);
}
コード例 #4
0
ファイル: z8530tty.c プロジェクト: ajinkya93/OpenBSD
/*
 * Open a zs serial (tty) port.
 */
int
zsopen(dev_t dev, int flags, int mode, struct proc *p)
{
	struct zstty_softc *zst;
	struct zs_chanstate *cs;
	struct tty *tp;
	int s;
#if IPL_ZS != IPL_TTY
	int s2;
#endif
	int error;

	zst = zs_device_lookup(&zstty_cd, ZSUNIT(dev));
	if (zst == NULL)
		return (ENXIO);

	tp = zst->zst_tty;
	cs = zst->zst_cs;

	/* If KGDB took the line, then tp==NULL */
	if (tp == NULL)
		return (EBUSY);

	if (ISSET(tp->t_state, TS_ISOPEN) &&
	    ISSET(tp->t_state, TS_XCLUDE) &&
	    suser(p, 0) != 0)
		return (EBUSY);

	s = spltty();

	/*
	 * Do the following iff this is a first open.
	 */
	if (!ISSET(tp->t_state, TS_ISOPEN)) {
		struct termios t;

		tp->t_dev = dev;

		/* Call the power management hook. */
		if (cs->enable) {
			if ((*cs->enable)(cs)) {
				splx(s);
				printf("%s: device enable failed\n",
				    zst->zst_dev.dv_xname);
				return (EIO);
			}
		}

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
		t.c_ospeed = cs->cs_defspeed;
		t.c_cflag = cs->cs_defcflag;
		if (ISSET(zst->zst_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(zst->zst_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(zst->zst_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);

#if IPL_ZS != IPL_TTY
		s2 = splzs();
#endif

		/*
		 * Turn on receiver and status interrupts.
		 * We defer the actual write of the register to zsparam(),
		 * but we must make sure status interrupts are turned on by
		 * the time zsparam() reads the initial rr0 state.
		 */
		SET(cs->cs_preg[1], ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE);

		/* Clear PPS capture state on first open. */
		zst->zst_ppsmask = 0;

#if IPL_ZS != IPL_TTY
		splx(s2);
#endif

		/* Make sure zsparam will see changes. */
		tp->t_ospeed = 0;
		(void)zsparam(tp, &t);

		/*
		 * Note: zsparam has done: cflag, ispeed, ospeed
		 * so we just need to do: iflag, oflag, lflag, cc
		 * For "raw" mode, just leave all zeros.
		 */
		if (!ISSET(zst->zst_hwflags, ZS_HWFLAG_RAW)) {
			tp->t_iflag = TTYDEF_IFLAG;
			tp->t_oflag = TTYDEF_OFLAG;
			tp->t_lflag = TTYDEF_LFLAG;
		} else {
			tp->t_iflag = 0;
			tp->t_oflag = 0;
			tp->t_lflag = 0;
		}
		ttychars(tp);
		ttsetwater(tp);

		if (ZSDIALOUT(dev))
			SET(tp->t_state, TS_CARR_ON);
		else
			CLR(tp->t_state, TS_CARR_ON);

#if IPL_ZS != IPL_TTY
		s2 = splzs();
#endif

		/* Clear the input ring, and unblock. */
		zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf;
		zst->zst_rbavail = zstty_rbuf_size;
		zs_iflush(cs);
		CLR(zst->zst_rx_flags, RX_ANY_BLOCK);
		zs_hwiflow(zst);

#if IPL_ZS != IPL_TTY
		splx(s2);
#endif
	}

	if (ZSDIALOUT(dev)) {
		if (ISSET(tp->t_state, TS_ISOPEN)) {
			/* someone already is dialed in... */
			splx(s);
			return EBUSY;
		}
		cs->cs_cua = 1;
	}

	error = 0;
	/* wait for carrier if necessary */
	if (ISSET(flags, O_NONBLOCK)) {
		if (!ZSDIALOUT(dev) && cs->cs_cua) {
			/* Opening TTY non-blocking... but the CUA is busy */
			error = EBUSY;
		}
	} else
	  while (cs->cs_cua ||
	    (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) {
		int rr0;

		error = 0;
		SET(tp->t_state, TS_WOPEN);

		if (!ZSDIALOUT(dev) && !cs->cs_cua) {
			/*
			 * Turn on DTR.  We must always do this on non-CUA
			 * devices, even if carrier is not present, because
			 * otherwise we'd have to use TIOCSDTR immediately
			 * after setting CLOCAL, which applications do not
			 * expect.  We always assert DTR while the device is
			 * open unless explicitly requested to deassert it.
			 */
#if IPL_ZS != IPL_TTY
			s2 = splzs();
#endif
			zs_modem(zst, 1);
			rr0 = zs_read_csr(cs);
#if IPL_ZS != IPL_TTY
			splx(s2);
#endif

			/* loop, turning on the device, until carrier present */
			if (ISSET(rr0, ZSRR0_DCD) ||
			    ISSET(zst->zst_swflags, TIOCFLAG_SOFTCAR))
				SET(tp->t_state, TS_CARR_ON);
		}

		if ((ISSET(tp->t_cflag, CLOCAL) ||
		    ISSET(tp->t_state, TS_CARR_ON)) && !cs->cs_cua)
			break;

		error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
		    ttopen, 0);

		if (!ZSDIALOUT(dev) && cs->cs_cua && error == EINTR) {
			error = 0;
			continue;
		}

		if (error) {
			if (!ISSET(tp->t_state, TS_ISOPEN)) {
#if IPL_ZS != IPL_TTY
				s2 = splzs();
#endif
				zs_modem(zst, 0);
#if IPL_ZS != IPL_TTY
				splx(s2);
#endif
				CLR(tp->t_state, TS_WOPEN);
				ttwakeup(tp);
			}
			if (ZSDIALOUT(dev))
				cs->cs_cua = 0;
			CLR(tp->t_state, TS_WOPEN);
			break;
		}
		if (!ZSDIALOUT(dev) && cs->cs_cua)
			continue;
	}

	splx(s);

	if (error == 0)
		error = ((*linesw[tp->t_line].l_open)(dev, tp, p));
	if (error)
		goto bad;

	return (0);

bad:
	if (!ISSET(tp->t_state, TS_ISOPEN)) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		zs_shutdown(zst);
	}

	return (error);
}
コード例 #5
0
ファイル: z8530tty.c プロジェクト: ajinkya93/OpenBSD
void
zstty_attach(struct device *parent, struct device *self, void *aux)
{
	struct zsc_softc *zsc = (struct zsc_softc *)parent;
	struct zstty_softc *zst = (struct zstty_softc *)self;
	struct cfdata *cf = self->dv_cfdata;
	struct zsc_attach_args *args = aux;
	struct zs_chanstate *cs;
	struct tty *tp;
	int channel, s, tty_unit;
	dev_t dev;
	const char *i, *o;
	int dtr_on;
	int resetbit;

	timeout_set(&zst->zst_diag_ch, zstty_diag, zst);

	tty_unit = zst->zst_dev.dv_unit;
	channel = args->channel;
	cs = zsc->zsc_cs[channel];
	cs->cs_private = zst;
	cs->cs_ops = &zsops_tty;

	zst->zst_cs = cs;
	zst->zst_swflags = cf->cf_flags;	/* softcar, etc. */
	zst->zst_hwflags = args->hwflags;
	dev = makedev(zs_major, tty_unit);

	if (zst->zst_swflags)
		printf(" flags 0x%x", zst->zst_swflags);

	if (ISSET(zst->zst_hwflags, ZS_HWFLAG_NO_DCD))
		SET(zst->zst_swflags, TIOCFLAG_SOFTCAR);

	/*
	 * Check whether we serve as a console device.
	 * XXX - split console input/output channels aren't
	 *	 supported yet on /dev/console
	 */
	i = o = NULL;
	if ((zst->zst_hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) {
		i = " input";
		if ((args->hwflags & ZS_HWFLAG_USE_CONSDEV) != 0) {
			args->consdev->cn_dev = dev;
			cn_tab->cn_pollc = args->consdev->cn_pollc;
			cn_tab->cn_getc = args->consdev->cn_getc;
		}
		cn_tab->cn_dev = dev;
	}
	if ((zst->zst_hwflags & ZS_HWFLAG_CONSOLE_OUTPUT) != 0) {
		o = " output";
		if ((args->hwflags & ZS_HWFLAG_USE_CONSDEV) != 0) {
			cn_tab->cn_putc = args->consdev->cn_putc;
		}
		cn_tab->cn_dev = dev;
	}
	if (i != NULL || o != NULL) {
		printf(": console%s", i ? (o ? "" : i) : o);
	}

#ifdef KGDB
	if (zs_check_kgdb(cs, dev)) {
		/*
		 * Allow kgdb to "take over" this port.  Returns true
		 * if this serial port is in-use by kgdb.
		 */
		printf(": kgdb\n");
		/*
		 * This is the kgdb port (exclusive use)
		 * so skip the normal attach code.
		 */
		return;
	}
#endif

#if defined(__sparc__) || defined(__sparc64__)
	if (strcmp(args->type, "keyboard") == 0 ||
	    strcmp(args->type, "mouse") == 0)
		printf(": %s", args->type);
#endif

	printf("\n");

	tp = ttymalloc(0);
	tp->t_dev = dev;
	tp->t_oproc = zsstart;
	tp->t_param = zsparam;
	tp->t_hwiflow = zshwiflow;

	zst->zst_tty = tp;
	zst->zst_rbuf = mallocarray(zstty_rbuf_size, 2, M_DEVBUF, M_WAITOK);
	zst->zst_ebuf = zst->zst_rbuf + (zstty_rbuf_size * 2);
	/* Disable the high water mark. */
	zst->zst_r_hiwat = 0;
	zst->zst_r_lowat = 0;
	zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf;
	zst->zst_rbavail = zstty_rbuf_size;

	/* if there are no enable/disable functions, assume the device
	   is always enabled */
	if (!cs->enable)
		cs->enabled = 1;

	/*
	 * Hardware init
	 */
	dtr_on = 0;
	resetbit = 0;
	if (ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) {
		/* Call zsparam similar to open. */
		struct termios t;

		/* Wait a while for previous console output to complete */
		DELAY(10000);

		/* Setup the "new" parameters in t. */
		t.c_ispeed = 0;
		t.c_ospeed = cs->cs_defspeed;
		t.c_cflag = cs->cs_defcflag;

		s = splzs();

		/*
		 * Turn on receiver and status interrupts.
		 * We defer the actual write of the register to zsparam(),
		 * but we must make sure status interrupts are turned on by
		 * the time zsparam() reads the initial rr0 state.
		 */
		SET(cs->cs_preg[1], ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE);

		splx(s);

		/* Make sure zsparam will see changes. */
		tp->t_ospeed = 0;
		(void)zsparam(tp, &t);

		/* Make sure DTR is on now. */
		dtr_on = 1;
	} else if (!ISSET(zst->zst_hwflags, ZS_HWFLAG_NORESET)) {
		/* Not the console; may need reset. */
		resetbit = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET;
	}

	s = splzs();
	if (resetbit)
		zs_write_reg(cs, 9, resetbit);
	zs_modem(zst, dtr_on);
	splx(s);
}