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