The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sbus/magma.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: magma.c,v 1.28 2004/03/17 17:04:58 pk Exp $    */
    2 /*
    3  * magma.c
    4  *
    5  * Copyright (c) 1998 Iain Hibbert
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by Iain Hibbert
   19  * 4. The name of the author may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  *
   33  */
   34 
   35 /*
   36  * Driver for Magma SBus Serial/Parallel cards using the Cirrus Logic
   37  * CD1400 & CD1190 chips
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __KERNEL_RCSID(0, "$NetBSD: magma.c,v 1.28 2004/03/17 17:04:58 pk Exp $");
   42 
   43 #if 0
   44 #define MAGMA_DEBUG
   45 #endif
   46 
   47 #include "magma.h"
   48 #if NMAGMA > 0
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/proc.h>
   53 #include <sys/device.h>
   54 #include <sys/file.h>
   55 #include <sys/ioctl.h>
   56 #include <sys/malloc.h>
   57 #include <sys/tty.h>
   58 #include <sys/time.h>
   59 #include <sys/kernel.h>
   60 #include <sys/syslog.h>
   61 #include <sys/conf.h>
   62 #include <sys/errno.h>
   63 
   64 #include <machine/bus.h>
   65 #include <machine/intr.h>
   66 #include <machine/autoconf.h>
   67 
   68 #include <dev/sbus/sbusvar.h>
   69 
   70 #include <dev/ic/cd1400reg.h>
   71 #include <dev/ic/cd1190reg.h>
   72 
   73 #include <dev/sbus/mbppio.h>
   74 #include <dev/sbus/magmareg.h>
   75 
   76 /* supported cards
   77  *
   78  *  The table below lists the cards that this driver is likely to
   79  *  be able to support.
   80  *
   81  *  Cards with parallel ports: except for the LC2+1Sp, they all use
   82  *  the CD1190 chip which I know nothing about.  I've tried to leave
   83  *  hooks for it so it shouldn't be too hard to add support later.
   84  *  (I think somebody is working on this separately)
   85  *
   86  *  Thanks to Bruce at Magma for telling me the hardware offsets.
   87  */
   88 static struct magma_board_info supported_cards[] = {
   89         {
   90                 "MAGMA_Sp", "MAGMA,4_Sp", "Magma 4 Sp", 4, 0,
   91                 1, 0xa000, 0xc000, 0xe000, { 0x8000, 0, 0, 0 },
   92                 0, { 0, 0 }
   93         },
   94         {
   95                 "MAGMA_Sp", "MAGMA,8_Sp", "Magma 8 Sp", 8, 0,
   96                 2, 0xa000, 0xc000, 0xe000, { 0x4000, 0x6000, 0, 0 },
   97                 0, { 0, 0 }
   98         },
   99         {
  100                 "MAGMA_Sp", "MAGMA,_8HS_Sp", "Magma Fast 8 Sp", 8, 0,
  101                 2, 0x2000, 0x4000, 0x6000, { 0x8000, 0xa000, 0, 0 },
  102                 0, { 0, 0 }
  103         },
  104         {
  105                 "MAGMA_Sp", "MAGMA,_8SP_422", "Magma 8 Sp - 422", 8, 0,
  106                 2, 0x2000, 0x4000, 0x6000, { 0x8000, 0xa000, 0, 0 },
  107                 0, { 0, 0 }
  108         },
  109         {
  110                 "MAGMA_Sp", "MAGMA,12_Sp", "Magma 12 Sp", 12, 0,
  111                 3, 0xa000, 0xc000, 0xe000, { 0x2000, 0x4000, 0x6000, 0 },
  112                 0, { 0, 0 }
  113         },
  114         {
  115                 "MAGMA_Sp", "MAGMA,16_Sp", "Magma 16 Sp", 16, 0,
  116                 4, 0xd000, 0xe000, 0xf000, { 0x8000, 0x9000, 0xa000, 0xb000 },
  117                 0, { 0, 0 }
  118         },
  119         {
  120                 "MAGMA_Sp", "MAGMA,16_Sp_2", "Magma 16 Sp", 16, 0,
  121                 4, 0x2000, 0x4000, 0x6000, { 0x8000, 0xa000, 0xc000, 0xe000 },
  122                 0, { 0, 0 }
  123         },
  124         {
  125                 "MAGMA_Sp", "MAGMA,16HS_Sp", "Magma Fast 16 Sp", 16, 0,
  126                 4, 0x2000, 0x4000, 0x6000, { 0x8000, 0xa000, 0xc000, 0xe000 },
  127                 0, { 0, 0 }
  128         },
  129         {
  130                 "MAGMA_Sp", "MAGMA,21_Sp", "Magma LC 2+1 Sp", 2, 1,
  131                 1, 0xa000, 0xc000, 0xe000, { 0x8000, 0, 0, 0 },
  132                 0, { 0, 0 }
  133         },
  134         {
  135                 "MAGMA_Sp", "MAGMA,21HS_Sp", "Magma 2+1 Sp", 2, 1,
  136                 1, 0xa000, 0xc000, 0xe000, { 0x4000, 0, 0, 0 },
  137                 1, { 0x6000, 0 }
  138         },
  139         {
  140                 "MAGMA_Sp", "MAGMA,41_Sp", "Magma 4+1 Sp", 4, 1,
  141                 1, 0xa000, 0xc000, 0xe000, { 0x4000, 0, 0, 0 },
  142                 1, { 0x6000, 0 }
  143         },
  144         {
  145                 "MAGMA_Sp", "MAGMA,82_Sp", "Magma 8+2 Sp", 8, 2,
  146                 2, 0xd000, 0xe000, 0xf000, { 0x8000, 0x9000, 0, 0 },
  147                 2, { 0xa000, 0xb000 }
  148         },
  149         {
  150                 "MAGMA_Sp", "MAGMA,P1_Sp", "Magma P1 Sp", 0, 1,
  151                 0, 0, 0, 0, { 0, 0, 0, 0 },
  152                 1, { 0x8000, 0 }
  153         },
  154         {
  155                 "MAGMA_Sp", "MAGMA,P2_Sp", "Magma P2 Sp", 0, 2,
  156                 0, 0, 0, 0, { 0, 0, 0, 0 },
  157                 2, { 0x4000, 0x8000 }
  158         },
  159         {
  160                 "MAGMA 2+1HS Sp", "", "Magma 2+1HS Sp", 2, 0,
  161                 1, 0xa000, 0xc000, 0xe000, { 0x4000, 0, 0, 0 },
  162                 1, { 0x8000, 0 }
  163         },
  164         {
  165                 NULL, NULL, NULL, 0, 0,
  166                 0, 0, 0, 0, { 0, 0, 0, 0 },
  167                 0, { 0, 0 }
  168         }
  169 };
  170 
  171 /************************************************************************
  172  *
  173  *  Autoconfig Stuff
  174  */
  175 
  176 CFATTACH_DECL(magma, sizeof(struct magma_softc),
  177     magma_match, magma_attach, NULL, NULL);
  178 
  179 CFATTACH_DECL(mtty, sizeof(struct mtty_softc),
  180     mtty_match, mtty_attach, NULL, NULL);
  181 
  182 CFATTACH_DECL(mbpp, sizeof(struct mbpp_softc),
  183     mbpp_match, mbpp_attach, NULL, NULL);
  184 
  185 extern struct cfdriver mtty_cd;
  186 extern struct cfdriver mbpp_cd;
  187 
  188 dev_type_open(mttyopen);
  189 dev_type_close(mttyclose);
  190 dev_type_read(mttyread);
  191 dev_type_write(mttywrite);
  192 dev_type_ioctl(mttyioctl);
  193 dev_type_stop(mttystop);
  194 dev_type_tty(mttytty);
  195 dev_type_poll(mttypoll);
  196 
  197 const struct cdevsw mtty_cdevsw = {
  198         mttyopen, mttyclose, mttyread, mttywrite, mttyioctl,
  199         mttystop, mttytty, mttypoll, nommap, ttykqfilter, D_TTY
  200 };
  201 
  202 dev_type_open(mbppopen);
  203 dev_type_close(mbppclose);
  204 dev_type_read(mbpp_rw);
  205 dev_type_ioctl(mbppioctl);
  206 
  207 const struct cdevsw mbpp_cdevsw = {
  208         mbppopen, mbppclose, mbpp_rw, mbpp_rw, mbppioctl,
  209         nostop, notty, nopoll, nommap, nokqfilter,
  210 };
  211 
  212 /************************************************************************
  213  *
  214  *  CD1400 Routines
  215  *
  216  *      cd1400_compute_baud             calculate COR/BPR register values
  217  *      cd1400_write_ccr                write a value to CD1400 ccr
  218  *      cd1400_read_reg                 read from a CD1400 register
  219  *      cd1400_write_reg                write to a CD1400 register
  220  *      cd1400_enable_transmitter       enable transmitting on CD1400 channel
  221  */
  222 
  223 /*
  224  * compute the bpr/cor pair for any baud rate
  225  * returns 0 for success, 1 for failure
  226  */
  227 int
  228 cd1400_compute_baud(speed, clock, cor, bpr)
  229         speed_t speed;
  230         int clock;
  231         int *cor, *bpr;
  232 {
  233         int c, co, br;
  234 
  235         if( speed < 50 || speed > 150000 )
  236                 return(1);
  237 
  238         for( c = 0, co = 8 ; co <= 2048 ; co <<= 2, c++ ) {
  239                 br = ((clock * 1000000) + (co * speed) / 2) / (co * speed);
  240                 if( br < 0x100 ) {
  241                         *bpr = br;
  242                         *cor = c;
  243                         return(0);
  244                 }
  245         }
  246 
  247         return(1);
  248 }
  249 
  250 /*
  251  * Write a CD1400 channel command, should have a timeout?
  252  */
  253 __inline void
  254 cd1400_write_ccr(cd, cmd)
  255         struct cd1400 *cd;
  256         u_char cmd;
  257 {
  258         while( cd1400_read_reg(cd, CD1400_CCR) )
  259                 ;
  260 
  261         cd1400_write_reg(cd, CD1400_CCR, cmd);
  262 }
  263 
  264 /*
  265  * read a value from a cd1400 register
  266  */
  267 __inline u_char
  268 cd1400_read_reg(cd, reg)
  269         struct cd1400 *cd;
  270         int reg;
  271 {
  272         return(cd->cd_reg[reg]);
  273 }
  274 
  275 /*
  276  * write a value to a cd1400 register
  277  */
  278 __inline void
  279 cd1400_write_reg(cd, reg, value)
  280         struct cd1400 *cd;
  281         int reg;
  282         u_char value;
  283 {
  284         cd->cd_reg[reg] = value;
  285 }
  286 
  287 /*
  288  * enable transmit service requests for cd1400 channel
  289  */
  290 void
  291 cd1400_enable_transmitter(cd, channel)
  292         struct cd1400 *cd;
  293         int channel;
  294 {
  295         int s, srer;
  296 
  297         s = spltty();
  298         cd1400_write_reg(cd, CD1400_CAR, channel);
  299         srer = cd1400_read_reg(cd, CD1400_SRER);
  300         SET(srer, CD1400_SRER_TXRDY);
  301         cd1400_write_reg(cd, CD1400_SRER, srer);
  302         splx(s);
  303 }
  304 
  305 /************************************************************************
  306  *
  307  *  CD1190 Routines
  308  */
  309 
  310 /* well, there are none yet */
  311 
  312 /************************************************************************
  313  *
  314  *  Magma Routines
  315  *
  316  * magma_match          reports if we have a magma board available
  317  * magma_attach         attaches magma boards to the sbus
  318  * magma_hard           hardware level interrupt routine
  319  * magma_soft           software level interrupt routine
  320  */
  321 
  322 int
  323 magma_match(parent, cf, aux)
  324         struct device *parent;
  325         struct cfdata *cf;
  326         void *aux;
  327 {
  328         struct sbus_attach_args *sa = aux;
  329         struct magma_board_info *card;
  330 
  331         /* See if we support this device */
  332         for (card = supported_cards; ; card++) {
  333                 if (card->mb_sbusname == NULL)
  334                         /* End of table: no match */
  335                         return (0);
  336                 if (strcmp(sa->sa_name, card->mb_sbusname) == 0)
  337                         break;
  338         }
  339 
  340         dprintf(("magma: matched `%s'\n", sa->sa_name));
  341         dprintf(("magma: magma_prom `%s'\n",
  342                 prom_getpropstring(sa->sa_node, "magma_prom")));
  343         dprintf(("magma: intlevels `%s'\n",
  344                 prom_getpropstring(sa->sa_node, "intlevels")));
  345         dprintf(("magma: chiprev `%s'\n",
  346                 prom_getpropstring(sa->sa_node, "chiprev")));
  347         dprintf(("magma: clock `%s'\n",
  348                 prom_getpropstring(sa->sa_node, "clock")));
  349 
  350         return (1);
  351 }
  352 
  353 void
  354 magma_attach(parent, self, aux)
  355         struct device *parent;
  356         struct device *self;
  357         void *aux;
  358 {
  359         struct sbus_attach_args *sa = aux;
  360         struct magma_softc *sc = (struct magma_softc *)self;
  361         struct magma_board_info *card;
  362         bus_space_handle_t bh;
  363         char *magma_prom, *clockstr;
  364         int cd_clock;
  365         int node, chip;
  366 
  367         node = sa->sa_node;
  368 
  369         /*
  370          * Find the card model.
  371          * Older models all have sbus node name `MAGMA_Sp' (see
  372          * `supported_cards[]' above), and must be distinguished
  373          * by the `magma_prom' property.
  374          */
  375         magma_prom = prom_getpropstring(node, "magma_prom");
  376 
  377         for (card = supported_cards; card->mb_name != NULL; card++) {
  378                 if (strcmp(sa->sa_name, card->mb_sbusname) != 0)
  379                         /* Sbus node name doesn't match */
  380                         continue;
  381                 if (strcmp(magma_prom, card->mb_name) == 0)
  382                         /* Model name match */
  383                         break;
  384         }
  385 
  386         if( card->mb_name == NULL ) {
  387                 printf(": %s (unsupported)\n", magma_prom);
  388                 return;
  389         }
  390 
  391         dprintf((" addr %p", sc));
  392         printf(": %s\n", card->mb_realname);
  393 
  394         sc->ms_board = card;
  395         sc->ms_ncd1400 = card->mb_ncd1400;
  396         sc->ms_ncd1190 = card->mb_ncd1190;
  397 
  398         if (sbus_bus_map(sa->sa_bustag,
  399                          sa->sa_slot, sa->sa_offset, sa->sa_size,
  400                          BUS_SPACE_MAP_LINEAR, &bh) != 0) {
  401                 printf("%s @ sbus: cannot map registers\n", self->dv_xname);
  402                 return;
  403         }
  404 
  405         /* the SVCACK* lines are daisychained */
  406         sc->ms_svcackr = (caddr_t)bus_space_vaddr(sa->sa_bustag, bh)
  407                 + card->mb_svcackr;
  408         sc->ms_svcackt = (caddr_t)bus_space_vaddr(sa->sa_bustag, bh)
  409                 + card->mb_svcackt;
  410         sc->ms_svcackm = (caddr_t)bus_space_vaddr(sa->sa_bustag, bh)
  411                 + card->mb_svcackm;
  412 
  413         /*
  414          * Find the clock speed; it's the same for all CD1400 chips
  415          * on the board.
  416          */
  417         clockstr = prom_getpropstring(node, "clock");
  418         if (*clockstr == '\0')
  419                 /* Default to 25MHz */
  420                 cd_clock = 25;
  421         else {
  422                 cd_clock = 0;
  423                 while (*clockstr != '\0')
  424                         cd_clock = (cd_clock * 10) + (*clockstr++ - '');
  425         }
  426 
  427         /* init the cd1400 chips */
  428         for( chip = 0 ; chip < card->mb_ncd1400 ; chip++ ) {
  429                 struct cd1400 *cd = &sc->ms_cd1400[chip];
  430 
  431                 cd->cd_clock = cd_clock;
  432                 cd->cd_reg = (caddr_t)bh + card->mb_cd1400[chip];
  433 
  434                 /* prom_getpropstring(node, "chiprev"); */
  435                 /* seemingly the Magma drivers just ignore the propstring */
  436                 cd->cd_chiprev = cd1400_read_reg(cd, CD1400_GFRCR);
  437 
  438                 dprintf(("%s attach CD1400 %d addr %p rev %x clock %dMHz\n",
  439                         sc->ms_dev.dv_xname, chip,
  440                         cd->cd_reg, cd->cd_chiprev, cd->cd_clock));
  441 
  442                 /* clear GFRCR */
  443                 cd1400_write_reg(cd, CD1400_GFRCR, 0x00);
  444 
  445                 /* reset whole chip */
  446                 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
  447 
  448                 /* wait for revision code to be restored */
  449                 while( cd1400_read_reg(cd, CD1400_GFRCR) != cd->cd_chiprev )
  450                         ;
  451 
  452                 /* set the Prescaler Period Register to tick at 1ms */
  453                 cd1400_write_reg(cd, CD1400_PPR,
  454                         ((cd->cd_clock * 1000000 / CD1400_PPR_PRESCALER + 500) / 1000));
  455 
  456                 /* The LC2+1Sp card is the only card that doesn't have
  457                  * a CD1190 for the parallel port, but uses channel 0 of
  458                  * the CD1400, so we make a note of it for later and set up
  459                  * the CD1400 for parallel mode operation.
  460                  */
  461                 if( card->mb_npar && card->mb_ncd1190 == 0 ) {
  462                         cd1400_write_reg(cd, CD1400_GCR, CD1400_GCR_PARALLEL);
  463                         cd->cd_parmode = 1;
  464                 }
  465         }
  466 
  467         /* init the cd1190 chips */
  468         for( chip = 0 ; chip < card->mb_ncd1190 ; chip++ ) {
  469                 struct cd1190 *cd = &sc->ms_cd1190[chip];
  470 
  471                 cd->cd_reg = (caddr_t)bh + card->mb_cd1190[chip];
  472 
  473                 /* XXX don't know anything about these chips yet */
  474                 printf("%s: CD1190 %d addr %p (unsupported)\n",
  475                         self->dv_xname, chip, cd->cd_reg);
  476         }
  477 
  478         sbus_establish(&sc->ms_sd, &sc->ms_dev);
  479 
  480         /* configure the children */
  481         (void)config_found(self, mtty_match, NULL);
  482         (void)config_found(self, mbpp_match, NULL);
  483 
  484         /*
  485          * Establish the interrupt handlers.
  486          */
  487         if (sa->sa_nintr == 0)
  488                 return;         /* No interrupts to service!? */
  489 
  490         (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_SERIAL,
  491                                  magma_hard, sc);
  492         sc->ms_sicookie = softintr_establish(IPL_SOFTSERIAL, magma_soft, sc);
  493         if (sc->ms_sicookie == NULL) {
  494                 printf("\n%s: cannot establish soft int handler\n",
  495                         sc->ms_dev.dv_xname);
  496                 return;
  497         }
  498         evcnt_attach_dynamic(&sc->ms_intrcnt, EVCNT_TYPE_INTR, NULL,
  499             sc->ms_dev.dv_xname, "intr");
  500 }
  501 
  502 /*
  503  * hard interrupt routine
  504  *
  505  *  returns 1 if it handled it, otherwise 0
  506  *
  507  *  runs at interrupt priority
  508  */
  509 int
  510 magma_hard(arg)
  511         void *arg;
  512 {
  513         struct magma_softc *sc = arg;
  514         struct cd1400 *cd;
  515         int chip, status = 0;
  516         int serviced = 0;
  517         int needsoftint = 0;
  518 
  519         /*
  520          * check status of all the CD1400 chips
  521          */
  522         for( chip = 0 ; chip < sc->ms_ncd1400 ; chip++ )
  523                 status |= cd1400_read_reg(&sc->ms_cd1400[chip], CD1400_SVRR);
  524 
  525         if( ISSET(status, CD1400_SVRR_RXRDY) ) {
  526                 u_char rivr = *sc->ms_svcackr;  /* enter rx service context */
  527                 int port = rivr >> 4;
  528 
  529                 if( rivr & (1<<3) ) {                   /* parallel port */
  530                         struct mbpp_port *mbpp;
  531                         int n_chars;
  532 
  533                         mbpp = &sc->ms_mbpp->ms_port[port];
  534                         cd = mbpp->mp_cd1400;
  535  
  536                         /* don't think we have to handle exceptions */
  537                         n_chars = cd1400_read_reg(cd, CD1400_RDCR);
  538                         while (n_chars--) {
  539                                 if( mbpp->mp_cnt == 0 ) {
  540                                         SET(mbpp->mp_flags, MBPPF_WAKEUP);
  541                                         needsoftint = 1;
  542                                         break;
  543                                 }
  544                                 *mbpp->mp_ptr = cd1400_read_reg(cd,CD1400_RDSR);
  545                                 mbpp->mp_ptr++;
  546                                 mbpp->mp_cnt--;
  547                         }
  548                 } else {                                /* serial port */
  549                         struct mtty_port *mtty;
  550                         u_char *ptr, n_chars, line_stat;
  551 
  552                         mtty = &sc->ms_mtty->ms_port[port];
  553                         cd = mtty->mp_cd1400;
  554 
  555                         if( ISSET(rivr, CD1400_RIVR_EXCEPTION) ) {
  556                                 line_stat = cd1400_read_reg(cd, CD1400_RDSR);
  557                                 n_chars = 1;
  558                         } else { /* no exception, received data OK */
  559                                 line_stat = 0;
  560                                 n_chars = cd1400_read_reg(cd, CD1400_RDCR);
  561                         }
  562 
  563                         ptr = mtty->mp_rput;
  564                         while( n_chars-- ) {
  565                                 *ptr++ = line_stat;
  566                                 *ptr++ = cd1400_read_reg(cd, CD1400_RDSR);
  567                                 if( ptr == mtty->mp_rend ) ptr = mtty->mp_rbuf;
  568                                 if( ptr == mtty->mp_rget ) {
  569                                         if( ptr == mtty->mp_rbuf )
  570                                                 ptr = mtty->mp_rend;
  571                                         ptr -= 2;
  572                                         SET(mtty->mp_flags, MTTYF_RING_OVERFLOW);
  573                                         break;
  574                                 }
  575                         }
  576                         mtty->mp_rput = ptr;
  577 
  578                         needsoftint = 1;
  579                 }
  580 
  581                 cd1400_write_reg(cd, CD1400_EOSRR, 0);  /* end service context */
  582                 serviced = 1;
  583         } /* if(rx_service...) */
  584 
  585         if( ISSET(status, CD1400_SVRR_MDMCH) ) {
  586                 u_char mivr = *sc->ms_svcackm;  /* enter mdm service context */
  587                 int port = mivr >> 4;
  588                 struct mtty_port *mtty;
  589                 int carrier;
  590                 u_char msvr;
  591 
  592                 /*
  593                  * Handle CD (LC2+1Sp = DSR) changes.
  594                  */
  595                 mtty = &sc->ms_mtty->ms_port[port];
  596                 cd = mtty->mp_cd1400;
  597                 msvr = cd1400_read_reg(cd, CD1400_MSVR2);
  598                 carrier = ISSET(msvr, cd->cd_parmode ? CD1400_MSVR2_DSR : CD1400_MSVR2_CD);
  599 
  600                 if( mtty->mp_carrier != carrier ) {
  601                         SET(mtty->mp_flags, MTTYF_CARRIER_CHANGED);
  602                         mtty->mp_carrier = carrier;
  603                         needsoftint = 1;
  604                 }
  605 
  606                 cd1400_write_reg(cd, CD1400_EOSRR, 0);  /* end service context */
  607                 serviced = 1;
  608         } /* if(mdm_service...) */
  609 
  610         if( ISSET(status, CD1400_SVRR_TXRDY) ) {
  611                 u_char tivr = *sc->ms_svcackt;  /* enter tx service context */
  612                 int port = tivr >> 4;
  613 
  614                 if( tivr & (1<<3) ) {   /* parallel port */
  615                         struct mbpp_port *mbpp;
  616 
  617                         mbpp = &sc->ms_mbpp->ms_port[port];
  618                         cd = mbpp->mp_cd1400;
  619 
  620                         if( mbpp->mp_cnt ) {
  621                                 int count = 0;
  622 
  623                                 /* fill the fifo */
  624                                 while (mbpp->mp_cnt &&
  625                                         count++ < CD1400_PAR_FIFO_SIZE) {
  626                                         cd1400_write_reg(cd, CD1400_TDR,
  627                                                          *mbpp->mp_ptr);
  628                                         mbpp->mp_ptr++;
  629                                         mbpp->mp_cnt--;
  630                                 }
  631                         } else {
  632                                 /*
  633                                  * fifo is empty and we got no more data
  634                                  * to send, so shut off interrupts and
  635                                  * signal for a wakeup, which can't be
  636                                  * done here in case we beat mbpp_send to
  637                                  * the tsleep call (we are running at >spltty)
  638                                  */
  639                                 cd1400_write_reg(cd, CD1400_SRER, 0);
  640                                 SET(mbpp->mp_flags, MBPPF_WAKEUP);
  641                                 needsoftint = 1;
  642                         }
  643                 } else {                /* serial port */
  644                         struct mtty_port *mtty;
  645                         struct tty *tp;
  646 
  647                         mtty = &sc->ms_mtty->ms_port[port];
  648                         cd = mtty->mp_cd1400;
  649                         tp = mtty->mp_tty;
  650 
  651                         if( !ISSET(mtty->mp_flags, MTTYF_STOP) ) {
  652                                 int count = 0;
  653 
  654                                 /* check if we should start/stop a break */
  655                                 if( ISSET(mtty->mp_flags, MTTYF_SET_BREAK) ) {
  656                                         cd1400_write_reg(cd, CD1400_TDR, 0);
  657                                         cd1400_write_reg(cd, CD1400_TDR, 0x81);
  658                                         /* should we delay too? */
  659                                         CLR(mtty->mp_flags, MTTYF_SET_BREAK);
  660                                         count += 2;
  661                                 }
  662 
  663                                 if( ISSET(mtty->mp_flags, MTTYF_CLR_BREAK) ) {
  664                                         cd1400_write_reg(cd, CD1400_TDR, 0);
  665                                         cd1400_write_reg(cd, CD1400_TDR, 0x83);
  666                                         CLR(mtty->mp_flags, MTTYF_CLR_BREAK);
  667                                         count += 2;
  668                                 }
  669 
  670                                 /* I don't quite fill the fifo in case the last one is a
  671                                  * NULL which I have to double up because its the escape
  672                                  * code for embedded transmit characters.
  673                                  */
  674                                 while( mtty->mp_txc > 0 && count < CD1400_TX_FIFO_SIZE - 1 ) {
  675                                         u_char ch;
  676 
  677                                         ch = *mtty->mp_txp;
  678 
  679                                         mtty->mp_txc--;
  680                                         mtty->mp_txp++;
  681 
  682                                         if( ch == 0 ) {
  683                                                 cd1400_write_reg(cd, CD1400_TDR, ch);
  684                                                 count++;
  685                                         }
  686 
  687                                         cd1400_write_reg(cd, CD1400_TDR, ch);
  688                                         count++;
  689                                 }
  690                         }
  691 
  692                         /* if we ran out of work or are requested to STOP then
  693                          * shut off the txrdy interrupts and signal DONE to flush
  694                          * out the chars we have sent.
  695                          */
  696                         if( mtty->mp_txc == 0 || ISSET(mtty->mp_flags, MTTYF_STOP) ) {
  697                                 register int srer;
  698 
  699                                 srer = cd1400_read_reg(cd, CD1400_SRER);
  700                                 CLR(srer, CD1400_SRER_TXRDY);
  701                                 cd1400_write_reg(cd, CD1400_SRER, srer);
  702                                 CLR(mtty->mp_flags, MTTYF_STOP);
  703 
  704                                 SET(mtty->mp_flags, MTTYF_DONE);
  705                                 needsoftint = 1;
  706                         }
  707                 }
  708 
  709                 cd1400_write_reg(cd, CD1400_EOSRR, 0);  /* end service context */
  710                 serviced = 1;
  711         } /* if(tx_service...) */
  712 
  713         /* XXX service CD1190 interrupts too
  714         for( chip = 0 ; chip < sc->ms_ncd1190 ; chip++ ) {
  715         }
  716         */
  717 
  718         if (needsoftint)
  719                 /* trigger the soft interrupt */
  720                 softintr_schedule(sc->ms_sicookie);
  721 
  722         return(serviced);
  723 }
  724 
  725 /*
  726  * magma soft interrupt handler
  727  *
  728  *  returns 1 if it handled it, 0 otherwise
  729  *
  730  *  runs at spltty()
  731  */
  732 void
  733 magma_soft(arg)
  734         void *arg;
  735 {
  736         struct magma_softc *sc = arg;
  737         struct mtty_softc *mtty = sc->ms_mtty;
  738         struct mbpp_softc *mbpp = sc->ms_mbpp;
  739         int port;
  740         int s, flags;
  741 
  742         if (mtty == NULL)
  743                 goto chkbpp;
  744 
  745         /*
  746          * check the tty ports to see what needs doing
  747          */
  748         for( port = 0 ; port < mtty->ms_nports ; port++ ) {
  749                 struct mtty_port *mp = &mtty->ms_port[port];
  750                 struct tty *tp = mp->mp_tty;
  751 
  752                 if( !ISSET(tp->t_state, TS_ISOPEN) )
  753                         continue;
  754 
  755                 /*
  756                  * handle any received data
  757                  */
  758                 while( mp->mp_rget != mp->mp_rput ) {
  759                         u_char stat;
  760                         int data;
  761 
  762                         stat = mp->mp_rget[0];
  763                         data = mp->mp_rget[1];
  764                         mp->mp_rget = ((mp->mp_rget + 2) == mp->mp_rend)
  765                                 ? mp->mp_rbuf : (mp->mp_rget + 2);
  766 
  767                         if( stat & (CD1400_RDSR_BREAK | CD1400_RDSR_FE) )
  768                                 data |= TTY_FE;
  769                         if( stat & CD1400_RDSR_PE )
  770                                 data |= TTY_PE;
  771 
  772                         if( stat & CD1400_RDSR_OE )
  773                                 log(LOG_WARNING, "%s%x: fifo overflow\n",
  774                                     mtty->ms_dev.dv_xname, port);
  775 
  776                         (*tp->t_linesw->l_rint)(data, tp);
  777                 }
  778 
  779                 s = splhigh();  /* block out hard interrupt routine */
  780                 flags = mp->mp_flags;
  781                 CLR(mp->mp_flags, MTTYF_DONE | MTTYF_CARRIER_CHANGED | MTTYF_RING_OVERFLOW);
  782                 splx(s);        /* ok */
  783 
  784                 if( ISSET(flags, MTTYF_CARRIER_CHANGED) ) {
  785                         dprintf(("%s%x: cd %s\n", mtty->ms_dev.dv_xname,
  786                                 port, mp->mp_carrier ? "on" : "off"));
  787                         (*tp->t_linesw->l_modem)(tp, mp->mp_carrier);
  788                 }
  789 
  790                 if( ISSET(flags, MTTYF_RING_OVERFLOW) ) {
  791                         log(LOG_WARNING, "%s%x: ring buffer overflow\n",
  792                             mtty->ms_dev.dv_xname, port);
  793                 }
  794 
  795                 if( ISSET(flags, MTTYF_DONE) ) {
  796                         ndflush(&tp->t_outq, mp->mp_txp - tp->t_outq.c_cf);
  797                         CLR(tp->t_state, TS_BUSY);
  798                         (*tp->t_linesw->l_start)(tp);   /* might be some more */
  799                 }
  800         } /* for(each mtty...) */
  801 
  802 
  803 chkbpp:
  804         /*
  805          * Check the bpp ports (if any) to see what needs doing
  806          */
  807         if (mbpp == NULL)
  808                 return;
  809 
  810         for( port = 0 ; port < mbpp->ms_nports ; port++ ) {
  811                 struct mbpp_port *mp = &mbpp->ms_port[port];
  812 
  813                 if( !ISSET(mp->mp_flags, MBPPF_OPEN) )
  814                         continue;
  815 
  816                 s = splhigh();
  817                 flags = mp->mp_flags;
  818                 CLR(mp->mp_flags, MBPPF_WAKEUP);
  819                 splx(s);
  820 
  821                 if( ISSET(flags, MBPPF_WAKEUP) ) {
  822                         wakeup(mp);
  823                 }
  824 
  825         } /* for(each mbpp...) */
  826 }
  827 
  828 /************************************************************************
  829  *
  830  *  MTTY Routines
  831  *
  832  *      mtty_match              match one mtty device
  833  *      mtty_attach             attach mtty devices
  834  *      mttyopen                open mtty device
  835  *      mttyclose               close mtty device
  836  *      mttyread                read from mtty
  837  *      mttywrite               write to mtty
  838  *      mttyioctl               do ioctl on mtty
  839  *      mttytty                 return tty pointer for mtty
  840  *      mttystop                stop mtty device
  841  *      mtty_start              start mtty device
  842  *      mtty_param              set mtty parameters
  843  *      mtty_modem_control      set modem control lines
  844  */
  845 
  846 int
  847 mtty_match(parent, cf, args)
  848         struct device *parent;
  849         struct cfdata *cf;
  850         void *args;
  851 {
  852         struct magma_softc *sc = (struct magma_softc *)parent;
  853 
  854         return( args == mtty_match && sc->ms_board->mb_nser && sc->ms_mtty == NULL );
  855 }
  856 
  857 void
  858 mtty_attach(parent, dev, args)
  859         struct device *parent;
  860         struct device *dev;
  861         void *args;
  862 {
  863         struct magma_softc *sc = (struct magma_softc *)parent;
  864         struct mtty_softc *ms = (struct mtty_softc *)dev;
  865         int port, chip, chan;
  866 
  867         sc->ms_mtty = ms;
  868         dprintf((" addr %p", ms));
  869 
  870         for( port = 0, chip = 0, chan = 0 ; port < sc->ms_board->mb_nser ; port++ ) {
  871                 struct mtty_port *mp = &ms->ms_port[port];
  872                 struct tty *tp;
  873 
  874                 mp->mp_cd1400 = &sc->ms_cd1400[chip];
  875                 if (mp->mp_cd1400->cd_parmode && chan == 0)
  876                         chan = 1; /* skip channel 0 if parmode */
  877                 mp->mp_channel = chan;
  878 
  879                 tp = ttymalloc();
  880                 if (tp == NULL) break;
  881                 tty_attach(tp);
  882                 tp->t_oproc = mtty_start;
  883                 tp->t_param = mtty_param;
  884 
  885                 mp->mp_tty = tp;
  886 
  887                 mp->mp_rbuf = malloc(MTTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT);
  888                 if (mp->mp_rbuf == NULL) break;
  889 
  890                 mp->mp_rend = mp->mp_rbuf + MTTY_RBUF_SIZE;
  891 
  892                 chan = (chan + 1) % CD1400_NO_OF_CHANNELS;
  893                 if (chan == 0)
  894                         chip++;
  895         }
  896 
  897         ms->ms_nports = port;
  898         printf(": %d tty%s\n", port, port == 1 ? "" : "s");
  899 }
  900 
  901 /*
  902  * open routine. returns zero if successful, else error code
  903  */
  904 int
  905 mttyopen(dev, flags, mode, p)
  906         dev_t dev;
  907         int flags;
  908         int mode;
  909         struct proc *p;
  910 {
  911         int card = MAGMA_CARD(dev);
  912         int port = MAGMA_PORT(dev);
  913         struct mtty_softc *ms;
  914         struct mtty_port *mp;
  915         struct tty *tp;
  916         struct cd1400 *cd;
  917         int error, s;
  918 
  919         if( card >= mtty_cd.cd_ndevs ||
  920             (ms = mtty_cd.cd_devs[card]) == NULL || port >= ms->ms_nports )
  921                 return(ENXIO);  /* device not configured */
  922 
  923         mp = &ms->ms_port[port];
  924         tp = mp->mp_tty;
  925         tp->t_dev = dev;
  926 
  927         if (ISSET(tp->t_state, TS_ISOPEN) &&
  928             ISSET(tp->t_state, TS_XCLUDE) &&
  929             p->p_ucred->cr_uid != 0)
  930                 return (EBUSY);
  931 
  932         s = spltty();
  933 
  934         if( !ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
  935 
  936                 /* set defaults */
  937                 ttychars(tp);
  938                 tp->t_iflag = TTYDEF_IFLAG;
  939                 tp->t_oflag = TTYDEF_OFLAG;
  940                 tp->t_cflag = TTYDEF_CFLAG;
  941                 if( ISSET(mp->mp_openflags, TIOCFLAG_CLOCAL) )
  942                         SET(tp->t_cflag, CLOCAL);
  943                 if( ISSET(mp->mp_openflags, TIOCFLAG_CRTSCTS) )
  944                         SET(tp->t_cflag, CRTSCTS);
  945                 if( ISSET(mp->mp_openflags, TIOCFLAG_MDMBUF) )
  946                         SET(tp->t_cflag, MDMBUF);
  947                 tp->t_lflag = TTYDEF_LFLAG;
  948                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  949 
  950                 /* init ring buffer */
  951                 mp->mp_rput = mp->mp_rget = mp->mp_rbuf;
  952 
  953                 /* reset CD1400 channel */
  954                 cd = mp->mp_cd1400;
  955                 cd1400_write_reg(cd, CD1400_CAR, mp->mp_channel);
  956                 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET);
  957 
  958                 /* encode the port number in top half of LIVR */
  959                 cd1400_write_reg(cd, CD1400_LIVR, port << 4 );
  960 
  961                 /* sets parameters and raises DTR */
  962                 (void)mtty_param(tp, &tp->t_termios);
  963 
  964                 /* set tty watermarks */
  965                 ttsetwater(tp);
  966 
  967                 /* enable service requests */
  968                 cd1400_write_reg(cd, CD1400_SRER,
  969                                  CD1400_SRER_RXDATA | CD1400_SRER_MDMCH);
  970 
  971                 /* tell the tty about the carrier status */
  972                 if( ISSET(mp->mp_openflags, TIOCFLAG_SOFTCAR) ||
  973                     mp->mp_carrier )
  974                         SET(tp->t_state, TS_CARR_ON);
  975                 else
  976                         CLR(tp->t_state, TS_CARR_ON);
  977         }
  978         splx(s);
  979 
  980         error = ttyopen(tp, MTTY_DIALOUT(dev), ISSET(flags, O_NONBLOCK));
  981         if (error != 0)
  982                 goto bad;
  983 
  984         error = (*tp->t_linesw->l_open)(dev, tp);
  985         if (error != 0)
  986                 goto bad;
  987 
  988 bad:
  989         if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
  990                 /*
  991                  * We failed to open the device, and nobody else had it opened.
  992                  * Clean up the state as appropriate.
  993                  */
  994                 /* XXX - do that here */
  995         }
  996 
  997         return (error);
  998 }
  999 
 1000 /*
 1001  * close routine. returns zero if successful, else error code
 1002  */
 1003 int
 1004 mttyclose(dev, flag, mode, p)
 1005         dev_t dev;
 1006         int flag;
 1007         int mode;
 1008         struct proc *p;
 1009 {
 1010         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
 1011         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
 1012         struct tty *tp = mp->mp_tty;
 1013         int s;
 1014 
 1015         (*tp->t_linesw->l_close)(tp, flag);
 1016         ttyclose(tp);
 1017 
 1018         s = spltty();
 1019 
 1020         /* if HUPCL is set, and the tty is no longer open
 1021          * shut down the port
 1022          */
 1023         if( ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN) ) {
 1024                 /* XXX wait until FIFO is empty before turning off the channel
 1025                 struct cd1400 *cd = mp->mp_cd1400;
 1026                 */
 1027 
 1028                 /* drop DTR and RTS */
 1029                 (void)mtty_modem_control(mp, 0, DMSET);
 1030 
 1031                 /* turn off the channel
 1032                 cd1400_write_reg(cd, CD1400_CAR, mp->mp_channel);
 1033                 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET);
 1034                 */
 1035         }
 1036 
 1037         splx(s);
 1038 
 1039         return(0);
 1040 }
 1041 
 1042 /*
 1043  * Read routine
 1044  */
 1045 int
 1046 mttyread(dev, uio, flags)
 1047         dev_t dev;
 1048         struct uio *uio;
 1049         int flags;
 1050 {
 1051         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
 1052         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
 1053         struct tty *tp = mp->mp_tty;
 1054 
 1055         return( (*tp->t_linesw->l_read)(tp, uio, flags) );
 1056 }
 1057 
 1058 /*
 1059  * Write routine
 1060  */
 1061 int
 1062 mttywrite(dev, uio, flags)
 1063         dev_t dev;
 1064         struct uio *uio;
 1065         int flags;
 1066 {
 1067         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
 1068         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
 1069         struct tty *tp = mp->mp_tty;
 1070 
 1071         return( (*tp->t_linesw->l_write)(tp, uio, flags) );
 1072 }
 1073 
 1074 /*
 1075  * Poll routine
 1076  */
 1077 int
 1078 mttypoll(dev, events, p)
 1079         dev_t dev;
 1080         int events;
 1081         struct proc *p;
 1082 {
 1083         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
 1084         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
 1085         struct tty *tp = mp->mp_tty;
 1086  
 1087         return ((*tp->t_linesw->l_poll)(tp, events, p));
 1088 }
 1089 
 1090 /*
 1091  * return tty pointer
 1092  */
 1093 struct tty *
 1094 mttytty(dev)
 1095         dev_t dev;
 1096 {
 1097         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
 1098         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
 1099 
 1100         return(mp->mp_tty);
 1101 }
 1102 
 1103 /*
 1104  * ioctl routine
 1105  */
 1106 int
 1107 mttyioctl(dev, cmd, data, flags, p)
 1108         dev_t dev;
 1109         u_long cmd;
 1110         caddr_t data;
 1111         int flags;
 1112         struct proc *p;
 1113 {
 1114         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
 1115         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
 1116         struct tty *tp = mp->mp_tty;
 1117         int error;
 1118 
 1119         error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, p);
 1120         if( error != EPASSTHROUGH ) return(error);
 1121 
 1122         error = ttioctl(tp, cmd, data, flags, p);
 1123         if( error != EPASSTHROUGH ) return(error);
 1124 
 1125         error = 0;
 1126 
 1127         switch(cmd) {
 1128         case TIOCSBRK:  /* set break */
 1129                 SET(mp->mp_flags, MTTYF_SET_BREAK);
 1130                 cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel);
 1131                 break;
 1132 
 1133         case TIOCCBRK:  /* clear break */
 1134                 SET(mp->mp_flags, MTTYF_CLR_BREAK);
 1135                 cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel);
 1136                 break;
 1137 
 1138         case TIOCSDTR:  /* set DTR */
 1139                 mtty_modem_control(mp, TIOCM_DTR, DMBIS);
 1140                 break;
 1141 
 1142         case TIOCCDTR:  /* clear DTR */
 1143                 mtty_modem_control(mp, TIOCM_DTR, DMBIC);
 1144                 break;
 1145 
 1146         case TIOCMSET:  /* set modem lines */
 1147                 mtty_modem_control(mp, *((int *)data), DMSET);
 1148                 break;
 1149 
 1150         case TIOCMBIS:  /* bit set modem lines */
 1151                 mtty_modem_control(mp, *((int *)data), DMBIS);
 1152                 break;
 1153 
 1154         case TIOCMBIC:  /* bit clear modem lines */
 1155                 mtty_modem_control(mp, *((int *)data), DMBIC);
 1156                 break;
 1157 
 1158         case TIOCMGET:  /* get modem lines */
 1159                 *((int *)data) = mtty_modem_control(mp, 0, DMGET);
 1160                 break;
 1161 
 1162         case TIOCGFLAGS:
 1163                 *((int *)data) = mp->mp_openflags;
 1164                 break;
 1165 
 1166         case TIOCSFLAGS:
 1167                 if( suser(p->p_ucred, &p->p_acflag) )
 1168                         error = EPERM;
 1169                 else
 1170                         mp->mp_openflags = *((int *)data) &
 1171                                 (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
 1172                                 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
 1173                 break;
 1174 
 1175         default:
 1176                 error = EPASSTHROUGH;
 1177         }
 1178 
 1179         return(error);
 1180 }
 1181 
 1182 /*
 1183  * Stop output, e.g., for ^S or output flush.
 1184  */
 1185 void
 1186 mttystop(tp, flags)
 1187         struct tty *tp;
 1188         int flags;
 1189 {
 1190         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)];
 1191         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)];
 1192         int s;
 1193 
 1194         s = spltty();
 1195 
 1196         if( ISSET(tp->t_state, TS_BUSY) ) {
 1197                 if( !ISSET(tp->t_state, TS_TTSTOP) )
 1198                         SET(tp->t_state, TS_FLUSH);
 1199 
 1200                 /*
 1201                  * the transmit interrupt routine will disable transmit when it
 1202                  * notices that MTTYF_STOP has been set.
 1203                  */
 1204                 SET(mp->mp_flags, MTTYF_STOP);
 1205         }
 1206 
 1207         splx(s);
 1208 }
 1209 
 1210 /*
 1211  * Start output, after a stop.
 1212  */
 1213 void
 1214 mtty_start(tp)
 1215         struct tty *tp;
 1216 {
 1217         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)];
 1218         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)];
 1219         int s;
 1220 
 1221         s = spltty();
 1222 
 1223         /* we only need to do something if we are not already busy
 1224          * or delaying or stopped
 1225          */
 1226         if( !ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY) ) {
 1227 
 1228                 /* if we are sleeping and output has drained below
 1229                  * low water mark, awaken
 1230                  */
 1231                 if( tp->t_outq.c_cc <= tp->t_lowat ) {
 1232                         if( ISSET(tp->t_state, TS_ASLEEP) ) {
 1233                                 CLR(tp->t_state, TS_ASLEEP);
 1234                                 wakeup(&tp->t_outq);
 1235                         }
 1236 
 1237                         selwakeup(&tp->t_wsel);
 1238                 }
 1239 
 1240                 /* if something to send, start transmitting
 1241                  */
 1242                 if( tp->t_outq.c_cc ) {
 1243                         mp->mp_txc = ndqb(&tp->t_outq, 0);
 1244                         mp->mp_txp = tp->t_outq.c_cf;
 1245                         SET(tp->t_state, TS_BUSY);
 1246                         cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel);
 1247                 }
 1248         }
 1249 
 1250         splx(s);
 1251 }
 1252 
 1253 /*
 1254  * set/get modem line status
 1255  *
 1256  * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR
 1257  *
 1258  * note that DTR and RTS lines are exchanged, and that DSR is
 1259  * not available on the LC2+1Sp card (used as CD)
 1260  *
 1261  * only let them fiddle with RTS if CRTSCTS is not enabled
 1262  */
 1263 int
 1264 mtty_modem_control(mp, bits, howto)
 1265         struct mtty_port *mp;
 1266         int bits;
 1267         int howto;
 1268 {
 1269         struct cd1400 *cd = mp->mp_cd1400;
 1270         struct tty *tp = mp->mp_tty;
 1271         int s, msvr;
 1272 
 1273         s = spltty();
 1274 
 1275         cd1400_write_reg(cd, CD1400_CAR, mp->mp_channel);
 1276 
 1277         switch(howto) {
 1278         case DMGET:     /* get bits */
 1279                 bits = 0;
 1280 
 1281                 bits |= TIOCM_LE;
 1282 
 1283                 msvr = cd1400_read_reg(cd, CD1400_MSVR1);
 1284                 if( msvr & CD1400_MSVR1_RTS ) bits |= TIOCM_DTR;
 1285 
 1286                 msvr = cd1400_read_reg(cd, CD1400_MSVR2);
 1287                 if( msvr & CD1400_MSVR2_DTR ) bits |= TIOCM_RTS;
 1288                 if( msvr & CD1400_MSVR2_CTS ) bits |= TIOCM_CTS;
 1289                 if( msvr & CD1400_MSVR2_RI ) bits |= TIOCM_RI;
 1290                 if( msvr & CD1400_MSVR2_DSR ) bits |= (cd->cd_parmode ? TIOCM_CD : TIOCM_DSR);
 1291                 if( msvr & CD1400_MSVR2_CD ) bits |= (cd->cd_parmode ? 0 : TIOCM_CD);
 1292 
 1293                 break;
 1294 
 1295         case DMSET:     /* reset bits */
 1296                 if( !ISSET(tp->t_cflag, CRTSCTS) )
 1297                         cd1400_write_reg(cd, CD1400_MSVR2, ((bits & TIOCM_RTS) ? CD1400_MSVR2_DTR : 0));
 1298 
 1299                 cd1400_write_reg(cd, CD1400_MSVR1, ((bits & TIOCM_DTR) ? CD1400_MSVR1_RTS : 0));
 1300 
 1301                 break;
 1302 
 1303         case DMBIS:     /* set bits */
 1304                 if( (bits & TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS) )
 1305                         cd1400_write_reg(cd, CD1400_MSVR2, CD1400_MSVR2_DTR);
 1306 
 1307                 if( bits & TIOCM_DTR )
 1308                         cd1400_write_reg(cd, CD1400_MSVR1, CD1400_MSVR1_RTS);
 1309 
 1310                 break;
 1311 
 1312         case DMBIC:     /* clear bits */
 1313                 if( (bits & TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS) )
 1314                         cd1400_write_reg(cd, CD1400_MSVR2, 0);
 1315 
 1316                 if( bits & TIOCM_DTR )
 1317                         cd1400_write_reg(cd, CD1400_MSVR1, 0);
 1318 
 1319                 break;
 1320         }
 1321 
 1322         splx(s);
 1323         return(bits);
 1324 }
 1325 
 1326 /*
 1327  * Set tty parameters, returns error or 0 on success
 1328  */
 1329 int
 1330 mtty_param(tp, t)
 1331         struct tty *tp;
 1332         struct termios *t;
 1333 {
 1334         struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)];
 1335         struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)];
 1336         struct cd1400 *cd = mp->mp_cd1400;
 1337         int rbpr, tbpr, rcor, tcor;
 1338         u_char mcor1 = 0, mcor2 = 0;
 1339         int s, opt;
 1340 
 1341         if( t->c_ospeed && cd1400_compute_baud(t->c_ospeed, cd->cd_clock, &tcor, &tbpr) )
 1342                 return(EINVAL);
 1343 
 1344         if( t->c_ispeed && cd1400_compute_baud(t->c_ispeed, cd->cd_clock, &rcor, &rbpr) )
 1345                 return(EINVAL);
 1346 
 1347         s = spltty();
 1348 
 1349         /* hang up the line if ospeed is zero, else raise DTR */
 1350         (void)mtty_modem_control(mp, TIOCM_DTR, (t->c_ospeed == 0 ? DMBIC : DMBIS));
 1351 
 1352         /* select channel, done in mtty_modem_control() */
 1353         /* cd1400_write_reg(cd, CD1400_CAR, mp->mp_channel); */
 1354 
 1355         /* set transmit speed */
 1356         if( t->c_ospeed ) {
 1357                 cd1400_write_reg(cd, CD1400_TCOR, tcor);
 1358                 cd1400_write_reg(cd, CD1400_TBPR, tbpr);
 1359         }
 1360 
 1361         /* set receive speed */
 1362         if( t->c_ispeed ) {
 1363                 cd1400_write_reg(cd, CD1400_RCOR, rcor);
 1364                 cd1400_write_reg(cd, CD1400_RBPR, rbpr);
 1365         }
 1366 
 1367         /* enable transmitting and receiving on this channel */
 1368         opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN | CD1400_CCR_RCVEN;
 1369         cd1400_write_ccr(cd, opt);
 1370 
 1371         /* set parity, data and stop bits */
 1372         opt = 0;
 1373         if( ISSET(t->c_cflag, PARENB) )
 1374                 opt |= (ISSET(t->c_cflag, PARODD) ? CD1400_COR1_PARODD : CD1400_COR1_PARNORMAL);
 1375 
 1376         if( !ISSET(t->c_iflag, INPCK) )
 1377                 opt |= CD1400_COR1_NOINPCK; /* no parity checking */
 1378 
 1379         if( ISSET(t->c_cflag, CSTOPB) )
 1380                 opt |= CD1400_COR1_STOP2;
 1381 
 1382         switch( t->c_cflag & CSIZE ) {
 1383         case CS5:
 1384                 opt |= CD1400_COR1_CS5;
 1385                 break;
 1386 
 1387         case CS6:
 1388                 opt |= CD1400_COR1_CS6;
 1389                 break;
 1390 
 1391         case CS7:
 1392                 opt |= CD1400_COR1_CS7;
 1393                 break;
 1394 
 1395         default:
 1396                 opt |= CD1400_COR1_CS8;
 1397                 break;
 1398         }
 1399 
 1400         cd1400_write_reg(cd, CD1400_COR1, opt);
 1401 
 1402         /*
 1403          * enable Embedded Transmit Commands (for breaks)
 1404          * use the CD1400 automatic CTS flow control if CRTSCTS is set
 1405          */
 1406         opt = CD1400_COR2_ETC;
 1407         if( ISSET(t->c_cflag, CRTSCTS) ) opt |= CD1400_COR2_CCTS_OFLOW;
 1408         cd1400_write_reg(cd, CD1400_COR2, opt);
 1409 
 1410         cd1400_write_reg(cd, CD1400_COR3, MTTY_RX_FIFO_THRESHOLD);
 1411 
 1412         cd1400_write_ccr(cd, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR1 | CD1400_CCR_COR2 | CD1400_CCR_COR3);
 1413 
 1414         cd1400_write_reg(cd, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION);
 1415         cd1400_write_reg(cd, CD1400_COR5, 0);
 1416 
 1417         /*
 1418          * if automatic RTS handshaking enabled, set DTR threshold
 1419          * (RTS and DTR lines are switched, CD1400 thinks its DTR)
 1420          */
 1421         if( ISSET(t->c_cflag, CRTSCTS) )
 1422                 mcor1 = MTTY_RX_DTR_THRESHOLD;
 1423 
 1424         /* set up `carrier detect' interrupts */
 1425         if( cd->cd_parmode ) {
 1426                 SET(mcor1, CD1400_MCOR1_DSRzd);
 1427                 SET(mcor2, CD1400_MCOR2_DSRod);
 1428         } else {
 1429                 SET(mcor1, CD1400_MCOR1_CDzd);
 1430                 SET(mcor2, CD1400_MCOR2_CDod);
 1431         }
 1432 
 1433         cd1400_write_reg(cd, CD1400_MCOR1, mcor1);
 1434         cd1400_write_reg(cd, CD1400_MCOR2, mcor2);
 1435 
 1436         /* receive timeout 2ms */
 1437         cd1400_write_reg(cd, CD1400_RTPR, 2);
 1438 
 1439         splx(s);
 1440         return(0);
 1441 }
 1442 
 1443 /************************************************************************
 1444  *
 1445  *  MBPP Routines
 1446  *
 1447  *      mbpp_match      match one mbpp device
 1448  *      mbpp_attach     attach mbpp devices
 1449  *      mbppopen        open mbpp device
 1450  *      mbppclose       close mbpp device
 1451  *      mbppioctl       do ioctl on mbpp
 1452  *      mbpp_rw         general rw routine
 1453  *      mbpp_timeout    rw timeout
 1454  *      mbpp_start      rw start after delay
 1455  *      mbpp_send       send data
 1456  *      mbpp_recv       recv data
 1457  */
 1458 
 1459 int
 1460 mbpp_match(parent, cf, args)
 1461         struct device *parent;
 1462         struct cfdata *cf;
 1463         void *args;
 1464 {
 1465         struct magma_softc *sc = (struct magma_softc *)parent;
 1466 
 1467         return( args == mbpp_match && sc->ms_board->mb_npar && sc->ms_mbpp == NULL );
 1468 }
 1469 
 1470 void
 1471 mbpp_attach(parent, dev, args)
 1472         struct device *parent;
 1473         struct device *dev;
 1474         void *args;
 1475 {
 1476         struct magma_softc *sc = (struct magma_softc *)parent;
 1477         struct mbpp_softc *ms = (struct mbpp_softc *)dev;
 1478         struct mbpp_port *mp;
 1479         int port;
 1480 
 1481         sc->ms_mbpp = ms;
 1482         dprintf((" addr %p", ms));
 1483 
 1484         for( port = 0 ; port < sc->ms_board->mb_npar ; port++ ) {
 1485                 mp = &ms->ms_port[port];
 1486 
 1487                 callout_init(&mp->mp_timeout_ch);
 1488                 callout_init(&mp->mp_start_ch);
 1489 
 1490                 if( sc->ms_ncd1190 )
 1491                         mp->mp_cd1190 = &sc->ms_cd1190[port];
 1492                 else
 1493                         mp->mp_cd1400 = &sc->ms_cd1400[0];
 1494         }
 1495 
 1496         ms->ms_nports = port;
 1497         printf(": %d port%s\n", port, port == 1 ? "" : "s");
 1498 }
 1499 
 1500 /*
 1501  * open routine. returns zero if successful, else error code
 1502  */
 1503 int
 1504 mbppopen(dev, flags, mode, p)
 1505         dev_t dev;
 1506         int flags;
 1507         int mode;
 1508         struct proc *p;
 1509 {
 1510         int card = MAGMA_CARD(dev);
 1511         int port = MAGMA_PORT(dev);
 1512         struct mbpp_softc *ms;
 1513         struct mbpp_port *mp;
 1514         int s;
 1515 
 1516         if( card >= mbpp_cd.cd_ndevs ||
 1517             (ms = mbpp_cd.cd_devs[card]) == NULL || port >= ms->ms_nports )
 1518                 return(ENXIO);
 1519 
 1520         mp = &ms->ms_port[port];
 1521 
 1522         s = spltty();
 1523         if( ISSET(mp->mp_flags, MBPPF_OPEN) ) {
 1524                 splx(s);
 1525                 return(EBUSY);
 1526         }
 1527         SET(mp->mp_flags, MBPPF_OPEN);
 1528         splx(s);
 1529 
 1530         /* set defaults */
 1531         mp->mp_burst = MBPP_BURST;
 1532         mp->mp_timeout = mbpp_mstohz(MBPP_TIMEOUT);
 1533         mp->mp_delay = mbpp_mstohz(MBPP_DELAY);
 1534 
 1535         /* init chips */
 1536         if( mp->mp_cd1400 ) {   /* CD1400 */
 1537                 struct cd1400 *cd = mp->mp_cd1400;
 1538 
 1539                 /* set up CD1400 channel */
 1540                 s = spltty();
 1541                 cd1400_write_reg(cd, CD1400_CAR, 0);
 1542                 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET);
 1543                 cd1400_write_reg(cd, CD1400_LIVR, (1<<3));
 1544                 splx(s);
 1545         } else {                /* CD1190 */
 1546                 mp->mp_flags = 0;
 1547                 return (ENXIO);
 1548         }
 1549 
 1550         return (0);
 1551 }
 1552 
 1553 /*
 1554  * close routine. returns zero if successful, else error code
 1555  */
 1556 int
 1557 mbppclose(dev, flag, mode, p)
 1558         dev_t dev;
 1559         int flag;
 1560         int mode;
 1561         struct proc *p;
 1562 {
 1563         struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)];
 1564         struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
 1565 
 1566         mp->mp_flags = 0;
 1567         return(0);
 1568 }
 1569 
 1570 /*
 1571  * ioctl routine
 1572  */
 1573 int
 1574 mbppioctl(dev, cmd, data, flags, p)
 1575         dev_t dev;
 1576         u_long cmd;
 1577         caddr_t data;
 1578         int flags;
 1579         struct proc *p;
 1580 {
 1581         struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)];
 1582         struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
 1583         struct mbpp_param *bp;
 1584         int error = 0;
 1585         int s;
 1586 
 1587         switch(cmd) {
 1588         case MBPPIOCSPARAM:
 1589                 bp = (struct mbpp_param *)data;
 1590                 if( bp->bp_burst < MBPP_BURST_MIN || bp->bp_burst > MBPP_BURST_MAX ||
 1591                     bp->bp_delay < MBPP_DELAY_MIN || bp->bp_delay > MBPP_DELAY_MIN ) {
 1592                         error = EINVAL;
 1593                 } else {
 1594                         mp->mp_burst = bp->bp_burst;
 1595                         mp->mp_timeout = mbpp_mstohz(bp->bp_timeout);
 1596                         mp->mp_delay = mbpp_mstohz(bp->bp_delay);
 1597                 }
 1598                 break;
 1599         case MBPPIOCGPARAM:
 1600                 bp = (struct mbpp_param *)data;
 1601                 bp->bp_burst = mp->mp_burst;
 1602                 bp->bp_timeout = mbpp_hztoms(mp->mp_timeout);
 1603                 bp->bp_delay = mbpp_hztoms(mp->mp_delay);
 1604                 break;
 1605         case MBPPIOCGSTAT:
 1606                 /* XXX make this more generic */
 1607                 s = spltty();
 1608                 cd1400_write_reg(mp->mp_cd1400, CD1400_CAR, 0);
 1609                 *(int *)data = cd1400_read_reg(mp->mp_cd1400, CD1400_PSVR);
 1610                 splx(s);
 1611                 break;
 1612         default:
 1613                 error = ENOTTY;
 1614         }
 1615 
 1616         return(error);
 1617 }
 1618 
 1619 int
 1620 mbpp_rw(dev, uio, flag)
 1621         dev_t dev;
 1622         struct uio *uio;
 1623         int flag;
 1624 {
 1625         int card = MAGMA_CARD(dev);
 1626         int port = MAGMA_PORT(dev);
 1627         struct mbpp_softc *ms = mbpp_cd.cd_devs[card];
 1628         struct mbpp_port *mp = &ms->ms_port[port];
 1629         caddr_t buffer, ptr;
 1630         int buflen, cnt, len;
 1631         int s, error = 0;
 1632         int gotdata = 0;
 1633 
 1634         if( uio->uio_resid == 0 )
 1635                 return(0);
 1636 
 1637         buflen = min(uio->uio_resid, mp->mp_burst);
 1638         buffer = malloc(buflen, M_DEVBUF, M_WAITOK);
 1639         if( buffer == NULL )
 1640                 return(ENOMEM);
 1641 
 1642         SET(mp->mp_flags, MBPPF_UIO);
 1643 
 1644         /*
 1645          * start timeout, if needed
 1646          */
 1647         if( mp->mp_timeout > 0 ) {
 1648                 SET(mp->mp_flags, MBPPF_TIMEOUT);
 1649                 callout_reset(&mp->mp_timeout_ch, mp->mp_timeout,
 1650                     mbpp_timeout, mp);
 1651         }
 1652 
 1653         len = cnt = 0;
 1654         while( uio->uio_resid > 0 ) {
 1655                 len = min(buflen, uio->uio_resid);
 1656                 ptr = buffer;
 1657 
 1658                 if( uio->uio_rw == UIO_WRITE ) {
 1659                         error = uiomove(ptr, len, uio);
 1660                         if( error ) break;
 1661                 }
 1662 again:          /* goto bad */
 1663                 /* timed out?  */
 1664                 if( !ISSET(mp->mp_flags, MBPPF_UIO) )
 1665                         break;
 1666 
 1667                 /*
 1668                  * perform the operation
 1669                  */
 1670                 if( uio->uio_rw == UIO_WRITE ) {
 1671                         cnt = mbpp_send(mp, ptr, len);
 1672                 } else {
 1673                         cnt = mbpp_recv(mp, ptr, len);
 1674                 }
 1675 
 1676                 if( uio->uio_rw == UIO_READ ) {
 1677                         if( cnt ) {
 1678                                 error = uiomove(ptr, cnt, uio);
 1679                                 if( error ) break;
 1680                                 gotdata++;
 1681                         }
 1682                         else if( gotdata )      /* consider us done */
 1683                                 break;
 1684                 }
 1685 
 1686                 /* timed out?  */
 1687                 if( !ISSET(mp->mp_flags, MBPPF_UIO) )
 1688                         break;
 1689 
 1690                 /*
 1691                  * poll delay?
 1692                  */
 1693                 if( mp->mp_delay > 0 ) {
 1694                         s = splsoftclock();
 1695                         SET(mp->mp_flags, MBPPF_DELAY);
 1696                         callout_reset(&mp->mp_start_ch, mp->mp_delay,
 1697                             mbpp_start, mp);
 1698                         error = tsleep(mp, PCATCH | PZERO, "mbppdelay", 0);
 1699                         splx(s);
 1700                         if( error ) break;
 1701                 }
 1702 
 1703                 /*
 1704                  * don't call uiomove again until we used all the data we grabbed
 1705                  */
 1706                 if( uio->uio_rw == UIO_WRITE && cnt != len ) {
 1707                         ptr += cnt;
 1708                         len -= cnt;
 1709                         cnt = 0;
 1710                         goto again;
 1711                 }
 1712         }
 1713 
 1714         /*
 1715          * clear timeouts
 1716          */
 1717         s = splsoftclock();
 1718         if( ISSET(mp->mp_flags, MBPPF_TIMEOUT) ) {
 1719                 callout_stop(&mp->mp_timeout_ch);
 1720                 CLR(mp->mp_flags, MBPPF_TIMEOUT);
 1721         }
 1722         if( ISSET(mp->mp_flags, MBPPF_DELAY) ) {
 1723                 callout_stop(&mp->mp_start_ch);
 1724                 CLR(mp->mp_flags, MBPPF_DELAY);
 1725         }
 1726         splx(s);
 1727 
 1728         /*
 1729          * adjust for those chars that we uiomoved but never actually wrote
 1730          */
 1731         if( uio->uio_rw == UIO_WRITE && cnt != len ) {
 1732                 uio->uio_resid += (len - cnt);
 1733         }
 1734 
 1735         free(buffer, M_DEVBUF);
 1736         return(error);
 1737 }
 1738 
 1739 void
 1740 mbpp_timeout(arg)
 1741         void *arg;
 1742 {
 1743         struct mbpp_port *mp = arg;
 1744 
 1745         CLR(mp->mp_flags, MBPPF_UIO | MBPPF_TIMEOUT);
 1746         wakeup(mp);
 1747 }
 1748 
 1749 void
 1750 mbpp_start(arg)
 1751         void *arg;
 1752 {
 1753         struct mbpp_port *mp = arg;
 1754 
 1755         CLR(mp->mp_flags, MBPPF_DELAY);
 1756         wakeup(mp);
 1757 }
 1758 
 1759 int
 1760 mbpp_send(mp, ptr, len)
 1761         struct mbpp_port *mp;
 1762         caddr_t ptr;
 1763         int len;
 1764 {
 1765         int s;
 1766         struct cd1400 *cd = mp->mp_cd1400;
 1767 
 1768         /* set up io information */
 1769         mp->mp_ptr = ptr;
 1770         mp->mp_cnt = len;
 1771 
 1772         /* start transmitting */
 1773         s = spltty();
 1774         if( cd ) {
 1775                 cd1400_write_reg(cd, CD1400_CAR, 0);
 1776 
 1777                 /* output strobe width ~1microsecond */
 1778                 cd1400_write_reg(cd, CD1400_TBPR, 10);
 1779 
 1780                 /* enable channel */
 1781                 cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN);
 1782                 cd1400_write_reg(cd, CD1400_SRER, CD1400_SRER_TXRDY);
 1783         }
 1784 
 1785         /* ZZzzz... */
 1786         tsleep(mp, PCATCH | PZERO, "mbpp_send", 0);
 1787 
 1788         /* stop transmitting */
 1789         if( cd ) {
 1790                 cd1400_write_reg(cd, CD1400_CAR, 0);
 1791 
 1792                 /* disable transmitter */
 1793                 cd1400_write_reg(cd, CD1400_SRER, 0);
 1794                 cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTDIS);
 1795 
 1796                 /* flush fifo */
 1797                 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
 1798         }
 1799         splx(s);
 1800 
 1801         /* return number of chars sent */
 1802         return(len - mp->mp_cnt);
 1803 }
 1804 
 1805 int
 1806 mbpp_recv(mp, ptr, len)
 1807         struct mbpp_port *mp;
 1808         caddr_t ptr;
 1809         int len;
 1810 {
 1811         int s;
 1812         struct cd1400 *cd = mp->mp_cd1400;
 1813 
 1814         /* set up io information */
 1815         mp->mp_ptr = ptr;
 1816         mp->mp_cnt = len;
 1817 
 1818         /* start receiving */
 1819         s = spltty();
 1820         if( cd ) {
 1821         int rcor, rbpr;
 1822 
 1823                 cd1400_write_reg(cd, CD1400_CAR, 0);
 1824 
 1825                 /* input strobe at 100kbaud (10microseconds) */
 1826                 cd1400_compute_baud(100000, cd->cd_clock, &rcor, &rbpr);
 1827                 cd1400_write_reg(cd, CD1400_RCOR, rcor);
 1828                 cd1400_write_reg(cd, CD1400_RBPR, rbpr);
 1829 
 1830                 /* rx threshold */
 1831                 cd1400_write_reg(cd, CD1400_COR3, MBPP_RX_FIFO_THRESHOLD);
 1832                 cd1400_write_ccr(cd, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3);
 1833 
 1834                 /* enable channel */
 1835                 cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_RCVEN);
 1836                 cd1400_write_reg(cd, CD1400_SRER, CD1400_SRER_RXDATA);
 1837         }
 1838 
 1839         /* ZZzzz... */
 1840         tsleep(mp, PCATCH | PZERO, "mbpp_recv", 0);
 1841 
 1842         /* stop receiving */
 1843         if( cd ) {
 1844                 cd1400_write_reg(cd, CD1400_CAR, 0);
 1845 
 1846                 /* disable receiving */
 1847                 cd1400_write_reg(cd, CD1400_SRER, 0);
 1848                 cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_RCVDIS);
 1849         }
 1850         splx(s);
 1851 
 1852         /* return number of chars received */
 1853         return(len - mp->mp_cnt);
 1854 }
 1855 
 1856 int
 1857 mbpp_hztoms(h)
 1858         int h;
 1859 {
 1860         int m = h;
 1861 
 1862         if( m > 0 )
 1863                 m = m * 1000 / hz;
 1864         return(m);
 1865 }
 1866 
 1867 int
 1868 mbpp_mstohz(m)
 1869         int m;
 1870 {
 1871         int h = m;
 1872 
 1873         if( h > 0 ) {
 1874                 h = h * hz / 1000;
 1875                 if( h == 0 )
 1876                         h = 1000 / hz;
 1877         }
 1878         return(h);
 1879 }
 1880 
 1881 #endif /* NMAGMA */

Cache object: 82aa5f8edbaf57d62aa326f65060d907


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.