Annotation of src/sys/dev/usb/ucom.c, Revision 1.58
1.58 ! kleink 1: /* $NetBSD: ucom.c,v 1.57 2005/08/26 12:42:11 drochner Exp $ */
1.1 augustss 2:
3: /*
1.22 augustss 4: * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
1.1 augustss 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
1.23 augustss 8: * by Lennart Augustsson (lennart@augustsson.net) at
1.1 augustss 9: * Carlstedt Research & Technology.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
1.22 augustss 39: /*
40: * This code is very heavily based on the 16550 driver, com.c.
41: */
1.40 lukem 42:
43: #include <sys/cdefs.h>
1.58 ! kleink 44: __KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.57 2005/08/26 12:42:11 drochner Exp $");
1.1 augustss 45:
46: #include <sys/param.h>
47: #include <sys/systm.h>
48: #include <sys/kernel.h>
49: #include <sys/ioctl.h>
1.3 augustss 50: #include <sys/conf.h>
1.1 augustss 51: #include <sys/tty.h>
52: #include <sys/file.h>
53: #include <sys/select.h>
54: #include <sys/proc.h>
55: #include <sys/vnode.h>
1.12 augustss 56: #include <sys/device.h>
1.1 augustss 57: #include <sys/poll.h>
1.31 explorer 58: #if defined(__NetBSD__)
59: #include "rnd.h"
60: #if NRND > 0
61: #include <sys/rnd.h>
62: #endif
63: #endif
1.1 augustss 64:
65: #include <dev/usb/usb.h>
66:
67: #include <dev/usb/usbdi.h>
68: #include <dev/usb/usbdi_util.h>
69: #include <dev/usb/usbdevs.h>
70: #include <dev/usb/usb_quirks.h>
71:
1.12 augustss 72: #include <dev/usb/ucomvar.h>
73:
1.13 augustss 74: #include "ucom.h"
75:
1.53 drochner 76: #include "locators.h"
77:
1.13 augustss 78: #if NUCOM > 0
79:
1.12 augustss 80: #ifdef UCOM_DEBUG
81: #define DPRINTFN(n, x) if (ucomdebug > (n)) logprintf x
82: int ucomdebug = 0;
1.1 augustss 83: #else
1.12 augustss 84: #define DPRINTFN(n, x)
1.1 augustss 85: #endif
1.12 augustss 86: #define DPRINTF(x) DPRINTFN(0, x)
87:
88: #define UCOMUNIT_MASK 0x3ffff
89: #define UCOMDIALOUT_MASK 0x80000
90: #define UCOMCALLUNIT_MASK 0x40000
91:
92: #define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK)
93: #define UCOMDIALOUT(x) (minor(x) & UCOMDIALOUT_MASK)
94: #define UCOMCALLUNIT(x) (minor(x) & UCOMCALLUNIT_MASK)
95:
1.1 augustss 96: struct ucom_softc {
1.12 augustss 97: USBBASEDEVICE sc_dev; /* base device */
98:
99: usbd_device_handle sc_udev; /* USB device */
100:
101: usbd_interface_handle sc_iface; /* data interface */
102:
103: int sc_bulkin_no; /* bulk in endpoint address */
104: usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */
105: usbd_xfer_handle sc_ixfer; /* read request */
106: u_char *sc_ibuf; /* read buffer */
1.19 augustss 107: u_int sc_ibufsize; /* read buffer size */
1.22 augustss 108: u_int sc_ibufsizepad; /* read buffer size padded */
1.12 augustss 109:
110: int sc_bulkout_no; /* bulk out endpoint address */
111: usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */
112: usbd_xfer_handle sc_oxfer; /* write request */
113: u_char *sc_obuf; /* write buffer */
1.19 augustss 114: u_int sc_obufsize; /* write buffer size */
1.25 augustss 115: u_int sc_opkthdrlen; /* header length of
116: * output packet */
1.12 augustss 117:
118: struct ucom_methods *sc_methods;
119: void *sc_parent;
120: int sc_portno;
121:
122: struct tty *sc_tty; /* our tty */
123: u_char sc_lsr;
124: u_char sc_msr;
125: u_char sc_mcr;
126: u_char sc_tx_stopped;
127: int sc_swflags;
128:
129: u_char sc_opening; /* lock during open */
1.17 augustss 130: int sc_refcnt;
1.12 augustss 131: u_char sc_dying; /* disconnecting */
1.31 explorer 132:
133: #if defined(__NetBSD__) && NRND > 0
134: rndsource_element_t sc_rndsource; /* random source */
135: #endif
1.1 augustss 136: };
137:
1.44 gehenna 138: dev_type_open(ucomopen);
139: dev_type_close(ucomclose);
140: dev_type_read(ucomread);
141: dev_type_write(ucomwrite);
142: dev_type_ioctl(ucomioctl);
143: dev_type_stop(ucomstop);
144: dev_type_tty(ucomtty);
145: dev_type_poll(ucompoll);
146:
147: const struct cdevsw ucom_cdevsw = {
148: ucomopen, ucomclose, ucomread, ucomwrite, ucomioctl,
1.47 jdolecek 149: ucomstop, ucomtty, ucompoll, nommap, ttykqfilter, D_TTY
1.44 gehenna 150: };
1.12 augustss 151:
1.24 augustss 152: Static void ucom_cleanup(struct ucom_softc *);
153: Static void ucom_hwiflow(struct ucom_softc *);
154: Static int ucomparam(struct tty *, struct termios *);
155: Static void ucomstart(struct tty *);
156: Static void ucom_shutdown(struct ucom_softc *);
157: Static int ucom_do_ioctl(struct ucom_softc *, u_long, caddr_t,
1.51 fvdl 158: int, usb_proc_ptr);
1.24 augustss 159: Static void ucom_dtr(struct ucom_softc *, int);
160: Static void ucom_rts(struct ucom_softc *, int);
161: Static void ucom_break(struct ucom_softc *, int);
162: Static usbd_status ucomstartread(struct ucom_softc *);
163: Static void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status);
164: Static void ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status);
1.29 toshii 165: Static void tiocm_to_ucom(struct ucom_softc *, u_long, int);
1.24 augustss 166: Static int ucom_to_tiocm(struct ucom_softc *);
1.1 augustss 167:
1.3 augustss 168: USB_DECLARE_DRIVER(ucom);
1.1 augustss 169:
1.3 augustss 170: USB_MATCH(ucom)
1.1 augustss 171: {
1.12 augustss 172: return (1);
1.1 augustss 173: }
174:
1.3 augustss 175: USB_ATTACH(ucom)
1.1 augustss 176: {
1.12 augustss 177: struct ucom_softc *sc = (struct ucom_softc *)self;
178: struct ucom_attach_args *uca = aux;
179: struct tty *tp;
180:
181: if (uca->portno != UCOM_UNK_PORTNO)
182: printf(": portno %d", uca->portno);
1.35 augustss 183: if (uca->info != NULL)
184: printf(", %s", uca->info);
1.12 augustss 185: printf("\n");
186:
187: sc->sc_udev = uca->device;
188: sc->sc_iface = uca->iface;
189: sc->sc_bulkout_no = uca->bulkout;
190: sc->sc_bulkin_no = uca->bulkin;
1.19 augustss 191: sc->sc_ibufsize = uca->ibufsize;
1.22 augustss 192: sc->sc_ibufsizepad = uca->ibufsizepad;
1.19 augustss 193: sc->sc_obufsize = uca->obufsize;
1.25 augustss 194: sc->sc_opkthdrlen = uca->opkthdrlen;
1.12 augustss 195: sc->sc_methods = uca->methods;
196: sc->sc_parent = uca->arg;
197: sc->sc_portno = uca->portno;
198:
199: tp = ttymalloc();
200: tp->t_oproc = ucomstart;
201: tp->t_param = ucomparam;
202: sc->sc_tty = tp;
203:
204: DPRINTF(("ucom_attach: tty_attach %p\n", tp));
205: tty_attach(tp);
206:
1.31 explorer 207: #if defined(__NetBSD__) && NRND > 0
208: rnd_attach_source(&sc->sc_rndsource, USBDEVNAME(sc->sc_dev),
209: RND_TYPE_TTY, 0);
210: #endif
211:
1.12 augustss 212: USB_ATTACH_SUCCESS_RETURN;
213: }
214:
215: USB_DETACH(ucom)
216: {
217: struct ucom_softc *sc = (struct ucom_softc *)self;
1.36 augustss 218: struct tty *tp = sc->sc_tty;
1.12 augustss 219: int maj, mn;
1.17 augustss 220: int s;
1.12 augustss 221:
1.43 augustss 222: DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n",
1.36 augustss 223: sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no));
1.12 augustss 224:
225: sc->sc_dying = 1;
226:
1.33 augustss 227: if (sc->sc_bulkin_pipe != NULL)
228: usbd_abort_pipe(sc->sc_bulkin_pipe);
229: if (sc->sc_bulkout_pipe != NULL)
230: usbd_abort_pipe(sc->sc_bulkout_pipe);
1.12 augustss 231:
1.17 augustss 232: s = splusb();
233: if (--sc->sc_refcnt >= 0) {
1.35 augustss 234: /* Wake up anyone waiting */
1.36 augustss 235: if (tp != NULL) {
236: CLR(tp->t_state, TS_CARR_ON);
237: CLR(tp->t_cflag, CLOCAL | MDMBUF);
238: ttyflush(tp, FREAD|FWRITE);
239: }
1.17 augustss 240: /* Wait for processes to go away. */
241: usb_detach_wait(USBDEV(sc->sc_dev));
242: }
243: splx(s);
1.12 augustss 244:
245: /* locate the major number */
1.44 gehenna 246: maj = cdevsw_lookup_major(&ucom_cdevsw);
1.12 augustss 247:
248: /* Nuke the vnodes for any open instances. */
249: mn = self->dv_unit;
1.17 augustss 250: DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn));
1.12 augustss 251: vdevgone(maj, mn, mn, VCHR);
1.22 augustss 252: vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR);
253: vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR);
1.12 augustss 254:
255: /* Detach and free the tty. */
1.36 augustss 256: if (tp != NULL) {
257: tty_detach(tp);
258: ttyfree(tp);
1.33 augustss 259: sc->sc_tty = NULL;
260: }
1.12 augustss 261:
1.31 explorer 262: /* Detach the random source */
263: #if defined(__NetBSD__) && NRND > 0
264: rnd_detach_source(&sc->sc_rndsource);
265: #endif
266:
1.12 augustss 267: return (0);
268: }
269:
270: int
1.24 augustss 271: ucom_activate(device_ptr_t self, enum devact act)
1.12 augustss 272: {
273: struct ucom_softc *sc = (struct ucom_softc *)self;
274:
1.34 augustss 275: DPRINTFN(5,("ucom_activate: %d\n", act));
276:
1.12 augustss 277: switch (act) {
278: case DVACT_ACTIVATE:
279: return (EOPNOTSUPP);
280:
281: case DVACT_DEACTIVATE:
282: sc->sc_dying = 1;
283: break;
284: }
285: return (0);
286: }
287:
288: void
1.24 augustss 289: ucom_shutdown(struct ucom_softc *sc)
1.12 augustss 290: {
291: struct tty *tp = sc->sc_tty;
292:
293: DPRINTF(("ucom_shutdown\n"));
294: /*
295: * Hang up if necessary. Wait a bit, so the other side has time to
296: * notice even if we immediately open the port again.
297: */
298: if (ISSET(tp->t_cflag, HUPCL)) {
299: ucom_dtr(sc, 0);
300: (void)tsleep(sc, TTIPRI, ttclos, hz);
301: }
302: }
303:
304: int
1.51 fvdl 305: ucomopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
1.12 augustss 306: {
307: int unit = UCOMUNIT(dev);
308: usbd_status err;
309: struct ucom_softc *sc;
310: struct tty *tp;
311: int s;
312: int error;
1.43 augustss 313:
1.12 augustss 314: if (unit >= ucom_cd.cd_ndevs)
315: return (ENXIO);
316: sc = ucom_cd.cd_devs[unit];
317: if (sc == NULL)
318: return (ENXIO);
319:
320: if (sc->sc_dying)
321: return (EIO);
322:
323: if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0)
324: return (ENXIO);
325:
326: tp = sc->sc_tty;
327:
328: DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));
329:
330: if (ISSET(tp->t_state, TS_ISOPEN) &&
331: ISSET(tp->t_state, TS_XCLUDE) &&
1.58 ! kleink 332: suser(p->p_ucred, &p->p_acflag) != 0)
1.12 augustss 333: return (EBUSY);
334:
335: s = spltty();
336:
337: /*
338: * Do the following iff this is a first open.
339: */
340: while (sc->sc_opening)
341: tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0);
1.17 augustss 342:
343: if (sc->sc_dying) {
344: splx(s);
345: return (EIO);
346: }
1.12 augustss 347: sc->sc_opening = 1;
1.43 augustss 348:
1.12 augustss 349: if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
350: struct termios t;
351:
352: tp->t_dev = dev;
353:
1.22 augustss 354: if (sc->sc_methods->ucom_open != NULL) {
355: error = sc->sc_methods->ucom_open(sc->sc_parent,
356: sc->sc_portno);
357: if (error) {
358: ucom_cleanup(sc);
1.26 toshii 359: sc->sc_opening = 0;
360: wakeup(&sc->sc_opening);
361: splx(s);
1.22 augustss 362: return (error);
363: }
364: }
365:
1.12 augustss 366: ucom_status_change(sc);
367:
368: /*
369: * Initialize the termios status to the defaults. Add in the
370: * sticky bits from TIOCSFLAGS.
371: */
372: t.c_ispeed = 0;
373: t.c_ospeed = TTYDEF_SPEED;
374: t.c_cflag = TTYDEF_CFLAG;
375: if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
376: SET(t.c_cflag, CLOCAL);
377: if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
378: SET(t.c_cflag, CRTSCTS);
379: if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
380: SET(t.c_cflag, MDMBUF);
381: /* Make sure ucomparam() will do something. */
382: tp->t_ospeed = 0;
383: (void) ucomparam(tp, &t);
384: tp->t_iflag = TTYDEF_IFLAG;
385: tp->t_oflag = TTYDEF_OFLAG;
386: tp->t_lflag = TTYDEF_LFLAG;
387: ttychars(tp);
388: ttsetwater(tp);
389:
390: /*
391: * Turn on DTR. We must always do this, even if carrier is not
392: * present, because otherwise we'd have to use TIOCSDTR
393: * immediately after setting CLOCAL, which applications do not
394: * expect. We always assert DTR while the device is open
395: * unless explicitly requested to deassert it.
396: */
397: ucom_dtr(sc, 1);
398:
1.30 augustss 399: /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/
1.12 augustss 400: ucom_hwiflow(sc);
401:
402: DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
403: sc->sc_bulkin_no, sc->sc_bulkout_no));
404:
405: /* Open the bulk pipes */
406: err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0,
407: &sc->sc_bulkin_pipe);
408: if (err) {
1.52 nathanw 409: DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
1.43 augustss 410: USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no,
1.12 augustss 411: usbd_errstr(err)));
1.28 toshii 412: error = EIO;
1.26 toshii 413: goto fail_0;
1.12 augustss 414: }
415: err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
416: USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
417: if (err) {
1.52 nathanw 418: DPRINTF(("%s: open bulk out error (addr %d), err=%s\n",
1.12 augustss 419: USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no,
420: usbd_errstr(err)));
1.28 toshii 421: error = EIO;
1.26 toshii 422: goto fail_1;
1.12 augustss 423: }
1.43 augustss 424:
1.12 augustss 425: /* Allocate a request and an input buffer and start reading. */
426: sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev);
1.28 toshii 427: if (sc->sc_ixfer == NULL) {
428: error = ENOMEM;
1.26 toshii 429: goto fail_2;
1.28 toshii 430: }
1.26 toshii 431:
1.22 augustss 432: sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer,
433: sc->sc_ibufsizepad);
1.28 toshii 434: if (sc->sc_ibuf == NULL) {
435: error = ENOMEM;
1.26 toshii 436: goto fail_3;
1.28 toshii 437: }
1.12 augustss 438:
439: sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
1.28 toshii 440: if (sc->sc_oxfer == NULL) {
441: error = ENOMEM;
1.26 toshii 442: goto fail_3;
1.28 toshii 443: }
1.26 toshii 444:
1.22 augustss 445: sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer,
1.25 augustss 446: sc->sc_obufsize +
447: sc->sc_opkthdrlen);
1.28 toshii 448: if (sc->sc_obuf == NULL) {
449: error = ENOMEM;
1.26 toshii 450: goto fail_4;
1.28 toshii 451: }
1.12 augustss 452:
453: ucomstartread(sc);
454: }
455: sc->sc_opening = 0;
456: wakeup(&sc->sc_opening);
457: splx(s);
458:
459: error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
460: if (error)
461: goto bad;
462:
1.32 eeh 463: error = (*tp->t_linesw->l_open)(dev, tp);
1.12 augustss 464: if (error)
465: goto bad;
466:
467: return (0);
1.26 toshii 468:
469: fail_4:
470: usbd_free_xfer(sc->sc_oxfer);
1.34 augustss 471: sc->sc_oxfer = NULL;
1.26 toshii 472: fail_3:
473: usbd_free_xfer(sc->sc_ixfer);
1.34 augustss 474: sc->sc_ixfer = NULL;
1.26 toshii 475: fail_2:
476: usbd_close_pipe(sc->sc_bulkout_pipe);
1.34 augustss 477: sc->sc_bulkout_pipe = NULL;
1.26 toshii 478: fail_1:
479: usbd_close_pipe(sc->sc_bulkin_pipe);
1.34 augustss 480: sc->sc_bulkin_pipe = NULL;
1.26 toshii 481: fail_0:
482: sc->sc_opening = 0;
483: wakeup(&sc->sc_opening);
484: splx(s);
1.28 toshii 485: return (error);
1.12 augustss 486:
487: bad:
488: if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
489: /*
490: * We failed to open the device, and nobody else had it opened.
491: * Clean up the state as appropriate.
492: */
493: ucom_cleanup(sc);
494: }
495:
496: return (error);
497: }
498:
499: int
1.51 fvdl 500: ucomclose(dev_t dev, int flag, int mode, usb_proc_ptr p)
1.12 augustss 501: {
502: struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
503: struct tty *tp = sc->sc_tty;
504:
505: DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev)));
506: if (!ISSET(tp->t_state, TS_ISOPEN))
507: return (0);
508:
1.17 augustss 509: sc->sc_refcnt++;
510:
1.32 eeh 511: (*tp->t_linesw->l_close)(tp, flag);
1.12 augustss 512: ttyclose(tp);
513:
514: if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
515: /*
516: * Although we got a last close, the device may still be in
517: * use; e.g. if this was the dialout node, and there are still
518: * processes waiting for carrier on the non-dialout node.
519: */
520: ucom_cleanup(sc);
521: }
522:
1.14 augustss 523: if (sc->sc_methods->ucom_close != NULL)
524: sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno);
525:
1.17 augustss 526: if (--sc->sc_refcnt < 0)
527: usb_detach_wakeup(USBDEV(sc->sc_dev));
528:
1.12 augustss 529: return (0);
530: }
1.43 augustss 531:
1.12 augustss 532: int
1.24 augustss 533: ucomread(dev_t dev, struct uio *uio, int flag)
1.12 augustss 534: {
535: struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
536: struct tty *tp = sc->sc_tty;
1.17 augustss 537: int error;
1.12 augustss 538:
539: if (sc->sc_dying)
540: return (EIO);
1.43 augustss 541:
1.17 augustss 542: sc->sc_refcnt++;
1.32 eeh 543: error = ((*tp->t_linesw->l_read)(tp, uio, flag));
1.17 augustss 544: if (--sc->sc_refcnt < 0)
545: usb_detach_wakeup(USBDEV(sc->sc_dev));
546: return (error);
1.12 augustss 547: }
1.43 augustss 548:
1.12 augustss 549: int
1.24 augustss 550: ucomwrite(dev_t dev, struct uio *uio, int flag)
1.12 augustss 551: {
552: struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
553: struct tty *tp = sc->sc_tty;
1.17 augustss 554: int error;
1.12 augustss 555:
556: if (sc->sc_dying)
557: return (EIO);
1.43 augustss 558:
1.17 augustss 559: sc->sc_refcnt++;
1.32 eeh 560: error = ((*tp->t_linesw->l_write)(tp, uio, flag));
1.38 scw 561: if (--sc->sc_refcnt < 0)
562: usb_detach_wakeup(USBDEV(sc->sc_dev));
563: return (error);
564: }
565:
566: int
1.51 fvdl 567: ucompoll(dev_t dev, int events, usb_proc_ptr p)
1.38 scw 568: {
569: struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
570: struct tty *tp = sc->sc_tty;
1.56 ws 571: int revents;
1.38 scw 572:
573: if (sc->sc_dying)
1.56 ws 574: return (POLLHUP);
1.43 augustss 575:
1.38 scw 576: sc->sc_refcnt++;
1.56 ws 577: revents = ((*tp->t_linesw->l_poll)(tp, events, p));
1.17 augustss 578: if (--sc->sc_refcnt < 0)
579: usb_detach_wakeup(USBDEV(sc->sc_dev));
1.56 ws 580: return (revents);
1.12 augustss 581: }
582:
583: struct tty *
1.24 augustss 584: ucomtty(dev_t dev)
1.12 augustss 585: {
586: struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
587: struct tty *tp = sc->sc_tty;
588:
589: return (tp);
590: }
591:
592: int
1.51 fvdl 593: ucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
1.12 augustss 594: {
595: struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
1.17 augustss 596: int error;
597:
598: sc->sc_refcnt++;
1.51 fvdl 599: error = ucom_do_ioctl(sc, cmd, data, flag, p);
1.17 augustss 600: if (--sc->sc_refcnt < 0)
601: usb_detach_wakeup(USBDEV(sc->sc_dev));
602: return (error);
603: }
604:
605: Static int
1.24 augustss 606: ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, caddr_t data,
1.51 fvdl 607: int flag, usb_proc_ptr p)
1.17 augustss 608: {
1.12 augustss 609: struct tty *tp = sc->sc_tty;
610: int error;
611: int s;
612:
613: if (sc->sc_dying)
614: return (EIO);
1.43 augustss 615:
1.12 augustss 616: DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd));
617:
1.51 fvdl 618: error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
1.42 atatat 619: if (error != EPASSTHROUGH)
1.12 augustss 620: return (error);
621:
1.51 fvdl 622: error = ttioctl(tp, cmd, data, flag, p);
1.42 atatat 623: if (error != EPASSTHROUGH)
1.12 augustss 624: return (error);
625:
626: if (sc->sc_methods->ucom_ioctl != NULL) {
627: error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
1.51 fvdl 628: sc->sc_portno, cmd, data, flag, p);
1.42 atatat 629: if (error != EPASSTHROUGH)
1.12 augustss 630: return (error);
631: }
632:
633: error = 0;
634:
635: DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd));
636: s = spltty();
637:
638: switch (cmd) {
639: case TIOCSBRK:
640: ucom_break(sc, 1);
641: break;
642:
643: case TIOCCBRK:
644: ucom_break(sc, 0);
645: break;
646:
647: case TIOCSDTR:
648: ucom_dtr(sc, 1);
649: break;
650:
651: case TIOCCDTR:
652: ucom_dtr(sc, 0);
653: break;
654:
655: case TIOCGFLAGS:
656: *(int *)data = sc->sc_swflags;
657: break;
658:
659: case TIOCSFLAGS:
1.43 augustss 660: error = suser(p->p_ucred, &p->p_acflag);
1.12 augustss 661: if (error)
662: break;
663: sc->sc_swflags = *(int *)data;
664: break;
665:
666: case TIOCMSET:
667: case TIOCMBIS:
668: case TIOCMBIC:
669: tiocm_to_ucom(sc, cmd, *(int *)data);
670: break;
671:
672: case TIOCMGET:
673: *(int *)data = ucom_to_tiocm(sc);
674: break;
675:
676: default:
1.42 atatat 677: error = EPASSTHROUGH;
1.12 augustss 678: break;
679: }
680:
681: splx(s);
682:
683: return (error);
684: }
685:
1.17 augustss 686: Static void
1.29 toshii 687: tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
1.12 augustss 688: {
689: u_char combits;
1.3 augustss 690:
1.12 augustss 691: combits = 0;
692: if (ISSET(ttybits, TIOCM_DTR))
693: SET(combits, UMCR_DTR);
694: if (ISSET(ttybits, TIOCM_RTS))
695: SET(combits, UMCR_RTS);
1.43 augustss 696:
1.12 augustss 697: switch (how) {
698: case TIOCMBIC:
699: CLR(sc->sc_mcr, combits);
700: break;
701:
702: case TIOCMBIS:
703: SET(sc->sc_mcr, combits);
704: break;
705:
706: case TIOCMSET:
707: CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
708: SET(sc->sc_mcr, combits);
709: break;
710: }
711:
1.27 toshii 712: if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
713: ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0);
714: if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
715: ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0);
1.12 augustss 716: }
717:
1.17 augustss 718: Static int
1.24 augustss 719: ucom_to_tiocm(struct ucom_softc *sc)
1.12 augustss 720: {
721: u_char combits;
722: int ttybits = 0;
723:
724: combits = sc->sc_mcr;
725: if (ISSET(combits, UMCR_DTR))
726: SET(ttybits, TIOCM_DTR);
727: if (ISSET(combits, UMCR_RTS))
728: SET(ttybits, TIOCM_RTS);
729:
730: combits = sc->sc_msr;
731: if (ISSET(combits, UMSR_DCD))
732: SET(ttybits, TIOCM_CD);
733: if (ISSET(combits, UMSR_CTS))
734: SET(ttybits, TIOCM_CTS);
735: if (ISSET(combits, UMSR_DSR))
736: SET(ttybits, TIOCM_DSR);
737: if (ISSET(combits, UMSR_RI | UMSR_TERI))
738: SET(ttybits, TIOCM_RI);
739:
740: #if 0
741: XXX;
742: if (sc->sc_ier != 0)
743: SET(ttybits, TIOCM_LE);
744: #endif
745:
746: return (ttybits);
747: }
748:
1.17 augustss 749: Static void
1.12 augustss 750: ucom_break(sc, onoff)
751: struct ucom_softc *sc;
752: int onoff;
753: {
754: DPRINTF(("ucom_break: onoff=%d\n", onoff));
755:
1.14 augustss 756: if (sc->sc_methods->ucom_set != NULL)
757: sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
758: UCOM_SET_BREAK, onoff);
1.12 augustss 759: }
760:
1.17 augustss 761: Static void
1.24 augustss 762: ucom_dtr(struct ucom_softc *sc, int onoff)
1.12 augustss 763: {
764: DPRINTF(("ucom_dtr: onoff=%d\n", onoff));
765:
1.14 augustss 766: if (sc->sc_methods->ucom_set != NULL)
1.43 augustss 767: sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1.14 augustss 768: UCOM_SET_DTR, onoff);
1.12 augustss 769: }
770:
1.17 augustss 771: Static void
1.24 augustss 772: ucom_rts(struct ucom_softc *sc, int onoff)
1.12 augustss 773: {
774: DPRINTF(("ucom_rts: onoff=%d\n", onoff));
775:
1.14 augustss 776: if (sc->sc_methods->ucom_set != NULL)
1.43 augustss 777: sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1.14 augustss 778: UCOM_SET_RTS, onoff);
1.12 augustss 779: }
780:
1.22 augustss 781: void
1.24 augustss 782: ucom_status_change(struct ucom_softc *sc)
1.12 augustss 783: {
1.27 toshii 784: struct tty *tp = sc->sc_tty;
785: u_char old_msr;
786:
1.14 augustss 787: if (sc->sc_methods->ucom_get_status != NULL) {
1.27 toshii 788: old_msr = sc->sc_msr;
1.14 augustss 789: sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
790: &sc->sc_lsr, &sc->sc_msr);
1.27 toshii 791: if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD))
1.32 eeh 792: (*tp->t_linesw->l_modem)(tp,
1.27 toshii 793: ISSET(sc->sc_msr, UMSR_DCD));
1.14 augustss 794: } else {
795: sc->sc_lsr = 0;
1.54 augustss 796: /* Assume DCD is present, if we have no chance to check it. */
797: sc->sc_msr = UMSR_DCD;
1.14 augustss 798: }
1.12 augustss 799: }
800:
1.17 augustss 801: Static int
1.24 augustss 802: ucomparam(struct tty *tp, struct termios *t)
1.12 augustss 803: {
804: struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
1.14 augustss 805: int error;
1.12 augustss 806:
807: if (sc->sc_dying)
808: return (EIO);
809:
810: /* Check requested parameters. */
811: if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
812: return (EINVAL);
813:
814: /*
815: * For the console, always force CLOCAL and !HUPCL, so that the port
816: * is always active.
817: */
818: if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
819: SET(t->c_cflag, CLOCAL);
820: CLR(t->c_cflag, HUPCL);
821: }
822:
823: /*
824: * If there were no changes, don't do anything. This avoids dropping
825: * input and improves performance when all we did was frob things like
826: * VMIN and VTIME.
827: */
828: if (tp->t_ospeed == t->c_ospeed &&
829: tp->t_cflag == t->c_cflag)
830: return (0);
831:
1.30 augustss 832: /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */
1.12 augustss 833:
834: /* And copy to tty. */
835: tp->t_ispeed = 0;
836: tp->t_ospeed = t->c_ospeed;
837: tp->t_cflag = t->c_cflag;
838:
1.14 augustss 839: if (sc->sc_methods->ucom_param != NULL) {
840: error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
841: t);
842: if (error)
843: return (error);
844: }
1.12 augustss 845:
1.30 augustss 846: /* XXX worry about CHWFLOW */
1.12 augustss 847:
848: /*
849: * Update the tty layer's idea of the carrier bit, in case we changed
850: * CLOCAL or MDMBUF. We don't hang up here; we only do that by
851: * explicit request.
852: */
853: DPRINTF(("ucomparam: l_modem\n"));
1.54 augustss 854: (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD));
1.12 augustss 855:
856: #if 0
857: XXX what if the hardware is not open
858: if (!ISSET(t->c_cflag, CHWFLOW)) {
859: if (sc->sc_tx_stopped) {
860: sc->sc_tx_stopped = 0;
861: ucomstart(tp);
862: }
863: }
864: #endif
865:
866: return (0);
867: }
868:
869: /*
870: * (un)block input via hw flowcontrol
871: */
1.17 augustss 872: Static void
1.24 augustss 873: ucom_hwiflow(struct ucom_softc *sc)
1.12 augustss 874: {
1.19 augustss 875: DPRINTF(("ucom_hwiflow:\n"));
1.12 augustss 876: #if 0
877: XXX
878: bus_space_tag_t iot = sc->sc_iot;
879: bus_space_handle_t ioh = sc->sc_ioh;
880:
881: if (sc->sc_mcr_rts == 0)
882: return;
883:
884: if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
885: CLR(sc->sc_mcr, sc->sc_mcr_rts);
886: CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
887: } else {
888: SET(sc->sc_mcr, sc->sc_mcr_rts);
889: SET(sc->sc_mcr_active, sc->sc_mcr_rts);
890: }
891: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active);
892: #endif
1.1 augustss 893: }
1.3 augustss 894:
1.17 augustss 895: Static void
1.24 augustss 896: ucomstart(struct tty *tp)
1.12 augustss 897: {
898: struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
899: usbd_status err;
900: int s;
901: u_char *data;
902: int cnt;
903:
904: if (sc->sc_dying)
905: return;
906:
907: s = spltty();
908: if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) {
1.19 augustss 909: DPRINTFN(4,("ucomstart: no go, state=0x%x\n", tp->t_state));
1.12 augustss 910: goto out;
911: }
912: if (sc->sc_tx_stopped)
913: goto out;
914:
915: if (tp->t_outq.c_cc <= tp->t_lowat) {
916: if (ISSET(tp->t_state, TS_ASLEEP)) {
917: CLR(tp->t_state, TS_ASLEEP);
918: wakeup(&tp->t_outq);
919: }
920: selwakeup(&tp->t_wsel);
921: if (tp->t_outq.c_cc == 0)
922: goto out;
923: }
924:
925: /* Grab the first contiguous region of buffer space. */
926: data = tp->t_outq.c_cf;
927: cnt = ndqb(&tp->t_outq, 0);
928:
929: if (cnt == 0) {
930: DPRINTF(("ucomstart: cnt==0\n"));
931: goto out;
932: }
933:
934: SET(tp->t_state, TS_BUSY);
935:
1.19 augustss 936: if (cnt > sc->sc_obufsize) {
1.12 augustss 937: DPRINTF(("ucomstart: big buffer %d chars\n", cnt));
1.19 augustss 938: cnt = sc->sc_obufsize;
1.12 augustss 939: }
1.22 augustss 940: if (sc->sc_methods->ucom_write != NULL)
941: sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
942: sc->sc_obuf, data, &cnt);
943: else
944: memcpy(sc->sc_obuf, data, cnt);
1.12 augustss 945:
946: DPRINTFN(4,("ucomstart: %d chars\n", cnt));
1.43 augustss 947: usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe,
1.12 augustss 948: (usbd_private_handle)sc, sc->sc_obuf, cnt,
949: USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
950: /* What can we do on error? */
951: err = usbd_transfer(sc->sc_oxfer);
952: #ifdef DIAGNOSTIC
953: if (err != USBD_IN_PROGRESS)
954: printf("ucomstart: err=%s\n", usbd_errstr(err));
1.3 augustss 955: #endif
956:
1.12 augustss 957: out:
958: splx(s);
959: }
960:
1.21 itojun 961: void
1.24 augustss 962: ucomstop(struct tty *tp, int flag)
1.12 augustss 963: {
1.19 augustss 964: DPRINTF(("ucomstop: flag=%d\n", flag));
965: #if 0
966: /*struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];*/
1.12 augustss 967: int s;
968:
969: s = spltty();
970: if (ISSET(tp->t_state, TS_BUSY)) {
971: DPRINTF(("ucomstop: XXX\n"));
1.19 augustss 972: /* sc->sc_tx_stopped = 1; */
1.12 augustss 973: if (!ISSET(tp->t_state, TS_TTSTOP))
974: SET(tp->t_state, TS_FLUSH);
975: }
976: splx(s);
1.19 augustss 977: #endif
1.12 augustss 978: }
979:
1.17 augustss 980: Static void
1.24 augustss 981: ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
1.12 augustss 982: {
983: struct ucom_softc *sc = (struct ucom_softc *)p;
984: struct tty *tp = sc->sc_tty;
985: u_int32_t cc;
986: int s;
987:
988: DPRINTFN(5,("ucomwritecb: status=%d\n", status));
989:
1.34 augustss 990: if (status == USBD_CANCELLED || sc->sc_dying)
1.39 augustss 991: goto error;
1.12 augustss 992:
993: if (status) {
994: DPRINTF(("ucomwritecb: status=%d\n", status));
995: usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
996: /* XXX we should restart after some delay. */
1.39 augustss 997: goto error;
1.12 augustss 998: }
999:
1.15 augustss 1000: usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
1.31 explorer 1001: #if defined(__NetBSD__) && NRND > 0
1002: rnd_add_uint32(&sc->sc_rndsource, cc);
1003: #endif
1.12 augustss 1004: DPRINTFN(5,("ucomwritecb: cc=%d\n", cc));
1.25 augustss 1005: /* convert from USB bytes to tty bytes */
1006: cc -= sc->sc_opkthdrlen;
1.12 augustss 1007:
1008: s = spltty();
1009: CLR(tp->t_state, TS_BUSY);
1010: if (ISSET(tp->t_state, TS_FLUSH))
1011: CLR(tp->t_state, TS_FLUSH);
1012: else
1013: ndflush(&tp->t_outq, cc);
1.32 eeh 1014: (*tp->t_linesw->l_start)(tp);
1.39 augustss 1015: splx(s);
1016: return;
1017:
1018: error:
1019: s = spltty();
1020: CLR(tp->t_state, TS_BUSY);
1.12 augustss 1021: splx(s);
1022: }
1023:
1.17 augustss 1024: Static usbd_status
1.24 augustss 1025: ucomstartread(struct ucom_softc *sc)
1.12 augustss 1026: {
1027: usbd_status err;
1028:
1029: DPRINTFN(5,("ucomstartread: start\n"));
1.43 augustss 1030: usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe,
1031: (usbd_private_handle)sc,
1.19 augustss 1032: sc->sc_ibuf, sc->sc_ibufsize,
1.12 augustss 1033: USBD_SHORT_XFER_OK | USBD_NO_COPY,
1034: USBD_NO_TIMEOUT, ucomreadcb);
1035: err = usbd_transfer(sc->sc_ixfer);
1036: if (err != USBD_IN_PROGRESS) {
1037: DPRINTF(("ucomstartread: err=%s\n", usbd_errstr(err)));
1038: return (err);
1039: }
1040: return (USBD_NORMAL_COMPLETION);
1041: }
1.43 augustss 1042:
1.17 augustss 1043: Static void
1.24 augustss 1044: ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
1.12 augustss 1045: {
1046: struct ucom_softc *sc = (struct ucom_softc *)p;
1047: struct tty *tp = sc->sc_tty;
1.55 christos 1048: int (*rint)(int, struct tty *) = tp->t_linesw->l_rint;
1.12 augustss 1049: usbd_status err;
1050: u_int32_t cc;
1051: u_char *cp;
1052: int s;
1053:
1.34 augustss 1054: DPRINTFN(5,("ucomreadcb: status=%d\n", status));
1055:
1056: if (status == USBD_CANCELLED || status == USBD_IOERROR ||
1057: sc->sc_dying) {
1058: DPRINTF(("ucomreadcb: dying\n"));
1059: /* Send something to wake upper layer */
1060: s = spltty();
1061: (*rint)('\n', tp);
1062: ttwakeup(tp);
1063: splx(s);
1.12 augustss 1064: return;
1.34 augustss 1065: }
1.12 augustss 1066:
1067: if (status) {
1068: usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1069: /* XXX we should restart after some delay. */
1070: return;
1071: }
1072:
1.48 thorpej 1073: usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
1.31 explorer 1074: #if defined(__NetBSD__) && NRND > 0
1075: rnd_add_uint32(&sc->sc_rndsource, cc);
1076: #endif
1.12 augustss 1077: DPRINTFN(5,("ucomreadcb: got %d chars, tp=%p\n", cc, tp));
1.22 augustss 1078: if (sc->sc_methods->ucom_read != NULL)
1079: sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
1080: &cp, &cc);
1081:
1.12 augustss 1082: s = spltty();
1083: /* Give characters to tty layer. */
1084: while (cc-- > 0) {
1085: DPRINTFN(7,("ucomreadcb: char=0x%02x\n", *cp));
1086: if ((*rint)(*cp++, tp) == -1) {
1087: /* XXX what should we do? */
1.19 augustss 1088: printf("%s: lost %d chars\n", USBDEVNAME(sc->sc_dev),
1089: cc);
1.12 augustss 1090: break;
1091: }
1092: }
1093: splx(s);
1094:
1095: err = ucomstartread(sc);
1096: if (err) {
1097: printf("%s: read start failed\n", USBDEVNAME(sc->sc_dev));
1098: /* XXX what should we dow now? */
1099: }
1100: }
1101:
1.17 augustss 1102: Static void
1.24 augustss 1103: ucom_cleanup(struct ucom_softc *sc)
1.12 augustss 1104: {
1105: DPRINTF(("ucom_cleanup: closing pipes\n"));
1106:
1107: ucom_shutdown(sc);
1.33 augustss 1108: if (sc->sc_bulkin_pipe != NULL) {
1109: usbd_abort_pipe(sc->sc_bulkin_pipe);
1110: usbd_close_pipe(sc->sc_bulkin_pipe);
1111: sc->sc_bulkin_pipe = NULL;
1112: }
1113: if (sc->sc_bulkout_pipe != NULL) {
1114: usbd_abort_pipe(sc->sc_bulkout_pipe);
1115: usbd_close_pipe(sc->sc_bulkout_pipe);
1116: sc->sc_bulkout_pipe = NULL;
1117: }
1118: if (sc->sc_ixfer != NULL) {
1119: usbd_free_xfer(sc->sc_ixfer);
1120: sc->sc_ixfer = NULL;
1121: }
1122: if (sc->sc_oxfer != NULL) {
1123: usbd_free_xfer(sc->sc_oxfer);
1124: sc->sc_oxfer = NULL;
1125: }
1.12 augustss 1126: }
1.13 augustss 1127:
1128: #endif /* NUCOM > 0 */
1.12 augustss 1129:
1.20 augustss 1130: int
1.24 augustss 1131: ucomprint(void *aux, const char *pnp)
1.12 augustss 1132: {
1.37 augustss 1133: struct ucom_attach_args *uca = aux;
1.12 augustss 1134:
1135: if (pnp)
1.49 thorpej 1136: aprint_normal("ucom at %s", pnp);
1.37 augustss 1137: if (uca->portno != UCOM_UNK_PORTNO)
1.49 thorpej 1138: aprint_normal(" portno %d", uca->portno);
1.12 augustss 1139: return (UNCONF);
1140: }
1141:
1.20 augustss 1142: int
1.53 drochner 1143: ucomsubmatch(struct device *parent, struct cfdata *cf,
1.57 drochner 1144: const int *ldesc, void *aux)
1.12 augustss 1145: {
1146: struct ucom_attach_args *uca = aux;
1147:
1148: if (uca->portno != UCOM_UNK_PORTNO &&
1.53 drochner 1149: cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT &&
1150: cf->cf_loc[UCOMBUSCF_PORTNO] != uca->portno)
1.12 augustss 1151: return (0);
1.46 thorpej 1152: return (config_match(parent, cf, aux));
1.12 augustss 1153: }
CVSweb <webmaster@jp.NetBSD.org>