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/i386/isa/cronyx.c

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

    1 /*
    2  * Low-level subroutines for Cronyx-Sigma adapter.
    3  *
    4  * Copyright (C) 1994-95 Cronyx Ltd.
    5  * Author: Serge Vakulenko, <vak@cronyx.ru>
    6  *
    7  * This software is distributed with NO WARRANTIES, not even the implied
    8  * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    9  *
   10  * Authors grant any other persons or organisations permission to use
   11  * or modify this software as long as this message is kept with the software,
   12  * all derivative works or modified versions.
   13  *
   14  * Version 1.6, Wed May 31 16:03:20 MSD 1995
   15  * $FreeBSD: releng/5.1/sys/i386/isa/cronyx.c 59874 2000-05-01 20:32:07Z peter $
   16  */
   17 #if defined (MSDOS) || defined (__MSDOS__)
   18 #   include <string.h>
   19 #   include <dos.h>
   20 #   define inb(port)    inportb(port)
   21 #   define inw(port)    inport(port)
   22 #   define outb(port,b) outportb(port,b)
   23 #   define outw(port,w) outport(port,w)
   24 #   define vtophys(a)   (((unsigned long)(a)>>12 & 0xffff0) +\
   25                         ((unsigned)(a) & 0xffff))
   26 #   include "cronyx.h"
   27 #   include "cxreg.h"
   28 #else
   29 #   include <sys/param.h>
   30 #   include <sys/systm.h>
   31 #   include <sys/socket.h>
   32 #   include <net/if.h>
   33 #   include <vm/vm.h>
   34 #   include <vm/vm_param.h>
   35 #   include <vm/pmap.h>
   36 #   ifndef __FreeBSD__
   37 #      include <machine/inline.h>
   38 #   endif
   39 #   include <machine/cronyx.h>
   40 #   include <i386/isa/cxreg.h>
   41 #endif
   42 
   43 #define DMA_MASK        0xd4    /* DMA mask register */
   44 #define DMA_MASK_CLEAR  0x04    /* DMA clear mask */
   45 #define DMA_MODE        0xd6    /* DMA mode register */
   46 #define DMA_MODE_MASTER 0xc0    /* DMA master mode */
   47 
   48 #define BYTE *(unsigned char*)&
   49 
   50 static unsigned char irqmask [] = {
   51         BCR0_IRQ_DIS,   BCR0_IRQ_DIS,   BCR0_IRQ_DIS,   BCR0_IRQ_3,
   52         BCR0_IRQ_DIS,   BCR0_IRQ_5,     BCR0_IRQ_DIS,   BCR0_IRQ_7,
   53         BCR0_IRQ_DIS,   BCR0_IRQ_DIS,   BCR0_IRQ_10,    BCR0_IRQ_11,
   54         BCR0_IRQ_12,    BCR0_IRQ_DIS,   BCR0_IRQ_DIS,   BCR0_IRQ_15,
   55 };
   56 
   57 static unsigned char dmamask [] = {
   58         BCR0_DMA_DIS,   BCR0_DMA_DIS,   BCR0_DMA_DIS,   BCR0_DMA_DIS,
   59         BCR0_DMA_DIS,   BCR0_DMA_5,     BCR0_DMA_6,     BCR0_DMA_7,
   60 };
   61 
   62 static long cx_rxbaud = CX_SPEED_DFLT;  /* receiver baud rate */
   63 static long cx_txbaud = CX_SPEED_DFLT;  /* transmitter baud rate */
   64 
   65 static int cx_univ_mode = M_ASYNC;      /* univ. chan. mode: async or sync */
   66 static int cx_sync_mode = M_HDLC;       /* sync. chan. mode: HDLC, Bisync or X.21 */
   67 static int cx_iftype = 0;               /* univ. chan. interface: upper/lower */
   68 
   69 static cx_chan_opt_t chan_opt_dflt = { /* mode-independent options */
   70         {                       /* cor4 */
   71                 7,              /* FIFO threshold, odd is better */
   72                 0,
   73                 0,              /* don't detect 1 to 0 on CTS */
   74                 1,              /* detect 1 to 0 on CD */
   75                 0,              /* detect 1 to 0 on DSR */
   76         },
   77         {                       /* cor5 */
   78                 0,              /* receive flow control FIFO threshold */
   79                 0,
   80                 0,              /* don't detect 0 to 1 on CTS */
   81                 1,              /* detect 0 to 1 on CD */
   82                 0,              /* detect 0 to 1 on DSR */
   83         },
   84         {                       /* rcor */
   85                 0,              /* dummy clock source */
   86                 ENCOD_NRZ,      /* NRZ mode */
   87                 0,              /* disable DPLL */
   88                 0,
   89                 0,              /* transmit line value */
   90         },
   91         {                       /* tcor */
   92                 0,
   93                 0,              /* local loopback mode */
   94                 0,
   95                 1,              /* external 1x clock mode */
   96                 0,
   97                 0,              /* dummy transmit clock source */
   98         },
   99 };
  100 
  101 static cx_opt_async_t opt_async_dflt = { /* default async options */
  102         {                       /* cor1 */
  103                 8-1,            /* 8-bit char length */
  104                 0,              /* don't ignore parity */
  105                 PARM_NOPAR,     /* no parity */
  106                 PAR_EVEN,       /* even parity */
  107         },
  108         {                       /* cor2 */
  109                 0,              /* disable automatic DSR */
  110                 1,              /* enable automatic CTS */
  111                 0,              /* disable automatic RTS */
  112                 0,              /* no remote loopback */
  113                 0,
  114                 0,              /* disable embedded cmds */
  115                 0,              /* disable XON/XOFF */
  116                 0,              /* disable XANY */
  117         },
  118         {                       /* cor3 */
  119                 STOPB_1,        /* 1 stop bit */
  120                 0,
  121                 0,              /* disable special char detection */
  122                 FLOWCC_PASS,    /* pass flow ctl chars to the host */
  123                 0,              /* range detect disable */
  124                 0,              /* disable extended spec. char detect */
  125         },
  126         {                       /* cor6 */
  127                 PERR_INTR,      /* generate exception on parity errors */
  128                 BRK_INTR,       /* generate exception on break condition */
  129                 0,              /* don't translate NL to CR on input */
  130                 0,              /* don't translate CR to NL on input */
  131                 0,              /* don't discard CR on input */
  132         },
  133         {                       /* cor7 */
  134                 0,              /* don't translate CR to NL on output */
  135                 0,              /* don't translate NL to CR on output */
  136                 0,
  137                 0,              /* don't process flow ctl err chars */
  138                 0,              /* disable LNext option */
  139                 0,              /* don't strip 8 bit on input */
  140         },
  141         0, 0, 0, 0, 0, 0, 0,    /* clear schr1-4, scrl, scrh, lnxt */
  142 };
  143 
  144 static cx_opt_hdlc_t opt_hdlc_dflt = { /* default hdlc options */
  145         {                       /* cor1 */
  146                 2,              /* 2 inter-frame flags */
  147                 0,              /* no-address mode */
  148                 CLRDET_DISABLE, /* disable clear detect */
  149                 AFLO_1OCT,      /* 1-byte address field length */
  150         },
  151         {                       /* cor2 */
  152                 0,              /* disable automatic DSR */
  153                 0,              /* disable automatic CTS */
  154                 0,              /* disable automatic RTS */
  155                 0,
  156                 CRC_INVERT,     /* use CRC V.41 */
  157                 0,
  158                 FCS_NOTPASS,    /* don't pass received CRC to the host */
  159                 0,
  160         },
  161         {                       /* cor3 */
  162                 0,              /* 0 pad characters sent */
  163                 IDLE_FLAG,      /* idle in flag */
  164                 0,              /* enable FCS */
  165                 FCSP_ONES,      /* FCS preset to all ones (V.41) */
  166                 SYNC_AA,        /* use AAh as sync char */
  167                 0,              /* disable pad characters */
  168         },
  169         0, 0, 0, 0,             /* clear rfar1-4 */
  170         POLY_V41,               /* use V.41 CRC polynomial */
  171 };
  172 
  173 static cx_opt_bisync_t opt_bisync_dflt = { /* default bisync options */
  174         {                       /* cor1 */
  175                 8-1,            /* 8-bit char length */
  176                 0,              /* don't ignore parity */
  177                 PARM_NOPAR,     /* no parity */
  178                 PAR_EVEN,       /* even parity */
  179         },
  180         {                       /* cor2 */
  181                 3-2,            /* send three SYN chars */
  182                 CRC_DONT_INVERT,/* don't invert CRC (CRC-16) */
  183                 0,              /* use ASCII, not EBCDIC */
  184                 0,              /* disable bcc append */
  185                 BCC_CRC16,      /* user CRC16, not LRC */
  186         },
  187         {                       /* cor3 */
  188                 0,              /* send 0 pad chars */
  189                 IDLE_FLAG,      /* idle in SYN */
  190                 0,              /* enable FCS */
  191                 FCSP_ZEROS,     /* FCS preset to all zeros (CRC-16) */
  192                 PAD_AA,         /* use AAh as pad char */
  193                 0,              /* disable pad characters */
  194         },
  195         {                       /* cor6 */
  196                 10,             /* DLE - disable special termination char */
  197         },
  198         POLY_16,                /* use CRC-16 polynomial */
  199 };
  200 
  201 static cx_opt_x21_t opt_x21_dflt = {   /* default x21 options */
  202         {                       /* cor1 */
  203                 8-1,            /* 8-bit char length */
  204                 0,              /* don't ignore parity */
  205                 PARM_NOPAR,     /* no parity */
  206                 PAR_EVEN,       /* even parity */
  207         },
  208         {                       /* cor2 */
  209                 0,
  210                 0,              /* disable embedded transmitter cmds */
  211                 0,
  212         },
  213         {                       /* cor3 */
  214                 0,
  215                 0,              /* disable special character detect */
  216                 0,              /* don't treat SYN as special condition */
  217                 0,              /* disable steady state detect */
  218                 X21SYN_2,       /* 2 SYN chars on receive are required */
  219         },
  220         {                       /* cor6 */
  221                 16,             /* SYN - standard SYN character */
  222         },
  223         0, 0, 0,                /* clear schr1-3 */
  224 };
  225 
  226 static int cx_probe_chip (int base);
  227 static void cx_setup_chip (cx_chip_t *c);
  228 static void cx_init_board (cx_board_t *b, int num, int port, int irq, int dma,
  229         int chain, int rev, int osc, int rev2, int osc2);
  230 static void cx_reinit_board (cx_board_t *b);
  231 
  232 /*
  233  * Wait for CCR to clear.
  234  */
  235 void cx_cmd (int base, int cmd)
  236 {
  237         unsigned short port = CCR(base);
  238         unsigned short count;
  239 
  240         /* Wait 10 msec for the previous command to complete. */
  241         for (count=0; inb(port) && count<20000; ++count)
  242                 continue;
  243 
  244         /* Issue the command. */
  245         outb (port, cmd);
  246 
  247         /* Wait 10 msec for the command to complete. */
  248         for (count=0; inb(port) && count<20000; ++count)
  249                 continue;
  250 }
  251 
  252 /*
  253  * Reset the chip.
  254  */
  255 static int cx_reset (unsigned short port)
  256 {
  257         int count;
  258 
  259         /* Wait up to 10 msec for revision code to appear after reset. */
  260         for (count=0; count<20000; ++count)
  261                 if (inb(GFRCR(port)) != 0)
  262                         break;
  263 
  264         cx_cmd (port, CCR_RSTALL);
  265 
  266         /* Firmware revision code should clear imediately. */
  267         /* Wait up to 10 msec for revision code to appear again. */
  268         for (count=0; count<20000; ++count)
  269                 if (inb(GFRCR(port)) != 0)
  270                         return (1);
  271 
  272         /* Reset failed. */
  273         return (0);
  274 }
  275 
  276 /*
  277  * Check if the CD2400 board is present at the given base port.
  278  */
  279 static int cx_probe_chained_board (int port, int *c0, int *c1)
  280 {
  281         int rev, i;
  282 
  283         /* Read and check the board revision code. */
  284         rev = inb (BSR(port));
  285         *c0 = *c1 = 0;
  286         switch (rev & BSR_VAR_MASK) {
  287         case CRONYX_100:        *c0 = 1;        break;
  288         case CRONYX_400:        *c1 = 1;        break;
  289         case CRONYX_500:        *c0 = *c1 = 1;  break;
  290         case CRONYX_410:        *c0 = 1;        break;
  291         case CRONYX_810:        *c0 = *c1 = 1;  break;
  292         case CRONYX_410s:       *c0 = 1;        break;
  293         case CRONYX_810s:       *c0 = *c1 = 1;  break;
  294         case CRONYX_440:        *c0 = 1;        break;
  295         case CRONYX_840:        *c0 = *c1 = 1;  break;
  296         case CRONYX_401:        *c0 = 1;        break;
  297         case CRONYX_801:        *c0 = *c1 = 1;  break;
  298         case CRONYX_401s:       *c0 = 1;        break;
  299         case CRONYX_801s:       *c0 = *c1 = 1;  break;
  300         case CRONYX_404:        *c0 = 1;        break;
  301         case CRONYX_703:        *c0 = *c1 = 1;  break;
  302         default:                return (0);     /* invalid variant code */
  303         }
  304 
  305         switch (rev & BSR_OSC_MASK) {
  306         case BSR_OSC_20:        /* 20 MHz */
  307         case BSR_OSC_18432:     /* 18.432 MHz */
  308                 break;
  309         default:
  310                 return (0);     /* oscillator frequency does not match */
  311         }
  312 
  313         for (i=2; i<0x10; i+=2)
  314                 if ((inb (BSR(port)+i) & BSR_REV_MASK) != (rev & BSR_REV_MASK))
  315                         return (0);     /* status changed? */
  316         return (1);
  317 }
  318 
  319 /*
  320  * Check if the CD2400 board is present at the given base port.
  321  */
  322 int
  323 cx_probe_board (int port)
  324 {
  325         int c0, c1, c2=0, c3=0, result;
  326 
  327         if (! cx_probe_chained_board (port, &c0, &c1))
  328                 return (0);     /* no board detected */
  329 
  330         if (! (inb (BSR(port)) & BSR_NOCHAIN)) { /* chained board attached */
  331                 if (! cx_probe_chained_board (port + 0x10, &c2, &c3))
  332                         return (0);     /* invalid chained board? */
  333 
  334                 if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN))
  335                         return (0);     /* invalid chained board flag? */
  336         }
  337 
  338         /* Turn off the reset bit. */
  339         outb (BCR0(port), BCR0_NORESET);
  340         if (c2 || c3)
  341                 outb (BCR0(port + 0x10), BCR0_NORESET);
  342 
  343         result = 1;
  344         if (c0 && ! cx_probe_chip (CS0(port)))
  345                 result = 0;     /* no CD2400 chip here */
  346         else if (c1 && ! cx_probe_chip (CS1(port)))
  347                 result = 0;     /* no second CD2400 chip */
  348         else if (c2 && ! cx_probe_chip (CS0(port + 0x10)))
  349                 result = 0;     /* no CD2400 chip on the slave board */
  350         else if (c3 && ! cx_probe_chip (CS1(port + 0x10)))
  351                 result = 0;     /* no second CD2400 chip on the slave board */
  352 
  353         /* Reset the controller. */
  354         outb (BCR0(port), 0);
  355         if (c2 || c3)
  356                 outb (BCR0(port + 0x10), 0);
  357 
  358         /* Yes, we really have valid CD2400 board. */
  359         return (result);
  360 }
  361 
  362 /*
  363  * Check if the CD2400 chip is present at the given base port.
  364  */
  365 static int cx_probe_chip (int base)
  366 {
  367         int rev, newrev, count;
  368 
  369         /* Wait up to 10 msec for revision code to appear after reset. */
  370         for (count=0; inb(GFRCR(base))==0; ++count)
  371                 if (count >= 20000)
  372                         return (0); /* reset failed */
  373 
  374         /* Read and check the global firmware revision code. */
  375         rev = inb (GFRCR(base));
  376         if (rev<REVCL_MIN || rev>REVCL_MAX)
  377                 return (0);     /* CD2400 revision does not match */
  378 
  379         /* Reset the chip. */
  380         if (! cx_reset (base))
  381                 return (0);
  382 
  383         /* Read and check the new global firmware revision code. */
  384         newrev = inb (GFRCR(base));
  385         if (newrev != rev)
  386                 return (0);     /* revision changed */
  387 
  388         /* Yes, we really have CD2400 chip here. */
  389         return (1);
  390 }
  391 
  392 /*
  393  * Probe and initialize the board structure.
  394  */
  395 void cx_init (cx_board_t *b, int num, int port, int irq, int dma)
  396 {
  397         int rev, chain, rev2;
  398 
  399         rev = inb (BSR(port));
  400         chain = !(rev & BSR_NOCHAIN);
  401         rev2 = chain ? inb (BSR(port+0x10)) : 0;
  402         cx_init_board (b, num, port, irq, dma, chain,
  403                 (rev & BSR_VAR_MASK), (rev & BSR_OSC_MASK),
  404                 (rev2 & BSR_VAR_MASK), (rev2 & BSR_OSC_MASK));
  405 }
  406 
  407 /*
  408  * Initialize the board structure, given the type of the board.
  409  */
  410 static void
  411 cx_init_board (cx_board_t *b, int num, int port, int irq, int dma,
  412         int chain, int rev, int osc, int rev2, int osc2)
  413 {
  414         cx_chan_t *c;
  415         int i, c0, c1;
  416 
  417         /* Initialize board structure. */
  418         b->port = port;
  419         b->num = num;
  420         b->irq = irq;
  421         b->dma = dma;
  422         b->if0type = b->if8type = cx_iftype;
  423 
  424         /* Set channels 0 and 8 mode, set DMA and IRQ. */
  425         b->bcr0 = b->bcr0b = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq];
  426 
  427         /* Clear DTR[0..3] and DTR[8..12]. */
  428         b->bcr1 = b->bcr1b = 0;
  429 
  430         /* Initialize chip structures. */
  431         for (i=0; i<NCHIP; ++i) {
  432                 b->chip[i].num = i;
  433                 b->chip[i].board = b;
  434         }
  435         b->chip[0].port = CS0(port);
  436         b->chip[1].port = CS1(port);
  437         b->chip[2].port = CS0(port+0x10);
  438         b->chip[3].port = CS1(port+0x10);
  439 
  440         /*------------------ Master board -------------------*/
  441 
  442         /* Read and check the board revision code. */
  443         c0 = c1 = 0;
  444         b->name[0] = 0;
  445         switch (rev) {
  446         case CRONYX_100:  strcpy (b->name, "100");  c0 = 1;      break;
  447         case CRONYX_400:  strcpy (b->name, "400");  c1 = 1;      break;
  448         case CRONYX_500:  strcpy (b->name, "500");  c0 = c1 = 1; break;
  449         case CRONYX_410:  strcpy (b->name, "410");  c0 = 1;      break;
  450         case CRONYX_810:  strcpy (b->name, "810");  c0 = c1 = 1; break;
  451         case CRONYX_410s: strcpy (b->name, "410s"); c0 = 1;      break;
  452         case CRONYX_810s: strcpy (b->name, "810s"); c0 = c1 = 1; break;
  453         case CRONYX_440:  strcpy (b->name, "440");  c0 = 1;      break;
  454         case CRONYX_840:  strcpy (b->name, "840");  c0 = c1 = 1; break;
  455         case CRONYX_401:  strcpy (b->name, "401");  c0 = 1;      break;
  456         case CRONYX_801:  strcpy (b->name, "801");  c0 = c1 = 1; break;
  457         case CRONYX_401s: strcpy (b->name, "401s"); c0 = 1;      break;
  458         case CRONYX_801s: strcpy (b->name, "801s"); c0 = c1 = 1; break;
  459         case CRONYX_404:  strcpy (b->name, "404");  c0 = 1;      break;
  460         case CRONYX_703:  strcpy (b->name, "703");  c0 = c1 = 1; break;
  461         }
  462 
  463         switch (osc) {
  464         default:
  465         case BSR_OSC_20: /* 20 MHz */
  466                 b->chip[0].oscfreq = b->chip[1].oscfreq = 20000000L;
  467                 strcat (b->name, "a");
  468                 break;
  469         case BSR_OSC_18432: /* 18.432 MHz */
  470                 b->chip[0].oscfreq = b->chip[1].oscfreq = 18432000L;
  471                 strcat (b->name, "b");
  472                 break;
  473         }
  474 
  475         if (! c0)
  476                 b->chip[0].port = 0;
  477         if (! c1)
  478                 b->chip[1].port = 0;
  479 
  480         /*------------------ Slave board -------------------*/
  481 
  482         if (! chain) {
  483                 b->chip[2].oscfreq = b->chip[3].oscfreq = 0L;
  484                 b->chip[2].port = b->chip[3].port = 0;
  485         } else {
  486                 /* Read and check the board revision code. */
  487                 c0 = c1 = 0;
  488                 strcat (b->name, "/");
  489                 switch (rev2) {
  490                 case CRONYX_100:  strcat(b->name,"100");  c0=1;    break;
  491                 case CRONYX_400:  strcat(b->name,"400");  c1=1;    break;
  492                 case CRONYX_500:  strcat(b->name,"500");  c0=c1=1; break;
  493                 case CRONYX_410:  strcat(b->name,"410");  c0=1;    break;
  494                 case CRONYX_810:  strcat(b->name,"810");  c0=c1=1; break;
  495                 case CRONYX_410s: strcat(b->name,"410s"); c0=1;    break;
  496                 case CRONYX_810s: strcat(b->name,"810s"); c0=c1=1; break;
  497                 case CRONYX_440:  strcat(b->name,"440");  c0=1;    break;
  498                 case CRONYX_840:  strcat(b->name,"840");  c0=c1=1; break;
  499                 case CRONYX_401:  strcat(b->name,"401");  c0=1;    break;
  500                 case CRONYX_801:  strcat(b->name,"801");  c0=c1=1; break;
  501                 case CRONYX_401s: strcat(b->name,"401s"); c0=1;    break;
  502                 case CRONYX_801s: strcat(b->name,"801s"); c0=c1=1; break;
  503                 case CRONYX_404:  strcat(b->name,"404");  c0=1;    break;
  504                 case CRONYX_703:  strcat(b->name,"703");  c0=c1=1; break;
  505                 }
  506 
  507                 switch (osc2) {
  508                 default:
  509                 case BSR_OSC_20: /* 20 MHz */
  510                         b->chip[2].oscfreq = b->chip[3].oscfreq = 20000000L;
  511                         strcat (b->name, "a");
  512                         break;
  513                 case BSR_OSC_18432: /* 18.432 MHz */
  514                         b->chip[2].oscfreq = b->chip[3].oscfreq = 18432000L;
  515                         strcat (b->name, "b");
  516                         break;
  517                 }
  518 
  519                 if (! c0)
  520                         b->chip[2].port = 0;
  521                 if (! c1)
  522                         b->chip[3].port = 0;
  523         }
  524 
  525         /* Initialize channel structures. */
  526         for (i=0; i<NCHAN; ++i) {
  527                 cx_chan_t *c = b->chan + i;
  528 
  529                 c->num = i;
  530                 c->board = b;
  531                 c->chip = b->chip + i*NCHIP/NCHAN;
  532                 c->stat = b->stat + i;
  533                 c->type = T_NONE;
  534         }
  535 
  536         /*------------------ Master board -------------------*/
  537 
  538         switch (rev) {
  539         case CRONYX_400:
  540                 break;
  541         case CRONYX_100:
  542         case CRONYX_500:
  543                 b->chan[0].type = T_UNIV_RS232;
  544                 break;
  545         case CRONYX_410:
  546         case CRONYX_810:
  547                 b->chan[0].type = T_UNIV_V35;
  548                 for (i=1; i<4; ++i)
  549                         b->chan[i].type = T_UNIV_RS232;
  550                 break;
  551         case CRONYX_410s:
  552         case CRONYX_810s:
  553                 b->chan[0].type = T_UNIV_V35;
  554                 for (i=1; i<4; ++i)
  555                         b->chan[i].type = T_SYNC_RS232;
  556                 break;
  557         case CRONYX_440:
  558         case CRONYX_840:
  559                 b->chan[0].type = T_UNIV_V35;
  560                 for (i=1; i<4; ++i)
  561                         b->chan[i].type = T_SYNC_V35;
  562                 break;
  563         case CRONYX_401:
  564         case CRONYX_801:
  565                 b->chan[0].type = T_UNIV_RS449;
  566                 for (i=1; i<4; ++i)
  567                         b->chan[i].type = T_UNIV_RS232;
  568                 break;
  569         case CRONYX_401s:
  570         case CRONYX_801s:
  571                 b->chan[0].type = T_UNIV_RS449;
  572                 for (i=1; i<4; ++i)
  573                         b->chan[i].type = T_SYNC_RS232;
  574                 break;
  575         case CRONYX_404:
  576                 b->chan[0].type = T_UNIV_RS449;
  577                 for (i=1; i<4; ++i)
  578                         b->chan[i].type = T_SYNC_RS449;
  579                 break;
  580         case CRONYX_703:
  581                 b->chan[0].type = T_UNIV_RS449;
  582                 for (i=1; i<3; ++i)
  583                         b->chan[i].type = T_SYNC_RS449;
  584                 break;
  585         }
  586 
  587         /* If the second controller is present,
  588          * then we have 4..7 channels in async. mode */
  589         if (b->chip[1].port)
  590                 for (i=4; i<8; ++i)
  591                         b->chan[i].type = T_UNIV_RS232;
  592 
  593         /*------------------ Slave board -------------------*/
  594 
  595         if (chain) {
  596                 switch (rev2) {
  597                 case CRONYX_400:
  598                         break;
  599                 case CRONYX_100:
  600                 case CRONYX_500:
  601                         b->chan[8].type = T_UNIV_RS232;
  602                         break;
  603                 case CRONYX_410:
  604                 case CRONYX_810:
  605                         b->chan[8].type = T_UNIV_V35;
  606                         for (i=9; i<12; ++i)
  607                                 b->chan[i].type = T_UNIV_RS232;
  608                         break;
  609                 case CRONYX_410s:
  610                 case CRONYX_810s:
  611                         b->chan[8].type = T_UNIV_V35;
  612                         for (i=9; i<12; ++i)
  613                                 b->chan[i].type = T_SYNC_RS232;
  614                         break;
  615                 case CRONYX_440:
  616                 case CRONYX_840:
  617                         b->chan[8].type = T_UNIV_V35;
  618                         for (i=9; i<12; ++i)
  619                                 b->chan[i].type = T_SYNC_V35;
  620                         break;
  621                 case CRONYX_401:
  622                 case CRONYX_801:
  623                         b->chan[8].type = T_UNIV_RS449;
  624                         for (i=9; i<12; ++i)
  625                                 b->chan[i].type = T_UNIV_RS232;
  626                         break;
  627                 case CRONYX_401s:
  628                 case CRONYX_801s:
  629                         b->chan[8].type = T_UNIV_RS449;
  630                         for (i=9; i<12; ++i)
  631                                 b->chan[i].type = T_UNIV_RS232;
  632                         break;
  633                 case CRONYX_404:
  634                         b->chan[8].type = T_UNIV_RS449;
  635                         for (i=9; i<12; ++i)
  636                                 b->chan[i].type = T_SYNC_RS449;
  637                         break;
  638                 case CRONYX_703:
  639                         b->chan[8].type = T_UNIV_RS449;
  640                         for (i=9; i<11; ++i)
  641                                 b->chan[i].type = T_SYNC_RS449;
  642                         break;
  643                 }
  644 
  645                 /* If the second controller is present,
  646                  * then we have 4..7 channels in async. mode */
  647                 if (b->chip[3].port)
  648                         for (i=12; i<16; ++i)
  649                                 b->chan[i].type = T_UNIV_RS232;
  650         }
  651 
  652         b->nuniv = b->nsync = b->nasync = 0;
  653         for (c=b->chan; c<b->chan+NCHAN; ++c)
  654                 switch (c->type) {
  655                 case T_ASYNC:      ++b->nasync; break;
  656                 case T_UNIV_RS232:
  657                 case T_UNIV_RS449:
  658                 case T_UNIV_V35:   ++b->nuniv;  break;
  659                 case T_SYNC_RS232:
  660                 case T_SYNC_V35:
  661                 case T_SYNC_RS449: ++b->nsync;  break;
  662                 }
  663 
  664         cx_reinit_board (b);
  665 }
  666 
  667 /*
  668  * Reinitialize all channels, using new options and baud rate.
  669  */
  670 static void
  671 cx_reinit_board (cx_board_t *b)
  672 {
  673         cx_chan_t *c;
  674 
  675         b->if0type = b->if8type = cx_iftype;
  676         for (c=b->chan; c<b->chan+NCHAN; ++c) {
  677                 switch (c->type) {
  678                 default:
  679                 case T_NONE:
  680                         continue;
  681                 case T_UNIV_RS232:
  682                 case T_UNIV_RS449:
  683                 case T_UNIV_V35:
  684                         c->mode = (cx_univ_mode == M_ASYNC) ?
  685                                 M_ASYNC : cx_sync_mode;
  686                         break;
  687                 case T_SYNC_RS232:
  688                 case T_SYNC_V35:
  689                 case T_SYNC_RS449:
  690                         c->mode = cx_sync_mode;
  691                         break;
  692                 case T_ASYNC:
  693                         c->mode = M_ASYNC;
  694                         break;
  695                 }
  696                 c->rxbaud = cx_rxbaud;
  697                 c->txbaud = cx_txbaud;
  698                 c->opt = chan_opt_dflt;
  699                 c->aopt = opt_async_dflt;
  700                 c->hopt = opt_hdlc_dflt;
  701                 c->bopt = opt_bisync_dflt;
  702                 c->xopt = opt_x21_dflt;
  703         }
  704 }
  705 
  706 /*
  707  * Set up the board.
  708  */
  709 void cx_setup_board (cx_board_t *b)
  710 {
  711         int i;
  712 
  713         /* Disable DMA channel. */
  714         outb (DMA_MASK, (b->dma & 3) | DMA_MASK_CLEAR);
  715 
  716         /* Reset the controller. */
  717         outb (BCR0(b->port), 0);
  718         if (b->chip[2].port || b->chip[3].port)
  719                 outb (BCR0(b->port+0x10), 0);
  720 
  721         /*
  722          * Set channels 0 and 8 to RS232 async. mode.
  723          * Enable DMA and IRQ.
  724          */
  725         outb (BCR0(b->port), b->bcr0);
  726         if (b->chip[2].port || b->chip[3].port)
  727                 outb (BCR0(b->port+0x10), b->bcr0b);
  728 
  729         /* Clear DTR[0..3] and DTR[8..12]. */
  730         outw (BCR1(b->port), b->bcr1);
  731         if (b->chip[2].port || b->chip[3].port)
  732                 outw (BCR1(b->port+0x10), b->bcr1b);
  733 
  734         /* Initialize all controllers. */
  735         for (i=0; i<NCHIP; ++i)
  736                 if (b->chip[i].port)
  737                         cx_setup_chip (b->chip + i);
  738 
  739         /* Set up DMA channel to master mode. */
  740         outb (DMA_MODE, (b->dma & 3) | DMA_MODE_MASTER);
  741 
  742         /* Enable DMA channel. */
  743         outb (DMA_MASK, b->dma & 3);
  744 
  745         /* Initialize all channels. */
  746         for (i=0; i<NCHAN; ++i)
  747                 if (b->chan[i].type != T_NONE)
  748                         cx_setup_chan (b->chan + i);
  749 }
  750 
  751 /*
  752  * Initialize the board.
  753  */
  754 static void cx_setup_chip (cx_chip_t *c)
  755 {
  756         /* Reset the chip. */
  757         cx_reset (c->port);
  758 
  759         /*
  760          * Set all interrupt level registers to the same value.
  761          * This enables the internal CD2400 priority scheme.
  762          */
  763         outb (RPILR(c->port), BRD_INTR_LEVEL);
  764         outb (TPILR(c->port), BRD_INTR_LEVEL);
  765         outb (MPILR(c->port), BRD_INTR_LEVEL);
  766 
  767         /* Set bus error count to zero. */
  768         outb (BERCNT(c->port), 0);
  769 
  770         /* Set 16-bit DMA mode. */
  771         outb (DMR(c->port), 0);
  772 
  773         /* Set timer period register to 1 msec (approximately). */
  774         outb (TPR(c->port), 10);
  775 }
  776 
  777 /*
  778  * Initialize the CD2400 channel.
  779  */
  780 void cx_setup_chan (cx_chan_t *c)
  781 {
  782         unsigned short port = c->chip->port;
  783         int clock, period;
  784 
  785         if (c->num == 0) {
  786                 c->board->bcr0 &= ~BCR0_UMASK;
  787                 if (c->mode != M_ASYNC)
  788                         c->board->bcr0 |= BCR0_UM_SYNC;
  789                 if (c->board->if0type &&
  790                     (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
  791                         c->board->bcr0 |= BCR0_UI_RS449;
  792                 outb (BCR0(c->board->port), c->board->bcr0);
  793         } else if (c->num == 8) {
  794                 c->board->bcr0b &= ~BCR0_UMASK;
  795                 if (c->mode != M_ASYNC)
  796                         c->board->bcr0b |= BCR0_UM_SYNC;
  797                 if (c->board->if8type &&
  798                     (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
  799                         c->board->bcr0b |= BCR0_UI_RS449;
  800                 outb (BCR0(c->board->port+0x10), c->board->bcr0b);
  801         }
  802 
  803         /* set current channel number */
  804         outb (CAR(port), c->num & 3);
  805 
  806         /* reset the channel */
  807         cx_cmd (port, CCR_CLRCH);
  808 
  809         /* set LIVR to contain the board and channel numbers */
  810         outb (LIVR(port), c->board->num << 6 | c->num << 2);
  811 
  812         /* clear DTR, RTS, set TXCout/DTR pin */
  813         outb (MSVR_RTS(port), 0);
  814         outb (MSVR_DTR(port), c->mode==M_ASYNC ? 0 : MSV_TXCOUT);
  815 
  816         switch (c->mode) {      /* initialize the channel mode */
  817         case M_ASYNC:
  818                 /* set receiver timeout register */
  819                 outw (RTPR(port), 10);          /* 10 msec, see TPR */
  820 
  821                 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_ASYNC);
  822                 outb (COR1(port), BYTE c->aopt.cor1);
  823                 outb (COR2(port), BYTE c->aopt.cor2);
  824                 outb (COR3(port), BYTE c->aopt.cor3);
  825                 outb (COR6(port), BYTE c->aopt.cor6);
  826                 outb (COR7(port), BYTE c->aopt.cor7);
  827                 outb (SCHR1(port), c->aopt.schr1);
  828                 outb (SCHR2(port), c->aopt.schr2);
  829                 outb (SCHR3(port), c->aopt.schr3);
  830                 outb (SCHR4(port), c->aopt.schr4);
  831                 outb (SCRL(port), c->aopt.scrl);
  832                 outb (SCRH(port), c->aopt.scrh);
  833                 outb (LNXT(port), c->aopt.lnxt);
  834                 break;
  835         case M_HDLC:
  836                 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_HDLC);
  837                 outb (COR1(port), BYTE c->hopt.cor1);
  838                 outb (COR2(port), BYTE c->hopt.cor2);
  839                 outb (COR3(port), BYTE c->hopt.cor3);
  840                 outb (RFAR1(port), c->hopt.rfar1);
  841                 outb (RFAR2(port), c->hopt.rfar2);
  842                 outb (RFAR3(port), c->hopt.rfar3);
  843                 outb (RFAR4(port), c->hopt.rfar4);
  844                 outb (CPSR(port), c->hopt.cpsr);
  845                 break;
  846         case M_BISYNC:
  847                 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_BISYNC);
  848                 outb (COR1(port), BYTE c->bopt.cor1);
  849                 outb (COR2(port), BYTE c->bopt.cor2);
  850                 outb (COR3(port), BYTE c->bopt.cor3);
  851                 outb (COR6(port), BYTE c->bopt.cor6);
  852                 outb (CPSR(port), c->bopt.cpsr);
  853                 break;
  854         case M_X21:
  855                 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_X21);
  856                 outb (COR1(port), BYTE c->xopt.cor1);
  857                 outb (COR2(port), BYTE c->xopt.cor2);
  858                 outb (COR3(port), BYTE c->xopt.cor3);
  859                 outb (COR6(port), BYTE c->xopt.cor6);
  860                 outb (SCHR1(port), c->xopt.schr1);
  861                 outb (SCHR2(port), c->xopt.schr2);
  862                 outb (SCHR3(port), c->xopt.schr3);
  863                 break;
  864         }
  865 
  866         /* set mode-independent options */
  867         outb (COR4(port), BYTE c->opt.cor4);
  868         outb (COR5(port), BYTE c->opt.cor5);
  869 
  870         /* set up receiver clock values */
  871         if (c->mode == M_ASYNC || c->opt.rcor.dpll) {
  872                 cx_clock (c->chip->oscfreq, c->rxbaud, &clock, &period);
  873                 c->opt.rcor.clk = clock;
  874         } else {
  875                 c->opt.rcor.clk = CLK_EXT;
  876                 period = 1;
  877         }
  878         outb (RCOR(port), BYTE c->opt.rcor);
  879         outb (RBPR(port), period);
  880 
  881         /* set up transmitter clock values */
  882         if (c->mode == M_ASYNC || !c->opt.tcor.ext1x) {
  883                 unsigned ext1x = c->opt.tcor.ext1x;
  884                 c->opt.tcor.ext1x = 0;
  885                 cx_clock (c->chip->oscfreq, c->txbaud, &clock, &period);
  886                 c->opt.tcor.clk = clock;
  887                 c->opt.tcor.ext1x = ext1x;
  888         } else {
  889                 c->opt.tcor.clk = CLK_EXT;
  890                 period = 1;
  891         }
  892         outb (TCOR(port), BYTE c->opt.tcor);
  893         outb (TBPR(port), period);
  894 
  895         /* set receiver A buffer physical address */
  896         c->arphys = vtophys (c->arbuf);
  897         outw (ARBADRU(port), (unsigned short) (c->arphys>>16));
  898         outw (ARBADRL(port), (unsigned short) c->arphys);
  899 
  900         /* set receiver B buffer physical address */
  901         c->brphys = vtophys (c->brbuf);
  902         outw (BRBADRU(port), (unsigned short) (c->brphys>>16));
  903         outw (BRBADRL(port), (unsigned short) c->brphys);
  904 
  905         /* set transmitter A buffer physical address */
  906         c->atphys = vtophys (c->atbuf);
  907         outw (ATBADRU(port), (unsigned short) (c->atphys>>16));
  908         outw (ATBADRL(port), (unsigned short) c->atphys);
  909 
  910         /* set transmitter B buffer physical address */
  911         c->btphys = vtophys (c->btbuf);
  912         outw (BTBADRU(port), (unsigned short) (c->btphys>>16));
  913         outw (BTBADRL(port), (unsigned short) c->btphys);
  914 
  915         c->dtr = 0;
  916         c->rts = 0;
  917 }
  918 
  919 /*
  920  * Control DTR signal for the channel.
  921  * Turn it on/off.
  922  */
  923 void cx_chan_dtr (cx_chan_t *c, int on)
  924 {
  925         c->dtr = on ? 1 : 0;
  926 
  927         if (c->mode == M_ASYNC) {
  928                 outb (CAR(c->chip->port), c->num & 3);
  929                 outb (MSVR_DTR(c->chip->port), on ? MSV_DTR : 0);
  930                 return;
  931         }
  932 
  933         switch (c->num) {
  934         default:
  935                 /* Channels 4..7 and 12..15 in syncronous mode
  936                  * have no DTR signal. */
  937                 break;
  938 
  939         case 1: case 2:  case 3:
  940                 if (c->type == T_UNIV_RS232)
  941                         break;
  942         case 0:
  943                 if (on)
  944                         c->board->bcr1 |= 0x100 << c->num;
  945                 else
  946                         c->board->bcr1 &= ~(0x100 << c->num);
  947                 outw (BCR1(c->board->port), c->board->bcr1);
  948                 break;
  949 
  950         case 9: case 10: case 11:
  951                 if (c->type == T_UNIV_RS232)
  952                         break;
  953         case 8:
  954                 if (on)
  955                         c->board->bcr1b |= 0x100 << (c->num & 3);
  956                 else
  957                         c->board->bcr1b &= ~(0x100 << (c->num & 3));
  958                 outw (BCR1(c->board->port+0x10), c->board->bcr1b);
  959                 break;
  960         }
  961 }
  962 
  963 /*
  964  * Control RTS signal for the channel.
  965  * Turn it on/off.
  966  */
  967 void
  968 cx_chan_rts (cx_chan_t *c, int on)
  969 {
  970         c->rts = on ? 1 : 0;
  971         outb (CAR(c->chip->port), c->num & 3);
  972         outb (MSVR_RTS(c->chip->port), on ? MSV_RTS : 0);
  973 }
  974 
  975 
  976 /*
  977  * Get the state of CARRIER signal of the channel.
  978  */
  979 int
  980 cx_chan_cd (cx_chan_t *c)
  981 {
  982         unsigned char sigval;
  983 
  984         if (c->mode == M_ASYNC) {
  985                 outb (CAR(c->chip->port), c->num & 3);
  986                 return (inb (MSVR(c->chip->port)) & MSV_CD ? 1 : 0);
  987         }
  988 
  989         /*
  990          * Channels 4..7 and 12..15 don't have CD signal available.
  991          */
  992         switch (c->num) {
  993         default:
  994                 return (1);
  995 
  996         case 1: case 2:  case 3:
  997                 if (c->type == T_UNIV_RS232)
  998                         return (1);
  999         case 0:
 1000                 sigval = inw (BSR(c->board->port)) >> 8;
 1001                 break;
 1002 
 1003         case 9: case 10: case 11:
 1004                 if (c->type == T_UNIV_RS232)
 1005                         return (1);
 1006         case 8:
 1007                 sigval = inw (BSR(c->board->port+0x10)) >> 8;
 1008                 break;
 1009         }
 1010         return (~sigval >> 4 >> (c->num & 3) & 1);
 1011 }
 1012 
 1013 /*
 1014  * Compute CD2400 clock values.
 1015  */
 1016 void cx_clock (long hz, long ba, int *clk, int *div)
 1017 {
 1018         static short clocktab[] = { 8, 32, 128, 512, 2048, 0 };
 1019 
 1020         for (*clk=0; clocktab[*clk]; ++*clk) {
 1021                 long c = ba * clocktab[*clk];
 1022                 if (hz <= c*256) {
 1023                         *div = (2 * hz + c) / (2 * c) - 1;
 1024                         return;
 1025                 }
 1026         }
 1027         /* Incorrect baud rate.  Return some meaningful values. */
 1028         *clk = 0;
 1029         *div = 255;
 1030 }

Cache object: 227d834a1e76d85acd9bf90bb0fd7982


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