1139749Simp/*-
2123120Simp * Low-level subroutines for Cronyx-Sigma adapter.
3123120Simp *
4123120Simp * Copyright (C) 1994-2000 Cronyx Engineering.
5123120Simp * Author: Serge Vakulenko, <vak@cronyx.ru>
6123120Simp *
7123120Simp * This software is distributed with NO WARRANTIES, not even the implied
8123120Simp * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9123120Simp *
10123120Simp * Authors grant any other persons or organisations permission to use
11123120Simp * or modify this software as long as this message is kept with the software,
12123120Simp * all derivative works or modified versions.
13123120Simp *
14123120Simp * Cronyx Id: csigma.c,v 1.1.2.1 2003/11/12 17:13:41 rik Exp $
15123120Simp * $FreeBSD: releng/10.2/sys/dev/cx/csigma.c 250460 2013-05-10 16:41:26Z eadler $
16123120Simp */
17123120Simp#include <dev/cx/machdep.h>
18123120Simp#include <dev/cx/cxddk.h>
19123120Simp#include <dev/cx/cxreg.h>
20123120Simp#include <dev/cx/cronyxfw.h>
21123120Simp
22123120Simp#define DMA_MASK	0xd4	/* DMA mask register */
23123120Simp#define DMA_MASK_CLEAR	0x04	/* DMA clear mask */
24123120Simp#define DMA_MODE	0xd6	/* DMA mode register */
25123120Simp#define DMA_MODE_MASTER	0xc0	/* DMA master mode */
26123120Simp
27123120Simp#define BYTE *(unsigned char*)&
28123120Simp
29123120Simpstatic unsigned char irqmask [] = {
30123120Simp	BCR0_IRQ_DIS,	BCR0_IRQ_DIS,	BCR0_IRQ_DIS,	BCR0_IRQ_3,
31123120Simp	BCR0_IRQ_DIS,	BCR0_IRQ_5,	BCR0_IRQ_DIS,	BCR0_IRQ_7,
32123120Simp	BCR0_IRQ_DIS,	BCR0_IRQ_DIS,	BCR0_IRQ_10,	BCR0_IRQ_11,
33123120Simp	BCR0_IRQ_12,	BCR0_IRQ_DIS,	BCR0_IRQ_DIS,	BCR0_IRQ_15,
34123120Simp};
35123120Simp
36123120Simpstatic unsigned char dmamask [] = {
37123120Simp	BCR0_DMA_DIS,	BCR0_DMA_DIS,	BCR0_DMA_DIS,	BCR0_DMA_DIS,
38123120Simp	BCR0_DMA_DIS,	BCR0_DMA_5,	BCR0_DMA_6,	BCR0_DMA_7,
39123120Simp};
40123120Simp
41123120Simp/* standard base port set */
42123120Simpstatic short porttab [] = {
43123120Simp	0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
44123120Simp	0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0
45123120Simp};
46123120Simp
47123120Simp/* valid IRQs and DRQs */
48123120Simpstatic short irqtab [] = { 3, 5, 7, 10, 11, 12, 15, 0 };
49123120Simpstatic short dmatab [] = { 5, 6, 7, 0 };
50123120Simp
51123120Simpstatic int valid (short value, short *list)
52123120Simp{
53123120Simp	while (*list)
54123120Simp		if (value == *list++)
55123120Simp			return 1;
56123120Simp	return 0;
57123120Simp}
58123120Simp
59123120Simplong cx_rxbaud = 9600;		/* receiver baud rate */
60123120Simplong cx_txbaud = 9600;		/* transmitter baud rate */
61123120Simp
62123120Simpint cx_univ_mode = M_HDLC;	/* univ. chan. mode: async or sync */
63123120Simpint cx_sync_mode = M_HDLC;	/* sync. chan. mode: HDLC, Bisync or X.21 */
64123120Simpint cx_iftype = 0;		/* univ. chan. interface: upper/lower */
65123120Simp
66123120Simpstatic int cx_probe_chip (port_t base);
67123120Simpstatic void cx_setup_chip (cx_chan_t *c);
68123120Simp
69123120Simp/*
70123120Simp * Wait for CCR to clear.
71123120Simp */
72123120Simpvoid cx_cmd (port_t base, int cmd)
73123120Simp{
74123120Simp	port_t port = CCR(base);
75123120Simp	int count;
76123120Simp
77123120Simp	/* Wait 10 msec for the previous command to complete. */
78123120Simp	for (count=0; inb(port) && count<20000; ++count)
79123120Simp		continue;
80123120Simp
81123120Simp	/* Issue the command. */
82123120Simp	outb (port, cmd);
83123120Simp
84123120Simp	/* Wait 10 msec for the command to complete. */
85123120Simp	for (count=0; inb(port) && count<20000; ++count)
86123120Simp		continue;
87123120Simp}
88123120Simp
89123120Simp/*
90123120Simp * Reset the chip.
91123120Simp */
92123120Simpstatic int cx_reset (port_t port)
93123120Simp{
94123120Simp	int count;
95123120Simp
96123120Simp	/* Wait up to 10 msec for revision code to appear after reset. */
97123120Simp	for (count=0; count<20000; ++count)
98123120Simp		if (inb(GFRCR(port)) != 0)
99123120Simp			break;
100123120Simp
101123120Simp	cx_cmd (port, CCR_RSTALL);
102123120Simp
103123120Simp	/* Firmware revision code should clear imediately. */
104123120Simp	/* Wait up to 10 msec for revision code to appear again. */
105123120Simp	for (count=0; count<20000; ++count)
106123120Simp		if (inb(GFRCR(port)) != 0)
107123120Simp			return (1);
108123120Simp
109123120Simp	/* Reset failed. */
110123120Simp	return (0);
111123120Simp}
112123120Simp
113123120Simpint cx_download (port_t port, const unsigned char *firmware, long bits,
114123120Simp	const cr_dat_tst_t *tst)
115123120Simp{
116123120Simp	unsigned char cr2, sr;
117123120Simp	long i, n, maxn = (bits + 7) / 8;
118123120Simp	int v, b;
119123120Simp
120123120Simp	inb (BDET(port));
121123120Simp	for (i=n=0; n<maxn; ++n) {
122123120Simp		v = ((firmware[n] ^ ' ') << 1) | (firmware[n] >> 7 & 1);
123123120Simp		for (b=0; b<7; b+=2, i+=2) {
124123120Simp			if (i >= bits)
125123120Simp				break;
126123120Simp			cr2 = 0;
127123120Simp			if (v >> b & 1) cr2 |= BCR2_TMS;
128123120Simp			if (v >> b & 2) cr2 |= BCR2_TDI;
129123120Simp			outb (BCR2(port), cr2);
130123120Simp			sr = inb (BSR(port));
131123120Simp			outb (BCR0(port), BCR0800_TCK);
132123120Simp			outb (BCR0(port), 0);
133123120Simp			if (i >= tst->end)
134123120Simp				++tst;
135123120Simp			if (i >= tst->start && (sr & BSR800_LERR))
136123120Simp				return (0);
137123120Simp		}
138123120Simp	}
139123120Simp	return (1);
140123120Simp}
141123120Simp
142123120Simp/*
143123120Simp * Check if the Sigma-XXX board is present at the given base port.
144123120Simp */
145123120Simpstatic int cx_probe_chained_board (port_t port, int *c0, int *c1)
146123120Simp{
147123120Simp	int rev, i;
148123120Simp
149123120Simp	/* Read and check the board revision code. */
150123120Simp	rev = inb (BSR(port));
151123120Simp	*c0 = *c1 = 0;
152123120Simp	switch (rev & BSR_VAR_MASK) {
153123120Simp	case CRONYX_100:	*c0 = 1;	break;
154123120Simp	case CRONYX_400:	*c1 = 1;	break;
155123120Simp	case CRONYX_500:	*c0 = *c1 = 1;	break;
156123120Simp	case CRONYX_410:	*c0 = 1;	break;
157123120Simp	case CRONYX_810:	*c0 = *c1 = 1;	break;
158123120Simp	case CRONYX_410s:	*c0 = 1;	break;
159123120Simp	case CRONYX_810s:	*c0 = *c1 = 1;	break;
160123120Simp	case CRONYX_440:	*c0 = 1;	break;
161123120Simp	case CRONYX_840:	*c0 = *c1 = 1;	break;
162123120Simp	case CRONYX_401:	*c0 = 1;	break;
163123120Simp	case CRONYX_801:	*c0 = *c1 = 1;	break;
164123120Simp	case CRONYX_401s:	*c0 = 1;	break;
165123120Simp	case CRONYX_801s:	*c0 = *c1 = 1;	break;
166123120Simp	case CRONYX_404:	*c0 = 1;	break;
167123120Simp	case CRONYX_703:	*c0 = *c1 = 1;	break;
168123120Simp	default:		return (0);	/* invalid variant code */
169123120Simp	}
170123120Simp
171123120Simp	switch (rev & BSR_OSC_MASK) {
172123120Simp	case BSR_OSC_20:	/* 20 MHz */
173123120Simp	case BSR_OSC_18432:	/* 18.432 MHz */
174123120Simp		break;
175123120Simp	default:
176123120Simp		return (0);	/* oscillator frequency does not match */
177123120Simp	}
178123120Simp
179123120Simp	for (i=2; i<0x10; i+=2)
180123120Simp		if ((inb (BSR(port)+i) & BSR_REV_MASK) != (rev & BSR_REV_MASK))
181123120Simp			return (0);	/* status changed? */
182123120Simp	return (1);
183123120Simp}
184123120Simp
185123120Simp/*
186123120Simp * Check if the Sigma-800 board is present at the given base port.
187123120Simp * Read board status register 1 and check identification bits
188123120Simp * which should invert every next read.
189123120Simp */
190123120Simpstatic int cx_probe_800_chained_board (port_t port)
191123120Simp{
192123120Simp	unsigned char det, odet;
193123120Simp	int i;
194123120Simp
195123120Simp	odet = inb (BDET(port));
196123120Simp	if ((odet & (BDET_IB | BDET_IB_NEG)) != BDET_IB &&
197123120Simp	    (odet & (BDET_IB | BDET_IB_NEG)) != BDET_IB_NEG)
198123120Simp		return (0);
199123120Simp	for (i=0; i<100; ++i) {
200123120Simp		det = inb (BDET(port));
201123120Simp		if (((det ^ odet) & (BDET_IB | BDET_IB_NEG)) !=
202123120Simp		    (BDET_IB | BDET_IB_NEG))
203123120Simp			return (0);
204123120Simp		odet = det;
205123120Simp	}
206123120Simp	/* Reset the controller. */
207123120Simp	outb (BCR0(port), 0);
208123120Simp	outb (BCR1(port), 0);
209123120Simp	outb (BCR2(port), 0);
210123120Simp	return (1);
211123120Simp}
212123120Simp
213123120Simp/*
214123120Simp * Check if the Sigma-2x board is present at the given base port.
215123120Simp */
216123120Simpstatic int cx_probe_2x_board (port_t port)
217123120Simp{
218123120Simp	int rev, i;
219123120Simp
220123120Simp	/* Read and check the board revision code. */
221123120Simp	rev = inb (BSR(port));
222123120Simp	if ((rev & BSR2X_VAR_MASK) != CRONYX_22 &&
223123120Simp	    (rev & BSR2X_VAR_MASK) != CRONYX_24)
224123120Simp		return (0);		/* invalid variant code */
225123120Simp
226123120Simp	for (i=2; i<0x10; i+=2)
227123120Simp		if ((inb (BSR(port)+i) & BSR2X_REV_MASK) !=
228123120Simp		    (rev & BSR2X_REV_MASK))
229123120Simp			return (0);	/* status changed? */
230123120Simp	return (1);
231123120Simp}
232123120Simp
233123120Simp/*
234123120Simp * Check if the Cronyx-Sigma board is present at the given base port.
235123120Simp */
236123120Simpint cx_probe_board (port_t port, int irq, int dma)
237123120Simp{
238123120Simp	int c0, c1, c2=0, c3=0, result;
239123120Simp
240123120Simp	if (! valid (port, porttab))
241123120Simp		return 0;
242123120Simp
243123120Simp	if (irq > 0 && ! valid (irq, irqtab))
244123120Simp		return 0;
245123120Simp
246123120Simp	if (dma > 0 && ! valid (dma, dmatab))
247123120Simp		return 0;
248123120Simp
249123120Simp	if (cx_probe_800_chained_board (port)) {
250123120Simp		/* Sigma-800 detected. */
251123120Simp		if (! (inb (BSR(port)) & BSR_NOCHAIN)) {
252123120Simp			/* chained board attached */
253123120Simp			if (! cx_probe_800_chained_board (port+0x10))
254123120Simp				/* invalid chained board? */
255123120Simp				return (0);
256123120Simp			if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN))
257123120Simp				/* invalid chained board flag? */
258123120Simp				return (0);
259123120Simp		}
260123120Simp		return 1;
261123120Simp	}
262123120Simp	if (cx_probe_chained_board (port, &c0, &c1)) {
263123120Simp		/* Sigma-XXX detected. */
264123120Simp		if (! (inb (BSR(port)) & BSR_NOCHAIN)) {
265123120Simp			/* chained board attached */
266123120Simp			if (! cx_probe_chained_board (port+0x10, &c2, &c3))
267123120Simp				/* invalid chained board? */
268123120Simp				return (0);
269123120Simp			if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN))
270123120Simp				/* invalid chained board flag? */
271123120Simp				return (0);
272123120Simp		}
273123120Simp	} else if (cx_probe_2x_board (port)) {
274123120Simp		c0 = 1;		/* Sigma-2x detected. */
275123120Simp		c1 = 0;
276123120Simp	} else
277123120Simp		return (0);     /* no board detected */
278123120Simp
279123120Simp	/* Turn off the reset bit. */
280123120Simp	outb (BCR0(port), BCR0_NORESET);
281123120Simp	if (c2 || c3)
282123120Simp		outb (BCR0(port + 0x10), BCR0_NORESET);
283123120Simp
284123120Simp	result = 1;
285123120Simp	if (c0 && ! cx_probe_chip (CS0(port)))
286123120Simp		result = 0;	/* no CD2400 chip here */
287123120Simp	else if (c1 && ! cx_probe_chip (CS1A(port)) &&
288123120Simp	    ! cx_probe_chip (CS1(port)))
289123120Simp		result = 0;	/* no second CD2400 chip */
290123120Simp	else if (c2 && ! cx_probe_chip (CS0(port + 0x10)))
291123120Simp		result = 0;	/* no CD2400 chip on the slave board */
292123120Simp	else if (c3 && ! cx_probe_chip (CS1(port + 0x10)))
293123120Simp		result = 0;	/* no second CD2400 chip on the slave board */
294123120Simp
295123120Simp	/* Reset the controller. */
296123120Simp	outb (BCR0(port), 0);
297123120Simp	if (c2 || c3)
298123120Simp		outb (BCR0(port + 0x10), 0);
299123120Simp
300123120Simp	/* Yes, we really have valid Sigma board. */
301123120Simp	return (result);
302123120Simp}
303123120Simp
304123120Simp/*
305123120Simp * Check if the CD2400 chip is present at the given base port.
306123120Simp */
307123120Simpstatic int cx_probe_chip (port_t base)
308123120Simp{
309123120Simp	int rev, newrev, count;
310123120Simp
311123120Simp	/* Wait up to 10 msec for revision code to appear after reset. */
312123120Simp	rev = 0;
313123120Simp	for (count=0; rev==0; ++count) {
314123120Simp		if (count >= 20000)
315123120Simp			return (0); /* reset failed */
316123120Simp		rev = inb (GFRCR(base));
317123120Simp	}
318123120Simp
319123120Simp	/* Read and check the global firmware revision code. */
320123120Simp	if (! (rev>=REVCL_MIN && rev<=REVCL_MAX) &&
321123120Simp	    ! (rev>=REVCL31_MIN && rev<=REVCL31_MAX))
322123120Simp		return (0);	/* CD2400/2431 revision does not match */
323123120Simp
324123120Simp	/* Reset the chip. */
325123120Simp	if (! cx_reset (base))
326123120Simp		return (0);
327123120Simp
328123120Simp	/* Read and check the new global firmware revision code. */
329123120Simp	newrev = inb (GFRCR(base));
330123120Simp	if (newrev != rev)
331123120Simp		return (0);	/* revision changed */
332123120Simp
333123120Simp	/* Yes, we really have CD2400/2431 chip here. */
334123120Simp	return (1);
335123120Simp}
336123120Simp
337123120Simp/*
338123120Simp * Check that the irq is functional.
339123120Simp * irq>0  - activate the interrupt from the adapter (irq=on)
340123120Simp * irq<0  - deactivate the interrupt (irq=off)
341123120Simp * irq==0 - free the interrupt line (irq=tri-state)
342123120Simp * Return the interrupt mask _before_ activating irq.
343123120Simp */
344123120Simpint cx_probe_irq (cx_board_t *b, int irq)
345123120Simp{
346123120Simp	int mask, rev;
347123120Simp        port_t port;
348123120Simp
349123120Simp	rev = inb (BSR(b->port));
350123120Simp        port = ((rev & BSR_VAR_MASK) != CRONYX_400) ? CS0(b->port) : CS1(b->port);
351123120Simp
352123120Simp	outb (0x20, 0x0a);
353123120Simp	mask = inb (0x20);
354123120Simp	outb (0xa0, 0x0a);
355123120Simp	mask |= inb (0xa0) << 8;
356123120Simp
357123120Simp	if (irq > 0) {
358123120Simp		outb (BCR0(b->port), BCR0_NORESET | irqmask[irq]);
359123120Simp		outb (CAR(port), 0);
360123120Simp		cx_cmd (port, CCR_CLRCH);
361123120Simp		outb (CMR(port), CMR_HDLC);
362123120Simp		outb (TCOR(port), 0);
363123120Simp		outb (TBPR(port), 1);
364123120Simp		cx_cmd (port, CCR_INITCH | CCR_ENTX);
365123120Simp		outb (IER(port), IER_TXMPTY);
366123120Simp	} else if (irq < 0) {
367123120Simp		cx_reset (port);
368123120Simp		if (-irq > 7) {
369123120Simp			outb (0xa0, 0x60 | ((-irq) & 7));
370123120Simp			outb (0x20, 0x62);
371123120Simp		} else
372123120Simp			outb (0x20, 0x60 | (-irq));
373123120Simp	} else
374123120Simp		outb (BCR0(b->port), 0);
375123120Simp	return mask;
376123120Simp}
377123120Simp
378123120Simpstatic int cx_chip_revision (port_t port, int rev)
379123120Simp{
380123120Simp	int count;
381123120Simp
382123120Simp	/* Model 400 has no first chip. */
383123120Simp	port = ((rev & BSR_VAR_MASK) != CRONYX_400) ? CS0(port) : CS1(port);
384123120Simp
385123120Simp	/* Wait up to 10 msec for revision code to appear after reset. */
386123120Simp	for (count=0; inb(GFRCR(port))==0; ++count)
387123120Simp		if (count >= 20000)
388123120Simp			return (0); /* reset failed */
389123120Simp
390123120Simp	return inb (GFRCR (port));
391123120Simp}
392123120Simp
393123120Simp/*
394123120Simp * Probe and initialize the board structure.
395123120Simp */
396123120Simpvoid cx_init (cx_board_t *b, int num, port_t port, int irq, int dma)
397123120Simp{
398123120Simp	int gfrcr, rev, chain, mod = 0, rev2 = 0, mod2 = 0;
399123120Simp
400123120Simp	rev = inb (BSR(port));
401123120Simp	chain = ! (rev & BSR_NOCHAIN);
402123120Simp	if (cx_probe_800_chained_board (port)) {
403123120Simp		cx_init_800 (b, num, port, irq, dma, chain);
404123120Simp		return;
405123120Simp	}
406123120Simp	if ((rev & BSR2X_VAR_MASK) == CRONYX_22 ||
407123120Simp	    (rev & BSR2X_VAR_MASK) == CRONYX_24) {
408123120Simp		cx_init_2x (b, num, port, irq, dma,
409123120Simp			(rev & BSR2X_VAR_MASK), (rev & BSR2X_OSC_33));
410123120Simp		return;
411123120Simp        }
412123120Simp
413123120Simp	outb (BCR0(port), BCR0_NORESET);
414123120Simp	if (chain)
415123120Simp		outb (BCR0(port+0x10), BCR0_NORESET);
416123120Simp	gfrcr = cx_chip_revision (port, rev);
417123120Simp	if (gfrcr >= REVCL31_MIN && gfrcr <= REVCL31_MAX)
418123120Simp		mod = 1;
419123120Simp	if (chain) {
420123120Simp		rev2 = inb (BSR(port+0x10));
421123120Simp		gfrcr = cx_chip_revision (port+0x10, rev2);
422123120Simp		if (gfrcr >= REVCL31_MIN && gfrcr <= REVCL31_MAX)
423123120Simp			mod2 = 1;
424123120Simp		outb (BCR0(port+0x10), 0);
425123120Simp	}
426123120Simp	outb (BCR0(port), 0);
427123120Simp
428123120Simp	cx_init_board (b, num, port, irq, dma, chain,
429123120Simp		(rev & BSR_VAR_MASK), (rev & BSR_OSC_MASK), mod,
430123120Simp		(rev2 & BSR_VAR_MASK), (rev2 & BSR_OSC_MASK), mod2);
431123120Simp}
432123120Simp
433123120Simp/*
434123120Simp * Initialize the board structure, given the type of the board.
435123120Simp */
436123120Simpvoid cx_init_board (cx_board_t *b, int num, port_t port, int irq, int dma,
437123120Simp	int chain, int rev, int osc, int mod, int rev2, int osc2, int mod2)
438123120Simp{
439123120Simp	cx_chan_t *c;
440123120Simp	char *type;
441123120Simp	int i;
442123120Simp
443123120Simp	/* Initialize board structure. */
444123120Simp	b->port = port;
445123120Simp	b->num = num;
446123120Simp	b->irq = irq;
447123120Simp	b->dma = dma;
448123120Simp	b->opt = board_opt_dflt;
449123120Simp
450123120Simp	b->type = B_SIGMA_XXX;
451123120Simp	b->if0type = b->if8type = cx_iftype;
452123120Simp
453123120Simp	/* Set channels 0 and 8 mode, set DMA and IRQ. */
454123120Simp	b->bcr0 = b->bcr0b = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq];
455123120Simp
456123120Simp	/* Clear DTR[0..3] and DTR[8..12]. */
457123120Simp	b->bcr1 = b->bcr1b = 0;
458123120Simp
459123120Simp	/*------------------ Master board -------------------*/
460123120Simp
461123120Simp	/* Read and check the board revision code. */
462123120Simp	strcpy (b->name, mod ? "m" : "");
463123120Simp	switch (rev) {
464123120Simp	default:	  type = "";	 break;
465123120Simp	case CRONYX_100:  type = "100";  break;
466123120Simp	case CRONYX_400:  type = "400";  break;
467123120Simp	case CRONYX_500:  type = "500";  break;
468123120Simp	case CRONYX_410:  type = "410";  break;
469123120Simp	case CRONYX_810:  type = "810";  break;
470123120Simp	case CRONYX_410s: type = "410s"; break;
471123120Simp	case CRONYX_810s: type = "810s"; break;
472123120Simp	case CRONYX_440:  type = "440";  break;
473123120Simp	case CRONYX_840:  type = "840";  break;
474123120Simp	case CRONYX_401:  type = "401";  break;
475123120Simp	case CRONYX_801:  type = "801";  break;
476123120Simp	case CRONYX_401s: type = "401s"; break;
477123120Simp	case CRONYX_801s: type = "801s"; break;
478123120Simp	case CRONYX_404:  type = "404";  break;
479123120Simp	case CRONYX_703:  type = "703";  break;
480123120Simp	}
481123120Simp	strcat (b->name, type);
482123120Simp
483123120Simp	switch (osc) {
484123120Simp	default:
485123120Simp	case BSR_OSC_20: /* 20 MHz */
486123120Simp		b->chan[0].oscfreq = b->chan[1].oscfreq =
487123120Simp		b->chan[2].oscfreq = b->chan[3].oscfreq =
488123120Simp		b->chan[4].oscfreq = b->chan[5].oscfreq =
489123120Simp		b->chan[6].oscfreq = b->chan[7].oscfreq =
490123120Simp			mod ? 33000000L : 20000000L;
491123120Simp		strcat (b->name, "a");
492123120Simp		break;
493123120Simp	case BSR_OSC_18432: /* 18.432 MHz */
494123120Simp		b->chan[0].oscfreq = b->chan[1].oscfreq =
495123120Simp		b->chan[2].oscfreq = b->chan[3].oscfreq =
496123120Simp		b->chan[4].oscfreq = b->chan[5].oscfreq =
497123120Simp		b->chan[6].oscfreq = b->chan[7].oscfreq =
498123120Simp			mod ? 20000000L : 18432000L;
499123120Simp		strcat (b->name, "b");
500123120Simp		break;
501123120Simp	}
502123120Simp
503123120Simp	/*------------------ Slave board -------------------*/
504123120Simp
505123120Simp	if (chain) {
506123120Simp		/* Read and check the board revision code. */
507123120Simp		strcat (b->name, mod2 ? "/m" : "/");
508123120Simp		switch (rev2) {
509123120Simp		default:	  type = "";	 break;
510123120Simp		case CRONYX_100:  type = "100";  break;
511123120Simp		case CRONYX_400:  type = "400";  break;
512123120Simp		case CRONYX_500:  type = "500";  break;
513123120Simp		case CRONYX_410:  type = "410";  break;
514123120Simp		case CRONYX_810:  type = "810";  break;
515123120Simp		case CRONYX_410s: type = "410s"; break;
516123120Simp		case CRONYX_810s: type = "810s"; break;
517123120Simp		case CRONYX_440:  type = "440";  break;
518123120Simp		case CRONYX_840:  type = "840";  break;
519123120Simp		case CRONYX_401:  type = "401";  break;
520123120Simp		case CRONYX_801:  type = "801";  break;
521123120Simp		case CRONYX_401s: type = "401s"; break;
522123120Simp		case CRONYX_801s: type = "801s"; break;
523123120Simp		case CRONYX_404:  type = "404";  break;
524123120Simp		case CRONYX_703:  type = "703";  break;
525123120Simp		}
526123120Simp		strcat (b->name, type);
527123120Simp
528123120Simp		switch (osc2) {
529123120Simp		default:
530123120Simp		case BSR_OSC_20: /* 20 MHz */
531123120Simp			b->chan[8].oscfreq = b->chan[9].oscfreq =
532123120Simp			b->chan[10].oscfreq = b->chan[11].oscfreq =
533123120Simp			b->chan[12].oscfreq = b->chan[13].oscfreq =
534123120Simp			b->chan[14].oscfreq = b->chan[15].oscfreq =
535123120Simp				mod2 ? 33000000L : 20000000L;
536123120Simp			strcat (b->name, "a");
537123120Simp			break;
538123120Simp		case BSR_OSC_18432: /* 18.432 MHz */
539123120Simp			b->chan[8].oscfreq = b->chan[9].oscfreq =
540123120Simp			b->chan[10].oscfreq = b->chan[11].oscfreq =
541123120Simp			b->chan[12].oscfreq = b->chan[13].oscfreq =
542123120Simp			b->chan[14].oscfreq = b->chan[15].oscfreq =
543123120Simp				mod2 ? 20000000L : 18432000L;
544123120Simp			strcat (b->name, "b");
545123120Simp			break;
546123120Simp		}
547123120Simp	}
548123120Simp
549123120Simp	/* Initialize channel structures. */
550123120Simp	for (i=0; i<4; ++i) {
551123120Simp		b->chan[i+0].port  = CS0(port);
552123120Simp		b->chan[i+4].port  = cx_probe_chip (CS1A(port)) ?
553123120Simp			CS1A(port) : CS1(port);
554123120Simp		b->chan[i+8].port  = CS0(port+0x10);
555123120Simp		b->chan[i+12].port = CS1(port+0x10);
556123120Simp	}
557123120Simp	for (c=b->chan; c<b->chan+NCHAN; ++c) {
558123120Simp		c->board = b;
559123120Simp		c->num = c - b->chan;
560123120Simp		c->type = T_NONE;
561123120Simp	}
562123120Simp
563123120Simp	/*------------------ Master board -------------------*/
564123120Simp
565123120Simp	switch (rev) {
566123120Simp	case CRONYX_400:
567123120Simp		for (i=4; i<8; ++i)
568123120Simp			b->chan[i].type = T_UNIV_RS232;
569123120Simp		break;
570123120Simp	case CRONYX_100:
571123120Simp		b->chan[0].type = T_UNIV_RS232;
572123120Simp		break;
573123120Simp	case CRONYX_500:
574123120Simp		b->chan[0].type = T_UNIV_RS232;
575123120Simp		for (i=4; i<8; ++i)
576123120Simp			b->chan[i].type = T_UNIV_RS232;
577123120Simp		break;
578123120Simp	case CRONYX_410:
579123120Simp		b->chan[0].type = T_UNIV_V35;
580123120Simp		for (i=1; i<4; ++i)
581123120Simp			b->chan[i].type = T_UNIV_RS232;
582123120Simp		break;
583123120Simp	case CRONYX_810:
584123120Simp		b->chan[0].type = T_UNIV_V35;
585123120Simp		for (i=1; i<8; ++i)
586123120Simp			b->chan[i].type = T_UNIV_RS232;
587123120Simp		break;
588123120Simp	case CRONYX_410s:
589123120Simp		b->chan[0].type = T_UNIV_V35;
590123120Simp		for (i=1; i<4; ++i)
591123120Simp			b->chan[i].type = T_SYNC_RS232;
592123120Simp		break;
593123120Simp	case CRONYX_810s:
594123120Simp		b->chan[0].type = T_UNIV_V35;
595123120Simp		for (i=1; i<4; ++i)
596123120Simp			b->chan[i].type = T_SYNC_RS232;
597123120Simp		for (i=4; i<8; ++i)
598123120Simp			b->chan[i].type = T_UNIV_RS232;
599123120Simp		break;
600123120Simp	case CRONYX_440:
601123120Simp		b->chan[0].type = T_UNIV_V35;
602123120Simp		for (i=1; i<4; ++i)
603123120Simp			b->chan[i].type = T_SYNC_V35;
604123120Simp		break;
605123120Simp	case CRONYX_840:
606123120Simp		b->chan[0].type = T_UNIV_V35;
607123120Simp		for (i=1; i<4; ++i)
608123120Simp			b->chan[i].type = T_SYNC_V35;
609123120Simp		for (i=4; i<8; ++i)
610123120Simp			b->chan[i].type = T_UNIV_RS232;
611123120Simp		break;
612123120Simp	case CRONYX_401:
613123120Simp		b->chan[0].type = T_UNIV_RS449;
614123120Simp		for (i=1; i<4; ++i)
615123120Simp			b->chan[i].type = T_UNIV_RS232;
616123120Simp		break;
617123120Simp	case CRONYX_801:
618123120Simp		b->chan[0].type = T_UNIV_RS449;
619123120Simp		for (i=1; i<8; ++i)
620123120Simp			b->chan[i].type = T_UNIV_RS232;
621123120Simp		break;
622123120Simp	case CRONYX_401s:
623123120Simp		b->chan[0].type = T_UNIV_RS449;
624123120Simp		for (i=1; i<4; ++i)
625123120Simp			b->chan[i].type = T_SYNC_RS232;
626123120Simp		break;
627123120Simp	case CRONYX_801s:
628123120Simp		b->chan[0].type = T_UNIV_RS449;
629123120Simp		for (i=1; i<4; ++i)
630123120Simp			b->chan[i].type = T_SYNC_RS232;
631123120Simp		for (i=4; i<8; ++i)
632123120Simp			b->chan[i].type = T_UNIV_RS232;
633123120Simp		break;
634123120Simp	case CRONYX_404:
635123120Simp		b->chan[0].type = T_UNIV_RS449;
636123120Simp		for (i=1; i<4; ++i)
637123120Simp			b->chan[i].type = T_SYNC_RS449;
638123120Simp		break;
639123120Simp	case CRONYX_703:
640123120Simp		b->chan[0].type = T_UNIV_RS449;
641123120Simp		for (i=1; i<3; ++i)
642123120Simp			b->chan[i].type = T_SYNC_RS449;
643123120Simp		for (i=4; i<8; ++i)
644123120Simp			b->chan[i].type = T_UNIV_RS232;
645123120Simp		break;
646123120Simp	}
647123120Simp
648123120Simp	/*------------------ Slave board -------------------*/
649123120Simp
650123120Simp	if (chain) {
651123120Simp		switch (rev2) {
652123120Simp		case CRONYX_400:
653123120Simp			break;
654123120Simp		case CRONYX_100:
655123120Simp			b->chan[8].type = T_UNIV_RS232;
656123120Simp			break;
657123120Simp		case CRONYX_500:
658123120Simp			b->chan[8].type = T_UNIV_RS232;
659123120Simp			for (i=12; i<16; ++i)
660123120Simp				b->chan[i].type = T_UNIV_RS232;
661123120Simp			break;
662123120Simp		case CRONYX_410:
663123120Simp			b->chan[8].type = T_UNIV_V35;
664123120Simp			for (i=9; i<12; ++i)
665123120Simp				b->chan[i].type = T_UNIV_RS232;
666123120Simp			break;
667123120Simp		case CRONYX_810:
668123120Simp			b->chan[8].type = T_UNIV_V35;
669123120Simp			for (i=9; i<16; ++i)
670123120Simp				b->chan[i].type = T_UNIV_RS232;
671123120Simp			break;
672123120Simp		case CRONYX_410s:
673123120Simp			b->chan[8].type = T_UNIV_V35;
674123120Simp			for (i=9; i<12; ++i)
675123120Simp				b->chan[i].type = T_SYNC_RS232;
676123120Simp			break;
677123120Simp		case CRONYX_810s:
678123120Simp			b->chan[8].type = T_UNIV_V35;
679123120Simp			for (i=9; i<12; ++i)
680123120Simp				b->chan[i].type = T_SYNC_RS232;
681123120Simp			for (i=12; i<16; ++i)
682123120Simp				b->chan[i].type = T_UNIV_RS232;
683123120Simp			break;
684123120Simp		case CRONYX_440:
685123120Simp			b->chan[8].type = T_UNIV_V35;
686123120Simp			for (i=9; i<12; ++i)
687123120Simp				b->chan[i].type = T_SYNC_V35;
688123120Simp			break;
689123120Simp		case CRONYX_840:
690123120Simp			b->chan[8].type = T_UNIV_V35;
691123120Simp			for (i=9; i<12; ++i)
692123120Simp				b->chan[i].type = T_SYNC_V35;
693123120Simp			for (i=12; i<16; ++i)
694123120Simp				b->chan[i].type = T_UNIV_RS232;
695123120Simp			break;
696123120Simp		case CRONYX_401:
697123120Simp			b->chan[8].type = T_UNIV_RS449;
698123120Simp			for (i=9; i<12; ++i)
699123120Simp				b->chan[i].type = T_UNIV_RS232;
700123120Simp			break;
701123120Simp		case CRONYX_801:
702123120Simp			b->chan[8].type = T_UNIV_RS449;
703123120Simp			for (i=9; i<16; ++i)
704123120Simp				b->chan[i].type = T_UNIV_RS232;
705123120Simp			break;
706123120Simp		case CRONYX_401s:
707123120Simp			b->chan[8].type = T_UNIV_RS449;
708123120Simp			for (i=9; i<12; ++i)
709123120Simp				b->chan[i].type = T_UNIV_RS232;
710123120Simp			break;
711123120Simp		case CRONYX_801s:
712123120Simp			b->chan[8].type = T_UNIV_RS449;
713123120Simp			for (i=9; i<12; ++i)
714123120Simp				b->chan[i].type = T_SYNC_RS232;
715123120Simp			for (i=12; i<16; ++i)
716123120Simp				b->chan[i].type = T_UNIV_RS232;
717123120Simp			break;
718123120Simp		case CRONYX_404:
719123120Simp			b->chan[8].type = T_UNIV_RS449;
720123120Simp			for (i=9; i<12; ++i)
721123120Simp				b->chan[i].type = T_SYNC_RS449;
722123120Simp			break;
723123120Simp		case CRONYX_703:
724123120Simp			b->chan[8].type = T_UNIV_RS449;
725123120Simp			for (i=9; i<11; ++i)
726123120Simp				b->chan[i].type = T_SYNC_RS449;
727123120Simp			for (i=12; i<16; ++i)
728123120Simp				b->chan[i].type = T_UNIV_RS232;
729123120Simp			break;
730123120Simp		}
731123120Simp	}
732123120Simp
733123120Simp	b->nuniv = b->nsync = b->nasync = 0;
734123120Simp	for (c=b->chan; c<b->chan+NCHAN; ++c)
735123120Simp		switch (c->type) {
736123120Simp		case T_ASYNC:      ++b->nasync; break;
737123120Simp		case T_UNIV:
738123120Simp		case T_UNIV_RS232:
739123120Simp		case T_UNIV_RS449:
740123120Simp		case T_UNIV_V35:   ++b->nuniv;  break;
741123120Simp		case T_SYNC_RS232:
742123120Simp		case T_SYNC_V35:
743123120Simp		case T_SYNC_RS449: ++b->nsync;  break;
744123120Simp		}
745123120Simp
746123120Simp	cx_reinit_board (b);
747123120Simp}
748123120Simp
749123120Simp/*
750123120Simp * Initialize the Sigma-800 board structure.
751123120Simp */
752123120Simpvoid cx_init_800 (cx_board_t *b, int num, port_t port, int irq, int dma,
753123120Simp	int chain)
754123120Simp{
755123120Simp	cx_chan_t *c;
756123120Simp	int i;
757123120Simp
758123120Simp	/* Initialize board structure. */
759123120Simp	b->port = port;
760123120Simp	b->num = num;
761123120Simp	b->irq = irq;
762123120Simp	b->dma = dma;
763123120Simp	b->opt = board_opt_dflt;
764123120Simp	b->type = B_SIGMA_800;
765123120Simp
766123120Simp	/* Set channels 0 and 8 mode, set DMA and IRQ. */
767123120Simp	b->bcr0 = b->bcr0b = dmamask[b->dma] | irqmask[b->irq];
768123120Simp
769123120Simp	/* Clear DTR[0..7] and DTR[8..15]. */
770123120Simp	b->bcr1 = b->bcr1b = 0;
771123120Simp
772123120Simp	strcpy (b->name, "800");
773123120Simp	if (chain)
774123120Simp		strcat (b->name, "/800");
775123120Simp
776123120Simp	/* Initialize channel structures. */
777123120Simp	for (i=0; i<4; ++i) {
778123120Simp		b->chan[i+0].port  = CS0(port);
779123120Simp		b->chan[i+4].port  = cx_probe_chip (CS1A(port)) ?
780123120Simp			CS1A(port) : CS1(port);
781123120Simp		b->chan[i+8].port  = CS0(port+0x10);
782123120Simp		b->chan[i+12].port = CS1(port+0x10);
783123120Simp	}
784123120Simp	for (c=b->chan; c<b->chan+NCHAN; ++c) {
785123120Simp		c->board = b;
786123120Simp		c->num = c - b->chan;
787123120Simp		c->oscfreq = 33000000L;
788123120Simp		c->type = (c->num < 8 || chain) ? T_UNIV_RS232 : T_NONE;
789123120Simp	}
790123120Simp
791123120Simp	b->nuniv = b->nsync = b->nasync = 0;
792123120Simp	for (c=b->chan; c<b->chan+NCHAN; ++c)
793123120Simp		switch (c->type) {
794123120Simp		case T_ASYNC:      ++b->nasync; break;
795123120Simp		case T_UNIV:
796123120Simp		case T_UNIV_RS232:
797123120Simp		case T_UNIV_RS449:
798123120Simp		case T_UNIV_V35:   ++b->nuniv;  break;
799123120Simp		case T_SYNC_RS232:
800123120Simp		case T_SYNC_V35:
801123120Simp		case T_SYNC_RS449: ++b->nsync;  break;
802123120Simp		}
803123120Simp
804123120Simp	cx_reinit_board (b);
805123120Simp}
806123120Simp
807123120Simp/*
808123120Simp * Initialize the Sigma-2x board structure.
809123120Simp */
810123120Simpvoid cx_init_2x (cx_board_t *b, int num, port_t port, int irq, int dma,
811123120Simp	int rev, int osc)
812123120Simp{
813123120Simp	cx_chan_t *c;
814123120Simp	int i;
815123120Simp
816123120Simp	/* Initialize board structure. */
817123120Simp	b->port = port;
818123120Simp	b->num = num;
819123120Simp	b->irq = irq;
820123120Simp	b->dma = dma;
821123120Simp	b->opt = board_opt_dflt;
822123120Simp
823123120Simp	b->type = B_SIGMA_2X;
824123120Simp
825123120Simp	/* Set channels 0 and 8 mode, set DMA and IRQ. */
826123120Simp	b->bcr0 = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq];
827123120Simp	if (b->type == B_SIGMA_2X && b->opt.fast)
828123120Simp		b->bcr0 |= BCR02X_FAST;
829123120Simp
830123120Simp	/* Clear DTR[0..3] and DTR[8..12]. */
831123120Simp	b->bcr1 = 0;
832123120Simp
833123120Simp	/* Initialize channel structures. */
834123120Simp	for (i=0; i<4; ++i) {
835123120Simp		b->chan[i+0].port  = CS0(port);
836123120Simp		b->chan[i+4].port  = CS1(port);
837123120Simp		b->chan[i+8].port  = CS0(port+0x10);
838123120Simp		b->chan[i+12].port = CS1(port+0x10);
839123120Simp	}
840123120Simp	for (c=b->chan; c<b->chan+NCHAN; ++c) {
841123120Simp		c->board = b;
842123120Simp		c->num = c - b->chan;
843123120Simp		c->type = T_NONE;
844123120Simp		c->oscfreq = (osc & BSR2X_OSC_33) ? 33000000L : 20000000L;
845123120Simp	}
846123120Simp
847123120Simp	/* Check the board revision code. */
848123120Simp	strcpy (b->name, "22");
849123120Simp	b->chan[0].type = T_UNIV;
850123120Simp	b->chan[1].type = T_UNIV;
851123120Simp	b->nsync = b->nasync = 0;
852123120Simp	b->nuniv = 2;
853123120Simp	if (rev == CRONYX_24) {
854123120Simp		strcpy (b->name, "24");
855123120Simp		b->chan[2].type = T_UNIV;
856123120Simp		b->chan[3].type = T_UNIV;
857123120Simp		b->nuniv += 2;
858123120Simp	}
859123120Simp	strcat (b->name, (osc & BSR2X_OSC_33) ? "c" : "a");
860123120Simp	cx_reinit_board (b);
861123120Simp}
862123120Simp
863123120Simp/*
864123120Simp * Reinitialize all channels, using new options and baud rate.
865123120Simp */
866123120Simpvoid cx_reinit_board (cx_board_t *b)
867123120Simp{
868123120Simp	cx_chan_t *c;
869123120Simp
870123120Simp	b->opt = board_opt_dflt;
871123120Simp	if (b->type == B_SIGMA_2X) {
872123120Simp		b->bcr0 &= ~BCR02X_FAST;
873123120Simp		if (b->opt.fast)
874123120Simp			b->bcr0 |= BCR02X_FAST;
875123120Simp	} else
876123120Simp		b->if0type = b->if8type = cx_iftype;
877123120Simp	for (c=b->chan; c<b->chan+NCHAN; ++c) {
878123120Simp		switch (c->type) {
879123120Simp		default:
880123120Simp		case T_NONE:
881123120Simp			continue;
882123120Simp		case T_UNIV:
883123120Simp		case T_UNIV_RS232:
884123120Simp		case T_UNIV_RS449:
885123120Simp		case T_UNIV_V35:
886123120Simp			c->mode = (cx_univ_mode == M_ASYNC) ?
887123120Simp				M_ASYNC : cx_sync_mode;
888123120Simp			break;
889123120Simp		case T_SYNC_RS232:
890123120Simp		case T_SYNC_V35:
891123120Simp		case T_SYNC_RS449:
892123120Simp			c->mode = cx_sync_mode;
893123120Simp			break;
894123120Simp		case T_ASYNC:
895123120Simp			c->mode = M_ASYNC;
896123120Simp			break;
897123120Simp		}
898123120Simp		c->rxbaud = cx_rxbaud;
899123120Simp		c->txbaud = cx_txbaud;
900123120Simp		c->opt = chan_opt_dflt;
901123120Simp		c->aopt = opt_async_dflt;
902123120Simp		c->hopt = opt_hdlc_dflt;
903123120Simp	}
904123120Simp}
905123120Simp
906123120Simp/*
907123120Simp * Set up the board.
908123120Simp */
909123120Simpint cx_setup_board (cx_board_t *b, const unsigned char *firmware,
910123120Simp	long bits, const cr_dat_tst_t *tst)
911123120Simp{
912123120Simp	int i;
913123120Simp#ifndef NDIS_MINIPORT_DRIVER
914123120Simp	/* Disable DMA channel. */
915123120Simp	outb (DMA_MASK, (b->dma & 3) | DMA_MASK_CLEAR);
916123120Simp#endif
917123120Simp	/* Reset the controller. */
918123120Simp	outb (BCR0(b->port), 0);
919123120Simp	if (b->chan[8].type || b->chan[12].type)
920123120Simp		outb (BCR0(b->port+0x10), 0);
921123120Simp
922123120Simp	/* Load the firmware. */
923123120Simp	if (b->type == B_SIGMA_800) {
924123120Simp		/* Reset the controllers. */
925123120Simp		outb (BCR2(b->port), BCR2_TMS);
926123120Simp		if (b->chan[8].type || b->chan[12].type)
927123120Simp			outb (BCR2(b->port+0x10), BCR2_TMS);
928123120Simp		outb (BCR2(b->port), 0);
929123120Simp		if (b->chan[8].type || b->chan[12].type)
930123120Simp			outb (BCR2(b->port+0x10), 0);
931123120Simp
932123120Simp		if (firmware &&
933123120Simp		    (! cx_download (b->port, firmware, bits, tst) ||
934123120Simp		    ((b->chan[8].type || b->chan[12].type) &&
935123120Simp		    ! cx_download (b->port+0x10, firmware, bits, tst))))
936123120Simp			return (0);
937123120Simp	}
938123120Simp
939123120Simp	/*
940123120Simp	 * Set channels 0 and 8 to RS232 async. mode.
941123120Simp	 * Enable DMA and IRQ.
942123120Simp	 */
943123120Simp	outb (BCR0(b->port), b->bcr0);
944123120Simp	if (b->chan[8].type || b->chan[12].type)
945123120Simp		outb (BCR0(b->port+0x10), b->bcr0b);
946123120Simp
947123120Simp	/* Clear DTR[0..3] and DTR[8..12]. */
948123120Simp	outw (BCR1(b->port), b->bcr1);
949123120Simp	if (b->chan[8].type || b->chan[12].type)
950123120Simp		outw (BCR1(b->port+0x10), b->bcr1b);
951123120Simp
952123120Simp	if (b->type == B_SIGMA_800)
953123120Simp		outb (BCR2(b->port), b->opt.fast &
954123120Simp			(BCR2_BUS0 | BCR2_BUS1));
955123120Simp
956123120Simp	/* Initialize all controllers. */
957123120Simp	for (i=0; i<NCHAN; i+=4)
958123120Simp		if (b->chan[i].type != T_NONE)
959123120Simp			cx_setup_chip (b->chan + i);
960123120Simp#ifndef NDIS_MINIPORT_DRIVER
961123120Simp	/* Set up DMA channel to master mode. */
962123120Simp	outb (DMA_MODE, (b->dma & 3) | DMA_MODE_MASTER);
963123120Simp
964123120Simp	/* Enable DMA channel. */
965123120Simp	outb (DMA_MASK, b->dma & 3);
966123120Simp#endif
967123120Simp	/* Initialize all channels. */
968123120Simp	for (i=0; i<NCHAN; ++i)
969123120Simp		if (b->chan[i].type != T_NONE)
970123120Simp			cx_setup_chan (b->chan + i);
971123120Simp	return (1);
972123120Simp}
973123120Simp
974123120Simp/*
975123120Simp * Initialize the board.
976123120Simp */
977123120Simpstatic void cx_setup_chip (cx_chan_t *c)
978123120Simp{
979123120Simp	/* Reset the chip. */
980123120Simp	cx_reset (c->port);
981123120Simp
982123120Simp	/*
983123120Simp	 * Set all interrupt level registers to the same value.
984123120Simp	 * This enables the internal CD2400 priority scheme.
985123120Simp	 */
986123120Simp	outb (RPILR(c->port), BRD_INTR_LEVEL);
987123120Simp	outb (TPILR(c->port), BRD_INTR_LEVEL);
988123120Simp	outb (MPILR(c->port), BRD_INTR_LEVEL);
989123120Simp
990123120Simp	/* Set bus error count to zero. */
991123120Simp	outb (BERCNT(c->port), 0);
992123120Simp
993123120Simp	/* Set 16-bit DMA mode. */
994123120Simp	outb (DMR(c->port), 0);
995123120Simp
996123120Simp	/* Set timer period register to 1 msec (approximately). */
997123120Simp	outb (TPR(c->port), 10);
998123120Simp}
999123120Simp
1000123120Simp/*
1001123120Simp * Initialize the CD2400 channel.
1002123120Simp */
1003123120Simpvoid cx_update_chan (cx_chan_t *c)
1004123120Simp{
1005123120Simp	int clock, period;
1006123120Simp
1007123120Simp	if (c->board->type == B_SIGMA_XXX)
1008123120Simp		switch (c->num) {
1009123120Simp		case 0:
1010123120Simp			c->board->bcr0 &= ~BCR0_UMASK;
1011123120Simp			if (c->mode != M_ASYNC)
1012123120Simp				c->board->bcr0 |= BCR0_UM_SYNC;
1013123120Simp			if (c->board->if0type &&
1014123120Simp			    (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
1015123120Simp				c->board->bcr0 |= BCR0_UI_RS449;
1016123120Simp			outb (BCR0(c->board->port), c->board->bcr0);
1017123120Simp			break;
1018123120Simp		case 8:
1019123120Simp			c->board->bcr0b &= ~BCR0_UMASK;
1020123120Simp			if (c->mode != M_ASYNC)
1021123120Simp				c->board->bcr0b |= BCR0_UM_SYNC;
1022123120Simp			if (c->board->if8type &&
1023123120Simp			    (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
1024123120Simp				c->board->bcr0b |= BCR0_UI_RS449;
1025123120Simp			outb (BCR0(c->board->port+0x10), c->board->bcr0b);
1026123120Simp			break;
1027123120Simp		}
1028123120Simp
1029123120Simp	/* set current channel number */
1030123120Simp	outb (CAR(c->port), c->num & 3);
1031123120Simp
1032123120Simp	switch (c->mode) {	/* initialize the channel mode */
1033123120Simp	case M_ASYNC:
1034123120Simp		/* set receiver timeout register */
1035123120Simp		outw (RTPR(c->port), 10);          /* 10 msec, see TPR */
1036123120Simp		c->opt.rcor.encod = ENCOD_NRZ;
1037123120Simp
1038123120Simp		outb (CMR(c->port), CMR_RXDMA | CMR_TXDMA | CMR_ASYNC);
1039123120Simp		outb (COR1(c->port), BYTE c->aopt.cor1);
1040123120Simp		outb (COR2(c->port), BYTE c->aopt.cor2);
1041123120Simp		outb (COR3(c->port), BYTE c->aopt.cor3);
1042123120Simp		outb (COR6(c->port), BYTE c->aopt.cor6);
1043123120Simp		outb (COR7(c->port), BYTE c->aopt.cor7);
1044123120Simp		outb (SCHR1(c->port), c->aopt.schr1);
1045123120Simp		outb (SCHR2(c->port), c->aopt.schr2);
1046123120Simp		outb (SCHR3(c->port), c->aopt.schr3);
1047123120Simp		outb (SCHR4(c->port), c->aopt.schr4);
1048123120Simp		outb (SCRL(c->port), c->aopt.scrl);
1049123120Simp		outb (SCRH(c->port), c->aopt.scrh);
1050123120Simp		outb (LNXT(c->port), c->aopt.lnxt);
1051123120Simp		break;
1052123120Simp	case M_HDLC:
1053123120Simp		outb (CMR(c->port), CMR_RXDMA | CMR_TXDMA | CMR_HDLC);
1054123120Simp		outb (COR1(c->port), BYTE c->hopt.cor1);
1055123120Simp		outb (COR2(c->port), BYTE c->hopt.cor2);
1056123120Simp		outb (COR3(c->port), BYTE c->hopt.cor3);
1057123120Simp		outb (RFAR1(c->port), c->hopt.rfar1);
1058123120Simp		outb (RFAR2(c->port), c->hopt.rfar2);
1059123120Simp		outb (RFAR3(c->port), c->hopt.rfar3);
1060123120Simp		outb (RFAR4(c->port), c->hopt.rfar4);
1061123120Simp		outb (CPSR(c->port), c->hopt.cpsr);
1062123120Simp		break;
1063123120Simp	}
1064123120Simp
1065123120Simp	/* set mode-independent options */
1066123120Simp	outb (COR4(c->port), BYTE c->opt.cor4);
1067123120Simp	outb (COR5(c->port), BYTE c->opt.cor5);
1068123120Simp
1069123120Simp	/* set up receiver clock values */
1070123120Simp	if (c->mode == M_ASYNC || c->opt.rcor.dpll || c->opt.tcor.llm) {
1071123120Simp		cx_clock (c->oscfreq, c->rxbaud, &clock, &period);
1072123120Simp		c->opt.rcor.clk = clock;
1073123120Simp	} else {
1074123120Simp		c->opt.rcor.clk = CLK_EXT;
1075123120Simp		period = 1;
1076123120Simp	}
1077123120Simp	outb (RCOR(c->port), BYTE c->opt.rcor);
1078123120Simp	outb (RBPR(c->port), period);
1079123120Simp
1080123120Simp	/* set up transmitter clock values */
1081123120Simp	if (c->mode == M_ASYNC || !c->opt.tcor.ext1x) {
1082123120Simp		unsigned ext1x = c->opt.tcor.ext1x;
1083123120Simp		c->opt.tcor.ext1x = 0;
1084123120Simp		cx_clock (c->oscfreq, c->txbaud, &clock, &period);
1085123120Simp		c->opt.tcor.clk = clock;
1086123120Simp		c->opt.tcor.ext1x = ext1x;
1087123120Simp	} else {
1088123120Simp		c->opt.tcor.clk = CLK_EXT;
1089123120Simp		period = 1;
1090123120Simp	}
1091123120Simp	outb (TCOR(c->port), BYTE c->opt.tcor);
1092123120Simp	outb (TBPR(c->port), period);
1093123120Simp}
1094123120Simp
1095123120Simp/*
1096123120Simp * Initialize the CD2400 channel.
1097123120Simp */
1098123120Simpvoid cx_setup_chan (cx_chan_t *c)
1099123120Simp{
1100123120Simp	/* set current channel number */
1101123120Simp	outb (CAR(c->port), c->num & 3);
1102123120Simp
1103123120Simp	/* reset the channel */
1104123120Simp	cx_cmd (c->port, CCR_CLRCH);
1105123120Simp
1106123120Simp	/* set LIVR to contain the board and channel numbers */
1107123120Simp	outb (LIVR(c->port), c->board->num << 6 | c->num << 2);
1108123120Simp
1109123120Simp	/* clear DTR, RTS, set TXCout/DTR pin */
1110123120Simp	outb (MSVR_RTS(c->port), 0);
1111123120Simp	outb (MSVR_DTR(c->port), c->mode==M_ASYNC ? 0 : MSV_TXCOUT);
1112123120Simp
1113123120Simp	/* set receiver A buffer physical address */
1114123120Simp	outw (ARBADRU(c->port), (unsigned short) (c->arphys>>16));
1115123120Simp	outw (ARBADRL(c->port), (unsigned short) c->arphys);
1116123120Simp
1117123120Simp	/* set receiver B buffer physical address */
1118123120Simp	outw (BRBADRU(c->port), (unsigned short) (c->brphys>>16));
1119123120Simp	outw (BRBADRL(c->port), (unsigned short) c->brphys);
1120123120Simp
1121123120Simp	/* set transmitter A buffer physical address */
1122123120Simp	outw (ATBADRU(c->port), (unsigned short) (c->atphys>>16));
1123123120Simp	outw (ATBADRL(c->port), (unsigned short) c->atphys);
1124123120Simp
1125123120Simp	/* set transmitter B buffer physical address */
1126123120Simp	outw (BTBADRU(c->port), (unsigned short) (c->btphys>>16));
1127123120Simp	outw (BTBADRL(c->port), (unsigned short) c->btphys);
1128123120Simp
1129123120Simp	c->dtr = 0;
1130123120Simp	c->rts = 0;
1131123120Simp
1132123120Simp	cx_update_chan (c);
1133123120Simp}
1134123120Simp
1135123120Simp/*
1136123120Simp * Control DTR signal for the channel.
1137123120Simp * Turn it on/off.
1138123120Simp */
1139123120Simpvoid cx_set_dtr (cx_chan_t *c, int on)
1140123120Simp{
1141123120Simp	cx_board_t *b = c->board;
1142123120Simp
1143123120Simp	c->dtr = on ? 1 : 0;
1144123120Simp
1145123120Simp	if (b->type == B_SIGMA_2X) {
1146123120Simp		if (on) b->bcr1 |= BCR1_DTR(c->num);
1147123120Simp		else    b->bcr1 &= ~BCR1_DTR(c->num);
1148123120Simp		outw (BCR1(b->port), b->bcr1);
1149123120Simp		return;
1150123120Simp	}
1151123120Simp	if (b->type == B_SIGMA_800) {
1152123120Simp		if (c->num >= 8) {
1153123120Simp			if (on) b->bcr1b |= BCR1800_DTR(c->num);
1154123120Simp			else    b->bcr1b &= ~BCR1800_DTR(c->num);
1155123120Simp			outb (BCR1(b->port+0x10), b->bcr1b);
1156123120Simp		} else {
1157123120Simp			if (on) b->bcr1 |= BCR1800_DTR(c->num);
1158123120Simp			else    b->bcr1 &= ~BCR1800_DTR(c->num);
1159123120Simp			outb (BCR1(b->port), b->bcr1);
1160123120Simp		}
1161123120Simp		return;
1162123120Simp	}
1163123120Simp	if (c->mode == M_ASYNC) {
1164123120Simp		outb (CAR(c->port), c->num & 3);
1165123120Simp		outb (MSVR_DTR(c->port), on ? MSV_DTR : 0);
1166123120Simp		return;
1167123120Simp	}
1168123120Simp
1169123120Simp	switch (c->num) {
1170123120Simp	default:
1171250460Seadler		/* Channels 4..7 and 12..15 in synchronous mode
1172123120Simp		 * have no DTR signal. */
1173123120Simp		break;
1174123120Simp
1175123120Simp	case 1: case 2:  case 3:
1176123120Simp		if (c->type == T_UNIV_RS232)
1177123120Simp			break;
1178123120Simp	case 0:
1179123120Simp		if (on) b->bcr1 |= BCR1_DTR(c->num);
1180123120Simp		else    b->bcr1 &= ~BCR1_DTR(c->num);
1181123120Simp		outw (BCR1(b->port), b->bcr1);
1182123120Simp		break;
1183123120Simp
1184123120Simp	case 9: case 10: case 11:
1185123120Simp		if (c->type == T_UNIV_RS232)
1186123120Simp			break;
1187123120Simp	case 8:
1188123120Simp		if (on) b->bcr1b |= BCR1_DTR(c->num & 3);
1189123120Simp		else    b->bcr1b &= ~BCR1_DTR(c->num & 3);
1190123120Simp		outw (BCR1(b->port+0x10), b->bcr1b);
1191123120Simp		break;
1192123120Simp	}
1193123120Simp}
1194123120Simp
1195123120Simp/*
1196123120Simp * Control RTS signal for the channel.
1197123120Simp * Turn it on/off.
1198123120Simp */
1199123120Simpvoid cx_set_rts (cx_chan_t *c, int on)
1200123120Simp{
1201123120Simp	c->rts = on ? 1 : 0;
1202123120Simp	outb (CAR(c->port), c->num & 3);
1203123120Simp	outb (MSVR_RTS(c->port), on ? MSV_RTS : 0);
1204123120Simp}
1205123120Simp
1206123120Simp/*
1207123120Simp * Get the state of DSR signal of the channel.
1208123120Simp */
1209123120Simpint cx_get_dsr (cx_chan_t *c)
1210123120Simp{
1211123120Simp	unsigned char sigval;
1212123120Simp
1213123120Simp	if (c->board->type == B_SIGMA_2X ||
1214123120Simp	    c->board->type == B_SIGMA_800 ||
1215123120Simp	    c->mode == M_ASYNC) {
1216123120Simp		outb (CAR(c->port), c->num & 3);
1217123120Simp		return (inb (MSVR(c->port)) & MSV_DSR ? 1 : 0);
1218123120Simp	}
1219123120Simp
1220123120Simp	/*
1221123120Simp	 * Channels 4..7 and 12..15 don't have DSR signal available.
1222123120Simp	 */
1223123120Simp	switch (c->num) {
1224123120Simp	default:
1225123120Simp		return (1);
1226123120Simp
1227123120Simp	case 1: case 2:  case 3:
1228123120Simp		if (c->type == T_UNIV_RS232)
1229123120Simp			return (1);
1230123120Simp	case 0:
1231123120Simp		sigval = inw (BSR(c->board->port)) >> 8;
1232123120Simp		break;
1233123120Simp
1234123120Simp	case 9: case 10: case 11:
1235123120Simp		if (c->type == T_UNIV_RS232)
1236123120Simp			return (1);
1237123120Simp	case 8:
1238123120Simp		sigval = inw (BSR(c->board->port+0x10)) >> 8;
1239123120Simp		break;
1240123120Simp	}
1241123120Simp	return (~sigval >> (c->num & 3) & 1);
1242123120Simp}
1243123120Simp
1244123120Simp/*
1245123120Simp * Get the state of CARRIER signal of the channel.
1246123120Simp */
1247123120Simpint cx_get_cd (cx_chan_t *c)
1248123120Simp{
1249123120Simp	unsigned char sigval;
1250123120Simp
1251123120Simp	if (c->board->type == B_SIGMA_2X ||
1252123120Simp	    c->board->type == B_SIGMA_800 ||
1253123120Simp	    c->mode == M_ASYNC) {
1254123120Simp		outb (CAR(c->port), c->num & 3);
1255123120Simp		return (inb (MSVR(c->port)) & MSV_CD ? 1 : 0);
1256123120Simp	}
1257123120Simp
1258123120Simp	/*
1259123120Simp	 * Channels 4..7 and 12..15 don't have CD signal available.
1260123120Simp	 */
1261123120Simp	switch (c->num) {
1262123120Simp	default:
1263123120Simp		return (1);
1264123120Simp
1265123120Simp	case 1: case 2:  case 3:
1266123120Simp		if (c->type == T_UNIV_RS232)
1267123120Simp			return (1);
1268123120Simp	case 0:
1269123120Simp		sigval = inw (BSR(c->board->port)) >> 8;
1270123120Simp		break;
1271123120Simp
1272123120Simp	case 9: case 10: case 11:
1273123120Simp		if (c->type == T_UNIV_RS232)
1274123120Simp			return (1);
1275123120Simp	case 8:
1276123120Simp		sigval = inw (BSR(c->board->port+0x10)) >> 8;
1277123120Simp		break;
1278123120Simp	}
1279123120Simp	return (~sigval >> 4 >> (c->num & 3) & 1);
1280123120Simp}
1281123120Simp
1282123120Simp/*
1283123120Simp * Get the state of CTS signal of the channel.
1284123120Simp */
1285123120Simpint cx_get_cts (cx_chan_t *c)
1286123120Simp{
1287123120Simp	outb (CAR(c->port), c->num & 3);
1288123120Simp	return (inb (MSVR(c->port)) & MSV_CTS ? 1 : 0);
1289123120Simp}
1290123120Simp
1291123120Simp/*
1292123120Simp * Compute CD2400 clock values.
1293123120Simp */
1294123120Simpvoid cx_clock (long hz, long ba, int *clk, int *div)
1295123120Simp{
1296123120Simp	static short clocktab[] = { 8, 32, 128, 512, 2048, 0 };
1297123120Simp
1298123120Simp	for (*clk=0; clocktab[*clk]; ++*clk) {
1299123120Simp		long c = ba * clocktab[*clk];
1300123120Simp		if (hz <= c*256) {
1301123120Simp			*div = (2 * hz + c) / (2 * c) - 1;
1302123120Simp			return;
1303123120Simp		}
1304123120Simp	}
1305123120Simp	/* Incorrect baud rate.  Return some meaningful values. */
1306123120Simp	*clk = 0;
1307123120Simp	*div = 255;
1308123120Simp}
1309123120Simp
1310123120Simp/*
1311123120Simp * Turn LED on/off.
1312123120Simp */
1313123120Simpvoid cx_led (cx_board_t *b, int on)
1314123120Simp{
1315123120Simp	switch (b->type) {
1316123120Simp	case B_SIGMA_2X:
1317123120Simp		if (on) b->bcr0 |= BCR02X_LED;
1318123120Simp		else    b->bcr0 &= ~BCR02X_LED;
1319123120Simp		outb (BCR0(b->port), b->bcr0);
1320123120Simp		break;
1321123120Simp	}
1322123120Simp}
1323123120Simp
1324123120Simpvoid cx_disable_dma (cx_board_t *b)
1325123120Simp{
1326123120Simp#ifndef NDIS_MINIPORT_DRIVER
1327123120Simp	/* Disable DMA channel. */
1328123120Simp	outb (DMA_MASK, (b->dma & 3) | DMA_MASK_CLEAR);
1329123120Simp#endif
1330123120Simp}
1331123120Simp
1332123120Simpcx_board_opt_t board_opt_dflt = { /* board options */
1333123120Simp	BUS_NORMAL,		/* normal bus master timing */
1334123120Simp};
1335123120Simp
1336123120Simpcx_chan_opt_t chan_opt_dflt = { /* mode-independent options */
1337123120Simp	{			/* cor4 */
1338123120Simp		7,		/* FIFO threshold, odd is better */
1339123120Simp		0,
1340123120Simp		0,              /* don't detect 1 to 0 on CTS */
1341123120Simp		1,		/* detect 1 to 0 on CD */
1342123120Simp		0,              /* detect 1 to 0 on DSR */
1343123120Simp	},
1344123120Simp	{			/* cor5 */
1345123120Simp		0,		/* receive flow control FIFO threshold */
1346123120Simp		0,
1347123120Simp		0,              /* don't detect 0 to 1 on CTS */
1348123120Simp		1,		/* detect 0 to 1 on CD */
1349123120Simp		0,              /* detect 0 to 1 on DSR */
1350123120Simp	},
1351123120Simp	{			/* rcor */
1352123120Simp		0,		/* dummy clock source */
1353123120Simp		ENCOD_NRZ,      /* NRZ mode */
1354123120Simp		0,              /* disable DPLL */
1355123120Simp		0,
1356123120Simp		0,		/* transmit line value */
1357123120Simp	},
1358123120Simp	{			/* tcor */
1359123120Simp		0,
1360123120Simp		0,		/* local loopback mode */
1361123120Simp		0,
1362123120Simp		1,		/* external 1x clock mode */
1363123120Simp		0,
1364123120Simp		0,		/* dummy transmit clock source */
1365123120Simp	},
1366123120Simp};
1367123120Simp
1368123120Simpcx_opt_async_t opt_async_dflt = { /* default async options */
1369123120Simp	{			/* cor1 */
1370123120Simp		8-1,		/* 8-bit char length */
1371123120Simp		0,		/* don't ignore parity */
1372123120Simp		PARM_NOPAR,	/* no parity */
1373123120Simp		PAR_EVEN,	/* even parity */
1374123120Simp	},
1375123120Simp	{			/* cor2 */
1376123120Simp		0,              /* disable automatic DSR */
1377123120Simp		1,              /* enable automatic CTS */
1378123120Simp		0,              /* disable automatic RTS */
1379123120Simp		0,		/* no remote loopback */
1380123120Simp		0,
1381123120Simp		0,              /* disable embedded cmds */
1382123120Simp		0,		/* disable XON/XOFF */
1383123120Simp		0,		/* disable XANY */
1384123120Simp	},
1385123120Simp	{			/* cor3 */
1386123120Simp		STOPB_1,	/* 1 stop bit */
1387123120Simp		0,
1388123120Simp		0,		/* disable special char detection */
1389123120Simp		FLOWCC_PASS,	/* pass flow ctl chars to the host */
1390123120Simp		0,		/* range detect disable */
1391123120Simp		0,		/* disable extended spec. char detect */
1392123120Simp	},
1393123120Simp	{			/* cor6 */
1394123120Simp		PERR_INTR,	/* generate exception on parity errors */
1395123120Simp		BRK_INTR,	/* generate exception on break condition */
1396123120Simp		0,		/* don't translate NL to CR on input */
1397123120Simp		0,		/* don't translate CR to NL on input */
1398123120Simp		0,		/* don't discard CR on input */
1399123120Simp	},
1400123120Simp	{			/* cor7 */
1401123120Simp		0,		/* don't translate CR to NL on output */
1402123120Simp		0,		/* don't translate NL to CR on output */
1403123120Simp		0,
1404123120Simp		0,		/* don't process flow ctl err chars */
1405123120Simp		0,		/* disable LNext option */
1406123120Simp		0,		/* don't strip 8 bit on input */
1407123120Simp	},
1408123120Simp	0, 0, 0, 0, 0, 0, 0,	/* clear schr1-4, scrl, scrh, lnxt */
1409123120Simp};
1410123120Simp
1411123120Simpcx_opt_hdlc_t opt_hdlc_dflt = { /* default hdlc options */
1412123120Simp	{			/* cor1 */
1413123120Simp		2,              /* 2 inter-frame flags */
1414123120Simp		0,		/* no-address mode */
1415123120Simp		CLRDET_DISABLE,	/* disable clear detect */
1416123120Simp		AFLO_1OCT,	/* 1-byte address field length */
1417123120Simp	},
1418123120Simp	{			/* cor2 */
1419123120Simp		0,		/* disable automatic DSR */
1420123120Simp		0,              /* disable automatic CTS */
1421123120Simp		0,              /* disable automatic RTS */
1422123120Simp		0,
1423123120Simp		CRC_INVERT,	/* use CRC V.41 */
1424123120Simp		0,
1425123120Simp		FCS_NOTPASS,	/* don't pass received CRC to the host */
1426123120Simp		0,
1427123120Simp	},
1428123120Simp	{			/* cor3 */
1429123120Simp		0,              /* 0 pad characters sent */
1430123120Simp		IDLE_FLAG,	/* idle in flag */
1431123120Simp		0,		/* enable FCS */
1432123120Simp		FCSP_ONES,	/* FCS preset to all ones (V.41) */
1433123120Simp		SYNC_AA,	/* use AAh as sync char */
1434123120Simp		0,              /* disable pad characters */
1435123120Simp	},
1436123120Simp	0, 0, 0, 0,		/* clear rfar1-4 */
1437123120Simp	POLY_V41,		/* use V.41 CRC polynomial */
1438123120Simp};
1439