|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * File: scc_8530_hdw.c ! 27: * Author: Alessandro Forin, Carnegie Mellon University ! 28: * Date: 6/91 ! 29: * ! 30: * Hardware-level operations for the SCC Serial Line Driver ! 31: */ ! 32: ! 33: #define NSCC 1 /* Number of serial chips, two ports per chip. */ ! 34: #if NSCC > 0 ! 35: ! 36: /* #include <mach_kgdb.h> */ ! 37: ! 38: /* #include <platforms.h> */ ! 39: ! 40: /* #include <mach_kdb.h> */ ! 41: /* #include <kgdb/gdb_defs.h> */ ! 42: /* #include <kgdb/kgdb_defs.h> */ /* For kgdb_printf */ ! 43: ! 44: #include <kernserv/machine/spl.h> ! 45: #include <mach/std_types.h> ! 46: /* #include <types.h> */ ! 47: /* #include <sys/syslog.h> */ ! 48: /* #include <device/io_req.h> */ ! 49: /* #include <device/tty.h> */ ! 50: /* #include <chips/busses.h> */ ! 51: /* #include <ppc/misc_protos.h> */ ! 52: #include <machdep/ppc/proc_reg.h> ! 53: #include <mach/machine/exception.h> ! 54: #include <machdep/ppc/serial_io.h> ! 55: #include <machdep/ppc/powermac.h> ! 56: #include <machdep/ppc/interrupts.h> ! 57: #include <machdep/ppc/scc_8530.h> ! 58: ! 59: #define kdebug_state() (1) ! 60: #define scc_delay(x) { volatile int _d_; for (_d_ = 0; _d_ < (10000*x); _d_++) ; } ! 61: ! 62: #define NSCC_LINE 2 /* 2 ttys per chip */ ! 63: ! 64: #if !MACH_KGDB ! 65: #define SCC_DMA_TRANSFERS 1 ! 66: #else ! 67: /* ! 68: * Don't deal with DMA because of the way KGDB needs to handle ! 69: * the system and serial ports. ! 70: */ ! 71: #define SCC_DMA_TRANSFERS 0 ! 72: #endif ! 73: ! 74: /*struct tty scc_tty[NSCC_LINE];*/ ! 75: ! 76: #define scc_dev_no(chan) (chan) ! 77: /* #define scc_tty_for(chan) (&scc_tty[chan]) */ ! 78: #define scc_unit(dev_no) (dev_no) ! 79: #define scc_chan(dev_no) (dev_no) ! 80: ! 81: int serial_initted = 0; ! 82: ! 83: static struct scc_byte { ! 84: unsigned char reg; ! 85: unsigned char val; ! 86: } scc_init_hw[] = { ! 87: 9, 0x40, /* SCC_WR9_RESET_CHA_B */ ! 88: 4, 0x44, /* SCC_WR4_CLK_x16| SCC_WR4_1_STOP, */ ! 89: 3, 0xC0, /* SCC_WR3_RX_8_BITS| */ ! 90: 5, 0xE2, /* SCC_WR5_DTR| SCC_WR5_TX_8_BITS| SCC_WR5_RTS, */ ! 91: 2, 0x00, ! 92: 10, 0x00, /* SCC_WR10_NRZ| SCC_WR10_8BIT_SYNCH, */ ! 93: 11, 0x50, /* SCC_WR11_RCLK_BAUDR| SCC_WR11_XTLK_BAUDR| ! 94: SCC_WR11_XTLK_RTc_PIN| SCC_WR11_TRcOUT_XTAL, */ ! 95: 12, 0x01, ! 96: 13, 0x00, ! 97: 3, 0xC1, /* SCC_WR3_RX_8_BITS| SCC_WR3_RX_ENABLE, */ ! 98: 5, 0xEA, /* SCC_WR5_DTR| SCC_WR5_TX_8_BITS| ! 99: SCC_WR5_TX_ENABLE| SCC_WR5_RTS, */ ! 100: 14, 0x01, /* SCC_WR14_BAUDR_ENABLE, */ ! 101: 15, 0x00, ! 102: 0, 0x10, /* SCC_RESET_EXT_IP, */ ! 103: 0, 0x10, /* SCC_RESET_EXT_IP, */ ! 104: 1, 0x12, /* SCC_WR1_RXI_ALL_CHAR|SCC_WR1_TX_IE, */ ! 105: 9, 0x0A /* SCC_WR9_MASTER_IE| SCC_WR9_NV, */ ! 106: ! 107: }; ! 108: ! 109: static int scc_init_hw_count = sizeof(scc_init_hw)/sizeof(scc_init_hw[0]); ! 110: ! 111: enum scc_error {SCC_ERR_NONE, SCC_ERR_PARITY, SCC_ERR_BREAK, SCC_ERR_OVERRUN}; ! 112: ! 113: ! 114: /* ! 115: * BRG formula is: ! 116: * ClockFrequency (115200 for Power Mac) ! 117: * BRGconstant = --------------------------- - 2 ! 118: * BaudRate ! 119: */ ! 120: ! 121: #define SERIAL_CLOCK_FREQUENCY (115200*2) /* Power Mac value */ ! 122: #define convert_baud_rate(rate) ((((SERIAL_CLOCK_FREQUENCY) + (rate)) / (2 * (rate))) - 2) ! 123: ! 124: #define DEFAULT_SPEED 9600 ! 125: #define DEFAULT_FLAGS (TF_LITOUT|TF_ECHO) ! 126: ! 127: #ifdef notdef_next ! 128: void scc_attach(struct bus_device *ui ); ! 129: void scc_set_modem_control(scc_softc_t scc, boolean_t on); ! 130: int scc_pollc(int unit, boolean_t on); ! 131: int scc_param(struct tty *tp); ! 132: int scc_mctl(struct tty* tp, int bits, int how); ! 133: int scc_cd_scan(void); ! 134: void scc_start(struct tty *tp); ! 135: void scc_intr(int device, struct ppc_saved_state *); ! 136: int scc_simple_tint(dev_t dev, boolean_t all_sent); ! 137: void scc_input(dev_t dev, int c, enum scc_error err); ! 138: void scc_stop(struct tty *tp, int flags); ! 139: void scc_update_modem(struct tty *tp); ! 140: void scc_waitforempty(struct tty *tp); ! 141: #endif /* notdef_next */ ! 142: ! 143: struct scc_softc scc_softc[NSCC]; ! 144: caddr_t scc_std[NSCC] = { (caddr_t) 0}; ! 145: ! 146: #ifdef notdef_next ! 147: /* ! 148: * Definition of the driver for the auto-configuration program. ! 149: */ ! 150: ! 151: struct bus_device *scc_info[NSCC]; ! 152: ! 153: struct bus_driver scc_driver = ! 154: {scc_probe, ! 155: 0, ! 156: scc_attach, ! 157: 0, ! 158: scc_std, ! 159: "scc", ! 160: scc_info, ! 161: 0, ! 162: 0, ! 163: 0 ! 164: }; ! 165: #endif /* notdef_next */ ! 166: ! 167: #if SCC_DMA_TRANSFERS ! 168: ! 169: extern struct scc_dma_ops scc_amic_ops /*, scc_db_ops*/; ! 170: #endif ! 171: ! 172: /* ! 173: * Adapt/Probe/Attach functions ! 174: */ ! 175: boolean_t scc_uses_modem_control = FALSE;/* patch this with adb */ ! 176: ! 177: /* This is called VERY early on in the init and therefore has to have ! 178: * hardcoded addresses of the serial hardware control registers. The ! 179: * serial line may be needed for console and debugging output before ! 180: * anything else takes place ! 181: */ ! 182: ! 183: void ! 184: initialize_serial() ! 185: { ! 186: int i, chan, bits; ! 187: scc_regmap_t regs; ! 188: /* static struct bus_device d; */ ! 189: ! 190: if (serial_initted) ! 191: return; ! 192: ! 193: // If this machine has PMU then turn on the serial ports. ! 194: if (HasPMU()) { ! 195: volatile unsigned long *ohareFeatureCntl; ! 196: ! 197: ohareFeatureCntl = powermac_io_info.io_base_phys + 0x38; ! 198: ! 199: *ohareFeatureCntl &= ~(1 << 24); ! 200: eieio(); ! 201: *ohareFeatureCntl |= (1 << 17) | ( 1 << 22) | (1 << 23); ! 202: eieio(); ! 203: } ! 204: ! 205: scc_softc[0].full_modem = TRUE; ! 206: ! 207: scc_std[0] = (caddr_t) PCI_SCC_BASE_PHYS; ! 208: ! 209: regs = scc_softc[0].regs = (scc_regmap_t)scc_std[0]; ! 210: ! 211: scc_write_reg(regs, 0, 9, 0xc0); /* hard reset */ ! 212: scc_delay(100); ! 213: for (chan = 0; chan < NSCC_LINE; chan++) { ! 214: if (chan == 1) ! 215: scc_init_hw[0].val = 0x80; ! 216: ! 217: for (i = 0; i < scc_init_hw_count; i++) { ! 218: if (scc_init_hw[i].reg == 0xff) { ! 219: scc_delay(100); ! 220: } else ! 221: scc_write_reg(regs, chan, ! 222: scc_init_hw[i].reg, scc_init_hw[i].val); ! 223: } ! 224: } ! 225: ! 226: #ifdef notdef_next ! 227: /* Call probe so we are ready very early for remote gdb and for serial ! 228: console output if appropriate. */ ! 229: /* d.unit = 0; */ ! 230: if (scc_probe(0, (void *) &d)) { ! 231: for (i = 0; i < NSCC_LINE; i++) { ! 232: scc_softc[0].softr[i].wr5 = SCC_WR5_DTR | SCC_WR5_RTS; ! 233: scc_param(scc_tty_for(i)); ! 234: /* Enable SCC interrupts (how many interrupts are to this thing?!?) */ ! 235: scc_write_reg(regs, i, 9, SCC_WR9_NV); ! 236: ! 237: scc_read_reg_zero(regs, 0, bits);/* Clear the status */ ! 238: } ! 239: } ! 240: #endif /* notdef_next */ ! 241: ! 242: serial_initted = TRUE; ! 243: return; ! 244: } ! 245: ! 246: #ifdef notdef_next ! 247: int ! 248: scc_probe(caddr_t xxx, void *param) ! 249: { ! 250: struct bus_device *ui = (struct bus_device *) param; ! 251: scc_softc_t scc; ! 252: register int val, i; ! 253: register scc_regmap_t regs; ! 254: spl_t s; ! 255: ! 256: /* Readjust the I/O address to handling ! 257: * new memory mappings. ! 258: */ ! 259: ! 260: scc_std[0] = POWERMAC_IO(scc_std[0]); ! 261: ! 262: regs = (scc_regmap_t)scc_std[0]; ! 263: ! 264: if (regs == (scc_regmap_t) 0) { ! 265: return 0; ! 266: } ! 267: ! 268: scc = &scc_softc[0]; ! 269: scc->regs = regs; ! 270: ! 271: if (scc->probed_once++){ ! 272: /* Second time in means called from system */ ! 273: ! 274: switch (powermac_info.class) { ! 275: case POWERMAC_CLASS_PDM: ! 276: #if SCC_DMA_TRANSFERS ! 277: scc_softc[0].dma_ops = &scc_amic_ops; ! 278: #endif ! 279: pmac_register_int(PMAC_DEV_SCC, SPLTTY, ! 280: (void (*)(int, void *))scc_intr); ! 281: break; ! 282: ! 283: case POWERMAC_CLASS_PCI: ! 284: #if SCC_DMA_TRANSFERS ! 285: /*scc_softc[0].dma_ops = &scc_db_ops;*/ ! 286: #endif ! 287: pmac_register_int(PMAC_DEV_SCC_A, SPLTTY, ! 288: (void (*)(int, void *))scc_intr); ! 289: pmac_register_int(PMAC_DEV_SCC_B, SPLTTY, ! 290: (void (*)(int, void *))scc_intr); ! 291: break; ! 292: default: ! 293: panic("unsupported class for serial code\n"); ! 294: } ! 295: ! 296: return 1; ! 297: } ! 298: ! 299: s = spltty(); ! 300: ! 301: for (i = 0; i < NSCC_LINE; i++) { ! 302: register struct tty *tp; ! 303: tp = scc_tty_for(i); ! 304: simple_lock_init(&tp->t_lock); ! 305: tp->t_addr = (char*)(0x80000000L + (i&1)); ! 306: /* Set default values. These will be overridden on ! 307: open but are needed if the port will be used ! 308: independently of the Mach interfaces, e.g., for ! 309: gdb or for a serial console. */ ! 310: tp->t_ispeed = DEFAULT_SPEED; ! 311: tp->t_ospeed = DEFAULT_SPEED; ! 312: tp->t_flags = DEFAULT_FLAGS; ! 313: scc->softr[i].speed = -1; ! 314: ! 315: /* do min buffering */ ! 316: tp->t_state |= TS_MIN; ! 317: ! 318: tp->t_dev = scc_dev_no(i); ! 319: } ! 320: ! 321: splx(s); ! 322: ! 323: return 1; ! 324: } ! 325: ! 326: boolean_t scc_timer_started = FALSE; ! 327: ! 328: void ! 329: scc_attach( register struct bus_device *ui ) ! 330: { ! 331: extern int tty_inq_size, tty_outq_size; ! 332: int i; ! 333: struct tty *tp; ! 334: ! 335: #if SCC_DMA_TRANSFERS ! 336: /* DMA Serial can send a lot... ;-) */ ! 337: tty_inq_size = 16384; ! 338: tty_outq_size = 16384; ! 339: ! 340: for (i = 0; i < NSCC_LINE; i++) { ! 341: if (scc_softc[0].dma_ops) { ! 342: scc_softc[0].dma_ops->scc_dma_init(i); ! 343: scc_softc[0].dma_initted |= (1<<i); ! 344: } ! 345: } ! 346: #endif ! 347: ! 348: if (!scc_timer_started) { ! 349: /* do all of them, before we call scc_scan() */ ! 350: /* harmless if done already */ ! 351: for (i = 0; i < NSCC_LINE; i++) { ! 352: tp = scc_tty_for(i); ! 353: ttychars(tp); ! 354: /* hack MEB 1/5/96 */ ! 355: tp->t_state |= TS_CARR_ON; ! 356: scc_softc[0].modem[i] = 0; ! 357: } ! 358: ! 359: scc_timer_started = TRUE; ! 360: scc_cd_scan(); ! 361: } ! 362: ! 363: printf("\n sl0: ( alternate console )\n sl1:"); ! 364: return; ! 365: } ! 366: ! 367: /* ! 368: * Would you like to make a phone call ? ! 369: */ ! 370: ! 371: void ! 372: scc_set_modem_control(scc, on) ! 373: scc_softc_t scc; ! 374: boolean_t on; ! 375: { ! 376: scc->full_modem = on; ! 377: /* user should do an scc_param() ifchanged */ ! 378: } ! 379: ! 380: /* ! 381: * Polled I/O (debugger) ! 382: */ ! 383: ! 384: int ! 385: scc_pollc(int unit, boolean_t on) ! 386: { ! 387: scc_softc_t scc; ! 388: ! 389: scc = &scc_softc[unit]; ! 390: if (on) { ! 391: scc->polling_mode++; ! 392: } else ! 393: scc->polling_mode--; ! 394: ! 395: return 0; ! 396: } ! 397: ! 398: /* ! 399: * Interrupt routine ! 400: */ ! 401: int scc_intr_count; ! 402: ! 403: void ! 404: scc_intr(int device, struct ppc_saved_state *ssp) ! 405: { ! 406: int chan; ! 407: scc_softc_t scc = &scc_softc[0]; ! 408: register scc_regmap_t regs = scc->regs; ! 409: register int rr1, rr2, status; ! 410: register int c; ! 411: ! 412: scc_intr_count++; ! 413: ! 414: scc_read_reg_zero(regs, 0, status);/* Clear the status */ ! 415: ! 416: scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR2, rr2); ! 417: ! 418: rr2 = SCC_RR2_STATUS(rr2); ! 419: ! 420: /*printf("{INTR %x}", rr2);*/ ! 421: if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { ! 422: ! 423: chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? ! 424: SCC_CHANNEL_A : SCC_CHANNEL_B; ! 425: ! 426: scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_TX_IP); ! 427: ! 428: c = scc_simple_tint(scc_dev_no(chan), FALSE); ! 429: ! 430: if (c == -1) { ! 431: /* no more data for this line */ ! 432: c = scc->softr[chan].wr1 & ~SCC_WR1_TX_IE; ! 433: scc_write_reg(regs, chan, SCC_WR1, c); ! 434: scc->softr[chan].wr1 = c; ! 435: ! 436: c = scc_simple_tint(scc_dev_no(chan), TRUE); ! 437: if (c != -1) { ! 438: /* funny race, scc_start has been called ! 439: already */ ! 440: scc_write_data(regs, chan, c); ! 441: } ! 442: } else { ! 443: ! 444: scc_write_data(regs, chan, c); ! 445: /* and leave it enabled */ ! 446: } ! 447: } ! 448: ! 449: else if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_B_RECV_DONE) { ! 450: int err = 0; ! 451: chan = (rr2 == SCC_RR2_A_RECV_DONE) ? ! 452: SCC_CHANNEL_A : SCC_CHANNEL_B; ! 453: ! 454: scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, ! 455: SCC_RESET_HIGHEST_IUS); ! 456: ! 457: #if MACH_KGDB ! 458: if (chan == KGDB_PORT) { ! 459: /* 11/10/95 MEB ! 460: * Drop into the debugger.. scc_getc() will ! 461: * pick up the character ! 462: */ ! 463: ! 464: call_kgdb_with_ctx(EXC_INTERRUPT, 0, ssp); ! 465: goto next_intr; ! 466: } ! 467: #endif ! 468: ! 469: scc_read_data(regs, chan, c); ! 470: ! 471: scc_input(scc_dev_no(chan), c, SCC_ERR_NONE); ! 472: } ! 473: ! 474: else if ((rr2 == SCC_RR2_A_EXT_STATUS) || ! 475: (rr2 == SCC_RR2_B_EXT_STATUS)) { ! 476: chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? ! 477: SCC_CHANNEL_A : SCC_CHANNEL_B; ! 478: ! 479: scc_read_reg(regs, chan, SCC_RR0, status); ! 480: if (status & SCC_RR0_TX_UNDERRUN) ! 481: scc_write_reg(regs, chan, SCC_RR0, ! 482: SCC_RESET_TXURUN_LATCH); ! 483: if (status & SCC_RR0_BREAK) ! 484: scc_input(scc_dev_no(chan), 0, SCC_ERR_BREAK); ! 485: ! 486: scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_EXT_IP); ! 487: scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 488: scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR); ! 489: ! 490: /* Update the modem lines */ ! 491: scc_update_modem(&scc_tty[chan]); ! 492: } ! 493: ! 494: else if ((rr2 == SCC_RR2_A_RECV_SPECIAL) || ! 495: (rr2 == SCC_RR2_B_RECV_SPECIAL)) { ! 496: chan = (rr2 == SCC_RR2_A_RECV_SPECIAL) ? ! 497: SCC_CHANNEL_A : SCC_CHANNEL_B; ! 498: ! 499: scc_read_reg(regs, chan, SCC_RR1, rr1); ! 500: #if SCC_DMA_TRANSFERS ! 501: if (scc->dma_initted & (chan<<1)) { ! 502: scc->dma_ops->scc_dma_reset_rx(chan); ! 503: scc->dma_ops->scc_dma_start_rx(chan); ! 504: } ! 505: #endif ! 506: if (rr1 & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) { ! 507: enum scc_error err; ! 508: scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR); ! 509: if (rr1 & SCC_RR1_FRAME_ERR) ! 510: err = SCC_ERR_BREAK; ! 511: else if (rr1 & SCC_RR1_PARITY_ERR) ! 512: err = SCC_ERR_OVERRUN; ! 513: else { ! 514: assert(rr1 & SCC_RR1_RX_OVERRUN); ! 515: err = SCC_ERR_OVERRUN; ! 516: } ! 517: #if SCC_DMA_TRANSFERS ! 518: if ((scc->dma_initted & (chan<<1)) == 0) ! 519: #endif ! 520: scc_input(scc_dev_no(chan), 0, err); ! 521: } ! 522: scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 523: } ! 524: ! 525: next_intr: ! 526: return; ! 527: } ! 528: ! 529: ! 530: /* ! 531: * Start output on a line ! 532: */ ! 533: ! 534: void ! 535: scc_start(tp) ! 536: struct tty *tp; ! 537: { ! 538: spl_t s; ! 539: int cc; ! 540: scc_regmap_t regs; ! 541: int chan = scc_chan(tp->t_dev), temp; ! 542: struct scc_softreg *sr = &scc_softc[0].softr[chan]; ! 543: scc_softc_t scc = &scc_softc[0]; ! 544: ! 545: s = spltty(); ! 546: ! 547: /* Start up the DMA channel if it was paused */ ! 548: if ((tp->t_state & TS_TTSTOP) == 0 && sr->dma_flags & SCC_FLAGS_DMA_PAUSED) { ! 549: /*printf("{DMA RESUME}");*/ ! 550: scc->dma_ops->scc_dma_continue_tx(chan); ! 551: splx(s); ! 552: return; ! 553: } ! 554: ! 555: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) ! 556: goto out; ! 557: ! 558: ! 559: #if SCC_DMA_TRANSFERS ! 560: if (scc_softc[0].dma_initted & (1<<chan)) { ! 561: /* Don't worry about low water marks... ! 562: * The DMA operation should be able to pull off most ! 563: * if not all of the TTY output queue ! 564: */ ! 565: ! 566: tt_write_wakeup(tp); ! 567: ! 568: if (tp->t_outq.c_cc <= 0) ! 569: goto out; ! 570: ! 571: tp->t_state |= TS_BUSY; ! 572: ! 573: scc_softc[0].dma_ops->scc_dma_start_tx(chan, tp); ! 574: } else ! 575: #endif ! 576: { ! 577: cc = tp->t_outq.c_cc; ! 578: if (cc <= TTLOWAT(tp)) { ! 579: tt_write_wakeup(tp); ! 580: } ! 581: if (cc <= 0) ! 582: goto out; ! 583: tp->t_state |= TS_BUSY; ! 584: ! 585: regs = scc_softc[0].regs; ! 586: sr = &scc_softc[0].softr[chan]; ! 587: ! 588: scc_read_reg(regs, chan, SCC_RR15, temp); ! 589: temp |= SCC_WR15_TX_UNDERRUN_IE; ! 590: scc_write_reg(regs, chan, SCC_WR15, temp); ! 591: ! 592: temp = sr->wr1 | SCC_WR1_TX_IE; ! 593: scc_write_reg(regs, chan, SCC_WR1, temp); ! 594: sr->wr1 = temp; ! 595: ! 596: /* but we need a first char out or no cookie */ ! 597: scc_read_reg(regs, chan, SCC_RR0, temp); ! 598: if (temp & SCC_RR0_TX_EMPTY) ! 599: { ! 600: register char c; ! 601: ! 602: c = getc(&tp->t_outq); ! 603: scc_write_data(regs, chan, c); ! 604: } ! 605: } ! 606: out: ! 607: splx(s); ! 608: } ! 609: ! 610: #define u_min(a,b) ((a) < (b) ? (a) : (b)) ! 611: #endif /* notdef_next */ ! 612: ! 613: /* ! 614: * Get a char from a specific SCC line ! 615: * [this is only used for console&screen purposes] ! 616: */ ! 617: ! 618: int ! 619: scc_getc(int unit, int line, boolean_t wait, boolean_t raw) ! 620: { ! 621: register scc_regmap_t regs; ! 622: unsigned char c, value; ! 623: int rcvalue, from_line; ! 624: spl_t s = spltty(); ! 625: ! 626: regs = scc_softc[0].regs; ! 627: ! 628: /* ! 629: * wait till something available ! 630: * ! 631: */ ! 632: again: ! 633: rcvalue = 0; ! 634: while (1) { ! 635: scc_read_reg_zero(regs, line, value); ! 636: ! 637: if (value & SCC_RR0_RX_AVAIL) ! 638: break; ! 639: ! 640: if (!wait) { ! 641: splx(s); ! 642: return -1; ! 643: } ! 644: } ! 645: ! 646: /* ! 647: * if nothing found return -1 ! 648: */ ! 649: ! 650: scc_read_reg(regs, line, SCC_RR1, value); ! 651: scc_read_data(regs, line, c); ! 652: ! 653: /* ! 654: * bad chars not ok ! 655: */ ! 656: if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) { ! 657: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_ERROR); ! 658: ! 659: if (wait) { ! 660: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 661: goto again; ! 662: } ! 663: } ! 664: ! 665: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 666: splx(s); ! 667: ! 668: return c; ! 669: } ! 670: ! 671: /* ! 672: * Put a char on a specific SCC line ! 673: */ ! 674: ! 675: int ! 676: scc_putc(int unit, int line, int c) ! 677: { ! 678: scc_regmap_t regs; ! 679: spl_t s = spltty(); ! 680: unsigned char value; ! 681: ! 682: regs = scc_softc[0].regs; ! 683: ! 684: do { ! 685: scc_read_reg(regs, line, SCC_RR0, value); ! 686: if (value & SCC_RR0_TX_EMPTY) ! 687: break; ! 688: scc_delay(100); ! 689: } while (1); ! 690: ! 691: scc_write_data(regs, line, c); ! 692: /* wait for it to swallow the char ? */ ! 693: ! 694: do { ! 695: scc_read_reg(regs, line, SCC_RR0, value); ! 696: if (value & SCC_RR0_TX_EMPTY) ! 697: break; ! 698: } while (1); ! 699: scc_write_reg(regs, line, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 700: splx(s); ! 701: ! 702: return 0; ! 703: } ! 704: ! 705: #ifdef notdef_next ! 706: int ! 707: scc_param(struct tty *tp) ! 708: { ! 709: scc_regmap_t regs; ! 710: unsigned char value; ! 711: unsigned short speed_value; ! 712: int bits, chan; ! 713: spl_t s; ! 714: struct scc_softreg *sr; ! 715: scc_softc_t scc; ! 716: ! 717: chan = scc_chan(tp->t_dev); ! 718: scc = &scc_softc[0]; ! 719: regs = scc->regs; ! 720: ! 721: sr = &scc->softr[chan]; ! 722: ! 723: /* Do a quick check to see if the hardware needs to change */ ! 724: if ((sr->flags & (TF_ODDP|TF_EVENP)) == (tp->t_flags & (TF_ODDP|TF_EVENP)) ! 725: && sr->speed == tp->t_ispeed) ! 726: return 0; ! 727: ! 728: sr->flags = tp->t_flags; ! 729: sr->speed = tp->t_ispeed; ! 730: ! 731: s = spltty(); ! 732: ! 733: if (tp->t_ispeed == 0) { ! 734: sr->wr5 &= ~SCC_WR5_DTR; ! 735: scc_write_reg(regs, chan, 5, sr->wr5); ! 736: splx(s); ! 737: ! 738: return 0; ! 739: } ! 740: ! 741: ! 742: #if SCC_DMA_TRANSFERS ! 743: if (scc->dma_initted & (1<<chan)) ! 744: scc->dma_ops->scc_dma_reset_rx(chan); ! 745: #endif ! 746: ! 747: value = SCC_WR4_1_STOP; ! 748: ! 749: /* ! 750: * For 115K the clocking divide changes to 64.. to 230K will ! 751: * start at the normal clock divide 16. ! 752: * ! 753: * However, both speeds will pull from a different clocking ! 754: * source ! 755: */ ! 756: ! 757: if (tp->t_ispeed == 115200) ! 758: value |= SCC_WR4_CLK_x32; ! 759: else ! 760: value |= SCC_WR4_CLK_x16 ; ! 761: ! 762: /* .. and parity */ ! 763: if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_EVENP) ! 764: value |= (SCC_WR4_EVEN_PARITY | SCC_WR4_PARITY_ENABLE); ! 765: else if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP) ! 766: value |= SCC_WR4_PARITY_ENABLE; ! 767: ! 768: /* set it now, remember it must be first after reset */ ! 769: sr->wr4 = value; ! 770: ! 771: /* Program Parity, and Stop bits */ ! 772: scc_write_reg(regs, chan, 4, sr->wr4); ! 773: ! 774: /* Setup for 8 bits */ ! 775: scc_write_reg(regs, chan, 3, SCC_WR3_RX_8_BITS); ! 776: ! 777: // Set DTR, RTS, and transmitter bits/character. ! 778: sr->wr5 = SCC_WR5_TX_8_BITS | SCC_WR5_RTS | SCC_WR5_DTR; ! 779: ! 780: scc_write_reg(regs, chan, 5, sr->wr5); ! 781: ! 782: scc_write_reg(regs, chan, 14, 0); /* Disable baud rate */ ! 783: ! 784: /* Setup baud rate 57.6Kbps, 115K, 230K should all yeild ! 785: * a converted baud rate of zero ! 786: */ ! 787: speed_value = convert_baud_rate(tp->t_ispeed); ! 788: ! 789: if (speed_value == 0xffff) ! 790: speed_value = 0; ! 791: ! 792: scc_set_timing_base(regs, chan, speed_value); ! 793: ! 794: if (tp->t_ispeed == 115200 || tp->t_ispeed == 230400) { ! 795: /* Special case here.. change the clock source*/ ! 796: scc_write_reg(regs, chan, 11, 0); ! 797: /* Baud rate generator is disabled.. */ ! 798: } else { ! 799: scc_write_reg(regs, chan, 11, SCC_WR11_RCLK_BAUDR|SCC_WR11_XTLK_BAUDR); ! 800: /* Enable the baud rate generator */ ! 801: scc_write_reg(regs, chan, 14, SCC_WR14_BAUDR_ENABLE); ! 802: } ! 803: ! 804: ! 805: scc_write_reg(regs, chan, 3, SCC_WR3_RX_8_BITS|SCC_WR3_RX_ENABLE); ! 806: ! 807: ! 808: sr->wr1 = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_EXT_IE; ! 809: scc_write_reg(regs, chan, 1, sr->wr1); ! 810: ! 811: scc_write_reg(regs, chan, 15, 0); ! 812: ! 813: /* Clear out any pending external or status interrupts */ ! 814: scc_write_reg(regs, chan, 0, SCC_RESET_EXT_IP); ! 815: scc_write_reg(regs, chan, 0, SCC_RESET_EXT_IP); ! 816: //scc_write_reg(regs, chan, 0, SCC_RESET_ERROR); ! 817: scc_write_reg(regs, chan, 0, SCC_IE_NEXT_CHAR); ! 818: ! 819: /* Enable SCC interrupts (how many interrupts are to this thing?!?) */ ! 820: scc_write_reg(regs, chan, 9, SCC_WR9_MASTER_IE|SCC_WR9_NV); ! 821: ! 822: scc_read_reg_zero(regs, 0, bits);/* Clear the status */ ! 823: ! 824: #if SCC_DMA_TRANSFERS ! 825: if (scc->dma_initted & (1<<chan)) { ! 826: scc->dma_ops->scc_dma_start_rx(chan); ! 827: scc->dma_ops->scc_dma_setup_8530(chan); ! 828: } else ! 829: #endif ! 830: { ! 831: sr->wr1 = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_EXT_IE; ! 832: scc_write_reg(regs, chan, 1, sr->wr1); ! 833: } ! 834: ! 835: sr->wr5 |= SCC_WR5_TX_ENABLE; ! 836: scc_write_reg(regs, chan, 5, sr->wr5); ! 837: ! 838: splx(s); ! 839: ! 840: return 0; ! 841: ! 842: } ! 843: ! 844: void ! 845: scc_update_modem(struct tty *tp) ! 846: { ! 847: scc_softc_t scc = &scc_softc[0]; ! 848: int chan = scc_chan(tp->t_dev); ! 849: scc_regmap_t regs = scc->regs; ! 850: unsigned char rr0, old_modem; ! 851: ! 852: old_modem = scc->modem[chan]; ! 853: scc->modem[chan] &= ~(TM_CTS|TM_CAR|TM_RNG|TM_DSR); ! 854: scc->modem[chan] |= TM_DSR|TM_CTS; ! 855: ! 856: scc_read_reg_zero(regs, chan, rr0); ! 857: ! 858: if (rr0 & SCC_RR0_DCD) { ! 859: scc->modem[chan] |= TM_CAR; ! 860: if ((old_modem & TM_CAR) == 0) { ! 861: /*printf("{DTR-ON %x/%x}", rr0, old_modem);*/ ! 862: /* ! 863: * The trick here is that ! 864: * the device_open does not hang ! 865: * waiting for DCD, but a message ! 866: * is sent to the process ! 867: */ ! 868: ! 869: if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) ! 870: && tp->t_flags & TF_OUT_OF_BAND) { ! 871: /*printf("{NOTIFY}");*/ ! 872: tp->t_outofband = TOOB_CARRIER; ! 873: tp->t_outofbandarg = TRUE; ! 874: tty_queue_completion(&tp->t_delayed_read); ! 875: } ! 876: } ! 877: } else if (old_modem & TM_CAR) { ! 878: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { ! 879: /*printf("{DTR-OFF %x/%x}", rr0, old_modem);*/ ! 880: ! 881: if (tp->t_flags & TF_OUT_OF_BAND) { ! 882: tp->t_outofband = TOOB_CARRIER; ! 883: tp->t_outofbandarg = FALSE; ! 884: tty_queue_completion(&tp->t_delayed_read); ! 885: } else ! 886: ttymodem(tp, FALSE); ! 887: } ! 888: } ! 889: } ! 890: ! 891: /* ! 892: * Modem control functions ! 893: */ ! 894: int ! 895: scc_mctl(struct tty* tty, int bits, int how) ! 896: { ! 897: register dev_t dev = tty->t_dev; ! 898: int sccline; ! 899: register int tcr, msr, brk, n_tcr, n_brk; ! 900: int b; ! 901: scc_softc_t scc; ! 902: int wr5; ! 903: ! 904: sccline = scc_chan(dev); ! 905: ! 906: if (bits == TM_HUP) { /* close line (internal) */ ! 907: bits = TM_DTR | TM_RTS; ! 908: how = DMBIC; ! 909: } ! 910: ! 911: scc = &scc_softc[0]; ! 912: wr5 = scc->softr[sccline].wr5; ! 913: ! 914: if (how == DMGET) { ! 915: scc_update_modem(tty); ! 916: return scc->modem[sccline]; ! 917: } ! 918: ! 919: switch (how) { ! 920: case DMSET: ! 921: b = bits; break; ! 922: case DMBIS: ! 923: b = scc->modem[sccline] | bits; break; ! 924: case DMBIC: ! 925: b = scc->modem[sccline] & ~bits; break; ! 926: default: ! 927: return 0; ! 928: } ! 929: ! 930: if (scc->modem[sccline] == b) ! 931: return b; ! 932: ! 933: scc->modem[sccline] = b; ! 934: ! 935: if (bits & TM_BRK) { ! 936: ttydrain(tty); ! 937: scc_waitforempty(tty); ! 938: } ! 939: ! 940: wr5 &= ~(SCC_WR5_SEND_BREAK|SCC_WR5_DTR); ! 941: ! 942: if (b & TM_BRK) ! 943: wr5 |= SCC_WR5_SEND_BREAK; ! 944: ! 945: if (b & TM_DTR) ! 946: wr5 |= SCC_WR5_DTR; ! 947: ! 948: wr5 |= SCC_WR5_RTS; ! 949: ! 950: scc_write_reg(scc->regs, sccline, 5, wr5); ! 951: scc->softr[sccline].wr5 = wr5; ! 952: ! 953: return scc->modem[sccline]; ! 954: } ! 955: ! 956: /* ! 957: * Periodically look at the CD signals: ! 958: * they do generate interrupts but we ! 959: * must fake them on channel A. We might ! 960: * also fake them on channel B. ! 961: */ ! 962: ! 963: int ! 964: scc_cd_scan(void) ! 965: { ! 966: spl_t s = spltty(); ! 967: scc_softc_t scc; ! 968: int j; ! 969: ! 970: scc = &scc_softc[0]; ! 971: for (j = 0; j < NSCC_LINE; j++) { ! 972: if (scc_tty[j].t_state & (TS_ISOPEN|TS_WOPEN)) ! 973: scc_update_modem(&scc_tty[j]); ! 974: } ! 975: splx(s); ! 976: ! 977: timeout((timeout_fcn_t)scc_cd_scan, (void *)0, hz/4); ! 978: ! 979: return 0; ! 980: } ! 981: ! 982: #if MACH_KGDB ! 983: void no_spl_scc_putc(int chan, char c) ! 984: { ! 985: register scc_regmap_t regs; ! 986: register unsigned char value; ! 987: ! 988: if (!serial_initted) ! 989: initialize_serial(); ! 990: ! 991: regs = scc_softc[0].regs; ! 992: ! 993: do { ! 994: scc_read_reg(regs, chan, SCC_RR0, value); ! 995: if (value & SCC_RR0_TX_EMPTY) ! 996: break; ! 997: scc_delay(100); ! 998: } while (1); ! 999: ! 1000: scc_write_data(regs, chan, c); ! 1001: /* wait for it to swallow the char ? */ ! 1002: ! 1003: do { ! 1004: scc_read_reg(regs, chan, SCC_RR0, value); ! 1005: if (value & SCC_RR0_TX_EMPTY) ! 1006: break; ! 1007: } while (1); ! 1008: scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 1009: ! 1010: if (c == '\n') ! 1011: no_spl_scc_putc(chan, '\r'); ! 1012: ! 1013: } ! 1014: ! 1015: #define SCC_KGDB_BUFFER 15 ! 1016: ! 1017: int no_spl_scc_getc(int chan, boolean_t timeout) ! 1018: { ! 1019: register scc_regmap_t regs; ! 1020: unsigned char c, value, i; ! 1021: int rcvalue, from_line; ! 1022: int timeremaining = timeout ? 10000000 : 0; /* XXX */ ! 1023: static unsigned char buffer[2][SCC_KGDB_BUFFER]; ! 1024: static int bufcnt[2], bufidx[2]; ! 1025: ! 1026: /* This should be rewritten to produce a constant timeout ! 1027: regardless of the processor speed. */ ! 1028: ! 1029: if (!serial_initted) ! 1030: initialize_serial(); ! 1031: ! 1032: regs = scc_softc[0].regs; ! 1033: ! 1034: get_char: ! 1035: if (bufcnt[chan]) { ! 1036: bufcnt[chan] --; ! 1037: return ((unsigned int) buffer[chan][bufidx[chan]++]); ! 1038: } ! 1039: ! 1040: /* ! 1041: * wait till something available ! 1042: * ! 1043: */ ! 1044: bufidx[chan] = 0; ! 1045: ! 1046: for (i = 0; i < SCC_KGDB_BUFFER; i++) { ! 1047: rcvalue = 0; ! 1048: ! 1049: while (1) { ! 1050: scc_read_reg_zero(regs, chan, value); ! 1051: if (value & SCC_RR0_RX_AVAIL) ! 1052: break; ! 1053: if (timeremaining && !--timeremaining) { ! 1054: if (i) ! 1055: goto get_char; ! 1056: else ! 1057: return KGDB_GETC_TIMEOUT; ! 1058: } ! 1059: } ! 1060: ! 1061: scc_read_reg(regs, chan, SCC_RR1, value); ! 1062: scc_read_data(regs, chan, c); ! 1063: buffer[chan][bufcnt[chan]] = c; ! 1064: bufcnt[chan]++; ! 1065: ! 1066: /* ! 1067: * bad chars not ok ! 1068: */ ! 1069: ! 1070: ! 1071: if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) { ! 1072: scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR); ! 1073: ! 1074: scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 1075: bufcnt[chan] = 0; ! 1076: return KGDB_GETC_BAD_CHAR; ! 1077: } ! 1078: ! 1079: ! 1080: scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_HIGHEST_IUS); ! 1081: ! 1082: for (timeremaining = 0; timeremaining < 1000; timeremaining++) { ! 1083: scc_read_reg_zero(regs, chan, value); ! 1084: ! 1085: if (value & SCC_RR0_RX_AVAIL) ! 1086: continue; ! 1087: } ! 1088: ! 1089: if (timeout == FALSE) ! 1090: break; ! 1091: ! 1092: } ! 1093: ! 1094: ! 1095: goto get_char; ! 1096: } ! 1097: #endif /* MACH_KGDB */ ! 1098: ! 1099: /* ! 1100: * Open routine ! 1101: */ ! 1102: ! 1103: io_return_t ! 1104: scc_open( ! 1105: dev_t dev, ! 1106: dev_mode_t flag, ! 1107: io_req_t ior) ! 1108: { ! 1109: register struct tty *tp; ! 1110: spl_t s; ! 1111: scc_softc_t scc; ! 1112: int chan; ! 1113: int forcedcarrier; ! 1114: io_return_t result; ! 1115: ! 1116: if (dev >= NSCC * NSCC_LINE) ! 1117: return D_NO_SUCH_DEVICE; ! 1118: ! 1119: chan = scc_chan(dev); ! 1120: tp = &scc_tty[chan]; ! 1121: scc = &scc_softc[0]; ! 1122: ! 1123: /* But was it there at probe time */ ! 1124: if (tp->t_addr == 0) ! 1125: return D_NO_SUCH_DEVICE; ! 1126: ! 1127: s = spltty(); ! 1128: simple_lock(&tp->t_lock); ! 1129: ! 1130: if (!(tp->t_state & (TS_ISOPEN|TS_WOPEN))) { ! 1131: tp->t_dev = dev; ! 1132: tp->t_start = scc_start; ! 1133: tp->t_stop = scc_stop; ! 1134: tp->t_mctl = scc_mctl; ! 1135: tp->t_getstat = scc_get_status; ! 1136: tp->t_setstat = scc_set_status; ! 1137: scc->modem[chan] = 0; /* No assumptions on things.. */ ! 1138: if (tp->t_ispeed == 0) { ! 1139: tp->t_ispeed = DEFAULT_SPEED; ! 1140: tp->t_ospeed = DEFAULT_SPEED; ! 1141: tp->t_flags = DEFAULT_FLAGS; ! 1142: } ! 1143: ! 1144: scc->softr[chan].speed = -1; /* Force reset */ ! 1145: scc->softr[chan].wr5 |= SCC_WR5_DTR; ! 1146: scc_param(tp); ! 1147: } ! 1148: ! 1149: scc_update_modem(tp); ! 1150: ! 1151: tp->t_state |= TS_CARR_ON; /* Always.. */ ! 1152: ! 1153: simple_unlock(&tp->t_lock); ! 1154: splx(s); ! 1155: result = char_open(dev, tp, flag, ior); ! 1156: ! 1157: if (tp->t_flags & CRTSCTS) { ! 1158: simple_lock(&tp->t_lock); ! 1159: if (!(scc->modem[chan] & TM_CTS)) ! 1160: tp->t_state |= TS_TTSTOP; ! 1161: simple_unlock(&tp->t_lock); ! 1162: } ! 1163: ! 1164: return result; ! 1165: } ! 1166: ! 1167: /* ! 1168: * Close routine ! 1169: */ ! 1170: void ! 1171: scc_close( ! 1172: dev_t dev) ! 1173: { ! 1174: register struct tty *tp; ! 1175: spl_t s; ! 1176: scc_softc_t scc = &scc_softc[0]; ! 1177: int chan = scc_chan(dev); ! 1178: ! 1179: tp = &scc_tty[dev]; ! 1180: ! 1181: s = spltty(); ! 1182: simple_lock(&tp->t_lock); ! 1183: ! 1184: ttstart(tp); ! 1185: ttydrain(tp); ! 1186: scc_waitforempty(tp); ! 1187: ! 1188: /* Disable Receiver.. */ ! 1189: scc_write_reg(scc->regs, chan, SCC_WR3, 0); ! 1190: #if SCC_DMA_TRANSFERS ! 1191: if (scc->dma_initted & (chan <<1)) ! 1192: scc->dma_ops->scc_dma_reset_rx(chan); ! 1193: #endif ! 1194: ! 1195: ttyclose(tp); ! 1196: if (tp->t_state & TS_HUPCLS) { ! 1197: scc->softr[chan].wr5 &= ~(SCC_WR5_DTR); ! 1198: scc_write_reg(scc->regs, chan, SCC_WR5, scc->softr[chan].wr5); ! 1199: scc->modem[chan] &= ~(TM_DTR|TM_RTS); ! 1200: } ! 1201: ! 1202: ! 1203: tp->t_state &= ~TS_ISOPEN; ! 1204: ! 1205: simple_unlock(&tp->t_lock); ! 1206: splx(s); ! 1207: } ! 1208: ! 1209: io_return_t ! 1210: scc_read( ! 1211: dev_t dev, ! 1212: io_req_t ior) ! 1213: { ! 1214: return char_read(&scc_tty[dev], ior); ! 1215: } ! 1216: ! 1217: io_return_t ! 1218: scc_write( ! 1219: dev_t dev, ! 1220: io_req_t ior) ! 1221: { ! 1222: return char_write(&scc_tty[dev], ior); ! 1223: } ! 1224: ! 1225: /* ! 1226: * Stop output on a line. ! 1227: */ ! 1228: void ! 1229: scc_stop( ! 1230: struct tty *tp, ! 1231: int flags) ! 1232: { ! 1233: int chan = scc_chan(tp->t_dev); ! 1234: scc_softc_t scc = &scc_softc[0]; ! 1235: struct scc_softreg *sr = &scc->softr[chan]; ! 1236: ! 1237: spl_t s = spltty(); ! 1238: ! 1239: if (tp->t_state & TS_BUSY) { ! 1240: if (sr->dma_flags & SCC_FLAGS_DMA_TX_BUSY) { ! 1241: /*printf("{DMA OFF}");*/ ! 1242: scc->dma_ops->scc_dma_pause_tx(chan); ! 1243: } else if ((tp->t_state&TS_TTSTOP)==0) ! 1244: tp->t_state |= TS_FLUSH; ! 1245: } ! 1246: ! 1247: splx(s); ! 1248: /*printf("{STOP %x}", flags);*/ ! 1249: } ! 1250: ! 1251: /* ! 1252: * Abnormal close ! 1253: */ ! 1254: boolean_t ! 1255: scc_portdeath( ! 1256: dev_t dev, ! 1257: ipc_port_t port) ! 1258: { ! 1259: return (tty_portdeath(&scc_tty[dev], port)); ! 1260: } ! 1261: ! 1262: /* ! 1263: * Get/Set status rotuines ! 1264: */ ! 1265: io_return_t ! 1266: scc_get_status( ! 1267: dev_t dev, ! 1268: dev_flavor_t flavor, ! 1269: dev_status_t data, ! 1270: mach_msg_type_number_t *status_count) ! 1271: { ! 1272: register struct tty *tp; ! 1273: ! 1274: tp = &scc_tty[dev]; ! 1275: ! 1276: switch (flavor) { ! 1277: case TTY_MODEM: ! 1278: scc_update_modem(tp); ! 1279: *data = scc_softc[0].modem[scc_chan(dev)]; ! 1280: *status_count = 1; ! 1281: return (D_SUCCESS); ! 1282: default: ! 1283: return (tty_get_status(tp, flavor, data, status_count)); ! 1284: } ! 1285: } ! 1286: ! 1287: io_return_t ! 1288: scc_set_status( ! 1289: dev_t dev, ! 1290: dev_flavor_t flavor, ! 1291: dev_status_t data, ! 1292: mach_msg_type_number_t status_count) ! 1293: { ! 1294: register struct tty *tp; ! 1295: spl_t s; ! 1296: io_return_t result = D_SUCCESS; ! 1297: scc_softc_t scc = &scc_softc[0]; ! 1298: int chan = scc_chan(dev); ! 1299: ! 1300: tp = &scc_tty[dev]; ! 1301: ! 1302: s = spltty(); ! 1303: simple_lock(&tp->t_lock); ! 1304: ! 1305: switch (flavor) { ! 1306: case TTY_MODEM: ! 1307: (void) scc_mctl(tp, *data, DMSET); ! 1308: break; ! 1309: ! 1310: case TTY_NMODEM: ! 1311: break; ! 1312: ! 1313: case TTY_SET_BREAK: ! 1314: (void) scc_mctl(tp, TM_BRK, DMBIS); ! 1315: break; ! 1316: ! 1317: case TTY_CLEAR_BREAK: ! 1318: (void) scc_mctl(tp, TM_BRK, DMBIC); ! 1319: break; ! 1320: ! 1321: default: ! 1322: simple_unlock(&tp->t_lock); ! 1323: splx(s); ! 1324: result = tty_set_status(tp, flavor, data, status_count); ! 1325: s = spltty(); ! 1326: simple_lock(&tp->t_lock); ! 1327: if (result == D_SUCCESS && ! 1328: (flavor== TTY_STATUS_NEW || flavor == TTY_STATUS_COMPAT)) { ! 1329: result = scc_param(tp); ! 1330: ! 1331: if (tp->t_flags & CRTSCTS) { ! 1332: if (scc->modem[chan] & TM_CTS) { ! 1333: tp->t_state &= ~TS_TTSTOP; ! 1334: ttstart(tp); ! 1335: } else ! 1336: tp->t_state |= TS_TTSTOP; ! 1337: } ! 1338: } ! 1339: break; ! 1340: } ! 1341: ! 1342: simple_unlock(&tp->t_lock); ! 1343: splx(s); ! 1344: ! 1345: return result; ! 1346: } ! 1347: ! 1348: void ! 1349: scc_waitforempty(struct tty *tp) ! 1350: { ! 1351: int chan = scc_chan(tp->t_dev); ! 1352: scc_softc_t scc = &scc_softc[0]; ! 1353: int rr0; ! 1354: ! 1355: while (1) { ! 1356: scc_read_reg(scc->regs, chan, SCC_RR0, rr0); ! 1357: if (rr0 & SCC_RR0_TX_EMPTY) ! 1358: break; ! 1359: assert_wait(0, TRUE); ! 1360: thread_set_timeout(1); ! 1361: simple_unlock(&tp->t_lock); ! 1362: thread_block((void (*)(void)) 0); ! 1363: reset_timeout_check(¤t_thread()->timer); ! 1364: simple_lock(&tp->t_lock); ! 1365: } ! 1366: } ! 1367: ! 1368: /* ! 1369: * Send along a character on a tty. If we were waiting for ! 1370: * this char to complete the open procedure do so; check ! 1371: * for errors; if all is well proceed to ttyinput(). ! 1372: */ ! 1373: ! 1374: void ! 1375: scc_input(dev_t dev, int c, enum scc_error err) ! 1376: { ! 1377: register struct tty *tp; ! 1378: ! 1379: tp = &scc_tty[dev]; ! 1380: ! 1381: if ((tp->t_state & TS_ISOPEN) == 0) { ! 1382: if (tp->t_state & TS_INIT) ! 1383: tt_open_wakeup(tp); ! 1384: return; ! 1385: } ! 1386: switch (err) { ! 1387: case SCC_ERR_NONE: ! 1388: ttyinput(c, tp); ! 1389: break; ! 1390: case SCC_ERR_OVERRUN: ! 1391: /*log(LOG_WARNING, "sl%d: silo overflow\n", dev);*/ ! 1392: /* Currently the Mach interface doesn't define an out-of-band ! 1393: event that we could use to signal this error to the user ! 1394: task that has this device open. */ ! 1395: break; ! 1396: case SCC_ERR_PARITY: ! 1397: ttyinputbadparity(c, tp); ! 1398: break; ! 1399: case SCC_ERR_BREAK: ! 1400: ttybreak(c, tp); ! 1401: break; ! 1402: } ! 1403: } ! 1404: ! 1405: /* ! 1406: * Transmission of a character is complete. ! 1407: * Return the next character or -1 if none. ! 1408: */ ! 1409: int ! 1410: scc_simple_tint(dev_t dev, boolean_t all_sent) ! 1411: { ! 1412: register struct tty *tp; ! 1413: ! 1414: tp = &scc_tty[dev]; ! 1415: if ((tp->t_addr == 0) || /* not probed --> stray */ ! 1416: (tp->t_state & TS_TTSTOP)) ! 1417: return -1; ! 1418: ! 1419: if (all_sent) { ! 1420: tp->t_state &= ~TS_BUSY; ! 1421: if (tp->t_state & TS_FLUSH) ! 1422: tp->t_state &= ~TS_FLUSH; ! 1423: ! 1424: scc_start(tp); ! 1425: } ! 1426: ! 1427: if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0) ! 1428: return -1; ! 1429: ! 1430: return getc(&tp->t_outq); ! 1431: } ! 1432: #endif /* notdef_next */ ! 1433: ! 1434: void ! 1435: powermac_scc_set_datum(scc_regmap_t regs, unsigned int offset, unsigned char value) ! 1436: { ! 1437: volatile unsigned char *address = (unsigned char *) regs + offset; ! 1438: ! 1439: *address = value; ! 1440: eieio(); ! 1441: } ! 1442: ! 1443: unsigned char ! 1444: powermac_scc_get_datum(scc_regmap_t regs, unsigned int offset) ! 1445: { ! 1446: volatile unsigned char *address = (unsigned char *) regs + offset; ! 1447: unsigned char value; ! 1448: ! 1449: value = *address; eieio(); ! 1450: return value; ! 1451: } ! 1452: ! 1453: /* modem port is 1, printer port is 0 */ ! 1454: #define LINE 1 ! 1455: ! 1456: #if got_console_now ! 1457: int ! 1458: kmtrygetc() ! 1459: { ! 1460: return scc_getc(0 /* ignored */, LINE, 0 /*no_wait*/, 0); ! 1461: } ! 1462: ! 1463: int ! 1464: cngetc() ! 1465: { ! 1466: return scc_getc(0 /* ignored */, LINE, 1 /*wait*/, 0); ! 1467: } ! 1468: ! 1469: int ! 1470: cnputc(char c) ! 1471: { ! 1472: int a; ! 1473: ! 1474: a= scc_putc(0 /* ignored */, LINE, c); ! 1475: if (c == '\n') ! 1476: a = cnputc('\r'); ! 1477: return a; ! 1478: } ! 1479: #endif /* got_console_now */ ! 1480: #endif /* NSCC > 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.