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