cxddk.c revision 315221
1/*- 2 * Cronyx-Sigma Driver Development Kit. 3 * 4 * Copyright (C) 1998 Cronyx Engineering. 5 * Author: Pavel Novikov, <pavel@inr.net.kiae.su> 6 * 7 * Copyright (C) 1998-2003 Cronyx Engineering. 8 * Author: Roman Kurakin, <rik@cronyx.ru> 9 * 10 * This software is distributed with NO WARRANTIES, not even the implied 11 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * Authors grant any other persons or organisations permission to use 14 * or modify this software as long as this message is kept with the software, 15 * all derivative works or modified versions. 16 * 17 * Cronyx Id: cxddk.c,v 1.1.2.2 2003/11/27 14:24:50 rik Exp $ 18 */ 19#include <sys/cdefs.h> 20__FBSDID("$FreeBSD: stable/11/sys/dev/cx/cxddk.c 315221 2017-03-14 02:06:03Z pfg $"); 21 22#include <dev/cx/machdep.h> 23#include <dev/cx/cxddk.h> 24#include <dev/cx/cxreg.h> 25#include <dev/cx/cronyxfw.h> 26#include <dev/cx/csigmafw.h> 27 28#define BYTE *(unsigned char*)& 29 30/* standard base port set */ 31static short porttab [] = { 32 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 33 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 34}; 35 36/* 37 * Compute the optimal size of the receive buffer. 38 */ 39static int cx_compute_buf_len (cx_chan_t *c) 40{ 41 int rbsz; 42 if (c->mode == M_ASYNC) { 43 rbsz = (c->rxbaud + 800 - 1) / 800 * 2; 44 if (rbsz < 4) 45 rbsz = 4; 46 else if (rbsz > DMABUFSZ) 47 rbsz = DMABUFSZ; 48 } 49 else 50 rbsz = DMABUFSZ; 51 52 return rbsz; 53} 54 55/* 56 * Auto-detect the installed adapters. 57 */ 58int cx_find (port_t *board_ports) 59{ 60 int i, n; 61 62 for (i=0, n=0; porttab[i] && n<NBRD; i++) 63 if (cx_probe_board (porttab[i], -1, -1)) 64 board_ports[n++] = porttab[i]; 65 return n; 66} 67 68/* 69 * Initialize the adapter. 70 */ 71int cx_open_board (cx_board_t *b, int num, port_t port, int irq, int dma) 72{ 73 cx_chan_t *c; 74 75 if (num >= NBRD || ! cx_probe_board (port, irq, dma)) 76 return 0; 77 78 /* init callback pointers */ 79 for (c=b->chan; c<b->chan+NCHAN; ++c) { 80 c->call_on_tx = 0; 81 c->call_on_rx = 0; 82 c->call_on_msig = 0; 83 c->call_on_err = 0; 84 } 85 86 cx_init (b, num, port, irq, dma); 87 88 /* Loading firmware */ 89 if (! cx_setup_board (b, csigma_fw_data, csigma_fw_len, csigma_fw_tvec)) 90 return 0; 91 return 1; 92} 93 94/* 95 * Shutdown the adapter. 96 */ 97void cx_close_board (cx_board_t *b) 98{ 99 cx_setup_board (b, 0, 0, 0); 100 101 /* Reset the controller. */ 102 outb (BCR0(b->port), 0); 103 if (b->chan[8].type || b->chan[12].type) 104 outb (BCR0(b->port+0x10), 0); 105} 106 107/* 108 * Start the channel. 109 */ 110void cx_start_chan (cx_chan_t *c, cx_buf_t *cb, unsigned long phys) 111{ 112 int command = 0; 113 int mode = 0; 114 int ier = 0; 115 int rbsz; 116 117 c->overflow = 0; 118 119 /* Setting up buffers */ 120 if (cb) { 121 c->arbuf = cb->rbuffer[0]; 122 c->brbuf = cb->rbuffer[1]; 123 c->atbuf = cb->tbuffer[0]; 124 c->btbuf = cb->tbuffer[1]; 125 c->arphys = phys + ((char*)c->arbuf - (char*)cb); 126 c->brphys = phys + ((char*)c->brbuf - (char*)cb); 127 c->atphys = phys + ((char*)c->atbuf - (char*)cb); 128 c->btphys = phys + ((char*)c->btbuf - (char*)cb); 129 } 130 131 /* Set current channel number */ 132 outb (CAR(c->port), c->num & 3); 133 134 /* set receiver A buffer physical address */ 135 outw (ARBADRU(c->port), (unsigned short) (c->arphys>>16)); 136 outw (ARBADRL(c->port), (unsigned short) c->arphys); 137 138 /* set receiver B buffer physical address */ 139 outw (BRBADRU(c->port), (unsigned short) (c->brphys>>16)); 140 outw (BRBADRL(c->port), (unsigned short) c->brphys); 141 142 /* set transmitter A buffer physical address */ 143 outw (ATBADRU(c->port), (unsigned short) (c->atphys>>16)); 144 outw (ATBADRL(c->port), (unsigned short) c->atphys); 145 146 /* set transmitter B buffer physical address */ 147 outw (BTBADRU(c->port), (unsigned short) (c->btphys>>16)); 148 outw (BTBADRL(c->port), (unsigned short) c->btphys); 149 150 /* rx */ 151 command |= CCR_ENRX; 152 ier |= IER_RXD; 153 if (c->board->dma) { 154 mode |= CMR_RXDMA; 155 if (c->mode == M_ASYNC) 156 ier |= IER_RET; 157 } 158 159 /* tx */ 160 command |= CCR_ENTX; 161 ier |= (c->mode == M_ASYNC) ? IER_TXD : (IER_TXD | IER_TXMPTY); 162 if (c->board->dma) 163 mode |= CMR_TXDMA; 164 165 /* Set mode */ 166 outb (CMR(c->port), mode | (c->mode == M_ASYNC ? CMR_ASYNC : CMR_HDLC)); 167 168 /* Clear and initialize channel */ 169 cx_cmd (c->port, CCR_CLRCH); 170 cx_cmd (c->port, CCR_INITCH | command); 171 if (c->mode == M_ASYNC) 172 cx_cmd (c->port, CCR_ENTX); 173 174 /* Start receiver */ 175 rbsz = cx_compute_buf_len(c); 176 outw (ARBCNT(c->port), rbsz); 177 outw (BRBCNT(c->port), rbsz); 178 outw (ARBSTS(c->port), BSTS_OWN24); 179 outw (BRBSTS(c->port), BSTS_OWN24); 180 181 if (c->mode == M_ASYNC) 182 ier |= IER_MDM; 183 184 /* Enable interrupts */ 185 outb (IER(c->port), ier); 186 187 /* Clear DTR and RTS */ 188 cx_set_dtr (c, 0); 189 cx_set_rts (c, 0); 190} 191 192/* 193 * Turn the receiver on/off. 194 */ 195void cx_enable_receive (cx_chan_t *c, int on) 196{ 197 unsigned char ier; 198 199 if (cx_receive_enabled(c) && ! on) { 200 outb (CAR(c->port), c->num & 3); 201 if (c->mode == M_ASYNC) { 202 ier = inb (IER(c->port)); 203 outb (IER(c->port), ier & ~ (IER_RXD | IER_RET)); 204 } 205 cx_cmd (c->port, CCR_DISRX); 206 } else if (! cx_receive_enabled(c) && on) { 207 outb (CAR(c->port), c->num & 3); 208 ier = inb (IER(c->port)); 209 if (c->mode == M_ASYNC) 210 outb (IER(c->port), ier | (IER_RXD | IER_RET)); 211 else 212 outb (IER(c->port), ier | IER_RXD); 213 cx_cmd (c->port, CCR_ENRX); 214 } 215} 216 217/* 218 * Turn the transmiter on/off. 219 */ 220void cx_enable_transmit (cx_chan_t *c, int on) 221{ 222 if (cx_transmit_enabled(c) && ! on) { 223 outb (CAR(c->port), c->num & 3); 224 if (c->mode != M_ASYNC) 225 outb (STCR(c->port), STC_ABORTTX | STC_SNDSPC); 226 cx_cmd (c->port, CCR_DISTX); 227 } else if (! cx_transmit_enabled(c) && on) { 228 outb (CAR(c->port), c->num & 3); 229 cx_cmd (c->port, CCR_ENTX); 230 } 231} 232 233/* 234 * Get channel status. 235 */ 236int cx_receive_enabled (cx_chan_t *c) 237{ 238 outb (CAR(c->port), c->num & 3); 239 return (inb (CSR(c->port)) & CSRA_RXEN) != 0; 240} 241 242int cx_transmit_enabled (cx_chan_t *c) 243{ 244 outb (CAR(c->port), c->num & 3); 245 return (inb (CSR(c->port)) & CSRA_TXEN) != 0; 246} 247 248unsigned long cx_get_baud (cx_chan_t *c) 249{ 250 return (c->opt.tcor.clk == CLK_EXT) ? 0 : c->txbaud; 251} 252 253int cx_get_loop (cx_chan_t *c) 254{ 255 return c->opt.tcor.llm ? 1 : 0; 256} 257 258int cx_get_nrzi (cx_chan_t *c) 259{ 260 return c->opt.rcor.encod == ENCOD_NRZI; 261} 262 263int cx_get_dpll (cx_chan_t *c) 264{ 265 return c->opt.rcor.dpll ? 1 : 0; 266} 267 268void cx_set_baud (cx_chan_t *c, unsigned long bps) 269{ 270 int clock, period; 271 272 c->txbaud = c->rxbaud = bps; 273 274 /* Set current channel number */ 275 outb (CAR(c->port), c->num & 3); 276 if (bps) { 277 if (c->mode == M_ASYNC || c->opt.rcor.dpll || c->opt.tcor.llm) { 278 /* Receive baud - internal */ 279 cx_clock (c->oscfreq, c->rxbaud, &clock, &period); 280 c->opt.rcor.clk = clock; 281 outb (RCOR(c->port), BYTE c->opt.rcor); 282 outb (RBPR(c->port), period); 283 } else { 284 /* Receive baud - external */ 285 c->opt.rcor.clk = CLK_EXT; 286 outb (RCOR(c->port), BYTE c->opt.rcor); 287 outb (RBPR(c->port), 1); 288 } 289 290 /* Transmit baud - internal */ 291 cx_clock (c->oscfreq, c->txbaud, &clock, &period); 292 c->opt.tcor.clk = clock; 293 c->opt.tcor.ext1x = 0; 294 outb (TBPR(c->port), period); 295 } else if (c->mode != M_ASYNC) { 296 /* External clock - disable local loopback and DPLL */ 297 c->opt.tcor.llm = 0; 298 c->opt.rcor.dpll = 0; 299 300 /* Transmit baud - external */ 301 c->opt.tcor.ext1x = 1; 302 c->opt.tcor.clk = CLK_EXT; 303 outb (TBPR(c->port), 1); 304 305 /* Receive baud - external */ 306 c->opt.rcor.clk = CLK_EXT; 307 outb (RCOR(c->port), BYTE c->opt.rcor); 308 outb (RBPR(c->port), 1); 309 } 310 if (c->opt.tcor.llm) 311 outb (COR2(c->port), (BYTE c->hopt.cor2) & ~3); 312 else 313 outb (COR2(c->port), BYTE c->hopt.cor2); 314 outb (TCOR(c->port), BYTE c->opt.tcor); 315} 316 317void cx_set_loop (cx_chan_t *c, int on) 318{ 319 if (! c->txbaud) 320 return; 321 322 c->opt.tcor.llm = on ? 1 : 0; 323 cx_set_baud (c, c->txbaud); 324} 325 326void cx_set_dpll (cx_chan_t *c, int on) 327{ 328 if (! c->txbaud) 329 return; 330 331 c->opt.rcor.dpll = on ? 1 : 0; 332 cx_set_baud (c, c->txbaud); 333} 334 335void cx_set_nrzi (cx_chan_t *c, int nrzi) 336{ 337 c->opt.rcor.encod = (nrzi ? ENCOD_NRZI : ENCOD_NRZ); 338 outb (CAR(c->port), c->num & 3); 339 outb (RCOR(c->port), BYTE c->opt.rcor); 340} 341 342static int cx_send (cx_chan_t *c, char *data, int len, 343 void *attachment) 344{ 345 unsigned char *buf; 346 port_t cnt_port, sts_port; 347 void **attp; 348 349 /* Set the current channel number. */ 350 outb (CAR(c->port), c->num & 3); 351 352 /* Determine the buffer order. */ 353 if (inb (DMABSTS(c->port)) & DMABSTS_NTBUF) { 354 if (inb (BTBSTS(c->port)) & BSTS_OWN24) { 355 buf = c->atbuf; 356 cnt_port = ATBCNT(c->port); 357 sts_port = ATBSTS(c->port); 358 attp = &c->attach[0]; 359 } else { 360 buf = c->btbuf; 361 cnt_port = BTBCNT(c->port); 362 sts_port = BTBSTS(c->port); 363 attp = &c->attach[1]; 364 } 365 } else { 366 if (inb (ATBSTS(c->port)) & BSTS_OWN24) { 367 buf = c->btbuf; 368 cnt_port = BTBCNT(c->port); 369 sts_port = BTBSTS(c->port); 370 attp = &c->attach[1]; 371 } else { 372 buf = c->atbuf; 373 cnt_port = ATBCNT(c->port); 374 sts_port = ATBSTS(c->port); 375 attp = &c->attach[0]; 376 } 377 } 378 /* Is it busy? */ 379 if (inb (sts_port) & BSTS_OWN24) 380 return -1; 381 382 memcpy (buf, data, len); 383 *attp = attachment; 384 385 /* Start transmitter. */ 386 outw (cnt_port, len); 387 outb (sts_port, BSTS_EOFR | BSTS_INTR | BSTS_OWN24); 388 389 /* Enable TXMPTY interrupt, 390 * to catch the case when the second buffer is empty. */ 391 if (c->mode != M_ASYNC) { 392 if ((inb(ATBSTS(c->port)) & BSTS_OWN24) && 393 (inb(BTBSTS(c->port)) & BSTS_OWN24)) { 394 outb (IER(c->port), IER_RXD | IER_TXD | IER_TXMPTY); 395 } else 396 outb (IER(c->port), IER_RXD | IER_TXD); 397 } 398 return 0; 399} 400 401/* 402 * Number of free buffs 403 */ 404int cx_buf_free (cx_chan_t *c) 405{ 406 return ! (inb (ATBSTS(c->port)) & BSTS_OWN24) + 407 ! (inb (BTBSTS(c->port)) & BSTS_OWN24); 408} 409 410/* 411 * Send the data packet. 412 */ 413int cx_send_packet (cx_chan_t *c, char *data, int len, void *attachment) 414{ 415 if (len >= DMABUFSZ) 416 return -2; 417 if (c->mode == M_ASYNC) { 418 static char buf [DMABUFSZ]; 419 char *p, *t = buf; 420 421 /* Async -- double all nulls. */ 422 for (p=data; p < data+len && t < buf+DMABUFSZ-1; ++p) 423 if ((*t++ = *p) == 0) 424 *t++ = 0; 425 return cx_send (c, buf, t-buf, attachment); 426 } 427 return cx_send (c, data, len, attachment); 428} 429 430static int cx_receive_interrupt (cx_chan_t *c) 431{ 432 unsigned short risr; 433 int len = 0, rbsz; 434 435 ++c->rintr; 436 risr = inw (RISR(c->port)); 437 438 /* Compute optimal receiver buffer length */ 439 rbsz = cx_compute_buf_len(c); 440 if (c->mode == M_ASYNC && (risr & RISA_TIMEOUT)) { 441 unsigned long rcbadr = (unsigned short) inw (RCBADRL(c->port)) | 442 (long) inw (RCBADRU(c->port)) << 16; 443 unsigned char *buf = NULL; 444 port_t cnt_port = 0, sts_port = 0; 445 446 if (rcbadr >= c->brphys && rcbadr < c->brphys+DMABUFSZ) { 447 buf = c->brbuf; 448 len = rcbadr - c->brphys; 449 cnt_port = BRBCNT(c->port); 450 sts_port = BRBSTS(c->port); 451 } else if (rcbadr >= c->arphys && rcbadr < c->arphys+DMABUFSZ) { 452 buf = c->arbuf; 453 len = rcbadr - c->arphys; 454 cnt_port = ARBCNT(c->port); 455 sts_port = ARBSTS(c->port); 456 } 457 458 if (len) { 459 c->ibytes += len; 460 c->received_data = buf; 461 c->received_len = len; 462 463 /* Restart receiver. */ 464 outw (cnt_port, rbsz); 465 outb (sts_port, BSTS_OWN24); 466 } 467 return (REOI_TERMBUFF); 468 } 469 470 /* Receive errors. */ 471 if (risr & RIS_OVERRUN) { 472 ++c->ierrs; 473 if (c->call_on_err) 474 c->call_on_err (c, CX_OVERRUN); 475 } else if (c->mode != M_ASYNC && (risr & RISH_CRCERR)) { 476 ++c->ierrs; 477 if (c->call_on_err) 478 c->call_on_err (c, CX_CRC); 479 } else if (c->mode != M_ASYNC && (risr & (RISH_RXABORT | RISH_RESIND))) { 480 ++c->ierrs; 481 if (c->call_on_err) 482 c->call_on_err (c, CX_FRAME); 483 } else if (c->mode == M_ASYNC && (risr & RISA_PARERR)) { 484 ++c->ierrs; 485 if (c->call_on_err) 486 c->call_on_err (c, CX_CRC); 487 } else if (c->mode == M_ASYNC && (risr & RISA_FRERR)) { 488 ++c->ierrs; 489 if (c->call_on_err) 490 c->call_on_err (c, CX_FRAME); 491 } else if (c->mode == M_ASYNC && (risr & RISA_BREAK)) { 492 if (c->call_on_err) 493 c->call_on_err (c, CX_BREAK); 494 } else if (! (risr & RIS_EOBUF)) { 495 ++c->ierrs; 496 } else { 497 /* Handle received data. */ 498 len = (risr & RIS_BB) ? inw(BRBCNT(c->port)) : inw(ARBCNT(c->port)); 499 500 if (len > DMABUFSZ) { 501 /* Fatal error: actual DMA transfer size 502 * exceeds our buffer size. It could be caused 503 * by incorrectly programmed DMA register or 504 * hardware fault. Possibly, should panic here. */ 505 len = DMABUFSZ; 506 } else if (c->mode != M_ASYNC && ! (risr & RIS_EOFR)) { 507 /* The received frame does not fit in the DMA buffer. 508 * It could be caused by serial lie noise, 509 * or if the peer has too big MTU. */ 510 if (! c->overflow) { 511 if (c->call_on_err) 512 c->call_on_err (c, CX_OVERFLOW); 513 c->overflow = 1; 514 ++c->ierrs; 515 } 516 } else if (! c->overflow) { 517 if (risr & RIS_BB) { 518 c->received_data = c->brbuf; 519 c->received_len = len; 520 } else { 521 c->received_data = c->arbuf; 522 c->received_len = len; 523 } 524 if (c->mode != M_ASYNC) 525 ++c->ipkts; 526 c->ibytes += len; 527 } else 528 c->overflow = 0; 529 } 530 531 /* Restart receiver. */ 532 if (! (inb (ARBSTS(c->port)) & BSTS_OWN24)) { 533 outw (ARBCNT(c->port), rbsz); 534 outb (ARBSTS(c->port), BSTS_OWN24); 535 } 536 if (! (inb (BRBSTS(c->port)) & BSTS_OWN24)) { 537 outw (BRBCNT(c->port), rbsz); 538 outb (BRBSTS(c->port), BSTS_OWN24); 539 } 540 541 /* Discard exception characters. */ 542 if ((risr & RISA_SCMASK) && c->aopt.cor2.ixon) 543 return (REOI_DISCEXC); 544 else 545 return (0); 546} 547 548static void cx_transmit_interrupt (cx_chan_t *c) 549{ 550 unsigned char tisr; 551 int len = 0; 552 553 ++c->tintr; 554 tisr = inb (TISR(c->port)); 555 if (tisr & TIS_UNDERRUN) { /* Transmit underrun error */ 556 if (c->call_on_err) 557 c->call_on_err (c, CX_UNDERRUN); 558 ++c->oerrs; 559 } else if (tisr & (TIS_EOBUF | TIS_TXEMPTY | TIS_TXDATA)) { 560 /* Call processing function */ 561 if (tisr & TIS_BB) { 562 len = inw(BTBCNT(c->port)); 563 if (c->call_on_tx) 564 c->call_on_tx (c, c->attach[1], len); 565 } else { 566 len = inw(ATBCNT(c->port)); 567 if (c->call_on_tx) 568 c->call_on_tx (c, c->attach[0], len); 569 } 570 if (c->mode != M_ASYNC && len != 0) 571 ++c->opkts; 572 c->obytes += len; 573 } 574 575 /* Enable TXMPTY interrupt, 576 * to catch the case when the second buffer is empty. */ 577 if (c->mode != M_ASYNC) { 578 if ((inb (ATBSTS(c->port)) & BSTS_OWN24) && 579 (inb (BTBSTS(c->port)) & BSTS_OWN24)) { 580 outb (IER(c->port), IER_RXD | IER_TXD | IER_TXMPTY); 581 } else 582 outb (IER(c->port), IER_RXD | IER_TXD); 583 } 584} 585 586void cx_int_handler (cx_board_t *b) 587{ 588 unsigned char livr; 589 cx_chan_t *c; 590 591 while (! (inw (BSR(b->port)) & BSR_NOINTR)) { 592 /* Enter the interrupt context, using IACK bus cycle. 593 Read the local interrupt vector register. */ 594 livr = inb (IACK(b->port, BRD_INTR_LEVEL)); 595 c = b->chan + (livr>>2 & 0xf); 596 if (c->type == T_NONE) 597 continue; 598 switch (livr & 3) { 599 case LIV_MODEM: /* modem interrupt */ 600 ++c->mintr; 601 if (c->call_on_msig) 602 c->call_on_msig (c); 603 outb (MEOIR(c->port), 0); 604 break; 605 case LIV_EXCEP: /* receive exception */ 606 case LIV_RXDATA: /* receive interrupt */ 607 outb (REOIR(c->port), cx_receive_interrupt (c)); 608 if (c->call_on_rx && c->received_data) { 609 c->call_on_rx (c, c->received_data, 610 c->received_len); 611 c->received_data = 0; 612 } 613 break; 614 case LIV_TXDATA: /* transmit interrupt */ 615 cx_transmit_interrupt (c); 616 outb (TEOIR(c->port), 0); 617 break; 618 } 619 } 620} 621 622/* 623 * Register event processing functions 624 */ 625void cx_register_transmit (cx_chan_t *c, 626 void (*func) (cx_chan_t *c, void *attachment, int len)) 627{ 628 c->call_on_tx = func; 629} 630 631void cx_register_receive (cx_chan_t *c, 632 void (*func) (cx_chan_t *c, char *data, int len)) 633{ 634 c->call_on_rx = func; 635} 636 637void cx_register_modem (cx_chan_t *c, void (*func) (cx_chan_t *c)) 638{ 639 c->call_on_msig = func; 640} 641 642void cx_register_error (cx_chan_t *c, void (*func) (cx_chan_t *c, int data)) 643{ 644 c->call_on_err = func; 645} 646 647/* 648 * Async protocol functions. 649 */ 650 651/* 652 * Enable/disable transmitter. 653 */ 654void cx_transmitter_ctl (cx_chan_t *c,int start) 655{ 656 outb (CAR(c->port), c->num & 3); 657 cx_cmd (c->port, start ? CCR_ENTX : CCR_DISTX); 658} 659 660/* 661 * Discard all data queued in transmitter. 662 */ 663void cx_flush_transmit (cx_chan_t *c) 664{ 665 outb (CAR(c->port), c->num & 3); 666 cx_cmd (c->port, CCR_CLRTX); 667} 668 669/* 670 * Send the XON/XOFF flow control symbol. 671 */ 672void cx_xflow_ctl (cx_chan_t *c, int on) 673{ 674 outb (CAR(c->port), c->num & 3); 675 outb (STCR(c->port), STC_SNDSPC | (on ? STC_SSPC_1 : STC_SSPC_2)); 676} 677 678/* 679 * Send the break signal for a given number of milliseconds. 680 */ 681void cx_send_break (cx_chan_t *c, int msec) 682{ 683 static unsigned char buf [128]; 684 unsigned char *p; 685 686 p = buf; 687 *p++ = 0; /* extended transmit command */ 688 *p++ = 0x81; /* send break */ 689 690 if (msec > 10000) /* max 10 seconds */ 691 msec = 10000; 692 if (msec < 10) /* min 10 msec */ 693 msec = 10; 694 while (msec > 0) { 695 int ms = 250; /* 250 msec */ 696 if (ms > msec) 697 ms = msec; 698 msec -= ms; 699 *p++ = 0; /* extended transmit command */ 700 *p++ = 0x82; /* insert delay */ 701 *p++ = ms; 702 } 703 *p++ = 0; /* extended transmit command */ 704 *p++ = 0x83; /* stop break */ 705 706 cx_send (c, buf, p-buf, 0); 707} 708 709/* 710 * Set async parameters. 711 */ 712void cx_set_async_param (cx_chan_t *c, int baud, int bits, int parity, 713 int stop2, int ignpar, int rtscts, 714 int ixon, int ixany, int symstart, int symstop) 715{ 716 int clock, period; 717 cx_cor1_async_t cor1; 718 719 /* Set character length and parity mode. */ 720 BYTE cor1 = 0; 721 cor1.charlen = bits - 1; 722 cor1.parmode = parity ? PARM_NORMAL : PARM_NOPAR; 723 cor1.parity = parity==1 ? PAR_ODD : PAR_EVEN; 724 cor1.ignpar = ignpar ? 1 : 0; 725 726 /* Enable/disable hardware CTS. */ 727 c->aopt.cor2.ctsae = rtscts ? 1 : 0; 728 729 /* Enable extended transmit command mode. 730 * Unfortunately, there is no other method for sending break. */ 731 c->aopt.cor2.etc = 1; 732 733 /* Enable/disable hardware XON/XOFF. */ 734 c->aopt.cor2.ixon = ixon ? 1 : 0; 735 c->aopt.cor2.ixany = ixany ? 1 : 0; 736 737 /* Set the number of stop bits. */ 738 if (stop2) 739 c->aopt.cor3.stopb = STOPB_2; 740 else 741 c->aopt.cor3.stopb = STOPB_1; 742 743 /* Disable/enable passing XON/XOFF chars to the host. */ 744 c->aopt.cor3.scde = ixon ? 1 : 0; 745 c->aopt.cor3.flowct = ixon ? FLOWCC_NOTPASS : FLOWCC_PASS; 746 747 c->aopt.schr1 = symstart; /* XON */ 748 c->aopt.schr2 = symstop; /* XOFF */ 749 750 /* Set current channel number. */ 751 outb (CAR(c->port), c->num & 3); 752 753 /* Set up clock values. */ 754 if (baud) { 755 c->rxbaud = c->txbaud = baud; 756 757 /* Receiver. */ 758 cx_clock (c->oscfreq, c->rxbaud, &clock, &period); 759 c->opt.rcor.clk = clock; 760 outb (RCOR(c->port), BYTE c->opt.rcor); 761 outb (RBPR(c->port), period); 762 763 /* Transmitter. */ 764 cx_clock (c->oscfreq, c->txbaud, &clock, &period); 765 c->opt.tcor.clk = clock; 766 c->opt.tcor.ext1x = 0; 767 outb (TCOR(c->port), BYTE c->opt.tcor); 768 outb (TBPR(c->port), period); 769 } 770 outb (COR2(c->port), BYTE c->aopt.cor2); 771 outb (COR3(c->port), BYTE c->aopt.cor3); 772 outb (SCHR1(c->port), c->aopt.schr1); 773 outb (SCHR2(c->port), c->aopt.schr2); 774 775 if (BYTE c->aopt.cor1 != BYTE cor1) { 776 BYTE c->aopt.cor1 = BYTE cor1; 777 outb (COR1(c->port), BYTE c->aopt.cor1); 778 /* Any change to COR1 require reinitialization. */ 779 /* Unfortunately, it may cause transmitter glitches... */ 780 cx_cmd (c->port, CCR_INITCH); 781 } 782} 783 784/* 785 * Set mode: M_ASYNC or M_HDLC. 786 * Both receiver and transmitter are disabled. 787 */ 788int cx_set_mode (cx_chan_t *c, int mode) 789{ 790 if (mode == M_HDLC) { 791 if (c->type == T_ASYNC) 792 return -1; 793 794 if (c->mode == M_HDLC) 795 return 0; 796 797 c->mode = M_HDLC; 798 } else if (mode == M_ASYNC) { 799 if (c->type == T_SYNC_RS232 || 800 c->type == T_SYNC_V35 || 801 c->type == T_SYNC_RS449) 802 return -1; 803 804 if (c->mode == M_ASYNC) 805 return 0; 806 807 c->mode = M_ASYNC; 808 c->opt.tcor.ext1x = 0; 809 c->opt.tcor.llm = 0; 810 c->opt.rcor.dpll = 0; 811 c->opt.rcor.encod = ENCOD_NRZ; 812 if (! c->txbaud || ! c->rxbaud) 813 c->txbaud = c->rxbaud = 9600; 814 } else 815 return -1; 816 817 cx_setup_chan (c); 818 cx_start_chan (c, 0, 0); 819 cx_enable_receive (c, 0); 820 cx_enable_transmit (c, 0); 821 return 0; 822} 823 824/* 825 * Set port type for old models of Sigma 826 */ 827void cx_set_port (cx_chan_t *c, int iftype) 828{ 829 if (c->board->type == B_SIGMA_XXX) { 830 switch (c->num) { 831 case 0: 832 if ((c->board->if0type != 0) == (iftype != 0)) 833 return; 834 c->board->if0type = iftype; 835 c->board->bcr0 &= ~BCR0_UMASK; 836 if (c->board->if0type && 837 (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35)) 838 c->board->bcr0 |= BCR0_UI_RS449; 839 outb (BCR0(c->board->port), c->board->bcr0); 840 break; 841 case 8: 842 if ((c->board->if8type != 0) == (iftype != 0)) 843 return; 844 c->board->if8type = iftype; 845 c->board->bcr0b &= ~BCR0_UMASK; 846 if (c->board->if8type && 847 (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35)) 848 c->board->bcr0b |= BCR0_UI_RS449; 849 outb (BCR0(c->board->port+0x10), c->board->bcr0b); 850 break; 851 } 852 } 853} 854 855/* 856 * Get port type for old models of Sigma 857 * -1 Fixed port type or auto detect 858 * 0 RS232 859 * 1 V35 860 * 2 RS449 861 */ 862int cx_get_port (cx_chan_t *c) 863{ 864 int iftype; 865 866 if (c->board->type == B_SIGMA_XXX) { 867 switch (c->num) { 868 case 0: 869 iftype = c->board->if0type; break; 870 case 8: 871 iftype = c->board->if8type; break; 872 default: 873 return -1; 874 } 875 876 if (iftype) 877 switch (c->type) { 878 case T_UNIV_V35: return 1; 879 case T_UNIV_RS449: return 2; 880 default: return -1; 881 } 882 else 883 return 0; 884 } else 885 return -1; 886} 887 888void cx_intr_off (cx_board_t *b) 889{ 890 outb (BCR0(b->port), b->bcr0 & ~BCR0_IRQ_MASK); 891 if (b->chan[8].port || b->chan[12].port) 892 outb (BCR0(b->port+0x10), b->bcr0b & ~BCR0_IRQ_MASK); 893} 894 895void cx_intr_on (cx_board_t *b) 896{ 897 outb (BCR0(b->port), b->bcr0); 898 if (b->chan[8].port || b->chan[12].port) 899 outb (BCR0(b->port+0x10), b->bcr0b); 900} 901 902int cx_checkintr (cx_board_t *b) 903{ 904 return (!(inw (BSR(b->port)) & BSR_NOINTR)); 905} 906