[BACK]Return to cz.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/cz.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cz.c,v 1.9 2003/10/03 16:44:51 miod Exp $ */
        !             2: /*     $NetBSD: cz.c,v 1.15 2001/01/20 19:10:36 thorpej Exp $  */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2000 Zembu Labs, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Authors: Jason R. Thorpe <thorpej@zembu.com>
        !             9:  *          Bill Studenmund <wrstuden@zembu.com>
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *     This product includes software developed by Zembu Labs, Inc.
        !            22:  * 4. Neither the name of Zembu Labs nor the names of its employees may
        !            23:  *    be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY ZEMBU LABS, INC. ``AS IS'' AND ANY EXPRESS
        !            27:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAR-
        !            28:  * RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS-
        !            29:  * CLAIMED.  IN NO EVENT SHALL ZEMBU LABS BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            30:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            31:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            32:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            33:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            35:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            36:  */
        !            37:
        !            38: /*
        !            39:  * Cyclades-Z series multi-port serial adapter driver for NetBSD.
        !            40:  *
        !            41:  * Some notes:
        !            42:  *
        !            43:  *     - The Cyclades-Z has fully automatic hardware (and software!)
        !            44:  *       flow control.  We only utilize RTS/CTS flow control here,
        !            45:  *       and it is implemented in a very simplistic manner.  This
        !            46:  *       may be an area of future work.
        !            47:  *
        !            48:  *     - The PLX can map the either the board's RAM or host RAM
        !            49:  *       into the MIPS's memory window.  This would enable us to
        !            50:  *       use less expensive (for us) memory reads/writes to host
        !            51:  *       RAM, rather than time-consuming reads/writes to PCI
        !            52:  *       memory space.  However, the PLX can only map a 0-128M
        !            53:  *       window, so we would have to ensure that the DMA address
        !            54:  *       of the host RAM fits there.  This is kind of a pain,
        !            55:  *       so we just don't bother right now.
        !            56:  *
        !            57:  *     - In a perfect world, we would use the autoconfiguration
        !            58:  *       mechanism to attach the TTYs that we find.  However,
        !            59:  *       that leads to somewhat icky looking autoconfiguration
        !            60:  *       messages (one for every TTY, up to 64 per board!).  So
        !            61:  *       we don't do it that way, but assign minors as if there
        !            62:  *       were the max of 64 ports per board.
        !            63:  *
        !            64:  *     - We don't bother with PPS support here.  There are so many
        !            65:  *       ports, each with a large amount of buffer space, that the
        !            66:  *       normal mode of operation is to poll the boards regularly
        !            67:  *       (generally, every 20ms or so).  This makes this driver
        !            68:  *       unsuitable for PPS, as the latency will be generally too
        !            69:  *       high.
        !            70:  */
        !            71: /*
        !            72:  * This driver inspired by the FreeBSD driver written by Brian J. McGovern
        !            73:  * for FreeBSD 3.2.
        !            74:  */
        !            75:
        !            76: #include <sys/param.h>
        !            77: #include <sys/systm.h>
        !            78: #include <sys/proc.h>
        !            79: #include <sys/device.h>
        !            80: #include <sys/malloc.h>
        !            81: #include <sys/tty.h>
        !            82: #include <sys/conf.h>
        !            83: #include <sys/time.h>
        !            84: #include <sys/kernel.h>
        !            85: #include <sys/fcntl.h>
        !            86: #include <sys/syslog.h>
        !            87:
        !            88: #include <dev/pci/pcireg.h>
        !            89: #include <dev/pci/pcivar.h>
        !            90: #include <dev/pci/pcidevs.h>
        !            91: #include <dev/pci/czreg.h>
        !            92:
        !            93: #include <dev/pci/plx9060reg.h>
        !            94: #include <dev/pci/plx9060var.h>
        !            95:
        !            96: #include <dev/microcode/cyclades/cyzfirm.h>
        !            97:
        !            98: #define        CZ_DRIVER_VERSION       0x20000411
        !            99:
        !           100: #define CZ_POLL_MS                     20
        !           101:
        !           102: /* These are the interrupts we always use. */
        !           103: #define        CZ_INTERRUPTS                                                   \
        !           104:        (C_IN_MDSR | C_IN_MRI | C_IN_MRTS | C_IN_MCTS | C_IN_TXBEMPTY | \
        !           105:         C_IN_TXFEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | C_IN_RXNNDT |     \
        !           106:         C_IN_MDCD | C_IN_PR_ERROR | C_IN_FR_ERROR | C_IN_OVR_ERROR |   \
        !           107:         C_IN_RXOFL | C_IN_IOCTLW | C_IN_RXBRK)
        !           108:
        !           109: /*
        !           110:  * cztty_softc:
        !           111:  *
        !           112:  *     Per-channel (TTY) state.
        !           113:  */
        !           114: struct cztty_softc {
        !           115:        struct cz_softc *sc_parent;
        !           116:        struct tty *sc_tty;
        !           117:
        !           118:        struct timeout sc_diag_to;
        !           119:
        !           120:        int sc_channel;                 /* Also used to flag unattached chan */
        !           121: #define CZTTY_CHANNEL_DEAD     -1
        !           122:
        !           123:        bus_space_tag_t sc_chan_st;     /* channel space tag */
        !           124:        bus_space_handle_t sc_chan_sh;  /* channel space handle */
        !           125:        bus_space_handle_t sc_buf_sh;   /* buffer space handle */
        !           126:
        !           127:        u_int sc_overflows,
        !           128:              sc_parity_errors,
        !           129:              sc_framing_errors,
        !           130:              sc_errors;
        !           131:
        !           132:        int sc_swflags;
        !           133:
        !           134:        u_int32_t sc_rs_control_dtr,
        !           135:                  sc_chanctl_hw_flow,
        !           136:                  sc_chanctl_comm_baud,
        !           137:                  sc_chanctl_rs_control,
        !           138:                  sc_chanctl_comm_data_l,
        !           139:                  sc_chanctl_comm_parity;
        !           140: };
        !           141:
        !           142: /*
        !           143:  * cz_softc:
        !           144:  *
        !           145:  *     Per-board state.
        !           146:  */
        !           147: struct cz_softc {
        !           148:        struct device cz_dev;           /* generic device info */
        !           149:        struct plx9060_config cz_plx;   /* PLX 9060 config info */
        !           150:        bus_space_tag_t cz_win_st;      /* window space tag */
        !           151:        bus_space_handle_t cz_win_sh;   /* window space handle */
        !           152:        struct timeout cz_timeout;      /* timeout for polling-mode */
        !           153:
        !           154:        void *cz_ih;                    /* interrupt handle */
        !           155:
        !           156:        u_int32_t cz_mailbox0;          /* our MAILBOX0 value */
        !           157:        int cz_nchannels;               /* number of channels */
        !           158:        int cz_nopenchan;               /* number of open channels */
        !           159:        struct cztty_softc *cz_ports;   /* our array of ports */
        !           160:
        !           161:        bus_addr_t cz_fwctl;            /* offset of firmware control */
        !           162: };
        !           163:
        !           164: int    cz_match(struct device *, void *, void *);
        !           165: void   cz_attach(struct device *, struct device *, void *);
        !           166: int    cz_wait_pci_doorbell(struct cz_softc *, char *);
        !           167:
        !           168: struct cfattach cz_ca = {
        !           169:        sizeof(struct cz_softc), cz_match, cz_attach
        !           170: };
        !           171:
        !           172: void   cz_reset_board(struct cz_softc *);
        !           173: int    cz_load_firmware(struct cz_softc *);
        !           174:
        !           175: int    cz_intr(void *);
        !           176: void   cz_poll(void *);
        !           177: int    cztty_transmit(struct cztty_softc *, struct tty *);
        !           178: int    cztty_receive(struct cztty_softc *, struct tty *);
        !           179:
        !           180: struct cztty_softc * cztty_getttysoftc(dev_t dev);
        !           181: int    cztty_findmajor(void);
        !           182: int    cztty_major;
        !           183: int    cztty_attached_ttys;
        !           184: int    cz_timeout_ticks;
        !           185:
        !           186: cdev_decl(cztty);
        !           187:
        !           188: void    czttystart(struct tty *tp);
        !           189: int    czttyparam(struct tty *tp, struct termios *t);
        !           190: void    cztty_shutdown(struct cztty_softc *sc);
        !           191: void   cztty_modem(struct cztty_softc *sc, int onoff);
        !           192: void   cztty_break(struct cztty_softc *sc, int onoff);
        !           193: void   tiocm_to_cztty(struct cztty_softc *sc, u_long how, int ttybits);
        !           194: int    cztty_to_tiocm(struct cztty_softc *sc);
        !           195: void   cztty_diag(void *arg);
        !           196:
        !           197: struct cfdriver cz_cd = {
        !           198:        0, "cz", DV_TTY
        !           199: };
        !           200:
        !           201: /*
        !           202:  * Macros to read and write the PLX.
        !           203:  */
        !           204: #define        CZ_PLX_READ(cz, reg)                                            \
        !           205:        bus_space_read_4((cz)->cz_plx.plx_st, (cz)->cz_plx.plx_sh, (reg))
        !           206: #define        CZ_PLX_WRITE(cz, reg, val)                                      \
        !           207:        bus_space_write_4((cz)->cz_plx.plx_st, (cz)->cz_plx.plx_sh,     \
        !           208:            (reg), (val))
        !           209:
        !           210: /*
        !           211:  * Macros to read and write the FPGA.  We must already be in the FPGA
        !           212:  * window for this.
        !           213:  */
        !           214: #define        CZ_FPGA_READ(cz, reg)                                           \
        !           215:        bus_space_read_4((cz)->cz_win_st, (cz)->cz_win_sh, (reg))
        !           216: #define        CZ_FPGA_WRITE(cz, reg, val)                                     \
        !           217:        bus_space_write_4((cz)->cz_win_st, (cz)->cz_win_sh, (reg), (val))
        !           218:
        !           219: /*
        !           220:  * Macros to read and write the firmware control structures in board RAM.
        !           221:  */
        !           222: #define        CZ_FWCTL_READ(cz, off)                                          \
        !           223:        bus_space_read_4((cz)->cz_win_st, (cz)->cz_win_sh,              \
        !           224:            (cz)->cz_fwctl + (off))
        !           225:
        !           226: #define        CZ_FWCTL_WRITE(cz, off, val)                                    \
        !           227:        bus_space_write_4((cz)->cz_win_st, (cz)->cz_win_sh,             \
        !           228:            (cz)->cz_fwctl + (off), (val))
        !           229:
        !           230: /*
        !           231:  * Convenience macros for cztty routines.  PLX window MUST be to RAM.
        !           232:  */
        !           233: #define CZTTY_CHAN_READ(sc, off)                                       \
        !           234:        bus_space_read_4((sc)->sc_chan_st, (sc)->sc_chan_sh, (off))
        !           235:
        !           236: #define CZTTY_CHAN_WRITE(sc, off, val)                                 \
        !           237:        bus_space_write_4((sc)->sc_chan_st, (sc)->sc_chan_sh,           \
        !           238:            (off), (val))
        !           239:
        !           240: #define CZTTY_BUF_READ(sc, off)                                                \
        !           241:        bus_space_read_4((sc)->sc_chan_st, (sc)->sc_buf_sh, (off))
        !           242:
        !           243: #define CZTTY_BUF_WRITE(sc, off, val)                                  \
        !           244:        bus_space_write_4((sc)->sc_chan_st, (sc)->sc_buf_sh,            \
        !           245:            (off), (val))
        !           246:
        !           247: /*
        !           248:  * Convenience macros.
        !           249:  */
        !           250: #define        CZ_WIN_RAM(cz)                                                  \
        !           251: do {                                                                   \
        !           252:        CZ_PLX_WRITE((cz), PLX_LAS0BA, LOCAL_ADDR0_RAM);                \
        !           253:        delay(100);                                                     \
        !           254: } while (0)
        !           255:
        !           256: #define        CZ_WIN_FPGA(cz)                                                 \
        !           257: do {                                                                   \
        !           258:        CZ_PLX_WRITE((cz), PLX_LAS0BA, LOCAL_ADDR0_FPGA);               \
        !           259:        delay(100);                                                     \
        !           260: } while (0)
        !           261:
        !           262: /*****************************************************************************
        !           263:  * Cyclades-Z controller code starts here...
        !           264:  *****************************************************************************/
        !           265:
        !           266: /*
        !           267:  * cz_match:
        !           268:  *
        !           269:  *     Determine if the given PCI device is a Cyclades-Z board.
        !           270:  */
        !           271: int
        !           272: cz_match(parent, match, aux)
        !           273:        struct device *parent;
        !           274:        void *match, *aux;
        !           275: {
        !           276:        struct pci_attach_args *pa = aux;
        !           277:
        !           278:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CYCLADES &&
        !           279:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CYCLADES_CYCLOMZ_2)
        !           280:                return (1);
        !           281:        return (0);
        !           282: }
        !           283:
        !           284: /*
        !           285:  * cz_attach:
        !           286:  *
        !           287:  *     A Cyclades-Z board was found; attach it.
        !           288:  */
        !           289: void
        !           290: cz_attach(parent, self, aux)
        !           291:        struct device *parent, *self;
        !           292:        void *aux;
        !           293: {
        !           294:        struct cz_softc *cz = (void *) self;
        !           295:        struct pci_attach_args *pa = aux;
        !           296:        pci_chipset_tag_t pc = pa->pa_pc;
        !           297:        pci_intr_handle_t ih;
        !           298:        const char *intrstr = NULL;
        !           299:        struct cztty_softc *sc;
        !           300:        struct tty *tp;
        !           301:        int i;
        !           302:
        !           303:        cz->cz_plx.plx_pc = pa->pa_pc;
        !           304:        cz->cz_plx.plx_tag = pa->pa_tag;
        !           305:
        !           306:        if (pci_mapreg_map(pa, PLX_PCI_RUNTIME_MEMADDR,
        !           307:            PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
        !           308:            &cz->cz_plx.plx_st, &cz->cz_plx.plx_sh, NULL, NULL, 0) != 0) {
        !           309:                printf(": unable to map PLX registers\n");
        !           310:                return;
        !           311:        }
        !           312:        if (pci_mapreg_map(pa, PLX_PCI_LOCAL_ADDR0,
        !           313:            PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
        !           314:            &cz->cz_win_st, &cz->cz_win_sh, NULL, NULL, 0) != 0) {
        !           315:                printf(": unable to map device window\n");
        !           316:                return;
        !           317:        }
        !           318:
        !           319:        cz->cz_mailbox0 = CZ_PLX_READ(cz, PLX_MAILBOX0);
        !           320:        cz->cz_nopenchan = 0;
        !           321:
        !           322:        /*
        !           323:         * Make sure that the board is completely stopped.
        !           324:         */
        !           325:        CZ_WIN_FPGA(cz);
        !           326:        CZ_FPGA_WRITE(cz, FPGA_CPU_STOP, 0);
        !           327:
        !           328:        /*
        !           329:         * Load the board's firmware.
        !           330:         */
        !           331:        if (cz_load_firmware(cz) != 0)
        !           332:                return;
        !           333:
        !           334:        /*
        !           335:         * Now that we're ready to roll, map and establish the interrupt
        !           336:         * handler.
        !           337:         */
        !           338:        if (pci_intr_map(pa, &ih) != 0) {
        !           339:                /*
        !           340:                 * The common case is for Cyclades-Z boards to run
        !           341:                 * in polling mode, and thus not have an interrupt
        !           342:                 * mapped for them.  Don't bother reporting that
        !           343:                 * the interrupt is not mappable, since this isn't
        !           344:                 * really an error.
        !           345:                 */
        !           346:                cz->cz_ih = NULL;
        !           347:                goto polling_mode;
        !           348:        } else {
        !           349:                intrstr = pci_intr_string(pa->pa_pc, ih);
        !           350:                cz->cz_ih = pci_intr_establish(pc, ih, IPL_TTY,
        !           351:                            cz_intr, cz, cz->cz_dev.dv_xname);
        !           352:        }
        !           353:        if (cz->cz_ih == NULL) {
        !           354:                printf(": unable to establish interrupt");
        !           355:                if (intrstr != NULL)
        !           356:                        printf(" at %s", intrstr);
        !           357:                printf("\n");
        !           358:                /* We will fall-back on polling mode. */
        !           359:        } else
        !           360:                printf(": %s\n", intrstr);
        !           361:
        !           362:  polling_mode:
        !           363:        if (cz->cz_ih == NULL) {
        !           364:                timeout_set(&cz->cz_timeout, cz_poll, cz);
        !           365:                if (cz_timeout_ticks == 0)
        !           366:                        cz_timeout_ticks = max(1, hz * CZ_POLL_MS / 1000);
        !           367:                printf("%s: polling mode, %d ms interval (%d tick%s)\n",
        !           368:                    cz->cz_dev.dv_xname, CZ_POLL_MS, cz_timeout_ticks,
        !           369:                    cz_timeout_ticks == 1 ? "" : "s");
        !           370:        }
        !           371:
        !           372:        if (cztty_major == 0)
        !           373:                cztty_major = cztty_findmajor();
        !           374:        /*
        !           375:         * Allocate sufficient pointers for the children and
        !           376:         * attach them.  Set all ports to a reasonable initial
        !           377:         * configuration while we're at it:
        !           378:         *
        !           379:         *      disabled
        !           380:         *      8N1
        !           381:         *      default baud rate
        !           382:         *      hardware flow control.
        !           383:         */
        !           384:        CZ_WIN_RAM(cz);
        !           385:
        !           386:        if (cz->cz_nchannels == 0) {
        !           387:                /* No channels?  No more work to do! */
        !           388:                return;
        !           389:        }
        !           390:
        !           391:        cz->cz_ports = malloc(sizeof(struct cztty_softc) * cz->cz_nchannels,
        !           392:            M_DEVBUF, M_WAITOK);
        !           393:        cztty_attached_ttys += cz->cz_nchannels;
        !           394:        memset(cz->cz_ports, 0,
        !           395:            sizeof(struct cztty_softc) * cz->cz_nchannels);
        !           396:
        !           397:        for (i = 0; i < cz->cz_nchannels; i++) {
        !           398:                sc = &cz->cz_ports[i];
        !           399:
        !           400:                sc->sc_channel = i;
        !           401:                sc->sc_chan_st = cz->cz_win_st;
        !           402:                sc->sc_parent = cz;
        !           403:
        !           404:                if (bus_space_subregion(cz->cz_win_st, cz->cz_win_sh,
        !           405:                    cz->cz_fwctl + ZFIRM_CHNCTL_OFF(i, 0),
        !           406:                    ZFIRM_CHNCTL_SIZE, &sc->sc_chan_sh)) {
        !           407:                        printf("%s: unable to subregion channel %d control\n",
        !           408:                            cz->cz_dev.dv_xname, i);
        !           409:                        sc->sc_channel = CZTTY_CHANNEL_DEAD;
        !           410:                        continue;
        !           411:                }
        !           412:                if (bus_space_subregion(cz->cz_win_st, cz->cz_win_sh,
        !           413:                    cz->cz_fwctl + ZFIRM_BUFCTL_OFF(i, 0),
        !           414:                    ZFIRM_BUFCTL_SIZE, &sc->sc_buf_sh)) {
        !           415:                        printf("%s: unable to subregion channel %d buffer\n",
        !           416:                            cz->cz_dev.dv_xname, i);
        !           417:                        sc->sc_channel = CZTTY_CHANNEL_DEAD;
        !           418:                        continue;
        !           419:                }
        !           420:
        !           421:                timeout_set(&sc->sc_diag_to, cztty_diag, sc);
        !           422:
        !           423:                tp = ttymalloc();
        !           424:                tp->t_dev = makedev(cztty_major,
        !           425:                    (cz->cz_dev.dv_unit * ZFIRM_MAX_CHANNELS) + i);
        !           426:                tp->t_oproc = czttystart;
        !           427:                tp->t_param = czttyparam;
        !           428:
        !           429:                sc->sc_tty = tp;
        !           430:
        !           431:                CZTTY_CHAN_WRITE(sc, CHNCTL_OP_MODE, C_CH_DISABLE);
        !           432:                CZTTY_CHAN_WRITE(sc, CHNCTL_INTR_ENABLE, CZ_INTERRUPTS);
        !           433:                CZTTY_CHAN_WRITE(sc, CHNCTL_SW_FLOW, 0);
        !           434:                CZTTY_CHAN_WRITE(sc, CHNCTL_FLOW_XON, 0x11);
        !           435:                CZTTY_CHAN_WRITE(sc, CHNCTL_FLOW_XOFF, 0x13);
        !           436:                CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_BAUD, TTYDEF_SPEED);
        !           437:                CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_PARITY, C_PR_NONE);
        !           438:                CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_DATA_L, C_DL_CS8 | C_DL_1STOP);
        !           439:                CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_FLAGS, 0);
        !           440:                CZTTY_CHAN_WRITE(sc, CHNCTL_HW_FLOW, C_RS_CTS | C_RS_RTS);
        !           441:                CZTTY_CHAN_WRITE(sc, CHNCTL_RS_CONTROL, 0);
        !           442:        }
        !           443: }
        !           444:
        !           445: /*
        !           446:  * cz_reset_board:
        !           447:  *
        !           448:  *     Reset the board via the PLX.
        !           449:  */
        !           450: void
        !           451: cz_reset_board(struct cz_softc *cz)
        !           452: {
        !           453:        u_int32_t reg;
        !           454:
        !           455:        reg = CZ_PLX_READ(cz, PLX_CONTROL);
        !           456:        CZ_PLX_WRITE(cz, PLX_CONTROL, reg | CONTROL_SWR);
        !           457:        delay(1000);
        !           458:
        !           459:        CZ_PLX_WRITE(cz, PLX_CONTROL, reg);
        !           460:        delay(1000);
        !           461:
        !           462:        /* Now reload the PLX from its EEPROM. */
        !           463:        reg = CZ_PLX_READ(cz, PLX_CONTROL);
        !           464:        CZ_PLX_WRITE(cz, PLX_CONTROL, reg | CONTROL_RELOADCFG);
        !           465:        delay(1000);
        !           466:        CZ_PLX_WRITE(cz, PLX_CONTROL, reg);
        !           467: }
        !           468:
        !           469: /*
        !           470:  * cz_load_firmware:
        !           471:  *
        !           472:  *     Load the ZFIRM firmware into the board's RAM and start it
        !           473:  *     running.
        !           474:  */
        !           475: int
        !           476: cz_load_firmware(struct cz_softc *cz)
        !           477: {
        !           478:        struct zfirm_header *zfh;
        !           479:        struct zfirm_config *zfc;
        !           480:        struct zfirm_block *zfb, *zblocks;
        !           481:        const u_int8_t *cp;
        !           482:        const char *board;
        !           483:        u_int32_t fid;
        !           484:        int i, j, nconfigs, nblocks, nbytes;
        !           485:
        !           486:        zfh = (struct zfirm_header *) cycladesz_firmware;
        !           487:
        !           488:        /* Find the config header. */
        !           489:        if (letoh32(zfh->zfh_configoff) & (sizeof(u_int32_t) - 1)) {
        !           490:                printf("%s: bad ZFIRM config offset: 0x%x\n",
        !           491:                    cz->cz_dev.dv_xname, letoh32(zfh->zfh_configoff));
        !           492:                return (EIO);
        !           493:        }
        !           494:        zfc = (struct zfirm_config *)(cycladesz_firmware +
        !           495:            letoh32(zfh->zfh_configoff));
        !           496:        nconfigs = letoh32(zfh->zfh_nconfig);
        !           497:
        !           498:        /* Locate the correct configuration for our board. */
        !           499:        for (i = 0; i < nconfigs; i++, zfc++) {
        !           500:                if (letoh32(zfc->zfc_mailbox) == cz->cz_mailbox0 &&
        !           501:                    letoh32(zfc->zfc_function) == ZFC_FUNCTION_NORMAL)
        !           502:                        break;
        !           503:        }
        !           504:        if (i == nconfigs) {
        !           505:                printf("%s: unable to locate config header\n",
        !           506:                    cz->cz_dev.dv_xname);
        !           507:                return (EIO);
        !           508:        }
        !           509:
        !           510:        nblocks = letoh32(zfc->zfc_nblocks);
        !           511:        zblocks = (struct zfirm_block *)(cycladesz_firmware +
        !           512:            letoh32(zfh->zfh_blockoff));
        !           513:
        !           514:        /*
        !           515:         * 8Zo ver. 1 doesn't have an FPGA.  Load it on all others if
        !           516:         * necessary.
        !           517:         */
        !           518:        if (cz->cz_mailbox0 != MAILBOX0_8Zo_V1
        !           519: #if 0
        !           520:            && ((CZ_PLX_READ(cz, PLX_CONTROL) & CONTROL_FPGA_LOADED) == 0)
        !           521: #endif
        !           522:                                                                ) {
        !           523: #ifdef CZ_DEBUG
        !           524:                printf("%s: Loading FPGA...", cz->cz_dev.dv_xname);
        !           525: #endif
        !           526:                CZ_WIN_FPGA(cz);
        !           527:                for (i = 0; i < nblocks; i++) {
        !           528:                        /* zfb = zblocks + letoh32(zfc->zfc_blocklist[i]) ?? */
        !           529:                        zfb = &zblocks[letoh32(zfc->zfc_blocklist[i])];
        !           530:                        if (letoh32(zfb->zfb_type) == ZFB_TYPE_FPGA) {
        !           531:                                nbytes = letoh32(zfb->zfb_size);
        !           532:                                cp = &cycladesz_firmware[
        !           533:                                    letoh32(zfb->zfb_fileoff)];
        !           534:                                for (j = 0; j < nbytes; j++, cp++) {
        !           535:                                        bus_space_write_1(cz->cz_win_st,
        !           536:                                            cz->cz_win_sh, 0, *cp);
        !           537:                                        /* FPGA needs 30-100us to settle. */
        !           538:                                        delay(10);
        !           539:                                }
        !           540:                        }
        !           541:                }
        !           542: #ifdef CZ_DEBUG
        !           543:                printf("done\n");
        !           544: #endif
        !           545:        }
        !           546:
        !           547:        /* Now load the firmware. */
        !           548:        CZ_WIN_RAM(cz);
        !           549:
        !           550:        for (i = 0; i < nblocks; i++) {
        !           551:                /* zfb = zblocks + letoh32(zfc->zfc_blocklist[i]) ?? */
        !           552:                zfb = &zblocks[letoh32(zfc->zfc_blocklist[i])];
        !           553:                if (letoh32(zfb->zfb_type) == ZFB_TYPE_FIRMWARE) {
        !           554:                        const u_int32_t *lp;
        !           555:                        u_int32_t ro = letoh32(zfb->zfb_ramoff);
        !           556:                        nbytes = letoh32(zfb->zfb_size);
        !           557:                        lp = (const u_int32_t *)
        !           558:                            &cycladesz_firmware[letoh32(zfb->zfb_fileoff)];
        !           559:                        for (j = 0; j < nbytes; j += 4, lp++) {
        !           560:                                bus_space_write_4(cz->cz_win_st, cz->cz_win_sh,
        !           561:                                    ro + j, letoh32(*lp));
        !           562:                                delay(10);
        !           563:                        }
        !           564:                }
        !           565:        }
        !           566:
        !           567:        /* Now restart the MIPS. */
        !           568:        CZ_WIN_FPGA(cz);
        !           569:        CZ_FPGA_WRITE(cz, FPGA_CPU_START, 0);
        !           570:
        !           571:        /* Wait for the MIPS to start, then report the results. */
        !           572:        CZ_WIN_RAM(cz);
        !           573:
        !           574: #ifdef CZ_DEBUG
        !           575:        printf("%s: waiting for MIPS to start", cz->cz_dev.dv_xname);
        !           576: #endif
        !           577:        for (i = 0; i < 100; i++) {
        !           578:                fid = bus_space_read_4(cz->cz_win_st, cz->cz_win_sh,
        !           579:                    ZFIRM_SIG_OFF);
        !           580:                if (fid == ZFIRM_SIG) {
        !           581:                        /* MIPS has booted. */
        !           582:                        break;
        !           583:                } else if (fid == ZFIRM_HLT) {
        !           584:                        /*
        !           585:                         * The MIPS has halted, usually due to a power
        !           586:                         * shortage on the expansion module.
        !           587:                         */
        !           588:                        printf("%s: MIPS halted; possible power supply "
        !           589:                            "problem\n", cz->cz_dev.dv_xname);
        !           590:                        return (EIO);
        !           591:                } else {
        !           592: #ifdef CZ_DEBUG
        !           593:                        if ((i % 8) == 0)
        !           594:                                printf(".");
        !           595: #endif
        !           596:                        delay(250000);
        !           597:                }
        !           598:        }
        !           599: #ifdef CZ_DEBUG
        !           600:        printf("\n");
        !           601: #endif
        !           602:        if (i == 100) {
        !           603:                CZ_WIN_FPGA(cz);
        !           604:                printf("%s: MIPS failed to start; wanted 0x%08x got 0x%08x\n",
        !           605:                    cz->cz_dev.dv_xname, ZFIRM_SIG, fid);
        !           606:                printf("%s: FPGA ID 0x%08x, FPGA version 0x%08x\n",
        !           607:                    cz->cz_dev.dv_xname, CZ_FPGA_READ(cz, FPGA_ID),
        !           608:                    CZ_FPGA_READ(cz, FPGA_VERSION));
        !           609:                return (EIO);
        !           610:        }
        !           611:
        !           612:        /*
        !           613:         * Locate the firmware control structures.
        !           614:         */
        !           615:        cz->cz_fwctl = bus_space_read_4(cz->cz_win_st, cz->cz_win_sh,
        !           616:            ZFIRM_CTRLADDR_OFF);
        !           617: #ifdef CZ_DEBUG
        !           618:        printf("%s: FWCTL structure at offset 0x%08lx\n",
        !           619:            cz->cz_dev.dv_xname, cz->cz_fwctl);
        !           620: #endif
        !           621:
        !           622:        CZ_FWCTL_WRITE(cz, BRDCTL_C_OS, C_OS_BSD);
        !           623:        CZ_FWCTL_WRITE(cz, BRDCTL_DRVERSION, CZ_DRIVER_VERSION);
        !           624:
        !           625:        cz->cz_nchannels = CZ_FWCTL_READ(cz, BRDCTL_NCHANNEL);
        !           626:
        !           627:        switch (cz->cz_mailbox0) {
        !           628:        case MAILBOX0_8Zo_V1:
        !           629:                board = "Cyclades-8Zo ver. 1";
        !           630:                break;
        !           631:
        !           632:        case MAILBOX0_8Zo_V2:
        !           633:                board = "Cyclades-8Zo ver. 2";
        !           634:                break;
        !           635:
        !           636:        case MAILBOX0_Ze_V1:
        !           637:                board = "Cyclades-Ze";
        !           638:                break;
        !           639:
        !           640:        default:
        !           641:                board = "unknown Cyclades Z-series";
        !           642:                break;
        !           643:        }
        !           644:
        !           645:        fid = CZ_FWCTL_READ(cz, BRDCTL_FWVERSION);
        !           646:        printf("%s: %s, ", cz->cz_dev.dv_xname, board);
        !           647:        if (cz->cz_nchannels == 0)
        !           648:                printf("no channels attached, ");
        !           649:        else
        !           650:                printf("%d channels (ttyCZ%04d..ttyCZ%04d), ",
        !           651:                    cz->cz_nchannels, cztty_attached_ttys,
        !           652:                    cztty_attached_ttys + (cz->cz_nchannels - 1));
        !           653:        printf("firmware %x.%x.%x\n",
        !           654:            (fid >> 8) & 0xf, (fid >> 4) & 0xf, fid & 0xf);
        !           655:
        !           656:        return (0);
        !           657: }
        !           658:
        !           659: /*
        !           660:  * cz_poll:
        !           661:  *
        !           662:  * This card doesn't do interrupts, so scan it for activity every CZ_POLL_MS
        !           663:  * ms.
        !           664:  */
        !           665: void
        !           666: cz_poll(void *arg)
        !           667: {
        !           668:        int s = spltty();
        !           669:        struct cz_softc *cz = arg;
        !           670:
        !           671:        cz_intr(cz);
        !           672:        timeout_add(&cz->cz_timeout, cz_timeout_ticks);
        !           673:
        !           674:        splx(s);
        !           675: }
        !           676:
        !           677: /*
        !           678:  * cz_intr:
        !           679:  *
        !           680:  *     Interrupt service routine.
        !           681:  *
        !           682:  * We either are receiving an interrupt directly from the board, or we are
        !           683:  * in polling mode and it's time to poll.
        !           684:  */
        !           685: int
        !           686: cz_intr(void *arg)
        !           687: {
        !           688:        int     rval = 0;
        !           689:        u_int   command, channel, param;
        !           690:        struct  cz_softc *cz = arg;
        !           691:        struct  cztty_softc *sc;
        !           692:        struct  tty *tp;
        !           693:
        !           694:        while ((command = (CZ_PLX_READ(cz, PLX_LOCAL_PCI_DOORBELL) & 0xff))) {
        !           695:                rval = 1;
        !           696:                channel = CZ_FWCTL_READ(cz, BRDCTL_FWCMD_CHANNEL);
        !           697:                param = CZ_FWCTL_READ(cz, BRDCTL_FWCMD_PARAM);
        !           698:
        !           699:                /* now clear this interrupt, posslibly enabling another */
        !           700:                CZ_PLX_WRITE(cz, PLX_LOCAL_PCI_DOORBELL, command);
        !           701:
        !           702:                if (cz->cz_ports == NULL) {
        !           703: #ifdef CZ_DEBUG
        !           704:                        printf("%s: interrupt on channel %d, but no channels\n",
        !           705:                            cz->cz_dev.dv_xname, channel);
        !           706: #endif
        !           707:                        continue;
        !           708:                }
        !           709:
        !           710:                sc = &cz->cz_ports[channel];
        !           711:
        !           712:                if (sc->sc_channel == CZTTY_CHANNEL_DEAD)
        !           713:                        break;
        !           714:
        !           715:                tp = sc->sc_tty;
        !           716:
        !           717:                switch (command) {
        !           718:                case C_CM_TXFEMPTY:             /* transmit cases */
        !           719:                case C_CM_TXBEMPTY:
        !           720:                case C_CM_TXLOWWM:
        !           721:                case C_CM_INTBACK:
        !           722:                        if (!ISSET(tp->t_state, TS_ISOPEN)) {
        !           723: #ifdef CZ_DEBUG
        !           724:                                printf("%s: tx intr on closed channel %d\n",
        !           725:                                    cz->cz_dev.dv_xname, channel);
        !           726: #endif
        !           727:                                break;
        !           728:                        }
        !           729:
        !           730:                        if (cztty_transmit(sc, tp)) {
        !           731:                                /*
        !           732:                                 * Do wakeup stuff here.
        !           733:                                 */
        !           734:                                ttwakeup(tp);
        !           735:                                wakeup(tp);
        !           736:                        }
        !           737:                        break;
        !           738:
        !           739:                case C_CM_RXNNDT:               /* receive cases */
        !           740:                case C_CM_RXHIWM:
        !           741:                case C_CM_INTBACK2:             /* from restart ?? */
        !           742: #if 0
        !           743:                case C_CM_ICHAR:
        !           744: #endif
        !           745:                        if (!ISSET(tp->t_state, TS_ISOPEN)) {
        !           746:                                CZTTY_BUF_WRITE(sc, BUFCTL_RX_GET,
        !           747:                                    CZTTY_BUF_READ(sc, BUFCTL_RX_PUT));
        !           748:                                break;
        !           749:                        }
        !           750:
        !           751:                        if (cztty_receive(sc, tp)) {
        !           752:                                /*
        !           753:                                 * Do wakeup stuff here.
        !           754:                                 */
        !           755:                                ttwakeup(tp);
        !           756:                                wakeup(tp);
        !           757:                        }
        !           758:                        break;
        !           759:
        !           760:                case C_CM_MDCD:
        !           761:                        if (!ISSET(tp->t_state, TS_ISOPEN))
        !           762:                                break;
        !           763:
        !           764:                        (void) (*linesw[tp->t_line].l_modem)(tp,
        !           765:                            ISSET(C_RS_DCD, CZTTY_CHAN_READ(sc,
        !           766:                            CHNCTL_RS_STATUS)));
        !           767:                        break;
        !           768:
        !           769:                case C_CM_MDSR:
        !           770:                case C_CM_MRI:
        !           771:                case C_CM_MCTS:
        !           772:                case C_CM_MRTS:
        !           773:                        break;
        !           774:
        !           775:                case C_CM_IOCTLW:
        !           776:                        break;
        !           777:
        !           778:                case C_CM_PR_ERROR:
        !           779:                        sc->sc_parity_errors++;
        !           780:                        goto error_common;
        !           781:
        !           782:                case C_CM_FR_ERROR:
        !           783:                        sc->sc_framing_errors++;
        !           784:                        goto error_common;
        !           785:
        !           786:                case C_CM_OVR_ERROR:
        !           787:                        sc->sc_overflows++;
        !           788:  error_common:
        !           789:                        if (sc->sc_errors++ == 0)
        !           790:                                timeout_add(&sc->sc_diag_to, 60 * hz);
        !           791:                        break;
        !           792:
        !           793:                case C_CM_RXBRK:
        !           794:                        if (!ISSET(tp->t_state, TS_ISOPEN))
        !           795:                                break;
        !           796:
        !           797:                        /*
        !           798:                         * A break is a \000 character with TTY_FE error
        !           799:                         * flags set. So TTY_FE by itself works.
        !           800:                         */
        !           801:                        (*linesw[tp->t_line].l_rint)(TTY_FE, tp);
        !           802:                        ttwakeup(tp);
        !           803:                        wakeup(tp);
        !           804:                        break;
        !           805:
        !           806:                default:
        !           807: #ifdef CZ_DEBUG
        !           808:                        printf("%s: channel %d: Unknown interrupt 0x%x\n",
        !           809:                            cz->cz_dev.dv_xname, sc->sc_channel, command);
        !           810: #endif
        !           811:                        break;
        !           812:                }
        !           813:        }
        !           814:
        !           815:        return (rval);
        !           816: }
        !           817:
        !           818: /*
        !           819:  * cz_wait_pci_doorbell:
        !           820:  *
        !           821:  *     Wait for the pci doorbell to be clear - wait for pending
        !           822:  *     activity to drain.
        !           823:  */
        !           824: int
        !           825: cz_wait_pci_doorbell(struct cz_softc *cz, char *wstring)
        !           826: {
        !           827:        int     error;
        !           828:
        !           829:        while (CZ_PLX_READ(cz, PLX_PCI_LOCAL_DOORBELL)) {
        !           830:                error = tsleep(cz, TTIPRI | PCATCH, wstring, max(1, hz/100));
        !           831:                if ((error != 0) && (error != EWOULDBLOCK))
        !           832:                        return (error);
        !           833:        }
        !           834:        return (0);
        !           835: }
        !           836:
        !           837: /*****************************************************************************
        !           838:  * Cyclades-Z TTY code starts here...
        !           839:  *****************************************************************************/
        !           840:
        !           841: #define CZTTYDIALOUT_MASK      0x80
        !           842:
        !           843: #define        CZTTY_DIALOUT(dev)      (minor((dev)) & CZTTYDIALOUT_MASK)
        !           844: #define        CZTTY_CZ(sc)            ((sc)->sc_parent)
        !           845:
        !           846: #define        CZTTY_SOFTC(dev)        cztty_getttysoftc(dev)
        !           847:
        !           848: struct cztty_softc *
        !           849: cztty_getttysoftc(dev_t dev)
        !           850: {
        !           851:        int i, j, k, u = minor(dev) & ~CZTTYDIALOUT_MASK;
        !           852:        struct cz_softc *cz;
        !           853:
        !           854:        for (i = 0, j = 0; i < cz_cd.cd_ndevs; i++) {
        !           855:                k = j;
        !           856:                cz = (struct cz_softc *)device_lookup(&cz_cd, i);
        !           857:                if (cz == NULL)
        !           858:                        continue;
        !           859:                if (cz->cz_ports == NULL)
        !           860:                        continue;
        !           861:                j += cz->cz_nchannels;
        !           862:                if (j > u)
        !           863:                        break;
        !           864:        }
        !           865:
        !           866:        if (i >= cz_cd.cd_ndevs)
        !           867:                return (NULL);
        !           868:        else
        !           869:                return (&cz->cz_ports[u - k]);
        !           870: }
        !           871:
        !           872: int
        !           873: cztty_findmajor(void)
        !           874: {
        !           875:        int     maj;
        !           876:
        !           877:        for (maj = 0; maj < nchrdev; maj++) {
        !           878:                if (cdevsw[maj].d_open == czttyopen)
        !           879:                        break;
        !           880:        }
        !           881:
        !           882:        return (maj == nchrdev) ? 0 : maj;
        !           883: }
        !           884:
        !           885: /*
        !           886:  * czttytty:
        !           887:  *
        !           888:  *     Return a pointer to our tty.
        !           889:  */
        !           890: struct tty *
        !           891: czttytty(dev_t dev)
        !           892: {
        !           893:        struct cztty_softc *sc = CZTTY_SOFTC(dev);
        !           894:
        !           895: #ifdef DIAGNOSTIC
        !           896:        if (sc == NULL)
        !           897:                panic("czttytty");
        !           898: #endif
        !           899:
        !           900:        return (sc->sc_tty);
        !           901: }
        !           902:
        !           903: /*
        !           904:  * cztty_shutdown:
        !           905:  *
        !           906:  *     Shut down a port.
        !           907:  */
        !           908: void
        !           909: cztty_shutdown(struct cztty_softc *sc)
        !           910: {
        !           911:        struct cz_softc *cz = CZTTY_CZ(sc);
        !           912:        struct tty *tp = sc->sc_tty;
        !           913:        int s;
        !           914:
        !           915:        s = spltty();
        !           916:
        !           917:        /* Clear any break condition set with TIOCSBRK. */
        !           918:        cztty_break(sc, 0);
        !           919:
        !           920:        /*
        !           921:         * Hang up if necessary.  Wait a bit, so the other side has time to
        !           922:         * notice even if we immediately open the port again.
        !           923:         */
        !           924:        if (ISSET(tp->t_cflag, HUPCL)) {
        !           925:                cztty_modem(sc, 0);
        !           926:                (void) tsleep(tp, TTIPRI, ttclos, hz);
        !           927:        }
        !           928:
        !           929:        /* Disable the channel. */
        !           930:        cz_wait_pci_doorbell(cz, "czdis");
        !           931:        CZTTY_CHAN_WRITE(sc, CHNCTL_OP_MODE, C_CH_DISABLE);
        !           932:        CZ_FWCTL_WRITE(cz, BRDCTL_HCMD_CHANNEL, sc->sc_channel);
        !           933:        CZ_PLX_WRITE(cz, PLX_PCI_LOCAL_DOORBELL, C_CM_IOCTL);
        !           934:
        !           935:        if ((--cz->cz_nopenchan == 0) && (cz->cz_ih == NULL)) {
        !           936: #ifdef CZ_DEBUG
        !           937:                printf("%s: Disabling polling\n", cz->cz_dev.dv_xname);
        !           938: #endif
        !           939:                timeout_del(&cz->cz_timeout);
        !           940:        }
        !           941:
        !           942:        splx(s);
        !           943: }
        !           944:
        !           945: /*
        !           946:  * czttyopen:
        !           947:  *
        !           948:  *     Open a Cyclades-Z serial port.
        !           949:  */
        !           950: int
        !           951: czttyopen(dev_t dev, int flags, int mode, struct proc *p)
        !           952: {
        !           953:        struct cztty_softc *sc = CZTTY_SOFTC(dev);
        !           954:        struct cz_softc *cz;
        !           955:        struct tty *tp;
        !           956:        int s, error;
        !           957:
        !           958:        if (sc == NULL)
        !           959:                return (ENXIO);
        !           960:
        !           961:        if (sc->sc_channel == CZTTY_CHANNEL_DEAD)
        !           962:                return (ENXIO);
        !           963:
        !           964:        cz = CZTTY_CZ(sc);
        !           965:        tp = sc->sc_tty;
        !           966:
        !           967:        if (ISSET(tp->t_state, TS_ISOPEN) &&
        !           968:            ISSET(tp->t_state, TS_XCLUDE) &&
        !           969:            p->p_ucred->cr_uid != 0)
        !           970:                return (EBUSY);
        !           971:
        !           972:        s = spltty();
        !           973:
        !           974:        /*
        !           975:         * Do the following iff this is a first open.
        !           976:         */
        !           977:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
        !           978:                struct termios t;
        !           979:
        !           980:                tp->t_dev = dev;
        !           981:
        !           982:                /* If we're turning things on, enable interrupts */
        !           983:                if ((cz->cz_nopenchan++ == 0) && (cz->cz_ih == NULL)) {
        !           984: #ifdef CZ_DEBUG
        !           985:                        printf("%s: Enabling polling.\n",
        !           986:                            cz->cz_dev.dv_xname);
        !           987: #endif
        !           988:                        timeout_add(&cz->cz_timeout, cz_timeout_ticks);
        !           989:                }
        !           990:
        !           991:                /*
        !           992:                 * Enable the channel.  Don't actually ring the
        !           993:                 * doorbell here; czttyparam() will do it for us.
        !           994:                 */
        !           995:                cz_wait_pci_doorbell(cz, "czopen");
        !           996:
        !           997:                CZTTY_CHAN_WRITE(sc, CHNCTL_OP_MODE, C_CH_ENABLE);
        !           998:
        !           999:                /*
        !          1000:                 * Initialize the termios status to the defaults.  Add in the
        !          1001:                 * sticky bits from TIOCSFLAGS.
        !          1002:                 */
        !          1003:                t.c_ispeed = 0;
        !          1004:                t.c_ospeed = TTYDEF_SPEED;
        !          1005:                t.c_cflag = TTYDEF_CFLAG;
        !          1006:                if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
        !          1007:                        SET(t.c_cflag, CLOCAL);
        !          1008:                if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
        !          1009:                        SET(t.c_cflag, CRTSCTS);
        !          1010:
        !          1011:                /*
        !          1012:                 * Reset the input and output rings.  Do this before
        !          1013:                 * we call czttyparam(), as that function enables
        !          1014:                 * the channel.
        !          1015:                 */
        !          1016:                CZTTY_BUF_WRITE(sc, BUFCTL_RX_GET,
        !          1017:                    CZTTY_BUF_READ(sc, BUFCTL_RX_PUT));
        !          1018:                CZTTY_BUF_WRITE(sc, BUFCTL_TX_PUT,
        !          1019:                    CZTTY_BUF_READ(sc, BUFCTL_TX_GET));
        !          1020:
        !          1021:                /* Make sure czttyparam() will see changes. */
        !          1022:                tp->t_ospeed = 0;
        !          1023:                (void) czttyparam(tp, &t);
        !          1024:                tp->t_iflag = TTYDEF_IFLAG;
        !          1025:                tp->t_oflag = TTYDEF_OFLAG;
        !          1026:                tp->t_lflag = TTYDEF_LFLAG;
        !          1027:                ttychars(tp);
        !          1028:                ttsetwater(tp);
        !          1029:
        !          1030:                /*
        !          1031:                 * Turn on DTR.  We must always do this, even if carrier is not
        !          1032:                 * present, because otherwise we'd have to use TIOCSDTR
        !          1033:                 * immediately after setting CLOCAL, which applications do not
        !          1034:                 * expect.  We always assert DTR while the device is open
        !          1035:                 * unless explicitly requested to deassert it.
        !          1036:                 */
        !          1037:                cztty_modem(sc, 1);
        !          1038:        }
        !          1039:
        !          1040:        splx(s);
        !          1041:
        !          1042:        error = ttyopen(CZTTY_DIALOUT(dev), tp);
        !          1043:        if (error)
        !          1044:                goto bad;
        !          1045:
        !          1046:        error = (*linesw[tp->t_line].l_open)(dev, tp);
        !          1047:        if (error)
        !          1048:                goto bad;
        !          1049:
        !          1050:        return (0);
        !          1051:
        !          1052:  bad:
        !          1053:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
        !          1054:                /*
        !          1055:                 * We failed to open the device, and nobody else had it opened.
        !          1056:                 * Clean up the state as appropriate.
        !          1057:                 */
        !          1058:                cztty_shutdown(sc);
        !          1059:        }
        !          1060:
        !          1061:        return (error);
        !          1062: }
        !          1063:
        !          1064: /*
        !          1065:  * czttyclose:
        !          1066:  *
        !          1067:  *     Close a Cyclades-Z serial port.
        !          1068:  */
        !          1069: int
        !          1070: czttyclose(dev_t dev, int flags, int mode, struct proc *p)
        !          1071: {
        !          1072:        struct cztty_softc *sc = CZTTY_SOFTC(dev);
        !          1073:        struct tty *tp = sc->sc_tty;
        !          1074:
        !          1075:        /* XXX This is for cons.c. */
        !          1076:        if (!ISSET(tp->t_state, TS_ISOPEN))
        !          1077:                return (0);
        !          1078:
        !          1079:        (*linesw[tp->t_line].l_close)(tp, flags);
        !          1080:        ttyclose(tp);
        !          1081:
        !          1082:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
        !          1083:                /*
        !          1084:                 * Although we got a last close, the device may still be in
        !          1085:                 * use; e.g. if this was the dialout node, and there are still
        !          1086:                 * processes waiting for carrier on the non-dialout node.
        !          1087:                 */
        !          1088:                cztty_shutdown(sc);
        !          1089:        }
        !          1090:
        !          1091:        return (0);
        !          1092: }
        !          1093:
        !          1094: /*
        !          1095:  * czttyread:
        !          1096:  *
        !          1097:  *     Read from a Cyclades-Z serial port.
        !          1098:  */
        !          1099: int
        !          1100: czttyread(dev_t dev, struct uio *uio, int flags)
        !          1101: {
        !          1102:        struct cztty_softc *sc = CZTTY_SOFTC(dev);
        !          1103:        struct tty *tp = sc->sc_tty;
        !          1104:
        !          1105:        return ((*linesw[tp->t_line].l_read)(tp, uio, flags));
        !          1106: }
        !          1107:
        !          1108: /*
        !          1109:  * czttywrite:
        !          1110:  *
        !          1111:  *     Write to a Cyclades-Z serial port.
        !          1112:  */
        !          1113: int
        !          1114: czttywrite(dev_t dev, struct uio *uio, int flags)
        !          1115: {
        !          1116:        struct cztty_softc *sc = CZTTY_SOFTC(dev);
        !          1117:        struct tty *tp = sc->sc_tty;
        !          1118:
        !          1119:        return ((*linesw[tp->t_line].l_write)(tp, uio, flags));
        !          1120: }
        !          1121:
        !          1122: #if 0
        !          1123: /*
        !          1124:  * czttypoll:
        !          1125:  *
        !          1126:  *     Poll a Cyclades-Z serial port.
        !          1127:  */
        !          1128: int
        !          1129: czttypoll(dev_t dev, int events, struct proc p)
        !          1130: {
        !          1131:        struct cztty_softc *sc = CZTTY_SOFTC(dev);
        !          1132:        struct tty *tp = sc->sc_tty;
        !          1133:
        !          1134:        return ((*linesw[tp->t_line].l_poll)(tp, events, p));
        !          1135: }
        !          1136: #endif
        !          1137:
        !          1138: /*
        !          1139:  * czttyioctl:
        !          1140:  *
        !          1141:  *     Perform a control operation on a Cyclades-Z serial port.
        !          1142:  */
        !          1143: int
        !          1144: czttyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
        !          1145: {
        !          1146:        struct cztty_softc *sc = CZTTY_SOFTC(dev);
        !          1147:        struct tty *tp = sc->sc_tty;
        !          1148:        int s, error;
        !          1149:
        !          1150:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
        !          1151:        if (error >= 0)
        !          1152:                return (error);
        !          1153:
        !          1154:        error = ttioctl(tp, cmd, data, flag, p);
        !          1155:        if (error >= 0)
        !          1156:                return (error);
        !          1157:
        !          1158:        error = 0;
        !          1159:
        !          1160:        s = spltty();
        !          1161:
        !          1162:        switch (cmd) {
        !          1163:        case TIOCSBRK:
        !          1164:                cztty_break(sc, 1);
        !          1165:                break;
        !          1166:
        !          1167:        case TIOCCBRK:
        !          1168:                cztty_break(sc, 0);
        !          1169:                break;
        !          1170:
        !          1171:        case TIOCGFLAGS:
        !          1172:                *(int *)data = sc->sc_swflags;
        !          1173:                break;
        !          1174:
        !          1175:        case TIOCSFLAGS:
        !          1176:                error = suser(p, 0);
        !          1177:                if (error)
        !          1178:                        break;
        !          1179:                sc->sc_swflags = *(int *)data;
        !          1180:                break;
        !          1181:
        !          1182:        case TIOCSDTR:
        !          1183:                cztty_modem(sc, 1);
        !          1184:                break;
        !          1185:
        !          1186:        case TIOCCDTR:
        !          1187:                cztty_modem(sc, 0);
        !          1188:                break;
        !          1189:
        !          1190:        case TIOCMSET:
        !          1191:        case TIOCMBIS:
        !          1192:        case TIOCMBIC:
        !          1193:                tiocm_to_cztty(sc, cmd, *(int *)data);
        !          1194:                break;
        !          1195:
        !          1196:        case TIOCMGET:
        !          1197:                *(int *)data = cztty_to_tiocm(sc);
        !          1198:                break;
        !          1199:
        !          1200:        default:
        !          1201:                error = ENOTTY;
        !          1202:                break;
        !          1203:        }
        !          1204:
        !          1205:        splx(s);
        !          1206:
        !          1207:        return (error);
        !          1208: }
        !          1209:
        !          1210: /*
        !          1211:  * cztty_break:
        !          1212:  *
        !          1213:  *     Set or clear BREAK on a port.
        !          1214:  */
        !          1215: void
        !          1216: cztty_break(struct cztty_softc *sc, int onoff)
        !          1217: {
        !          1218:        struct cz_softc *cz = CZTTY_CZ(sc);
        !          1219:
        !          1220:        cz_wait_pci_doorbell(cz, "czbreak");
        !          1221:
        !          1222:        CZ_FWCTL_WRITE(cz, BRDCTL_HCMD_CHANNEL, sc->sc_channel);
        !          1223:        CZ_PLX_WRITE(cz, PLX_PCI_LOCAL_DOORBELL,
        !          1224:            onoff ? C_CM_SET_BREAK : C_CM_CLR_BREAK);
        !          1225: }
        !          1226:
        !          1227: /*
        !          1228:  * cztty_modem:
        !          1229:  *
        !          1230:  *     Set or clear DTR on a port.
        !          1231:  */
        !          1232: void
        !          1233: cztty_modem(struct cztty_softc *sc, int onoff)
        !          1234: {
        !          1235:        struct cz_softc *cz = CZTTY_CZ(sc);
        !          1236:
        !          1237:        if (sc->sc_rs_control_dtr == 0)
        !          1238:                return;
        !          1239:
        !          1240:        cz_wait_pci_doorbell(cz, "czmod");
        !          1241:
        !          1242:        if (onoff)
        !          1243:                sc->sc_chanctl_rs_control |= sc->sc_rs_control_dtr;
        !          1244:        else
        !          1245:                sc->sc_chanctl_rs_control &= ~sc->sc_rs_control_dtr;
        !          1246:        CZTTY_CHAN_WRITE(sc, CHNCTL_RS_CONTROL, sc->sc_chanctl_rs_control);
        !          1247:
        !          1248:        CZ_FWCTL_WRITE(cz, BRDCTL_HCMD_CHANNEL, sc->sc_channel);
        !          1249:        CZ_PLX_WRITE(cz, PLX_PCI_LOCAL_DOORBELL, C_CM_IOCTLM);
        !          1250: }
        !          1251:
        !          1252: /*
        !          1253:  * tiocm_to_cztty:
        !          1254:  *
        !          1255:  *     Process TIOCM* ioctls.
        !          1256:  */
        !          1257: void
        !          1258: tiocm_to_cztty(struct cztty_softc *sc, u_long how, int ttybits)
        !          1259: {
        !          1260:        struct cz_softc *cz = CZTTY_CZ(sc);
        !          1261:        u_int32_t czttybits;
        !          1262:
        !          1263:        czttybits = 0;
        !          1264:        if (ISSET(ttybits, TIOCM_DTR))
        !          1265:                SET(czttybits, C_RS_DTR);
        !          1266:        if (ISSET(ttybits, TIOCM_RTS))
        !          1267:                SET(czttybits, C_RS_RTS);
        !          1268:
        !          1269:        cz_wait_pci_doorbell(cz, "cztiocm");
        !          1270:
        !          1271:        switch (how) {
        !          1272:        case TIOCMBIC:
        !          1273:                CLR(sc->sc_chanctl_rs_control, czttybits);
        !          1274:                break;
        !          1275:
        !          1276:        case TIOCMBIS:
        !          1277:                SET(sc->sc_chanctl_rs_control, czttybits);
        !          1278:                break;
        !          1279:
        !          1280:        case TIOCMSET:
        !          1281:                CLR(sc->sc_chanctl_rs_control, C_RS_DTR | C_RS_RTS);
        !          1282:                SET(sc->sc_chanctl_rs_control, czttybits);
        !          1283:                break;
        !          1284:        }
        !          1285:
        !          1286:        CZTTY_CHAN_WRITE(sc, CHNCTL_RS_CONTROL, sc->sc_chanctl_rs_control);
        !          1287:
        !          1288:        CZ_FWCTL_WRITE(cz, BRDCTL_HCMD_CHANNEL, sc->sc_channel);
        !          1289:        CZ_PLX_WRITE(cz, PLX_PCI_LOCAL_DOORBELL, C_CM_IOCTLM);
        !          1290: }
        !          1291:
        !          1292: /*
        !          1293:  * cztty_to_tiocm:
        !          1294:  *
        !          1295:  *     Process the TIOCMGET ioctl.
        !          1296:  */
        !          1297: int
        !          1298: cztty_to_tiocm(struct cztty_softc *sc)
        !          1299: {
        !          1300:        struct cz_softc *cz = CZTTY_CZ(sc);
        !          1301:        u_int32_t rs_status, op_mode;
        !          1302:        int ttybits = 0;
        !          1303:
        !          1304:        cz_wait_pci_doorbell(cz, "cztty");
        !          1305:
        !          1306:        rs_status = CZTTY_CHAN_READ(sc, CHNCTL_RS_STATUS);
        !          1307:        op_mode = CZTTY_CHAN_READ(sc, CHNCTL_OP_MODE);
        !          1308:
        !          1309:        if (ISSET(rs_status, C_RS_RTS))
        !          1310:                SET(ttybits, TIOCM_RTS);
        !          1311:        if (ISSET(rs_status, C_RS_CTS))
        !          1312:                SET(ttybits, TIOCM_CTS);
        !          1313:        if (ISSET(rs_status, C_RS_DCD))
        !          1314:                SET(ttybits, TIOCM_CAR);
        !          1315:        if (ISSET(rs_status, C_RS_DTR))
        !          1316:                SET(ttybits, TIOCM_DTR);
        !          1317:        if (ISSET(rs_status, C_RS_RI))
        !          1318:                SET(ttybits, TIOCM_RNG);
        !          1319:        if (ISSET(rs_status, C_RS_DSR))
        !          1320:                SET(ttybits, TIOCM_DSR);
        !          1321:
        !          1322:        if (ISSET(op_mode, C_CH_ENABLE))
        !          1323:                SET(ttybits, TIOCM_LE);
        !          1324:
        !          1325:        return (ttybits);
        !          1326: }
        !          1327:
        !          1328: /*
        !          1329:  * czttyparam:
        !          1330:  *
        !          1331:  *     Set Cyclades-Z serial port parameters from termios.
        !          1332:  *
        !          1333:  *     XXX Should just copy the whole termios after making
        !          1334:  *     XXX sure all the changes could be done.
        !          1335:  */
        !          1336: int
        !          1337: czttyparam(struct tty *tp, struct termios *t)
        !          1338: {
        !          1339:        struct cztty_softc *sc = CZTTY_SOFTC(tp->t_dev);
        !          1340:        struct cz_softc *cz = CZTTY_CZ(sc);
        !          1341:        u_int32_t rs_status;
        !          1342:        int ospeed, cflag;
        !          1343:
        !          1344:        ospeed = t->c_ospeed;
        !          1345:        cflag = t->c_cflag;
        !          1346:
        !          1347:        /* Check requested parameters. */
        !          1348:        if (ospeed < 0)
        !          1349:                return (EINVAL);
        !          1350:        if (t->c_ispeed && t->c_ispeed != ospeed)
        !          1351:                return (EINVAL);
        !          1352:
        !          1353:        if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
        !          1354:                SET(cflag, CLOCAL);
        !          1355:                CLR(cflag, HUPCL);
        !          1356:        }
        !          1357:
        !          1358:        /*
        !          1359:         * If there were no changes, don't do anything.  This avoids dropping
        !          1360:         * input and improves performance when all we did was frob things like
        !          1361:         * VMIN and VTIME.
        !          1362:         */
        !          1363:        if (tp->t_ospeed == ospeed &&
        !          1364:            tp->t_cflag == cflag)
        !          1365:                return (0);
        !          1366:
        !          1367:        /* Data bits. */
        !          1368:        sc->sc_chanctl_comm_data_l = 0;
        !          1369:        switch (t->c_cflag & CSIZE) {
        !          1370:        case CS5:
        !          1371:                sc->sc_chanctl_comm_data_l |= C_DL_CS5;
        !          1372:                break;
        !          1373:
        !          1374:        case CS6:
        !          1375:                sc->sc_chanctl_comm_data_l |= C_DL_CS6;
        !          1376:                break;
        !          1377:
        !          1378:        case CS7:
        !          1379:                sc->sc_chanctl_comm_data_l |= C_DL_CS7;
        !          1380:                break;
        !          1381:
        !          1382:        case CS8:
        !          1383:                sc->sc_chanctl_comm_data_l |= C_DL_CS8;
        !          1384:                break;
        !          1385:        }
        !          1386:
        !          1387:        /* Stop bits. */
        !          1388:        if (t->c_cflag & CSTOPB) {
        !          1389:                if ((sc->sc_chanctl_comm_data_l & C_DL_CS) == C_DL_CS5)
        !          1390:                        sc->sc_chanctl_comm_data_l |= C_DL_15STOP;
        !          1391:                else
        !          1392:                        sc->sc_chanctl_comm_data_l |= C_DL_2STOP;
        !          1393:        } else
        !          1394:                sc->sc_chanctl_comm_data_l |= C_DL_1STOP;
        !          1395:
        !          1396:        /* Parity. */
        !          1397:        if (t->c_cflag & PARENB) {
        !          1398:                if (t->c_cflag & PARODD)
        !          1399:                        sc->sc_chanctl_comm_parity = C_PR_ODD;
        !          1400:                else
        !          1401:                        sc->sc_chanctl_comm_parity = C_PR_EVEN;
        !          1402:        } else
        !          1403:                sc->sc_chanctl_comm_parity = C_PR_NONE;
        !          1404:
        !          1405:        /*
        !          1406:         * Initialize flow control pins depending on the current flow control
        !          1407:         * mode.
        !          1408:         */
        !          1409:        if (ISSET(t->c_cflag, CRTSCTS)) {
        !          1410:                sc->sc_rs_control_dtr = C_RS_DTR;
        !          1411:                sc->sc_chanctl_hw_flow = C_RS_CTS | C_RS_RTS;
        !          1412:        } else if (ISSET(t->c_cflag, MDMBUF)) {
        !          1413:                sc->sc_rs_control_dtr = 0;
        !          1414:                sc->sc_chanctl_hw_flow = C_RS_DCD | C_RS_DTR;
        !          1415:        } else {
        !          1416:                /*
        !          1417:                 * If no flow control, then always set RTS.  This will make
        !          1418:                 * the other side happy if it mistakenly thinks we're doing
        !          1419:                 * RTS/CTS flow control.
        !          1420:                 */
        !          1421:                sc->sc_rs_control_dtr = C_RS_DTR | C_RS_RTS;
        !          1422:                sc->sc_chanctl_hw_flow = 0;
        !          1423:                if (ISSET(sc->sc_chanctl_rs_control, C_RS_DTR))
        !          1424:                        SET(sc->sc_chanctl_rs_control, C_RS_RTS);
        !          1425:                else
        !          1426:                        CLR(sc->sc_chanctl_rs_control, C_RS_RTS);
        !          1427:        }
        !          1428:
        !          1429:        /* Baud rate. */
        !          1430:        sc->sc_chanctl_comm_baud = ospeed;
        !          1431:
        !          1432:        /* Copy to tty. */
        !          1433:        tp->t_ispeed =  0;
        !          1434:        tp->t_ospeed = t->c_ospeed;
        !          1435:        tp->t_cflag = t->c_cflag;
        !          1436:
        !          1437:        /*
        !          1438:         * Now load the channel control structure.
        !          1439:         */
        !          1440:
        !          1441:        cz_wait_pci_doorbell(cz, "czparam");
        !          1442:
        !          1443:        CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_BAUD, sc->sc_chanctl_comm_baud);
        !          1444:        CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_DATA_L, sc->sc_chanctl_comm_data_l);
        !          1445:        CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_PARITY, sc->sc_chanctl_comm_parity);
        !          1446:        CZTTY_CHAN_WRITE(sc, CHNCTL_HW_FLOW, sc->sc_chanctl_hw_flow);
        !          1447:        CZTTY_CHAN_WRITE(sc, CHNCTL_RS_CONTROL, sc->sc_chanctl_rs_control);
        !          1448:
        !          1449:        CZ_FWCTL_WRITE(cz, BRDCTL_HCMD_CHANNEL, sc->sc_channel);
        !          1450:        CZ_PLX_WRITE(cz, PLX_PCI_LOCAL_DOORBELL, C_CM_IOCTLW);
        !          1451:
        !          1452:        cz_wait_pci_doorbell(cz, "czparam");
        !          1453:
        !          1454:        CZ_FWCTL_WRITE(cz, BRDCTL_HCMD_CHANNEL, sc->sc_channel);
        !          1455:        CZ_PLX_WRITE(cz, PLX_PCI_LOCAL_DOORBELL, C_CM_IOCTLM);
        !          1456:
        !          1457:        cz_wait_pci_doorbell(cz, "czparam");
        !          1458:
        !          1459:        /*
        !          1460:         * Update the tty layer's idea of the carrier bit, in case we changed
        !          1461:         * CLOCAL.  We don't hang up here; we only do that by explicit
        !          1462:         * request.
        !          1463:         */
        !          1464:        rs_status = CZTTY_CHAN_READ(sc, CHNCTL_RS_STATUS);
        !          1465:        (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(rs_status, C_RS_DCD));
        !          1466:
        !          1467:        return (0);
        !          1468: }
        !          1469:
        !          1470: /*
        !          1471:  * czttystart:
        !          1472:  *
        !          1473:  *     Start or restart transmission.
        !          1474:  */
        !          1475: void
        !          1476: czttystart(struct tty *tp)
        !          1477: {
        !          1478:        struct cztty_softc *sc = CZTTY_SOFTC(tp->t_dev);
        !          1479:        int s;
        !          1480:
        !          1481:        s = spltty();
        !          1482:        if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
        !          1483:                goto out;
        !          1484:
        !          1485:        if (tp->t_outq.c_cc <= tp->t_lowat) {
        !          1486:                if (ISSET(tp->t_state, TS_ASLEEP)) {
        !          1487:                        CLR(tp->t_state, TS_ASLEEP);
        !          1488:                        wakeup(&tp->t_outq);
        !          1489:                }
        !          1490:                selwakeup(&tp->t_wsel);
        !          1491:                if (tp->t_outq.c_cc == 0)
        !          1492:                        goto out;
        !          1493:        }
        !          1494:
        !          1495:        cztty_transmit(sc, tp);
        !          1496:  out:
        !          1497:        splx(s);
        !          1498: }
        !          1499:
        !          1500: /*
        !          1501:  * czttystop:
        !          1502:  *
        !          1503:  *     Stop output, e.g., for ^S or output flush.
        !          1504:  */
        !          1505: int
        !          1506: czttystop(struct tty *tp, int flag)
        !          1507: {
        !          1508:
        !          1509:        /*
        !          1510:         * XXX We don't do anything here, yet.  Mostly, I don't know
        !          1511:         * XXX exactly how this should be implemented on this device.
        !          1512:         * XXX We've given a big chunk of data to the MIPS already,
        !          1513:         * XXX and I don't know how we request the MIPS to stop sending
        !          1514:         * XXX the data.  So, punt for now.  --thorpej
        !          1515:         */
        !          1516:        return (0);
        !          1517: }
        !          1518:
        !          1519: /*
        !          1520:  * cztty_diag:
        !          1521:  *
        !          1522:  *     Issue a scheduled diagnostic message.
        !          1523:  */
        !          1524: void
        !          1525: cztty_diag(void *arg)
        !          1526: {
        !          1527:        struct cztty_softc *sc = arg;
        !          1528:        struct cz_softc *cz = CZTTY_CZ(sc);
        !          1529:        u_int overflows, parity_errors, framing_errors;
        !          1530:        int s;
        !          1531:
        !          1532:        s = spltty();
        !          1533:
        !          1534:        overflows = sc->sc_overflows;
        !          1535:        sc->sc_overflows = 0;
        !          1536:
        !          1537:        parity_errors = sc->sc_parity_errors;
        !          1538:        sc->sc_parity_errors = 0;
        !          1539:
        !          1540:        framing_errors = sc->sc_framing_errors;
        !          1541:        sc->sc_framing_errors = 0;
        !          1542:
        !          1543:        sc->sc_errors = 0;
        !          1544:
        !          1545:        splx(s);
        !          1546:
        !          1547:        log(LOG_WARNING,
        !          1548:            "%s: channel %d: %u overflow%s, %u parity, %u framing error%s\n",
        !          1549:            cz->cz_dev.dv_xname, sc->sc_channel,
        !          1550:            overflows, overflows == 1 ? "" : "s",
        !          1551:            parity_errors,
        !          1552:            framing_errors, framing_errors == 1 ? "" : "s");
        !          1553: }
        !          1554:
        !          1555: /*
        !          1556:  * tx and rx ring buffer size macros:
        !          1557:  *
        !          1558:  * The transmitter and receiver both use ring buffers. For each one, there
        !          1559:  * is a get (consumer) and a put (producer) offset. The get value is the
        !          1560:  * next byte to be read from the ring, and the put is the next one to be
        !          1561:  * put into the ring.  get == put means the ring is empty.
        !          1562:  *
        !          1563:  * For each ring, the firmware controls one of (get, put) and this driver
        !          1564:  * controls the other. For transmission, this driver updates put to point
        !          1565:  * past the valid data, and the firmware moves get as bytes are sent. Likewise
        !          1566:  * for receive, the driver controls put, and this driver controls get.
        !          1567:  */
        !          1568: #define        TX_MOVEABLE(g, p, s)    (((g) > (p)) ? ((g) - (p) - 1) : ((s) - (p)))
        !          1569: #define RX_MOVEABLE(g, p, s)   (((g) > (p)) ? ((s) - (g)) : ((p) - (g)))
        !          1570:
        !          1571: /*
        !          1572:  * cztty_transmit()
        !          1573:  *
        !          1574:  * Look at the tty for this port and start sending.
        !          1575:  */
        !          1576: int
        !          1577: cztty_transmit(struct cztty_softc *sc, struct tty *tp)
        !          1578: {
        !          1579:        struct cz_softc *cz = CZTTY_CZ(sc);
        !          1580:        u_int move, get, put, size, address;
        !          1581: #ifdef HOSTRAMCODE
        !          1582:        int error, done = 0;
        !          1583: #else
        !          1584:        int done = 0;
        !          1585: #endif
        !          1586:
        !          1587:        size    = CZTTY_BUF_READ(sc, BUFCTL_TX_BUFSIZE);
        !          1588:        get     = CZTTY_BUF_READ(sc, BUFCTL_TX_GET);
        !          1589:        put     = CZTTY_BUF_READ(sc, BUFCTL_TX_PUT);
        !          1590:        address = CZTTY_BUF_READ(sc, BUFCTL_TX_BUFADDR);
        !          1591:
        !          1592:        while ((tp->t_outq.c_cc > 0) && ((move = TX_MOVEABLE(get, put, size)))){
        !          1593: #ifdef HOSTRAMCODE
        !          1594:                if (0) {
        !          1595:                        move = min(tp->t_outq.c_cc, move);
        !          1596:                        error = q_to_b(&tp->t_outq, 0, move);
        !          1597:                        if (error != move) {
        !          1598:                                printf("%s: channel %d: error moving to "
        !          1599:                                    "transmit buf\n", cz->cz_dev.dv_xname,
        !          1600:                                    sc->sc_channel);
        !          1601:                                move = error;
        !          1602:                        }
        !          1603:                } else {
        !          1604: #endif
        !          1605:                        move = min(ndqb(&tp->t_outq, 0), move);
        !          1606:                        bus_space_write_region_1(cz->cz_win_st, cz->cz_win_sh,
        !          1607:                            address + put, tp->t_outq.c_cf, move);
        !          1608:                        ndflush(&tp->t_outq, move);
        !          1609: #ifdef HOSTRAMCODE
        !          1610:                }
        !          1611: #endif
        !          1612:
        !          1613:                put = ((put + move) % size);
        !          1614:                done = 1;
        !          1615:        }
        !          1616:        if (done) {
        !          1617:                CZTTY_BUF_WRITE(sc, BUFCTL_TX_PUT, put);
        !          1618:        }
        !          1619:        return (done);
        !          1620: }
        !          1621:
        !          1622: int
        !          1623: cztty_receive(struct cztty_softc *sc, struct tty *tp)
        !          1624: {
        !          1625:        struct cz_softc *cz = CZTTY_CZ(sc);
        !          1626:        u_int get, put, size, address;
        !          1627:        int done = 0, ch;
        !          1628:
        !          1629:        size    = CZTTY_BUF_READ(sc, BUFCTL_RX_BUFSIZE);
        !          1630:        get     = CZTTY_BUF_READ(sc, BUFCTL_RX_GET);
        !          1631:        put     = CZTTY_BUF_READ(sc, BUFCTL_RX_PUT);
        !          1632:        address = CZTTY_BUF_READ(sc, BUFCTL_RX_BUFADDR);
        !          1633:
        !          1634:        while ((get != put) && ((tp->t_canq.c_cc + tp->t_rawq.c_cc) < tp->t_hiwat)) {
        !          1635: #ifdef HOSTRAMCODE
        !          1636:                if (hostram)
        !          1637:                        ch = ((char *)fifoaddr)[get];
        !          1638:                } else {
        !          1639: #endif
        !          1640:                        ch = bus_space_read_1(cz->cz_win_st, cz->cz_win_sh,
        !          1641:                            address + get);
        !          1642: #ifdef HOSTRAMCODE
        !          1643:                }
        !          1644: #endif
        !          1645:                (*linesw[tp->t_line].l_rint)(ch, tp);
        !          1646:                get = (get + 1) % size;
        !          1647:                done = 1;
        !          1648:        }
        !          1649:        if (done) {
        !          1650:                CZTTY_BUF_WRITE(sc, BUFCTL_RX_GET, get);
        !          1651:        }
        !          1652:        return (done);
        !          1653: }

CVSweb