|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * @APPLE_FREE_COPYRIGHT@ ! 27: */ ! 28: /* ! 29: * Mach Operating System ! 30: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 31: * All Rights Reserved. ! 32: * ! 33: * Permission to use, copy, modify and distribute this software and its ! 34: * documentation is hereby granted, provided that both the copyright ! 35: * notice and this permission notice appear in all copies of the ! 36: * software, derivative works or modified versions, and any portions ! 37: * thereof, and that both notices appear in supporting documentation. ! 38: * ! 39: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 40: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 41: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 42: * ! 43: * Carnegie Mellon requests users of this software to return to ! 44: * ! 45: * Software Distribution Coordinator or [email protected] ! 46: * School of Computer Science ! 47: * Carnegie Mellon University ! 48: * Pittsburgh PA 15213-3890 ! 49: * ! 50: * any improvements or extensions that they make and grant Carnegie Mellon ! 51: * the rights to redistribute these changes. ! 52: */ ! 53: /* ! 54: */ ! 55: /* ! 56: * File: scc_8530_hdw.c ! 57: * Author: Alessandro Forin, Carnegie Mellon University ! 58: * Date: 6/91 ! 59: * ! 60: * Hardware-level operations for the SCC Serial Line Driver ! 61: */ ! 62: ! 63: #define NSCC 1 /* Number of serial chips, two ports per chip. */ ! 64: #if NSCC > 0 ! 65: ! 66: #include <mach_kdb.h> ! 67: #include <platforms.h> ! 68: #include <kern/spl.h> ! 69: #include <mach/std_types.h> ! 70: #include <types.h> ! 71: #include <sys/syslog.h> ! 72: #include <ppc/misc_protos.h> ! 73: #include <ppc/proc_reg.h> ! 74: #include <ppc/exception.h> ! 75: #include <ppc/Firmware.h> ! 76: #include <ppc/POWERMAC/serial_io.h> ! 77: #include <pexpert/ppc/powermac.h> ! 78: #include <ppc/POWERMAC/scc_8530.h> ! 79: ! 80: #if MACH_KDB ! 81: #include <machine/db_machdep.h> ! 82: #endif /* MACH_KDB */ ! 83: ! 84: #define kdebug_state() (1) ! 85: #define delay(x) { volatile int _d_; for (_d_ = 0; _d_ < (10000*x); _d_++) ; } ! 86: ! 87: #define NSCC_LINE 2 /* 2 ttys per chip */ ! 88: ! 89: #define SCC_DMA_TRANSFERS 0 ! 90: ! 91: struct scc_tty scc_tty[NSCC_LINE]; ! 92: ! 93: #define scc_tty_for(chan) (&scc_tty[chan]) ! 94: /* #define scc_unit(dev_no) (dev_no) */ ! 95: ! 96: #define scc_dev_no(chan) ((chan)^0x01) ! 97: #define scc_chan(dev_no) ((dev_no)^0x01) ! 98: ! 99: int serial_initted = 0; ! 100: unsigned int scc_parm_done = 0; /* (TEST/DEBUG) */ ! 101: ! 102: static struct scc_byte { ! 103: unsigned char reg; ! 104: unsigned char val; ! 105: } scc_init_hw[] = { ! 106: ! 107: 9, 0x80, ! 108: 4, 0x44, ! 109: 3, 0xC0, ! 110: 5, 0xE2, ! 111: 2, 0x00, ! 112: 10, 0x00, ! 113: 11, 0x50, ! 114: 12, 0x0A, ! 115: 13, 0x00, ! 116: 3, 0xC1, ! 117: 5, 0xEA, ! 118: 14, 0x01, ! 119: 15, 0x00, ! 120: 0, 0x10, ! 121: 0, 0x10, ! 122: #if 0 ! 123: 1, 0x12, /* int or Rx, Tx int enable */ ! 124: #else ! 125: 1, 0x10, /* int or Rx, no Tx int enable */ ! 126: #endif ! 127: 9, 0x0A ! 128: }; ! 129: ! 130: static int scc_init_hw_count = sizeof(scc_init_hw)/sizeof(scc_init_hw[0]); ! 131: ! 132: enum scc_error {SCC_ERR_NONE, SCC_ERR_PARITY, SCC_ERR_BREAK, SCC_ERR_OVERRUN}; ! 133: ! 134: ! 135: /* ! 136: * BRG formula is: ! 137: * ClockFrequency (115200 for Power Mac) ! 138: * BRGconstant = --------------------------- - 2 ! 139: * BaudRate ! 140: */ ! 141: ! 142: #define SERIAL_CLOCK_FREQUENCY (115200*2) /* Power Mac value */ ! 143: #define convert_baud_rate(rate) ((((SERIAL_CLOCK_FREQUENCY) + (rate)) / (2 * (rate))) - 2) ! 144: ! 145: #define DEFAULT_SPEED 38400 ! 146: #define DEFAULT_FLAGS (TF_LITOUT|TF_ECHO) ! 147: ! 148: int scc_param(struct scc_tty *tp); ! 149: ! 150: ! 151: struct scc_softc scc_softc[NSCC]; ! 152: caddr_t scc_std[NSCC] = { (caddr_t) 0}; ! 153: ! 154: ! 155: #define SCC_RR1_ERRS (SCC_RR1_FRAME_ERR|SCC_RR1_RX_OVERRUN|SCC_RR1_PARITY_ERR) ! 156: #define SCC_RR3_ALL (SCC_RR3_RX_IP_A|SCC_RR3_TX_IP_A|SCC_RR3_EXT_IP_A|\ ! 157: SCC_RR3_RX_IP_B|SCC_RR3_TX_IP_B|SCC_RR3_EXT_IP_B) ! 158: ! 159: #define DEBUG_SCC ! 160: #undef DEBUG_SCC ! 161: ! 162: #ifdef DEBUG_SCC ! 163: static int total_chars, total_ints, total_overruns, total_errors, num_ints, max_chars; ! 164: static int chars_received[8]; ! 165: static int __SCC_STATS = 0; ! 166: static int max_in_q = 0; ! 167: static int max_out_q = 0; ! 168: #endif ! 169: ! 170: DECL_FUNNEL(, scc_funnel) /* funnel to serialize the SCC driver */ ! 171: boolean_t scc_funnel_initted = FALSE; ! 172: #define SCC_FUNNEL scc_funnel ! 173: #define SCC_FUNNEL_INITTED scc_funnel_initted ! 174: ! 175: ! 176: /* ! 177: * Adapt/Probe/Attach functions ! 178: */ ! 179: boolean_t scc_uses_modem_control = FALSE;/* patch this with adb */ ! 180: decl_simple_lock_data(,scc_stomp) /* (TEST/DEBUG) */ ! 181: ! 182: /* This is called VERY early on in the init and therefore has to have ! 183: * hardcoded addresses of the serial hardware control registers. The ! 184: * serial line may be needed for console and debugging output before ! 185: * anything else takes place ! 186: */ ! 187: ! 188: void ! 189: initialize_serial( caddr_t scc_phys_base ) ! 190: { ! 191: int i, chan, bits; ! 192: scc_regmap_t regs; ! 193: DECL_FUNNEL_VARS ! 194: ! 195: assert( scc_phys_base ); ! 196: ! 197: if (!SCC_FUNNEL_INITTED) { ! 198: FUNNEL_INIT(&SCC_FUNNEL, master_processor); ! 199: SCC_FUNNEL_INITTED = TRUE; ! 200: } ! 201: FUNNEL_ENTER(&SCC_FUNNEL); ! 202: ! 203: if (serial_initted) { ! 204: FUNNEL_EXIT(&SCC_FUNNEL); ! 205: return; ! 206: } ! 207: ! 208: simple_lock_init(&scc_stomp, FALSE); /* (TEST/DEBUG) */ ! 209: ! 210: scc_softc[0].full_modem = TRUE; ! 211: ! 212: scc_std[0] = scc_phys_base; ! 213: ! 214: regs = scc_softc[0].regs = (scc_regmap_t)scc_std[0]; ! 215: ! 216: for (chan = 0; chan < NSCC_LINE; chan++) { ! 217: if (chan == 1) ! 218: scc_init_hw[0].val = 0x80; ! 219: ! 220: for (i = 0; i < scc_init_hw_count; i++) { ! 221: scc_write_reg(regs, chan, ! 222: scc_init_hw[i].reg, scc_init_hw[i].val); ! 223: } ! 224: } ! 225: ! 226: /* Call probe so we are ready very early for remote gdb and for serial ! 227: console output if appropriate. */ ! 228: if (scc_probe()) { ! 229: for (i = 0; i < NSCC_LINE; i++) { ! 230: scc_softc[0].softr[i].wr5 = SCC_WR5_DTR | SCC_WR5_RTS; ! 231: scc_param(scc_tty_for(i)); ! 232: /* Enable SCC interrupts (how many interrupts are to this thing?!?) */ ! 233: scc_write_reg(regs, i, 9, SCC_WR9_NV); ! 234: ! 235: scc_read_reg_zero(regs, 0, bits);/* Clear the status */ ! 236: } ! 237: scc_parm_done = 1; /* (TEST/DEBUG) */ ! 238: } ! 239: ! 240: serial_initted = TRUE; ! 241: ! 242: FUNNEL_EXIT(&SCC_FUNNEL); ! 243: return; ! 244: } ! 245: ! 246: int ! 247: scc_probe(void) ! 248: { ! 249: scc_softc_t scc; ! 250: register int val, i; ! 251: register scc_regmap_t regs; ! 252: spl_t s; ! 253: DECL_FUNNEL_VARS ! 254: ! 255: if (!SCC_FUNNEL_INITTED) { ! 256: FUNNEL_INIT(&SCC_FUNNEL, master_processor); ! 257: SCC_FUNNEL_INITTED = TRUE; ! 258: } ! 259: FUNNEL_ENTER(&SCC_FUNNEL); ! 260: ! 261: /* Readjust the I/O address to handling ! 262: * new memory mappings. ! 263: */ ! 264: ! 265: // scc_std[0] = POWERMAC_IO(scc_std[0]); ! 266: ! 267: regs = (scc_regmap_t)scc_std[0]; ! 268: ! 269: if (regs == (scc_regmap_t) 0) { ! 270: FUNNEL_EXIT(&SCC_FUNNEL); ! 271: return 0; ! 272: } ! 273: ! 274: scc = &scc_softc[0]; ! 275: scc->regs = regs; ! 276: ! 277: s = splhigh(); ! 278: ! 279: for (i = 0; i < NSCC_LINE; i++) { ! 280: register struct scc_tty *tp; ! 281: tp = scc_tty_for(i); ! 282: tp->t_addr = (char*)(0x80000000L + (i&1)); ! 283: /* Set default values. These will be overridden on ! 284: open but are needed if the port will be used ! 285: independently of the Mach interfaces, e.g., for ! 286: gdb or for a serial console. */ ! 287: tp->t_ispeed = DEFAULT_SPEED; ! 288: tp->t_ospeed = DEFAULT_SPEED; ! 289: tp->t_flags = DEFAULT_FLAGS; ! 290: scc->softr[i].speed = -1; ! 291: ! 292: /* do min buffering */ ! 293: tp->t_state |= TS_MIN; ! 294: ! 295: tp->t_dev = scc_dev_no(i); ! 296: } ! 297: ! 298: splx(s); ! 299: ! 300: FUNNEL_EXIT(&SCC_FUNNEL); ! 301: return 1; ! 302: } ! 303: ! 304: /* ! 305: * Get a char from a specific SCC line ! 306: * [this is only used for console&screen purposes] ! 307: * must be splhigh since it may be called from another routine under spl ! 308: */ ! 309: ! 310: int ! 311: scc_getc(int unit, int line, boolean_t wait, boolean_t raw) ! 312: { ! 313: register scc_regmap_t regs; ! 314: unsigned char c, value; ! 315: int rcvalue, from_line; ! 316: spl_t s = splhigh(); ! 317: DECL_FUNNEL_VARS ! 318: ! 319: FUNNEL_ENTER(&SCC_FUNNEL); ! 320: ! 321: simple_lock(&scc_stomp); /* (TEST/DEBUG) */ ! 322: regs = scc_softc[0].regs; ! 323: ! 324: /* ! 325: * wait till something available ! 326: * ! 327: */ ! 328: again: ! 329: rcvalue = 0; ! 330: while (1) { ! 331: scc_read_reg_zero(regs, line, value); ! 332: ! 333: if (value & SCC_RR0_RX_AVAIL) ! 334: break; ! 335: ! 336: if (!wait) { ! 337: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 338: splx(s); ! 339: FUNNEL_EXIT(&SCC_FUNNEL); ! 340: return -1; ! 341: } ! 342: } ! 343: ! 344: /* ! 345: * if nothing found return -1 ! 346: */ ! 347: ! 348: scc_read_reg(regs, line, SCC_RR1, value); ! 349: scc_read_data(regs, line, c); ! 350: ! 351: #if MACH_KDB ! 352: if (console_is_serial() && ! 353: c == ('_' & 0x1f)) { ! 354: /* Drop into the debugger */ ! 355: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 356: Debugger("Serial Line Request"); ! 357: simple_lock(&scc_stomp); /* (TEST/DEBUG) */ ! 358: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 359: if (wait) { ! 360: goto again; ! 361: } ! 362: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 363: splx(s); ! 364: FUNNEL_EXIT(&SCC_FUNNEL); ! 365: return -1; ! 366: } ! 367: #endif /* MACH_KDB */ ! 368: ! 369: /* ! 370: * bad chars not ok ! 371: */ ! 372: if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) { ! 373: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_ERROR); ! 374: ! 375: if (wait) { ! 376: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 377: goto again; ! 378: } ! 379: } ! 380: ! 381: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 382: ! 383: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 384: splx(s); ! 385: ! 386: FUNNEL_EXIT(&SCC_FUNNEL); ! 387: return c; ! 388: } ! 389: ! 390: /* ! 391: * Put a char on a specific SCC line ! 392: * use splhigh since we might be doing a printf in high spl'd code ! 393: */ ! 394: ! 395: int ! 396: scc_putc(int unit, int line, int c) ! 397: { ! 398: scc_regmap_t regs; ! 399: spl_t s = splhigh(); ! 400: unsigned char value; ! 401: DECL_FUNNEL_VARS ! 402: ! 403: FUNNEL_ENTER(&SCC_FUNNEL); ! 404: simple_lock(&scc_stomp); /* (TEST/DEBUG) */ ! 405: ! 406: regs = scc_softc[0].regs; ! 407: ! 408: do { ! 409: scc_read_reg(regs, line, SCC_RR0, value); ! 410: if (value & SCC_RR0_TX_EMPTY) ! 411: break; ! 412: delay(1); ! 413: } while (1); ! 414: ! 415: scc_write_data(regs, line, c); ! 416: /* wait for it to swallow the char ? */ ! 417: ! 418: do { ! 419: scc_read_reg(regs, line, SCC_RR0, value); ! 420: if (value & SCC_RR0_TX_EMPTY) ! 421: break; ! 422: } while (1); ! 423: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 424: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 425: ! 426: splx(s); ! 427: ! 428: FUNNEL_EXIT(&SCC_FUNNEL); ! 429: return 0; ! 430: } ! 431: ! 432: ! 433: void ! 434: powermac_scc_set_datum(scc_regmap_t regs, unsigned int offset, unsigned char value) ! 435: { ! 436: volatile unsigned char *address = (unsigned char *) regs + offset; ! 437: ! 438: assert(FUNNEL_IN_USE(&SCC_FUNNEL)); ! 439: ! 440: *address = value; ! 441: eieio(); ! 442: ! 443: assert(FUNNEL_IN_USE(&SCC_FUNNEL)); ! 444: } ! 445: ! 446: unsigned char ! 447: powermac_scc_get_datum(scc_regmap_t regs, unsigned int offset) ! 448: { ! 449: volatile unsigned char *address = (unsigned char *) regs + offset; ! 450: unsigned char value; ! 451: ! 452: assert(FUNNEL_IN_USE(&SCC_FUNNEL)); ! 453: ! 454: value = *address; eieio(); ! 455: return value; ! 456: ! 457: assert(FUNNEL_IN_USE(&SCC_FUNNEL)); ! 458: } ! 459: ! 460: int ! 461: scc_param(struct scc_tty *tp) ! 462: { ! 463: scc_regmap_t regs; ! 464: unsigned char value; ! 465: unsigned short speed_value; ! 466: int bits, chan; ! 467: spl_t s; ! 468: struct scc_softreg *sr; ! 469: scc_softc_t scc; ! 470: ! 471: assert(FUNNEL_IN_USE(&SCC_FUNNEL)); ! 472: ! 473: s = splhigh(); ! 474: simple_lock(&scc_stomp); /* (TEST/DEBUG) */ ! 475: ! 476: chan = scc_chan(tp->t_dev); ! 477: scc = &scc_softc[0]; ! 478: regs = scc->regs; ! 479: ! 480: sr = &scc->softr[chan]; ! 481: ! 482: /* Do a quick check to see if the hardware needs to change */ ! 483: if ((sr->flags & (TF_ODDP|TF_EVENP)) == (tp->t_flags & (TF_ODDP|TF_EVENP)) ! 484: && sr->speed == tp->t_ispeed) { ! 485: assert(FUNNEL_IN_USE(&SCC_FUNNEL)); ! 486: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 487: splx(s); /* (TEST/DEBUG) */ ! 488: return 0; /* (TEST/DEBUG) */ ! 489: } ! 490: ! 491: if(scc_parm_done) { ! 492: ! 493: scc_write_reg(regs, chan, 3, SCC_WR3_RX_8_BITS|SCC_WR3_RX_ENABLE); /* (TEST/DEBUG) */ ! 494: sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE; /* (TEST/DEBUG) */ ! 495: scc_write_reg(regs, chan, 1, sr->wr1); /* (TEST/DEBUG) */ ! 496: scc_write_reg(regs, chan, 15, SCC_WR15_ENABLE_ESCC); /* (TEST/DEBUG) */ ! 497: scc_write_reg(regs, chan, 7, SCC_WR7P_RX_FIFO); /* (TEST/DEBUG) */ ! 498: scc_write_reg(regs, chan, 0, SCC_IE_NEXT_CHAR); /* (TEST/DEBUG) */ ! 499: scc_write_reg(regs, chan, 0, SCC_RESET_EXT_IP); /* (TEST/DEBUG) */ ! 500: scc_write_reg(regs, chan, 0, SCC_RESET_EXT_IP); /* (TEST/DEBUG) */ ! 501: scc_write_reg(regs, chan, 9, SCC_WR9_MASTER_IE|SCC_WR9_NV); /* (TEST/DEBUG) */ ! 502: scc_read_reg_zero(regs, 0, bits); /* (TEST/DEBUG) */ ! 503: sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE; /* (TEST/DEBUG) */ ! 504: scc_write_reg(regs, chan, 1, sr->wr1); /* (TEST/DEBUG) */ ! 505: scc_write_reg(regs, chan, 0, SCC_IE_NEXT_CHAR); /* (TEST/DEBUG) */ ! 506: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 507: splx(s); /* (TEST/DEBUG) */ ! 508: return 0; /* (TEST/DEBUG) */ ! 509: } ! 510: ! 511: sr->flags = tp->t_flags; ! 512: sr->speed = tp->t_ispeed; ! 513: ! 514: ! 515: if (tp->t_ispeed == 0) { ! 516: sr->wr5 &= ~SCC_WR5_DTR; ! 517: scc_write_reg(regs, chan, 5, sr->wr5); ! 518: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 519: splx(s); ! 520: ! 521: assert(FUNNEL_IN_USE(&SCC_FUNNEL)); ! 522: return 0; ! 523: } ! 524: ! 525: ! 526: #if SCC_DMA_TRANSFERS ! 527: if (scc->dma_initted & (1<<chan)) ! 528: scc->dma_ops->scc_dma_reset_rx(chan); ! 529: #endif ! 530: ! 531: value = SCC_WR4_1_STOP; ! 532: ! 533: /* ! 534: * For 115K the clocking divide changes to 64.. to 230K will ! 535: * start at the normal clock divide 16. ! 536: * ! 537: * However, both speeds will pull from a different clocking ! 538: * source ! 539: */ ! 540: ! 541: if (tp->t_ispeed == 115200) ! 542: value |= SCC_WR4_CLK_x32; ! 543: else ! 544: value |= SCC_WR4_CLK_x16 ; ! 545: ! 546: /* .. and parity */ ! 547: if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_EVENP) ! 548: value |= (SCC_WR4_EVEN_PARITY | SCC_WR4_PARITY_ENABLE); ! 549: else if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP) ! 550: value |= SCC_WR4_PARITY_ENABLE; ! 551: ! 552: /* set it now, remember it must be first after reset */ ! 553: sr->wr4 = value; ! 554: ! 555: /* Program Parity, and Stop bits */ ! 556: scc_write_reg(regs, chan, 4, sr->wr4); ! 557: ! 558: /* Setup for 8 bits */ ! 559: scc_write_reg(regs, chan, 3, SCC_WR3_RX_8_BITS); ! 560: ! 561: // Set DTR, RTS, and transmitter bits/character. ! 562: sr->wr5 = SCC_WR5_TX_8_BITS | SCC_WR5_RTS | SCC_WR5_DTR; ! 563: ! 564: scc_write_reg(regs, chan, 5, sr->wr5); ! 565: ! 566: scc_write_reg(regs, chan, 14, 0); /* Disable baud rate */ ! 567: ! 568: /* Setup baud rate 57.6Kbps, 115K, 230K should all yeild ! 569: * a converted baud rate of zero ! 570: */ ! 571: speed_value = convert_baud_rate(tp->t_ispeed); ! 572: ! 573: if (speed_value == 0xffff) ! 574: speed_value = 0; ! 575: ! 576: scc_set_timing_base(regs, chan, speed_value); ! 577: ! 578: if (tp->t_ispeed == 115200 || tp->t_ispeed == 230400) { ! 579: /* Special case here.. change the clock source*/ ! 580: scc_write_reg(regs, chan, 11, 0); ! 581: /* Baud rate generator is disabled.. */ ! 582: } else { ! 583: scc_write_reg(regs, chan, 11, SCC_WR11_RCLK_BAUDR|SCC_WR11_XTLK_BAUDR); ! 584: /* Enable the baud rate generator */ ! 585: scc_write_reg(regs, chan, 14, SCC_WR14_BAUDR_ENABLE); ! 586: } ! 587: ! 588: ! 589: scc_write_reg(regs, chan, 3, SCC_WR3_RX_8_BITS|SCC_WR3_RX_ENABLE); ! 590: ! 591: ! 592: sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE; ! 593: scc_write_reg(regs, chan, 1, sr->wr1); ! 594: scc_write_reg(regs, chan, 15, SCC_WR15_ENABLE_ESCC); ! 595: scc_write_reg(regs, chan, 7, SCC_WR7P_RX_FIFO); ! 596: scc_write_reg(regs, chan, 0, SCC_IE_NEXT_CHAR); ! 597: ! 598: ! 599: /* Clear out any pending external or status interrupts */ ! 600: scc_write_reg(regs, chan, 0, SCC_RESET_EXT_IP); ! 601: scc_write_reg(regs, chan, 0, SCC_RESET_EXT_IP); ! 602: //scc_write_reg(regs, chan, 0, SCC_RESET_ERROR); ! 603: ! 604: /* Enable SCC interrupts (how many interrupts are to this thing?!?) */ ! 605: scc_write_reg(regs, chan, 9, SCC_WR9_MASTER_IE|SCC_WR9_NV); ! 606: ! 607: scc_read_reg_zero(regs, 0, bits);/* Clear the status */ ! 608: ! 609: #if SCC_DMA_TRANSFERS ! 610: if (scc->dma_initted & (1<<chan)) { ! 611: scc->dma_ops->scc_dma_start_rx(chan); ! 612: scc->dma_ops->scc_dma_setup_8530(chan); ! 613: } else ! 614: #endif ! 615: { ! 616: sr->wr1 = SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_EXT_IE; ! 617: scc_write_reg(regs, chan, 1, sr->wr1); ! 618: scc_write_reg(regs, chan, 0, SCC_IE_NEXT_CHAR); ! 619: } ! 620: ! 621: sr->wr5 |= SCC_WR5_TX_ENABLE; ! 622: scc_write_reg(regs, chan, 5, sr->wr5); ! 623: ! 624: simple_unlock(&scc_stomp); /* (TEST/DEBUG) */ ! 625: splx(s); ! 626: ! 627: assert(FUNNEL_IN_USE(&SCC_FUNNEL)); ! 628: return 0; ! 629: ! 630: } ! 631: ! 632: #endif /* NSCC > 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.