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

Cache object: 8b1bc0ce2fb20f404492d96b05ea9f57


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