1*3836e7c7Smiod /* $OpenBSD: scif.c,v 1.24 2024/11/05 18:58:59 miod Exp $ */ 295c7671fSmiod /* $NetBSD: scif.c,v 1.47 2006/07/23 22:06:06 ad Exp $ */ 395c7671fSmiod 495c7671fSmiod /*- 595c7671fSmiod * Copyright (C) 1999 T.Horiuchi and SAITOH Masanobu. All rights reserved. 695c7671fSmiod * 795c7671fSmiod * Redistribution and use in source and binary forms, with or without 895c7671fSmiod * modification, are permitted provided that the following conditions 995c7671fSmiod * are met: 1095c7671fSmiod * 1. Redistributions of source code must retain the above copyright 1195c7671fSmiod * notice, this list of conditions and the following disclaimer. 1295c7671fSmiod * 2. Redistributions in binary form must reproduce the above copyright 1395c7671fSmiod * notice, this list of conditions and the following disclaimer in the 1495c7671fSmiod * documentation and/or other materials provided with the distribution. 1595c7671fSmiod * 3. The name of the author may not be used to endorse or promote products 1695c7671fSmiod * derived from this software without specific prior written permission. 1795c7671fSmiod * 1895c7671fSmiod * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1995c7671fSmiod * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2095c7671fSmiod * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2195c7671fSmiod * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2295c7671fSmiod * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2395c7671fSmiod * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2495c7671fSmiod * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2595c7671fSmiod * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2695c7671fSmiod * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2795c7671fSmiod * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2895c7671fSmiod */ 2995c7671fSmiod 3095c7671fSmiod /*- 3195c7671fSmiod * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 3295c7671fSmiod * All rights reserved. 3395c7671fSmiod * 3495c7671fSmiod * This code is derived from software contributed to The NetBSD Foundation 3595c7671fSmiod * by Charles M. Hannum. 3695c7671fSmiod * 3795c7671fSmiod * Redistribution and use in source and binary forms, with or without 3895c7671fSmiod * modification, are permitted provided that the following conditions 3995c7671fSmiod * are met: 4095c7671fSmiod * 1. Redistributions of source code must retain the above copyright 4195c7671fSmiod * notice, this list of conditions and the following disclaimer. 4295c7671fSmiod * 2. Redistributions in binary form must reproduce the above copyright 4395c7671fSmiod * notice, this list of conditions and the following disclaimer in the 4495c7671fSmiod * documentation and/or other materials provided with the distribution. 4595c7671fSmiod * 4695c7671fSmiod * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 4795c7671fSmiod * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 4895c7671fSmiod * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4995c7671fSmiod * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 5095c7671fSmiod * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5195c7671fSmiod * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 5295c7671fSmiod * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 5395c7671fSmiod * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 5495c7671fSmiod * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5595c7671fSmiod * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 5695c7671fSmiod * POSSIBILITY OF SUCH DAMAGE. 5795c7671fSmiod */ 5895c7671fSmiod 5995c7671fSmiod /* 6095c7671fSmiod * Copyright (c) 1991 The Regents of the University of California. 6195c7671fSmiod * All rights reserved. 6295c7671fSmiod * 6395c7671fSmiod * Redistribution and use in source and binary forms, with or without 6495c7671fSmiod * modification, are permitted provided that the following conditions 6595c7671fSmiod * are met: 6695c7671fSmiod * 1. Redistributions of source code must retain the above copyright 6795c7671fSmiod * notice, this list of conditions and the following disclaimer. 6895c7671fSmiod * 2. Redistributions in binary form must reproduce the above copyright 6995c7671fSmiod * notice, this list of conditions and the following disclaimer in the 7095c7671fSmiod * documentation and/or other materials provided with the distribution. 7195c7671fSmiod * 3. Neither the name of the University nor the names of its contributors 7295c7671fSmiod * may be used to endorse or promote products derived from this software 7395c7671fSmiod * without specific prior written permission. 7495c7671fSmiod * 7595c7671fSmiod * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 7695c7671fSmiod * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 7795c7671fSmiod * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 7895c7671fSmiod * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 7995c7671fSmiod * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 8095c7671fSmiod * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 8195c7671fSmiod * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 8295c7671fSmiod * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 8395c7671fSmiod * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 8495c7671fSmiod * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 8595c7671fSmiod * SUCH DAMAGE. 8695c7671fSmiod * 8795c7671fSmiod * @(#)com.c 7.5 (Berkeley) 5/16/91 8895c7671fSmiod */ 8995c7671fSmiod 9095c7671fSmiod /* 9195c7671fSmiod * SH internal serial driver 9295c7671fSmiod * 9395c7671fSmiod * This code is derived from both z8530tty.c and com.c 9495c7671fSmiod */ 9595c7671fSmiod 9695c7671fSmiod #include <sys/param.h> 9795c7671fSmiod #include <sys/systm.h> 9895c7671fSmiod #include <sys/tty.h> 9995c7671fSmiod #include <sys/proc.h> 10095c7671fSmiod #include <sys/conf.h> 10195c7671fSmiod #include <sys/syslog.h> 10295c7671fSmiod #include <sys/kernel.h> 10395c7671fSmiod #include <sys/device.h> 10495c7671fSmiod #include <sys/malloc.h> 10595c7671fSmiod #include <sys/timeout.h> 10695c7671fSmiod 10795c7671fSmiod #include <dev/cons.h> 10895c7671fSmiod 10995c7671fSmiod #include <sh/clock.h> 11095c7671fSmiod #include <sh/trap.h> 11195c7671fSmiod #include <machine/intr.h> 112cd4d230cSmickey #include <machine/conf.h> 11395c7671fSmiod 11495c7671fSmiod #include <sh/dev/scifreg.h> 11595c7671fSmiod 11695c7671fSmiod #ifdef DDB 11795c7671fSmiod #include <ddb/db_var.h> 11895c7671fSmiod #endif 11995c7671fSmiod 12095c7671fSmiod void scifstart(struct tty *); 12195c7671fSmiod int scifparam(struct tty *, struct termios *); 12295c7671fSmiod 123e5f0bf7fSmiod cons_decl(scif); 12495c7671fSmiod void scif_intr_init(void); 12595c7671fSmiod int scifintr(void *); 12695c7671fSmiod 12795c7671fSmiod struct scif_softc { 12895c7671fSmiod struct device sc_dev; /* boilerplate */ 12995c7671fSmiod struct tty *sc_tty; 13095c7671fSmiod void *sc_si; 13195c7671fSmiod 13295c7671fSmiod struct timeout sc_diag_tmo; 13395c7671fSmiod 13495c7671fSmiod #if 0 13595c7671fSmiod bus_space_tag_t sc_iot; /* ISA i/o space identifier */ 13695c7671fSmiod bus_space_handle_t sc_ioh; /* ISA io handle */ 13795c7671fSmiod 13895c7671fSmiod int sc_drq; 13995c7671fSmiod 14095c7671fSmiod int sc_frequency; 14195c7671fSmiod #endif 14295c7671fSmiod 14395c7671fSmiod u_int sc_overflows, 14495c7671fSmiod sc_floods, 14595c7671fSmiod sc_errors; /* number of retries so far */ 14695c7671fSmiod u_char sc_status[7]; /* copy of registers */ 14795c7671fSmiod 14895c7671fSmiod int sc_hwflags; 14995c7671fSmiod int sc_swflags; 15095c7671fSmiod u_int sc_fifolen; 15195c7671fSmiod 15295c7671fSmiod u_int sc_r_hiwat, 15395c7671fSmiod sc_r_lowat; 15495c7671fSmiod u_char *volatile sc_rbget, 15595c7671fSmiod *volatile sc_rbput; 15695c7671fSmiod volatile u_int sc_rbavail; 15795c7671fSmiod u_char *sc_rbuf, 15895c7671fSmiod *sc_ebuf; 15995c7671fSmiod 16095c7671fSmiod u_char *sc_tba; /* transmit buffer address */ 16195c7671fSmiod u_int sc_tbc, /* transmit byte count */ 16295c7671fSmiod sc_heldtbc; 16395c7671fSmiod 16495c7671fSmiod volatile u_char sc_rx_flags, 16595c7671fSmiod #define RX_TTY_BLOCKED 0x01 16695c7671fSmiod #define RX_TTY_OVERFLOWED 0x02 16795c7671fSmiod #define RX_IBUF_BLOCKED 0x04 16895c7671fSmiod #define RX_IBUF_OVERFLOWED 0x08 16995c7671fSmiod #define RX_ANY_BLOCK 0x0f 17095c7671fSmiod sc_tx_busy, /* working on an output chunk */ 17195c7671fSmiod sc_tx_done, /* done with one output chunk */ 17295c7671fSmiod sc_tx_stopped, /* H/W level stop (lost CTS) */ 17395c7671fSmiod sc_st_check, /* got a status interrupt */ 17495c7671fSmiod sc_rx_ready; 17595c7671fSmiod 17695c7671fSmiod volatile u_char sc_heldchange; 17795c7671fSmiod }; 17895c7671fSmiod 17995c7671fSmiod /* controller driver configuration */ 18095c7671fSmiod int scif_match(struct device *, void *, void *); 18195c7671fSmiod void scif_attach(struct device *, struct device *, void *); 18295c7671fSmiod 18395c7671fSmiod void scif_break(struct scif_softc *, int); 18495c7671fSmiod void scif_iflush(struct scif_softc *); 18595c7671fSmiod 18695c7671fSmiod void scifsoft(void *); 18795c7671fSmiod void scif_rxsoft(struct scif_softc *, struct tty *); 18895c7671fSmiod void scif_txsoft(struct scif_softc *, struct tty *); 18995c7671fSmiod void scif_stsoft(struct scif_softc *, struct tty *); 19095c7671fSmiod void scif_schedrx(struct scif_softc *); 19195c7671fSmiod void scifdiag(void *); 19295c7671fSmiod 19395c7671fSmiod 19495c7671fSmiod #define SCIFUNIT_MASK 0x7ffff 19595c7671fSmiod #define SCIFDIALOUT_MASK 0x80000 19695c7671fSmiod 19795c7671fSmiod #define SCIFUNIT(x) (minor(x) & SCIFUNIT_MASK) 19895c7671fSmiod #define SCIFDIALOUT(x) (minor(x) & SCIFDIALOUT_MASK) 19995c7671fSmiod 20095c7671fSmiod /* Hardware flag masks */ 20195c7671fSmiod #define SCIF_HW_NOIEN 0x01 20295c7671fSmiod #define SCIF_HW_FIFO 0x02 20395c7671fSmiod #define SCIF_HW_FLOW 0x08 20495c7671fSmiod #define SCIF_HW_DEV_OK 0x20 20595c7671fSmiod #define SCIF_HW_CONSOLE 0x40 20695c7671fSmiod 20795c7671fSmiod /* Buffer size for character buffer */ 20895c7671fSmiod #define SCIF_RING_SIZE 2048 20995c7671fSmiod 21095c7671fSmiod /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 21195c7671fSmiod u_int scif_rbuf_hiwat = (SCIF_RING_SIZE * 1) / 4; 21295c7671fSmiod u_int scif_rbuf_lowat = (SCIF_RING_SIZE * 3) / 4; 21395c7671fSmiod 21495c7671fSmiod #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 21595c7671fSmiod int scifconscflag = CONMODE; 21695c7671fSmiod int scifisconsole = 0; 21795c7671fSmiod 21895c7671fSmiod #ifdef SCIFCN_SPEED 21995c7671fSmiod unsigned int scifcn_speed = SCIFCN_SPEED; 22095c7671fSmiod #else 22195c7671fSmiod unsigned int scifcn_speed = 9600; 22295c7671fSmiod #endif 22395c7671fSmiod 22495c7671fSmiod #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 22595c7671fSmiod 22695c7671fSmiod u_int scif_rbuf_size = SCIF_RING_SIZE; 22795c7671fSmiod 228471aeecfSnaddy const struct cfattach scif_ca = { 22995c7671fSmiod sizeof(struct scif_softc), scif_match, scif_attach 23095c7671fSmiod }; 23195c7671fSmiod 23295c7671fSmiod struct cfdriver scif_cd = { 233*3836e7c7Smiod NULL, "scif", DV_DULL 23495c7671fSmiod }; 23595c7671fSmiod 23695c7671fSmiod static int scif_attached; 23795c7671fSmiod 23895c7671fSmiod void InitializeScif(unsigned int); 23995c7671fSmiod 24095c7671fSmiod /* 241b076d4fbSjsg * following functions are for debugging purposes only 24295c7671fSmiod */ 24395c7671fSmiod #define CR 0x0D 24495c7671fSmiod #define USART_ON (unsigned int)~0x08 24595c7671fSmiod 24695c7671fSmiod void scif_putc(unsigned char); 24795c7671fSmiod unsigned char scif_getc(void); 24895c7671fSmiod int ScifErrCheck(void); 24995c7671fSmiod 25095c7671fSmiod 25195c7671fSmiod /* XXX: uwe 25295c7671fSmiod * Prepare for bus_spacification. The difference in access widths is 25395c7671fSmiod * still handled by the magic definitions in scifreg.h 25495c7671fSmiod */ 25595c7671fSmiod #define scif_smr_read() SHREG_SCSMR2 25695c7671fSmiod #define scif_smr_write(v) (SHREG_SCSMR2 = (v)) 25795c7671fSmiod 25895c7671fSmiod #define scif_brr_read() SHREG_SCBRR2 25995c7671fSmiod #define scif_brr_write(v) (SHREG_SCBRR2 = (v)) 26095c7671fSmiod 26195c7671fSmiod #define scif_scr_read() SHREG_SCSCR2 26295c7671fSmiod #define scif_scr_write(v) (SHREG_SCSCR2 = (v)) 26395c7671fSmiod 26495c7671fSmiod #define scif_ftdr_write(v) (SHREG_SCFTDR2 = (v)) 26595c7671fSmiod 26695c7671fSmiod #define scif_ssr_read() SHREG_SCSSR2 26795c7671fSmiod #define scif_ssr_write(v) (SHREG_SCSSR2 = (v)) 26895c7671fSmiod 26995c7671fSmiod #define scif_frdr_read() SHREG_SCFRDR2 27095c7671fSmiod 27195c7671fSmiod #define scif_fcr_read() SHREG_SCFCR2 27295c7671fSmiod #define scif_fcr_write(v) (SHREG_SCFCR2 = (v)) 27395c7671fSmiod 27495c7671fSmiod #define scif_fdr_read() SHREG_SCFDR2 27595c7671fSmiod 27695c7671fSmiod #ifdef SH4 /* additional registers in sh4 */ 27795c7671fSmiod 27895c7671fSmiod #define scif_sptr_read() SHREG_SCSPTR2 27995c7671fSmiod #define scif_sptr_write(v) (SHREG_SCSPTR2 = (v)) 28095c7671fSmiod 28195c7671fSmiod #define scif_lsr_read() SHREG_SCLSR2 28295c7671fSmiod #define scif_lsr_write(v) (SHREG_SCLSR2 = (v)) 28395c7671fSmiod 28495c7671fSmiod #endif /* SH4 */ 28595c7671fSmiod 28695c7671fSmiod 28795c7671fSmiod /* 28895c7671fSmiod * InitializeScif 28995c7671fSmiod * : unsigned int bps; 29095c7671fSmiod * : SCIF(Serial Communication Interface) 29195c7671fSmiod */ 29295c7671fSmiod 29395c7671fSmiod void 29495c7671fSmiod InitializeScif(unsigned int bps) 29595c7671fSmiod { 29695c7671fSmiod /* Initialize SCR */ 29795c7671fSmiod scif_scr_write(0x00); 29895c7671fSmiod 29995c7671fSmiod #if 0 30095c7671fSmiod scif_fcr_write(SCFCR2_TFRST | SCFCR2_RFRST | SCFCR2_MCE); 30195c7671fSmiod #else 30295c7671fSmiod scif_fcr_write(SCFCR2_TFRST | SCFCR2_RFRST); 30395c7671fSmiod #endif 30495c7671fSmiod /* Serial Mode Register */ 30595c7671fSmiod scif_smr_write(0x00); /* 8bit,NonParity,Even,1Stop */ 30695c7671fSmiod 30795c7671fSmiod /* Bit Rate Register */ 30895c7671fSmiod scif_brr_write(divrnd(sh_clock_get_pclock(), 32 * bps) - 1); 30995c7671fSmiod 31095c7671fSmiod /* 31195c7671fSmiod * wait 2m Sec, because Send/Recv must begin 1 bit period after 31295c7671fSmiod * BRR is set. 31395c7671fSmiod */ 31495c7671fSmiod delay(2000); 31595c7671fSmiod 31695c7671fSmiod #if 0 31795c7671fSmiod scif_fcr_write(FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1 | SCFCR2_MCE); 31895c7671fSmiod #else 31995c7671fSmiod scif_fcr_write(FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1); 32095c7671fSmiod #endif 32195c7671fSmiod 32295c7671fSmiod /* Send permission, Receive permission ON */ 32395c7671fSmiod scif_scr_write(SCSCR2_TE | SCSCR2_RE); 32495c7671fSmiod 32595c7671fSmiod /* Serial Status Register */ 32695c7671fSmiod scif_ssr_write(scif_ssr_read() & SCSSR2_TDFE); /* Clear Status */ 32795c7671fSmiod } 32895c7671fSmiod 32995c7671fSmiod 33095c7671fSmiod /* 33195c7671fSmiod * scif_putc 33295c7671fSmiod * : unsigned char c; 33395c7671fSmiod */ 33495c7671fSmiod 33595c7671fSmiod void 33695c7671fSmiod scif_putc(unsigned char c) 33795c7671fSmiod { 33895c7671fSmiod /* wait for ready */ 33995c7671fSmiod while ((scif_fdr_read() & SCFDR2_TXCNT) == SCFDR2_TXF_FULL) 34095c7671fSmiod continue; 34195c7671fSmiod 34295c7671fSmiod /* write send data to send register */ 34395c7671fSmiod scif_ftdr_write(c); 34495c7671fSmiod 34595c7671fSmiod /* clear ready flag */ 34695c7671fSmiod scif_ssr_write(scif_ssr_read() & ~(SCSSR2_TDFE | SCSSR2_TEND)); 34795c7671fSmiod } 34895c7671fSmiod 34995c7671fSmiod /* 35095c7671fSmiod * : ScifErrCheck 35195c7671fSmiod * 0x80 = error 35295c7671fSmiod * 0x08 = frame error 35395c7671fSmiod * 0x04 = parity error 35495c7671fSmiod */ 35595c7671fSmiod int 35695c7671fSmiod ScifErrCheck(void) 35795c7671fSmiod { 35895c7671fSmiod return (scif_ssr_read() & (SCSSR2_ER | SCSSR2_FER | SCSSR2_PER)); 35995c7671fSmiod } 36095c7671fSmiod 36195c7671fSmiod /* 36295c7671fSmiod * scif_getc 36395c7671fSmiod */ 36495c7671fSmiod unsigned char 36595c7671fSmiod scif_getc(void) 36695c7671fSmiod { 36795c7671fSmiod unsigned char c, err_c; 36895c7671fSmiod #ifdef SH4 36995c7671fSmiod unsigned short err_c2 = 0; /* XXXGCC: -Wuninitialized */ 37095c7671fSmiod #endif 37195c7671fSmiod 37295c7671fSmiod for (;;) { 37395c7671fSmiod /* wait for ready */ 37495c7671fSmiod while ((scif_fdr_read() & SCFDR2_RECVCNT) == 0) 37595c7671fSmiod continue; 37695c7671fSmiod 37795c7671fSmiod c = scif_frdr_read(); 37895c7671fSmiod err_c = scif_ssr_read(); 37995c7671fSmiod scif_ssr_write(scif_ssr_read() 38095c7671fSmiod & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_RDF | SCSSR2_DR)); 38195c7671fSmiod #ifdef SH4 38295c7671fSmiod if (CPU_IS_SH4) { 38395c7671fSmiod err_c2 = scif_lsr_read(); 38495c7671fSmiod scif_lsr_write(scif_lsr_read() & ~SCLSR2_ORER); 38595c7671fSmiod } 38695c7671fSmiod #endif 38795c7671fSmiod if ((err_c & (SCSSR2_ER | SCSSR2_BRK | SCSSR2_FER 38895c7671fSmiod | SCSSR2_PER)) == 0) { 38995c7671fSmiod #ifdef SH4 39095c7671fSmiod if (CPU_IS_SH4 && ((err_c2 & SCLSR2_ORER) == 0)) 39195c7671fSmiod #endif 39295c7671fSmiod return(c); 39395c7671fSmiod } 39495c7671fSmiod } 39595c7671fSmiod 39695c7671fSmiod } 39795c7671fSmiod 39895c7671fSmiod int 39995c7671fSmiod scif_match(struct device *parent, void *vcf, void *aux) 40095c7671fSmiod { 40195c7671fSmiod if (scif_attached != 0) 40295c7671fSmiod return 0; 40395c7671fSmiod 40495c7671fSmiod return 1; 40595c7671fSmiod } 40695c7671fSmiod 40795c7671fSmiod void 40895c7671fSmiod scif_attach(struct device *parent, struct device *self, void *aux) 40995c7671fSmiod { 41095c7671fSmiod struct scif_softc *sc = (struct scif_softc *)self; 41195c7671fSmiod struct tty *tp; 41295c7671fSmiod 41395c7671fSmiod scif_attached = 1; 41495c7671fSmiod 41595c7671fSmiod sc->sc_hwflags = 0; /* XXX */ 41695c7671fSmiod sc->sc_swflags = 0; /* XXX */ 41795c7671fSmiod sc->sc_fifolen = 16; 41895c7671fSmiod 41995c7671fSmiod if (scifisconsole) { 42095c7671fSmiod /* InitializeScif(scifcn_speed); */ 42195c7671fSmiod SET(sc->sc_hwflags, SCIF_HW_CONSOLE); 42295c7671fSmiod SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); 42395c7671fSmiod printf("\n%s: console\n", sc->sc_dev.dv_xname); 42495c7671fSmiod } else { 42595c7671fSmiod InitializeScif(9600); 42695c7671fSmiod printf("\n"); 42795c7671fSmiod } 42895c7671fSmiod 42995c7671fSmiod timeout_set(&sc->sc_diag_tmo, scifdiag, sc); 43095c7671fSmiod #ifdef SH4 431266ce419Sdrahn intc_intr_establish(SH4_INTEVT_SCIF_ERI, IST_LEVEL, IPL_TTY, 43295c7671fSmiod scifintr, sc, self->dv_xname); 433266ce419Sdrahn intc_intr_establish(SH4_INTEVT_SCIF_RXI, IST_LEVEL, IPL_TTY, 43495c7671fSmiod scifintr, sc, self->dv_xname); 435266ce419Sdrahn intc_intr_establish(SH4_INTEVT_SCIF_BRI, IST_LEVEL, IPL_TTY, 43695c7671fSmiod scifintr, sc, self->dv_xname); 437266ce419Sdrahn intc_intr_establish(SH4_INTEVT_SCIF_TXI, IST_LEVEL, IPL_TTY, 43895c7671fSmiod scifintr, sc, self->dv_xname); 43995c7671fSmiod #else 440266ce419Sdrahn intc_intr_establish(SH7709_INTEVT2_SCIF_ERI, IST_LEVEL, IPL_TTY, 44195c7671fSmiod scifintr, sc, self->dv_xname); 442266ce419Sdrahn intc_intr_establish(SH7709_INTEVT2_SCIF_RXI, IST_LEVEL, IPL_TTY, 44395c7671fSmiod scifintr, sc, self->dv_xname); 444266ce419Sdrahn intc_intr_establish(SH7709_INTEVT2_SCIF_BRI, IST_LEVEL, IPL_TTY, 44595c7671fSmiod scifintr, sc, self->dv_xname); 446266ce419Sdrahn intc_intr_establish(SH7709_INTEVT2_SCIF_TXI, IST_LEVEL, IPL_TTY, 44795c7671fSmiod scifintr, sc, self->dv_xname); 44895c7671fSmiod #endif 44995c7671fSmiod 45095c7671fSmiod sc->sc_si = softintr_establish(IPL_SOFTSERIAL, scifsoft, sc); 45195c7671fSmiod SET(sc->sc_hwflags, SCIF_HW_DEV_OK); 45295c7671fSmiod 453197ff252Sderaadt tp = ttymalloc(0); 45495c7671fSmiod tp->t_oproc = scifstart; 45595c7671fSmiod tp->t_param = scifparam; 45695c7671fSmiod tp->t_hwiflow = NULL; 45795c7671fSmiod 45895c7671fSmiod sc->sc_tty = tp; 45995c7671fSmiod sc->sc_rbuf = malloc(scif_rbuf_size << 1, M_DEVBUF, M_NOWAIT); 46095c7671fSmiod if (sc->sc_rbuf == NULL) { 46195c7671fSmiod printf("%s: unable to allocate ring buffer\n", 46295c7671fSmiod sc->sc_dev.dv_xname); 46395c7671fSmiod return; 46495c7671fSmiod } 46595c7671fSmiod sc->sc_ebuf = sc->sc_rbuf + (scif_rbuf_size << 1); 46695c7671fSmiod } 46795c7671fSmiod 46895c7671fSmiod /* 46995c7671fSmiod * Start or restart transmission. 47095c7671fSmiod */ 47195c7671fSmiod void 47295c7671fSmiod scifstart(struct tty *tp) 47395c7671fSmiod { 47495c7671fSmiod struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; 47595c7671fSmiod int s; 47695c7671fSmiod 47795c7671fSmiod s = spltty(); 47895c7671fSmiod if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 47995c7671fSmiod goto out; 48095c7671fSmiod if (sc->sc_tx_stopped) 48195c7671fSmiod goto out; 48295c7671fSmiod 4834cc8800eSnicm ttwakeupwr(tp); 48495c7671fSmiod if (tp->t_outq.c_cc == 0) 48595c7671fSmiod goto out; 48695c7671fSmiod 48795c7671fSmiod /* Grab the first contiguous region of buffer space. */ 48895c7671fSmiod { 48995c7671fSmiod u_char *tba; 49095c7671fSmiod int tbc; 49195c7671fSmiod 49295c7671fSmiod tba = tp->t_outq.c_cf; 49395c7671fSmiod tbc = ndqb(&tp->t_outq, 0); 49495c7671fSmiod 49595c7671fSmiod 49695c7671fSmiod sc->sc_tba = tba; 49795c7671fSmiod sc->sc_tbc = tbc; 49895c7671fSmiod } 49995c7671fSmiod 50095c7671fSmiod SET(tp->t_state, TS_BUSY); 50195c7671fSmiod sc->sc_tx_busy = 1; 50295c7671fSmiod 50395c7671fSmiod /* Enable transmit completion interrupts if necessary. */ 50495c7671fSmiod scif_scr_write(scif_scr_read() | SCSCR2_TIE | SCSCR2_RIE); 50595c7671fSmiod 50695c7671fSmiod /* Output the first chunk of the contiguous buffer. */ 50795c7671fSmiod { 50895c7671fSmiod int n; 50995c7671fSmiod int maxchars; 51095c7671fSmiod int i; 51195c7671fSmiod 51295c7671fSmiod n = sc->sc_tbc; 51395c7671fSmiod maxchars = sc->sc_fifolen 51495c7671fSmiod - ((scif_fdr_read() & SCFDR2_TXCNT) >> 8); 51595c7671fSmiod if (n > maxchars) 51695c7671fSmiod n = maxchars; 51795c7671fSmiod 51895c7671fSmiod for (i = 0; i < n; i++) { 51995c7671fSmiod scif_putc(*(sc->sc_tba)); 52095c7671fSmiod sc->sc_tba++; 52195c7671fSmiod } 52295c7671fSmiod sc->sc_tbc -= n; 52395c7671fSmiod } 52495c7671fSmiod out: 52595c7671fSmiod splx(s); 52695c7671fSmiod return; 52795c7671fSmiod } 52895c7671fSmiod 52995c7671fSmiod /* 53095c7671fSmiod * Set SCIF tty parameters from termios. 53195c7671fSmiod * XXX - Should just copy the whole termios after 53295c7671fSmiod * making sure all the changes could be done. 53395c7671fSmiod */ 53495c7671fSmiod int 53595c7671fSmiod scifparam(struct tty *tp, struct termios *t) 53695c7671fSmiod { 53795c7671fSmiod struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; 53895c7671fSmiod int ospeed = t->c_ospeed; 53995c7671fSmiod int s; 54095c7671fSmiod 54195c7671fSmiod /* Check requested parameters. */ 54295c7671fSmiod if (ospeed < 0) 54395c7671fSmiod return (EINVAL); 54495c7671fSmiod if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 54595c7671fSmiod return (EINVAL); 54695c7671fSmiod 54795c7671fSmiod /* 54895c7671fSmiod * For the console, always force CLOCAL and !HUPCL, so that the port 54995c7671fSmiod * is always active. 55095c7671fSmiod */ 55195c7671fSmiod if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 55295c7671fSmiod ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) { 55395c7671fSmiod SET(t->c_cflag, CLOCAL); 55495c7671fSmiod CLR(t->c_cflag, HUPCL); 55595c7671fSmiod } 55695c7671fSmiod 55795c7671fSmiod /* 55895c7671fSmiod * If there were no changes, don't do anything. This avoids dropping 55995c7671fSmiod * input and improves performance when all we did was frob things like 56095c7671fSmiod * VMIN and VTIME. 56195c7671fSmiod */ 56295c7671fSmiod if (tp->t_ospeed == t->c_ospeed && 56395c7671fSmiod tp->t_cflag == t->c_cflag) 56495c7671fSmiod return (0); 56595c7671fSmiod 56695c7671fSmiod #if 0 56795c7671fSmiod /* XXX (msaitoh) */ 56895c7671fSmiod lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); 56995c7671fSmiod #endif 57095c7671fSmiod 571266ce419Sdrahn s = spltty(); 57295c7671fSmiod 57395c7671fSmiod /* 57495c7671fSmiod * Set the flow control pins depending on the current flow control 57595c7671fSmiod * mode. 57695c7671fSmiod */ 57795c7671fSmiod if (ISSET(t->c_cflag, CRTSCTS)) { 57895c7671fSmiod scif_fcr_write(scif_fcr_read() | SCFCR2_MCE); 57995c7671fSmiod } else { 58095c7671fSmiod scif_fcr_write(scif_fcr_read() & ~SCFCR2_MCE); 58195c7671fSmiod } 58295c7671fSmiod 58395c7671fSmiod scif_brr_write(divrnd(sh_clock_get_pclock(), 32 * ospeed) -1); 58495c7671fSmiod 58595c7671fSmiod /* 58695c7671fSmiod * Set the FIFO threshold based on the receive speed. 58795c7671fSmiod * 58895c7671fSmiod * * If it's a low speed, it's probably a mouse or some other 58995c7671fSmiod * interactive device, so set the threshold low. 59095c7671fSmiod * * If it's a high speed, trim the trigger level down to prevent 59195c7671fSmiod * overflows. 59295c7671fSmiod * * Otherwise set it a bit higher. 59395c7671fSmiod */ 59495c7671fSmiod #if 0 59595c7671fSmiod /* XXX (msaitoh) */ 59695c7671fSmiod if (ISSET(sc->sc_hwflags, SCIF_HW_HAYESP)) 59795c7671fSmiod sc->sc_fifo = FIFO_DMA_MODE | FIFO_ENABLE | FIFO_TRIGGER_8; 59895c7671fSmiod else if (ISSET(sc->sc_hwflags, SCIF_HW_FIFO)) 59995c7671fSmiod sc->sc_fifo = FIFO_ENABLE | 60095c7671fSmiod (t->c_ospeed <= 1200 ? FIFO_TRIGGER_1 : 60195c7671fSmiod t->c_ospeed <= 38400 ? FIFO_TRIGGER_8 : FIFO_TRIGGER_4); 60295c7671fSmiod else 60395c7671fSmiod sc->sc_fifo = 0; 60495c7671fSmiod #endif 60595c7671fSmiod 60695c7671fSmiod /* And copy to tty. */ 60795c7671fSmiod tp->t_ispeed = 0; 60895c7671fSmiod tp->t_ospeed = t->c_ospeed; 60995c7671fSmiod tp->t_cflag = t->c_cflag; 61095c7671fSmiod 61195c7671fSmiod if (!sc->sc_heldchange) { 61295c7671fSmiod if (sc->sc_tx_busy) { 61395c7671fSmiod sc->sc_heldtbc = sc->sc_tbc; 61495c7671fSmiod sc->sc_tbc = 0; 61595c7671fSmiod sc->sc_heldchange = 1; 61695c7671fSmiod } 61795c7671fSmiod #if 0 61895c7671fSmiod /* XXX (msaitoh) */ 61995c7671fSmiod else 62095c7671fSmiod scif_loadchannelregs(sc); 62195c7671fSmiod #endif 62295c7671fSmiod } 62395c7671fSmiod 62495c7671fSmiod if (!ISSET(t->c_cflag, CHWFLOW)) { 62595c7671fSmiod /* Disable the high water mark. */ 62695c7671fSmiod sc->sc_r_hiwat = 0; 62795c7671fSmiod sc->sc_r_lowat = 0; 62895c7671fSmiod if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) { 62995c7671fSmiod CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 63095c7671fSmiod scif_schedrx(sc); 63195c7671fSmiod } 63295c7671fSmiod } else { 63395c7671fSmiod sc->sc_r_hiwat = scif_rbuf_hiwat; 63495c7671fSmiod sc->sc_r_lowat = scif_rbuf_lowat; 63595c7671fSmiod } 63695c7671fSmiod 63795c7671fSmiod splx(s); 63895c7671fSmiod 63995c7671fSmiod #ifdef SCIF_DEBUG 64095c7671fSmiod if (scif_debug) 64195c7671fSmiod scifstatus(sc, "scifparam "); 64295c7671fSmiod #endif 64395c7671fSmiod 64495c7671fSmiod if (!ISSET(t->c_cflag, CHWFLOW)) { 64595c7671fSmiod if (sc->sc_tx_stopped) { 64695c7671fSmiod sc->sc_tx_stopped = 0; 64795c7671fSmiod scifstart(tp); 64895c7671fSmiod } 64995c7671fSmiod } 65095c7671fSmiod 65195c7671fSmiod return (0); 65295c7671fSmiod } 65395c7671fSmiod 65495c7671fSmiod void 65595c7671fSmiod scif_iflush(struct scif_softc *sc) 65695c7671fSmiod { 65795c7671fSmiod int i; 65895c7671fSmiod unsigned char c; 65995c7671fSmiod 66095c7671fSmiod i = scif_fdr_read() & SCFDR2_RECVCNT; 66195c7671fSmiod 66295c7671fSmiod while (i > 0) { 66395c7671fSmiod c = scif_frdr_read(); 66495c7671fSmiod scif_ssr_write(scif_ssr_read() & ~(SCSSR2_RDF | SCSSR2_DR)); 66595c7671fSmiod i--; 66695c7671fSmiod } 66795c7671fSmiod } 66895c7671fSmiod 66995c7671fSmiod int 67095c7671fSmiod scifopen(dev_t dev, int flag, int mode, struct proc *p) 67195c7671fSmiod { 67295c7671fSmiod int unit = SCIFUNIT(dev); 67395c7671fSmiod struct scif_softc *sc; 67495c7671fSmiod struct tty *tp; 675266ce419Sdrahn int s; 67695c7671fSmiod int error; 67795c7671fSmiod 67895c7671fSmiod if (unit >= scif_cd.cd_ndevs) 67995c7671fSmiod return (ENXIO); 68095c7671fSmiod sc = scif_cd.cd_devs[unit]; 68195c7671fSmiod if (sc == 0 || !ISSET(sc->sc_hwflags, SCIF_HW_DEV_OK) || 68295c7671fSmiod sc->sc_rbuf == NULL) 68395c7671fSmiod return (ENXIO); 68495c7671fSmiod 68595c7671fSmiod tp = sc->sc_tty; 68695c7671fSmiod 68795c7671fSmiod if (ISSET(tp->t_state, TS_ISOPEN) && 68895c7671fSmiod ISSET(tp->t_state, TS_XCLUDE) && 6893e676399Smpi suser(p) != 0) 69095c7671fSmiod return (EBUSY); 69195c7671fSmiod 69295c7671fSmiod s = spltty(); 69395c7671fSmiod 69495c7671fSmiod /* 69595c7671fSmiod * Do the following iff this is a first open. 69695c7671fSmiod */ 69795c7671fSmiod if (!ISSET(tp->t_state, TS_ISOPEN)) { 69895c7671fSmiod struct termios t; 69995c7671fSmiod 70095c7671fSmiod tp->t_dev = dev; 70195c7671fSmiod 70295c7671fSmiod 70395c7671fSmiod /* Turn on interrupts. */ 70495c7671fSmiod scif_scr_write(scif_scr_read() | SCSCR2_TIE | SCSCR2_RIE); 70595c7671fSmiod 70695c7671fSmiod /* 70795c7671fSmiod * Initialize the termios status to the defaults. Add in the 70895c7671fSmiod * sticky bits from TIOCSFLAGS. 70995c7671fSmiod */ 71095c7671fSmiod t.c_ispeed = 0; 71195c7671fSmiod if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) { 71295c7671fSmiod t.c_ospeed = scifcn_speed; /* XXX (msaitoh) */ 71395c7671fSmiod t.c_cflag = scifconscflag; 71495c7671fSmiod } else { 71595c7671fSmiod t.c_ospeed = TTYDEF_SPEED; 71695c7671fSmiod t.c_cflag = TTYDEF_CFLAG; 71795c7671fSmiod } 71895c7671fSmiod if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 71995c7671fSmiod SET(t.c_cflag, CLOCAL); 72095c7671fSmiod if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 72195c7671fSmiod SET(t.c_cflag, CRTSCTS); 72295c7671fSmiod if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 72395c7671fSmiod SET(t.c_cflag, MDMBUF); 72495c7671fSmiod /* Make sure scifparam() will do something. */ 72595c7671fSmiod tp->t_ospeed = 0; 72695c7671fSmiod (void) scifparam(tp, &t); 72716da585eSderaadt 72816da585eSderaadt /* 72916da585eSderaadt * XXX landisk has no hardware flow control! 73016da585eSderaadt * When porting to another platform, fix this somehow 73116da585eSderaadt */ 73216da585eSderaadt SET(tp->t_state, TS_CARR_ON); 73316da585eSderaadt 73495c7671fSmiod tp->t_iflag = TTYDEF_IFLAG; 73595c7671fSmiod tp->t_oflag = TTYDEF_OFLAG; 73695c7671fSmiod tp->t_lflag = TTYDEF_LFLAG; 73795c7671fSmiod ttychars(tp); 73895c7671fSmiod ttsetwater(tp); 73995c7671fSmiod 74095c7671fSmiod /* Clear the input ring, and unblock. */ 74195c7671fSmiod sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 74295c7671fSmiod sc->sc_rbavail = scif_rbuf_size; 74395c7671fSmiod scif_iflush(sc); 74495c7671fSmiod CLR(sc->sc_rx_flags, RX_ANY_BLOCK); 74595c7671fSmiod #if 0 74695c7671fSmiod /* XXX (msaitoh) */ 74795c7671fSmiod scif_hwiflow(sc); 74895c7671fSmiod #endif 74995c7671fSmiod 75095c7671fSmiod #ifdef SCIF_DEBUG 75195c7671fSmiod if (scif_debug) 75295c7671fSmiod scifstatus(sc, "scifopen "); 75395c7671fSmiod #endif 75495c7671fSmiod 75595c7671fSmiod } 75695c7671fSmiod 75795c7671fSmiod splx(s); 75895c7671fSmiod 75979f6c33aStedu error = (*linesw[tp->t_line].l_open)(dev, tp, p); 76095c7671fSmiod if (error) 76195c7671fSmiod goto bad; 76295c7671fSmiod 76395c7671fSmiod return (0); 76495c7671fSmiod 76595c7671fSmiod bad: 76695c7671fSmiod 76795c7671fSmiod return (error); 76895c7671fSmiod } 76995c7671fSmiod 77095c7671fSmiod int 77195c7671fSmiod scifclose(dev_t dev, int flag, int mode, struct proc *p) 77295c7671fSmiod { 77395c7671fSmiod struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 77495c7671fSmiod struct tty *tp = sc->sc_tty; 77595c7671fSmiod 77695c7671fSmiod /* XXX This is for cons.c. */ 77795c7671fSmiod if (!ISSET(tp->t_state, TS_ISOPEN)) 77895c7671fSmiod return (0); 77995c7671fSmiod 78079f6c33aStedu (*linesw[tp->t_line].l_close)(tp, flag, p); 78195c7671fSmiod ttyclose(tp); 78295c7671fSmiod 78395c7671fSmiod return (0); 78495c7671fSmiod } 78595c7671fSmiod 78695c7671fSmiod int 78795c7671fSmiod scifread(dev_t dev, struct uio *uio, int flag) 78895c7671fSmiod { 78995c7671fSmiod struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 79095c7671fSmiod struct tty *tp = sc->sc_tty; 79195c7671fSmiod 79295c7671fSmiod return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 79395c7671fSmiod } 79495c7671fSmiod 79595c7671fSmiod int 79695c7671fSmiod scifwrite(dev_t dev, struct uio *uio, int flag) 79795c7671fSmiod { 79895c7671fSmiod struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 79995c7671fSmiod struct tty *tp = sc->sc_tty; 80095c7671fSmiod 80195c7671fSmiod return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 80295c7671fSmiod } 80395c7671fSmiod 80495c7671fSmiod struct tty * 80595c7671fSmiod sciftty(dev_t dev) 80695c7671fSmiod { 80795c7671fSmiod struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 80895c7671fSmiod struct tty *tp = sc->sc_tty; 80995c7671fSmiod 81095c7671fSmiod return (tp); 81195c7671fSmiod } 81295c7671fSmiod 81395c7671fSmiod int 81495c7671fSmiod scifioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 81595c7671fSmiod { 81695c7671fSmiod struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 81795c7671fSmiod struct tty *tp = sc->sc_tty; 81895c7671fSmiod int error; 81995c7671fSmiod int s; 82095c7671fSmiod 82195c7671fSmiod error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 82295c7671fSmiod if (error != -1) 82395c7671fSmiod return (error); 82495c7671fSmiod 82595c7671fSmiod error = ttioctl(tp, cmd, data, flag, p); 82695c7671fSmiod if (error != -1) 82795c7671fSmiod return (error); 82895c7671fSmiod 82995c7671fSmiod error = 0; 83095c7671fSmiod 831266ce419Sdrahn s = spltty(); 83295c7671fSmiod 83395c7671fSmiod switch (cmd) { 83495c7671fSmiod case TIOCSBRK: 83595c7671fSmiod scif_break(sc, 1); 83695c7671fSmiod break; 83795c7671fSmiod 83895c7671fSmiod case TIOCCBRK: 83995c7671fSmiod scif_break(sc, 0); 84095c7671fSmiod break; 84195c7671fSmiod 84295c7671fSmiod case TIOCGFLAGS: 84395c7671fSmiod *(int *)data = sc->sc_swflags; 84495c7671fSmiod break; 84595c7671fSmiod 84695c7671fSmiod case TIOCSFLAGS: 8473e676399Smpi error = suser(p); 84895c7671fSmiod if (error) 84995c7671fSmiod break; 85095c7671fSmiod sc->sc_swflags = *(int *)data; 85195c7671fSmiod break; 85295c7671fSmiod 85395c7671fSmiod default: 85495c7671fSmiod error = -1; 85595c7671fSmiod break; 85695c7671fSmiod } 85795c7671fSmiod 85895c7671fSmiod splx(s); 85995c7671fSmiod 86095c7671fSmiod return (error); 86195c7671fSmiod } 86295c7671fSmiod 86395c7671fSmiod void 86495c7671fSmiod scif_schedrx(struct scif_softc *sc) 86595c7671fSmiod { 86695c7671fSmiod sc->sc_rx_ready = 1; 86795c7671fSmiod 86895c7671fSmiod /* Wake up the poller. */ 86995c7671fSmiod softintr_schedule(sc->sc_si); 87095c7671fSmiod } 87195c7671fSmiod 87295c7671fSmiod void 87395c7671fSmiod scif_break(struct scif_softc *sc, int onoff) 87495c7671fSmiod { 87595c7671fSmiod if (onoff) 87695c7671fSmiod scif_ssr_write(scif_ssr_read() & ~SCSSR2_TDFE); 87795c7671fSmiod else 87895c7671fSmiod scif_ssr_write(scif_ssr_read() | SCSSR2_TDFE); 87995c7671fSmiod 88095c7671fSmiod #if 0 /* XXX */ 88195c7671fSmiod if (!sc->sc_heldchange) { 88295c7671fSmiod if (sc->sc_tx_busy) { 88395c7671fSmiod sc->sc_heldtbc = sc->sc_tbc; 88495c7671fSmiod sc->sc_tbc = 0; 88595c7671fSmiod sc->sc_heldchange = 1; 88695c7671fSmiod } else 88795c7671fSmiod scif_loadchannelregs(sc); 88895c7671fSmiod } 88995c7671fSmiod #endif 89095c7671fSmiod } 89195c7671fSmiod 89295c7671fSmiod /* 89395c7671fSmiod * Stop output, e.g., for ^S or output flush. 89495c7671fSmiod */ 89595c7671fSmiod int 89695c7671fSmiod scifstop(struct tty *tp, int flag) 89795c7671fSmiod { 89895c7671fSmiod struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; 89995c7671fSmiod int s; 90095c7671fSmiod 901266ce419Sdrahn s = spltty(); 90295c7671fSmiod if (ISSET(tp->t_state, TS_BUSY)) { 90395c7671fSmiod /* Stop transmitting at the next chunk. */ 90495c7671fSmiod sc->sc_tbc = 0; 90595c7671fSmiod sc->sc_heldtbc = 0; 90695c7671fSmiod if (!ISSET(tp->t_state, TS_TTSTOP)) 90795c7671fSmiod SET(tp->t_state, TS_FLUSH); 90895c7671fSmiod } 90995c7671fSmiod splx(s); 91095c7671fSmiod return (0); 91195c7671fSmiod } 91295c7671fSmiod 91395c7671fSmiod void 9140f1d1626Stobiasu scif_intr_init(void) 91595c7671fSmiod { 91695c7671fSmiod /* XXX */ 91795c7671fSmiod } 91895c7671fSmiod 91995c7671fSmiod void 92095c7671fSmiod scifdiag(void *arg) 92195c7671fSmiod { 92295c7671fSmiod struct scif_softc *sc = arg; 92395c7671fSmiod int overflows, floods; 92495c7671fSmiod int s; 92595c7671fSmiod 926266ce419Sdrahn s = spltty(); 92795c7671fSmiod overflows = sc->sc_overflows; 92895c7671fSmiod sc->sc_overflows = 0; 92995c7671fSmiod floods = sc->sc_floods; 93095c7671fSmiod sc->sc_floods = 0; 93195c7671fSmiod sc->sc_errors = 0; 93295c7671fSmiod splx(s); 93395c7671fSmiod 93495c7671fSmiod log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n", 93595c7671fSmiod sc->sc_dev.dv_xname, 93695c7671fSmiod overflows, overflows == 1 ? "" : "s", 93795c7671fSmiod floods, floods == 1 ? "" : "s"); 93895c7671fSmiod } 93995c7671fSmiod 94095c7671fSmiod void 94195c7671fSmiod scif_rxsoft(struct scif_softc *sc, struct tty *tp) 94295c7671fSmiod { 94395c7671fSmiod int (*rint)(int, struct tty *) = *linesw[tp->t_line].l_rint; 94495c7671fSmiod u_char *get, *end; 94595c7671fSmiod u_int cc, scc; 94695c7671fSmiod u_char ssr2; 94795c7671fSmiod int code; 94895c7671fSmiod int s; 94995c7671fSmiod 95095c7671fSmiod end = sc->sc_ebuf; 95195c7671fSmiod get = sc->sc_rbget; 95295c7671fSmiod scc = cc = scif_rbuf_size - sc->sc_rbavail; 95395c7671fSmiod 95495c7671fSmiod if (cc == scif_rbuf_size) { 95595c7671fSmiod sc->sc_floods++; 95695c7671fSmiod if (sc->sc_errors++ == 0) 95729e86e5eSblambert timeout_add_sec(&sc->sc_diag_tmo, 60); 95895c7671fSmiod } 95995c7671fSmiod 96095c7671fSmiod while (cc) { 96195c7671fSmiod code = get[0]; 96295c7671fSmiod ssr2 = get[1]; 96395c7671fSmiod if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER | SCSSR2_PER)) { 96495c7671fSmiod if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER)) 96595c7671fSmiod SET(code, TTY_FE); 96695c7671fSmiod if (ISSET(ssr2, SCSSR2_PER)) 96795c7671fSmiod SET(code, TTY_PE); 96895c7671fSmiod } 96995c7671fSmiod if ((*rint)(code, tp) == -1) { 97095c7671fSmiod /* 97195c7671fSmiod * The line discipline's buffer is out of space. 97295c7671fSmiod */ 97395c7671fSmiod if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 97495c7671fSmiod /* 97595c7671fSmiod * We're either not using flow control, or the 97695c7671fSmiod * line discipline didn't tell us to block for 97795c7671fSmiod * some reason. Either way, we have no way to 97895c7671fSmiod * know when there's more space available, so 97995c7671fSmiod * just drop the rest of the data. 98095c7671fSmiod */ 98195c7671fSmiod get += cc << 1; 98295c7671fSmiod if (get >= end) 98395c7671fSmiod get -= scif_rbuf_size << 1; 98495c7671fSmiod cc = 0; 98595c7671fSmiod } else { 98695c7671fSmiod /* 98795c7671fSmiod * Don't schedule any more receive processing 98895c7671fSmiod * until the line discipline tells us there's 98995c7671fSmiod * space available (through scifhwiflow()). 99095c7671fSmiod * Leave the rest of the data in the input 99195c7671fSmiod * buffer. 99295c7671fSmiod */ 99395c7671fSmiod SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 99495c7671fSmiod } 99595c7671fSmiod break; 99695c7671fSmiod } 99795c7671fSmiod get += 2; 99895c7671fSmiod if (get >= end) 99995c7671fSmiod get = sc->sc_rbuf; 100095c7671fSmiod cc--; 100195c7671fSmiod } 100295c7671fSmiod 100395c7671fSmiod if (cc != scc) { 100495c7671fSmiod sc->sc_rbget = get; 1005266ce419Sdrahn s = spltty(); 100695c7671fSmiod cc = sc->sc_rbavail += scc - cc; 100795c7671fSmiod /* Buffers should be ok again, release possible block. */ 100895c7671fSmiod if (cc >= sc->sc_r_lowat) { 100995c7671fSmiod if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 101095c7671fSmiod CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 101195c7671fSmiod scif_scr_write(scif_scr_read() | SCSCR2_RIE); 101295c7671fSmiod } 101395c7671fSmiod #if 0 101495c7671fSmiod if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) { 101595c7671fSmiod CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED); 101695c7671fSmiod scif_hwiflow(sc); 101795c7671fSmiod } 101895c7671fSmiod #endif 101995c7671fSmiod } 102095c7671fSmiod splx(s); 102195c7671fSmiod } 102295c7671fSmiod } 102395c7671fSmiod 102495c7671fSmiod void 102595c7671fSmiod scif_txsoft(struct scif_softc *sc, struct tty *tp) 102695c7671fSmiod { 102795c7671fSmiod CLR(tp->t_state, TS_BUSY); 102895c7671fSmiod if (ISSET(tp->t_state, TS_FLUSH)) 102995c7671fSmiod CLR(tp->t_state, TS_FLUSH); 103095c7671fSmiod else 103195c7671fSmiod ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); 103295c7671fSmiod (*linesw[tp->t_line].l_start)(tp); 103395c7671fSmiod } 103495c7671fSmiod 103595c7671fSmiod void 103695c7671fSmiod scif_stsoft(struct scif_softc *sc, struct tty *tp) 103795c7671fSmiod { 103895c7671fSmiod #if 0 103995c7671fSmiod /* XXX (msaitoh) */ 104095c7671fSmiod u_char msr, delta; 104195c7671fSmiod int s; 104295c7671fSmiod 1043266ce419Sdrahn s = spltty(); 104495c7671fSmiod msr = sc->sc_msr; 104595c7671fSmiod delta = sc->sc_msr_delta; 104695c7671fSmiod sc->sc_msr_delta = 0; 104795c7671fSmiod splx(s); 104895c7671fSmiod 104995c7671fSmiod if (ISSET(delta, sc->sc_msr_dcd)) { 105095c7671fSmiod /* 105195c7671fSmiod * Inform the tty layer that carrier detect changed. 105295c7671fSmiod */ 105395c7671fSmiod (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)); 105495c7671fSmiod } 105595c7671fSmiod 105695c7671fSmiod if (ISSET(delta, sc->sc_msr_cts)) { 105795c7671fSmiod /* Block or unblock output according to flow control. */ 105895c7671fSmiod if (ISSET(msr, sc->sc_msr_cts)) { 105995c7671fSmiod sc->sc_tx_stopped = 0; 106095c7671fSmiod (*linesw[tp->t_line].l_start)(tp); 106195c7671fSmiod } else { 106295c7671fSmiod sc->sc_tx_stopped = 1; 106395c7671fSmiod } 106495c7671fSmiod } 106595c7671fSmiod 106695c7671fSmiod #ifdef SCIF_DEBUG 106795c7671fSmiod if (scif_debug) 106895c7671fSmiod scifstatus(sc, "scif_stsoft"); 106995c7671fSmiod #endif 107095c7671fSmiod #endif 107195c7671fSmiod } 107295c7671fSmiod 107395c7671fSmiod void 107495c7671fSmiod scifsoft(void *arg) 107595c7671fSmiod { 107695c7671fSmiod struct scif_softc *sc = arg; 107795c7671fSmiod struct tty *tp; 107895c7671fSmiod 107995c7671fSmiod tp = sc->sc_tty; 108095c7671fSmiod 108195c7671fSmiod if (sc->sc_rx_ready) { 108295c7671fSmiod sc->sc_rx_ready = 0; 108395c7671fSmiod scif_rxsoft(sc, tp); 108495c7671fSmiod } 108595c7671fSmiod 108695c7671fSmiod #if 0 108795c7671fSmiod if (sc->sc_st_check) { 108895c7671fSmiod sc->sc_st_check = 0; 108995c7671fSmiod scif_stsoft(sc, tp); 109095c7671fSmiod } 109195c7671fSmiod #endif 109295c7671fSmiod 109395c7671fSmiod if (sc->sc_tx_done) { 109495c7671fSmiod sc->sc_tx_done = 0; 109595c7671fSmiod scif_txsoft(sc, tp); 109695c7671fSmiod } 109795c7671fSmiod } 109895c7671fSmiod 109995c7671fSmiod int 110095c7671fSmiod scifintr(void *arg) 110195c7671fSmiod { 110295c7671fSmiod struct scif_softc *sc = arg; 110395c7671fSmiod u_char *put, *end; 110495c7671fSmiod u_int cc; 110595c7671fSmiod u_short ssr2; 110695c7671fSmiod int count; 110795c7671fSmiod 110895c7671fSmiod end = sc->sc_ebuf; 110995c7671fSmiod put = sc->sc_rbput; 111095c7671fSmiod cc = sc->sc_rbavail; 111195c7671fSmiod 111295c7671fSmiod do { 111395c7671fSmiod ssr2 = scif_ssr_read(); 111495c7671fSmiod if (ISSET(ssr2, SCSSR2_BRK)) { 111595c7671fSmiod scif_ssr_write(scif_ssr_read() 111695c7671fSmiod & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_DR)); 111795c7671fSmiod #ifdef DDB 111895c7671fSmiod if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE) && 111995c7671fSmiod db_console != 0) { 1120e97088d6Smpi db_enter(); 112195c7671fSmiod } 112295c7671fSmiod #endif /* DDB */ 112395c7671fSmiod } 112495c7671fSmiod count = scif_fdr_read() & SCFDR2_RECVCNT; 112595c7671fSmiod if (count != 0) { 112695c7671fSmiod for (;;) { 112795c7671fSmiod u_char c = scif_frdr_read(); 112895c7671fSmiod u_char err = (u_char)(scif_ssr_read() & 0x00ff); 112995c7671fSmiod 113095c7671fSmiod scif_ssr_write(scif_ssr_read() 113195c7671fSmiod & ~(SCSSR2_ER | SCSSR2_RDF | SCSSR2_DR)); 113295c7671fSmiod #ifdef SH4 113395c7671fSmiod if (CPU_IS_SH4) 113495c7671fSmiod scif_lsr_write(scif_lsr_read() 113595c7671fSmiod & ~SCLSR2_ORER); 113695c7671fSmiod #endif 113795c7671fSmiod if ((cc > 0) && (count > 0)) { 113895c7671fSmiod put[0] = c; 113995c7671fSmiod put[1] = err; 114095c7671fSmiod put += 2; 114195c7671fSmiod if (put >= end) 114295c7671fSmiod put = sc->sc_rbuf; 114395c7671fSmiod cc--; 114495c7671fSmiod count--; 114595c7671fSmiod } else 114695c7671fSmiod break; 114795c7671fSmiod } 114895c7671fSmiod 114995c7671fSmiod /* 115095c7671fSmiod * Current string of incoming characters ended because 115195c7671fSmiod * no more data was available or we ran out of space. 115295c7671fSmiod * Schedule a receive event if any data was received. 115395c7671fSmiod * If we're out of space, turn off receive interrupts. 115495c7671fSmiod */ 115595c7671fSmiod sc->sc_rbput = put; 115695c7671fSmiod sc->sc_rbavail = cc; 115795c7671fSmiod if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) 115895c7671fSmiod sc->sc_rx_ready = 1; 115995c7671fSmiod 116095c7671fSmiod /* 116195c7671fSmiod * See if we are in danger of overflowing a buffer. If 116295c7671fSmiod * so, use hardware flow control to ease the pressure. 116395c7671fSmiod */ 116495c7671fSmiod if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) && 116595c7671fSmiod cc < sc->sc_r_hiwat) { 116695c7671fSmiod SET(sc->sc_rx_flags, RX_IBUF_BLOCKED); 116795c7671fSmiod #if 0 116895c7671fSmiod scif_hwiflow(sc); 116995c7671fSmiod #endif 117095c7671fSmiod } 117195c7671fSmiod 117295c7671fSmiod /* 117395c7671fSmiod * If we're out of space, disable receive interrupts 117495c7671fSmiod * until the queue has drained a bit. 117595c7671fSmiod */ 117695c7671fSmiod if (!cc) { 117795c7671fSmiod SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 117895c7671fSmiod scif_scr_write(scif_scr_read() & ~SCSCR2_RIE); 117995c7671fSmiod } 118095c7671fSmiod } else { 118195c7671fSmiod if (scif_ssr_read() & (SCSSR2_RDF | SCSSR2_DR)) { 118295c7671fSmiod scif_scr_write(scif_scr_read() 118395c7671fSmiod & ~(SCSCR2_TIE | SCSCR2_RIE)); 118495c7671fSmiod delay(10); 118595c7671fSmiod scif_scr_write(scif_scr_read() 118695c7671fSmiod | SCSCR2_TIE | SCSCR2_RIE); 118795c7671fSmiod continue; 118895c7671fSmiod } 118995c7671fSmiod } 119095c7671fSmiod } while (scif_ssr_read() & (SCSSR2_RDF | SCSSR2_DR)); 119195c7671fSmiod 119295c7671fSmiod #if 0 119395c7671fSmiod msr = bus_space_read_1(iot, ioh, scif_msr); 119495c7671fSmiod delta = msr ^ sc->sc_msr; 119595c7671fSmiod sc->sc_msr = msr; 119695c7671fSmiod if (ISSET(delta, sc->sc_msr_mask)) { 119795c7671fSmiod SET(sc->sc_msr_delta, delta); 119895c7671fSmiod 119995c7671fSmiod /* 120095c7671fSmiod * Pulse-per-second clock signal on edge of DCD? 120195c7671fSmiod */ 120295c7671fSmiod if (ISSET(delta, sc->sc_ppsmask)) { 120395c7671fSmiod struct timeval tv; 120495c7671fSmiod if (ISSET(msr, sc->sc_ppsmask) == 120595c7671fSmiod sc->sc_ppsassert) { 120695c7671fSmiod /* XXX nanotime() */ 120795c7671fSmiod microtime(&tv); 120895c7671fSmiod TIMEVAL_TO_TIMESPEC(&tv, 120995c7671fSmiod &sc->ppsinfo.assert_timestamp); 121095c7671fSmiod if (sc->ppsparam.mode & PPS_OFFSETASSERT) { 121195c7671fSmiod timespecadd(&sc->ppsinfo.assert_timestamp, 121295c7671fSmiod &sc->ppsparam.assert_offset, 121395c7671fSmiod &sc->ppsinfo.assert_timestamp); 121495c7671fSmiod TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.assert_timestamp); 121595c7671fSmiod } 121695c7671fSmiod 121795c7671fSmiod #ifdef PPS_SYNC 121895c7671fSmiod if (sc->ppsparam.mode & PPS_HARDPPSONASSERT) 121995c7671fSmiod hardpps(&tv, tv.tv_usec); 122095c7671fSmiod #endif 122195c7671fSmiod sc->ppsinfo.assert_sequence++; 122295c7671fSmiod sc->ppsinfo.current_mode = 122395c7671fSmiod sc->ppsparam.mode; 122495c7671fSmiod 122595c7671fSmiod } else if (ISSET(msr, sc->sc_ppsmask) == 122695c7671fSmiod sc->sc_ppsclear) { 122795c7671fSmiod /* XXX nanotime() */ 122895c7671fSmiod microtime(&tv); 122995c7671fSmiod TIMEVAL_TO_TIMESPEC(&tv, 123095c7671fSmiod &sc->ppsinfo.clear_timestamp); 123195c7671fSmiod if (sc->ppsparam.mode & PPS_OFFSETCLEAR) { 123295c7671fSmiod timespecadd(&sc->ppsinfo.clear_timestamp, 123395c7671fSmiod &sc->ppsparam.clear_offset, 123495c7671fSmiod &sc->ppsinfo.clear_timestamp); 123595c7671fSmiod TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.clear_timestamp); 123695c7671fSmiod } 123795c7671fSmiod 123895c7671fSmiod #ifdef PPS_SYNC 123995c7671fSmiod if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR) 124095c7671fSmiod hardpps(&tv, tv.tv_usec); 124195c7671fSmiod #endif 124295c7671fSmiod sc->ppsinfo.clear_sequence++; 124395c7671fSmiod sc->ppsinfo.current_mode = 124495c7671fSmiod sc->ppsparam.mode; 124595c7671fSmiod } 124695c7671fSmiod } 124795c7671fSmiod 124895c7671fSmiod /* 124995c7671fSmiod * Stop output immediately if we lose the output 125095c7671fSmiod * flow control signal or carrier detect. 125195c7671fSmiod */ 125295c7671fSmiod if (ISSET(~msr, sc->sc_msr_mask)) { 125395c7671fSmiod sc->sc_tbc = 0; 125495c7671fSmiod sc->sc_heldtbc = 0; 125595c7671fSmiod #ifdef SCIF_DEBUG 125695c7671fSmiod if (scif_debug) 125795c7671fSmiod scifstatus(sc, "scifintr "); 125895c7671fSmiod #endif 125995c7671fSmiod } 126095c7671fSmiod 126195c7671fSmiod sc->sc_st_check = 1; 126295c7671fSmiod } 126395c7671fSmiod #endif 126495c7671fSmiod 126595c7671fSmiod /* 126695c7671fSmiod * Done handling any receive interrupts. See if data can be 126795c7671fSmiod * transmitted as well. Schedule tx done event if no data left 126895c7671fSmiod * and tty was marked busy. 126995c7671fSmiod */ 127095c7671fSmiod if (((scif_fdr_read() & SCFDR2_TXCNT) >> 8) != 16) { /* XXX (msaitoh) */ 127195c7671fSmiod /* 127295c7671fSmiod * If we've delayed a parameter change, do it now, and restart 127395c7671fSmiod * output. 127495c7671fSmiod */ 127595c7671fSmiod if (sc->sc_heldchange) { 127695c7671fSmiod sc->sc_heldchange = 0; 127795c7671fSmiod sc->sc_tbc = sc->sc_heldtbc; 127895c7671fSmiod sc->sc_heldtbc = 0; 127995c7671fSmiod } 128095c7671fSmiod 128195c7671fSmiod /* Output the next chunk of the contiguous buffer, if any. */ 128295c7671fSmiod if (sc->sc_tbc > 0) { 128395c7671fSmiod int n; 128495c7671fSmiod int maxchars; 128595c7671fSmiod int i; 128695c7671fSmiod 128795c7671fSmiod n = sc->sc_tbc; 128895c7671fSmiod maxchars = sc->sc_fifolen - 128995c7671fSmiod ((scif_fdr_read() & SCFDR2_TXCNT) >> 8); 129095c7671fSmiod if (n > maxchars) 129195c7671fSmiod n = maxchars; 129295c7671fSmiod 129395c7671fSmiod for (i = 0; i < n; i++) { 129495c7671fSmiod scif_putc(*(sc->sc_tba)); 129595c7671fSmiod sc->sc_tba++; 129695c7671fSmiod } 129795c7671fSmiod sc->sc_tbc -= n; 129895c7671fSmiod } else { 129995c7671fSmiod /* Disable transmit completion interrupts if necessary. */ 130095c7671fSmiod #if 0 130195c7671fSmiod if (ISSET(sc->sc_ier, IER_ETXRDY)) 130295c7671fSmiod #endif 130395c7671fSmiod scif_scr_write(scif_scr_read() & ~SCSCR2_TIE); 130495c7671fSmiod 130595c7671fSmiod if (sc->sc_tx_busy) { 130695c7671fSmiod sc->sc_tx_busy = 0; 130795c7671fSmiod sc->sc_tx_done = 1; 130895c7671fSmiod } 130995c7671fSmiod } 131095c7671fSmiod } 131195c7671fSmiod 131295c7671fSmiod /* Wake up the poller. */ 131395c7671fSmiod softintr_schedule(sc->sc_si); 131495c7671fSmiod 131595c7671fSmiod return (1); 131695c7671fSmiod } 131795c7671fSmiod 131895c7671fSmiod void 131995c7671fSmiod scifcnprobe(struct consdev *cp) 132095c7671fSmiod { 132195c7671fSmiod int maj; 132295c7671fSmiod 132395c7671fSmiod /* locate the major number */ 132495c7671fSmiod for (maj = 0; maj < nchrdev; maj++) 132595c7671fSmiod if (cdevsw[maj].d_open == scifopen) 132695c7671fSmiod break; 132795c7671fSmiod 132895c7671fSmiod cp->cn_dev = makedev(maj, 0); 132995c7671fSmiod #ifdef SCIFCONSOLE 1330713cf266Sjsing cp->cn_pri = CN_HIGHPRI; 133195c7671fSmiod #else 1332713cf266Sjsing cp->cn_pri = CN_LOWPRI; 133395c7671fSmiod #endif 133495c7671fSmiod } 133595c7671fSmiod 133695c7671fSmiod void 133795c7671fSmiod scifcninit(struct consdev *cp) 133895c7671fSmiod { 133995c7671fSmiod InitializeScif(scifcn_speed); 134095c7671fSmiod scifisconsole = 1; 134195c7671fSmiod } 134295c7671fSmiod 134395c7671fSmiod int 134495c7671fSmiod scifcngetc(dev_t dev) 134595c7671fSmiod { 134695c7671fSmiod int c; 134795c7671fSmiod int s; 134895c7671fSmiod 1349266ce419Sdrahn s = spltty(); 135095c7671fSmiod c = scif_getc(); 135195c7671fSmiod splx(s); 135295c7671fSmiod 135395c7671fSmiod return (c); 135495c7671fSmiod } 135595c7671fSmiod 135695c7671fSmiod void 135795c7671fSmiod scifcnputc(dev_t dev, int c) 135895c7671fSmiod { 135995c7671fSmiod int s; 136095c7671fSmiod 1361266ce419Sdrahn s = spltty(); 136295c7671fSmiod scif_putc((u_char)c); 136395c7671fSmiod splx(s); 136495c7671fSmiod } 1365