Esempio n. 1
0
int
cirioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
	struct cir_softc *sc;
	int error;

	sc = device_lookup_private(&cir_cd, CIRUNIT(dev));
	if (sc == NULL)
		return (ENXIO);
	if (!device_is_active(sc->sc_dev))
		return (EIO);

	switch (cmd) {
	case FIONBIO:
		/* All handled in the upper FS layer. */
		error = 0;
		break;
	case CIR_GET_PARAMS:
		*(struct cir_params *)addr = sc->sc_params;
		error = 0;
		break;
	case CIR_SET_PARAMS:
		error = sc->sc_methods->im_setparams(sc->sc_handle,
			    (struct cir_params *)addr);
		if (!error)
			sc->sc_params = *(struct cir_params *)addr;
		break;
	default:
		error = EINVAL;
		break;
	}
	return (error);
}
Esempio n. 2
0
/*
 * Perform special action on behalf of the user;
 * knows about the internals of this device
 */
int
ssioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
	struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
	int error = 0;
	struct scan_io *sio;

	if (!device_is_active(&ss->sc_dev))
		return (ENODEV);

	switch (cmd) {
	case SCIOCGET:
		if (ss->special && ss->special->get_params) {
			/* call special handler */
			error = (ss->special->get_params)(ss);
			if (error)
				return (error);
		} else {
			/* XXX add code for SCSI2 scanner, if any */
			return (EOPNOTSUPP);
		}
		memcpy(addr, &ss->sio, sizeof(struct scan_io));
		break;
	case SCIOCSET:
		sio = (struct scan_io *)addr;

		if (ss->special && ss->special->set_params) {
			/* call special handler */
			error = (ss->special->set_params)(ss, sio);
			if (error)
				return (error);
		} else {
			/* XXX add code for SCSI2 scanner, if any */
			return (EOPNOTSUPP);
		}
		break;
	case SCIOCRESTART:
		if (ss->special && ss->special->rewind_scanner ) {
			/* call special handler */
			error = (ss->special->rewind_scanner)(ss);
			if (error)
				return (error);
		} else
			/* XXX add code for SCSI2 scanner, if any */
			return (EOPNOTSUPP);
		ss->flags &= ~SSF_TRIGGERED;
		break;
#ifdef NOTYET
	case SCAN_USE_ADF:
		break;
#endif
	default:
		return (scsipi_do_ioctl(ss->sc_periph, dev, cmd, addr,
		    flag, l));
	}
	return (error);
}
Esempio n. 3
0
/*
 * Actually translate the requested transfer into one the physical
 * driver can understand The transfer is described by a buf and will
 * include only one physical transfer.
 */
static void
ssstrategy(struct buf *bp)
{
	struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev));
	struct scsipi_periph *periph = ss->sc_periph;
	int s;

	SC_DEBUG(ss->sc_periph, SCSIPI_DB1,
	    ("ssstrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount,
	    bp->b_blkno));

	/* If the device has been made invalid, error out */
	if (!device_is_active(ss->sc_dev)) {
		if (periph->periph_flags & PERIPH_OPEN)
			bp->b_error = EIO;
		else
			bp->b_error = ENODEV;
		goto done;
	}

	/* If negative offset, error */
	if (bp->b_blkno < 0) {
		bp->b_error = EINVAL;
		goto done;
	}

	if (bp->b_bcount > ss->sio.scan_window_size)
		bp->b_bcount = ss->sio.scan_window_size;

	/* If it's a null transfer, return immediatly */
	if (bp->b_bcount == 0)
		goto done;

	s = splbio();

	/*
	 * Place it in the queue of activities for this scanner
	 * at the end (a bit silly because we only have on user..
	 * (but it could fork()))
	 */
	bufq_put(ss->buf_queue, bp);

	/*
	 * Tell the device to get going on the transfer if it's
	 * not doing anything, otherwise just wait for completion
	 * (All a bit silly if we're only allowing 1 open but..)
	 */
	ssstart(ss->sc_periph);

	splx(s);
	return;
done:
	/* Correctly set the buf to indicate a completed xfer */
	bp->b_resid = bp->b_bcount;
	biodone(bp);
}
Esempio n. 4
0
int
cirwrite(dev_t dev, struct uio *uio, int flag)
{
	struct cir_softc *sc;

	sc = device_lookup_private(&cir_cd, CIRUNIT(dev));
	if (sc == NULL)
		return (ENXIO);
	if (!device_is_active(sc->sc_dev))
		return (EIO);
	return (sc->sc_methods->im_write(sc->sc_handle, uio, flag));
}
Esempio n. 5
0
void
fdcstart(struct fdc_softc *fdc)
{

	KASSERT(mutex_owned(&fdc->sc_mtx));

	if (!device_is_active(fdc->sc_dev))
		return;

#ifdef DIAGNOSTIC
	/* only got here if controller's drive queue was inactive; should
	   be in idle state */
	if (fdc->sc_state != DEVIDLE) {
		printf("fdcstart: not idle\n");
		return;
	}
#endif
	(void)fdcintr1(fdc);
}
Esempio n. 6
0
/*
 * Do a read on a device for a user process.
 * Prime scanner at start of read, check uio values, call ssstrategy
 * via physio for the actual transfer.
 */
static int
ssread(dev_t dev, struct uio *uio, int flag)
{
	struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
	int error;

	if (!device_is_active(ss->sc_dev))
		return ENODEV;

	/* if the scanner has not yet been started, do it now */
	if (!(ss->flags & SSF_TRIGGERED)) {
		if (ss->special && ss->special->trigger_scanner) {
			error = (ss->special->trigger_scanner)(ss);
			if (error)
				return (error);
		}
		ss->flags |= SSF_TRIGGERED;
	}

	return physio(ssstrategy, NULL, dev, B_READ, ssminphys, uio);
}
Esempio n. 7
0
int
cirpoll(dev_t dev, int events, struct lwp *l)
{
	struct cir_softc *sc;
	int revents;
	int s;

	sc = device_lookup_private(&cir_cd, CIRUNIT(dev));
	if (sc == NULL)
		return (POLLERR);
	if (!device_is_active(sc->sc_dev))
		return (POLLERR);

	revents = 0;
	s = splir();
	if (events & (POLLIN | POLLRDNORM))
		if (sc->sc_rdframes > 0)
			revents |= events & (POLLIN | POLLRDNORM);

#if 0
	/* How about write? */
	if (events & (POLLOUT | POLLWRNORM))
		if (/* ??? */)
			revents |= events & (POLLOUT | POLLWRNORM);
#endif

	if (revents == 0) {
		if (events & (POLLIN | POLLRDNORM))
			selrecord(l, &sc->sc_rdsel);

#if 0
		if (events & (POLLOUT | POLLWRNORM))
			selrecord(p, &sc->sc_wrsel);
#endif
	}

	splx(s);
	return (revents);
}
Esempio n. 8
0
int
ciropen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct cir_softc *sc;
	int error;

	sc = device_lookup_private(&cir_cd, CIRUNIT(dev));
	if (sc == NULL)
		return (ENXIO);
	if (!device_is_active(sc->sc_dev))
		return (EIO);
	if (sc->sc_open)
		return (EBUSY);

	sc->sc_rdframes = 0;
	if (sc->sc_methods->im_open != NULL) {
		error = sc->sc_methods->im_open(sc->sc_handle, flag, mode,
		    l->l_proc);
		if (error)
			return (error);
	}
	sc->sc_open = 1;
	return (0);
}
Esempio n. 9
0
int
ucomopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	int unit = UCOMUNIT(dev);
	usbd_status err;
	struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
	struct ucom_buffer *ub;
	struct tty *tp;
	int s, i;
	int error;

	if (sc == NULL)
		return (ENXIO);

	if (sc->sc_dying)
		return (EIO);

	if (!device_is_active(sc->sc_dev))
		return (ENXIO);

	tp = sc->sc_tty;

	DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));

	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.
	 */
	while (sc->sc_opening)
		tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0);

	if (sc->sc_dying) {
		splx(s);
		return (EIO);
	}
	sc->sc_opening = 1;

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		if (sc->sc_methods->ucom_open != NULL) {
			error = sc->sc_methods->ucom_open(sc->sc_parent,
							  sc->sc_portno);
			if (error) {
				ucom_cleanup(sc);
				sc->sc_opening = 0;
				wakeup(&sc->sc_opening);
				splx(s);
				return (error);
			}
		}

		ucom_status_change(sc);

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
		t.c_ospeed = TTYDEF_SPEED;
		t.c_cflag = TTYDEF_CFLAG;
		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);
		/* Make sure ucomparam() will do something. */
		tp->t_ospeed = 0;
		(void) ucomparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		/*
		 * 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.  Ditto RTS.
		 */
		ucom_dtr(sc, 1);
		ucom_rts(sc, 1);		

		DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
			 sc->sc_bulkin_no, sc->sc_bulkout_no));

		/* Open the bulk pipes */
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
		if (err) {
			DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
				 USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no,
				 usbd_errstr(err)));
			error = EIO;
			goto fail_0;
		}
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
		if (err) {
			DPRINTF(("%s: open bulk out error (addr %d), err=%s\n",
				 USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no,
				 usbd_errstr(err)));
			error = EIO;
			goto fail_1;
		}

		sc->sc_rx_unblock = 0;
		sc->sc_rx_stopped = 0;
		sc->sc_tx_stopped = 0;

		memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
		memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));

		SIMPLEQ_INIT(&sc->sc_ibuff_empty);
		SIMPLEQ_INIT(&sc->sc_ibuff_full);
		SIMPLEQ_INIT(&sc->sc_obuff_free);
		SIMPLEQ_INIT(&sc->sc_obuff_full);

		/* Allocate input buffers */
		for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
		    ub++) {
			ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
			if (ub->ub_xfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}
			ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
			    sc->sc_ibufsizepad);
			if (ub->ub_data == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) {
				error = EIO;
				goto fail_2;
			}
		}

		for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
		    ub++) {
			ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
			if (ub->ub_xfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}
			ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
			    sc->sc_obufsize);
			if (ub->ub_data == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
		}

	}
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);

	error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
	if (error)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error)
		goto bad;

	return (0);

fail_2:
	usbd_abort_pipe(sc->sc_bulkin_pipe);
	for (i = 0; i < UCOM_IN_BUFFS; i++) {
		if (sc->sc_ibuff[i].ub_xfer != NULL) {
			usbd_free_xfer(sc->sc_ibuff[i].ub_xfer);
			sc->sc_ibuff[i].ub_xfer = NULL;
			sc->sc_ibuff[i].ub_data = NULL;
		}
	}
	usbd_abort_pipe(sc->sc_bulkout_pipe);
	for (i = 0; i < UCOM_OUT_BUFFS; i++) {
		if (sc->sc_obuff[i].ub_xfer != NULL) {
			usbd_free_xfer(sc->sc_obuff[i].ub_xfer);
			sc->sc_obuff[i].ub_xfer = NULL;
			sc->sc_obuff[i].ub_data = NULL;
		}
	}

	usbd_close_pipe(sc->sc_bulkout_pipe);
	sc->sc_bulkout_pipe = NULL;
fail_1:
	usbd_close_pipe(sc->sc_bulkin_pipe);
	sc->sc_bulkin_pipe = NULL;
fail_0:
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);
	return (error);

bad:
	s = spltty();
	CLR(tp->t_state, TS_BUSY);
	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		ucom_cleanup(sc);
	}
	splx(s);

	return (error);
}
int
at91usart_open(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct at91usart_softc *sc;
	struct tty *tp;
	int s;
	int error;

	sc = device_lookup_private(&at91usart_cd, COMUNIT(dev));
	if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK))
		return (ENXIO);

	if (!device_is_active(sc->sc_dev))
		return (ENXIO);

#ifdef KGDB
	/*
	 * If this is the kgdb port, no other use is permitted.
	 */
	if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
		return (EBUSY);
#endif

	tp = sc->sc_tty;

	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 (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		if (sc->enable) {
			if ((*sc->enable)(sc)) {
				splx(s);
				printf("%s: device enable failed\n",
				       device_xname(sc->sc_dev));
				return (EIO);
			}
			sc->enabled = 1;
#if 0
/* XXXXXXXXXXXXXXX */
			com_config(sc);
#endif
		}

		/* reset fifos: */
		AT91PDC_RESET_FIFO(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_rx_fifo, 0);
		AT91PDC_RESET_FIFO(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_tx_fifo, 1);

		/* reset receive */
		at91usart_writereg(sc, US_CR, US_CR_RSTSTA | US_CR_STTTO);

		/* Turn on interrupts. */
		sc->sc_ier = US_CSR_ENDRX|US_CSR_RXBUFF|US_CSR_TIMEOUT|US_CSR_RXBRK;
		at91usart_writereg(sc, US_IER, sc->sc_ier);

		/* enable DMA: */
		at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_RXTEN);

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
/*		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
			t.c_ospeed = usart_cn_sc.sc_ospeed;
			t.c_cflag = usart_cn_sc.sc_cflag;
		} else*/ {
			t.c_ospeed = TTYDEF_SPEED;
			t.c_cflag = TTYDEF_CFLAG;
		}
		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);

		/* Make sure at91usart_param() will do something. */
		tp->t_ospeed = 0;
		(void) at91usart_param(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		/* and unblock. */
		CLR(sc->sc_rx_flags, RX_ANY_BLOCK);

#ifdef COM_DEBUG
		if (at91usart_debug)
			comstatus(sc, "at91usart_open  ");
#endif

	}
	
	splx(s);

	error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
	if (error)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error)
		goto bad;

	return (0);

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

	return (error);
}
Esempio n. 11
0
int
at91dbgu_open(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct at91dbgu_softc *sc;
	struct tty *tp;
	int s, s2;
	int error;

	sc = device_lookup_private(&at91dbgu_cd, COMUNIT(dev));
	if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) ||
		sc->sc_rbuf == NULL)
		return (ENXIO);

	if (!device_is_active(sc->sc_dev))
		return (ENXIO);

#ifdef KGDB
	/*
	 * If this is the kgdb port, no other use is permitted.
	 */
	if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
		return (EBUSY);
#endif

	tp = sc->sc_tty;

	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 (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		s2 = splserial();

		if (sc->enable) {
			if ((*sc->enable)(sc)) {
				splx(s2);
				splx(s);
				printf("%s: device enable failed\n",
				       device_xname(sc->sc_dev));
				return (EIO);
			}
			sc->enabled = 1;
#if 0
/* XXXXXXXXXXXXXXX */
			com_config(sc);
#endif
		}

		/* Turn on interrupts. */
		sc->sc_ier |= DBGU_INT_RXRDY;
		DBGUREG(DBGU_IER) = DBGU_INT_RXRDY;

#if 0
		/* Fetch the current modem control status, needed later. */
		sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr);

		/* Clear PPS capture state on first open. */
		sc->sc_ppsmask = 0;
		sc->ppsparam.mode = 0;
#endif

		splx(s2);

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
			t.c_ospeed = dbgu_cn_sc.sc_ospeed;
			t.c_cflag = dbgu_cn_sc.sc_cflag;
		} else {
			t.c_ospeed = TTYDEF_SPEED;
			t.c_cflag = TTYDEF_CFLAG;
		}
		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);
		/* Make sure at91dbgu_param() will do something. */
		tp->t_ospeed = 0;
		(void) at91dbgu_param(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		s2 = splserial();

		/* Clear the input ring, and unblock. */
		sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
		sc->sc_rbavail = AT91DBGU_RING_SIZE;
		at91dbgu_iflush(sc);
		CLR(sc->sc_rx_flags, RX_ANY_BLOCK);

#ifdef COM_DEBUG
		if (at91dbgu_debug)
			comstatus(sc, "at91dbgu_open  ");
#endif

		splx(s2);
	}
	
	splx(s);

	error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
	if (error)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error)
		goto bad;

	return (0);

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

	return (error);
}
Esempio n. 12
0
int
sscomopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct sscom_softc *sc;
	struct tty *tp;
	int s, s2;
	int error;

	sc = device_lookup_private(&sscom_cd, SSCOMUNIT(dev));
	if (sc == NULL || !ISSET(sc->sc_hwflags, SSCOM_HW_DEV_OK) ||
		sc->sc_rbuf == NULL)
		return ENXIO;

	if (!device_is_active(sc->sc_dev))
		return ENXIO;

#ifdef KGDB
	/*
	 * If this is the kgdb port, no other use is permitted.
	 */
	if (ISSET(sc->sc_hwflags, SSCOM_HW_KGDB))
		return EBUSY;
#endif

	tp = sc->sc_tty;

	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 (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		s2 = splserial();
		SSCOM_LOCK(sc);

		/* Turn on interrupts. */
		sscom_enable_txrxint(sc);

		/* Fetch the current modem control status, needed later. */
		sc->sc_msts = sc->sc_read_modem_status(sc);

#if 0
		/* Clear PPS capture state on first open. */
		sc->sc_ppsmask = 0;
		sc->ppsparam.mode = 0;
#endif

		SSCOM_UNLOCK(sc);
		splx(s2);

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
		if (ISSET(sc->sc_hwflags, SSCOM_HW_CONSOLE)) {
			t.c_ospeed = sscomconsrate;
			t.c_cflag = sscomconscflag;
		} else {
			t.c_ospeed = TTYDEF_SPEED;
			t.c_cflag = TTYDEF_CFLAG;
		}
		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);
		/* Make sure sscomparam() will do something. */
		tp->t_ospeed = 0;
		(void) sscomparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		s2 = splserial();
		SSCOM_LOCK(sc);

		/*
		 * 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.
		 */
		sscom_modem(sc, 1);

		/* Clear the input ring, and unblock. */
		sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
		sc->sc_rbavail = sscom_rbuf_size;
		sscom_iflush(sc);
		CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
		sscom_hwiflow(sc);

		if (sscom_debug)
			sscomstatus(sc, "sscomopen  ");

		SSCOM_UNLOCK(sc);
		splx(s2);
	}
	
	splx(s);

	error = ttyopen(tp, SSCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
	if (error)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error)
		goto bad;

	return 0;

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

	return error;
}
Esempio n. 13
0
int
sacomopen(dev_t dev, int flag, int mode, struct lwp *l)
{
    struct sacom_softc *sc;
    struct tty *tp;
    int s, s2;
    int error;

    sc = device_lookup_private(&sacom_cd, COMUNIT(dev));
    if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) ||
            sc->sc_rbuf == NULL)
        return ENXIO;

    if (!device_is_active(&sc->sc_dev))
        return ENXIO;

    tp = sc->sc_tty;

    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 (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
        struct termios t;

        tp->t_dev = dev;

        s2 = splserial();
        COM_LOCK(sc);

        if (sc->enable) {
            if ((*sc->enable)(sc)) {
                COM_UNLOCK(sc);
                splx(s2);
                splx(s);
                printf("%s: device enable failed\n",
                       sc->sc_dev.dv_xname);
                return EIO;
            }
            sc->enabled = 1;
            sacom_config(sc);
        }

        /* Turn on interrupts. */
        sc->sc_cr3 = CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE;
        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACOM_CR3,
                          sc->sc_cr3);


        COM_UNLOCK(sc);
        splx(s2);

        /*
         * Initialize the termios status to the defaults.  Add in the
         * sticky bits from TIOCSFLAGS.
         */
        t.c_ispeed = 0;
        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
            t.c_ospeed = sacomconsrate;
            t.c_cflag = sacomconscflag;
        } else {
            t.c_ospeed = TTYDEF_SPEED;
            t.c_cflag = TTYDEF_CFLAG;
        }
        if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
            SET(t.c_cflag, CLOCAL);
        if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
            SET(t.c_cflag, CRTSCTS);
        if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
            SET(t.c_cflag, MDMBUF);
        /* Make sure sacomparam() will do something. */
        tp->t_ospeed = 0;
        (void) sacomparam(tp, &t);
        tp->t_iflag = TTYDEF_IFLAG;
        tp->t_oflag = TTYDEF_OFLAG;
        tp->t_lflag = TTYDEF_LFLAG;
        ttychars(tp);
        ttsetwater(tp);

        s2 = splserial();
        COM_LOCK(sc);

        /*
         * 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.
         */
        sacom_modem(sc, 1);

        /* Clear the input ring, and unblock. */
        sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
        sc->sc_rbavail = SACOM_RING_SIZE;
        sacom_iflush(sc);
        CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
        sacom_hwiflow(sc);

#ifdef COM_DEBUG
        if (sacom_debug)
            comstatus(sc, "sacomopen  ");
#endif

        COM_UNLOCK(sc);
        splx(s2);
    }

    splx(s);

    error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
    if (error)
        goto bad;

    error = (*tp->t_linesw->l_open)(dev, tp);
    if (error)
        goto bad;

    return 0;

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

    return error;
}
Esempio n. 14
0
/*  open the device. */
static int
ssopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	int unit;
	u_int ssmode;
	int error;
	struct ss_softc *ss;
	struct scsipi_periph *periph;
	struct scsipi_adapter *adapt;

	unit = SSUNIT(dev);
	ss = device_lookup_private(&ss_cd, unit);
	if (ss == NULL)
		return ENXIO;

	if (!device_is_active(ss->sc_dev))
		return ENODEV;

	ssmode = SSMODE(dev);

	periph = ss->sc_periph;
	adapt = periph->periph_channel->chan_adapter;

	SC_DEBUG(periph, SCSIPI_DB1,
	    ("open: dev=0x%"PRIx64" (unit %d (of %d))\n", dev, unit,
	    ss_cd.cd_ndevs));

	if (periph->periph_flags & PERIPH_OPEN) {
		aprint_error_dev(ss->sc_dev, "already open\n");
		return EBUSY;
	}

	if ((error = scsipi_adapter_addref(adapt)) != 0)
		return error;

	/*
	 * Catch any unit attention errors.
	 *
	 * XS_CTL_IGNORE_MEDIA_CHANGE: when you have an ADF, some scanners
	 * consider paper to be a changeable media
	 *
	 */
	error = scsipi_test_unit_ready(periph,
	    XS_CTL_IGNORE_MEDIA_CHANGE | XS_CTL_IGNORE_ILLEGAL_REQUEST |
	    (ssmode == MODE_CONTROL ? XS_CTL_IGNORE_NOT_READY : 0));
	if (error)
		goto bad;

	periph->periph_flags |= PERIPH_OPEN;	/* unit attn now errors */

	/*
	 * If the mode is 3 (e.g. minor = 3,7,11,15)
	 * then the device has been opened to set defaults
	 * This mode does NOT ALLOW I/O, only ioctls
	 */
	if (ssmode == MODE_CONTROL)
		return 0;

	SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n"));
	return 0;

bad:
	scsipi_adapter_delref(adapt);
	periph->periph_flags &= ~PERIPH_OPEN;
	return error;
}
Esempio n. 15
0
static void
wdc_atapi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
    void *arg)
{
	struct scsipi_adapter *adapt = chan->chan_adapter;
	struct scsipi_periph *periph;
	struct scsipi_xfer *sc_xfer;
	struct wdc_softc *wdc = device_private(adapt->adapt_dev);
	struct atac_softc *atac = &wdc->sc_atac;
	struct ata_xfer *xfer;
	int channel = chan->chan_channel;
	int drive, s;

	switch (req) {
	case ADAPTER_REQ_RUN_XFER:
		sc_xfer = arg;
		periph = sc_xfer->xs_periph;
		drive = periph->periph_target;

		ATADEBUG_PRINT(("wdc_atapi_scsipi_request %s:%d:%d\n",
		    device_xname(atac->atac_dev), channel, drive),
		    DEBUG_XFERS);
		if (!device_is_active(atac->atac_dev)) {
			sc_xfer->error = XS_DRIVER_STUFFUP;
			scsipi_done(sc_xfer);
			return;
		}

		xfer = ata_get_xfer(ATAXF_NOSLEEP);
		if (xfer == NULL) {
			sc_xfer->error = XS_RESOURCE_SHORTAGE;
			scsipi_done(sc_xfer);
			return;
		}

		if (sc_xfer->xs_control & XS_CTL_POLL)
			xfer->c_flags |= C_POLL;
#if NATA_DMA
		if ((atac->atac_channels[channel]->ch_drive[drive].drive_flags &
		    (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) && sc_xfer->datalen > 0)
			xfer->c_flags |= C_DMA;
#endif
#if NATA_DMA && NATA_PIOBM
		else
#endif
#if NATA_PIOBM
		if ((atac->atac_cap & ATAC_CAP_PIOBM) &&
		    sc_xfer->datalen > 0)
			xfer->c_flags |= C_PIOBM;
#endif
		xfer->c_drive = drive;
		xfer->c_flags |= C_ATAPI;
#if NATA_DMA
		if (sc_xfer->cmd->opcode == GPCMD_REPORT_KEY ||
		    sc_xfer->cmd->opcode == GPCMD_SEND_KEY ||
		    sc_xfer->cmd->opcode == GPCMD_READ_DVD_STRUCTURE) {
			/*
			 * DVD authentication commands must always be done in
			 * PIO mode.
			 */
			xfer->c_flags &= ~C_DMA;
		}

		/*
		 * DMA normally can't deal with transfers which are not a
		 * multiple of its databus width. It's a bug to request odd
		 * length transfers for ATAPI.
		 *
		 * Some devices also can't cope with unaligned DMA xfers
		 * either. Also some devices seem to not handle DMA xfers of
		 * less than 4 bytes.
		 *
		 * By enforcing at least 4 byte aligned offset and length for
		 * DMA, we might use PIO where DMA could be allowed but better
		 * safe than sorry as recent problems proved.
		 *
		 * Offending structures that are thus done by PIO instead of
		 * DMA are normally small structures since all bulkdata is
		 * aligned. But as the request may come from userland, we have
		 * to protect against it anyway.
		 *
		 * XXX check for the 32 bit wide flag?
		 */

		if (((uintptr_t) sc_xfer->data) & 0x03)
			xfer->c_flags &= ~C_DMA;
		if ((sc_xfer->datalen < 4) || (sc_xfer->datalen & 0x03))
			xfer->c_flags &= ~C_DMA;
#endif	/* NATA_DMA */

		xfer->c_cmd = sc_xfer;
		xfer->c_databuf = sc_xfer->data;
		xfer->c_bcount = sc_xfer->datalen;
		xfer->c_start = wdc_atapi_start;
		xfer->c_intr = wdc_atapi_intr;
		xfer->c_kill_xfer = wdc_atapi_kill_xfer;
		xfer->c_dscpoll = 0;
		s = splbio();
		ata_exec_xfer(atac->atac_channels[channel], xfer);
#ifdef DIAGNOSTIC
		if ((sc_xfer->xs_control & XS_CTL_POLL) != 0 &&
		    (sc_xfer->xs_status & XS_STS_DONE) == 0)
			panic("wdc_atapi_scsipi_request: polled command "
			    "not done");
#endif
		splx(s);
		return;

	default:
		/* Not supported, nothing to do. */
		;
	}
}