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); }
/* * 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); }
/* * 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); }
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)); }
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); }
/* * 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); }
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); }
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); }
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); }
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); }
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; }
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; }
/* 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; }
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. */ ; } }