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