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.3 (Berkeley) 01/20/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/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 1, 0, 173 3, 2, 174 5, 4, 175 7, 6, 176 9, 8 177 }; 178 179 scc_rint(vec) 180 int vec; 181 { 182 int chan = vec_to_chan(vec); 183 register Scc_channel *scc = &sccsw[chan]; 184 register VOLATILE struct scc_reg *port = scc->scc_port; 185 register int c; 186 187 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 188 scc_reset(chan); 189 goto out; 190 } 191 if (scc->scc_status & LINE_BREAK){ 192 scc->scc_status &= ~LINE_BREAK; 193 c = port->data; 194 SCCWAIT; 195 } 196 while (port->ctrl & R0_RxCA) { 197 SCCWAIT; 198 c = port->data; 199 SCCWAIT; 200 #if NRS > 0 201 scc_pdma(chan, c); 202 #endif 203 } 204 SCCWAIT; 205 out: 206 port->ctrl = W0_RES_IUS; 207 SCCWAIT; 208 } 209 210 #if NRS > 0 211 scc_enable(chan) 212 int chan; 213 { 214 register Scc_channel *scc = &sccsw[chan]; 215 int n; 216 int s; 217 218 s = splscc(); 219 if ((n = scc->r_dma.dma_count) > 0) { 220 scc->r_dma.dma_count = 0; 221 rsrint(chan, scc->r_dma.dma_addr, n); 222 } else 223 scc->scc_status |= ENABLE; 224 (void) splx(s); 225 } 226 227 scc_pdma(chan, c) 228 int chan; 229 int c; 230 { 231 register Scc_channel *scc = &sccsw[chan]; 232 int n; 233 234 if (scc->r_dma.dma_count >= SCC_BUFSIZE) 235 printf("rs%d soft fifo overflow\n", chan); 236 else 237 scc->r_dma.dma_addr[scc->r_dma.dma_count++] = c; 238 if (scc->scc_status & ENABLE || scc->r_dma.dma_count >= SCC_BUFSIZE) { 239 scc->scc_status &= ~ENABLE; 240 n = scc->r_dma.dma_count; 241 scc->r_dma.dma_count = 0; 242 rsrint(chan, scc->r_dma.dma_addr, n); 243 } 244 } 245 #endif /* NRS > 0 */ 246 247 scc_xint(vec) 248 int vec; 249 { 250 int chan = vec_to_chan(vec); 251 register Scc_channel *scc = &sccsw[chan]; 252 register VOLATILE struct scc_reg *port = scc->scc_port; 253 254 if (scc->scc_status & OSTOP) 255 scc->scc_status &= ~(OACTIVE|OSTOP); 256 if (scc->scc_status & OFLUSH) { 257 scc->x_dma.dma_count = 0; 258 scc->scc_status &= ~(OACTIVE|OFLUSH); 259 } 260 if ((scc->scc_status & OACTIVE) && (scc->x_dma.dma_count > 0)) { 261 port->data = *(scc->x_dma.dma_addr)++; 262 SCCWAIT; 263 scc->x_dma.dma_count--; 264 } else { 265 port->ctrl = W0_RES_TxINT; 266 SCCWAIT; 267 scc->scc_status &= ~OACTIVE; 268 #if NRS > 0 269 if (scc->x_dma.dma_count == 0) 270 rsxint(chan); 271 #endif 272 } 273 port->ctrl = W0_RES_IUS; 274 SCCWAIT; 275 } 276 277 scc_sint(vec) 278 int vec; 279 { 280 int chan = vec_to_chan(vec); 281 register Scc_channel *scc = &sccsw[chan]; 282 register VOLATILE struct scc_reg *port = scc->scc_port; 283 register int status; 284 register int param = 0; 285 286 port->ctrl = W0_RES_EXT; 287 SCCWAIT; 288 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 289 scc_reset(chan); 290 goto out; 291 } 292 status = port->ctrl; 293 SCCWAIT; 294 if (status & R0_DCD) 295 param |= DCD; 296 if (status & R0_CTS) 297 param |= CTS; 298 if (status & R0_BREAK){ 299 param |= RBREAK; 300 scc->scc_status |= LINE_BREAK; 301 } 302 if ((scc->scc_param & (DCD|CTS|RBREAK)) != param) { 303 scc->scc_param = (scc->scc_param & ~(DCD|CTS|RBREAK)) | param; 304 #if NRS > 0 305 rssint(chan, scc->scc_param); 306 #endif 307 } 308 out: 309 port->ctrl = W0_RES_IUS; 310 SCCWAIT; 311 } 312 313 scc_cint(vec) 314 int vec; 315 { 316 int chan = vec_to_chan(vec); 317 register Scc_channel *scc = &sccsw[chan]; 318 register VOLATILE struct scc_reg *port = scc->scc_port; 319 register int status; 320 int c; 321 322 if ((scc->scc_status & CHAN_ACTIVE) == 0) { 323 scc_reset(chan); 324 goto out; 325 } 326 status = scc_read_reg(chan, RR1); 327 if (status & R1_CRC) 328 scc->scc_param |= FRAMING_ERROR; 329 if (status & R1_OVRUN) { 330 if ((scc->scc_param & OVERRUN_ERROR) == 0) { 331 scc->scc_param |= OVERRUN_ERROR; 332 #if NRS > 0 333 rssint(chan, scc->scc_param); 334 #endif 335 } 336 } 337 if (status & R1_PARITY) { 338 scc->scc_param |= SCC_PARITY_ERROR; 339 while (port->ctrl & R0_RxCA) { 340 SCCWAIT; 341 c = port->data; 342 SCCWAIT; 343 #if NRS > 0 344 if (scc->scc_param & NOCHECK) 345 scc_pdma(chan, c); 346 #endif 347 } 348 SCCWAIT; 349 } 350 out: 351 port->ctrl = W0_RES_ERROR; 352 SCCWAIT; 353 port->ctrl = W0_RES_IUS; 354 SCCWAIT; 355 } 356 357 scc_write_reg(chan, reg, data) 358 int chan, reg, data; 359 { 360 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 361 362 port->ctrl = reg; 363 SCCWAIT; 364 port->ctrl = data; 365 SCCWAIT; 366 } 367 368 scc_read_reg(chan, reg) 369 int chan, reg; 370 { 371 register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 372 int result; 373 374 port->ctrl = reg; 375 SCCWAIT; 376 result = port->ctrl; 377 SCCWAIT; 378 return (result); 379 } 380 381 #ifdef news3400 382 #define DSRA 0x01 383 #define RIA 0x02 384 #define DSRB 0x04 385 #define RIB 0x08 386 387 #define DSRC 0x01 388 #define RIC 0x02 389 #define DSRD 0x04 390 #define RID 0x08 391 #define DSRE 0x10 392 #define RIE 0x20 393 #define DSRF 0x40 394 #define RIF 0x80 395 #endif /* news3400 */ 396 397 struct ri_dsr { 398 char *status; 399 int ri; 400 int dsr; 401 } ri_dsr[] = { 402 { (char *)SCC_STATUS0, RIA, DSRA }, 403 { (char *)SCC_STATUS0, RIB, DSRB }, 404 #if !defined(news3200) 405 { (char *)SCC_STATUS1, RIC, DSRC }, 406 { (char *)SCC_STATUS1, RID, DSRD }, 407 { (char *)SCC_STATUS1, RIE, DSRE }, 408 { (char *)SCC_STATUS1, RIF, DSRF }, 409 { (char *)SCC_STATUS2, RIC, DSRC }, 410 { (char *)SCC_STATUS2, RID, DSRD }, 411 { (char *)SCC_STATUS2, RIE, DSRE }, 412 { (char *)SCC_STATUS2, RIF, DSRF } 413 #endif /* !news3200 */ 414 }; 415 416 get_ri_dsr(chan) 417 int chan; 418 { 419 register struct ri_dsr *p; 420 register int status, param; 421 422 param = 0; 423 p = &ri_dsr[chan]; 424 status = *p->status; 425 if ((status & p->ri) == 0) 426 param |= RI; 427 if ((status & p->dsr) == 0) 428 param |= DSR; 429 return (param); 430 } 431 432 #if defined(news3400) 433 /* 434 * tc0 = floor(4915200 / 32 / baudrate - 2 + 0.5); 435 */ 436 static int tc0[] = { 437 0, /* B0 */ 438 3070, /* B50 */ 439 2046, /* B75 */ 440 1394, /* B110 */ 441 1144, /* B134 */ 442 1022, /* B150 */ 443 766, /* B200 */ 444 510, /* B300 */ 445 254, /* B600 */ 446 126, /* B1200 */ 447 83, /* B1800 */ 448 62, /* B2400 */ 449 30, /* B4800 */ 450 14, /* B9600 */ 451 6, /* EXTA (B19200) */ 452 2 /* EXTB (B38400) */ 453 }; 454 #endif /* news3400 */ 455 456 static int tc1[] = { 457 /* 458 * tc1 = floor(3686400 / 32 / baudrate - 2 + 0.5); 459 */ 460 0, /* B0 */ 461 2302, /* B50 */ 462 1534, /* B75 */ 463 1045, /* B110 */ 464 858, /* B134 */ 465 766, /* B150 */ 466 574, /* B200 */ 467 382, /* B300 */ 468 190, /* B600 */ 469 94, /* B1200 */ 470 62, /* B1800 */ 471 46, /* B2400 */ 472 22, /* B4800 */ 473 10, /* B9600 */ 474 4, /* B19200 */ 475 1, /* B38400 */ 476 }; 477 478 scc_set_param(chan, param) 479 int chan; 480 register int param; 481 { 482 register Scc_channel *scc = &sccsw[chan]; 483 register int bit, baud, *tc; 484 int s; 485 486 s = splscc(); 487 488 /* 489 * Baud rate / external clock 490 */ 491 if ((baud = param & BAUD_RATE) == EXTB && chan <= SCC_REMOTE1 && 492 param & EXTCLK_ENABLE) { 493 scc_write_reg(chan, WR11, W11_RxC_RTxC|W11_TxC_TRxC); 494 bit = W4_X1; 495 } else { 496 tc = (chan <= SCC_REMOTE1) ? tc0 : tc1; 497 scc_write_reg(chan, WR11, W11_RxC_BRG|W11_TxC_BRG); 498 scc_write_reg(chan, WR12, tc[baud] & 0xff); 499 scc_write_reg(chan, WR13, tc[baud] >> 8); 500 bit = W4_X16; 501 } 502 503 /* 504 * Clock mode / parity / stop bit 505 */ 506 if (param & PARITY) { 507 bit |= W4_PARITY; 508 if (param & EVEN) 509 bit |= W4_EVEN; 510 } 511 switch (param & STOPBIT) { 512 513 case STOP1: 514 bit |= W4_STOP1; 515 break; 516 517 case STOP1_5: 518 bit |= W4_STOP1_5; 519 break; 520 521 case STOP2: 522 bit |= W4_STOP2; 523 break; 524 525 } 526 scc_write_reg(chan, WR4, bit); 527 528 /* 529 * Receiver enable / receive character size / auto enable 530 */ 531 bit = (param & RXE ? W3_RxE : 0); 532 switch (param & CHAR_SIZE) { 533 534 case C5BIT: 535 break; 536 537 case C6BIT: 538 bit |= W3_Rx6BIT; 539 break; 540 541 case C7BIT: 542 bit |= W3_Rx7BIT; 543 break; 544 545 case C8BIT: 546 bit |= W3_Rx8BIT; 547 break; 548 } 549 #ifdef AUTO_ENABLE 550 if (param & AUTO_ENABLE) 551 bit |= W3_AUTO; 552 #endif /* AUTO_ENABLE */ 553 scc_write_reg(chan, WR3, bit); 554 555 /* 556 * Transmitter enable / transmit character size / RTS / DTR / BREAK 557 */ 558 bit = (param & TXE ? W5_TxE : 0); 559 switch (param & CHAR_SIZE) { 560 561 case C5BIT: 562 break; 563 564 case C6BIT: 565 bit |= W5_Tx6BIT; 566 break; 567 568 case C7BIT: 569 bit |= W5_Tx7BIT; 570 break; 571 572 case C8BIT: 573 bit |= W5_Tx8BIT; 574 break; 575 } 576 if (param & RTS) 577 bit |= W5_RTS; 578 if (param & DTR) 579 bit |= W5_DTR; 580 if (param & XBREAK) 581 bit |= W5_BREAK; 582 scc_write_reg(chan, WR5, bit); 583 scc->scc_param = param; 584 (void) splx(s); 585 return (0); 586 } 587 588 scc_get_param(chan) 589 int chan; 590 { 591 register Scc_channel *scc = &sccsw[chan]; 592 593 scc->scc_param = (scc->scc_param & ~(RI|DSR)) | get_ri_dsr(chan); 594 return (scc->scc_param); 595 } 596 597 scc_get_status(chan) 598 int chan; 599 { 600 601 return (sccsw[chan].scc_status); 602 } 603 604 scc_set_status(chan, stat) 605 int chan, stat; 606 { 607 608 sccsw[chan].scc_status = stat; 609 610 return (0); 611 } 612 613 scc_flush(chan) 614 int chan; 615 { 616 register Scc_channel *scc = &sccsw[chan]; 617 618 if (scc->scc_status & OACTIVE) 619 scc->scc_status |= OFLUSH; 620 else if (scc->x_dma.dma_count > 0) { 621 scc->x_dma.dma_count = 0; 622 #if NRS > 0 623 rsxint(chan); 624 #endif 625 } 626 return (0); 627 } 628 629 scc_start(chan) 630 int chan; 631 { 632 register Scc_channel *scc = &sccsw[chan]; 633 634 if ((scc->scc_status & OACTIVE) == 0 && scc->x_dma.dma_count > 0) { 635 scc->scc_port->data = *(scc->x_dma.dma_addr)++; 636 SCCWAIT; 637 scc->x_dma.dma_count--; 638 scc->scc_status |= OACTIVE; 639 } 640 return (0); 641 } 642 643 scc_stop(chan) 644 int chan; 645 { 646 register Scc_channel *scc = &sccsw[chan]; 647 648 if (scc->scc_status & OACTIVE) 649 scc->scc_status |= OSTOP; 650 return (0); 651 } 652 653 scc_write(chan, buf, count) 654 int chan; 655 caddr_t buf; 656 int count; 657 { 658 register Scc_channel *scc = &sccsw[chan]; 659 660 if (count <= 0) 661 return (0); 662 scc->x_dma.dma_addr = buf; 663 scc->x_dma.dma_count = count; 664 scc_start(chan); 665 return (count); 666 } 667 668 scc_error_write(chan, buf, count) 669 int chan; 670 register char *buf; 671 register int count; 672 { 673 register int i; 674 675 for (i = 0; i < count; i++) 676 scc_putc(chan, *buf++); 677 return (i); 678 } 679 680 scc_reset(chan) 681 int chan; 682 { 683 register Scc_channel *scc = &sccsw[chan]; 684 685 while (scc_getc(chan) != -1) 686 ; 687 scc->scc_status &= ~CHAN_ACTIVE; 688 } 689