root/dev/sbus/spif.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. spifmatch
  2. spifattach
  3. sttymatch
  4. sttyattach
  5. sttyopen
  6. sttyclose
  7. sttyioctl
  8. stty_modem_control
  9. stty_param
  10. sttyread
  11. sttywrite
  12. sttytty
  13. sttystop
  14. stty_start
  15. spifstcintr_rxexception
  16. spifstcintr_rx
  17. spifstcintr_tx
  18. spifstcintr_mx
  19. spifstcintr
  20. spifsoftintr
  21. stty_write_ccr
  22. stty_compute_baud
  23. sbppmatch
  24. sbppattach
  25. sbppopen
  26. sbppclose
  27. spifppcintr
  28. sbppread
  29. sbppwrite
  30. sbpp_rw
  31. sbpppoll
  32. sbppioctl

    1 /*      $OpenBSD: spif.c,v 1.13 2006/03/04 13:00:55 miod Exp $  */
    2 
    3 /*
    4  * Copyright (c) 1999-2002 Jason L. Wright (jason@thought.net)
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   26  * POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * Effort sponsored in part by the Defense Advanced Research Projects
   29  * Agency (DARPA) and Air Force Research Laboratory, Air Force
   30  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
   31  *
   32  */
   33 
   34 /*
   35  * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board
   36  * based heavily on Iain Hibbert's driver for the MAGMA cards
   37  */
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/proc.h>
   42 #include <sys/device.h>
   43 #include <sys/kernel.h>
   44 #include <sys/file.h>
   45 #include <sys/errno.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/socket.h>
   49 #include <sys/syslog.h>
   50 #include <sys/malloc.h>
   51 #include <sys/tty.h>
   52 #include <sys/conf.h>
   53 
   54 #include <machine/autoconf.h>
   55 #include <dev/sbus/sbusvar.h>
   56 #include <dev/sbus/spifreg.h>
   57 #include <dev/sbus/spifvar.h>
   58 
   59 int     spifmatch(struct device *, void *, void *);
   60 void    spifattach(struct device *, struct device *, void *);
   61 
   62 int     sttymatch(struct device *, void *, void *);
   63 void    sttyattach(struct device *, struct device *, void *);
   64 int     sttyopen(dev_t, int, int, struct proc *);
   65 int     sttyclose(dev_t, int, int, struct proc *);
   66 int     sttyread(dev_t, struct uio *, int);
   67 int     sttywrite(dev_t, struct uio *, int);
   68 int     sttyioctl(dev_t, u_long, caddr_t, int, struct proc *);
   69 int     sttystop(struct tty *, int);
   70 
   71 int     spifstcintr(void *);
   72 int     spifstcintr_mx(struct spif_softc *, int *);
   73 int     spifstcintr_tx(struct spif_softc *, int *);
   74 int     spifstcintr_rx(struct spif_softc *, int *);
   75 int     spifstcintr_rxexception(struct spif_softc *, int *);
   76 void    spifsoftintr(void *);
   77 
   78 int     stty_param(struct tty *, struct termios *);
   79 struct tty *sttytty(dev_t);
   80 int     stty_modem_control(struct stty_port *, int, int);
   81 void    stty_write_ccr(struct spif_softc *, u_int8_t);
   82 int     stty_compute_baud(speed_t, int, u_int8_t *, u_int8_t *);
   83 void    stty_start(struct tty *);
   84 
   85 int     sbppmatch(struct device *, void *, void *);
   86 void    sbppattach(struct device *, struct device *, void *);
   87 int     sbppopen(dev_t, int, int, struct proc *);
   88 int     sbppclose(dev_t, int, int, struct proc *);
   89 int     sbppread(dev_t, struct uio *, int);
   90 int     sbppwrite(dev_t, struct uio *, int);
   91 int     sbpp_rw(dev_t, struct uio *);
   92 int     spifppcintr(void *);
   93 int     sbpppoll(dev_t, int, struct proc *);
   94 int     sbppioctl(dev_t, u_long, caddr_t, int, struct proc *);
   95 
   96 struct cfattach spif_ca = {
   97         sizeof (struct spif_softc), spifmatch, spifattach
   98 };
   99 
  100 struct cfdriver spif_cd = {
  101         NULL, "spif", DV_DULL
  102 };
  103 
  104 struct cfattach stty_ca = {
  105         sizeof(struct stty_softc), sttymatch, sttyattach
  106 };
  107 
  108 struct cfdriver stty_cd = {
  109         NULL, "stty", DV_TTY
  110 };
  111 
  112 struct cfattach sbpp_ca = {
  113         sizeof(struct sbpp_softc), sbppmatch, sbppattach
  114 };
  115 
  116 struct cfdriver sbpp_cd = {
  117         NULL, "sbpp", DV_DULL
  118 };
  119 
  120 /* normal STC access */
  121 #define STC_WRITE(sc,r,v)       \
  122     bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v))
  123 #define STC_READ(sc,r)          \
  124     bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r))
  125 
  126 /* IACK STC access */
  127 #define ISTC_WRITE(sc,r,v)      \
  128     bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v))
  129 #define ISTC_READ(sc,r)         \
  130     bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r))
  131 
  132 /* PPC access */
  133 #define PPC_WRITE(sc,r,v)       \
  134     bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v))
  135 #define PPC_READ(sc,r)          \
  136     bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r))
  137 
  138 #define DTR_WRITE(sc,port,v)                                            \
  139     do {                                                                \
  140         sc->sc_ttys->sc_port[(port)].sp_dtr = v;                        \
  141         bus_space_write_1((sc)->sc_bustag,                              \
  142             sc->sc_dtrh, port, (v == 0) ? 1 : 0);                       \
  143     } while (0)
  144 
  145 #define DTR_READ(sc,port)       ((sc)->sc_ttys->sc_port[(port)].sp_dtr)
  146 
  147 int
  148 spifmatch(parent, vcf, aux)
  149         struct device *parent;
  150         void *vcf, *aux;
  151 {
  152         struct cfdata *cf = vcf;
  153         struct sbus_attach_args *sa = aux;
  154 
  155         if (strcmp(cf->cf_driver->cd_name, sa->sa_name) &&
  156             strcmp("SUNW,spif", sa->sa_name))
  157                 return (0);
  158         return (1);
  159 }
  160 
  161 void    
  162 spifattach(parent, self, aux)
  163         struct device *parent, *self;
  164         void *aux;
  165 {
  166         struct spif_softc *sc = (struct spif_softc *)self;
  167         struct sbus_attach_args *sa = aux;
  168 
  169         if (sa->sa_nintr != 2) {
  170                 printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr);
  171                 return;
  172         }
  173 
  174         if (sa->sa_nreg != 1) {
  175                 printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
  176                 return;
  177         }
  178 
  179         sc->sc_bustag = sa->sa_bustag;
  180         if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
  181             sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
  182             0, 0, &sc->sc_regh) != 0) {
  183                 printf(": can't map registers\n");
  184                 return;
  185         }
  186 
  187         if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
  188             DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) {
  189                 printf(": can't map dtr regs\n");
  190                 goto fail_unmapregs;
  191         }
  192 
  193         if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
  194             STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) {
  195                 printf(": can't map dtr regs\n");
  196                 goto fail_unmapregs;
  197         }
  198 
  199         if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
  200             ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) {
  201                 printf(": can't map dtr regs\n");
  202                 goto fail_unmapregs;
  203         }
  204 
  205         if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
  206             PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) {
  207                 printf(": can't map dtr regs\n");
  208                 goto fail_unmapregs;
  209         }
  210 
  211         sc->sc_ppcih = bus_intr_establish(sa->sa_bustag,
  212             sa->sa_intr[PARALLEL_INTR].sbi_pri, IPL_TTY, 0, spifppcintr, sc,
  213             self->dv_xname);
  214         if (sc->sc_ppcih == NULL) {
  215                 printf(": failed to establish ppc interrupt\n");
  216                 goto fail_unmapregs;
  217         }
  218 
  219         sc->sc_stcih = bus_intr_establish(sa->sa_bustag,
  220             sa->sa_intr[SERIAL_INTR].sbi_pri, IPL_TTY, 0, spifstcintr, sc,
  221             self->dv_xname);
  222         if (sc->sc_stcih == NULL) {
  223                 printf(": failed to establish stc interrupt\n");
  224                 goto fail_unmapregs;
  225         }
  226 
  227         sc->sc_softih = softintr_establish(IPL_TTY, spifsoftintr, sc);
  228         if (sc->sc_softih == NULL) {
  229                 printf(": can't get soft intr\n");
  230                 goto fail_unmapregs;
  231         }
  232 
  233         sc->sc_node = sa->sa_node;
  234 
  235         sc->sc_rev = getpropint(sc->sc_node, "revlev", 0);
  236 
  237         sc->sc_osc = getpropint(sc->sc_node, "verosc", 0);
  238         switch (sc->sc_osc) {
  239         case SPIF_OSC10:
  240                 sc->sc_osc = 10000000;
  241                 break;
  242         case SPIF_OSC9:
  243         default:
  244                 sc->sc_osc = 9830400;
  245                 break;
  246         }
  247 
  248         sc->sc_nser = 8;
  249         sc->sc_npar = 1;
  250 
  251         sc->sc_rev2 = STC_READ(sc, STC_GFRCR);
  252         STC_WRITE(sc, STC_GSVR, 0);
  253 
  254         stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL);
  255         while (STC_READ(sc, STC_GSVR) != 0xff);
  256         while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2);
  257 
  258         STC_WRITE(sc, STC_PPRH, CD180_PPRH);
  259         STC_WRITE(sc, STC_PPRL, CD180_PPRL);
  260         STC_WRITE(sc, STC_MSMR, SPIF_MSMR);
  261         STC_WRITE(sc, STC_TSMR, SPIF_TSMR);
  262         STC_WRITE(sc, STC_RSMR, SPIF_RSMR);
  263         STC_WRITE(sc, STC_GSVR, 0);
  264         STC_WRITE(sc, STC_GSCR1, 0);
  265         STC_WRITE(sc, STC_GSCR2, 0);
  266         STC_WRITE(sc, STC_GSCR3, 0);
  267 
  268         printf(": rev %x chiprev %x osc %sMHz\n",
  269             sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc));
  270 
  271         (void)config_found(self, sttymatch, NULL);
  272         (void)config_found(self, sbppmatch, NULL);
  273 
  274         return;
  275 
  276 fail_unmapregs:
  277         bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_reg[0].sbr_size);
  278 }
  279 
  280 int
  281 sttymatch(parent, vcf, aux)
  282         struct device *parent;
  283         void *vcf, *aux;
  284 {
  285         struct spif_softc *sc = (struct spif_softc *)parent;
  286 
  287         return (aux == sttymatch && sc->sc_ttys == NULL);
  288 }
  289 
  290 void
  291 sttyattach(parent, dev, aux)
  292         struct device *parent, *dev;
  293         void *aux;
  294 {
  295         struct spif_softc *sc = (struct spif_softc *)parent;
  296         struct stty_softc *ssc = (struct stty_softc *)dev;
  297         int port;
  298 
  299         sc->sc_ttys = ssc;
  300 
  301         for (port = 0; port < sc->sc_nser; port++) {
  302                 struct stty_port *sp = &ssc->sc_port[port];
  303                 struct tty *tp;
  304 
  305                 DTR_WRITE(sc, port, 0);
  306 
  307                 tp = ttymalloc();
  308 
  309                 tp->t_oproc = stty_start;
  310                 tp->t_param = stty_param;
  311 
  312                 sp->sp_tty = tp;
  313                 sp->sp_sc = sc;
  314                 sp->sp_channel = port;
  315 
  316                 sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT);
  317                 if(sp->sp_rbuf == NULL)
  318                         break;
  319 
  320                 sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE;
  321         }
  322 
  323         ssc->sc_nports = port;
  324 
  325         printf(": %d tty%s\n", port, port == 1 ? "" : "s");
  326 }
  327 
  328 int
  329 sttyopen(dev, flags, mode, p)
  330         dev_t dev;
  331         int flags;
  332         int mode;
  333         struct proc *p;
  334 {
  335         struct spif_softc *csc;
  336         struct stty_softc *sc;
  337         struct stty_port *sp;
  338         struct tty *tp;
  339         int card = SPIF_CARD(dev);
  340         int port = SPIF_PORT(dev);
  341         int s;
  342 
  343         if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs)
  344                 return (ENXIO);
  345 
  346         sc = stty_cd.cd_devs[card];
  347         csc = spif_cd.cd_devs[card];
  348         if (sc == NULL || csc == NULL)
  349                 return (ENXIO);
  350 
  351         if (port >= sc->sc_nports)
  352                 return (ENXIO);
  353 
  354         sp = &sc->sc_port[port];
  355         tp = sp->sp_tty;
  356         tp->t_dev = dev;
  357 
  358         if (!ISSET(tp->t_state, TS_ISOPEN)) {
  359                 SET(tp->t_state, TS_WOPEN);
  360 
  361                 ttychars(tp);
  362                 tp->t_iflag = TTYDEF_IFLAG;
  363                 tp->t_oflag = TTYDEF_OFLAG;
  364                 tp->t_cflag = TTYDEF_CFLAG;
  365                 if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL))
  366                         SET(tp->t_cflag, CLOCAL);
  367                 if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS))
  368                         SET(tp->t_cflag, CRTSCTS);
  369                 if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF))
  370                         SET(tp->t_cflag, MDMBUF);
  371                 tp->t_lflag = TTYDEF_LFLAG;
  372                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  373 
  374                 sp->sp_rput = sp->sp_rget = sp->sp_rbuf;
  375 
  376                 s = spltty();
  377 
  378                 STC_WRITE(csc, STC_CAR, sp->sp_channel);
  379                 stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
  380                 STC_WRITE(csc, STC_CAR, sp->sp_channel);
  381 
  382                 stty_param(tp, &tp->t_termios);
  383 
  384                 ttsetwater(tp);
  385 
  386                 STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD);
  387 
  388                 if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier)
  389                         SET(tp->t_state, TS_CARR_ON);
  390                 else
  391                         CLR(tp->t_state, TS_CARR_ON);
  392         }
  393         else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) {
  394                 return (EBUSY);
  395         } else {
  396                 s = spltty();
  397         }
  398 
  399         if (!ISSET(flags, O_NONBLOCK)) {
  400                 while (!ISSET(tp->t_cflag, CLOCAL) &&
  401                     !ISSET(tp->t_state, TS_CARR_ON)) {
  402                         int error;
  403 
  404                         SET(tp->t_state, TS_WOPEN);
  405                         error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
  406                             "sttycd", 0);
  407                         if (error != 0) {
  408                                 splx(s);
  409                                 CLR(tp->t_state, TS_WOPEN);
  410                                 return (error);
  411                         }
  412                 }
  413         }
  414 
  415         splx(s);
  416 
  417         return ((*linesw[tp->t_line].l_open)(dev, tp));
  418 }
  419 
  420 int
  421 sttyclose(dev, flags, mode, p)
  422         dev_t dev;
  423         int flags;
  424         int mode;
  425         struct proc *p;
  426 {
  427         struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
  428         struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
  429         struct spif_softc *csc = sp->sp_sc;
  430         struct tty *tp = sp->sp_tty;
  431         int port = SPIF_PORT(dev);
  432         int s;
  433 
  434         (*linesw[tp->t_line].l_close)(tp, flags);
  435         s = spltty();
  436 
  437         if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
  438                 stty_modem_control(sp, 0, DMSET);
  439                 STC_WRITE(csc, STC_CAR, port);
  440                 STC_WRITE(csc, STC_CCR,
  441                     CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
  442         }
  443 
  444         splx(s);
  445         ttyclose(tp);
  446         return (0);
  447 }
  448 
  449 int
  450 sttyioctl(dev, cmd, data, flags, p)
  451         dev_t dev;
  452         u_long cmd;
  453         caddr_t data;
  454         int flags;
  455         struct proc *p;
  456 {
  457         struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)];
  458         struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
  459         struct spif_softc *sc = sp->sp_sc;
  460         struct tty *tp = sp->sp_tty;
  461         int error;
  462 
  463         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p);
  464         if (error >= 0)
  465                 return (error);
  466 
  467         error = ttioctl(tp, cmd, data, flags, p);
  468         if (error >= 0)
  469                 return (error);
  470 
  471         error = 0;
  472 
  473         switch (cmd) {
  474         case TIOCSBRK:
  475                 SET(sp->sp_flags, STTYF_SET_BREAK);
  476                 STC_WRITE(sc, STC_CAR, sp->sp_channel);
  477                 STC_WRITE(sc, STC_SRER,
  478                     STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
  479                 break;
  480         case TIOCCBRK:
  481                 SET(sp->sp_flags, STTYF_CLR_BREAK);
  482                 STC_WRITE(sc, STC_CAR, sp->sp_channel);
  483                 STC_WRITE(sc, STC_SRER,
  484                     STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
  485                 break;
  486         case TIOCSDTR:
  487                 stty_modem_control(sp, TIOCM_DTR, DMBIS);
  488                 break;
  489         case TIOCCDTR:
  490                 stty_modem_control(sp, TIOCM_DTR, DMBIC);
  491                 break;
  492         case TIOCMBIS:
  493                 stty_modem_control(sp, *((int *)data), DMBIS);
  494                 break;
  495         case TIOCMBIC:
  496                 stty_modem_control(sp, *((int *)data), DMBIC);
  497                 break;
  498         case TIOCMGET:
  499                 *((int *)data) = stty_modem_control(sp, 0, DMGET);
  500                 break;
  501         case TIOCMSET:
  502                 stty_modem_control(sp, *((int *)data), DMSET);
  503                 break;
  504         case TIOCGFLAGS:
  505                 *((int *)data) = sp->sp_openflags;
  506                 break;
  507         case TIOCSFLAGS:
  508                 if (suser(p, 0))
  509                         error = EPERM;
  510                 else
  511                         sp->sp_openflags = *((int *)data) &
  512                             (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
  513                              TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
  514                 break;
  515         default:
  516                 error = ENOTTY;
  517         }
  518 
  519         return (error);
  520 }
  521 
  522 int
  523 stty_modem_control(sp, bits, how)
  524         struct stty_port *sp;
  525         int bits, how;
  526 {
  527         struct spif_softc *csc = sp->sp_sc;
  528         struct tty *tp = sp->sp_tty;
  529         int s, msvr;
  530 
  531         s = spltty();
  532         STC_WRITE(csc, STC_CAR, sp->sp_channel);
  533 
  534         switch (how) {
  535         case DMGET:
  536                 bits = TIOCM_LE;
  537                 if (DTR_READ(csc, sp->sp_channel))
  538                         bits |= TIOCM_DTR;
  539                 msvr = STC_READ(csc, STC_MSVR);
  540                 if (ISSET(msvr, CD180_MSVR_DSR))
  541                         bits |= TIOCM_DSR;
  542                 if (ISSET(msvr, CD180_MSVR_CD))
  543                         bits |= TIOCM_CD;
  544                 if (ISSET(msvr, CD180_MSVR_CTS))
  545                         bits |= TIOCM_CTS;
  546                 if (ISSET(msvr, CD180_MSVR_RTS))
  547                         bits |= TIOCM_RTS;
  548                 break;
  549         case DMSET:
  550                 DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0);
  551                 if (ISSET(bits, TIOCM_RTS))
  552                         STC_WRITE(csc, STC_MSVR,
  553                             STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
  554                 else
  555                         STC_WRITE(csc, STC_MSVR,
  556                             STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
  557                 break;
  558         case DMBIS:
  559                 if (ISSET(bits, TIOCM_DTR))
  560                         DTR_WRITE(csc, sp->sp_channel, 1);
  561                 if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
  562                         STC_WRITE(csc, STC_MSVR,
  563                             STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
  564                 break;
  565         case DMBIC:
  566                 if (ISSET(bits, TIOCM_DTR))
  567                         DTR_WRITE(csc, sp->sp_channel, 0);
  568                 if (ISSET(bits, TIOCM_RTS))
  569                         STC_WRITE(csc, STC_MSVR,
  570                             STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
  571                 break;
  572         }
  573 
  574         splx(s);
  575         return (bits);
  576 }
  577 
  578 int
  579 stty_param(tp, t)
  580         struct tty *tp;
  581         struct termios *t;
  582 {
  583         struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
  584         struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
  585         struct spif_softc *sc = sp->sp_sc;
  586         u_int8_t rbprl, rbprh, tbprl, tbprh;
  587         int s, opt;
  588 
  589         if (t->c_ospeed &&
  590             stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
  591                 return (EINVAL);
  592 
  593         if (t->c_ispeed &&
  594             stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
  595                 return (EINVAL);
  596 
  597         s = spltty();
  598 
  599         /* hang up line if ospeed is zero, otherwise raise DTR */
  600         stty_modem_control(sp, TIOCM_DTR,
  601             (t->c_ospeed == 0 ? DMBIC : DMBIS));
  602 
  603         STC_WRITE(sc, STC_CAR, sp->sp_channel);
  604 
  605         opt = 0;
  606         if (ISSET(t->c_cflag, PARENB)) {
  607                 opt |= CD180_COR1_PARMODE_NORMAL;
  608                 opt |= (ISSET(t->c_cflag, PARODD) ?
  609                                 CD180_COR1_ODDPAR :
  610                                 CD180_COR1_EVENPAR);
  611         }
  612         else
  613                 opt |= CD180_COR1_PARMODE_NO;
  614 
  615         if (!ISSET(t->c_iflag, INPCK))
  616                 opt |= CD180_COR1_IGNPAR;
  617 
  618         if (ISSET(t->c_cflag, CSTOPB))
  619                 opt |= CD180_COR1_STOP2;
  620 
  621         switch (t->c_cflag & CSIZE) {
  622         case CS5:
  623                 opt |= CD180_COR1_CS5;
  624                 break;
  625         case CS6:
  626                 opt |= CD180_COR1_CS6;
  627                 break;
  628         case CS7:
  629                 opt |= CD180_COR1_CS7;
  630                 break;
  631         default:
  632                 opt |= CD180_COR1_CS8;
  633                 break;
  634         }
  635         STC_WRITE(sc, STC_COR1, opt);
  636         stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
  637 
  638         opt = CD180_COR2_ETC;
  639         if (ISSET(t->c_cflag, CRTSCTS))
  640                 opt |= CD180_COR2_CTSAE;
  641         STC_WRITE(sc, STC_COR2, opt);
  642         stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
  643 
  644         STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD);
  645         stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
  646 
  647         STC_WRITE(sc, STC_SCHR1, 0x11);
  648         STC_WRITE(sc, STC_SCHR2, 0x13);
  649         STC_WRITE(sc, STC_SCHR3, 0x11);
  650         STC_WRITE(sc, STC_SCHR4, 0x13);
  651         STC_WRITE(sc, STC_RTPR, 0x12);
  652 
  653         STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD);
  654         STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD);
  655         STC_WRITE(sc, STC_MCR, 0);
  656 
  657         if (t->c_ospeed) {
  658                 STC_WRITE(sc, STC_TBPRH, tbprh);
  659                 STC_WRITE(sc, STC_TBPRL, tbprl);
  660         }
  661 
  662         if (t->c_ispeed) {
  663                 STC_WRITE(sc, STC_RBPRH, rbprh);
  664                 STC_WRITE(sc, STC_RBPRL, rbprl);
  665         }
  666 
  667         stty_write_ccr(sc, CD180_CCR_CMD_CHAN |
  668             CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
  669 
  670         sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD;
  671 
  672         splx(s);
  673         return (0);
  674 }
  675 
  676 int
  677 sttyread(dev, uio, flags)
  678         dev_t dev;
  679         struct uio *uio;
  680         int flags;
  681 {
  682         struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
  683         struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
  684         struct tty *tp = sp->sp_tty;
  685 
  686         return ((*linesw[tp->t_line].l_read)(tp, uio, flags));
  687 }
  688 
  689 int
  690 sttywrite(dev, uio, flags)
  691         dev_t dev;
  692         struct uio *uio;
  693         int flags;
  694 {
  695         struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
  696         struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
  697         struct tty *tp = sp->sp_tty;
  698 
  699         return ((*linesw[tp->t_line].l_write)(tp, uio, flags));
  700 }
  701 
  702 struct tty *
  703 sttytty(dev)
  704         dev_t dev;
  705 {
  706         struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
  707         struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
  708 
  709         return (sp->sp_tty);
  710 }
  711 
  712 int
  713 sttystop(tp, flags)
  714         struct tty *tp;
  715         int flags;
  716 {
  717         struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
  718         struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
  719         int s;
  720 
  721         s = spltty();
  722         if (ISSET(tp->t_state, TS_BUSY)) {
  723                 if (!ISSET(tp->t_state, TS_TTSTOP))
  724                         SET(tp->t_state, TS_FLUSH);
  725                 SET(sp->sp_flags, STTYF_STOP);
  726         }
  727         splx(s);
  728         return (0);
  729 }
  730 
  731 void
  732 stty_start(tp)
  733         struct tty *tp;
  734 {
  735         struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
  736         struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)];
  737         struct spif_softc *sc = sp->sp_sc;
  738         int s;
  739 
  740         s = spltty();
  741 
  742         if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
  743                 if (tp->t_outq.c_cc <= tp->t_lowat) {
  744                         if (ISSET(tp->t_state, TS_ASLEEP)) {
  745                                 CLR(tp->t_state, TS_ASLEEP);
  746                                 wakeup(&tp->t_outq);
  747                         }
  748                         selwakeup(&tp->t_wsel);
  749                 }
  750                 if (tp->t_outq.c_cc) {
  751                         sp->sp_txc = ndqb(&tp->t_outq, 0);
  752                         sp->sp_txp = tp->t_outq.c_cf;
  753                         SET(tp->t_state, TS_BUSY);
  754                         STC_WRITE(sc, STC_CAR, sp->sp_channel);
  755                         STC_WRITE(sc, STC_SRER,
  756                             STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
  757                 }
  758         }
  759 
  760         splx(s);
  761 }
  762 
  763 int
  764 spifstcintr_rxexception(sc, needsoftp)
  765         struct spif_softc *sc;
  766         int *needsoftp;
  767 {
  768         struct stty_port *sp;
  769         u_int8_t channel, *ptr;
  770 
  771         channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
  772         sp = &sc->sc_ttys->sc_port[channel];
  773         ptr = sp->sp_rput;
  774         *ptr++ = STC_READ(sc, STC_RCSR);
  775         *ptr++ = STC_READ(sc, STC_RDR);
  776         if (ptr == sp->sp_rend)
  777                 ptr = sp->sp_rbuf;
  778         if (ptr == sp->sp_rget) {
  779                 if (ptr == sp->sp_rbuf)
  780                         ptr = sp->sp_rend;
  781                 ptr -= 2;
  782                 SET(sp->sp_flags, STTYF_RING_OVERFLOW);
  783         }
  784         STC_WRITE(sc, STC_EOSRR, 0);
  785         *needsoftp = 1;
  786         sp->sp_rput = ptr;
  787         return (1);
  788 }
  789 
  790 int
  791 spifstcintr_rx(sc, needsoftp)
  792         struct spif_softc *sc;
  793         int *needsoftp;
  794 {
  795         struct stty_port *sp;
  796         u_int8_t channel, *ptr, cnt, rcsr;
  797         int i;
  798 
  799         channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
  800         sp = &sc->sc_ttys->sc_port[channel];
  801         ptr = sp->sp_rput;
  802         cnt = STC_READ(sc, STC_RDCR);
  803         for (i = 0; i < cnt; i++) {
  804                 *ptr++ = 0;
  805                 rcsr = STC_READ(sc, STC_RCSR);
  806                 *ptr++ = STC_READ(sc, STC_RDR);
  807                 if (ptr == sp->sp_rend)
  808                         ptr = sp->sp_rbuf;
  809                 if (ptr == sp->sp_rget) {
  810                         if (ptr == sp->sp_rbuf)
  811                                 ptr = sp->sp_rend;
  812                         ptr -= 2;
  813                         SET(sp->sp_flags, STTYF_RING_OVERFLOW);
  814                         break;
  815                 }
  816         }
  817         STC_WRITE(sc, STC_EOSRR, 0);
  818         if (cnt) {
  819                 *needsoftp = 1;
  820                 sp->sp_rput = ptr;
  821         }
  822         return (1);
  823 }
  824 
  825 int
  826 spifstcintr_tx(sc, needsoftp)
  827         struct spif_softc *sc;
  828         int *needsoftp;
  829 {
  830         struct stty_port *sp;
  831         u_int8_t channel, ch;
  832         int cnt = 0;
  833 
  834         channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
  835         sp = &sc->sc_ttys->sc_port[channel];
  836         if (!ISSET(sp->sp_flags, STTYF_STOP)) {
  837                 if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
  838                         STC_WRITE(sc, STC_TDR, 0);
  839                         STC_WRITE(sc, STC_TDR, 0x81);
  840                         CLR(sp->sp_flags, STTYF_SET_BREAK);
  841                         cnt += 2;
  842                 }
  843                 if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
  844                         STC_WRITE(sc, STC_TDR, 0);
  845                         STC_WRITE(sc, STC_TDR, 0x83);
  846                         CLR(sp->sp_flags, STTYF_CLR_BREAK);
  847                         cnt += 2;
  848                 }
  849 
  850                 while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
  851                         ch = *sp->sp_txp;
  852                         sp->sp_txc--;
  853                         sp->sp_txp++;
  854 
  855                         if (ch == 0) {
  856                                 STC_WRITE(sc, STC_TDR, ch);
  857                                 cnt++;
  858                         }
  859                         STC_WRITE(sc, STC_TDR, ch);
  860                         cnt++;
  861                 }
  862         }
  863 
  864         if (sp->sp_txc == 0 ||
  865             ISSET(sp->sp_flags, STTYF_STOP)) {
  866                 STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) &
  867                     (~CD180_SRER_TXD));
  868                 CLR(sp->sp_flags, STTYF_STOP);
  869                 SET(sp->sp_flags, STTYF_DONE);
  870                 *needsoftp = 1;
  871         }
  872 
  873         STC_WRITE(sc, STC_EOSRR, 0);
  874 
  875         return (1);
  876 }
  877 
  878 int
  879 spifstcintr_mx(sc, needsoftp)
  880         struct spif_softc *sc;
  881         int *needsoftp;
  882 {
  883         struct stty_port *sp;
  884         u_int8_t channel, mcr;
  885 
  886         channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
  887         sp = &sc->sc_ttys->sc_port[channel];
  888         mcr = STC_READ(sc, STC_MCR);
  889         if (mcr & CD180_MCR_CD) {
  890                 SET(sp->sp_flags, STTYF_CDCHG);
  891                 *needsoftp = 1;
  892         }
  893         STC_WRITE(sc, STC_MCR, 0);
  894         STC_WRITE(sc, STC_EOSRR, 0);
  895         return (1);
  896 }
  897 
  898 int
  899 spifstcintr(vsc)
  900         void *vsc;
  901 {
  902         struct spif_softc *sc = (struct spif_softc *)vsc;
  903         int needsoft = 0, r = 0, i;
  904         u_int8_t ar;
  905 
  906         for (i = 0; i < 8; i++) {
  907                 ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK;
  908                 if (ar == CD180_GSVR_RXGOOD)
  909                         r |= spifstcintr_rx(sc, &needsoft);
  910                 else if (ar == CD180_GSVR_RXEXCEPTION)
  911                         r |= spifstcintr_rxexception(sc, &needsoft);
  912         }
  913 
  914         for (i = 0; i < 8; i++) {
  915                 ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK;
  916                 if (ar == CD180_GSVR_TXDATA)
  917                         r |= spifstcintr_tx(sc, &needsoft);
  918         }
  919 
  920         for (i = 0; i < 8; i++) {
  921                 ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK;
  922                 if (ar == CD180_GSVR_STATCHG)
  923                         r |= spifstcintr_mx(sc, &needsoft);
  924         }
  925 
  926         if (needsoft)
  927                 softintr_schedule(sc->sc_softih);
  928         return (r);
  929 }
  930 
  931 void
  932 spifsoftintr(vsc)
  933         void *vsc;
  934 {
  935         struct spif_softc *sc = (struct spif_softc *)vsc;
  936         struct stty_softc *stc = sc->sc_ttys;
  937         int r = 0, i, data, s, flags;
  938         u_int8_t stat, msvr;
  939         struct stty_port *sp;
  940         struct tty *tp;
  941 
  942         if (stc != NULL) {
  943                 for (i = 0; i < stc->sc_nports; i++) {
  944                         sp = &stc->sc_port[i];
  945                         tp = sp->sp_tty;
  946 
  947                         if (!ISSET(tp->t_state, TS_ISOPEN))
  948                                 continue;
  949 
  950                         while (sp->sp_rget != sp->sp_rput) {
  951                                 stat = sp->sp_rget[0];
  952                                 data = sp->sp_rget[1];
  953                                 sp->sp_rget += 2;
  954                                 if (sp->sp_rget == sp->sp_rend)
  955                                         sp->sp_rget = sp->sp_rbuf;
  956 
  957                                 if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
  958                                         data |= TTY_FE;
  959 
  960                                 if (stat & CD180_RCSR_PE)
  961                                         data |= TTY_PE;
  962 
  963                                 (*linesw[tp->t_line].l_rint)(data, tp);
  964                                 r = 1;
  965                         }
  966 
  967                         s = splhigh();
  968                         flags = sp->sp_flags;
  969                         CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
  970                             STTYF_RING_OVERFLOW);
  971                         splx(s);
  972 
  973                         if (ISSET(flags, STTYF_CDCHG)) {
  974                                 s = spltty();
  975                                 STC_WRITE(sc, STC_CAR, i);
  976                                 msvr = STC_READ(sc, STC_MSVR);
  977                                 splx(s);
  978 
  979                                 sp->sp_carrier = msvr & CD180_MSVR_CD;
  980                                 (*linesw[tp->t_line].l_modem)(tp,
  981                                     sp->sp_carrier);
  982                                 r = 1;
  983                         }
  984 
  985                         if (ISSET(flags, STTYF_RING_OVERFLOW)) {
  986                                 log(LOG_WARNING, "%s-%x: ring overflow\n",
  987                                         stc->sc_dev.dv_xname, i);
  988                                 r = 1;
  989                         }
  990 
  991                         if (ISSET(flags, STTYF_DONE)) {
  992                                 ndflush(&tp->t_outq,
  993                                     sp->sp_txp - tp->t_outq.c_cf);
  994                                 CLR(tp->t_state, TS_BUSY);
  995                                 (*linesw[tp->t_line].l_start)(tp);
  996                                 r = 1;
  997                         }
  998                 }
  999         }
 1000 }
 1001 
 1002 void
 1003 stty_write_ccr(sc, val)
 1004         struct spif_softc *sc;
 1005         u_int8_t val;
 1006 {
 1007         int tries = 100000;
 1008 
 1009         while (STC_READ(sc, STC_CCR) && tries--)
 1010                 /*EMPTY*/;
 1011         if (tries == 0)
 1012                 printf("%s: ccr timeout\n", sc->sc_dev.dv_xname);
 1013         STC_WRITE(sc, STC_CCR, val);
 1014 }
 1015 
 1016 int
 1017 stty_compute_baud(speed, clock, bprlp, bprhp)
 1018         speed_t speed;
 1019         int clock;
 1020         u_int8_t *bprlp, *bprhp;
 1021 {
 1022         u_int32_t rate;
 1023 
 1024         rate = (2 * clock) / (16 * speed);
 1025         if (rate & 1)
 1026                 rate = (rate >> 1) + 1;
 1027         else
 1028                 rate = rate >> 1;
 1029 
 1030         if (rate > 0xffff || rate == 0)
 1031                 return (1);
 1032 
 1033         *bprlp = rate & 0xff;
 1034         *bprhp = (rate >> 8) & 0xff;
 1035         return (0);
 1036 }
 1037 
 1038 int
 1039 sbppmatch(parent, vcf, aux)
 1040         struct device *parent;
 1041         void *vcf, *aux;
 1042 {
 1043         struct spif_softc *sc = (struct spif_softc *)parent;
 1044 
 1045         return (aux == sbppmatch && sc->sc_bpps == NULL);
 1046 }
 1047 
 1048 void
 1049 sbppattach(parent, dev, aux)
 1050         struct device *parent, *dev;
 1051         void *aux;
 1052 {
 1053         struct spif_softc *sc = (struct spif_softc *)parent;
 1054         struct sbpp_softc *psc = (struct sbpp_softc *)dev;
 1055         int port;
 1056 
 1057         sc->sc_bpps = psc;
 1058 
 1059         for (port = 0; port < sc->sc_npar; port++) {
 1060         }
 1061 
 1062         psc->sc_nports = port;
 1063         printf(": %d port%s\n", port, port == 1 ? "" : "s");
 1064 }
 1065 
 1066 int
 1067 sbppopen(dev, flags, mode, p)
 1068         dev_t dev;
 1069         int flags;
 1070         int mode;
 1071         struct proc *p;
 1072 {
 1073         return (ENXIO);
 1074 }
 1075 
 1076 int
 1077 sbppclose(dev, flags, mode, p)
 1078         dev_t dev;
 1079         int flags;
 1080         int mode;
 1081         struct proc *p;
 1082 {
 1083         return (ENXIO);
 1084 }
 1085 
 1086 int
 1087 spifppcintr(v)
 1088         void *v;
 1089 {
 1090         return (0);
 1091 }
 1092 
 1093 int
 1094 sbppread(dev, uio, flags)
 1095         dev_t dev;
 1096         struct uio *uio;
 1097         int flags;
 1098 {
 1099         return (sbpp_rw(dev, uio));
 1100 }
 1101 
 1102 int
 1103 sbppwrite(dev, uio, flags)
 1104         dev_t dev;
 1105         struct uio *uio;
 1106         int flags;
 1107 {
 1108         return (sbpp_rw(dev, uio));
 1109 }
 1110 
 1111 int
 1112 sbpp_rw(dev, uio)
 1113         dev_t dev;
 1114         struct uio *uio;
 1115 {
 1116         return (ENXIO);
 1117 }
 1118 
 1119 int
 1120 sbpppoll(dev, events, p)
 1121         dev_t dev;
 1122         int events;
 1123         struct proc *p;
 1124 {
 1125         return (seltrue(dev, events, p));
 1126 }
 1127 
 1128 int
 1129 sbppioctl(dev, cmd, data, flags, p)
 1130         dev_t dev;
 1131         u_long cmd;
 1132         caddr_t data;
 1133         int flags;
 1134         struct proc *p;
 1135 {
 1136         int error;
 1137 
 1138         error = ENOTTY;
 1139 
 1140         return (error);
 1141 }

/* [<][>][^][v][top][bottom][index][help] */