Annotation of sys/arch/sh/dev/scif.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: scif.c,v 1.4 2006/11/20 17:53:16 drahn Exp $ */
2: /* $NetBSD: scif.c,v 1.47 2006/07/23 22:06:06 ad Exp $ */
3:
4: /*-
5: * Copyright (C) 1999 T.Horiuchi and SAITOH Masanobu. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
29:
30: /*-
31: * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
32: * All rights reserved.
33: *
34: * This code is derived from software contributed to The NetBSD Foundation
35: * by Charles M. Hannum.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
45: * 3. All advertising materials mentioning features or use of this software
46: * must display the following acknowledgement:
47: * This product includes software developed by the NetBSD
48: * Foundation, Inc. and its contributors.
49: * 4. Neither the name of The NetBSD Foundation nor the names of its
50: * contributors may be used to endorse or promote products derived
51: * from this software without specific prior written permission.
52: *
53: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
54: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
57: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63: * POSSIBILITY OF SUCH DAMAGE.
64: */
65:
66: /*
67: * Copyright (c) 1991 The Regents of the University of California.
68: * All rights reserved.
69: *
70: * Redistribution and use in source and binary forms, with or without
71: * modification, are permitted provided that the following conditions
72: * are met:
73: * 1. Redistributions of source code must retain the above copyright
74: * notice, this list of conditions and the following disclaimer.
75: * 2. Redistributions in binary form must reproduce the above copyright
76: * notice, this list of conditions and the following disclaimer in the
77: * documentation and/or other materials provided with the distribution.
78: * 3. Neither the name of the University nor the names of its contributors
79: * may be used to endorse or promote products derived from this software
80: * without specific prior written permission.
81: *
82: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
83: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
86: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
87: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
88: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
89: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
90: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
91: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
92: * SUCH DAMAGE.
93: *
94: * @(#)com.c 7.5 (Berkeley) 5/16/91
95: */
96:
97: /*
98: * SH internal serial driver
99: *
100: * This code is derived from both z8530tty.c and com.c
101: */
102:
103: #include <sys/param.h>
104: #include <sys/systm.h>
105: #include <sys/tty.h>
106: #include <sys/proc.h>
107: #include <sys/conf.h>
108: #include <sys/file.h>
109: #include <sys/syslog.h>
110: #include <sys/kernel.h>
111: #include <sys/device.h>
112: #include <sys/malloc.h>
113: #include <sys/timeout.h>
114:
115: #include <dev/cons.h>
116:
117: #include <sh/clock.h>
118: #include <sh/trap.h>
119: #include <machine/intr.h>
120: #include <machine/conf.h>
121:
122: #include <sh/dev/scifreg.h>
123:
124: #ifdef DDB
125: #include <ddb/db_var.h>
126: #endif
127:
128: void scifstart(struct tty *);
129: int scifparam(struct tty *, struct termios *);
130:
131: void scifcnprobe(struct consdev *);
132: void scifcninit(struct consdev *);
133: void scifcnputc(dev_t, int);
134: int scifcngetc(dev_t);
135: void scifcnpoolc(dev_t, int);
136: void scif_intr_init(void);
137: int scifintr(void *);
138:
139: struct scif_softc {
140: struct device sc_dev; /* boilerplate */
141: struct tty *sc_tty;
142: void *sc_si;
143:
144: struct timeout sc_diag_tmo;
145:
146: #if 0
147: bus_space_tag_t sc_iot; /* ISA i/o space identifier */
148: bus_space_handle_t sc_ioh; /* ISA io handle */
149:
150: int sc_drq;
151:
152: int sc_frequency;
153: #endif
154:
155: u_int sc_overflows,
156: sc_floods,
157: sc_errors; /* number of retries so far */
158: u_char sc_status[7]; /* copy of registers */
159:
160: int sc_hwflags;
161: int sc_swflags;
162: u_int sc_fifolen;
163:
164: u_int sc_r_hiwat,
165: sc_r_lowat;
166: u_char *volatile sc_rbget,
167: *volatile sc_rbput;
168: volatile u_int sc_rbavail;
169: u_char *sc_rbuf,
170: *sc_ebuf;
171:
172: u_char *sc_tba; /* transmit buffer address */
173: u_int sc_tbc, /* transmit byte count */
174: sc_heldtbc;
175:
176: volatile u_char sc_rx_flags,
177: #define RX_TTY_BLOCKED 0x01
178: #define RX_TTY_OVERFLOWED 0x02
179: #define RX_IBUF_BLOCKED 0x04
180: #define RX_IBUF_OVERFLOWED 0x08
181: #define RX_ANY_BLOCK 0x0f
182: sc_tx_busy, /* working on an output chunk */
183: sc_tx_done, /* done with one output chunk */
184: sc_tx_stopped, /* H/W level stop (lost CTS) */
185: sc_st_check, /* got a status interrupt */
186: sc_rx_ready;
187:
188: volatile u_char sc_heldchange;
189: };
190:
191: /* controller driver configuration */
192: int scif_match(struct device *, void *, void *);
193: void scif_attach(struct device *, struct device *, void *);
194:
195: void scif_break(struct scif_softc *, int);
196: void scif_iflush(struct scif_softc *);
197:
198: void scifsoft(void *);
199: void scif_rxsoft(struct scif_softc *, struct tty *);
200: void scif_txsoft(struct scif_softc *, struct tty *);
201: void scif_stsoft(struct scif_softc *, struct tty *);
202: void scif_schedrx(struct scif_softc *);
203: void scifdiag(void *);
204:
205:
206: #define SCIFUNIT_MASK 0x7ffff
207: #define SCIFDIALOUT_MASK 0x80000
208:
209: #define SCIFUNIT(x) (minor(x) & SCIFUNIT_MASK)
210: #define SCIFDIALOUT(x) (minor(x) & SCIFDIALOUT_MASK)
211:
212: /* Hardware flag masks */
213: #define SCIF_HW_NOIEN 0x01
214: #define SCIF_HW_FIFO 0x02
215: #define SCIF_HW_FLOW 0x08
216: #define SCIF_HW_DEV_OK 0x20
217: #define SCIF_HW_CONSOLE 0x40
218:
219: /* Buffer size for character buffer */
220: #define SCIF_RING_SIZE 2048
221:
222: /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
223: u_int scif_rbuf_hiwat = (SCIF_RING_SIZE * 1) / 4;
224: u_int scif_rbuf_lowat = (SCIF_RING_SIZE * 3) / 4;
225:
226: #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
227: int scifconscflag = CONMODE;
228: int scifisconsole = 0;
229:
230: #ifdef SCIFCN_SPEED
231: unsigned int scifcn_speed = SCIFCN_SPEED;
232: #else
233: unsigned int scifcn_speed = 9600;
234: #endif
235:
236: #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
237:
238: u_int scif_rbuf_size = SCIF_RING_SIZE;
239:
240: struct cfattach scif_ca = {
241: sizeof(struct scif_softc), scif_match, scif_attach
242: };
243:
244: struct cfdriver scif_cd = {
245: 0, "scif", DV_DULL
246: };
247:
248: static int scif_attached;
249:
250: void InitializeScif(unsigned int);
251:
252: /*
253: * following functions are debugging prupose only
254: */
255: #define CR 0x0D
256: #define USART_ON (unsigned int)~0x08
257:
258: void scif_putc(unsigned char);
259: unsigned char scif_getc(void);
260: int ScifErrCheck(void);
261:
262:
263: /* XXX: uwe
264: * Prepare for bus_spacification. The difference in access widths is
265: * still handled by the magic definitions in scifreg.h
266: */
267: #define scif_smr_read() SHREG_SCSMR2
268: #define scif_smr_write(v) (SHREG_SCSMR2 = (v))
269:
270: #define scif_brr_read() SHREG_SCBRR2
271: #define scif_brr_write(v) (SHREG_SCBRR2 = (v))
272:
273: #define scif_scr_read() SHREG_SCSCR2
274: #define scif_scr_write(v) (SHREG_SCSCR2 = (v))
275:
276: #define scif_ftdr_write(v) (SHREG_SCFTDR2 = (v))
277:
278: #define scif_ssr_read() SHREG_SCSSR2
279: #define scif_ssr_write(v) (SHREG_SCSSR2 = (v))
280:
281: #define scif_frdr_read() SHREG_SCFRDR2
282:
283: #define scif_fcr_read() SHREG_SCFCR2
284: #define scif_fcr_write(v) (SHREG_SCFCR2 = (v))
285:
286: #define scif_fdr_read() SHREG_SCFDR2
287:
288: #ifdef SH4 /* additional registers in sh4 */
289:
290: #define scif_sptr_read() SHREG_SCSPTR2
291: #define scif_sptr_write(v) (SHREG_SCSPTR2 = (v))
292:
293: #define scif_lsr_read() SHREG_SCLSR2
294: #define scif_lsr_write(v) (SHREG_SCLSR2 = (v))
295:
296: #endif /* SH4 */
297:
298:
299: /*
300: * InitializeScif
301: * : unsigned int bps;
302: * : SCIF(Serial Communication Interface)
303: */
304:
305: void
306: InitializeScif(unsigned int bps)
307: {
308: /* Initialize SCR */
309: scif_scr_write(0x00);
310:
311: #if 0
312: scif_fcr_write(SCFCR2_TFRST | SCFCR2_RFRST | SCFCR2_MCE);
313: #else
314: scif_fcr_write(SCFCR2_TFRST | SCFCR2_RFRST);
315: #endif
316: /* Serial Mode Register */
317: scif_smr_write(0x00); /* 8bit,NonParity,Even,1Stop */
318:
319: /* Bit Rate Register */
320: scif_brr_write(divrnd(sh_clock_get_pclock(), 32 * bps) - 1);
321:
322: /*
323: * wait 2m Sec, because Send/Recv must begin 1 bit period after
324: * BRR is set.
325: */
326: delay(2000);
327:
328: #if 0
329: scif_fcr_write(FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1 | SCFCR2_MCE);
330: #else
331: scif_fcr_write(FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1);
332: #endif
333:
334: /* Send permission, Receive permission ON */
335: scif_scr_write(SCSCR2_TE | SCSCR2_RE);
336:
337: /* Serial Status Register */
338: scif_ssr_write(scif_ssr_read() & SCSSR2_TDFE); /* Clear Status */
339: }
340:
341:
342: /*
343: * scif_putc
344: * : unsigned char c;
345: */
346:
347: void
348: scif_putc(unsigned char c)
349: {
350: /* wait for ready */
351: while ((scif_fdr_read() & SCFDR2_TXCNT) == SCFDR2_TXF_FULL)
352: continue;
353:
354: /* write send data to send register */
355: scif_ftdr_write(c);
356:
357: /* clear ready flag */
358: scif_ssr_write(scif_ssr_read() & ~(SCSSR2_TDFE | SCSSR2_TEND));
359: }
360:
361: /*
362: * : ScifErrCheck
363: * 0x80 = error
364: * 0x08 = frame error
365: * 0x04 = parity error
366: */
367: int
368: ScifErrCheck(void)
369: {
370: return (scif_ssr_read() & (SCSSR2_ER | SCSSR2_FER | SCSSR2_PER));
371: }
372:
373: /*
374: * scif_getc
375: */
376: unsigned char
377: scif_getc(void)
378: {
379: unsigned char c, err_c;
380: #ifdef SH4
381: unsigned short err_c2 = 0; /* XXXGCC: -Wuninitialized */
382: #endif
383:
384: for (;;) {
385: /* wait for ready */
386: while ((scif_fdr_read() & SCFDR2_RECVCNT) == 0)
387: continue;
388:
389: c = scif_frdr_read();
390: err_c = scif_ssr_read();
391: scif_ssr_write(scif_ssr_read()
392: & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_RDF | SCSSR2_DR));
393: #ifdef SH4
394: if (CPU_IS_SH4) {
395: err_c2 = scif_lsr_read();
396: scif_lsr_write(scif_lsr_read() & ~SCLSR2_ORER);
397: }
398: #endif
399: if ((err_c & (SCSSR2_ER | SCSSR2_BRK | SCSSR2_FER
400: | SCSSR2_PER)) == 0) {
401: #ifdef SH4
402: if (CPU_IS_SH4 && ((err_c2 & SCLSR2_ORER) == 0))
403: #endif
404: return(c);
405: }
406: }
407:
408: }
409:
410: int
411: scif_match(struct device *parent, void *vcf, void *aux)
412: {
413: if (scif_attached != 0)
414: return 0;
415:
416: return 1;
417: }
418:
419: void
420: scif_attach(struct device *parent, struct device *self, void *aux)
421: {
422: struct scif_softc *sc = (struct scif_softc *)self;
423: struct tty *tp;
424:
425: scif_attached = 1;
426:
427: sc->sc_hwflags = 0; /* XXX */
428: sc->sc_swflags = 0; /* XXX */
429: sc->sc_fifolen = 16;
430:
431: if (scifisconsole) {
432: /* InitializeScif(scifcn_speed); */
433: SET(sc->sc_hwflags, SCIF_HW_CONSOLE);
434: SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
435: printf("\n%s: console\n", sc->sc_dev.dv_xname);
436: } else {
437: InitializeScif(9600);
438: printf("\n");
439: }
440:
441: timeout_set(&sc->sc_diag_tmo, scifdiag, sc);
442: #ifdef SH4
443: intc_intr_establish(SH4_INTEVT_SCIF_ERI, IST_LEVEL, IPL_TTY,
444: scifintr, sc, self->dv_xname);
445: intc_intr_establish(SH4_INTEVT_SCIF_RXI, IST_LEVEL, IPL_TTY,
446: scifintr, sc, self->dv_xname);
447: intc_intr_establish(SH4_INTEVT_SCIF_BRI, IST_LEVEL, IPL_TTY,
448: scifintr, sc, self->dv_xname);
449: intc_intr_establish(SH4_INTEVT_SCIF_TXI, IST_LEVEL, IPL_TTY,
450: scifintr, sc, self->dv_xname);
451: #else
452: intc_intr_establish(SH7709_INTEVT2_SCIF_ERI, IST_LEVEL, IPL_TTY,
453: scifintr, sc, self->dv_xname);
454: intc_intr_establish(SH7709_INTEVT2_SCIF_RXI, IST_LEVEL, IPL_TTY,
455: scifintr, sc, self->dv_xname);
456: intc_intr_establish(SH7709_INTEVT2_SCIF_BRI, IST_LEVEL, IPL_TTY,
457: scifintr, sc, self->dv_xname);
458: intc_intr_establish(SH7709_INTEVT2_SCIF_TXI, IST_LEVEL, IPL_TTY,
459: scifintr, sc, self->dv_xname);
460: #endif
461:
462: sc->sc_si = softintr_establish(IPL_SOFTSERIAL, scifsoft, sc);
463: SET(sc->sc_hwflags, SCIF_HW_DEV_OK);
464:
465: tp = ttymalloc();
466: tp->t_oproc = scifstart;
467: tp->t_param = scifparam;
468: tp->t_hwiflow = NULL;
469:
470: sc->sc_tty = tp;
471: sc->sc_rbuf = malloc(scif_rbuf_size << 1, M_DEVBUF, M_NOWAIT);
472: if (sc->sc_rbuf == NULL) {
473: printf("%s: unable to allocate ring buffer\n",
474: sc->sc_dev.dv_xname);
475: return;
476: }
477: sc->sc_ebuf = sc->sc_rbuf + (scif_rbuf_size << 1);
478: }
479:
480: /*
481: * Start or restart transmission.
482: */
483: void
484: scifstart(struct tty *tp)
485: {
486: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)];
487: int s;
488:
489: s = spltty();
490: if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
491: goto out;
492: if (sc->sc_tx_stopped)
493: goto out;
494:
495: if (tp->t_outq.c_cc <= tp->t_lowat) {
496: if (ISSET(tp->t_state, TS_ASLEEP)) {
497: CLR(tp->t_state, TS_ASLEEP);
498: wakeup(&tp->t_outq);
499: }
500: selwakeup(&tp->t_wsel);
501: if (tp->t_outq.c_cc == 0)
502: goto out;
503: }
504:
505: /* Grab the first contiguous region of buffer space. */
506: {
507: u_char *tba;
508: int tbc;
509:
510: tba = tp->t_outq.c_cf;
511: tbc = ndqb(&tp->t_outq, 0);
512:
513:
514: sc->sc_tba = tba;
515: sc->sc_tbc = tbc;
516: }
517:
518: SET(tp->t_state, TS_BUSY);
519: sc->sc_tx_busy = 1;
520:
521: /* Enable transmit completion interrupts if necessary. */
522: scif_scr_write(scif_scr_read() | SCSCR2_TIE | SCSCR2_RIE);
523:
524: /* Output the first chunk of the contiguous buffer. */
525: {
526: int n;
527: int maxchars;
528: int i;
529:
530: n = sc->sc_tbc;
531: maxchars = sc->sc_fifolen
532: - ((scif_fdr_read() & SCFDR2_TXCNT) >> 8);
533: if (n > maxchars)
534: n = maxchars;
535:
536: for (i = 0; i < n; i++) {
537: scif_putc(*(sc->sc_tba));
538: sc->sc_tba++;
539: }
540: sc->sc_tbc -= n;
541: }
542: out:
543: splx(s);
544: return;
545: }
546:
547: /*
548: * Set SCIF tty parameters from termios.
549: * XXX - Should just copy the whole termios after
550: * making sure all the changes could be done.
551: */
552: int
553: scifparam(struct tty *tp, struct termios *t)
554: {
555: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)];
556: int ospeed = t->c_ospeed;
557: int s;
558:
559: /* Check requested parameters. */
560: if (ospeed < 0)
561: return (EINVAL);
562: if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
563: return (EINVAL);
564:
565: /*
566: * For the console, always force CLOCAL and !HUPCL, so that the port
567: * is always active.
568: */
569: if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
570: ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) {
571: SET(t->c_cflag, CLOCAL);
572: CLR(t->c_cflag, HUPCL);
573: }
574:
575: /*
576: * If there were no changes, don't do anything. This avoids dropping
577: * input and improves performance when all we did was frob things like
578: * VMIN and VTIME.
579: */
580: if (tp->t_ospeed == t->c_ospeed &&
581: tp->t_cflag == t->c_cflag)
582: return (0);
583:
584: #if 0
585: /* XXX (msaitoh) */
586: lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag);
587: #endif
588:
589: s = spltty();
590:
591: /*
592: * Set the flow control pins depending on the current flow control
593: * mode.
594: */
595: if (ISSET(t->c_cflag, CRTSCTS)) {
596: scif_fcr_write(scif_fcr_read() | SCFCR2_MCE);
597: } else {
598: scif_fcr_write(scif_fcr_read() & ~SCFCR2_MCE);
599: }
600:
601: scif_brr_write(divrnd(sh_clock_get_pclock(), 32 * ospeed) -1);
602:
603: /*
604: * Set the FIFO threshold based on the receive speed.
605: *
606: * * If it's a low speed, it's probably a mouse or some other
607: * interactive device, so set the threshold low.
608: * * If it's a high speed, trim the trigger level down to prevent
609: * overflows.
610: * * Otherwise set it a bit higher.
611: */
612: #if 0
613: /* XXX (msaitoh) */
614: if (ISSET(sc->sc_hwflags, SCIF_HW_HAYESP))
615: sc->sc_fifo = FIFO_DMA_MODE | FIFO_ENABLE | FIFO_TRIGGER_8;
616: else if (ISSET(sc->sc_hwflags, SCIF_HW_FIFO))
617: sc->sc_fifo = FIFO_ENABLE |
618: (t->c_ospeed <= 1200 ? FIFO_TRIGGER_1 :
619: t->c_ospeed <= 38400 ? FIFO_TRIGGER_8 : FIFO_TRIGGER_4);
620: else
621: sc->sc_fifo = 0;
622: #endif
623:
624: /* And copy to tty. */
625: tp->t_ispeed = 0;
626: tp->t_ospeed = t->c_ospeed;
627: tp->t_cflag = t->c_cflag;
628:
629: if (!sc->sc_heldchange) {
630: if (sc->sc_tx_busy) {
631: sc->sc_heldtbc = sc->sc_tbc;
632: sc->sc_tbc = 0;
633: sc->sc_heldchange = 1;
634: }
635: #if 0
636: /* XXX (msaitoh) */
637: else
638: scif_loadchannelregs(sc);
639: #endif
640: }
641:
642: if (!ISSET(t->c_cflag, CHWFLOW)) {
643: /* Disable the high water mark. */
644: sc->sc_r_hiwat = 0;
645: sc->sc_r_lowat = 0;
646: if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
647: CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
648: scif_schedrx(sc);
649: }
650: } else {
651: sc->sc_r_hiwat = scif_rbuf_hiwat;
652: sc->sc_r_lowat = scif_rbuf_lowat;
653: }
654:
655: splx(s);
656:
657: #ifdef SCIF_DEBUG
658: if (scif_debug)
659: scifstatus(sc, "scifparam ");
660: #endif
661:
662: if (!ISSET(t->c_cflag, CHWFLOW)) {
663: if (sc->sc_tx_stopped) {
664: sc->sc_tx_stopped = 0;
665: scifstart(tp);
666: }
667: }
668:
669: return (0);
670: }
671:
672: void
673: scif_iflush(struct scif_softc *sc)
674: {
675: int i;
676: unsigned char c;
677:
678: i = scif_fdr_read() & SCFDR2_RECVCNT;
679:
680: while (i > 0) {
681: c = scif_frdr_read();
682: scif_ssr_write(scif_ssr_read() & ~(SCSSR2_RDF | SCSSR2_DR));
683: i--;
684: }
685: }
686:
687: int
688: scifopen(dev_t dev, int flag, int mode, struct proc *p)
689: {
690: int unit = SCIFUNIT(dev);
691: struct scif_softc *sc;
692: struct tty *tp;
693: int s;
694: int error;
695:
696: if (unit >= scif_cd.cd_ndevs)
697: return (ENXIO);
698: sc = scif_cd.cd_devs[unit];
699: if (sc == 0 || !ISSET(sc->sc_hwflags, SCIF_HW_DEV_OK) ||
700: sc->sc_rbuf == NULL)
701: return (ENXIO);
702:
703: tp = sc->sc_tty;
704:
705: if (ISSET(tp->t_state, TS_ISOPEN) &&
706: ISSET(tp->t_state, TS_XCLUDE) &&
707: p->p_ucred->cr_uid != 0)
708: return (EBUSY);
709:
710: s = spltty();
711:
712: /*
713: * Do the following iff this is a first open.
714: */
715: if (!ISSET(tp->t_state, TS_ISOPEN)) {
716: struct termios t;
717:
718: tp->t_dev = dev;
719:
720:
721: /* Turn on interrupts. */
722: scif_scr_write(scif_scr_read() | SCSCR2_TIE | SCSCR2_RIE);
723:
724: /*
725: * Initialize the termios status to the defaults. Add in the
726: * sticky bits from TIOCSFLAGS.
727: */
728: t.c_ispeed = 0;
729: if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) {
730: t.c_ospeed = scifcn_speed; /* XXX (msaitoh) */
731: t.c_cflag = scifconscflag;
732: } else {
733: t.c_ospeed = TTYDEF_SPEED;
734: t.c_cflag = TTYDEF_CFLAG;
735: }
736: if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
737: SET(t.c_cflag, CLOCAL);
738: if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
739: SET(t.c_cflag, CRTSCTS);
740: if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
741: SET(t.c_cflag, MDMBUF);
742: /* Make sure scifparam() will do something. */
743: tp->t_ospeed = 0;
744: (void) scifparam(tp, &t);
745:
746: /*
747: * XXX landisk has no hardware flow control!
748: * When porting to another platform, fix this somehow
749: */
750: SET(tp->t_state, TS_CARR_ON);
751:
752: tp->t_iflag = TTYDEF_IFLAG;
753: tp->t_oflag = TTYDEF_OFLAG;
754: tp->t_lflag = TTYDEF_LFLAG;
755: ttychars(tp);
756: ttsetwater(tp);
757:
758: /* Clear the input ring, and unblock. */
759: sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
760: sc->sc_rbavail = scif_rbuf_size;
761: scif_iflush(sc);
762: CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
763: #if 0
764: /* XXX (msaitoh) */
765: scif_hwiflow(sc);
766: #endif
767:
768: #ifdef SCIF_DEBUG
769: if (scif_debug)
770: scifstatus(sc, "scifopen ");
771: #endif
772:
773: }
774:
775: splx(s);
776:
777: error = ttyopen(dev, tp);
778: if (error)
779: goto bad;
780:
781: error = (*linesw[tp->t_line].l_open)(dev, tp);
782: if (error)
783: goto bad;
784:
785: return (0);
786:
787: bad:
788:
789: return (error);
790: }
791:
792: int
793: scifclose(dev_t dev, int flag, int mode, struct proc *p)
794: {
795: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
796: struct tty *tp = sc->sc_tty;
797:
798: /* XXX This is for cons.c. */
799: if (!ISSET(tp->t_state, TS_ISOPEN))
800: return (0);
801:
802: (*linesw[tp->t_line].l_close)(tp, flag);
803: ttyclose(tp);
804:
805: return (0);
806: }
807:
808: int
809: scifread(dev_t dev, struct uio *uio, int flag)
810: {
811: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
812: struct tty *tp = sc->sc_tty;
813:
814: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
815: }
816:
817: int
818: scifwrite(dev_t dev, struct uio *uio, int flag)
819: {
820: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
821: struct tty *tp = sc->sc_tty;
822:
823: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
824: }
825:
826: #if 0
827: int
828: scifpoll(dev_t dev, int events, struct proc *p)
829: {
830: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
831: struct tty *tp = sc->sc_tty;
832:
833: return ((*linesw[tp->t_line].l_poll)(tp, events, p));
834: }
835: #endif
836:
837: struct tty *
838: sciftty(dev_t dev)
839: {
840: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
841: struct tty *tp = sc->sc_tty;
842:
843: return (tp);
844: }
845:
846: int
847: scifioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
848: {
849: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
850: struct tty *tp = sc->sc_tty;
851: int error;
852: int s;
853:
854: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
855: if (error != -1)
856: return (error);
857:
858: error = ttioctl(tp, cmd, data, flag, p);
859: if (error != -1)
860: return (error);
861:
862: error = 0;
863:
864: s = spltty();
865:
866: switch (cmd) {
867: case TIOCSBRK:
868: scif_break(sc, 1);
869: break;
870:
871: case TIOCCBRK:
872: scif_break(sc, 0);
873: break;
874:
875: case TIOCGFLAGS:
876: *(int *)data = sc->sc_swflags;
877: break;
878:
879: case TIOCSFLAGS:
880: error = suser(p, 0);
881: if (error)
882: break;
883: sc->sc_swflags = *(int *)data;
884: break;
885:
886: default:
887: error = -1;
888: break;
889: }
890:
891: splx(s);
892:
893: return (error);
894: }
895:
896: void
897: scif_schedrx(struct scif_softc *sc)
898: {
899: sc->sc_rx_ready = 1;
900:
901: /* Wake up the poller. */
902: softintr_schedule(sc->sc_si);
903: }
904:
905: void
906: scif_break(struct scif_softc *sc, int onoff)
907: {
908: if (onoff)
909: scif_ssr_write(scif_ssr_read() & ~SCSSR2_TDFE);
910: else
911: scif_ssr_write(scif_ssr_read() | SCSSR2_TDFE);
912:
913: #if 0 /* XXX */
914: if (!sc->sc_heldchange) {
915: if (sc->sc_tx_busy) {
916: sc->sc_heldtbc = sc->sc_tbc;
917: sc->sc_tbc = 0;
918: sc->sc_heldchange = 1;
919: } else
920: scif_loadchannelregs(sc);
921: }
922: #endif
923: }
924:
925: /*
926: * Stop output, e.g., for ^S or output flush.
927: */
928: int
929: scifstop(struct tty *tp, int flag)
930: {
931: struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)];
932: int s;
933:
934: s = spltty();
935: if (ISSET(tp->t_state, TS_BUSY)) {
936: /* Stop transmitting at the next chunk. */
937: sc->sc_tbc = 0;
938: sc->sc_heldtbc = 0;
939: if (!ISSET(tp->t_state, TS_TTSTOP))
940: SET(tp->t_state, TS_FLUSH);
941: }
942: splx(s);
943: return (0);
944: }
945:
946: void
947: scif_intr_init()
948: {
949: /* XXX */
950: }
951:
952: void
953: scifdiag(void *arg)
954: {
955: struct scif_softc *sc = arg;
956: int overflows, floods;
957: int s;
958:
959: s = spltty();
960: overflows = sc->sc_overflows;
961: sc->sc_overflows = 0;
962: floods = sc->sc_floods;
963: sc->sc_floods = 0;
964: sc->sc_errors = 0;
965: splx(s);
966:
967: log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n",
968: sc->sc_dev.dv_xname,
969: overflows, overflows == 1 ? "" : "s",
970: floods, floods == 1 ? "" : "s");
971: }
972:
973: void
974: scif_rxsoft(struct scif_softc *sc, struct tty *tp)
975: {
976: int (*rint)(int, struct tty *) = *linesw[tp->t_line].l_rint;
977: u_char *get, *end;
978: u_int cc, scc;
979: u_char ssr2;
980: int code;
981: int s;
982:
983: end = sc->sc_ebuf;
984: get = sc->sc_rbget;
985: scc = cc = scif_rbuf_size - sc->sc_rbavail;
986:
987: if (cc == scif_rbuf_size) {
988: sc->sc_floods++;
989: if (sc->sc_errors++ == 0)
990: timeout_add(&sc->sc_diag_tmo, 60 * hz);
991: }
992:
993: while (cc) {
994: code = get[0];
995: ssr2 = get[1];
996: if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER | SCSSR2_PER)) {
997: if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER))
998: SET(code, TTY_FE);
999: if (ISSET(ssr2, SCSSR2_PER))
1000: SET(code, TTY_PE);
1001: }
1002: if ((*rint)(code, tp) == -1) {
1003: /*
1004: * The line discipline's buffer is out of space.
1005: */
1006: if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
1007: /*
1008: * We're either not using flow control, or the
1009: * line discipline didn't tell us to block for
1010: * some reason. Either way, we have no way to
1011: * know when there's more space available, so
1012: * just drop the rest of the data.
1013: */
1014: get += cc << 1;
1015: if (get >= end)
1016: get -= scif_rbuf_size << 1;
1017: cc = 0;
1018: } else {
1019: /*
1020: * Don't schedule any more receive processing
1021: * until the line discipline tells us there's
1022: * space available (through scifhwiflow()).
1023: * Leave the rest of the data in the input
1024: * buffer.
1025: */
1026: SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
1027: }
1028: break;
1029: }
1030: get += 2;
1031: if (get >= end)
1032: get = sc->sc_rbuf;
1033: cc--;
1034: }
1035:
1036: if (cc != scc) {
1037: sc->sc_rbget = get;
1038: s = spltty();
1039: cc = sc->sc_rbavail += scc - cc;
1040: /* Buffers should be ok again, release possible block. */
1041: if (cc >= sc->sc_r_lowat) {
1042: if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
1043: CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
1044: scif_scr_write(scif_scr_read() | SCSCR2_RIE);
1045: }
1046: #if 0
1047: if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
1048: CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
1049: scif_hwiflow(sc);
1050: }
1051: #endif
1052: }
1053: splx(s);
1054: }
1055: }
1056:
1057: void
1058: scif_txsoft(struct scif_softc *sc, struct tty *tp)
1059: {
1060: CLR(tp->t_state, TS_BUSY);
1061: if (ISSET(tp->t_state, TS_FLUSH))
1062: CLR(tp->t_state, TS_FLUSH);
1063: else
1064: ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
1065: (*linesw[tp->t_line].l_start)(tp);
1066: }
1067:
1068: void
1069: scif_stsoft(struct scif_softc *sc, struct tty *tp)
1070: {
1071: #if 0
1072: /* XXX (msaitoh) */
1073: u_char msr, delta;
1074: int s;
1075:
1076: s = spltty();
1077: msr = sc->sc_msr;
1078: delta = sc->sc_msr_delta;
1079: sc->sc_msr_delta = 0;
1080: splx(s);
1081:
1082: if (ISSET(delta, sc->sc_msr_dcd)) {
1083: /*
1084: * Inform the tty layer that carrier detect changed.
1085: */
1086: (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD));
1087: }
1088:
1089: if (ISSET(delta, sc->sc_msr_cts)) {
1090: /* Block or unblock output according to flow control. */
1091: if (ISSET(msr, sc->sc_msr_cts)) {
1092: sc->sc_tx_stopped = 0;
1093: (*linesw[tp->t_line].l_start)(tp);
1094: } else {
1095: sc->sc_tx_stopped = 1;
1096: }
1097: }
1098:
1099: #ifdef SCIF_DEBUG
1100: if (scif_debug)
1101: scifstatus(sc, "scif_stsoft");
1102: #endif
1103: #endif
1104: }
1105:
1106: void
1107: scifsoft(void *arg)
1108: {
1109: struct scif_softc *sc = arg;
1110: struct tty *tp;
1111:
1112: tp = sc->sc_tty;
1113:
1114: if (sc->sc_rx_ready) {
1115: sc->sc_rx_ready = 0;
1116: scif_rxsoft(sc, tp);
1117: }
1118:
1119: #if 0
1120: if (sc->sc_st_check) {
1121: sc->sc_st_check = 0;
1122: scif_stsoft(sc, tp);
1123: }
1124: #endif
1125:
1126: if (sc->sc_tx_done) {
1127: sc->sc_tx_done = 0;
1128: scif_txsoft(sc, tp);
1129: }
1130: }
1131:
1132: int
1133: scifintr(void *arg)
1134: {
1135: struct scif_softc *sc = arg;
1136: u_char *put, *end;
1137: u_int cc;
1138: u_short ssr2;
1139: int count;
1140:
1141: end = sc->sc_ebuf;
1142: put = sc->sc_rbput;
1143: cc = sc->sc_rbavail;
1144:
1145: do {
1146: ssr2 = scif_ssr_read();
1147: if (ISSET(ssr2, SCSSR2_BRK)) {
1148: scif_ssr_write(scif_ssr_read()
1149: & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_DR));
1150: #ifdef DDB
1151: if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE) &&
1152: db_console != 0) {
1153: Debugger();
1154: }
1155: #endif /* DDB */
1156: }
1157: count = scif_fdr_read() & SCFDR2_RECVCNT;
1158: if (count != 0) {
1159: for (;;) {
1160: u_char c = scif_frdr_read();
1161: u_char err = (u_char)(scif_ssr_read() & 0x00ff);
1162:
1163: scif_ssr_write(scif_ssr_read()
1164: & ~(SCSSR2_ER | SCSSR2_RDF | SCSSR2_DR));
1165: #ifdef SH4
1166: if (CPU_IS_SH4)
1167: scif_lsr_write(scif_lsr_read()
1168: & ~SCLSR2_ORER);
1169: #endif
1170: if ((cc > 0) && (count > 0)) {
1171: put[0] = c;
1172: put[1] = err;
1173: put += 2;
1174: if (put >= end)
1175: put = sc->sc_rbuf;
1176: cc--;
1177: count--;
1178: } else
1179: break;
1180: }
1181:
1182: /*
1183: * Current string of incoming characters ended because
1184: * no more data was available or we ran out of space.
1185: * Schedule a receive event if any data was received.
1186: * If we're out of space, turn off receive interrupts.
1187: */
1188: sc->sc_rbput = put;
1189: sc->sc_rbavail = cc;
1190: if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
1191: sc->sc_rx_ready = 1;
1192:
1193: /*
1194: * See if we are in danger of overflowing a buffer. If
1195: * so, use hardware flow control to ease the pressure.
1196: */
1197: if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) &&
1198: cc < sc->sc_r_hiwat) {
1199: SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
1200: #if 0
1201: scif_hwiflow(sc);
1202: #endif
1203: }
1204:
1205: /*
1206: * If we're out of space, disable receive interrupts
1207: * until the queue has drained a bit.
1208: */
1209: if (!cc) {
1210: SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
1211: scif_scr_write(scif_scr_read() & ~SCSCR2_RIE);
1212: }
1213: } else {
1214: if (scif_ssr_read() & (SCSSR2_RDF | SCSSR2_DR)) {
1215: scif_scr_write(scif_scr_read()
1216: & ~(SCSCR2_TIE | SCSCR2_RIE));
1217: delay(10);
1218: scif_scr_write(scif_scr_read()
1219: | SCSCR2_TIE | SCSCR2_RIE);
1220: continue;
1221: }
1222: }
1223: } while (scif_ssr_read() & (SCSSR2_RDF | SCSSR2_DR));
1224:
1225: #if 0
1226: msr = bus_space_read_1(iot, ioh, scif_msr);
1227: delta = msr ^ sc->sc_msr;
1228: sc->sc_msr = msr;
1229: if (ISSET(delta, sc->sc_msr_mask)) {
1230: SET(sc->sc_msr_delta, delta);
1231:
1232: /*
1233: * Pulse-per-second clock signal on edge of DCD?
1234: */
1235: if (ISSET(delta, sc->sc_ppsmask)) {
1236: struct timeval tv;
1237: if (ISSET(msr, sc->sc_ppsmask) ==
1238: sc->sc_ppsassert) {
1239: /* XXX nanotime() */
1240: microtime(&tv);
1241: TIMEVAL_TO_TIMESPEC(&tv,
1242: &sc->ppsinfo.assert_timestamp);
1243: if (sc->ppsparam.mode & PPS_OFFSETASSERT) {
1244: timespecadd(&sc->ppsinfo.assert_timestamp,
1245: &sc->ppsparam.assert_offset,
1246: &sc->ppsinfo.assert_timestamp);
1247: TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.assert_timestamp);
1248: }
1249:
1250: #ifdef PPS_SYNC
1251: if (sc->ppsparam.mode & PPS_HARDPPSONASSERT)
1252: hardpps(&tv, tv.tv_usec);
1253: #endif
1254: sc->ppsinfo.assert_sequence++;
1255: sc->ppsinfo.current_mode =
1256: sc->ppsparam.mode;
1257:
1258: } else if (ISSET(msr, sc->sc_ppsmask) ==
1259: sc->sc_ppsclear) {
1260: /* XXX nanotime() */
1261: microtime(&tv);
1262: TIMEVAL_TO_TIMESPEC(&tv,
1263: &sc->ppsinfo.clear_timestamp);
1264: if (sc->ppsparam.mode & PPS_OFFSETCLEAR) {
1265: timespecadd(&sc->ppsinfo.clear_timestamp,
1266: &sc->ppsparam.clear_offset,
1267: &sc->ppsinfo.clear_timestamp);
1268: TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.clear_timestamp);
1269: }
1270:
1271: #ifdef PPS_SYNC
1272: if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR)
1273: hardpps(&tv, tv.tv_usec);
1274: #endif
1275: sc->ppsinfo.clear_sequence++;
1276: sc->ppsinfo.current_mode =
1277: sc->ppsparam.mode;
1278: }
1279: }
1280:
1281: /*
1282: * Stop output immediately if we lose the output
1283: * flow control signal or carrier detect.
1284: */
1285: if (ISSET(~msr, sc->sc_msr_mask)) {
1286: sc->sc_tbc = 0;
1287: sc->sc_heldtbc = 0;
1288: #ifdef SCIF_DEBUG
1289: if (scif_debug)
1290: scifstatus(sc, "scifintr ");
1291: #endif
1292: }
1293:
1294: sc->sc_st_check = 1;
1295: }
1296: #endif
1297:
1298: /*
1299: * Done handling any receive interrupts. See if data can be
1300: * transmitted as well. Schedule tx done event if no data left
1301: * and tty was marked busy.
1302: */
1303: if (((scif_fdr_read() & SCFDR2_TXCNT) >> 8) != 16) { /* XXX (msaitoh) */
1304: /*
1305: * If we've delayed a parameter change, do it now, and restart
1306: * output.
1307: */
1308: if (sc->sc_heldchange) {
1309: sc->sc_heldchange = 0;
1310: sc->sc_tbc = sc->sc_heldtbc;
1311: sc->sc_heldtbc = 0;
1312: }
1313:
1314: /* Output the next chunk of the contiguous buffer, if any. */
1315: if (sc->sc_tbc > 0) {
1316: int n;
1317: int maxchars;
1318: int i;
1319:
1320: n = sc->sc_tbc;
1321: maxchars = sc->sc_fifolen -
1322: ((scif_fdr_read() & SCFDR2_TXCNT) >> 8);
1323: if (n > maxchars)
1324: n = maxchars;
1325:
1326: for (i = 0; i < n; i++) {
1327: scif_putc(*(sc->sc_tba));
1328: sc->sc_tba++;
1329: }
1330: sc->sc_tbc -= n;
1331: } else {
1332: /* Disable transmit completion interrupts if necessary. */
1333: #if 0
1334: if (ISSET(sc->sc_ier, IER_ETXRDY))
1335: #endif
1336: scif_scr_write(scif_scr_read() & ~SCSCR2_TIE);
1337:
1338: if (sc->sc_tx_busy) {
1339: sc->sc_tx_busy = 0;
1340: sc->sc_tx_done = 1;
1341: }
1342: }
1343: }
1344:
1345: /* Wake up the poller. */
1346: softintr_schedule(sc->sc_si);
1347:
1348: return (1);
1349: }
1350:
1351: void
1352: scifcnprobe(struct consdev *cp)
1353: {
1354: int maj;
1355:
1356: /* locate the major number */
1357: for (maj = 0; maj < nchrdev; maj++)
1358: if (cdevsw[maj].d_open == scifopen)
1359: break;
1360:
1361: cp->cn_dev = makedev(maj, 0);
1362: #ifdef SCIFCONSOLE
1363: cp->cn_pri = CN_REMOTE;
1364: #else
1365: cp->cn_pri = CN_NORMAL;
1366: #endif
1367: }
1368:
1369: void
1370: scifcninit(struct consdev *cp)
1371: {
1372: InitializeScif(scifcn_speed);
1373: scifisconsole = 1;
1374: }
1375:
1376: int
1377: scifcngetc(dev_t dev)
1378: {
1379: int c;
1380: int s;
1381:
1382: s = spltty();
1383: c = scif_getc();
1384: splx(s);
1385:
1386: return (c);
1387: }
1388:
1389: void
1390: scifcnputc(dev_t dev, int c)
1391: {
1392: int s;
1393:
1394: s = spltty();
1395: scif_putc((u_char)c);
1396: splx(s);
1397: }
CVSweb