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