1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * from: $Hdr: scc.c,v 4.300 91/06/09 06:44:53 root Rel41 $ SONY 11 * 12 * @(#)scc.c 8.1 (Berkeley) 06/11/93 13 */ 14 15 /* 16 * LH8530 SCC (serial communication controller) driver 17 * 18 * NOTE: This driver is available only for news700/1200/1700/3400. 19 * 20 * Any code and mechanism in this module may not be used 21 * in any form without permissions. COPYRIGHT (C) 1989- 22 * SONY Corporation, Super Microsystems Group (SMSG), 23 * Work Station Division, all rights RESERVED. 24 */ 25 26 #include <machine/adrsmap.h> 27 28 #include "rs.h" 29 30 #include <sys/param.h> 31 #include <sys/ioctl.h> 32 #include <sys/tty.h> 33 #include <sys/malloc.h> 34 35 #include <news3400/sio/sccparam.h> 36 #include <news3400/sio/sccreg.h> 37 #include <news3400/sio/scc.h> 38 #include <news3400/sio/scc.conf> 39 40 #define PROBE_DATA 0x55 41 42 #ifdef mips 43 #define VOLATILE volatile 44 #else 45 #define VOLATILE 46 #endif 47 48 int tty00_is_console = 0; 49 50 #define SCC_BUFSIZE 256 51 52 char scc_buf[2][SCC_BUFSIZE]; 53 54 scc_open(chan) 55 int chan; 56 { 57 register Scc_channel *scc = &sccsw[chan]; 58 register int s; 59 60 s = splscc(); 61 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 62 scc_init(chan); 63 if (chan <= SCC_REMOTE1) 64 scc->r_dma.dma_addr = scc_buf[chan]; 65 else 66 scc->r_dma.dma_addr = 67 malloc(SCC_BUFSIZE, M_DEVBUF, M_WAITOK); 68 scc->r_dma.dma_count = 0; 69 scc->scc_status |= CHAN_ACTIVE; 70 } 71 (void) splx(s); 72 return (0); 73 } 74 75 scc_probe(chan) 76 register int chan; 77 { 78 VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 79 int s, temp, probe; 80 81 if (badaddr(port, 1)) 82 return (0); 83 s = splscc(); 84 temp = scc_read_reg(chan, RR12); 85 scc_write_reg(chan, WR12, PROBE_DATA); 86 probe = scc_read_reg(chan, RR12); 87 scc_write_reg(chan, WR12, temp); 88 (void) splx(s); 89 return (probe == PROBE_DATA); 90 } 91 92 scc_getc(chan) 93 int chan; 94 { 95 VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 96 int c; 97 98 if (port->ctrl & R0_RxCA) { 99 SCCWAIT; 100 c = port->data; 101 SCCWAIT; 102 return (c); 103 } 104 SCCWAIT; 105 return (-1); 106 } 107 108 #ifndef notdef 109 scc_putc(chan, c) 110 int chan, c; 111 { 112 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 113 114 while ((port->ctrl & R0_TxBE) == 0) 115 SCCWAIT; 116 SCCWAIT; 117 port->data = c; 118 SCCWAIT; 119 } 120 #else 121 scc_putc(chan, c) 122 int chan, c; 123 { 124 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 125 register VOLATILE u_char *ctrl = &sccsw[chan].scc_port->ctrl; 126 register VOLATILE u_char *data = &sccsw[chan].scc_port->data; 127 128 SCCWAIT; 129 while ((*ctrl & R0_TxBE) == 0) { 130 SCCWAIT; 131 } 132 SCCWAIT; 133 134 *ctrl = W0_RES_TxINT; 135 SCCWAIT; 136 *data = (char)(c & 0xff); 137 SCCWAIT; 138 scc_write_reg(chan, WR1, W1_RxINT_ALL|W1_TxINTE|W1_EXTINTE|W1_PARITY); 139 SCCWAIT; 140 } 141 #endif 142 143 scc_init(chan) 144 int chan; 145 { 146 register VOLATILE struct scc_reg *port; 147 register char *data; 148 register int i; 149 register Scc_channel *scc = &sccsw[chan]; 150 int s; 151 152 s = splscc(); 153 data = scc->scc_init; 154 port = scc->scc_port; 155 for (i = 0; i < N_INITDATA; i++) { 156 port->ctrl = *data++; 157 SCCWAIT; 158 } 159 scc_write_reg(chan, WR2, scc->scc_vec & ~0x0f); 160 /* KU:XXX 161 This must be bug because scc->scc_param is not initialized yet. 162 scc_set_param(chan, scc->scc_param); 163 */ 164 (void) splx(s); 165 } 166 167 #define vec_to_scc(vec) ((((vec) - SCCVEC0) >> 3) & 0x000f) 168 #define vec_to_chan(vec) scc2chan[vec_to_scc(vec)] 169 170 int scc2chan[] = { 171 1, 0, 172 3, 2, 173 5, 4, 174 7, 6, 175 9, 8 176 }; 177 178 scc_rint(vec) 179 int vec; 180 { 181 int chan = vec_to_chan(vec); 182 register Scc_channel *scc = &sccsw[chan]; 183 register VOLATILE struct scc_reg *port = scc->scc_port; 184 register int c; 185 186 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 187 scc_reset(chan); 188 goto out; 189 } 190 if (scc->scc_status & LINE_BREAK){ 191 scc->scc_status &= ~LINE_BREAK; 192 c = port->data; 193 SCCWAIT; 194 } 195 while (port->ctrl & R0_RxCA) { 196 SCCWAIT; 197 c = port->data; 198 SCCWAIT; 199 #if NRS > 0 200 scc_pdma(chan, c); 201 #endif 202 } 203 SCCWAIT; 204 out: 205 port->ctrl = W0_RES_IUS; 206 SCCWAIT; 207 } 208 209 #if NRS > 0 210 scc_enable(chan) 211 int chan; 212 { 213 register Scc_channel *scc = &sccsw[chan]; 214 int n; 215 int s; 216 217 s = splscc(); 218 if ((n = scc->r_dma.dma_count) > 0) { 219 scc->r_dma.dma_count = 0; 220 rsrint(chan, scc->r_dma.dma_addr, n); 221 } else 222 scc->scc_status |= ENABLE; 223 (void) splx(s); 224 } 225 226 scc_pdma(chan, c) 227 int chan; 228 int c; 229 { 230 register Scc_channel *scc = &sccsw[chan]; 231 int n; 232 233 if (scc->r_dma.dma_count >= SCC_BUFSIZE) 234 printf("rs%d soft fifo overflow\n", chan); 235 else 236 scc->r_dma.dma_addr[scc->r_dma.dma_count++] = c; 237 if (scc->scc_status & ENABLE || scc->r_dma.dma_count >= SCC_BUFSIZE) { 238 scc->scc_status &= ~ENABLE; 239 n = scc->r_dma.dma_count; 240 scc->r_dma.dma_count = 0; 241 rsrint(chan, scc->r_dma.dma_addr, n); 242 } 243 } 244 #endif /* NRS > 0 */ 245 246 scc_xint(vec) 247 int vec; 248 { 249 int chan = vec_to_chan(vec); 250 register Scc_channel *scc = &sccsw[chan]; 251 register VOLATILE struct scc_reg *port = scc->scc_port; 252 253 if (scc->scc_status & OSTOP) 254 scc->scc_status &= ~(OACTIVE|OSTOP); 255 if (scc->scc_status & OFLUSH) { 256 scc->x_dma.dma_count = 0; 257 scc->scc_status &= ~(OACTIVE|OFLUSH); 258 } 259 if ((scc->scc_status & OACTIVE) && (scc->x_dma.dma_count > 0)) { 260 port->data = *(scc->x_dma.dma_addr)++; 261 SCCWAIT; 262 scc->x_dma.dma_count--; 263 } else { 264 port->ctrl = W0_RES_TxINT; 265 SCCWAIT; 266 scc->scc_status &= ~OACTIVE; 267 #if NRS > 0 268 if (scc->x_dma.dma_count == 0) 269 rsxint(chan); 270 #endif 271 } 272 port->ctrl = W0_RES_IUS; 273 SCCWAIT; 274 } 275 276 scc_sint(vec) 277 int vec; 278 { 279 int chan = vec_to_chan(vec); 280 register Scc_channel *scc = &sccsw[chan]; 281 register VOLATILE struct scc_reg *port = scc->scc_port; 282 register int status; 283 register int param = 0; 284 285 port->ctrl = W0_RES_EXT; 286 SCCWAIT; 287 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 288 scc_reset(chan); 289 goto out; 290 } 291 status = port->ctrl; 292 SCCWAIT; 293 if (status & R0_DCD) 294 param |= DCD; 295 if (status & R0_CTS) 296 param |= CTS; 297 if (status & R0_BREAK){ 298 param |= RBREAK; 299 scc->scc_status |= LINE_BREAK; 300 } 301 if ((scc->scc_param & (DCD|CTS|RBREAK)) != param) { 302 scc->scc_param = (scc->scc_param & ~(DCD|CTS|RBREAK)) | param; 303 #if NRS > 0 304 rssint(chan, scc->scc_param); 305 #endif 306 } 307 out: 308 port->ctrl = W0_RES_IUS; 309 SCCWAIT; 310 } 311 312 scc_cint(vec) 313 int vec; 314 { 315 int chan = vec_to_chan(vec); 316 register Scc_channel *scc = &sccsw[chan]; 317 register VOLATILE struct scc_reg *port = scc->scc_port; 318 register int status; 319 int c; 320 321 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 322 scc_reset(chan); 323 goto out; 324 } 325 status = scc_read_reg(chan, RR1); 326 if (status & R1_CRC) 327 scc->scc_param |= FRAMING_ERROR; 328 if (status & R1_OVRUN) { 329 if ((scc->scc_param & OVERRUN_ERROR) == 0) { 330 scc->scc_param |= OVERRUN_ERROR; 331 #if NRS > 0 332 rssint(chan, scc->scc_param); 333 #endif 334 } 335 } 336 if (status & R1_PARITY) { 337 scc->scc_param |= SCC_PARITY_ERROR; 338 while (port->ctrl & R0_RxCA) { 339 SCCWAIT; 340 c = port->data; 341 SCCWAIT; 342 #if NRS > 0 343 if (scc->scc_param & NOCHECK) 344 scc_pdma(chan, c); 345 #endif 346 } 347 SCCWAIT; 348 } 349 out: 350 port->ctrl = W0_RES_ERROR; 351 SCCWAIT; 352 port->ctrl = W0_RES_IUS; 353 SCCWAIT; 354 } 355 356 scc_write_reg(chan, reg, data) 357 int chan, reg, data; 358 { 359 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 360 361 port->ctrl = reg; 362 SCCWAIT; 363 port->ctrl = data; 364 SCCWAIT; 365 } 366 367 scc_read_reg(chan, reg) 368 int chan, reg; 369 { 370 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 371 int result; 372 373 port->ctrl = reg; 374 SCCWAIT; 375 result = port->ctrl; 376 SCCWAIT; 377 return (result); 378 } 379 380 #ifdef news3400 381 #define DSRA 0x01 382 #define RIA 0x02 383 #define DSRB 0x04 384 #define RIB 0x08 385 386 #define DSRC 0x01 387 #define RIC 0x02 388 #define DSRD 0x04 389 #define RID 0x08 390 #define DSRE 0x10 391 #define RIE 0x20 392 #define DSRF 0x40 393 #define RIF 0x80 394 #endif /* news3400 */ 395 396 struct ri_dsr { 397 char *status; 398 int ri; 399 int dsr; 400 } ri_dsr[] = { 401 { (char *)SCC_STATUS0, RIA, DSRA }, 402 { (char *)SCC_STATUS0, RIB, DSRB }, 403 #if !defined(news3200) 404 { (char *)SCC_STATUS1, RIC, DSRC }, 405 { (char *)SCC_STATUS1, RID, DSRD }, 406 { (char *)SCC_STATUS1, RIE, DSRE }, 407 { (char *)SCC_STATUS1, RIF, DSRF }, 408 { (char *)SCC_STATUS2, RIC, DSRC }, 409 { (char *)SCC_STATUS2, RID, DSRD }, 410 { (char *)SCC_STATUS2, RIE, DSRE }, 411 { (char *)SCC_STATUS2, RIF, DSRF } 412 #endif /* !news3200 */ 413 }; 414 415 get_ri_dsr(chan) 416 int chan; 417 { 418 register struct ri_dsr *p; 419 register int status, param; 420 421 param = 0; 422 p = &ri_dsr[chan]; 423 status = *p->status; 424 if ((status & p->ri) == 0) 425 param |= RI; 426 if ((status & p->dsr) == 0) 427 param |= DSR; 428 return (param); 429 } 430 431 #if defined(news3400) 432 /* 433 * tc0 = floor(4915200 / 32 / baudrate - 2 + 0.5); 434 */ 435 static int tc0[] = { 436 0, /* B0 */ 437 3070, /* B50 */ 438 2046, /* B75 */ 439 1394, /* B110 */ 440 1144, /* B134 */ 441 1022, /* B150 */ 442 766, /* B200 */ 443 510, /* B300 */ 444 254, /* B600 */ 445 126, /* B1200 */ 446 83, /* B1800 */ 447 62, /* B2400 */ 448 30, /* B4800 */ 449 14, /* B9600 */ 450 6, /* EXTA (B19200) */ 451 2 /* EXTB (B38400) */ 452 }; 453 #endif /* news3400 */ 454 455 static int tc1[] = { 456 /* 457 * tc1 = floor(3686400 / 32 / baudrate - 2 + 0.5); 458 */ 459 0, /* B0 */ 460 2302, /* B50 */ 461 1534, /* B75 */ 462 1045, /* B110 */ 463 858, /* B134 */ 464 766, /* B150 */ 465 574, /* B200 */ 466 382, /* B300 */ 467 190, /* B600 */ 468 94, /* B1200 */ 469 62, /* B1800 */ 470 46, /* B2400 */ 471 22, /* B4800 */ 472 10, /* B9600 */ 473 4, /* B19200 */ 474 1, /* B38400 */ 475 }; 476 477 scc_set_param(chan, param) 478 int chan; 479 register int param; 480 { 481 register Scc_channel *scc = &sccsw[chan]; 482 register int bit, baud, *tc; 483 int s; 484 485 s = splscc(); 486 487 /* 488 * Baud rate / external clock 489 */ 490 if ((baud = param & BAUD_RATE) == EXTB && chan <= SCC_REMOTE1 && 491 param & EXTCLK_ENABLE) { 492 scc_write_reg(chan, WR11, W11_RxC_RTxC|W11_TxC_TRxC); 493 bit = W4_X1; 494 } else { 495 tc = (chan <= SCC_REMOTE1) ? tc0 : tc1; 496 scc_write_reg(chan, WR11, W11_RxC_BRG|W11_TxC_BRG); 497 scc_write_reg(chan, WR12, tc[baud] & 0xff); 498 scc_write_reg(chan, WR13, tc[baud] >> 8); 499 bit = W4_X16; 500 } 501 502 /* 503 * Clock mode / parity / stop bit 504 */ 505 if (param & PARITY) { 506 bit |= W4_PARITY; 507 if (param & EVEN) 508 bit |= W4_EVEN; 509 } 510 switch (param & STOPBIT) { 511 512 case STOP1: 513 bit |= W4_STOP1; 514 break; 515 516 case STOP1_5: 517 bit |= W4_STOP1_5; 518 break; 519 520 case STOP2: 521 bit |= W4_STOP2; 522 break; 523 524 } 525 scc_write_reg(chan, WR4, bit); 526 527 /* 528 * Receiver enable / receive character size / auto enable 529 */ 530 bit = (param & RXE ? W3_RxE : 0); 531 switch (param & CHAR_SIZE) { 532 533 case C5BIT: 534 break; 535 536 case C6BIT: 537 bit |= W3_Rx6BIT; 538 break; 539 540 case C7BIT: 541 bit |= W3_Rx7BIT; 542 break; 543 544 case C8BIT: 545 bit |= W3_Rx8BIT; 546 break; 547 } 548 #ifdef AUTO_ENABLE 549 if (param & AUTO_ENABLE) 550 bit |= W3_AUTO; 551 #endif /* AUTO_ENABLE */ 552 scc_write_reg(chan, WR3, bit); 553 554 /* 555 * Transmitter enable / transmit character size / RTS / DTR / BREAK 556 */ 557 bit = (param & TXE ? W5_TxE : 0); 558 switch (param & CHAR_SIZE) { 559 560 case C5BIT: 561 break; 562 563 case C6BIT: 564 bit |= W5_Tx6BIT; 565 break; 566 567 case C7BIT: 568 bit |= W5_Tx7BIT; 569 break; 570 571 case C8BIT: 572 bit |= W5_Tx8BIT; 573 break; 574 } 575 if (param & RTS) 576 bit |= W5_RTS; 577 if (param & DTR) 578 bit |= W5_DTR; 579 if (param & XBREAK) 580 bit |= W5_BREAK; 581 scc_write_reg(chan, WR5, bit); 582 scc->scc_param = param; 583 (void) splx(s); 584 return (0); 585 } 586 587 scc_get_param(chan) 588 int chan; 589 { 590 register Scc_channel *scc = &sccsw[chan]; 591 592 scc->scc_param = (scc->scc_param & ~(RI|DSR)) | get_ri_dsr(chan); 593 return (scc->scc_param); 594 } 595 596 scc_get_status(chan) 597 int chan; 598 { 599 600 return (sccsw[chan].scc_status); 601 } 602 603 scc_set_status(chan, stat) 604 int chan, stat; 605 { 606 607 sccsw[chan].scc_status = stat; 608 609 return (0); 610 } 611 612 scc_flush(chan) 613 int chan; 614 { 615 register Scc_channel *scc = &sccsw[chan]; 616 617 if (scc->scc_status & OACTIVE) 618 scc->scc_status |= OFLUSH; 619 else if (scc->x_dma.dma_count > 0) { 620 scc->x_dma.dma_count = 0; 621 #if NRS > 0 622 rsxint(chan); 623 #endif 624 } 625 return (0); 626 } 627 628 scc_start(chan) 629 int chan; 630 { 631 register Scc_channel *scc = &sccsw[chan]; 632 633 if ((scc->scc_status & OACTIVE) == 0 && scc->x_dma.dma_count > 0) { 634 scc->scc_port->data = *(scc->x_dma.dma_addr)++; 635 SCCWAIT; 636 scc->x_dma.dma_count--; 637 scc->scc_status |= OACTIVE; 638 } 639 return (0); 640 } 641 642 scc_stop(chan) 643 int chan; 644 { 645 register Scc_channel *scc = &sccsw[chan]; 646 647 if (scc->scc_status & OACTIVE) 648 scc->scc_status |= OSTOP; 649 return (0); 650 } 651 652 scc_write(chan, buf, count) 653 int chan; 654 caddr_t buf; 655 int count; 656 { 657 register Scc_channel *scc = &sccsw[chan]; 658 659 if (count <= 0) 660 return (0); 661 scc->x_dma.dma_addr = buf; 662 scc->x_dma.dma_count = count; 663 scc_start(chan); 664 return (count); 665 } 666 667 scc_error_write(chan, buf, count) 668 int chan; 669 register char *buf; 670 register int count; 671 { 672 register int i; 673 674 for (i = 0; i < count; i++) 675 scc_putc(chan, *buf++); 676 return (i); 677 } 678 679 scc_reset(chan) 680 int chan; 681 { 682 register Scc_channel *scc = &sccsw[chan]; 683 684 while (scc_getc(chan) != -1) 685 ; 686 scc->scc_status &= ~CHAN_ACTIVE; 687 } 688