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