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

Cache object: a14b7f64eb2111ce9afc8a1d37f61083


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