Annotation of src/sys/dev/usb/ucom.c, Revision 1.118.8.1
1.118.8.1! snj 1: /* $NetBSD: ucom.c,v 1.118 2016/12/14 15:11:29 skrll Exp $ */
1.1 augustss 2:
3: /*
1.22 augustss 4: * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
1.1 augustss 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
1.23 augustss 8: * by Lennart Augustsson (lennart@augustsson.net) at
1.1 augustss 9: * Carlstedt Research & Technology.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30: * POSSIBILITY OF SUCH DAMAGE.
31: */
1.22 augustss 32: /*
33: * This code is very heavily based on the 16550 driver, com.c.
34: */
1.40 lukem 35:
36: #include <sys/cdefs.h>
1.118.8.1! snj 37: __KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.118 2016/12/14 15:11:29 skrll Exp $");
1.115 skrll 38:
39: #ifdef _KERNEL_OPT
40: #include "opt_usb.h"
41: #endif
1.1 augustss 42:
43: #include <sys/param.h>
44: #include <sys/systm.h>
45: #include <sys/kernel.h>
46: #include <sys/ioctl.h>
1.3 augustss 47: #include <sys/conf.h>
1.1 augustss 48: #include <sys/tty.h>
49: #include <sys/file.h>
50: #include <sys/select.h>
51: #include <sys/proc.h>
52: #include <sys/vnode.h>
1.12 augustss 53: #include <sys/device.h>
1.1 augustss 54: #include <sys/poll.h>
1.82 martin 55: #include <sys/queue.h>
1.63 elad 56: #include <sys/kauth.h>
1.111 skrll 57: #include <sys/sysctl.h>
1.106 gdt 58: #include <sys/timepps.h>
1.109 riastrad 59: #include <sys/rndsource.h>
1.1 augustss 60:
61: #include <dev/usb/usb.h>
62:
63: #include <dev/usb/usbdi.h>
64: #include <dev/usb/usbdi_util.h>
65: #include <dev/usb/usbdevs.h>
66: #include <dev/usb/usb_quirks.h>
1.111 skrll 67: #include <dev/usb/usbhist.h>
1.1 augustss 68:
1.12 augustss 69: #include <dev/usb/ucomvar.h>
70:
1.13 augustss 71: #include "ucom.h"
72:
1.53 drochner 73: #include "locators.h"
74:
1.13 augustss 75: #if NUCOM > 0
76:
1.111 skrll 77: #ifdef USB_DEBUG
78: #ifndef UCOM_DEBUG
79: #define ucomdebug 0
80: #else
1.12 augustss 81: int ucomdebug = 0;
1.111 skrll 82:
83: SYSCTL_SETUP(sysctl_hw_ucom_setup, "sysctl hw.ucom setup")
84: {
1.117 skrll 85: int err;
86: const struct sysctlnode *rnode;
87: const struct sysctlnode *cnode;
88:
89: err = sysctl_createv(clog, 0, NULL, &rnode,
90: CTLFLAG_PERMANENT, CTLTYPE_NODE, "ucom",
91: SYSCTL_DESCR("ucom global controls"),
92: NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
93:
94: if (err)
95: goto fail;
96:
97: /* control debugging printfs */
98: err = sysctl_createv(clog, 0, &rnode, &cnode,
99: CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
100: "debug", SYSCTL_DESCR("Enable debugging output"),
101: NULL, 0, &ucomdebug, sizeof(ucomdebug), CTL_CREATE, CTL_EOL);
102: if (err)
103: goto fail;
1.111 skrll 104:
1.117 skrll 105: return;
1.111 skrll 106: fail:
1.117 skrll 107: aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
1.111 skrll 108: }
109:
110: #endif /* UCOM_DEBUG */
111: #endif /* USB_DEBUG */
112:
113: #define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(ucomdebug,1,FMT,A,B,C,D)
114: #define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(ucomdebug,N,FMT,A,B,C,D)
115: #define UCOMHIST_FUNC() USBHIST_FUNC()
116: #define UCOMHIST_CALLED(name) USBHIST_CALLED(ucomdebug)
1.12 augustss 117:
1.108 christos 118: #define UCOMCALLUNIT_MASK TTCALLUNIT_MASK
119: #define UCOMUNIT_MASK TTUNIT_MASK
120: #define UCOMDIALOUT_MASK TTDIALOUT_MASK
121:
122: #define UCOMCALLUNIT(x) TTCALLUNIT(x)
123: #define UCOMUNIT(x) TTUNIT(x)
124: #define UCOMDIALOUT(x) TTDIALOUT(x)
1.12 augustss 125:
1.82 martin 126: /*
127: * XXX: We can submit multiple input/output buffers to the usb stack
128: * to improve throughput, but the usb stack is too lame to deal with this
129: * in a number of places.
130: */
131: #define UCOM_IN_BUFFS 1
132: #define UCOM_OUT_BUFFS 1
133:
134: struct ucom_buffer {
135: SIMPLEQ_ENTRY(ucom_buffer) ub_link;
1.111 skrll 136: struct usbd_xfer *ub_xfer;
1.82 martin 137: u_char *ub_data;
138: u_int ub_len;
139: u_int ub_index;
140: };
141:
1.1 augustss 142: struct ucom_softc {
1.85 dyoung 143: device_t sc_dev; /* base device */
1.12 augustss 144:
1.111 skrll 145: struct usbd_device * sc_udev; /* USB device */
146: struct usbd_interface * sc_iface; /* data interface */
1.12 augustss 147:
148: int sc_bulkin_no; /* bulk in endpoint address */
1.115 skrll 149: struct usbd_pipe * sc_bulkin_pipe;/* bulk in pipe */
1.19 augustss 150: u_int sc_ibufsize; /* read buffer size */
1.22 augustss 151: u_int sc_ibufsizepad; /* read buffer size padded */
1.82 martin 152: struct ucom_buffer sc_ibuff[UCOM_IN_BUFFS];
153: SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_empty;
154: SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_full;
1.12 augustss 155:
156: int sc_bulkout_no; /* bulk out endpoint address */
1.111 skrll 157: struct usbd_pipe * sc_bulkout_pipe;/* bulk out pipe */
1.19 augustss 158: u_int sc_obufsize; /* write buffer size */
1.82 martin 159: u_int sc_opkthdrlen; /* header length of */
160: struct ucom_buffer sc_obuff[UCOM_OUT_BUFFS];
161: SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_free;
162: SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_full;
163:
164: void *sc_si;
1.12 augustss 165:
1.90 jakllsch 166: const struct ucom_methods *sc_methods;
1.12 augustss 167: void *sc_parent;
168: int sc_portno;
169:
170: struct tty *sc_tty; /* our tty */
171: u_char sc_lsr;
172: u_char sc_msr;
173: u_char sc_mcr;
1.82 martin 174: volatile u_char sc_rx_stopped;
175: u_char sc_rx_unblock;
1.12 augustss 176: u_char sc_tx_stopped;
177: int sc_swflags;
178:
1.115 skrll 179: enum ucom_state {
180: UCOM_DEAD,
181: UCOM_ATTACHED,
182: UCOM_OPENING,
183: UCOM_CLOSING,
184: UCOM_OPEN
185: } sc_state;
1.17 augustss 186: int sc_refcnt;
1.115 skrll 187: bool sc_dying; /* disconnecting */
1.31 explorer 188:
1.106 gdt 189: struct pps_state sc_pps_state; /* pps state */
190:
1.111 skrll 191: krndsource_t sc_rndsource; /* random source */
192:
193: kmutex_t sc_lock;
1.115 skrll 194: kcondvar_t sc_statecv;
1.111 skrll 195: kcondvar_t sc_detachcv;
1.1 augustss 196: };
197:
1.44 gehenna 198: dev_type_open(ucomopen);
199: dev_type_close(ucomclose);
200: dev_type_read(ucomread);
201: dev_type_write(ucomwrite);
202: dev_type_ioctl(ucomioctl);
203: dev_type_stop(ucomstop);
204: dev_type_tty(ucomtty);
205: dev_type_poll(ucompoll);
206:
207: const struct cdevsw ucom_cdevsw = {
1.103 dholland 208: .d_open = ucomopen,
209: .d_close = ucomclose,
210: .d_read = ucomread,
211: .d_write = ucomwrite,
212: .d_ioctl = ucomioctl,
213: .d_stop = ucomstop,
214: .d_tty = ucomtty,
215: .d_poll = ucompoll,
216: .d_mmap = nommap,
217: .d_kqfilter = ttykqfilter,
1.105 dholland 218: .d_discard = nodiscard,
1.111 skrll 219: .d_flag = D_TTY | D_MPSAFE
1.44 gehenna 220: };
1.12 augustss 221:
1.82 martin 222: static void ucom_cleanup(struct ucom_softc *);
223: static int ucomparam(struct tty *, struct termios *);
224: static int ucomhwiflow(struct tty *, int);
225: static void ucomstart(struct tty *);
226: static void ucom_shutdown(struct ucom_softc *);
227: static int ucom_do_ioctl(struct ucom_softc *, u_long, void *,
1.60 christos 228: int, struct lwp *);
1.82 martin 229: static void ucom_dtr(struct ucom_softc *, int);
230: static void ucom_rts(struct ucom_softc *, int);
231: static void ucom_break(struct ucom_softc *, int);
232: static void tiocm_to_ucom(struct ucom_softc *, u_long, int);
233: static int ucom_to_tiocm(struct ucom_softc *);
234:
1.111 skrll 235: static void ucomreadcb(struct usbd_xfer *, void *, usbd_status);
1.82 martin 236: static void ucom_submit_write(struct ucom_softc *, struct ucom_buffer *);
237: static void ucom_write_status(struct ucom_softc *, struct ucom_buffer *,
1.115 skrll 238: usbd_status);
1.82 martin 239:
1.111 skrll 240: static void ucomwritecb(struct usbd_xfer *, void *, usbd_status);
1.82 martin 241: static void ucom_read_complete(struct ucom_softc *);
1.115 skrll 242: static int ucomsubmitread(struct ucom_softc *, struct ucom_buffer *);
1.82 martin 243: static void ucom_softintr(void *);
1.1 augustss 244:
1.85 dyoung 245: int ucom_match(device_t, cfdata_t, void *);
246: void ucom_attach(device_t, device_t, void *);
247: int ucom_detach(device_t, int);
248: int ucom_activate(device_t, enum devact);
249: extern struct cfdriver ucom_cd;
250: CFATTACH_DECL_NEW(ucom, sizeof(struct ucom_softc), ucom_match, ucom_attach,
251: ucom_detach, ucom_activate);
1.1 augustss 252:
1.85 dyoung 253: int
254: ucom_match(device_t parent, cfdata_t match, void *aux)
1.1 augustss 255: {
1.111 skrll 256: return 1;
1.1 augustss 257: }
258:
1.85 dyoung 259: void
260: ucom_attach(device_t parent, device_t self, void *aux)
1.1 augustss 261: {
1.77 cube 262: struct ucom_softc *sc = device_private(self);
1.111 skrll 263: struct ucom_attach_args *ucaa = aux;
1.12 augustss 264:
1.111 skrll 265: UCOMHIST_FUNC(); UCOMHIST_CALLED();
266:
267: if (ucaa->ucaa_info != NULL)
268: aprint_normal(": %s", ucaa->ucaa_info);
1.83 pooka 269: aprint_normal("\n");
1.12 augustss 270:
1.111 skrll 271: prop_dictionary_set_int32(device_properties(self), "port",
272: ucaa->ucaa_portno);
1.110 joerg 273:
1.77 cube 274: sc->sc_dev = self;
1.111 skrll 275: sc->sc_udev = ucaa->ucaa_device;
276: sc->sc_iface = ucaa->ucaa_iface;
277: sc->sc_bulkout_no = ucaa->ucaa_bulkout;
278: sc->sc_bulkin_no = ucaa->ucaa_bulkin;
279: sc->sc_ibufsize = ucaa->ucaa_ibufsize;
280: sc->sc_ibufsizepad = ucaa->ucaa_ibufsizepad;
281: sc->sc_obufsize = ucaa->ucaa_obufsize;
282: sc->sc_opkthdrlen = ucaa->ucaa_opkthdrlen;
283: sc->sc_methods = ucaa->ucaa_methods;
284: sc->sc_parent = ucaa->ucaa_arg;
285: sc->sc_portno = ucaa->ucaa_portno;
1.12 augustss 286:
1.82 martin 287: sc->sc_lsr = 0;
288: sc->sc_msr = 0;
289: sc->sc_mcr = 0;
290: sc->sc_tx_stopped = 0;
291: sc->sc_swflags = 0;
292: sc->sc_refcnt = 0;
1.115 skrll 293: sc->sc_dying = false;
294: sc->sc_state = UCOM_DEAD;
1.82 martin 295:
1.111 skrll 296: sc->sc_si = softint_establish(SOFTINT_USB, ucom_softintr, sc);
297: mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
1.115 skrll 298: cv_init(&sc->sc_statecv, "ucomstate");
1.111 skrll 299: cv_init(&sc->sc_detachcv, "ucomdtch");
300:
301: SIMPLEQ_INIT(&sc->sc_ibuff_empty);
302: SIMPLEQ_INIT(&sc->sc_ibuff_full);
303: SIMPLEQ_INIT(&sc->sc_obuff_free);
304: SIMPLEQ_INIT(&sc->sc_obuff_full);
305:
306: memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
307: memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));
308:
1.118.8.1! snj 309: DPRINTF("open pipes in=%jd out=%jd",
! 310: sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0);
1.111 skrll 311:
312: struct ucom_buffer *ub;
313: usbd_status err;
314: int error;
315:
316: /* Open the bulk pipes */
317: err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
318: USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
319: if (err) {
1.118.8.1! snj 320: DPRINTF("open bulk in error (addr %jd), err=%jd",
1.111 skrll 321: sc->sc_bulkin_no, err, 0, 0);
322: error = EIO;
323: goto fail_0;
324: }
1.115 skrll 325: /* Allocate input buffers */
326: for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
327: ub++) {
328: error = usbd_create_xfer(sc->sc_bulkin_pipe,
329: sc->sc_ibufsizepad, USBD_SHORT_XFER_OK, 0,
330: &ub->ub_xfer);
331: if (error)
332: goto fail_1;
333: ub->ub_data = usbd_get_buffer(ub->ub_xfer);
334: }
335:
1.111 skrll 336: err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
337: USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
338: if (err) {
1.118.8.1! snj 339: DPRINTF("open bulk out error (addr %jd), err=%jd",
1.111 skrll 340: sc->sc_bulkout_no, err, 0, 0);
341: error = EIO;
342: goto fail_1;
343: }
344: for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
345: ub++) {
1.115 skrll 346: error = usbd_create_xfer(sc->sc_bulkout_pipe,
347: sc->sc_obufsize, 0, 0, &ub->ub_xfer);
1.111 skrll 348: if (error)
349: goto fail_2;
350: ub->ub_data = usbd_get_buffer(ub->ub_xfer);
351: SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
352: }
1.82 martin 353:
1.115 skrll 354: struct tty *tp = tty_alloc();
1.12 augustss 355: tp->t_oproc = ucomstart;
356: tp->t_param = ucomparam;
1.82 martin 357: tp->t_hwiflow = ucomhwiflow;
1.12 augustss 358: sc->sc_tty = tp;
359:
1.118.8.1! snj 360: DPRINTF("tty_attach %#jx", (uintptr_t)tp, 0, 0, 0);
1.12 augustss 361: tty_attach(tp);
362:
1.85 dyoung 363: rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev),
1.107 tls 364: RND_TYPE_TTY, RND_FLAG_DEFAULT);
1.31 explorer 365:
1.74 smb 366: if (!pmf_device_register(self, NULL, NULL))
367: aprint_error_dev(self, "couldn't establish power handler\n");
1.115 skrll 368:
369: sc->sc_state = UCOM_ATTACHED;
370:
1.85 dyoung 371: return;
1.111 skrll 372:
373: fail_2:
1.115 skrll 374: for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
1.111 skrll 375: ub++) {
376: if (ub->ub_xfer)
377: usbd_destroy_xfer(ub->ub_xfer);
378: }
1.115 skrll 379:
380: usbd_close_pipe(sc->sc_bulkout_pipe);
381:
382: fail_1:
383: for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
1.111 skrll 384: ub++) {
385: if (ub->ub_xfer)
386: usbd_destroy_xfer(ub->ub_xfer);
387: }
388: usbd_close_pipe(sc->sc_bulkin_pipe);
389:
390: fail_0:
391: aprint_error_dev(self, "attach failed, error=%d\n", error);
392:
393: return;
1.12 augustss 394: }
395:
1.85 dyoung 396: int
397: ucom_detach(device_t self, int flags)
1.12 augustss 398: {
1.77 cube 399: struct ucom_softc *sc = device_private(self);
1.36 augustss 400: struct tty *tp = sc->sc_tty;
1.12 augustss 401: int maj, mn;
1.111 skrll 402: int i;
403:
404: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1.12 augustss 405:
1.118.8.1! snj 406: DPRINTF("sc=%#jx flags=%jd tp=%#jx", (uintptr_t)sc, flags,
! 407: (uintptr_t)tp, 0);
! 408: DPRINTF("... pipe=%jd,%jd", sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0);
1.12 augustss 409:
1.111 skrll 410: mutex_enter(&sc->sc_lock);
1.115 skrll 411: sc->sc_dying = true;
1.111 skrll 412: mutex_exit(&sc->sc_lock);
413:
1.74 smb 414: pmf_device_deregister(self);
1.12 augustss 415:
1.33 augustss 416: if (sc->sc_bulkin_pipe != NULL)
417: usbd_abort_pipe(sc->sc_bulkin_pipe);
418: if (sc->sc_bulkout_pipe != NULL)
419: usbd_abort_pipe(sc->sc_bulkout_pipe);
1.12 augustss 420:
1.111 skrll 421: mutex_enter(&sc->sc_lock);
1.115 skrll 422:
423: /* wait for open/close to finish */
424: while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) {
425: int error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock);
426:
427: if (error) {
428: mutex_exit(&sc->sc_lock);
429: return error;
430: }
431: }
432:
433: sc->sc_refcnt--;
1.111 skrll 434: while (sc->sc_refcnt > 0) {
1.35 augustss 435: /* Wake up anyone waiting */
1.36 augustss 436: if (tp != NULL) {
1.71 ad 437: mutex_spin_enter(&tty_lock);
1.36 augustss 438: CLR(tp->t_state, TS_CARR_ON);
439: CLR(tp->t_cflag, CLOCAL | MDMBUF);
440: ttyflush(tp, FREAD|FWRITE);
1.71 ad 441: mutex_spin_exit(&tty_lock);
1.36 augustss 442: }
1.17 augustss 443: /* Wait for processes to go away. */
1.115 skrll 444: if (cv_timedwait(&sc->sc_detachcv, &sc->sc_lock, hz * 60)) {
445: printf("%s: %s didn't detach\n", __func__,
446: device_xname(sc->sc_dev));
447: }
1.17 augustss 448: }
1.82 martin 449:
450: softint_disestablish(sc->sc_si);
1.111 skrll 451: mutex_exit(&sc->sc_lock);
1.12 augustss 452:
453: /* locate the major number */
1.44 gehenna 454: maj = cdevsw_lookup_major(&ucom_cdevsw);
1.12 augustss 455:
456: /* Nuke the vnodes for any open instances. */
1.62 thorpej 457: mn = device_unit(self);
1.118.8.1! snj 458: DPRINTF("maj=%jd mn=%jd", maj, mn, 0, 0);
1.12 augustss 459: vdevgone(maj, mn, mn, VCHR);
1.22 augustss 460: vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR);
461: vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR);
1.12 augustss 462:
463: /* Detach and free the tty. */
1.36 augustss 464: if (tp != NULL) {
465: tty_detach(tp);
1.87 rmind 466: tty_free(tp);
1.33 augustss 467: sc->sc_tty = NULL;
468: }
1.12 augustss 469:
1.82 martin 470: for (i = 0; i < UCOM_IN_BUFFS; i++) {
471: if (sc->sc_ibuff[i].ub_xfer != NULL)
1.111 skrll 472: usbd_destroy_xfer(sc->sc_ibuff[i].ub_xfer);
1.82 martin 473: }
474:
475: for (i = 0; i < UCOM_OUT_BUFFS; i++) {
476: if (sc->sc_obuff[i].ub_xfer != NULL)
1.111 skrll 477: usbd_destroy_xfer(sc->sc_obuff[i].ub_xfer);
478: }
479:
480: if (sc->sc_bulkin_pipe != NULL) {
481: usbd_close_pipe(sc->sc_bulkin_pipe);
482: sc->sc_bulkin_pipe = NULL;
483: }
484:
485: if (sc->sc_bulkout_pipe != NULL) {
486: usbd_close_pipe(sc->sc_bulkout_pipe);
487: sc->sc_bulkout_pipe = NULL;
1.82 martin 488: }
489:
1.31 explorer 490: /* Detach the random source */
491: rnd_detach_source(&sc->sc_rndsource);
492:
1.111 skrll 493: mutex_destroy(&sc->sc_lock);
1.115 skrll 494: cv_destroy(&sc->sc_statecv);
1.111 skrll 495: cv_destroy(&sc->sc_detachcv);
496:
497: return 0;
1.12 augustss 498: }
499:
500: int
1.85 dyoung 501: ucom_activate(device_t self, enum devact act)
1.12 augustss 502: {
1.77 cube 503: struct ucom_softc *sc = device_private(self);
1.12 augustss 504:
1.111 skrll 505: UCOMHIST_FUNC(); UCOMHIST_CALLED();
506:
1.118.8.1! snj 507: DPRINTFN(5, "%jd", act, 0, 0, 0);
1.34 augustss 508:
1.12 augustss 509: switch (act) {
510: case DVACT_DEACTIVATE:
1.111 skrll 511: mutex_enter(&sc->sc_lock);
1.115 skrll 512: sc->sc_dying = true;
1.111 skrll 513: mutex_exit(&sc->sc_lock);
1.81 dyoung 514: return 0;
515: default:
516: return EOPNOTSUPP;
1.12 augustss 517: }
518: }
519:
520: void
1.24 augustss 521: ucom_shutdown(struct ucom_softc *sc)
1.12 augustss 522: {
523: struct tty *tp = sc->sc_tty;
524:
1.111 skrll 525: UCOMHIST_FUNC(); UCOMHIST_CALLED();
526:
1.12 augustss 527: /*
528: * Hang up if necessary. Wait a bit, so the other side has time to
529: * notice even if we immediately open the port again.
530: */
531: if (ISSET(tp->t_cflag, HUPCL)) {
532: ucom_dtr(sc, 0);
1.111 skrll 533: /* XXX will only timeout */
1.116 skrll 534: (void) kpause(ttclos, false, hz, NULL);
1.12 augustss 535: }
536: }
537:
538: int
1.69 christos 539: ucomopen(dev_t dev, int flag, int mode, struct lwp *l)
1.12 augustss 540: {
1.115 skrll 541: const int unit = UCOMUNIT(dev);
542: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
543: int error = 0;
1.43 augustss 544:
1.111 skrll 545: UCOMHIST_FUNC(); UCOMHIST_CALLED();
546:
1.12 augustss 547: if (sc == NULL)
1.111 skrll 548: return ENXIO;
1.12 augustss 549:
1.111 skrll 550: mutex_enter(&sc->sc_lock);
551: if (sc->sc_dying) {
1.115 skrll 552: DPRINTF("... dying", 0, 0, 0, 0);
1.111 skrll 553: mutex_exit(&sc->sc_lock);
554: return EIO;
555: }
1.12 augustss 556:
1.111 skrll 557: if (!device_is_active(sc->sc_dev)) {
558: mutex_exit(&sc->sc_lock);
559: return ENXIO;
560: }
1.12 augustss 561:
1.115 skrll 562: struct tty *tp = sc->sc_tty;
1.12 augustss 563:
1.118.8.1! snj 564: DPRINTF("unit=%jd, tp=%#jx", unit, (uintptr_t)tp, 0, 0);
1.12 augustss 565:
1.111 skrll 566: if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) {
567: mutex_exit(&sc->sc_lock);
568: return EBUSY;
569: }
1.12 augustss 570:
571: /*
1.113 mlelstv 572: * Wait while the device is initialized by the
573: * first opener or cleaned up by the last closer.
1.12 augustss 574: */
1.115 skrll 575: while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) {
576: error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock);
577:
578: if (sc->sc_dying)
579: error = EIO;
1.17 augustss 580:
1.111 skrll 581: if (error) {
582: mutex_exit(&sc->sc_lock);
583: return error;
584: }
1.17 augustss 585: }
1.115 skrll 586: enum ucom_state state = sc->sc_state;
1.111 skrll 587:
1.115 skrll 588: KASSERTMSG(state == UCOM_OPEN || state == UCOM_ATTACHED,
589: "state is %d", state);
1.43 augustss 590:
1.115 skrll 591: bool cleanup = false;
592: /* If this is the first open then perform the initialisation */
1.12 augustss 593: if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
1.115 skrll 594: KASSERT(state == UCOM_ATTACHED);
1.12 augustss 595: tp->t_dev = dev;
1.115 skrll 596: cleanup = true;
597: sc->sc_state = UCOM_OPENING;
1.12 augustss 598:
1.115 skrll 599: mutex_exit(&sc->sc_lock);
1.22 augustss 600: if (sc->sc_methods->ucom_open != NULL) {
601: error = sc->sc_methods->ucom_open(sc->sc_parent,
1.115 skrll 602: sc->sc_portno);
1.22 augustss 603: if (error) {
1.115 skrll 604: goto fail_2;
1.22 augustss 605: }
606: }
607:
1.12 augustss 608: ucom_status_change(sc);
609:
1.106 gdt 610: /* Clear PPS capture state on first open. */
611: mutex_spin_enter(&timecounter_lock);
612: memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
613: sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
614: pps_init(&sc->sc_pps_state);
615: mutex_spin_exit(&timecounter_lock);
616:
1.12 augustss 617: /*
618: * Initialize the termios status to the defaults. Add in the
619: * sticky bits from TIOCSFLAGS.
620: */
1.115 skrll 621: struct termios t;
622:
1.12 augustss 623: t.c_ispeed = 0;
624: t.c_ospeed = TTYDEF_SPEED;
625: t.c_cflag = TTYDEF_CFLAG;
626: if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
627: SET(t.c_cflag, CLOCAL);
628: if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
629: SET(t.c_cflag, CRTSCTS);
630: if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
631: SET(t.c_cflag, MDMBUF);
632: /* Make sure ucomparam() will do something. */
633: tp->t_ospeed = 0;
634: (void) ucomparam(tp, &t);
635: tp->t_iflag = TTYDEF_IFLAG;
636: tp->t_oflag = TTYDEF_OFLAG;
637: tp->t_lflag = TTYDEF_LFLAG;
638: ttychars(tp);
639: ttsetwater(tp);
640:
641: /*
642: * Turn on DTR. We must always do this, even if carrier is not
643: * present, because otherwise we'd have to use TIOCSDTR
644: * immediately after setting CLOCAL, which applications do not
645: * expect. We always assert DTR while the device is open
1.64 gson 646: * unless explicitly requested to deassert it. Ditto RTS.
1.12 augustss 647: */
648: ucom_dtr(sc, 1);
1.102 jakllsch 649: ucom_rts(sc, 1);
1.12 augustss 650:
1.115 skrll 651: mutex_enter(&sc->sc_lock);
652: if (sc->sc_dying) {
653: DPRINTF("... dying", 0, 0, 0, 0);
654: error = EIO;
655: goto fail_1;
656: }
657:
1.82 martin 658: sc->sc_rx_unblock = 0;
659: sc->sc_rx_stopped = 0;
660: sc->sc_tx_stopped = 0;
661:
1.115 skrll 662: for (size_t i = 0; i < UCOM_IN_BUFFS; i++) {
663: struct ucom_buffer *ub = &sc->sc_ibuff[i];
664: error = ucomsubmitread(sc, ub);
665: if (error) {
666: mutex_exit(&sc->sc_lock);
1.82 martin 667: goto fail_2;
668: }
1.28 toshii 669: }
1.12 augustss 670: }
1.115 skrll 671: sc->sc_state = UCOM_OPEN;
672: cv_signal(&sc->sc_statecv);
1.111 skrll 673: mutex_exit(&sc->sc_lock);
1.12 augustss 674:
1.118.8.1! snj 675: DPRINTF("unit=%jd, tp=%#jx dialout %jd nonblock %jd", unit,
! 676: (uintptr_t)tp, !!UCOMDIALOUT(dev), !!ISSET(flag, O_NONBLOCK));
1.12 augustss 677: error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
678: if (error)
679: goto bad;
680:
1.32 eeh 681: error = (*tp->t_linesw->l_open)(dev, tp);
1.12 augustss 682: if (error)
683: goto bad;
684:
1.111 skrll 685: return 0;
1.26 toshii 686:
1.115 skrll 687: bad:
688: cleanup = !ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0;
689:
1.26 toshii 690: fail_2:
1.115 skrll 691: if (cleanup) {
1.12 augustss 692: /*
1.115 skrll 693: * We failed to open the device, and nobody else had
694: * it opened. Clean up the state as appropriate.
1.12 augustss 695: */
696: ucom_cleanup(sc);
697: }
1.115 skrll 698:
699: mutex_enter(&sc->sc_lock);
700:
701: fail_1:
702: sc->sc_state = state;
703: cv_signal(&sc->sc_statecv);
704: mutex_exit(&sc->sc_lock);
1.12 augustss 705:
1.111 skrll 706: return error;
1.12 augustss 707: }
708:
709: int
1.69 christos 710: ucomclose(dev_t dev, int flag, int mode, struct lwp *l)
1.12 augustss 711: {
1.115 skrll 712: const int unit = UCOMUNIT(dev);
713: struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
714: int error = 0;
1.12 augustss 715:
1.111 skrll 716: UCOMHIST_FUNC(); UCOMHIST_CALLED();
717:
1.118.8.1! snj 718: DPRINTF("unit=%jd", UCOMUNIT(dev), 0, 0, 0);
1.101 jakllsch 719:
720: if (sc == NULL)
721: return 0;
722:
1.111 skrll 723: mutex_enter(&sc->sc_lock);
1.115 skrll 724: if (sc->sc_dying) {
725: DPRINTF("... dying", 0, 0, 0, 0);
726: mutex_exit(&sc->sc_lock);
727: return ENXIO;
728: }
729:
730: /*
731: * Wait until any opens/closes have finished
732: */
733: while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) {
734: error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock);
735:
736: if (sc->sc_dying)
737: error = EIO;
738:
739: if (error) {
740: mutex_exit(&sc->sc_lock);
741: return error;
742: }
743: }
1.101 jakllsch 744:
1.115 skrll 745: struct tty *tp = sc->sc_tty;
1.113 mlelstv 746:
1.111 skrll 747: if (!ISSET(tp->t_state, TS_ISOPEN)) {
1.115 skrll 748: KASSERT(sc->sc_state == UCOM_ATTACHED);
749: mutex_exit(&sc->sc_lock);
750: return 0;
1.111 skrll 751: }
1.12 augustss 752:
1.115 skrll 753: KASSERT(sc->sc_state == UCOM_OPEN);
754: sc->sc_state = UCOM_CLOSING;
755: mutex_exit(&sc->sc_lock);
1.17 augustss 756:
1.32 eeh 757: (*tp->t_linesw->l_close)(tp, flag);
1.12 augustss 758: ttyclose(tp);
759:
1.115 skrll 760: /* state when we're done - default to open */
761: enum ucom_state state = UCOM_OPEN;
1.12 augustss 762: if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
763: /*
764: * Although we got a last close, the device may still be in
765: * use; e.g. if this was the dialout node, and there are still
766: * processes waiting for carrier on the non-dialout node.
767: */
768: ucom_cleanup(sc);
1.115 skrll 769: if (sc->sc_methods->ucom_close != NULL)
770: sc->sc_methods->ucom_close(sc->sc_parent,
771: sc->sc_portno);
772: state = UCOM_ATTACHED;
1.12 augustss 773: }
774:
1.115 skrll 775: mutex_enter(&sc->sc_lock);
776: sc->sc_state = state;
777: cv_signal(&sc->sc_statecv);
1.111 skrll 778: mutex_exit(&sc->sc_lock);
779:
1.115 skrll 780: return error;
1.12 augustss 781: }
1.43 augustss 782:
1.12 augustss 783: int
1.24 augustss 784: ucomread(dev_t dev, struct uio *uio, int flag)
1.12 augustss 785: {
1.115 skrll 786: const int unit = UCOMUNIT(dev);
787: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.17 augustss 788: int error;
1.12 augustss 789:
1.111 skrll 790: UCOMHIST_FUNC(); UCOMHIST_CALLED();
791:
792: if (sc == NULL)
793: return EIO;
794:
795: mutex_enter(&sc->sc_lock);
796: if (sc->sc_dying) {
1.115 skrll 797: DPRINTF("... dying", 0, 0, 0, 0);
1.111 skrll 798: mutex_exit(&sc->sc_lock);
799: return EIO;
800: }
1.43 augustss 801:
1.115 skrll 802: struct tty *tp = sc->sc_tty;
1.101 jakllsch 803:
1.17 augustss 804: sc->sc_refcnt++;
1.111 skrll 805: mutex_exit(&sc->sc_lock);
1.115 skrll 806:
1.32 eeh 807: error = ((*tp->t_linesw->l_read)(tp, uio, flag));
1.115 skrll 808:
1.111 skrll 809: mutex_enter(&sc->sc_lock);
1.17 augustss 810: if (--sc->sc_refcnt < 0)
1.115 skrll 811: cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj 812: DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0);
1.111 skrll 813: mutex_exit(&sc->sc_lock);
814:
815: return error;
1.12 augustss 816: }
1.43 augustss 817:
1.12 augustss 818: int
1.24 augustss 819: ucomwrite(dev_t dev, struct uio *uio, int flag)
1.12 augustss 820: {
1.115 skrll 821: const int unit = UCOMUNIT(dev);
822: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.17 augustss 823: int error;
1.12 augustss 824:
1.115 skrll 825: UCOMHIST_FUNC(); UCOMHIST_CALLED();
826:
1.111 skrll 827: if (sc == NULL)
828: return EIO;
829:
830: mutex_enter(&sc->sc_lock);
831: if (sc->sc_dying) {
1.115 skrll 832: DPRINTF("... dying", 0, 0, 0, 0);
1.111 skrll 833: mutex_exit(&sc->sc_lock);
834: return EIO;
835: }
1.43 augustss 836:
1.115 skrll 837: struct tty *tp = sc->sc_tty;
1.101 jakllsch 838:
1.17 augustss 839: sc->sc_refcnt++;
1.111 skrll 840: mutex_exit(&sc->sc_lock);
1.115 skrll 841:
1.32 eeh 842: error = ((*tp->t_linesw->l_write)(tp, uio, flag));
1.115 skrll 843:
1.111 skrll 844: mutex_enter(&sc->sc_lock);
1.38 scw 845: if (--sc->sc_refcnt < 0)
1.115 skrll 846: cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj 847: DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0);
1.111 skrll 848: mutex_exit(&sc->sc_lock);
849:
850: return error;
1.38 scw 851: }
852:
853: int
1.60 christos 854: ucompoll(dev_t dev, int events, struct lwp *l)
1.38 scw 855: {
1.115 skrll 856: const int unit = UCOMUNIT(dev);
857: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
858:
859: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1.38 scw 860:
1.111 skrll 861: if (sc == NULL)
862: return POLLHUP;
1.43 augustss 863:
1.111 skrll 864: mutex_enter(&sc->sc_lock);
865: if (sc->sc_dying) {
1.115 skrll 866: DPRINTF("... dying", 0, 0, 0, 0);
1.111 skrll 867: mutex_exit(&sc->sc_lock);
868: return POLLHUP;
869: }
1.115 skrll 870: struct tty *tp = sc->sc_tty;
1.94 jakllsch 871:
1.38 scw 872: sc->sc_refcnt++;
1.111 skrll 873: mutex_exit(&sc->sc_lock);
1.115 skrll 874:
875: int revents = ((*tp->t_linesw->l_poll)(tp, events, l));
876:
1.111 skrll 877: mutex_enter(&sc->sc_lock);
1.17 augustss 878: if (--sc->sc_refcnt < 0)
1.115 skrll 879: cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj 880: DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0);
1.111 skrll 881: mutex_exit(&sc->sc_lock);
882:
883: return revents;
1.12 augustss 884: }
885:
886: struct tty *
1.24 augustss 887: ucomtty(dev_t dev)
1.12 augustss 888: {
1.115 skrll 889: const int unit = UCOMUNIT(dev);
890: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.12 augustss 891:
1.111 skrll 892: return sc != NULL ? sc->sc_tty : NULL;
1.12 augustss 893: }
894:
895: int
1.70 christos 896: ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.12 augustss 897: {
1.115 skrll 898: const int unit = UCOMUNIT(dev);
899: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.17 augustss 900: int error;
901:
1.115 skrll 902: UCOMHIST_FUNC(); UCOMHIST_CALLED();
903:
1.111 skrll 904: if (sc == NULL)
905: return EIO;
906:
907: mutex_enter(&sc->sc_lock);
908: if (sc->sc_dying) {
1.115 skrll 909: DPRINTF("... dying", 0, 0, 0, 0);
1.111 skrll 910: mutex_exit(&sc->sc_lock);
911: return EIO;
912: }
1.101 jakllsch 913:
1.17 augustss 914: sc->sc_refcnt++;
1.114 skrll 915: mutex_exit(&sc->sc_lock);
1.115 skrll 916:
1.60 christos 917: error = ucom_do_ioctl(sc, cmd, data, flag, l);
1.115 skrll 918:
1.114 skrll 919: mutex_enter(&sc->sc_lock);
1.17 augustss 920: if (--sc->sc_refcnt < 0)
1.115 skrll 921: cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj 922: DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0);
1.111 skrll 923: mutex_exit(&sc->sc_lock);
1.115 skrll 924:
1.111 skrll 925: return error;
1.17 augustss 926: }
927:
1.82 martin 928: static int
1.115 skrll 929: ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data, int flag,
930: struct lwp *l)
1.17 augustss 931: {
1.12 augustss 932: struct tty *tp = sc->sc_tty;
933: int error;
934:
1.111 skrll 935: UCOMHIST_FUNC(); UCOMHIST_CALLED();
936:
1.118.8.1! snj 937: DPRINTF("cmd=0x%08jx", cmd, 0, 0, 0);
1.12 augustss 938:
1.60 christos 939: error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
1.42 atatat 940: if (error != EPASSTHROUGH)
1.111 skrll 941: return error;
1.12 augustss 942:
1.60 christos 943: error = ttioctl(tp, cmd, data, flag, l);
1.42 atatat 944: if (error != EPASSTHROUGH)
1.111 skrll 945: return error;
1.12 augustss 946:
947: if (sc->sc_methods->ucom_ioctl != NULL) {
948: error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
1.115 skrll 949: sc->sc_portno, cmd, data, flag, l->l_proc);
1.42 atatat 950: if (error != EPASSTHROUGH)
1.111 skrll 951: return error;
1.12 augustss 952: }
953:
954: error = 0;
955:
1.118.8.1! snj 956: DPRINTF("our cmd=0x%08jx", cmd, 0, 0, 0);
1.12 augustss 957:
958: switch (cmd) {
959: case TIOCSBRK:
960: ucom_break(sc, 1);
961: break;
962:
963: case TIOCCBRK:
964: ucom_break(sc, 0);
965: break;
966:
967: case TIOCSDTR:
968: ucom_dtr(sc, 1);
969: break;
970:
971: case TIOCCDTR:
972: ucom_dtr(sc, 0);
973: break;
974:
975: case TIOCGFLAGS:
1.114 skrll 976: mutex_enter(&sc->sc_lock);
1.12 augustss 977: *(int *)data = sc->sc_swflags;
1.114 skrll 978: mutex_exit(&sc->sc_lock);
1.12 augustss 979: break;
980:
981: case TIOCSFLAGS:
1.67 elad 982: error = kauth_authorize_device_tty(l->l_cred,
983: KAUTH_DEVICE_TTY_PRIVSET, tp);
1.12 augustss 984: if (error)
985: break;
1.114 skrll 986: mutex_enter(&sc->sc_lock);
1.12 augustss 987: sc->sc_swflags = *(int *)data;
1.114 skrll 988: mutex_exit(&sc->sc_lock);
1.12 augustss 989: break;
990:
991: case TIOCMSET:
992: case TIOCMBIS:
993: case TIOCMBIC:
994: tiocm_to_ucom(sc, cmd, *(int *)data);
995: break;
996:
997: case TIOCMGET:
998: *(int *)data = ucom_to_tiocm(sc);
999: break;
1000:
1.106 gdt 1001: case PPS_IOC_CREATE:
1002: case PPS_IOC_DESTROY:
1003: case PPS_IOC_GETPARAMS:
1004: case PPS_IOC_SETPARAMS:
1005: case PPS_IOC_GETCAP:
1006: case PPS_IOC_FETCH:
1007: #ifdef PPS_SYNC
1008: case PPS_IOC_KCBIND:
1009: #endif
1010: mutex_spin_enter(&timecounter_lock);
1011: error = pps_ioctl(cmd, data, &sc->sc_pps_state);
1012: mutex_spin_exit(&timecounter_lock);
1013: break;
1014:
1.12 augustss 1015: default:
1.42 atatat 1016: error = EPASSTHROUGH;
1.12 augustss 1017: break;
1018: }
1019:
1.111 skrll 1020: return error;
1.12 augustss 1021: }
1022:
1.82 martin 1023: static void
1.29 toshii 1024: tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
1.12 augustss 1025: {
1026: u_char combits;
1.3 augustss 1027:
1.12 augustss 1028: combits = 0;
1029: if (ISSET(ttybits, TIOCM_DTR))
1030: SET(combits, UMCR_DTR);
1031: if (ISSET(ttybits, TIOCM_RTS))
1032: SET(combits, UMCR_RTS);
1.43 augustss 1033:
1.114 skrll 1034: mutex_enter(&sc->sc_lock);
1.12 augustss 1035: switch (how) {
1036: case TIOCMBIC:
1037: CLR(sc->sc_mcr, combits);
1038: break;
1039:
1040: case TIOCMBIS:
1041: SET(sc->sc_mcr, combits);
1042: break;
1043:
1044: case TIOCMSET:
1045: CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
1046: SET(sc->sc_mcr, combits);
1047: break;
1048: }
1.115 skrll 1049: u_char mcr = sc->sc_mcr;
1.114 skrll 1050: mutex_exit(&sc->sc_lock);
1.12 augustss 1051:
1.27 toshii 1052: if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
1.115 skrll 1053: ucom_dtr(sc, (mcr & UMCR_DTR) != 0);
1.27 toshii 1054: if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
1.115 skrll 1055: ucom_rts(sc, (mcr & UMCR_RTS) != 0);
1.12 augustss 1056: }
1057:
1.82 martin 1058: static int
1.24 augustss 1059: ucom_to_tiocm(struct ucom_softc *sc)
1.12 augustss 1060: {
1061: u_char combits;
1062: int ttybits = 0;
1063:
1.114 skrll 1064: mutex_enter(&sc->sc_lock);
1.12 augustss 1065: combits = sc->sc_mcr;
1066: if (ISSET(combits, UMCR_DTR))
1067: SET(ttybits, TIOCM_DTR);
1068: if (ISSET(combits, UMCR_RTS))
1069: SET(ttybits, TIOCM_RTS);
1070:
1071: combits = sc->sc_msr;
1072: if (ISSET(combits, UMSR_DCD))
1073: SET(ttybits, TIOCM_CD);
1074: if (ISSET(combits, UMSR_CTS))
1075: SET(ttybits, TIOCM_CTS);
1076: if (ISSET(combits, UMSR_DSR))
1077: SET(ttybits, TIOCM_DSR);
1078: if (ISSET(combits, UMSR_RI | UMSR_TERI))
1079: SET(ttybits, TIOCM_RI);
1080:
1081: #if 0
1082: XXX;
1083: if (sc->sc_ier != 0)
1084: SET(ttybits, TIOCM_LE);
1085: #endif
1.114 skrll 1086: mutex_exit(&sc->sc_lock);
1.12 augustss 1087:
1.111 skrll 1088: return ttybits;
1.12 augustss 1089: }
1090:
1.82 martin 1091: static void
1.77 cube 1092: ucom_break(struct ucom_softc *sc, int onoff)
1.12 augustss 1093: {
1.111 skrll 1094: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1095:
1.118.8.1! snj 1096: DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1.12 augustss 1097:
1.14 augustss 1098: if (sc->sc_methods->ucom_set != NULL)
1099: sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1100: UCOM_SET_BREAK, onoff);
1.12 augustss 1101: }
1102:
1.82 martin 1103: static void
1.24 augustss 1104: ucom_dtr(struct ucom_softc *sc, int onoff)
1.12 augustss 1105: {
1.111 skrll 1106: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1107:
1.118.8.1! snj 1108: DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1.12 augustss 1109:
1.14 augustss 1110: if (sc->sc_methods->ucom_set != NULL)
1.43 augustss 1111: sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1.14 augustss 1112: UCOM_SET_DTR, onoff);
1.12 augustss 1113: }
1114:
1.82 martin 1115: static void
1.24 augustss 1116: ucom_rts(struct ucom_softc *sc, int onoff)
1.12 augustss 1117: {
1.111 skrll 1118: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1119:
1.118.8.1! snj 1120: DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1.12 augustss 1121:
1.14 augustss 1122: if (sc->sc_methods->ucom_set != NULL)
1.43 augustss 1123: sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1.14 augustss 1124: UCOM_SET_RTS, onoff);
1.12 augustss 1125: }
1126:
1.22 augustss 1127: void
1.24 augustss 1128: ucom_status_change(struct ucom_softc *sc)
1.12 augustss 1129: {
1.27 toshii 1130: struct tty *tp = sc->sc_tty;
1131:
1.14 augustss 1132: if (sc->sc_methods->ucom_get_status != NULL) {
1.117 skrll 1133: u_char msr, lsr;
1.115 skrll 1134:
1.14 augustss 1135: sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
1.115 skrll 1136: &lsr, &msr);
1137: mutex_enter(&sc->sc_lock);
1138: u_char old_msr = sc->sc_msr;
1139:
1140: sc->sc_lsr = lsr;
1141: sc->sc_msr = msr;
1142: mutex_exit(&sc->sc_lock);
1143:
1144: if (ISSET((msr ^ old_msr), UMSR_DCD)) {
1.106 gdt 1145: mutex_spin_enter(&timecounter_lock);
1146: pps_capture(&sc->sc_pps_state);
1147: pps_event(&sc->sc_pps_state,
1148: (sc->sc_msr & UMSR_DCD) ?
1149: PPS_CAPTUREASSERT :
1150: PPS_CAPTURECLEAR);
1151: mutex_spin_exit(&timecounter_lock);
1152:
1.115 skrll 1153: (*tp->t_linesw->l_modem)(tp, ISSET(msr, UMSR_DCD));
1.106 gdt 1154: }
1.14 augustss 1155: } else {
1.115 skrll 1156: mutex_enter(&sc->sc_lock);
1.14 augustss 1157: sc->sc_lsr = 0;
1.54 augustss 1158: /* Assume DCD is present, if we have no chance to check it. */
1159: sc->sc_msr = UMSR_DCD;
1.115 skrll 1160: mutex_exit(&sc->sc_lock);
1.14 augustss 1161: }
1.12 augustss 1162: }
1163:
1.82 martin 1164: static int
1.24 augustss 1165: ucomparam(struct tty *tp, struct termios *t)
1.12 augustss 1166: {
1.115 skrll 1167: const int unit = UCOMUNIT(tp->t_dev);
1168: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1169: int error = 0;
1.12 augustss 1170:
1.111 skrll 1171: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1172:
1.115 skrll 1173: if (sc == NULL)
1.111 skrll 1174: return EIO;
1.12 augustss 1175:
1.115 skrll 1176: mutex_enter(&sc->sc_lock);
1177: if (sc->sc_dying) {
1178: DPRINTF("... dying", 0, 0, 0, 0);
1179: mutex_exit(&sc->sc_lock);
1180: return EIO;
1181: }
1182:
1183: sc->sc_refcnt++;
1184: mutex_exit(&sc->sc_lock);
1185:
1.12 augustss 1186: /* Check requested parameters. */
1.115 skrll 1187: if (t->c_ispeed && t->c_ispeed != t->c_ospeed) {
1188: error = EINVAL;
1189: goto out;
1190: }
1.12 augustss 1191:
1192: /*
1193: * For the console, always force CLOCAL and !HUPCL, so that the port
1194: * is always active.
1195: */
1196: if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
1197: SET(t->c_cflag, CLOCAL);
1198: CLR(t->c_cflag, HUPCL);
1199: }
1200:
1201: /*
1202: * If there were no changes, don't do anything. This avoids dropping
1203: * input and improves performance when all we did was frob things like
1204: * VMIN and VTIME.
1205: */
1206: if (tp->t_ospeed == t->c_ospeed &&
1.115 skrll 1207: tp->t_cflag == t->c_cflag) {
1208: goto out;
1209: }
1.12 augustss 1210:
1.30 augustss 1211: /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */
1.12 augustss 1212:
1213: /* And copy to tty. */
1214: tp->t_ispeed = 0;
1215: tp->t_ospeed = t->c_ospeed;
1216: tp->t_cflag = t->c_cflag;
1217:
1.14 augustss 1218: if (sc->sc_methods->ucom_param != NULL) {
1219: error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
1.115 skrll 1220: t);
1.14 augustss 1221: if (error)
1.115 skrll 1222: goto out;
1.14 augustss 1223: }
1.12 augustss 1224:
1.30 augustss 1225: /* XXX worry about CHWFLOW */
1.12 augustss 1226:
1227: /*
1228: * Update the tty layer's idea of the carrier bit, in case we changed
1229: * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1230: * explicit request.
1231: */
1.111 skrll 1232: DPRINTF("l_modem", 0, 0, 0, 0);
1.54 augustss 1233: (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD));
1.12 augustss 1234:
1235: #if 0
1236: XXX what if the hardware is not open
1237: if (!ISSET(t->c_cflag, CHWFLOW)) {
1238: if (sc->sc_tx_stopped) {
1239: sc->sc_tx_stopped = 0;
1240: ucomstart(tp);
1241: }
1242: }
1243: #endif
1.115 skrll 1244: out:
1245: mutex_enter(&sc->sc_lock);
1246: if (--sc->sc_refcnt < 0)
1247: cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj 1248: DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(tp->t_dev), sc->sc_refcnt,
! 1249: 0, 0);
1.115 skrll 1250:
1251: mutex_exit(&sc->sc_lock);
1.12 augustss 1252:
1.111 skrll 1253: return 0;
1.12 augustss 1254: }
1255:
1.82 martin 1256: static int
1257: ucomhwiflow(struct tty *tp, int block)
1.12 augustss 1258: {
1.115 skrll 1259: const int unit = UCOMUNIT(tp->t_dev);
1260: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.82 martin 1261: int old;
1.12 augustss 1262:
1.115 skrll 1263: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1264:
1.101 jakllsch 1265: if (sc == NULL)
1.111 skrll 1266: return 0;
1.101 jakllsch 1267:
1.111 skrll 1268: mutex_enter(&sc->sc_lock);
1.82 martin 1269: old = sc->sc_rx_stopped;
1270: sc->sc_rx_stopped = (u_char)block;
1.12 augustss 1271:
1.82 martin 1272: if (old && !block) {
1273: sc->sc_rx_unblock = 1;
1274: softint_schedule(sc->sc_si);
1.12 augustss 1275: }
1.111 skrll 1276: mutex_exit(&sc->sc_lock);
1.82 martin 1277:
1.111 skrll 1278: return 1;
1.1 augustss 1279: }
1.3 augustss 1280:
1.82 martin 1281: static void
1.24 augustss 1282: ucomstart(struct tty *tp)
1.12 augustss 1283: {
1.115 skrll 1284: const int unit = UCOMUNIT(tp->t_dev);
1285: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.82 martin 1286: struct ucom_buffer *ub;
1.12 augustss 1287: u_char *data;
1288: int cnt;
1289:
1.115 skrll 1290: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1291:
1.111 skrll 1292: if (sc == NULL)
1293: return;
1294:
1295: KASSERT(&sc->sc_lock);
1296: KASSERT(mutex_owned(&tty_lock));
1297: if (sc->sc_dying) {
1.115 skrll 1298: DPRINTF("... dying", 0, 0, 0, 0);
1.12 augustss 1299: return;
1.111 skrll 1300: }
1.12 augustss 1301:
1.84 christos 1302: if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
1.12 augustss 1303: goto out;
1304: if (sc->sc_tx_stopped)
1305: goto out;
1306:
1.82 martin 1307: if (!ttypull(tp))
1.73 ad 1308: goto out;
1.12 augustss 1309:
1310: /* Grab the first contiguous region of buffer space. */
1311: data = tp->t_outq.c_cf;
1312: cnt = ndqb(&tp->t_outq, 0);
1313:
1.84 christos 1314: if (cnt == 0)
1.12 augustss 1315: goto out;
1316:
1.82 martin 1317: ub = SIMPLEQ_FIRST(&sc->sc_obuff_free);
1.100 mlelstv 1318: if (ub == NULL) {
1319: SET(tp->t_state, TS_BUSY);
1320: goto out;
1321: }
1.111 skrll 1322:
1.82 martin 1323: SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_free, ub_link);
1.12 augustss 1324:
1.82 martin 1325: if (SIMPLEQ_FIRST(&sc->sc_obuff_free) == NULL)
1326: SET(tp->t_state, TS_BUSY);
1327:
1328: if (cnt > sc->sc_obufsize)
1.19 augustss 1329: cnt = sc->sc_obufsize;
1.82 martin 1330:
1.22 augustss 1331: if (sc->sc_methods->ucom_write != NULL)
1332: sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
1.115 skrll 1333: ub->ub_data, data, &cnt);
1.22 augustss 1334: else
1.82 martin 1335: memcpy(ub->ub_data, data, cnt);
1336:
1337: ub->ub_len = cnt;
1338: ub->ub_index = 0;
1.12 augustss 1339:
1.82 martin 1340: SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_full, ub, ub_link);
1341:
1342: softint_schedule(sc->sc_si);
1.3 augustss 1343:
1.82 martin 1344: out:
1.115 skrll 1345: DPRINTF("... done", 0, 0, 0, 0);
1.111 skrll 1346: return;
1.12 augustss 1347: }
1348:
1.21 itojun 1349: void
1.69 christos 1350: ucomstop(struct tty *tp, int flag)
1.12 augustss 1351: {
1.19 augustss 1352: #if 0
1.115 skrll 1353: const int unit = UCOMUNIT(tp->t_dev);
1354: struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.12 augustss 1355:
1.111 skrll 1356: mutex_enter(&sc->sc_lock);
1357: mutex_spin_enter(&tty_lock);
1.12 augustss 1358: if (ISSET(tp->t_state, TS_BUSY)) {
1.111 skrll 1359: /* obuff_full -> obuff_free? */
1.19 augustss 1360: /* sc->sc_tx_stopped = 1; */
1.12 augustss 1361: if (!ISSET(tp->t_state, TS_TTSTOP))
1362: SET(tp->t_state, TS_FLUSH);
1363: }
1.111 skrll 1364: mutex_spin_exit(&tty_lock);
1365: mutex_exit(&sc->sc_lock);
1.19 augustss 1366: #endif
1.12 augustss 1367: }
1368:
1.82 martin 1369: static void
1370: ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub,
1371: usbd_status err)
1372: {
1373: struct tty *tp = sc->sc_tty;
1374: uint32_t cc = ub->ub_len;
1375:
1.111 skrll 1376: KASSERT(mutex_owned(&sc->sc_lock));
1377:
1.82 martin 1378: switch (err) {
1379: case USBD_IN_PROGRESS:
1380: ub->ub_index = ub->ub_len;
1381: break;
1382: case USBD_STALLED:
1383: ub->ub_index = 0;
1384: softint_schedule(sc->sc_si);
1385: break;
1386: case USBD_NORMAL_COMPLETION:
1387: usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL);
1388: rnd_add_uint32(&sc->sc_rndsource, cc);
1389: /*FALLTHROUGH*/
1390: default:
1391: SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link);
1392: SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
1393: cc -= sc->sc_opkthdrlen;
1394:
1.100 mlelstv 1395: mutex_spin_enter(&tty_lock);
1.82 martin 1396: CLR(tp->t_state, TS_BUSY);
1397: if (ISSET(tp->t_state, TS_FLUSH))
1398: CLR(tp->t_state, TS_FLUSH);
1399: else
1400: ndflush(&tp->t_outq, cc);
1.100 mlelstv 1401: mutex_spin_exit(&tty_lock);
1.82 martin 1402:
1403: if (err != USBD_CANCELLED && err != USBD_IOERROR &&
1404: !sc->sc_dying) {
1405: if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL)
1406: ucom_submit_write(sc, ub);
1407:
1.111 skrll 1408: mutex_spin_enter(&tty_lock);
1.82 martin 1409: (*tp->t_linesw->l_start)(tp);
1.111 skrll 1410: mutex_spin_exit(&tty_lock);
1.82 martin 1411: }
1412: break;
1413: }
1414: }
1415:
1416: static void
1417: ucom_submit_write(struct ucom_softc *sc, struct ucom_buffer *ub)
1418: {
1419:
1.111 skrll 1420: KASSERT(mutex_owned(&sc->sc_lock));
1421:
1422: usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, ub->ub_len,
1423: 0, USBD_NO_TIMEOUT, ucomwritecb);
1.82 martin 1424:
1425: ucom_write_status(sc, ub, usbd_transfer(ub->ub_xfer));
1426: }
1427:
1428: static void
1.111 skrll 1429: ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status)
1.12 augustss 1430: {
1431: struct ucom_softc *sc = (struct ucom_softc *)p;
1.82 martin 1432:
1.111 skrll 1433: mutex_enter(&sc->sc_lock);
1.82 martin 1434: ucom_write_status(sc, SIMPLEQ_FIRST(&sc->sc_obuff_full), status);
1.111 skrll 1435: mutex_exit(&sc->sc_lock);
1.82 martin 1436:
1437: }
1438:
1439: static void
1440: ucom_softintr(void *arg)
1441: {
1.115 skrll 1442: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1443:
1.82 martin 1444: struct ucom_softc *sc = arg;
1.12 augustss 1445:
1.111 skrll 1446: mutex_enter(&sc->sc_lock);
1.115 skrll 1447: if (sc->sc_dying) {
1448: DPRINTF("... dying", 0, 0, 0, 0);
1449: mutex_exit(&sc->sc_lock);
1450: return;
1451: }
1452:
1453: struct tty *tp = sc->sc_tty;
1.111 skrll 1454: mutex_enter(&tty_lock);
1455: if (!ISSET(tp->t_state, TS_ISOPEN)) {
1456: mutex_exit(&tty_lock);
1457: mutex_exit(&sc->sc_lock);
1.82 martin 1458: return;
1.111 skrll 1459: }
1460: mutex_exit(&tty_lock);
1.12 augustss 1461:
1.115 skrll 1462: struct ucom_buffer *ub = SIMPLEQ_FIRST(&sc->sc_obuff_full);
1.82 martin 1463:
1464: if (ub != NULL && ub->ub_index == 0)
1465: ucom_submit_write(sc, ub);
1.12 augustss 1466:
1.82 martin 1467: if (sc->sc_rx_unblock)
1468: ucom_read_complete(sc);
1.12 augustss 1469:
1.111 skrll 1470: mutex_exit(&sc->sc_lock);
1.82 martin 1471: }
1472:
1473: static void
1474: ucom_read_complete(struct ucom_softc *sc)
1475: {
1476: int (*rint)(int, struct tty *);
1477: struct ucom_buffer *ub;
1478: struct tty *tp;
1.111 skrll 1479:
1480: KASSERT(mutex_owned(&sc->sc_lock));
1.82 martin 1481:
1482: tp = sc->sc_tty;
1483: rint = tp->t_linesw->l_rint;
1484: ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1.39 augustss 1485:
1.82 martin 1486: while (ub != NULL && !sc->sc_rx_stopped) {
1487:
1.111 skrll 1488: /* XXX ttyinput takes tty_lock */
1.82 martin 1489: while (ub->ub_index < ub->ub_len && !sc->sc_rx_stopped) {
1490: /* Give characters to tty layer. */
1491: if ((*rint)(ub->ub_data[ub->ub_index], tp) == -1) {
1492: /* Overflow: drop remainder */
1493: ub->ub_index = ub->ub_len;
1494: } else
1495: ub->ub_index++;
1496: }
1497:
1498: if (ub->ub_index == ub->ub_len) {
1499: SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_full, ub_link);
1500:
1.115 skrll 1501: sc->sc_refcnt--;
1502: /* increments sc_refcnt */
1.82 martin 1503: ucomsubmitread(sc, ub);
1504:
1505: ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1506: }
1507: }
1508:
1509: sc->sc_rx_unblock = (ub != NULL);
1.12 augustss 1510: }
1511:
1.115 skrll 1512: static int
1.82 martin 1513: ucomsubmitread(struct ucom_softc *sc, struct ucom_buffer *ub)
1.12 augustss 1514: {
1515: usbd_status err;
1516:
1.115 skrll 1517: KASSERT(mutex_owned(&sc->sc_lock));
1518:
1.111 skrll 1519: usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize,
1520: USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb);
1.82 martin 1521:
1522: if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) {
1523: /* XXX: Recover from this, please! */
1.115 skrll 1524: printf("%s: err=%s\n", __func__, usbd_errstr(err));
1525: return EIO;
1.12 augustss 1526: }
1.82 martin 1527:
1.115 skrll 1528: sc->sc_refcnt++;
1529:
1.82 martin 1530: SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link);
1531:
1.115 skrll 1532: return 0;
1.12 augustss 1533: }
1.43 augustss 1534:
1.82 martin 1535: static void
1.111 skrll 1536: ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status)
1.12 augustss 1537: {
1538: struct ucom_softc *sc = (struct ucom_softc *)p;
1.82 martin 1539: struct ucom_buffer *ub;
1.111 skrll 1540: uint32_t cc;
1.12 augustss 1541: u_char *cp;
1542:
1.111 skrll 1543: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1544:
1.115 skrll 1545: mutex_enter(&sc->sc_lock);
1546:
1547: struct tty *tp = sc->sc_tty;
1.112 skrll 1548:
1.115 skrll 1549: if (status == USBD_CANCELLED || status == USBD_IOERROR ||
1.34 augustss 1550: sc->sc_dying) {
1.115 skrll 1551:
1.118.8.1! snj 1552: DPRINTF("... done (status %jd dying %jd)", status, sc->sc_dying,
1.115 skrll 1553: 0, 0);
1554:
1555: if (status == USBD_IOERROR || sc->sc_dying) {
1556: /* Send something to wake upper layer */
1557: (tp->t_linesw->l_rint)('\n', tp);
1558: mutex_spin_enter(&tty_lock); /* XXX */
1559: ttwakeup(tp);
1560: mutex_spin_exit(&tty_lock); /* XXX */
1561: }
1562:
1563: if (--sc->sc_refcnt < 0)
1564: cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj 1565: DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(tp->t_dev),
! 1566: sc->sc_refcnt, 0, 0);
1.111 skrll 1567: mutex_exit(&sc->sc_lock);
1.115 skrll 1568:
1.12 augustss 1569: return;
1.34 augustss 1570: }
1.12 augustss 1571:
1.112 skrll 1572: ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty);
1573: SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link);
1574:
1.115 skrll 1575: if (status != USBD_NORMAL_COMPLETION) {
1576: if (status == USBD_STALLED) {
1577: usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1578: } else {
1579: printf("ucomreadcb: wonky status=%s\n",
1580: usbd_errstr(status));
1581: }
1582:
1.118.8.1! snj 1583: DPRINTF("... done (status %jd)", status, 0, 0, 0);
1.115 skrll 1584: sc->sc_refcnt--;
1585: /* re-adds ub to sc_ibuff_empty and increments sc_refcnt */
1.82 martin 1586: ucomsubmitread(sc, ub);
1.111 skrll 1587: mutex_exit(&sc->sc_lock);
1.82 martin 1588: return;
1589: }
1590:
1.48 thorpej 1591: usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
1.82 martin 1592:
1.95 jakllsch 1593: #ifdef UCOM_DEBUG
1594: /* This is triggered by uslsa(4) occasionally. */
1595: if ((ucomdebug > 0) && (cc == 0)) {
1596: device_printf(sc->sc_dev, "ucomreadcb: zero length xfer!\n");
1.82 martin 1597: }
1.95 jakllsch 1598: #endif
1.82 martin 1599: KDASSERT(cp == ub->ub_data);
1600:
1.31 explorer 1601: rnd_add_uint32(&sc->sc_rndsource, cc);
1.82 martin 1602:
1.115 skrll 1603: if (sc->sc_state != UCOM_OPEN) {
1604: /* Go around again - we're not quite ready */
1605: sc->sc_refcnt--;
1606: /* re-adds ub to sc_ibuff_empty and increments sc_refcnt */
1.82 martin 1607: ucomsubmitread(sc, ub);
1.111 skrll 1608: mutex_exit(&sc->sc_lock);
1.115 skrll 1609: DPRINTF("... done (not open)", 0, 0, 0, 0);
1.82 martin 1610: return;
1611: }
1612:
1.118 skrll 1613: mutex_exit(&sc->sc_lock);
1.82 martin 1614: if (sc->sc_methods->ucom_read != NULL) {
1.22 augustss 1615: sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
1.82 martin 1616: &cp, &cc);
1617: ub->ub_index = (u_int)(cp - ub->ub_data);
1618: } else
1619: ub->ub_index = 0;
1620:
1621: ub->ub_len = cc;
1.22 augustss 1622:
1.118 skrll 1623: mutex_enter(&sc->sc_lock);
1624: if (sc->sc_dying) {
1625: if (--sc->sc_refcnt < 0)
1626: cv_broadcast(&sc->sc_detachcv);
1627: mutex_exit(&sc->sc_lock);
1628: DPRINTF("... dying", 0, 0, 0, 0);
1629: return;
1630: }
1631:
1.82 martin 1632: SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link);
1.12 augustss 1633:
1.82 martin 1634: ucom_read_complete(sc);
1.111 skrll 1635: mutex_exit(&sc->sc_lock);
1.115 skrll 1636:
1637: DPRINTF("... done", 0, 0, 0, 0);
1.12 augustss 1638: }
1639:
1.82 martin 1640: static void
1.24 augustss 1641: ucom_cleanup(struct ucom_softc *sc)
1.12 augustss 1642: {
1.82 martin 1643:
1.111 skrll 1644: UCOMHIST_FUNC(); UCOMHIST_CALLED();
1645:
1646: DPRINTF("aborting pipes", 0, 0, 0, 0);
1647:
1.115 skrll 1648: mutex_enter(&sc->sc_lock);
1649:
1650: /* If we're dying then the detach routine will abort our pipes, etc */
1651: if (sc->sc_dying) {
1652: DPRINTF("... dying", 0, 0, 0, 0);
1653:
1654: mutex_exit(&sc->sc_lock);
1655: return;
1656: }
1.12 augustss 1657:
1.116 skrll 1658: mutex_exit(&sc->sc_lock);
1659:
1.12 augustss 1660: ucom_shutdown(sc);
1.115 skrll 1661:
1.33 augustss 1662: if (sc->sc_bulkin_pipe != NULL) {
1.112 skrll 1663: usbd_abort_pipe(sc->sc_bulkin_pipe);
1.33 augustss 1664: }
1665: if (sc->sc_bulkout_pipe != NULL) {
1.112 skrll 1666: usbd_abort_pipe(sc->sc_bulkout_pipe);
1.33 augustss 1667: }
1.12 augustss 1668: }
1.13 augustss 1669:
1670: #endif /* NUCOM > 0 */
1.12 augustss 1671:
1.20 augustss 1672: int
1.24 augustss 1673: ucomprint(void *aux, const char *pnp)
1.12 augustss 1674: {
1.111 skrll 1675: struct ucom_attach_args *ucaa = aux;
1.12 augustss 1676:
1677: if (pnp)
1.49 thorpej 1678: aprint_normal("ucom at %s", pnp);
1.111 skrll 1679: if (ucaa->ucaa_portno != UCOM_UNK_PORTNO)
1680: aprint_normal(" portno %d", ucaa->ucaa_portno);
1681: return UNCONF;
1.12 augustss 1682: }
1683:
1.20 augustss 1684: int
1.77 cube 1685: ucomsubmatch(device_t parent, cfdata_t cf,
1.69 christos 1686: const int *ldesc, void *aux)
1.12 augustss 1687: {
1.111 skrll 1688: struct ucom_attach_args *ucaa = aux;
1.12 augustss 1689:
1.111 skrll 1690: if (ucaa->ucaa_portno != UCOM_UNK_PORTNO &&
1.53 drochner 1691: cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT &&
1.111 skrll 1692: cf->cf_loc[UCOMBUSCF_PORTNO] != ucaa->ucaa_portno)
1693: return 0;
1694: return config_match(parent, cf, aux);
1.12 augustss 1695: }
CVSweb <webmaster@jp.NetBSD.org>