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