1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * 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 7.1 (Berkeley) 06/04/92 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 "../include/fix_machine_type.h" 27 #include "../include/adrsmap.h" 28 29 #ifdef news700 30 #include "ms.h" 31 #include "bm.h" 32 #else 33 #include "rs.h" 34 #endif 35 36 #include "param.h" 37 #include "ioctl.h" 38 #include "tty.h" 39 #include "malloc.h" 40 41 #include "sccparam.h" 42 #include "sccreg.h" 43 #include "scc.h" 44 #include "scc.conf" 45 46 #define PROBE_DATA 0x55 47 48 #ifdef mips 49 #define VOLATILE volatile 50 #else 51 #define VOLATILE 52 #endif 53 54 int tty00_is_console = 0; 55 56 #define SCC_BUFSIZE 256 57 58 char scc_buf[2][SCC_BUFSIZE]; 59 60 scc_open(chan) 61 int chan; 62 { 63 register Scc_channel *scc = &sccsw[chan]; 64 register int s; 65 66 s = splscc(); 67 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 68 scc_init(chan); 69 if (chan <= SCC_REMOTE1) 70 scc->r_dma.dma_addr = scc_buf[chan]; 71 else 72 scc->r_dma.dma_addr = 73 malloc(SCC_BUFSIZE, M_DEVBUF, M_WAITOK); 74 scc->r_dma.dma_count = 0; 75 scc->scc_status |= CHAN_ACTIVE; 76 } 77 (void) splx(s); 78 return (0); 79 } 80 81 scc_probe(chan) 82 register int chan; 83 { 84 VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 85 int s, temp, probe; 86 87 if (badaddr(port, 1)) 88 return (0); 89 s = splscc(); 90 temp = scc_read_reg(chan, RR12); 91 scc_write_reg(chan, WR12, PROBE_DATA); 92 probe = scc_read_reg(chan, RR12); 93 scc_write_reg(chan, WR12, temp); 94 (void) splx(s); 95 return (probe == PROBE_DATA); 96 } 97 98 scc_getc(chan) 99 int chan; 100 { 101 VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 102 int c; 103 104 if (port->ctrl & R0_RxCA) { 105 SCCWAIT; 106 c = port->data; 107 SCCWAIT; 108 return (c); 109 } 110 SCCWAIT; 111 return (-1); 112 } 113 114 #ifndef notdef 115 scc_putc(chan, c) 116 int chan, c; 117 { 118 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 119 120 while ((port->ctrl & R0_TxBE) == 0) 121 SCCWAIT; 122 SCCWAIT; 123 port->data = c; 124 SCCWAIT; 125 } 126 #else 127 scc_putc(chan, c) 128 int chan, c; 129 { 130 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 131 register VOLATILE u_char *ctrl = &sccsw[chan].scc_port->ctrl; 132 register VOLATILE u_char *data = &sccsw[chan].scc_port->data; 133 134 SCCWAIT; 135 while ((*ctrl & R0_TxBE) == 0) { 136 SCCWAIT; 137 } 138 SCCWAIT; 139 140 *ctrl = W0_RES_TxINT; 141 SCCWAIT; 142 *data = (char)(c & 0xff); 143 SCCWAIT; 144 scc_write_reg(chan, WR1, W1_RxINT_ALL|W1_TxINTE|W1_EXTINTE|W1_PARITY); 145 SCCWAIT; 146 } 147 #endif 148 149 scc_init(chan) 150 int chan; 151 { 152 register VOLATILE struct scc_reg *port; 153 register char *data; 154 register int i; 155 register Scc_channel *scc = &sccsw[chan]; 156 int s; 157 158 s = splscc(); 159 data = scc->scc_init; 160 port = scc->scc_port; 161 for (i = 0; i < N_INITDATA; i++) { 162 port->ctrl = *data++; 163 SCCWAIT; 164 } 165 scc_write_reg(chan, WR2, scc->scc_vec & ~0x0f); 166 /* KU:XXX 167 This must be bug because scc->scc_param is not initialized yet. 168 scc_set_param(chan, scc->scc_param); 169 */ 170 (void) splx(s); 171 } 172 173 #define vec_to_scc(vec) ((((vec) - SCCVEC0) >> 3) & 0x000f) 174 #define vec_to_chan(vec) scc2chan[vec_to_scc(vec)] 175 176 int scc2chan[] = { 177 #ifdef news700 178 0, 1, 179 #else /* news700 */ 180 1, 0, 181 #endif /* news700 */ 182 3, 2, 183 5, 4, 184 7, 6, 185 9, 8 186 }; 187 188 #ifdef news700 189 #define OFF 0x80 190 191 scc_rint(vec) 192 int vec; 193 { 194 int chan = vec_to_chan(vec); 195 Scc_channel *scc = &sccsw[chan]; 196 register struct scc_reg *port = scc->scc_port; 197 register int c; 198 #if NMS > 0 199 extern int _ms_helper(); 200 #endif /* NMS > 0 */ 201 #if NBM > 0 202 extern int kb_softint(); 203 #endif /* NBM > 0 */ 204 205 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 206 scc_reset(chan); 207 goto out; 208 } 209 while (port->ctrl & R0_RxCA) { 210 SCCWAIT; 211 c = port->data; 212 SCCWAIT; 213 switch (chan) { 214 215 case SCC_MOUSE: 216 #if NMS > 0 217 if (xputc(c, SCC_MOUSE) < 0) 218 printf("mouse queue overflow\n"); 219 softcall(_ms_helper, (caddr_t)0); 220 #endif 221 break; 222 223 case SCC_KEYBOARD: 224 #if NBM > 0 225 if (xputc(c, SCC_KEYBOARD) < 0) 226 printf("keyboard queue overflow\n"); 227 softcall(kb_softint, (caddr_t)0); 228 #endif 229 break; 230 231 default: 232 printf("kb or ms stray intr\n"); 233 break; 234 } 235 SCCWAIT; 236 } 237 out: 238 port->ctrl = W0_RES_IUS; 239 SCCWAIT; 240 } 241 #else /* news700 */ 242 scc_rint(vec) 243 int vec; 244 { 245 int chan = vec_to_chan(vec); 246 register Scc_channel *scc = &sccsw[chan]; 247 register VOLATILE struct scc_reg *port = scc->scc_port; 248 register int c; 249 250 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 251 scc_reset(chan); 252 goto out; 253 } 254 if (scc->scc_status & LINE_BREAK){ 255 scc->scc_status &= ~LINE_BREAK; 256 c = port->data; 257 SCCWAIT; 258 } 259 while (port->ctrl & R0_RxCA) { 260 SCCWAIT; 261 c = port->data; 262 SCCWAIT; 263 #if NRS > 0 264 scc_pdma(chan, c); 265 #endif 266 } 267 SCCWAIT; 268 out: 269 port->ctrl = W0_RES_IUS; 270 SCCWAIT; 271 } 272 #endif /* news700 */ 273 274 #if NRS > 0 275 scc_enable(chan) 276 int chan; 277 { 278 register Scc_channel *scc = &sccsw[chan]; 279 int n; 280 int s; 281 282 s = splscc(); 283 if ((n = scc->r_dma.dma_count) > 0) { 284 scc->r_dma.dma_count = 0; 285 rsrint(chan, scc->r_dma.dma_addr, n); 286 } else 287 scc->scc_status |= ENABLE; 288 (void) splx(s); 289 } 290 291 scc_pdma(chan, c) 292 int chan; 293 int c; 294 { 295 register Scc_channel *scc = &sccsw[chan]; 296 int n; 297 298 if (scc->r_dma.dma_count >= SCC_BUFSIZE) 299 printf("rs%d soft fifo overflow\n", chan); 300 else 301 scc->r_dma.dma_addr[scc->r_dma.dma_count++] = c; 302 if (scc->scc_status & ENABLE || scc->r_dma.dma_count >= SCC_BUFSIZE) { 303 scc->scc_status &= ~ENABLE; 304 n = scc->r_dma.dma_count; 305 scc->r_dma.dma_count = 0; 306 rsrint(chan, scc->r_dma.dma_addr, n); 307 } 308 } 309 #endif /* NRS > 0 */ 310 311 scc_xint(vec) 312 int vec; 313 { 314 int chan = vec_to_chan(vec); 315 register Scc_channel *scc = &sccsw[chan]; 316 register VOLATILE struct scc_reg *port = scc->scc_port; 317 318 if (scc->scc_status & OSTOP) 319 scc->scc_status &= ~(OACTIVE|OSTOP); 320 if (scc->scc_status & OFLUSH) { 321 scc->x_dma.dma_count = 0; 322 scc->scc_status &= ~(OACTIVE|OFLUSH); 323 } 324 if ((scc->scc_status & OACTIVE) && (scc->x_dma.dma_count > 0)) { 325 port->data = *(scc->x_dma.dma_addr)++; 326 SCCWAIT; 327 scc->x_dma.dma_count--; 328 } else { 329 port->ctrl = W0_RES_TxINT; 330 SCCWAIT; 331 scc->scc_status &= ~OACTIVE; 332 #if NRS > 0 333 if (scc->x_dma.dma_count == 0) 334 rsxint(chan); 335 #endif 336 } 337 port->ctrl = W0_RES_IUS; 338 SCCWAIT; 339 } 340 341 scc_sint(vec) 342 int vec; 343 { 344 int chan = vec_to_chan(vec); 345 register Scc_channel *scc = &sccsw[chan]; 346 register VOLATILE struct scc_reg *port = scc->scc_port; 347 register int status; 348 register int param = 0; 349 350 port->ctrl = W0_RES_EXT; 351 SCCWAIT; 352 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 353 scc_reset(chan); 354 goto out; 355 } 356 status = port->ctrl; 357 SCCWAIT; 358 if (status & R0_DCD) 359 param |= DCD; 360 if (status & R0_CTS) 361 param |= CTS; 362 if (status & R0_BREAK){ 363 param |= RBREAK; 364 scc->scc_status |= LINE_BREAK; 365 } 366 if ((scc->scc_param & (DCD|CTS|RBREAK)) != param) { 367 scc->scc_param = (scc->scc_param & ~(DCD|CTS|RBREAK)) | param; 368 #if NRS > 0 369 rssint(chan, scc->scc_param); 370 #endif 371 } 372 out: 373 port->ctrl = W0_RES_IUS; 374 SCCWAIT; 375 } 376 377 scc_cint(vec) 378 int vec; 379 { 380 int chan = vec_to_chan(vec); 381 register Scc_channel *scc = &sccsw[chan]; 382 register VOLATILE struct scc_reg *port = scc->scc_port; 383 register int status; 384 int c; 385 386 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 387 scc_reset(chan); 388 goto out; 389 } 390 status = scc_read_reg(chan, RR1); 391 if (status & R1_CRC) 392 scc->scc_param |= FRAMING_ERROR; 393 if (status & R1_OVRUN) { 394 if ((scc->scc_param & OVERRUN_ERROR) == 0) { 395 scc->scc_param |= OVERRUN_ERROR; 396 #if NRS > 0 397 rssint(chan, scc->scc_param); 398 #endif /* NRS > 0 */ 399 } 400 } 401 if (status & R1_PARITY) { 402 scc->scc_param |= SCC_PARITY_ERROR; 403 while (port->ctrl & R0_RxCA) { 404 SCCWAIT; 405 c = port->data; 406 SCCWAIT; 407 #if NRS > 0 408 if (scc->scc_param & NOCHECK) 409 scc_pdma(chan, c); 410 #endif 411 } 412 SCCWAIT; 413 } 414 out: 415 port->ctrl = W0_RES_ERROR; 416 SCCWAIT; 417 port->ctrl = W0_RES_IUS; 418 SCCWAIT; 419 } 420 421 scc_write_reg(chan, reg, data) 422 int chan, reg, data; 423 { 424 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 425 426 port->ctrl = reg; 427 SCCWAIT; 428 port->ctrl = data; 429 SCCWAIT; 430 } 431 432 scc_read_reg(chan, reg) 433 int chan, reg; 434 { 435 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 436 int result; 437 438 port->ctrl = reg; 439 SCCWAIT; 440 result = port->ctrl; 441 SCCWAIT; 442 return (result); 443 } 444 445 #ifdef news1700 446 #define DSRA 0x20 447 #define RIA 0x04 448 #define DSRB 0x02 449 #define RIB 0x01 450 451 #define DSRC 0x01 452 #define RIC 0x02 453 #define DSRD 0x04 454 #define RID 0x08 455 #define DSRE 0x10 456 #define RIE 0x20 457 #define DSRF 0x40 458 #define RIF 0x80 459 #endif /* news1700 */ 460 461 #ifdef news1200 462 #define DSRA 0x08 463 #define RIA 0x04 464 #define DSRB 0x02 465 #define RIB 0x01 466 #endif /* news1200 */ 467 468 #ifdef news3400 469 #define DSRA 0x01 470 #define RIA 0x02 471 #define DSRB 0x04 472 #define RIB 0x08 473 474 #define DSRC 0x01 475 #define RIC 0x02 476 #define DSRD 0x04 477 #define RID 0x08 478 #define DSRE 0x10 479 #define RIE 0x20 480 #define DSRF 0x40 481 #define RIF 0x80 482 #endif /* news3400 */ 483 484 struct ri_dsr { 485 char *status; 486 int ri; 487 int dsr; 488 } ri_dsr[] = { 489 #ifdef news700 490 { (char *)0, 0, 0 } 491 #else /* news700 */ 492 { (char *)SCC_STATUS0, RIA, DSRA }, 493 { (char *)SCC_STATUS0, RIB, DSRB }, 494 #if !defined(news1200) && !defined(news3200) 495 { (char *)SCC_STATUS1, RIC, DSRC }, 496 { (char *)SCC_STATUS1, RID, DSRD }, 497 { (char *)SCC_STATUS1, RIE, DSRE }, 498 { (char *)SCC_STATUS1, RIF, DSRF }, 499 { (char *)SCC_STATUS2, RIC, DSRC }, 500 { (char *)SCC_STATUS2, RID, DSRD }, 501 { (char *)SCC_STATUS2, RIE, DSRE }, 502 { (char *)SCC_STATUS2, RIF, DSRF } 503 #endif /* !news1200 && !news3200 */ 504 #endif /* news700 */ 505 }; 506 507 get_ri_dsr(chan) 508 int chan; 509 { 510 register struct ri_dsr *p; 511 register int status, param; 512 513 param = 0; 514 #ifndef news700 515 p = &ri_dsr[chan]; 516 status = *p->status; 517 if ((status & p->ri) == 0) 518 param |= RI; 519 if ((status & p->dsr) == 0) 520 param |= DSR; 521 #endif /* !news700 */ 522 return (param); 523 } 524 525 #ifdef news700 526 /* 527 * tc = floor(5000000 / 32 / baudrate - 2 + 0.5); 528 */ 529 static int tc0[] = { 530 0, /* B0 */ 531 3123, /* B50 */ 532 2081, /* B75 */ 533 1418, /* B110 */ 534 1164, /* B134 */ 535 1039, /* B150 */ 536 779, /* B200 */ 537 518, /* B300 */ 538 258, /* B600 */ 539 128, /* B1200 */ 540 84, /* B1800 */ 541 63, /* B2400 */ 542 30, /* B4800 */ 543 14, /* B9600 */ 544 14, /* EXTA */ 545 14 /* EXTB */ 546 }; 547 #endif /* news700 */ 548 549 #ifdef news1700 550 /* 551 * tc0 = floor(4000000 / 32 / baudrate - 2 + 0.5); 552 */ 553 static int tc0[] = { 554 0, /* B0 */ 555 2498, /* B50 */ 556 1664, /* B75 */ 557 1134, /* B110 */ 558 930, /* B134 */ 559 831, /* B150 */ 560 623, /* B200 */ 561 414, /* B300 */ 562 206, /* B600 */ 563 102, /* B1200 */ 564 67, /* B1800 */ 565 50, /* B2400 */ 566 24, /* B4800 */ 567 11, /* B9600 */ 568 11, /* EXTA (B9600)*/ 569 11 /* EXTB (B9600)*/ 570 }; 571 #endif /* news1700 */ 572 573 #if defined(news1200) || defined(news3400) 574 /* 575 * tc0 = floor(4915200 / 32 / baudrate - 2 + 0.5); 576 */ 577 static int tc0[] = { 578 0, /* B0 */ 579 3070, /* B50 */ 580 2046, /* B75 */ 581 1394, /* B110 */ 582 1144, /* B134 */ 583 1022, /* B150 */ 584 766, /* B200 */ 585 510, /* B300 */ 586 254, /* B600 */ 587 126, /* B1200 */ 588 83, /* B1800 */ 589 62, /* B2400 */ 590 30, /* B4800 */ 591 14, /* B9600 */ 592 6, /* EXTA (B19200) */ 593 2 /* EXTB (B38400) */ 594 }; 595 #endif /* news1200 || news3400 */ 596 597 #ifndef news700 598 static int tc1[] = { 599 /* 600 * tc1 = floor(3686400 / 32 / baudrate - 2 + 0.5); 601 */ 602 0, /* B0 */ 603 2302, /* B50 */ 604 1534, /* B75 */ 605 1045, /* B110 */ 606 858, /* B134 */ 607 766, /* B150 */ 608 574, /* B200 */ 609 382, /* B300 */ 610 190, /* B600 */ 611 94, /* B1200 */ 612 62, /* B1800 */ 613 46, /* B2400 */ 614 22, /* B4800 */ 615 10, /* B9600 */ 616 4, /* B19200 */ 617 1, /* B38400 */ 618 }; 619 #endif /* !news700 */ 620 621 scc_set_param(chan, param) 622 int chan; 623 register int param; 624 { 625 register Scc_channel *scc = &sccsw[chan]; 626 register int bit, baud, *tc; 627 int s; 628 629 s = splscc(); 630 631 /* 632 * Baud rate / external clock 633 */ 634 if ((baud = param & BAUD_RATE) == EXTB && chan <= SCC_REMOTE1 && 635 param & EXTCLK_ENABLE) { 636 scc_write_reg(chan, WR11, W11_RxC_RTxC|W11_TxC_TRxC); 637 bit = W4_X1; 638 } else { 639 #ifdef news700 640 tc = tc0; 641 #else /* news700 */ 642 tc = (chan <= SCC_REMOTE1) ? tc0 : tc1; 643 #endif /* news700 */ 644 scc_write_reg(chan, WR11, W11_RxC_BRG|W11_TxC_BRG); 645 scc_write_reg(chan, WR12, tc[baud] & 0xff); 646 scc_write_reg(chan, WR13, tc[baud] >> 8); 647 bit = W4_X16; 648 } 649 650 /* 651 * Clock mode / parity / stop bit 652 */ 653 if (param & PARITY) { 654 bit |= W4_PARITY; 655 if (param & EVEN) 656 bit |= W4_EVEN; 657 } 658 switch (param & STOPBIT) { 659 660 case STOP1: 661 bit |= W4_STOP1; 662 break; 663 664 case STOP1_5: 665 bit |= W4_STOP1_5; 666 break; 667 668 case STOP2: 669 bit |= W4_STOP2; 670 break; 671 672 } 673 scc_write_reg(chan, WR4, bit); 674 675 /* 676 * Receiver enable / receive character size / auto enable 677 */ 678 bit = (param & RXE ? W3_RxE : 0); 679 switch (param & CHAR_SIZE) { 680 681 case C5BIT: 682 break; 683 684 case C6BIT: 685 bit |= W3_Rx6BIT; 686 break; 687 688 case C7BIT: 689 bit |= W3_Rx7BIT; 690 break; 691 692 case C8BIT: 693 bit |= W3_Rx8BIT; 694 break; 695 } 696 #ifdef AUTO_ENABLE 697 if (param & AUTO_ENABLE) 698 bit |= W3_AUTO; 699 #endif /* AUTO_ENABLE */ 700 scc_write_reg(chan, WR3, bit); 701 702 /* 703 * Transmitter enable / transmit character size / RTS / DTR / BREAK 704 */ 705 bit = (param & TXE ? W5_TxE : 0); 706 switch (param & CHAR_SIZE) { 707 708 case C5BIT: 709 break; 710 711 case C6BIT: 712 bit |= W5_Tx6BIT; 713 break; 714 715 case C7BIT: 716 bit |= W5_Tx7BIT; 717 break; 718 719 case C8BIT: 720 bit |= W5_Tx8BIT; 721 break; 722 } 723 if (param & RTS) 724 bit |= W5_RTS; 725 if (param & DTR) 726 bit |= W5_DTR; 727 if (param & XBREAK) 728 bit |= W5_BREAK; 729 scc_write_reg(chan, WR5, bit); 730 scc->scc_param = param; 731 (void) splx(s); 732 return (0); 733 } 734 735 scc_get_param(chan) 736 int chan; 737 { 738 register Scc_channel *scc = &sccsw[chan]; 739 740 scc->scc_param = (scc->scc_param & ~(RI|DSR)) | get_ri_dsr(chan); 741 return (scc->scc_param); 742 } 743 744 scc_get_status(chan) 745 int chan; 746 { 747 748 return (sccsw[chan].scc_status); 749 } 750 751 scc_set_status(chan, stat) 752 int chan, stat; 753 { 754 755 sccsw[chan].scc_status = stat; 756 757 return (0); 758 } 759 760 scc_flush(chan) 761 int chan; 762 { 763 register Scc_channel *scc = &sccsw[chan]; 764 765 if (scc->scc_status & OACTIVE) 766 scc->scc_status |= OFLUSH; 767 else if (scc->x_dma.dma_count > 0) { 768 scc->x_dma.dma_count = 0; 769 #if NRS > 0 770 rsxint(chan); 771 #endif 772 } 773 return (0); 774 } 775 776 scc_start(chan) 777 int chan; 778 { 779 register Scc_channel *scc = &sccsw[chan]; 780 781 if ((scc->scc_status & OACTIVE) == 0 && scc->x_dma.dma_count > 0) { 782 scc->scc_port->data = *(scc->x_dma.dma_addr)++; 783 SCCWAIT; 784 scc->x_dma.dma_count--; 785 scc->scc_status |= OACTIVE; 786 } 787 return (0); 788 } 789 790 scc_stop(chan) 791 int chan; 792 { 793 register Scc_channel *scc = &sccsw[chan]; 794 795 if (scc->scc_status & OACTIVE) 796 scc->scc_status |= OSTOP; 797 return (0); 798 } 799 800 scc_write(chan, buf, count) 801 int chan; 802 caddr_t buf; 803 int count; 804 { 805 register Scc_channel *scc = &sccsw[chan]; 806 807 if (count <= 0) 808 return (0); 809 scc->x_dma.dma_addr = buf; 810 scc->x_dma.dma_count = count; 811 scc_start(chan); 812 return (count); 813 } 814 815 scc_error_write(chan, buf, count) 816 int chan; 817 register char *buf; 818 register int count; 819 { 820 register int i; 821 822 for (i = 0; i < count; i++) 823 scc_putc(chan, *buf++); 824 return (i); 825 } 826 827 scc_reset(chan) 828 int chan; 829 { 830 register Scc_channel *scc = &sccsw[chan]; 831 832 while (scc_getc(chan) != -1) 833 ; 834 scc->scc_status &= ~CHAN_ACTIVE; 835 } 836