]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/isa/cronyx.c
This commit was generated by cvs2svn to compensate for changes in r74481,
[FreeBSD/FreeBSD.git] / sys / i386 / isa / cronyx.c
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$
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 }