|
|
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.