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/uart/uart_dev_z8530.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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2003 Marcel Moolenaar
    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  *
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/conf.h>
   36 #include <machine/bus.h>
   37 
   38 #include <dev/uart/uart.h>
   39 #include <dev/uart/uart_cpu.h>
   40 #include <dev/uart/uart_bus.h>
   41 
   42 #include <dev/ic/z8530.h>
   43 
   44 #include "uart_if.h"
   45 
   46 #define DEFAULT_RCLK    307200
   47 
   48 /* Hack! */
   49 #ifdef __powerpc__
   50 #define UART_PCLK       0
   51 #else
   52 #define UART_PCLK       MCB2_PCLK
   53 #endif
   54 
   55 /* Multiplexed I/O. */
   56 static __inline void
   57 uart_setmreg(struct uart_bas *bas, int reg, int val)
   58 {
   59 
   60         uart_setreg(bas, REG_CTRL, reg);
   61         uart_barrier(bas);
   62         uart_setreg(bas, REG_CTRL, val);
   63 }
   64 
   65 static __inline uint8_t
   66 uart_getmreg(struct uart_bas *bas, int reg)
   67 {
   68 
   69         uart_setreg(bas, REG_CTRL, reg);
   70         uart_barrier(bas);
   71         return (uart_getreg(bas, REG_CTRL));
   72 }
   73 
   74 static int
   75 z8530_divisor(int rclk, int baudrate)
   76 {
   77         int act_baud, divisor, error;
   78 
   79         if (baudrate == 0)
   80                 return (-1);
   81 
   82         divisor = (rclk + baudrate) / (baudrate << 1) - 2;
   83         if (divisor < 0 || divisor >= 65536)
   84                 return (-1);
   85         act_baud = rclk / 2 / (divisor + 2);
   86 
   87         /* 10 times error in percent: */
   88         error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1;
   89 
   90         /* 3.0% maximum error tolerance: */
   91         if (error < -30 || error > 30)
   92                 return (-1);
   93 
   94         return (divisor);
   95 }
   96 
   97 static int
   98 z8530_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
   99     int parity, uint8_t *tpcp)
  100 {
  101         int divisor;
  102         uint8_t mpm, rpc, tpc;
  103 
  104         rpc = RPC_RXE;
  105         mpm = MPM_CM16;
  106         tpc = TPC_TXE | (*tpcp & (TPC_DTR | TPC_RTS));
  107 
  108         if (databits >= 8) {
  109                 rpc |= RPC_RB8;
  110                 tpc |= TPC_TB8;
  111         } else if (databits == 7) {
  112                 rpc |= RPC_RB7;
  113                 tpc |= TPC_TB7;
  114         } else if (databits == 6) {
  115                 rpc |= RPC_RB6;
  116                 tpc |= TPC_TB6;
  117         } else {
  118                 rpc |= RPC_RB5;
  119                 tpc |= TPC_TB5;
  120         }
  121         mpm |= (stopbits > 1) ? MPM_SB2 : MPM_SB1;
  122         switch (parity) {
  123         case UART_PARITY_EVEN:  mpm |= MPM_PE | MPM_EVEN; break;
  124         case UART_PARITY_NONE:  break;
  125         case UART_PARITY_ODD:   mpm |= MPM_PE; break;
  126         default:                return (EINVAL);
  127         }
  128 
  129         if (baudrate > 0) {
  130                 divisor = z8530_divisor(bas->rclk, baudrate);
  131                 if (divisor == -1)
  132                         return (EINVAL);
  133         } else
  134                 divisor = -1;
  135 
  136         uart_setmreg(bas, WR_MCB2, UART_PCLK);
  137         uart_barrier(bas);
  138 
  139         if (divisor >= 0) {
  140                 uart_setmreg(bas, WR_TCL, divisor & 0xff);
  141                 uart_barrier(bas);
  142                 uart_setmreg(bas, WR_TCH, (divisor >> 8) & 0xff);
  143                 uart_barrier(bas);
  144         }
  145 
  146         uart_setmreg(bas, WR_RPC, rpc);
  147         uart_barrier(bas);
  148         uart_setmreg(bas, WR_MPM, mpm);
  149         uart_barrier(bas);
  150         uart_setmreg(bas, WR_TPC, tpc);
  151         uart_barrier(bas);
  152         uart_setmreg(bas, WR_MCB2, UART_PCLK | MCB2_BRGE);
  153         uart_barrier(bas);
  154         *tpcp = tpc;
  155         return (0);
  156 }
  157 
  158 static int
  159 z8530_setup(struct uart_bas *bas, int baudrate, int databits, int stopbits,
  160     int parity)
  161 {
  162         uint8_t tpc;
  163 
  164         if (bas->rclk == 0)
  165                 bas->rclk = DEFAULT_RCLK;
  166 
  167         /* Assume we don't need to perform a full hardware reset. */
  168         switch (bas->chan) {
  169         case 1:
  170                 uart_setmreg(bas, WR_MIC, MIC_NV | MIC_CRA);
  171                 break;
  172         case 2:
  173                 uart_setmreg(bas, WR_MIC, MIC_NV | MIC_CRB);
  174                 break;
  175         }
  176         uart_barrier(bas);
  177         /* Set clock sources. */
  178         uart_setmreg(bas, WR_CMC, CMC_RC_BRG | CMC_TC_BRG);
  179         uart_setmreg(bas, WR_MCB2, UART_PCLK);
  180         uart_barrier(bas);
  181         /* Set data encoding. */
  182         uart_setmreg(bas, WR_MCB1, MCB1_NRZ);
  183         uart_barrier(bas);
  184 
  185         tpc = TPC_DTR | TPC_RTS;
  186         z8530_param(bas, baudrate, databits, stopbits, parity, &tpc);
  187         return (int)tpc;
  188 }
  189 
  190 /*
  191  * Low-level UART interface.
  192  */
  193 static int z8530_probe(struct uart_bas *bas);
  194 static void z8530_init(struct uart_bas *bas, int, int, int, int);
  195 static void z8530_term(struct uart_bas *bas);
  196 static void z8530_putc(struct uart_bas *bas, int);
  197 static int z8530_rxready(struct uart_bas *bas);
  198 static int z8530_getc(struct uart_bas *bas, struct mtx *);
  199 
  200 static struct uart_ops uart_z8530_ops = {
  201         .probe = z8530_probe,
  202         .init = z8530_init,
  203         .term = z8530_term,
  204         .putc = z8530_putc,
  205         .rxready = z8530_rxready,
  206         .getc = z8530_getc,
  207 };
  208 
  209 static int
  210 z8530_probe(struct uart_bas *bas)
  211 {
  212 
  213         return (0);
  214 }
  215 
  216 static void
  217 z8530_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
  218     int parity)
  219 {
  220 
  221         z8530_setup(bas, baudrate, databits, stopbits, parity);
  222 }
  223 
  224 static void
  225 z8530_term(struct uart_bas *bas)
  226 {
  227 }
  228 
  229 static void
  230 z8530_putc(struct uart_bas *bas, int c)
  231 {
  232 
  233         while (!(uart_getreg(bas, REG_CTRL) & BES_TXE))
  234                 ;
  235         uart_setreg(bas, REG_DATA, c);
  236         uart_barrier(bas);
  237 }
  238 
  239 static int
  240 z8530_rxready(struct uart_bas *bas)
  241 {
  242 
  243         return ((uart_getreg(bas, REG_CTRL) & BES_RXA) != 0 ? 1 : 0);
  244 }
  245 
  246 static int
  247 z8530_getc(struct uart_bas *bas, struct mtx *hwmtx)
  248 {
  249         int c;
  250 
  251         uart_lock(hwmtx);
  252 
  253         while (!(uart_getreg(bas, REG_CTRL) & BES_RXA)) {
  254                 uart_unlock(hwmtx);
  255                 DELAY(10);
  256                 uart_lock(hwmtx);
  257         }
  258 
  259         c = uart_getreg(bas, REG_DATA);
  260 
  261         uart_unlock(hwmtx);
  262 
  263         return (c);
  264 }
  265 
  266 /*
  267  * High-level UART interface.
  268  */
  269 struct z8530_softc {
  270         struct uart_softc base;
  271         uint8_t tpc;
  272         uint8_t txidle;
  273 };
  274 
  275 static int z8530_bus_attach(struct uart_softc *);
  276 static int z8530_bus_detach(struct uart_softc *);
  277 static int z8530_bus_flush(struct uart_softc *, int);
  278 static int z8530_bus_getsig(struct uart_softc *);
  279 static int z8530_bus_ioctl(struct uart_softc *, int, intptr_t);
  280 static int z8530_bus_ipend(struct uart_softc *);
  281 static int z8530_bus_param(struct uart_softc *, int, int, int, int);
  282 static int z8530_bus_probe(struct uart_softc *);
  283 static int z8530_bus_receive(struct uart_softc *);
  284 static int z8530_bus_setsig(struct uart_softc *, int);
  285 static int z8530_bus_transmit(struct uart_softc *);
  286 static void z8530_bus_grab(struct uart_softc *);
  287 static void z8530_bus_ungrab(struct uart_softc *);
  288 
  289 static kobj_method_t z8530_methods[] = {
  290         KOBJMETHOD(uart_attach,         z8530_bus_attach),
  291         KOBJMETHOD(uart_detach,         z8530_bus_detach),
  292         KOBJMETHOD(uart_flush,          z8530_bus_flush),
  293         KOBJMETHOD(uart_getsig,         z8530_bus_getsig),
  294         KOBJMETHOD(uart_ioctl,          z8530_bus_ioctl),
  295         KOBJMETHOD(uart_ipend,          z8530_bus_ipend),
  296         KOBJMETHOD(uart_param,          z8530_bus_param),
  297         KOBJMETHOD(uart_probe,          z8530_bus_probe),
  298         KOBJMETHOD(uart_receive,        z8530_bus_receive),
  299         KOBJMETHOD(uart_setsig,         z8530_bus_setsig),
  300         KOBJMETHOD(uart_transmit,       z8530_bus_transmit),
  301         KOBJMETHOD(uart_grab,           z8530_bus_grab),
  302         KOBJMETHOD(uart_ungrab,         z8530_bus_ungrab),
  303         { 0, 0 }
  304 };
  305 
  306 struct uart_class uart_z8530_class = {
  307         "z8530",
  308         z8530_methods,
  309         sizeof(struct z8530_softc),
  310         .uc_ops = &uart_z8530_ops,
  311         .uc_range = 2,
  312         .uc_rclk = DEFAULT_RCLK,
  313         .uc_rshift = 0
  314 };
  315 
  316 #define SIGCHG(c, i, s, d)                              \
  317         if (c) {                                        \
  318                 i |= (i & s) ? s : s | d;               \
  319         } else {                                        \
  320                 i = (i & s) ? (i & ~s) | d : i;         \
  321         }
  322 
  323 static int
  324 z8530_bus_attach(struct uart_softc *sc)
  325 {
  326         struct z8530_softc *z8530 = (struct z8530_softc*)sc;
  327         struct uart_bas *bas;
  328         struct uart_devinfo *di;
  329 
  330         bas = &sc->sc_bas;
  331         if (sc->sc_sysdev != NULL) {
  332                 di = sc->sc_sysdev;
  333                 z8530->tpc = TPC_DTR|TPC_RTS;
  334                 z8530_param(bas, di->baudrate, di->databits, di->stopbits,
  335                     di->parity, &z8530->tpc);
  336         } else {
  337                 z8530->tpc = z8530_setup(bas, 9600, 8, 1, UART_PARITY_NONE);
  338                 z8530->tpc &= ~(TPC_DTR|TPC_RTS);
  339         }
  340         z8530->txidle = 1;      /* Report SER_INT_TXIDLE. */
  341 
  342         (void)z8530_bus_getsig(sc);
  343 
  344         uart_setmreg(bas, WR_IC, IC_BRK | IC_CTS | IC_DCD);
  345         uart_barrier(bas);
  346         uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE | IDT_RIA);
  347         uart_barrier(bas);
  348         uart_setmreg(bas, WR_IV, 0);
  349         uart_barrier(bas);
  350         uart_setmreg(bas, WR_TPC, z8530->tpc);
  351         uart_barrier(bas);
  352         uart_setmreg(bas, WR_MIC, MIC_NV | MIC_MIE);
  353         uart_barrier(bas);
  354         return (0);
  355 }
  356 
  357 static int
  358 z8530_bus_detach(struct uart_softc *sc)
  359 {
  360 
  361         return (0);
  362 }
  363 
  364 static int
  365 z8530_bus_flush(struct uart_softc *sc, int what)
  366 {
  367 
  368         return (0);
  369 }
  370 
  371 static int
  372 z8530_bus_getsig(struct uart_softc *sc)
  373 {
  374         uint32_t new, old, sig;
  375         uint8_t bes;
  376 
  377         do {
  378                 old = sc->sc_hwsig;
  379                 sig = old;
  380                 uart_lock(sc->sc_hwmtx);
  381                 bes = uart_getmreg(&sc->sc_bas, RR_BES);
  382                 uart_unlock(sc->sc_hwmtx);
  383                 SIGCHG(bes & BES_CTS, sig, SER_CTS, SER_DCTS);
  384                 SIGCHG(bes & BES_DCD, sig, SER_DCD, SER_DDCD);
  385                 SIGCHG(bes & BES_SYNC, sig, SER_DSR, SER_DDSR);
  386                 new = sig & ~SER_MASK_DELTA;
  387         } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
  388         return (sig);
  389 }
  390 
  391 static int
  392 z8530_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
  393 {
  394         struct z8530_softc *z8530 = (struct z8530_softc*)sc;
  395         struct uart_bas *bas;
  396         int baudrate, divisor, error;
  397 
  398         bas = &sc->sc_bas;
  399         error = 0;
  400         uart_lock(sc->sc_hwmtx);
  401         switch (request) {
  402         case UART_IOCTL_BREAK:
  403                 if (data)
  404                         z8530->tpc |= TPC_BRK;
  405                 else
  406                         z8530->tpc &= ~TPC_BRK;
  407                 uart_setmreg(bas, WR_TPC, z8530->tpc);
  408                 uart_barrier(bas);
  409                 break;
  410         case UART_IOCTL_BAUD:
  411                 divisor = uart_getmreg(bas, RR_TCH);
  412                 divisor = (divisor << 8) | uart_getmreg(bas, RR_TCL);
  413                 baudrate = bas->rclk / 2 / (divisor + 2);
  414                 *(int*)data = baudrate;
  415                 break;
  416         default:
  417                 error = EINVAL;
  418                 break;
  419         }
  420         uart_unlock(sc->sc_hwmtx);
  421         return (error);
  422 }
  423 
  424 static int
  425 z8530_bus_ipend(struct uart_softc *sc)
  426 {
  427         struct z8530_softc *z8530 = (struct z8530_softc*)sc;
  428         struct uart_bas *bas;
  429         int ipend;
  430         uint32_t sig;
  431         uint8_t bes, ip, iv, src;
  432 
  433         bas = &sc->sc_bas;
  434         ipend = 0;
  435 
  436         uart_lock(sc->sc_hwmtx);
  437         switch (bas->chan) {
  438         case 1:
  439                 ip = uart_getmreg(bas, RR_IP);
  440                 break;
  441         case 2: /* XXX hack!!! */
  442                 iv = uart_getmreg(bas, RR_IV) & 0x0E;
  443                 switch (iv) {
  444                 case IV_TEB:    ip = IP_TIA; break;
  445                 case IV_XSB:    ip = IP_SIA; break;
  446                 case IV_RAB:    ip = IP_RIA; break;
  447                 default:        ip = 0; break;
  448                 }
  449                 break;
  450         default:
  451                 ip = 0;
  452                 break;
  453         }
  454 
  455         if (ip & IP_RIA)
  456                 ipend |= SER_INT_RXREADY;
  457 
  458         if (ip & IP_TIA) {
  459                 uart_setreg(bas, REG_CTRL, CR_RSTTXI);
  460                 uart_barrier(bas);
  461                 if (z8530->txidle) {
  462                         ipend |= SER_INT_TXIDLE;
  463                         z8530->txidle = 0;      /* Mask SER_INT_TXIDLE. */
  464                 }
  465         }
  466 
  467         if (ip & IP_SIA) {
  468                 uart_setreg(bas, REG_CTRL, CR_RSTXSI);
  469                 uart_barrier(bas);
  470                 bes = uart_getmreg(bas, RR_BES);
  471                 if (bes & BES_BRK)
  472                         ipend |= SER_INT_BREAK;
  473                 sig = sc->sc_hwsig;
  474                 SIGCHG(bes & BES_CTS, sig, SER_CTS, SER_DCTS);
  475                 SIGCHG(bes & BES_DCD, sig, SER_DCD, SER_DDCD);
  476                 SIGCHG(bes & BES_SYNC, sig, SER_DSR, SER_DDSR);
  477                 if (sig & SER_MASK_DELTA)
  478                         ipend |= SER_INT_SIGCHG;
  479                 src = uart_getmreg(bas, RR_SRC);
  480                 if (src & SRC_OVR) {
  481                         uart_setreg(bas, REG_CTRL, CR_RSTERR);
  482                         uart_barrier(bas);
  483                         ipend |= SER_INT_OVERRUN;
  484                 }
  485         }
  486 
  487         if (ipend) {
  488                 uart_setreg(bas, REG_CTRL, CR_RSTIUS);
  489                 uart_barrier(bas);
  490         }
  491 
  492         uart_unlock(sc->sc_hwmtx);
  493 
  494         return (ipend);
  495 }
  496 
  497 static int
  498 z8530_bus_param(struct uart_softc *sc, int baudrate, int databits,
  499     int stopbits, int parity)
  500 {
  501         struct z8530_softc *z8530 = (struct z8530_softc*)sc;
  502         int error;
  503 
  504         uart_lock(sc->sc_hwmtx);
  505         error = z8530_param(&sc->sc_bas, baudrate, databits, stopbits, parity,
  506             &z8530->tpc);
  507         uart_unlock(sc->sc_hwmtx);
  508         return (error);
  509 }
  510 
  511 static int
  512 z8530_bus_probe(struct uart_softc *sc)
  513 {
  514         char buf[80];
  515         int error;
  516         char ch;
  517 
  518         error = z8530_probe(&sc->sc_bas);
  519         if (error)
  520                 return (error);
  521 
  522         sc->sc_rxfifosz = 3;
  523         sc->sc_txfifosz = 1;
  524 
  525         ch = sc->sc_bas.chan - 1 + 'A';
  526 
  527         snprintf(buf, sizeof(buf), "z8530, channel %c", ch);
  528         device_set_desc_copy(sc->sc_dev, buf);
  529         return (0);
  530 }
  531 
  532 static int
  533 z8530_bus_receive(struct uart_softc *sc)
  534 {
  535         struct uart_bas *bas;
  536         int xc;
  537         uint8_t bes, src;
  538 
  539         bas = &sc->sc_bas;
  540         uart_lock(sc->sc_hwmtx);
  541         bes = uart_getmreg(bas, RR_BES);
  542         while (bes & BES_RXA) {
  543                 if (uart_rx_full(sc)) {
  544                         sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
  545                         break;
  546                 }
  547                 xc = uart_getreg(bas, REG_DATA);
  548                 uart_barrier(bas);
  549                 src = uart_getmreg(bas, RR_SRC);
  550                 if (src & SRC_FE)
  551                         xc |= UART_STAT_FRAMERR;
  552                 if (src & SRC_PE)
  553                         xc |= UART_STAT_PARERR;
  554                 if (src & SRC_OVR)
  555                         xc |= UART_STAT_OVERRUN;
  556                 uart_rx_put(sc, xc);
  557                 if (src & (SRC_FE | SRC_PE | SRC_OVR)) {
  558                         uart_setreg(bas, REG_CTRL, CR_RSTERR);
  559                         uart_barrier(bas);
  560                 }
  561                 bes = uart_getmreg(bas, RR_BES);
  562         }
  563         /* Discard everything left in the Rx FIFO. */
  564         while (bes & BES_RXA) {
  565                 (void)uart_getreg(bas, REG_DATA);
  566                 uart_barrier(bas);
  567                 src = uart_getmreg(bas, RR_SRC);
  568                 if (src & (SRC_FE | SRC_PE | SRC_OVR)) {
  569                         uart_setreg(bas, REG_CTRL, CR_RSTERR);
  570                         uart_barrier(bas);
  571                 }
  572                 bes = uart_getmreg(bas, RR_BES);
  573         }
  574         uart_unlock(sc->sc_hwmtx);
  575         return (0);
  576 }
  577 
  578 static int
  579 z8530_bus_setsig(struct uart_softc *sc, int sig)
  580 {
  581         struct z8530_softc *z8530 = (struct z8530_softc*)sc;
  582         struct uart_bas *bas;
  583         uint32_t new, old;
  584 
  585         bas = &sc->sc_bas;
  586         do {
  587                 old = sc->sc_hwsig;
  588                 new = old;
  589                 if (sig & SER_DDTR) {
  590                         SIGCHG(sig & SER_DTR, new, SER_DTR,
  591                             SER_DDTR);
  592                 }
  593                 if (sig & SER_DRTS) {
  594                         SIGCHG(sig & SER_RTS, new, SER_RTS,
  595                             SER_DRTS);
  596                 }
  597         } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
  598 
  599         uart_lock(sc->sc_hwmtx);
  600         if (new & SER_DTR)
  601                 z8530->tpc |= TPC_DTR;
  602         else
  603                 z8530->tpc &= ~TPC_DTR;
  604         if (new & SER_RTS)
  605                 z8530->tpc |= TPC_RTS;
  606         else
  607                 z8530->tpc &= ~TPC_RTS;
  608         uart_setmreg(bas, WR_TPC, z8530->tpc);
  609         uart_barrier(bas);
  610         uart_unlock(sc->sc_hwmtx);
  611         return (0);
  612 }
  613 
  614 static int
  615 z8530_bus_transmit(struct uart_softc *sc)
  616 {
  617         struct z8530_softc *z8530 = (struct z8530_softc*)sc;
  618         struct uart_bas *bas;
  619 
  620         bas = &sc->sc_bas;
  621         uart_lock(sc->sc_hwmtx);
  622         while (!(uart_getmreg(bas, RR_BES) & BES_TXE))
  623                 ;
  624         uart_setreg(bas, REG_DATA, sc->sc_txbuf[0]);
  625         uart_barrier(bas);
  626         sc->sc_txbusy = 1;
  627         z8530->txidle = 1;      /* Report SER_INT_TXIDLE again. */
  628         uart_unlock(sc->sc_hwmtx);
  629         return (0);
  630 }
  631 
  632 static void
  633 z8530_bus_grab(struct uart_softc *sc)
  634 {
  635         struct uart_bas *bas;
  636 
  637         bas = &sc->sc_bas;
  638         uart_lock(sc->sc_hwmtx);
  639         uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE);
  640         uart_barrier(bas);
  641         uart_unlock(sc->sc_hwmtx);
  642 }
  643 
  644 static void
  645 z8530_bus_ungrab(struct uart_softc *sc)
  646 {
  647         struct uart_bas *bas;
  648 
  649         bas = &sc->sc_bas;
  650         uart_lock(sc->sc_hwmtx);
  651         uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE | IDT_RIA);
  652         uart_barrier(bas);
  653         uart_unlock(sc->sc_hwmtx);
  654 }

Cache object: c545e97edabb0eab287f169810506f3b


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