The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/qbus/dl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: dl.c,v 1.49 2014/07/25 08:10:38 dholland Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1997  Ben Harris.  All rights reserved.
   34  * Copyright (c) 1982, 1986, 1990, 1992, 1993
   35  *      The Regents of the University of California.  All rights reserved.
   36  *
   37  * This code is derived from software contributed to Berkeley by
   38  * Ralph Campbell and Rick Macklem.
   39  *
   40  * Redistribution and use in source and binary forms, with or without
   41  * modification, are permitted provided that the following conditions
   42  * are met:
   43  * 1. Redistributions of source code must retain the above copyright
   44  *    notice, this list of conditions and the following disclaimer.
   45  * 2. Redistributions in binary form must reproduce the above copyright
   46  *    notice, this list of conditions and the following disclaimer in the
   47  *    documentation and/or other materials provided with the distribution.
   48  * 3. Neither the name of the University nor the names of its contributors
   49  *    may be used to endorse or promote products derived from this software
   50  *    without specific prior written permission.
   51  *
   52  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   62  * SUCH DAMAGE.
   63  */
   64 
   65 /*
   66  * Copyright (c) 1996  Ken C. Wellsch.  All rights reserved.
   67  *
   68  * This code is derived from software contributed to Berkeley by
   69  * Ralph Campbell and Rick Macklem.
   70  *
   71  * Redistribution and use in source and binary forms, with or without
   72  * modification, are permitted provided that the following conditions
   73  * are met:
   74  * 1. Redistributions of source code must retain the above copyright
   75  *    notice, this list of conditions and the following disclaimer.
   76  * 2. Redistributions in binary form must reproduce the above copyright
   77  *    notice, this list of conditions and the following disclaimer in the
   78  *    documentation and/or other materials provided with the distribution.
   79  * 3. All advertising materials mentioning features or use of this software
   80  *    must display the following acknowledgement:
   81  *      This product includes software developed by the University of
   82  *      California, Berkeley and its contributors.
   83  * 4. Neither the name of the University nor the names of its contributors
   84  *    may be used to endorse or promote products derived from this software
   85  *    without specific prior written permission.
   86  *
   87  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   88  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   89  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   90  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   91  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   92  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   93  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   94  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   95  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   96  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   97  * SUCH DAMAGE.
   98  */
   99 
  100 /*
  101  * dl.c -- Device driver for the DL11 and DLV11 serial cards.
  102  *
  103  * OS-interface code derived from the dz and dca (hp300) drivers.
  104  */
  105 
  106 #include <sys/cdefs.h>
  107 __KERNEL_RCSID(0, "$NetBSD: dl.c,v 1.49 2014/07/25 08:10:38 dholland Exp $");
  108 
  109 #include <sys/param.h>
  110 #include <sys/systm.h>
  111 #include <sys/ioctl.h>
  112 #include <sys/tty.h>
  113 #include <sys/proc.h>
  114 #include <sys/buf.h>
  115 #include <sys/conf.h>
  116 #include <sys/file.h>
  117 #include <sys/uio.h>
  118 #include <sys/kernel.h>
  119 #include <sys/syslog.h>
  120 #include <sys/device.h>
  121 #include <sys/kauth.h>
  122 
  123 #include <sys/bus.h>
  124 
  125 #include <dev/qbus/ubavar.h>
  126 
  127 #include <dev/qbus/dlreg.h>
  128 
  129 #include "ioconf.h"
  130 
  131 struct dl_softc {
  132         device_t        sc_dev;
  133         struct evcnt    sc_rintrcnt;
  134         struct evcnt    sc_tintrcnt;
  135         bus_space_tag_t sc_iot;
  136         bus_space_handle_t sc_ioh;
  137         struct tty      *sc_tty;
  138 };
  139 
  140 static  int     dl_match (device_t, cfdata_t, void *);
  141 static  void    dl_attach (device_t, device_t, void *);
  142 static  void    dlrint (void *);
  143 static  void    dlxint (void *);
  144 static  void    dlstart (struct tty *);
  145 static  int     dlparam (struct tty *, struct termios *);
  146 static  void    dlbrk (struct dl_softc *, int);
  147 
  148 CFATTACH_DECL_NEW(dl, sizeof(struct dl_softc),
  149     dl_match, dl_attach, NULL, NULL);
  150 
  151 dev_type_open(dlopen);
  152 dev_type_close(dlclose);
  153 dev_type_read(dlread);
  154 dev_type_write(dlwrite);
  155 dev_type_ioctl(dlioctl);
  156 dev_type_stop(dlstop);
  157 dev_type_tty(dltty);
  158 dev_type_poll(dlpoll);
  159 
  160 const struct cdevsw dl_cdevsw = {
  161         .d_open = dlopen,
  162         .d_close = dlclose,
  163         .d_read = dlread,
  164         .d_write = dlwrite,
  165         .d_ioctl = dlioctl,
  166         .d_stop = dlstop,
  167         .d_tty = dltty,
  168         .d_poll = dlpoll,
  169         .d_mmap = nommap,
  170         .d_kqfilter = ttykqfilter,
  171         .d_discard = nodiscard,
  172         .d_flag = D_TTY
  173 };
  174 
  175 #define DL_READ_WORD(reg) \
  176         bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
  177 #define DL_WRITE_WORD(reg, val) \
  178         bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
  179 #define DL_WRITE_BYTE(reg, val) \
  180         bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
  181 
  182 /* Autoconfig handles: setup the controller to interrupt, */
  183 /* then complete the housecleaning for full operation */
  184 
  185 static int
  186 dl_match (device_t parent, cfdata_t cf, void *aux)
  187 {
  188         struct uba_attach_args *ua = aux;
  189 
  190 #ifdef DL_DEBUG
  191         printf("Probing for dl at %lo ... ", (long)ua->ua_iaddr);
  192 #endif
  193 
  194         bus_space_write_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR, DL_XCSR_TXIE);
  195         if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
  196             (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
  197 #ifdef DL_DEBUG
  198                 printf("failed (step 1; XCSR = %.4b)\n",
  199                     bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
  200                     DL_XCSR_BITS);
  201 #endif
  202                 return 0;
  203         }
  204 
  205         /*
  206          * We have to force an interrupt so the uba driver can work
  207          * out where we are.  Unfortunately, the only way to make a
  208          * DL11 interrupt is to get it to send or receive a
  209          * character.  We'll send a NUL and hope it doesn't hurt
  210          * anything.
  211          */
  212 
  213         bus_space_write_1(ua->ua_iot, ua->ua_ioh, DL_UBA_XBUFL, '\0');
  214 #if 0 /* This test seems to fail 2/3 of the time :-( */
  215         if (dladdr->dl_xcsr != (DL_XCSR_TXIE)) {
  216 #ifdef DL_DEBUG
  217                 printf("failed (step 2; XCSR = %.4b)\n", dladdr->dl_xcsr,
  218                     DL_XCSR_BITS);
  219 #endif
  220                 return 0;
  221         }
  222 #endif
  223         DELAY(100000); /* delay 1/10 s for character to transmit */
  224         if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
  225             (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
  226 #ifdef DL_DEBUG
  227                 printf("failed (step 3; XCSR = %.4b)\n",
  228                     bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
  229                     DL_XCSR_BITS);
  230 #endif
  231                 return 0;
  232         }
  233 
  234 
  235         /* What else do I need to do? */
  236 
  237         return 1;
  238 
  239 }
  240 
  241 static void
  242 dl_attach (device_t parent, device_t self, void *aux)
  243 {
  244         struct dl_softc *sc = device_private(self);
  245         struct uba_attach_args *ua = aux;
  246 
  247         sc->sc_dev = self;
  248         sc->sc_iot = ua->ua_iot;
  249         sc->sc_ioh = ua->ua_ioh;
  250 
  251         /* Tidy up the device */
  252 
  253         DL_WRITE_WORD(DL_UBA_RCSR, DL_RCSR_RXIE);
  254         DL_WRITE_WORD(DL_UBA_XCSR, DL_XCSR_TXIE);
  255 
  256         /* Initialize our softc structure. Should be done in open? */
  257 
  258         sc->sc_tty = tty_alloc();
  259         tty_attach(sc->sc_tty);
  260 
  261         /* Now register the TX & RX interrupt handlers */
  262         uba_intr_establish(ua->ua_icookie, ua->ua_cvec,
  263                 dlxint, sc, &sc->sc_tintrcnt);
  264         uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4,
  265                 dlrint, sc, &sc->sc_rintrcnt);
  266         evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  267                 device_xname(sc->sc_dev), "rintr");
  268         evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  269                 device_xname(sc->sc_dev), "tintr");
  270 
  271         printf("\n");
  272 }
  273 
  274 /* Receiver Interrupt Handler */
  275 
  276 static void
  277 dlrint(void *arg)
  278 {
  279         struct dl_softc *sc = arg;
  280 
  281         if (DL_READ_WORD(DL_UBA_RCSR) & DL_RCSR_RX_DONE) {
  282                 struct tty *tp = sc->sc_tty;
  283                 unsigned c;
  284                 int cc;
  285 
  286                 c = DL_READ_WORD(DL_UBA_RBUF);
  287                 cc = c & 0xFF;
  288 
  289                 if (!(tp->t_state & TS_ISOPEN)) {
  290                         cv_broadcast(&tp->t_rawcv);
  291                         return;
  292                 }
  293 
  294                 if (c & DL_RBUF_OVERRUN_ERR) {
  295                         /*
  296                          * XXX: This should really be logged somwhere
  297                          * else where we can afford the time.
  298                          */
  299                         log(LOG_WARNING, "%s: rx overrun\n",
  300                             device_xname(sc->sc_dev));
  301                 }
  302                 if (c & DL_RBUF_FRAMING_ERR)
  303                         cc |= TTY_FE;
  304                 if (c & DL_RBUF_PARITY_ERR)
  305                         cc |= TTY_PE;
  306 
  307                 (*tp->t_linesw->l_rint)(cc, tp);
  308 #if defined(DIAGNOSTIC)
  309         } else {
  310                 log(LOG_WARNING, "%s: stray rx interrupt\n",
  311                     device_xname(sc->sc_dev));
  312 #endif
  313         }
  314 }
  315 
  316 /* Transmitter Interrupt Handler */
  317 
  318 static void
  319 dlxint(void *arg)
  320 {
  321         struct dl_softc *sc = arg;
  322         struct tty *tp = sc->sc_tty;
  323 
  324         tp->t_state &= ~(TS_BUSY | TS_FLUSH);
  325         (*tp->t_linesw->l_start)(tp);
  326 
  327         return;
  328 }
  329 
  330 int
  331 dlopen(dev_t dev, int flag, int mode, struct lwp *l)
  332 {
  333         struct tty *tp;
  334         struct dl_softc *sc;
  335         int unit;
  336 
  337         unit = minor(dev);
  338 
  339         sc = device_lookup_private(&dl_cd, unit);
  340         if (!sc)
  341                 return ENXIO;
  342 
  343         tp = sc->sc_tty;
  344         if (tp == NULL)
  345                 return ENODEV;
  346         tp->t_oproc = dlstart;
  347         tp->t_param = dlparam;
  348         tp->t_dev = dev;
  349 
  350         if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
  351                 return (EBUSY);
  352 
  353         if (!(tp->t_state & TS_ISOPEN)) {
  354                 ttychars(tp);
  355                 tp->t_iflag = TTYDEF_IFLAG;
  356                 tp->t_oflag = TTYDEF_OFLAG;
  357                 /* No modem control, so set CLOCAL. */
  358                 tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
  359                 tp->t_lflag = TTYDEF_LFLAG;
  360                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  361 
  362                 dlparam(tp, &tp->t_termios);
  363                 ttsetwater(tp);
  364 
  365         }
  366 
  367         return ((*tp->t_linesw->l_open)(dev, tp));
  368 }
  369 
  370 /*ARGSUSED*/
  371 int
  372 dlclose(dev_t dev, int flag, int mode, struct lwp *l)
  373 {
  374         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  375         struct tty *tp = sc->sc_tty;
  376 
  377         (*tp->t_linesw->l_close)(tp, flag);
  378 
  379         /* Make sure a BREAK state is not left enabled. */
  380         dlbrk(sc, 0);
  381 
  382         return (ttyclose(tp));
  383 }
  384 
  385 int
  386 dlread(dev_t dev, struct uio *uio, int flag)
  387 {
  388         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  389         struct tty *tp = sc->sc_tty;
  390 
  391         return ((*tp->t_linesw->l_read)(tp, uio, flag));
  392 }
  393 
  394 int
  395 dlwrite(dev_t dev, struct uio *uio, int flag)
  396 {
  397         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  398         struct tty *tp = sc->sc_tty;
  399 
  400         return ((*tp->t_linesw->l_write)(tp, uio, flag));
  401 }
  402 
  403 int
  404 dlpoll(dev_t dev, int events, struct lwp *l)
  405 {
  406         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  407         struct tty *tp = sc->sc_tty;
  408 
  409         return ((*tp->t_linesw->l_poll)(tp, events, l));
  410 }
  411 
  412 int
  413 dlioctl(dev_t dev, unsigned long cmd, void *data, int flag, struct lwp *l)
  414 {
  415         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  416         struct tty *tp = sc->sc_tty;
  417         int error;
  418 
  419 
  420         error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
  421         if (error != EPASSTHROUGH)
  422                 return (error);
  423 
  424         error = ttioctl(tp, cmd, data, flag, l);
  425         if (error != EPASSTHROUGH)
  426                 return (error);
  427 
  428         switch (cmd) {
  429 
  430         case TIOCSBRK:
  431                 dlbrk(sc, 1);
  432                 break;
  433 
  434         case TIOCCBRK:
  435                 dlbrk(sc, 0);
  436                 break;
  437 
  438         case TIOCMGET:
  439                 /* No modem control, assume they're all low. */
  440                 *(int *)data = 0;
  441                 break;
  442 
  443         default:
  444                 return (EPASSTHROUGH);
  445         }
  446         return (0);
  447 }
  448 
  449 struct tty *
  450 dltty(dev_t dev)
  451 {
  452         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  453 
  454         return sc->sc_tty;
  455 }
  456 
  457 void
  458 dlstop(struct tty *tp, int flag)
  459 {
  460         int s = spltty();
  461 
  462         if ((tp->t_state & (TS_BUSY|TS_TTSTOP)) == TS_BUSY)
  463                 tp->t_state |= TS_FLUSH;
  464         splx(s);
  465 }
  466 
  467 static void
  468 dlstart(struct tty *tp)
  469 {
  470         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(tp->t_dev));
  471         int s = spltty();
  472 
  473         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
  474                 goto out;
  475         if (!ttypull(tp))
  476                 goto out;
  477         if (DL_READ_WORD(DL_UBA_XCSR) & DL_XCSR_TX_READY) {
  478                 tp->t_state |= TS_BUSY;
  479                 DL_WRITE_BYTE(DL_UBA_XBUFL, getc(&tp->t_outq));
  480         }
  481 out:
  482         splx(s);
  483         return;
  484 }
  485 
  486 /*ARGSUSED*/
  487 static int
  488 dlparam(struct tty *tp, struct termios *t)
  489 {
  490         /*
  491          * All this kind of stuff (speed, character format, whatever)
  492          * is set by jumpers on the card.  Changing it is thus rather
  493          * tricky for a mere device driver.
  494          */
  495         return 0;
  496 }
  497 
  498 static void
  499 dlbrk(struct dl_softc *sc, int state)
  500 {
  501         int s = spltty();
  502 
  503         if (state) {
  504                 DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) |
  505                     DL_XCSR_TX_BREAK);
  506         } else {
  507                 DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) &
  508                     ~DL_XCSR_TX_BREAK);
  509         }
  510         splx(s);
  511 }

Cache object: e5c1240f10b6a66cb899aebd2f58c16f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.