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