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