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.43 2008/06/11 17:32:30 drochner 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.43 2008/06/11 17:32:30 drochner 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         struct device   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 (struct device *, struct cfdata *, void *);
  141 static  void    dl_attach (struct device *, struct device *, 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(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         dlopen, dlclose, dlread, dlwrite, dlioctl,
  162         dlstop, dltty, dlpoll, nommap, ttykqfilter, D_TTY
  163 };
  164 
  165 #define DL_READ_WORD(reg) \
  166         bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
  167 #define DL_WRITE_WORD(reg, val) \
  168         bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
  169 #define DL_WRITE_BYTE(reg, val) \
  170         bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
  171 
  172 /* Autoconfig handles: setup the controller to interrupt, */
  173 /* then complete the housecleaning for full operation */
  174 
  175 static int
  176 dl_match (struct device *parent, struct cfdata *cf, void *aux)
  177 {
  178         struct uba_attach_args *ua = aux;
  179 
  180 #ifdef DL_DEBUG
  181         printf("Probing for dl at %lo ... ", (long)ua->ua_iaddr);
  182 #endif
  183 
  184         bus_space_write_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR, DL_XCSR_TXIE);
  185         if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
  186             (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
  187 #ifdef DL_DEBUG
  188                 printf("failed (step 1; XCSR = %.4b)\n",
  189                     bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
  190                     DL_XCSR_BITS);
  191 #endif
  192                 return 0;
  193         }
  194 
  195         /*
  196          * We have to force an interrupt so the uba driver can work
  197          * out where we are.  Unfortunately, the only way to make a
  198          * DL11 interrupt is to get it to send or receive a
  199          * character.  We'll send a NUL and hope it doesn't hurt
  200          * anything.
  201          */
  202 
  203         bus_space_write_1(ua->ua_iot, ua->ua_ioh, DL_UBA_XBUFL, '\0');
  204 #if 0 /* This test seems to fail 2/3 of the time :-( */
  205         if (dladdr->dl_xcsr != (DL_XCSR_TXIE)) {
  206 #ifdef DL_DEBUG
  207                 printf("failed (step 2; XCSR = %.4b)\n", dladdr->dl_xcsr,
  208                     DL_XCSR_BITS);
  209 #endif
  210                 return 0;
  211         }
  212 #endif
  213         DELAY(100000); /* delay 1/10 s for character to transmit */
  214         if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
  215             (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
  216 #ifdef DL_DEBUG
  217                 printf("failed (step 3; XCSR = %.4b)\n",
  218                     bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
  219                     DL_XCSR_BITS);
  220 #endif
  221                 return 0;
  222         }
  223 
  224 
  225         /* What else do I need to do? */
  226 
  227         return 1;
  228 
  229 }
  230 
  231 static void
  232 dl_attach (struct device *parent, struct device *self, void *aux)
  233 {
  234         struct dl_softc *sc = device_private(self);
  235         struct uba_attach_args *ua = aux;
  236 
  237         sc->sc_iot = ua->ua_iot;
  238         sc->sc_ioh = ua->ua_ioh;
  239 
  240         /* Tidy up the device */
  241 
  242         DL_WRITE_WORD(DL_UBA_RCSR, DL_RCSR_RXIE);
  243         DL_WRITE_WORD(DL_UBA_XCSR, DL_XCSR_TXIE);
  244 
  245         /* Initialize our softc structure. Should be done in open? */
  246 
  247         sc->sc_tty = ttymalloc();
  248         tty_attach(sc->sc_tty);
  249 
  250         /* Now register the TX & RX interrupt handlers */
  251         uba_intr_establish(ua->ua_icookie, ua->ua_cvec,
  252                 dlxint, sc, &sc->sc_tintrcnt);
  253         uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4,
  254                 dlrint, sc, &sc->sc_rintrcnt);
  255         evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  256                 device_xname(&sc->sc_dev), "rintr");
  257         evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  258                 device_xname(&sc->sc_dev), "tintr");
  259 
  260         printf("\n");
  261 }
  262 
  263 /* Receiver Interrupt Handler */
  264 
  265 static void
  266 dlrint(void *arg)
  267 {
  268         struct dl_softc *sc = arg;
  269 
  270         if (DL_READ_WORD(DL_UBA_RCSR) & DL_RCSR_RX_DONE) {
  271                 struct tty *tp = sc->sc_tty;
  272                 unsigned c;
  273                 int cc;
  274 
  275                 c = DL_READ_WORD(DL_UBA_RBUF);
  276                 cc = c & 0xFF;
  277 
  278                 if (!(tp->t_state & TS_ISOPEN)) {
  279                         cv_broadcast(&tp->t_rawcv);
  280                         return;
  281                 }
  282 
  283                 if (c & DL_RBUF_OVERRUN_ERR) {
  284                         /*
  285                          * XXX: This should really be logged somwhere
  286                          * else where we can afford the time.
  287                          */
  288                         log(LOG_WARNING, "%s: rx overrun\n",
  289                             device_xname(&sc->sc_dev));
  290                 }
  291                 if (c & DL_RBUF_FRAMING_ERR)
  292                         cc |= TTY_FE;
  293                 if (c & DL_RBUF_PARITY_ERR)
  294                         cc |= TTY_PE;
  295 
  296                 (*tp->t_linesw->l_rint)(cc, tp);
  297 #if defined(DIAGNOSTIC)
  298         } else {
  299                 log(LOG_WARNING, "%s: stray rx interrupt\n",
  300                     device_xname(&sc->sc_dev));
  301 #endif
  302         }
  303 }
  304 
  305 /* Transmitter Interrupt Handler */
  306 
  307 static void
  308 dlxint(void *arg)
  309 {
  310         struct dl_softc *sc = arg;
  311         struct tty *tp = sc->sc_tty;
  312 
  313         tp->t_state &= ~(TS_BUSY | TS_FLUSH);
  314         (*tp->t_linesw->l_start)(tp);
  315 
  316         return;
  317 }
  318 
  319 int
  320 dlopen(dev_t dev, int flag, int mode, struct lwp *l)
  321 {
  322         struct tty *tp;
  323         struct dl_softc *sc;
  324         int unit;
  325 
  326         unit = minor(dev);
  327 
  328         sc = device_lookup_private(&dl_cd, unit);
  329         if (!sc)
  330                 return ENXIO;
  331 
  332         tp = sc->sc_tty;
  333         if (tp == NULL)
  334                 return ENODEV;
  335         tp->t_oproc = dlstart;
  336         tp->t_param = dlparam;
  337         tp->t_dev = dev;
  338 
  339         if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
  340                 return (EBUSY);
  341 
  342         if (!(tp->t_state & TS_ISOPEN)) {
  343                 ttychars(tp);
  344                 tp->t_iflag = TTYDEF_IFLAG;
  345                 tp->t_oflag = TTYDEF_OFLAG;
  346                 /* No modem control, so set CLOCAL. */
  347                 tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
  348                 tp->t_lflag = TTYDEF_LFLAG;
  349                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  350 
  351                 dlparam(tp, &tp->t_termios);
  352                 ttsetwater(tp);
  353 
  354         }
  355 
  356         return ((*tp->t_linesw->l_open)(dev, tp));
  357 }
  358 
  359 /*ARGSUSED*/
  360 int
  361 dlclose(dev_t dev, int flag, int mode, struct lwp *l)
  362 {
  363         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  364         struct tty *tp = sc->sc_tty;
  365 
  366         (*tp->t_linesw->l_close)(tp, flag);
  367 
  368         /* Make sure a BREAK state is not left enabled. */
  369         dlbrk(sc, 0);
  370 
  371         return (ttyclose(tp));
  372 }
  373 
  374 int
  375 dlread(dev_t dev, struct uio *uio, int flag)
  376 {
  377         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  378         struct tty *tp = sc->sc_tty;
  379 
  380         return ((*tp->t_linesw->l_read)(tp, uio, flag));
  381 }
  382 
  383 int
  384 dlwrite(dev_t dev, struct uio *uio, int flag)
  385 {
  386         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  387         struct tty *tp = sc->sc_tty;
  388 
  389         return ((*tp->t_linesw->l_write)(tp, uio, flag));
  390 }
  391 
  392 int
  393 dlpoll(dev_t dev, int events, struct lwp *l)
  394 {
  395         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  396         struct tty *tp = sc->sc_tty;
  397 
  398         return ((*tp->t_linesw->l_poll)(tp, events, l));
  399 }
  400 
  401 int
  402 dlioctl(dev_t dev, unsigned long cmd, void *data, int flag, struct lwp *l)
  403 {
  404         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  405         struct tty *tp = sc->sc_tty;
  406         int error;
  407 
  408 
  409         error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
  410         if (error != EPASSTHROUGH)
  411                 return (error);
  412 
  413         error = ttioctl(tp, cmd, data, flag, l);
  414         if (error != EPASSTHROUGH)
  415                 return (error);
  416 
  417         switch (cmd) {
  418 
  419         case TIOCSBRK:
  420                 dlbrk(sc, 1);
  421                 break;
  422 
  423         case TIOCCBRK:
  424                 dlbrk(sc, 0);
  425                 break;
  426 
  427         case TIOCMGET:
  428                 /* No modem control, assume they're all low. */
  429                 *(int *)data = 0;
  430                 break;
  431 
  432         default:
  433                 return (EPASSTHROUGH);
  434         }
  435         return (0);
  436 }
  437 
  438 struct tty *
  439 dltty(dev_t dev)
  440 {
  441         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(dev));
  442 
  443         return sc->sc_tty;
  444 }
  445 
  446 void
  447 dlstop(struct tty *tp, int flag)
  448 {
  449         int s = spltty();
  450 
  451         if ((tp->t_state & (TS_BUSY|TS_TTSTOP)) == TS_BUSY)
  452                 tp->t_state |= TS_FLUSH;
  453         splx(s);
  454 }
  455 
  456 static void
  457 dlstart(struct tty *tp)
  458 {
  459         struct dl_softc *sc = device_lookup_private(&dl_cd, minor(tp->t_dev));
  460         int s = spltty();
  461 
  462         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
  463                 goto out;
  464         if (!ttypull(tp))
  465                 goto out;
  466         if (DL_READ_WORD(DL_UBA_XCSR) & DL_XCSR_TX_READY) {
  467                 tp->t_state |= TS_BUSY;
  468                 DL_WRITE_BYTE(DL_UBA_XBUFL, getc(&tp->t_outq));
  469         }
  470 out:
  471         splx(s);
  472         return;
  473 }
  474 
  475 /*ARGSUSED*/
  476 static int
  477 dlparam(struct tty *tp, struct termios *t)
  478 {
  479         /*
  480          * All this kind of stuff (speed, character format, whatever)
  481          * is set by jumpers on the card.  Changing it is thus rather
  482          * tricky for a mere device driver.
  483          */
  484         return 0;
  485 }
  486 
  487 static void
  488 dlbrk(struct dl_softc *sc, int state)
  489 {
  490         int s = spltty();
  491 
  492         if (state) {
  493                 DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) |
  494                     DL_XCSR_TX_BREAK);
  495         } else {
  496                 DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) &
  497                     ~DL_XCSR_TX_BREAK);
  498         }
  499         splx(s);
  500 }

Cache object: 67b96f9ae322223ff823043de9ce76f0


[ 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.