1 1.11 thorpej /* $NetBSD: scn.c,v 1.11 2023/12/20 15:29:07 thorpej Exp $ */ 2 1.1 rumble 3 1.1 rumble /* 4 1.1 rumble * Resurrected from the old pc532 port 1/18/2009. 5 1.1 rumble * 6 1.1 rumble * XXX- The locking in this is probably totally broken. I haven't attempted 7 1.1 rumble * to get it right, but it seems to work okay anyhow. 8 1.1 rumble */ 9 1.1 rumble 10 1.1 rumble /* 11 1.1 rumble * Copyright (c) 1991, 1992, 1993 12 1.1 rumble * The Regents of the University of California. All rights reserved. 13 1.1 rumble * 14 1.1 rumble * Portions of this software were developed by the Computer Systems 15 1.1 rumble * Engineering group at Lawrence Berkeley Laboratory under DARPA 16 1.1 rumble * contract BG 91-66 and contributed to Berkeley. 17 1.1 rumble * 18 1.1 rumble * All advertising materials mentioning features or use of this software 19 1.1 rumble * must display the following acknowledgement: 20 1.1 rumble * This product includes software developed by the University of 21 1.1 rumble * California, Lawrence Berkeley Laboratory. 22 1.1 rumble * 23 1.1 rumble * Redistribution and use in source and binary forms, with or without 24 1.1 rumble * modification, are permitted provided that the following conditions 25 1.1 rumble * are met: 26 1.1 rumble * 1. Redistributions of source code must retain the above copyright 27 1.1 rumble * notice, this list of conditions and the following disclaimer. 28 1.1 rumble * 2. Redistributions in binary form must reproduce the above copyright 29 1.1 rumble * notice, this list of conditions and the following disclaimer in the 30 1.1 rumble * documentation and/or other materials provided with the distribution. 31 1.1 rumble * 3. Neither the name of the University nor the names of its contributors 32 1.1 rumble * may be used to endorse or promote products derived from this software 33 1.1 rumble * without specific prior written permission. 34 1.1 rumble * 35 1.1 rumble * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 36 1.1 rumble * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 1.1 rumble * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38 1.1 rumble * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 39 1.1 rumble * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 40 1.1 rumble * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 41 1.1 rumble * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 1.1 rumble * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43 1.1 rumble * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 1.1 rumble * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 1.1 rumble * SUCH DAMAGE. 46 1.1 rumble * 47 1.1 rumble * from: @(#)com.c 7.5 (Berkeley) 5/16/91 48 1.1 rumble */ 49 1.1 rumble 50 1.1 rumble /* 51 1.1 rumble * Copyright (c) 1996, 1997 Philip L. Budne. 52 1.1 rumble * Copyright (c) 1993 Philip A. Nelson. 53 1.1 rumble * 54 1.1 rumble * Portions of this software were developed by the Computer Systems 55 1.1 rumble * Engineering group at Lawrence Berkeley Laboratory under DARPA 56 1.1 rumble * contract BG 91-66 and contributed to Berkeley. 57 1.1 rumble * 58 1.1 rumble * All advertising materials mentioning features or use of this software 59 1.1 rumble * must display the following acknowledgement: 60 1.1 rumble * This product includes software developed by the University of 61 1.1 rumble * California, Lawrence Berkeley Laboratory. 62 1.1 rumble * 63 1.1 rumble * Redistribution and use in source and binary forms, with or without 64 1.1 rumble * modification, are permitted provided that the following conditions 65 1.1 rumble * are met: 66 1.1 rumble * 1. Redistributions of source code must retain the above copyright 67 1.1 rumble * notice, this list of conditions and the following disclaimer. 68 1.1 rumble * 2. Redistributions in binary form must reproduce the above copyright 69 1.1 rumble * notice, this list of conditions and the following disclaimer in the 70 1.1 rumble * documentation and/or other materials provided with the distribution. 71 1.1 rumble * 3. All advertising materials mentioning features or use of this software 72 1.1 rumble * must display the following acknowledgement: 73 1.1 rumble * This product includes software developed by the University of 74 1.1 rumble * California, Berkeley and its contributors. 75 1.1 rumble * 4. Neither the name of the University nor the names of its contributors 76 1.1 rumble * may be used to endorse or promote products derived from this software 77 1.1 rumble * without specific prior written permission. 78 1.1 rumble * 79 1.1 rumble * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 80 1.1 rumble * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 81 1.1 rumble * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 82 1.1 rumble * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 83 1.1 rumble * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 84 1.1 rumble * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 85 1.1 rumble * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 86 1.1 rumble * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 87 1.1 rumble * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 88 1.1 rumble * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 89 1.1 rumble * SUCH DAMAGE. 90 1.1 rumble * 91 1.1 rumble * from: @(#)com.c 7.5 (Berkeley) 5/16/91 92 1.1 rumble */ 93 1.1 rumble 94 1.1 rumble #include <sys/cdefs.h> 95 1.11 thorpej __KERNEL_RCSID(0, "$NetBSD: scn.c,v 1.11 2023/12/20 15:29:07 thorpej Exp $"); 96 1.1 rumble 97 1.1 rumble #include "opt_ddb.h" 98 1.1 rumble #include "opt_kgdb.h" 99 1.1 rumble #include "scn.h" 100 1.1 rumble 101 1.1 rumble #include <sys/param.h> 102 1.1 rumble #include <sys/systm.h> 103 1.1 rumble #include <sys/ioctl.h> 104 1.1 rumble #include <sys/select.h> 105 1.1 rumble #include <sys/tty.h> 106 1.1 rumble #include <sys/proc.h> 107 1.1 rumble #include <sys/file.h> 108 1.1 rumble #include <sys/uio.h> 109 1.1 rumble #include <sys/kernel.h> 110 1.1 rumble #include <sys/syslog.h> 111 1.1 rumble #include <sys/types.h> 112 1.1 rumble #include <sys/device.h> 113 1.1 rumble #include <sys/conf.h> 114 1.1 rumble #include <sys/intr.h> 115 1.1 rumble #ifdef KGDB 116 1.1 rumble #include <sys/kgdb.h> 117 1.1 rumble #endif 118 1.1 rumble #include <sys/kauth.h> 119 1.1 rumble 120 1.1 rumble #include <dev/cons.h> 121 1.1 rumble 122 1.1 rumble #include <machine/autoconf.h> 123 1.1 rumble #include <machine/machtype.h> 124 1.1 rumble 125 1.1 rumble #include <sgimips/dev/scnreg.h> 126 1.1 rumble #include <sgimips/dev/scnvar.h> 127 1.1 rumble 128 1.1 rumble int scn_match(device_t, struct cfdata *, void *); 129 1.1 rumble void scn_attach(device_t, device_t, void *); 130 1.1 rumble int scnparam(struct tty *, struct termios *); 131 1.1 rumble void scnstart(struct tty *); 132 1.1 rumble int scnhwiflow(struct tty *, int); 133 1.1 rumble 134 1.1 rumble void scncnprobe(struct consdev *); 135 1.1 rumble void scncninit(struct consdev *); 136 1.1 rumble int scncngetc(dev_t); 137 1.1 rumble void scncnputc(dev_t, int); 138 1.1 rumble void scncnpollc(dev_t, int); 139 1.1 rumble int scninit(dev_t, int); 140 1.1 rumble void scncnreinit(void *); 141 1.1 rumble 142 1.4 chs CFATTACH_DECL_NEW(scn, sizeof(struct scn_softc), 143 1.1 rumble scn_match, scn_attach, NULL, NULL); 144 1.1 rumble 145 1.1 rumble extern struct cfdriver scn_cd; 146 1.1 rumble 147 1.1 rumble dev_type_open(scnopen); 148 1.1 rumble dev_type_close(scnclose); 149 1.1 rumble dev_type_read(scnread); 150 1.1 rumble dev_type_write(scnwrite); 151 1.1 rumble dev_type_ioctl(scnioctl); 152 1.1 rumble dev_type_stop(scnstop); 153 1.1 rumble dev_type_tty(scntty); 154 1.1 rumble dev_type_poll(scnpoll); 155 1.1 rumble 156 1.1 rumble const struct cdevsw scn_cdevsw = { 157 1.5 dholland .d_open = scnopen, 158 1.5 dholland .d_close = scnclose, 159 1.5 dholland .d_read = scnread, 160 1.5 dholland .d_write = scnwrite, 161 1.5 dholland .d_ioctl = scnioctl, 162 1.5 dholland .d_stop = scnstop, 163 1.5 dholland .d_tty = scntty, 164 1.5 dholland .d_poll = scnpoll, 165 1.5 dholland .d_mmap = nommap, 166 1.5 dholland .d_kqfilter = ttykqfilter, 167 1.7 dholland .d_discard = nodiscard, 168 1.5 dholland .d_flag = D_TTY 169 1.1 rumble }; 170 1.1 rumble 171 1.1 rumble struct consdev scn_cn = { 172 1.1 rumble scncnprobe, 173 1.1 rumble scncninit, 174 1.1 rumble scncngetc, 175 1.1 rumble scncnputc, 176 1.1 rumble scncnpollc, 177 1.1 rumble NULL, 178 1.1 rumble NULL, 179 1.1 rumble NULL, 180 1.1 rumble NODEV, 181 1.1 rumble CN_NORMAL 182 1.1 rumble }; 183 1.1 rumble 184 1.1 rumble #ifndef CONSOLE_SPEED 185 1.1 rumble #define CONSOLE_SPEED TTYDEF_SPEED 186 1.1 rumble #endif 187 1.1 rumble 188 1.1 rumble #ifndef SCNDEF_CFLAG 189 1.1 rumble #define SCNDEF_CFLAG TTYDEF_CFLAG 190 1.1 rumble #endif 191 1.1 rumble 192 1.1 rumble #ifdef CPU30MHZ 193 1.1 rumble #define RECOVER() __asm volatile("bispsrw 0x800" : : : "cc") 194 1.1 rumble #else 195 1.1 rumble #define RECOVER() 196 1.1 rumble #endif 197 1.1 rumble 198 1.1 rumble int scndefaultrate = TTYDEF_SPEED; 199 1.1 rumble int scnconsrate = CONSOLE_SPEED; 200 1.1 rumble 201 1.1 rumble static inline struct scn_softc * 202 1.1 rumble SOFTC(int unit) 203 1.1 rumble { 204 1.1 rumble if (unit < 0 || unit >= scn_cd.cd_ndevs) 205 1.1 rumble return (NULL); 206 1.4 chs return device_private(scn_cd.cd_devs[unit]); 207 1.1 rumble } 208 1.1 rumble 209 1.1 rumble static int scnintr(void *); 210 1.1 rumble static void scnrxintr(void *); 211 1.1 rumble static int scn_rxintr(struct scn_softc *); 212 1.1 rumble static void scnsoft(void *); 213 1.1 rumble static void scn_setchip(struct scn_softc *sc); 214 1.1 rumble static int scniter(int *, int, int*, int*, struct chan *, int); 215 1.1 rumble static int scn_config(int, int, int, int, u_char, u_char); 216 1.1 rumble static void scn_rxenable(struct scn_softc *); 217 1.1 rumble static void scn_rxdisable(struct scn_softc *); 218 1.1 rumble static void dcd_int(struct scn_softc *, struct tty *, u_char); 219 1.1 rumble static void scnoverrun(int, long *, const char *); 220 1.1 rumble static u_char opbits(struct scn_softc *, int); 221 1.1 rumble 222 1.1 rumble static void *scnsir = NULL; /* s/w intr cookie */ 223 1.1 rumble #define setsoftscn() softint_schedule(scnsir) 224 1.1 rumble 225 1.1 rumble #ifdef SCN_TIMING 226 1.1 rumble /* 227 1.1 rumble * Keep timing info on latency of software interrupt used by 228 1.1 rumble * the ringbuf code to empty ring buffer. 229 1.1 rumble * "getinfo" program reads data from /dev/kmem. 230 1.1 rumble */ 231 1.1 rumble static struct timeval tstart; 232 1.1 rumble #define NJITTER 100 233 1.1 rumble int scn_njitter = NJITTER; 234 1.1 rumble int scn_jitter[NJITTER]; 235 1.1 rumble #endif 236 1.1 rumble 237 1.1 rumble #define SCN_CLOCK 3686400 /* input clock */ 238 1.1 rumble 239 1.1 rumble /* speed table groups ACR[7] */ 240 1.1 rumble #define GRP_A 0 241 1.1 rumble #define GRP_B ACR_BRG 242 1.1 rumble 243 1.1 rumble /* combo of MR0[2:0] and ACR[7] */ 244 1.1 rumble #define MODE0A MR0_MODE_0 245 1.1 rumble #define MODE0B (MR0_MODE_0|ACR_BRG) 246 1.1 rumble #define MODE1A MR0_MODE_1 247 1.1 rumble #define MODE1B (MR0_MODE_1|ACR_BRG) 248 1.1 rumble #define MODE2A MR0_MODE_2 249 1.1 rumble #define MODE2B (MR0_MODE_2|ACR_BRG) 250 1.1 rumble 251 1.1 rumble #define ANYMODE -1 252 1.1 rumble #define DEFMODE(C92) MODE0A /* use MODE4A if 26c92? */ 253 1.1 rumble 254 1.1 rumble /* speed code for Counter/Timer (all modes, groups) */ 255 1.1 rumble #define USE_CT 0xd 256 1.1 rumble 257 1.1 rumble /* 258 1.1 rumble * Rate table, ordered by speed, then mode. 259 1.1 rumble * NOTE: ordering of modes must be done carefully! 260 1.1 rumble */ 261 1.1 rumble struct tabent { 262 1.1 rumble int32_t speed; 263 1.1 rumble int16_t code; 264 1.1 rumble int16_t mode; 265 1.1 rumble } table[] = { 266 1.1 rumble { 50, 0x0, MODE0A }, 267 1.1 rumble { 75, 0x0, MODE0B }, 268 1.1 rumble { 110, 0x1, MODE0A }, 269 1.1 rumble { 110, 0x1, MODE0B }, 270 1.1 rumble { 110, 0x1, MODE1A }, 271 1.1 rumble { 110, 0x1, MODE1B }, 272 1.1 rumble { 134, 0x2, MODE0A }, /* 134.5 */ 273 1.1 rumble { 134, 0x2, MODE0B }, /* 134.5 */ 274 1.1 rumble { 134, 0x2, MODE1A }, /* 134.5 */ 275 1.1 rumble { 134, 0x2, MODE1B }, /* 134.5 */ 276 1.1 rumble { 150, 0x3, MODE0A }, 277 1.1 rumble { 150, 0x3, MODE0A }, 278 1.1 rumble { 200, 0x3, MODE0A }, 279 1.1 rumble { 300, 0x4, MODE0A }, 280 1.1 rumble { 300, 0x4, MODE0B }, 281 1.1 rumble { 300, 0x0, MODE1A }, 282 1.1 rumble { 450, 0x0, MODE1B }, 283 1.1 rumble { 600, 0x5, MODE0A }, 284 1.1 rumble { 600, 0x5, MODE0B }, 285 1.1 rumble { 880, 0x1, MODE2A }, 286 1.1 rumble { 880, 0x1, MODE2B }, 287 1.1 rumble { 900, 0x3, MODE1B }, 288 1.1 rumble { 1050, 0x7, MODE0A }, 289 1.1 rumble { 1050, 0x7, MODE1A }, 290 1.1 rumble { 1076, 0x2, MODE2A }, 291 1.1 rumble { 1076, 0x2, MODE2B }, 292 1.1 rumble { 1200, 0x6, MODE0A }, 293 1.1 rumble { 1200, 0x6, MODE0B }, 294 1.1 rumble { 1200, 0x3, MODE1A }, 295 1.1 rumble { 1800, 0xa, MODE0B }, 296 1.1 rumble { 1800, 0x4, MODE1A }, 297 1.1 rumble { 1800, 0x4, MODE1B }, 298 1.1 rumble { 2000, 0x7, MODE0B }, 299 1.1 rumble { 2000, 0x7, MODE1B }, 300 1.1 rumble { 2400, 0x8, MODE0A }, 301 1.1 rumble { 2400, 0x8, MODE0B }, 302 1.1 rumble { 3600, 0x5, MODE1A }, 303 1.1 rumble { 3600, 0x5, MODE1B }, 304 1.1 rumble { 4800, 0x9, MODE2A }, 305 1.1 rumble { 4800, 0x9, MODE2B }, 306 1.1 rumble { 4800, 0x9, MODE0A }, 307 1.1 rumble { 4800, 0x9, MODE0B }, 308 1.1 rumble { 7200, 0xa, MODE0A }, 309 1.1 rumble { 7200, 0x0, MODE2B }, 310 1.1 rumble { 7200, 0x6, MODE1A }, 311 1.1 rumble { 7200, 0x6, MODE1B }, 312 1.1 rumble { 9600, 0xb, MODE2A }, 313 1.1 rumble { 9600, 0xb, MODE2B }, 314 1.1 rumble { 9600, 0xb, MODE0A }, 315 1.1 rumble { 9600, 0xb, MODE0B }, 316 1.1 rumble { 9600, 0xd, MODE1A }, /* use C/T as entre' to mode1 */ 317 1.1 rumble { 9600, 0xd, MODE1B }, /* use C/T as entre' to mode1 */ 318 1.1 rumble { 14400, 0x3, MODE2B }, 319 1.1 rumble { 14400, 0x8, MODE1A }, 320 1.1 rumble { 14400, 0x8, MODE1B }, 321 1.1 rumble { 19200, 0x3, MODE2A }, 322 1.1 rumble { 19200, 0xc, MODE2B }, 323 1.1 rumble { 19200, 0xc, MODE0B }, 324 1.1 rumble { 19200, 0xd, MODE1A }, /* use C/T as entre' to mode1 */ 325 1.1 rumble { 19200, 0xd, MODE1B }, /* use C/T as entre' to mode1 */ 326 1.1 rumble { 28800, 0x4, MODE2A }, 327 1.1 rumble { 28800, 0x4, MODE2B }, 328 1.1 rumble { 28800, 0x9, MODE1A }, 329 1.1 rumble { 28800, 0x9, MODE1B }, 330 1.1 rumble { 38400, 0xc, MODE2A }, 331 1.1 rumble { 38400, 0xc, MODE0A }, 332 1.1 rumble { 57600, 0x5, MODE2A }, 333 1.1 rumble { 57600, 0x5, MODE2B }, 334 1.1 rumble { 57600, 0xb, MODE1A }, 335 1.1 rumble { 57600, 0xb, MODE1B }, 336 1.1 rumble { 115200, 0x6, MODE2A }, 337 1.1 rumble { 115200, 0x6, MODE2B }, 338 1.1 rumble { 115200, 0xc, MODE1B }, 339 1.1 rumble { 230400, 0xc, MODE1A } 340 1.1 rumble }; 341 1.1 rumble #define TABENTRIES (sizeof(table)/sizeof(table[0])) 342 1.1 rumble 343 1.1 rumble /* 344 1.1 rumble * boolean for speed codes which are identical in both A/B BRG groups 345 1.1 rumble * in all modes 346 1.1 rumble */ 347 1.1 rumble static u_char bothgroups[16] = { 348 1.1 rumble 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1 349 1.1 rumble }; 350 1.1 rumble 351 1.1 rumble /* 352 1.1 rumble * Manually constructed divisors table 353 1.1 rumble * for minimum error (from some of Dave Rand's code) 354 1.1 rumble */ 355 1.1 rumble const struct { 356 1.1 rumble uint16_t speed; 357 1.1 rumble uint16_t div; 358 1.1 rumble } divs[] = { 359 1.1 rumble { 50, 2303 }, /* 2304 is exact?? */ 360 1.1 rumble { 110, 1047 }, /* Should be 1047.27 */ 361 1.1 rumble { 134, 857 }, /* Should be 856.505576 */ 362 1.1 rumble { 1050, 110 }, /* Should be 109.7142857 */ 363 1.1 rumble { 2000, 57 } /* Should be 57.6 */ 364 1.1 rumble }; 365 1.1 rumble #define DIVS (sizeof(divs)/sizeof(divs[0])) 366 1.1 rumble 367 1.1 rumble /* 368 1.1 rumble * minor unit bit decode: 369 1.1 rumble * CxxxUUU 370 1.1 rumble * 371 1.1 rumble * C - carrier 372 1.1 rumble * 0 - delay open until carrier high 373 1.1 rumble * 1 - allow open with carrier low 374 1.1 rumble * UUU - unit 0-7 375 1.1 rumble */ 376 1.1 rumble 377 1.1 rumble #define DEV_UNIT(x) (minor(x) & 0x7) 378 1.1 rumble #define DEV_DIALOUT(x) (minor(x) & 0x80) 379 1.1 rumble 380 1.1 rumble #define SCN_MAXDUART 4 381 1.1 rumble static struct duart scn_duart[SCN_MAXDUART]; 382 1.1 rumble 383 1.1 rumble #ifdef KGDB 384 1.1 rumble extern int kgdb_dev; 385 1.1 rumble extern int kgdb_rate; 386 1.1 rumble extern int kgdb_debug_init; 387 1.1 rumble #endif 388 1.1 rumble 389 1.1 rumble /* XXXXX - fix this */ 390 1.1 rumble #define splrtty() spltty() 391 1.1 rumble 392 1.1 rumble /* RS-232 configuration routines */ 393 1.1 rumble 394 1.1 rumble /* 395 1.1 rumble * set chip parameters, or mark for delayed change. 396 1.1 rumble * called at spltty() or on TxEMPTY interrupt. 397 1.1 rumble * 398 1.1 rumble * Reads current values to avoid glitches from redundant sets. 399 1.1 rumble * Perhaps should save last value set to avoid read/write? NOTE: 400 1.1 rumble * Would still need to do read if write not needed to advance MR 401 1.1 rumble * pointer. 402 1.1 rumble * 403 1.1 rumble * new 2/97 -plb 404 1.1 rumble */ 405 1.1 rumble 406 1.1 rumble static void 407 1.1 rumble scn_setchip(struct scn_softc *sc) 408 1.1 rumble { 409 1.1 rumble struct duart *dp; 410 1.1 rumble u_char acr, csr, mr1, mr2; 411 1.1 rumble int chan; 412 1.1 rumble 413 1.1 rumble if (sc->sc_tty && (sc->sc_tty->t_state & TS_BUSY)) { 414 1.1 rumble sc->sc_heldchanges = 1; 415 1.1 rumble return; 416 1.1 rumble } 417 1.1 rumble 418 1.1 rumble chan = sc->sc_channel; 419 1.1 rumble dp = sc->sc_duart; 420 1.1 rumble if (dp->type == SC26C92) { 421 1.1 rumble u_char nmr0a, mr0a; 422 1.1 rumble 423 1.1 rumble /* input rate high enough so 64 bit time watchdog not 424 1.1 rumble * onerous? */ 425 1.1 rumble if (dp->chan[chan].ispeed >= 1200) { 426 1.1 rumble /* set FIFO threshold at 6 for other 427 1.1 rumble * thresholds we could have to set MR1_FFULL 428 1.1 rumble */ 429 1.1 rumble dp->chan[chan].mr0 |= MR0_RXWD | MR0_RXINT; 430 1.1 rumble } else { 431 1.1 rumble dp->chan[chan].mr0 &= ~(MR0_RXWD | MR0_RXINT); 432 1.1 rumble } 433 1.1 rumble 434 1.1 rumble /* select BRG mode (MR0A only) */ 435 1.1 rumble nmr0a = dp->chan[0].mr0 | (dp->mode & MR0_MODE); 436 1.1 rumble 437 1.1 rumble dp->base[CH_CR] = CR_CMD_MR0; 438 1.1 rumble RECOVER(); 439 1.1 rumble 440 1.1 rumble mr0a = dp->base[CH_MR]; 441 1.1 rumble if (mr0a != nmr0a) { 442 1.1 rumble dp->base[CH_CR] = CR_CMD_MR0; 443 1.1 rumble RECOVER(); 444 1.1 rumble dp->base[CH_MR] = nmr0a; 445 1.1 rumble } 446 1.1 rumble 447 1.1 rumble if (chan) { /* channel B? */ 448 1.1 rumble u_char mr0b; 449 1.1 rumble 450 1.1 rumble sc->sc_chbase[CH_CR] = CR_CMD_MR0; 451 1.1 rumble RECOVER(); 452 1.1 rumble mr0b = dp->base[CH_MR]; 453 1.1 rumble 454 1.1 rumble if (dp->chan[chan].mr0 != mr0b) { 455 1.1 rumble sc->sc_chbase[CH_CR] = CR_CMD_MR0; 456 1.1 rumble RECOVER(); 457 1.1 rumble sc->sc_chbase[CH_MR] = dp->chan[chan].mr0; 458 1.1 rumble } 459 1.1 rumble } 460 1.1 rumble } else { 461 1.1 rumble sc->sc_chbase[CH_CR] = CR_CMD_MR1; 462 1.1 rumble RECOVER(); 463 1.1 rumble } 464 1.1 rumble 465 1.1 rumble mr1 = sc->sc_chbase[CH_MR]; 466 1.1 rumble mr2 = sc->sc_chbase[CH_MR]; 467 1.1 rumble if (mr1 != dp->chan[chan].new_mr1 || 468 1.1 rumble mr2 != dp->chan[chan].new_mr2) { 469 1.1 rumble sc->sc_chbase[CH_CR] = CR_CMD_MR1; 470 1.1 rumble RECOVER(); 471 1.1 rumble sc->sc_chbase[CH_MR] = dp->chan[chan].new_mr1; 472 1.1 rumble sc->sc_chbase[CH_MR] = dp->chan[chan].new_mr2; 473 1.1 rumble } 474 1.1 rumble 475 1.1 rumble acr = dp->acr | (dp->mode & ACR_BRG); 476 1.1 rumble dp->base[DU_ACR] = acr; /* write-only reg! */ 477 1.1 rumble 478 1.1 rumble /* set speed codes */ 479 1.1 rumble csr = (dp->chan[chan].icode<<4) | dp->chan[chan].ocode; 480 1.1 rumble if (sc->sc_chbase[CH_CSR] != csr) { 481 1.1 rumble sc->sc_chbase[CH_CSR] = csr; 482 1.1 rumble } 483 1.1 rumble 484 1.1 rumble /* see if counter/timer in use */ 485 1.1 rumble if (dp->counter && 486 1.1 rumble (dp->chan[0].icode == USE_CT || dp->chan[0].ocode == USE_CT || 487 1.1 rumble dp->chan[1].icode == USE_CT || dp->chan[1].ocode == USE_CT)) { 488 1.1 rumble 489 1.1 rumble /* program counter/timer only if necessary */ 490 1.1 rumble if (dp->counter != dp->ocounter) { 491 1.1 rumble uint16_t div; 492 1.1 rumble #ifdef DIVS 493 1.1 rumble int i; 494 1.1 rumble 495 1.1 rumble /* look for precalculated rate, for minimum error */ 496 1.1 rumble for (i = 0; i < DIVS && divs[i].speed <= dp->counter; i++) { 497 1.1 rumble if (divs[i].speed == dp->counter) { 498 1.1 rumble div = divs[i].div; 499 1.1 rumble goto found; 500 1.1 rumble } 501 1.1 rumble } 502 1.1 rumble #endif 503 1.1 rumble 504 1.1 rumble /* not found in table; calculate a value (rounding up) */ 505 1.1 rumble div = ((long)SCN_CLOCK/16/2 + dp->counter/2) / dp->counter; 506 1.1 rumble 507 1.1 rumble found: 508 1.1 rumble /* halt before loading? may ALWAYS glitch? 509 1.1 rumble * reload race may only sometimes glitch?? 510 1.1 rumble */ 511 1.1 rumble dp->base[DU_CTUR] = div >> 8; 512 1.1 rumble dp->base[DU_CTLR] = div & 255; 513 1.1 rumble if (dp->ocounter == 0) { 514 1.1 rumble /* not previously used? */ 515 1.1 rumble u_char temp; 516 1.1 rumble /* start C/T running */ 517 1.1 rumble temp = dp->base[DU_CSTRT]; 518 1.6 christos __USE(temp); 519 1.1 rumble } 520 1.1 rumble dp->ocounter = dp->counter; 521 1.1 rumble } 522 1.1 rumble } else { 523 1.1 rumble /* counter not in use; mark as free */ 524 1.1 rumble dp->counter = 0; 525 1.1 rumble } 526 1.1 rumble sc->sc_heldchanges = 0; 527 1.1 rumble 528 1.1 rumble /* 529 1.1 rumble * delay a tiny bit to try and avoid tx glitching. 530 1.1 rumble * I know we're at spltty(), but this is much better than the 531 1.1 rumble * old version used DELAY((96000 / out_speed) * 10000) 532 1.1 rumble * -plb 533 1.1 rumble */ 534 1.1 rumble DELAY(10); 535 1.1 rumble } 536 1.1 rumble 537 1.1 rumble /* 538 1.1 rumble * iterator function for speeds. 539 1.1 rumble * (could be called "findnextcode") 540 1.1 rumble * Returns sequence of possible speed codes for a given rate. 541 1.1 rumble * should set index to zero before first call. 542 1.1 rumble * 543 1.1 rumble * Could be implemented as a "checkspeed()" function called 544 1.1 rumble * to evaluate table entries, BUT this allows more variety in 545 1.1 rumble * use of C/T with fewer table entries. 546 1.1 rumble */ 547 1.1 rumble 548 1.1 rumble static int 549 1.1 rumble scniter(int *index, int wanted, int *counter, int *mode, struct chan *other, 550 1.1 rumble int c92) 551 1.1 rumble { 552 1.1 rumble 553 1.1 rumble while (*index < TABENTRIES) { 554 1.1 rumble struct tabent *tp; 555 1.1 rumble 556 1.1 rumble tp = table + (*index)++; 557 1.1 rumble if (tp->speed != wanted) 558 1.1 rumble continue; 559 1.1 rumble 560 1.1 rumble /* if not a 26C92 only look at MODE0 entries */ 561 1.1 rumble if (!c92 && (tp->mode & MR0_MODE) != MR0_MODE_0) 562 1.1 rumble continue; 563 1.1 rumble 564 1.1 rumble /* 565 1.1 rumble * check mode; 566 1.1 rumble * OK if this table entry for current mode, or mode not 567 1.1 rumble * yet set, or other channel's rates are available in both 568 1.1 rumble * A and B groups. 569 1.1 rumble */ 570 1.1 rumble 571 1.1 rumble if (tp->mode == *mode || *mode == ANYMODE || 572 1.1 rumble (other != NULL && (tp->mode & MR0_MODE) == (*mode & MR0_MODE) && 573 1.1 rumble bothgroups[other->icode] && bothgroups[other->ocode])) { 574 1.1 rumble /* 575 1.1 rumble * for future table entries specifying 576 1.1 rumble * use of counter/timer 577 1.1 rumble */ 578 1.1 rumble if (tp->code == USE_CT) { 579 1.1 rumble if (*counter != wanted && *counter != 0) 580 1.1 rumble continue; /* counter busy */ 581 1.1 rumble *counter = wanted; 582 1.1 rumble } 583 1.1 rumble *mode = tp->mode; 584 1.1 rumble return tp->code; 585 1.1 rumble } 586 1.1 rumble } 587 1.1 rumble 588 1.1 rumble /* here after returning all applicable table entries */ 589 1.1 rumble /* XXX return sequence of USE_CT with all possible modes?? */ 590 1.1 rumble if ((*index)++ == TABENTRIES) { 591 1.1 rumble /* Max C/T rate (even on 26C92?) is 57600 */ 592 1.1 rumble if (wanted <= 57600 && (*counter == wanted || *counter == 0)) { 593 1.1 rumble *counter = wanted; 594 1.1 rumble return USE_CT; 595 1.1 rumble } 596 1.1 rumble } 597 1.1 rumble 598 1.1 rumble return -1; /* FAIL */ 599 1.1 rumble } 600 1.1 rumble 601 1.1 rumble /* 602 1.1 rumble * calculate configuration 603 1.1 rumble * rewritten 2/97 -plb 604 1.1 rumble */ 605 1.1 rumble static int 606 1.1 rumble scn_config(int unit, int chan, int ispeed, int ospeed, u_char mr1, u_char mr2) 607 1.1 rumble { 608 1.1 rumble struct scn_softc *sc; 609 1.1 rumble struct duart *dp; 610 1.1 rumble int other; /* opposite of chan */ 611 1.1 rumble int mode; 612 1.1 rumble int counter; 613 1.1 rumble int i, o; /* input, output iterator indexes */ 614 1.1 rumble int ic, oc; /* input, output codes */ 615 1.1 rumble struct chan *ocp; /* other duart channel */ 616 1.1 rumble struct tty *otp; /* other channel tty struct */ 617 1.1 rumble int c92; /* true if duart is sc26c92 */ 618 1.1 rumble int s; 619 1.1 rumble 620 1.1 rumble /* Set up softc pointer. */ 621 1.1 rumble if (unit >= scn_cd.cd_ndevs) 622 1.1 rumble return ENXIO; 623 1.1 rumble sc = SOFTC(unit); 624 1.1 rumble chan = sc->sc_channel; 625 1.1 rumble other = chan ^ 1; 626 1.1 rumble dp = sc->sc_duart; 627 1.1 rumble ocp = &dp->chan[other]; 628 1.1 rumble otp = ocp->tty; 629 1.1 rumble c92 = (dp->type == SC26C92); 630 1.1 rumble 631 1.1 rumble /* 632 1.1 rumble * Right now the first combination that works is used. 633 1.1 rumble * Perhaps it should search entire solution space for "best" 634 1.1 rumble * combination. For example, use heuristic weighting of mode 635 1.1 rumble * preferences, and use of counter timer? 636 1.1 rumble * 637 1.1 rumble * For example right now with 2681/2692 when default rate is 638 1.1 rumble * 9600 and other channel is closed setting 19200 will pick 639 1.1 rumble * mode 0a and use counter/timer. Better solution might be 640 1.1 rumble * mode 0b, leaving counter/timer free! 641 1.1 rumble * 642 1.1 rumble * When other channel is open might want to prefer 643 1.1 rumble * leaving counter timer free, or not flipping A/B group? 644 1.1 rumble */ 645 1.1 rumble if (otp && (otp->t_state & TS_ISOPEN)) { 646 1.1 rumble 647 1.1 rumble /* 648 1.1 rumble * Other channel open; 649 1.1 rumble * Find speed codes compatible with current mode/counter. 650 1.1 rumble */ 651 1.1 rumble 652 1.1 rumble i = 0; 653 1.1 rumble for (;;) { 654 1.1 rumble mode = dp->mode; 655 1.1 rumble counter = dp->counter; 656 1.1 rumble 657 1.1 rumble /* NOTE: pass other chan pointer to allow group flipping */ 658 1.1 rumble ic = scniter(&i, ispeed, &counter, &mode, ocp, c92); 659 1.1 rumble if (ic == -1) 660 1.1 rumble break; 661 1.1 rumble 662 1.1 rumble o = 0; 663 1.1 rumble if ((oc = scniter(&o, ospeed, &counter, 664 1.1 rumble &mode, NULL, c92)) != -1) { 665 1.1 rumble /* 666 1.1 rumble * take first match 667 1.1 rumble * 668 1.1 rumble * Perhaps calculate heuristic "score", 669 1.1 rumble * save score,codes,mode,counter if score 670 1.1 rumble * better than previous best? 671 1.1 rumble */ 672 1.1 rumble goto gotit; 673 1.1 rumble } 674 1.1 rumble } 675 1.1 rumble /* XXX try looping for ospeed? */ 676 1.1 rumble } else { 677 1.1 rumble /* other channel closed */ 678 1.1 rumble int oo, oi; /* other input, output iterators */ 679 1.1 rumble int oic, ooc; /* other input, output codes */ 680 1.1 rumble 681 1.1 rumble /* 682 1.1 rumble * Here when other channel closed. Finds first 683 1.1 rumble * combination that will allow other channel to be opened 684 1.1 rumble * (with defaults) and fits our needs. 685 1.1 rumble */ 686 1.1 rumble oi = 0; 687 1.1 rumble for (;;) { 688 1.1 rumble mode = ANYMODE; 689 1.1 rumble counter = 0; 690 1.1 rumble 691 1.1 rumble oic = scniter(&oi, ocp->ispeed, &counter, &mode, NULL, c92); 692 1.1 rumble if (oic == -1) 693 1.1 rumble break; 694 1.1 rumble 695 1.1 rumble oo = 0; 696 1.1 rumble while ((ooc = scniter(&oo, ocp->ospeed, &counter, 697 1.1 rumble &mode, NULL, c92)) != -1) { 698 1.1 rumble i = 0; 699 1.1 rumble while ((ic = scniter(&i, ispeed, &counter, 700 1.1 rumble &mode, NULL, c92)) != -1) { 701 1.1 rumble o = 0; 702 1.1 rumble if ((oc = scniter(&o, ospeed, &counter, 703 1.1 rumble &mode, NULL, c92)) != -1) { 704 1.1 rumble /* 705 1.1 rumble * take first match 706 1.1 rumble * 707 1.1 rumble * Perhaps calculate heuristic 708 1.1 rumble * "score", save 709 1.1 rumble * score,codes,mode,counter 710 1.1 rumble * if score better than 711 1.1 rumble * previous best? 712 1.1 rumble */ 713 1.1 rumble s = spltty(); 714 1.1 rumble dp->chan[other].icode = oic; 715 1.1 rumble dp->chan[other].ocode = ooc; 716 1.1 rumble goto gotit2; 717 1.1 rumble } 718 1.1 rumble } 719 1.1 rumble } 720 1.1 rumble } 721 1.1 rumble } 722 1.1 rumble return EINVAL; 723 1.1 rumble 724 1.1 rumble gotit: 725 1.1 rumble s = spltty(); 726 1.1 rumble gotit2: 727 1.1 rumble dp->chan[chan].new_mr1 = mr1; 728 1.1 rumble dp->chan[chan].new_mr2 = mr2; 729 1.1 rumble dp->chan[chan].ispeed = ispeed; 730 1.1 rumble dp->chan[chan].ospeed = ospeed; 731 1.1 rumble dp->chan[chan].icode = ic; 732 1.1 rumble dp->chan[chan].ocode = oc; 733 1.1 rumble if (mode == ANYMODE) /* no mode selected?? */ 734 1.1 rumble mode = DEFMODE(c92); 735 1.1 rumble dp->mode = mode; 736 1.1 rumble dp->counter = counter; 737 1.1 rumble 738 1.1 rumble scn_setchip(sc); /* set chip now, if possible */ 739 1.1 rumble splx(s); 740 1.1 rumble return (0); 741 1.1 rumble } 742 1.1 rumble 743 1.1 rumble int 744 1.1 rumble scn_match(device_t parent, struct cfdata *cf, void *aux) 745 1.1 rumble { 746 1.1 rumble struct mainbus_attach_args *ma = aux; 747 1.1 rumble 748 1.1 rumble if ((mach_type == MACH_SGI_IP6 || mach_type == MACH_SGI_IP10) && 749 1.1 rumble ma->ma_addr == 0x1fb80004) 750 1.1 rumble return (1); 751 1.1 rumble 752 1.1 rumble return (0); 753 1.1 rumble } 754 1.1 rumble 755 1.1 rumble /* 756 1.1 rumble * No need to make scn_rx{en,dis}able too efficient, 757 1.1 rumble * they're only called on setup, open & close! 758 1.1 rumble */ 759 1.1 rumble static inline void 760 1.1 rumble scn_rxenable(struct scn_softc *sc) 761 1.1 rumble { 762 1.1 rumble struct duart *dp; 763 1.1 rumble int channel; 764 1.1 rumble 765 1.1 rumble dp = sc->sc_duart; 766 1.1 rumble channel = sc->sc_channel; 767 1.1 rumble 768 1.1 rumble /* Outputs wire-ored and connected to ICU input for fast rx interrupt. */ 769 1.1 rumble if (channel == 0) 770 1.1 rumble dp->opcr |= OPCR_OP4_RXRDYA; 771 1.1 rumble else 772 1.1 rumble dp->opcr |= OPCR_OP5_RXRDYB; 773 1.1 rumble dp->base[DU_OPCR] = dp->opcr; 774 1.1 rumble dp->imr |= sc->sc_rx_int; 775 1.1 rumble dp->base[DU_IMR] = dp->imr; 776 1.1 rumble } 777 1.1 rumble 778 1.1 rumble static inline void 779 1.1 rumble scn_rxdisable(struct scn_softc *sc) 780 1.1 rumble { 781 1.1 rumble struct duart *dp; 782 1.1 rumble int channel; 783 1.1 rumble 784 1.1 rumble dp = sc->sc_duart; 785 1.1 rumble channel = sc->sc_channel; 786 1.1 rumble 787 1.1 rumble /* Outputs wire-ored and connected to ICU input for fast rx interrupt. */ 788 1.1 rumble if (channel == 0) 789 1.1 rumble dp->opcr &= ~OPCR_OP4_RXRDYA; 790 1.1 rumble else 791 1.1 rumble dp->opcr &= ~OPCR_OP5_RXRDYB; 792 1.1 rumble dp->base[DU_OPCR] = dp->opcr; 793 1.1 rumble dp->imr &= ~sc->sc_rx_int; 794 1.1 rumble dp->base[DU_IMR] = dp->imr; 795 1.1 rumble } 796 1.1 rumble 797 1.1 rumble void 798 1.1 rumble scn_attach(device_t parent, device_t self, void *aux) 799 1.1 rumble { 800 1.1 rumble struct mainbus_attach_args *ma = aux; 801 1.1 rumble struct scn_softc *sc; 802 1.1 rumble struct duart *duart; 803 1.1 rumble volatile u_char *ch_base; 804 1.1 rumble volatile u_char *duart_base; 805 1.1 rumble int channel; 806 1.1 rumble int speed; 807 1.1 rumble int s; 808 1.6 christos int maj __diagused; 809 1.1 rumble u_char unit; 810 1.1 rumble u_char duartno; 811 1.1 rumble u_char delim = ':'; 812 1.1 rumble u_char mr1, mr2; 813 1.1 rumble enum scntype scntype = SCNUNK; 814 1.1 rumble const char *duart_type = "Unknown"; 815 1.1 rumble bool console, first; 816 1.1 rumble devmajor_t major; 817 1.1 rumble 818 1.1 rumble (void)major; 819 1.1 rumble 820 1.1 rumble sc = device_private(self); 821 1.1 rumble unit = device_unit(self); 822 1.1 rumble 823 1.1 rumble /* XXX - hard-coded */ 824 1.1 rumble if (ma->ma_addr == 0x1fb80004) 825 1.1 rumble duartno = 1; 826 1.1 rumble else 827 1.1 rumble duartno = 0; 828 1.1 rumble channel = 0; 829 1.1 rumble console = 1; 830 1.1 rumble 831 1.1 rumble duart = sc->sc_duart = &scn_duart[duartno]; 832 1.1 rumble duart->chan[channel].sc = sc; 833 1.1 rumble first = (duart->base == NULL); 834 1.1 rumble 835 1.1 rumble if (console) { 836 1.1 rumble sc->sc_isconsole = 1; 837 1.1 rumble sc->sc_swflags |= SCN_SW_SOFTCAR; /* ignore carrier */ 838 1.1 rumble } 839 1.1 rumble 840 1.1 rumble duart_base = (volatile u_char *)MIPS_PHYS_TO_KSEG1(ma->ma_addr); 841 1.1 rumble ch_base = duart_base; /* XXX */ 842 1.1 rumble 843 1.1 rumble if (first) { 844 1.1 rumble /* Probe DUART type */ 845 1.1 rumble s = spltty(); 846 1.1 rumble if (console) { 847 1.1 rumble ch_base[CH_CR] = CR_DIS_TX; 848 1.1 rumble delay(5 * 10000); 849 1.1 rumble } 850 1.1 rumble ch_base[CH_CR] = CR_CMD_MR1; 851 1.1 rumble RECOVER(); 852 1.1 rumble mr1 = ch_base[CH_MR]; 853 1.1 rumble mr2 = ch_base[CH_MR]; 854 1.1 rumble ch_base[CH_CR] = CR_CMD_MR1; 855 1.1 rumble RECOVER(); 856 1.1 rumble ch_base[CH_MR] = 1; 857 1.1 rumble ch_base[CH_MR] = 0; 858 1.1 rumble ch_base[CH_CR] = CR_CMD_MR1; 859 1.1 rumble RECOVER(); 860 1.1 rumble if (ch_base[CH_MR] == 1) { 861 1.1 rumble /* MR 2 selected */ 862 1.1 rumble ch_base[CH_CR] = CR_CMD_MR0; 863 1.1 rumble RECOVER(); 864 1.1 rumble /* if 2681, MR2 still selected */ 865 1.1 rumble ch_base[CH_MR] = 1; 866 1.1 rumble ch_base[CH_CR] = CR_CMD_MR1; 867 1.1 rumble RECOVER(); 868 1.1 rumble ch_base[CH_MR] = 0; /* MR1 */ 869 1.1 rumble ch_base[CH_MR] = 0; /* MR2 */ 870 1.1 rumble ch_base[CH_CR] = CR_CMD_MR0; 871 1.1 rumble RECOVER(); 872 1.1 rumble /* if 2681, MR2 still selected */ 873 1.1 rumble if((ch_base[CH_MR] & 1) == 1) { 874 1.1 rumble duart_type = "sc26c92"; 875 1.1 rumble scntype = SC26C92; 876 1.1 rumble } else { 877 1.1 rumble /* 2681 treats as MR1 Select */ 878 1.1 rumble ch_base[CH_CR] = CR_CMD_RTS_OFF; 879 1.1 rumble RECOVER(); 880 1.1 rumble ch_base[CH_MR] = 1; 881 1.1 rumble ch_base[CH_MR] = 0; 882 1.1 rumble ch_base[CH_CR] = CR_CMD_RTS_OFF; 883 1.1 rumble RECOVER(); 884 1.1 rumble if (ch_base[CH_MR] == 1) { 885 1.1 rumble duart_type = "scn2681"; 886 1.1 rumble scntype = SCN2681; 887 1.1 rumble } else { 888 1.1 rumble duart_type = "scn2692"; 889 1.1 rumble scntype = SCN2692; 890 1.1 rumble } 891 1.1 rumble } 892 1.1 rumble } 893 1.1 rumble 894 1.1 rumble /* If a 2681, the CR_CMD_MR0 is interpreted as a TX_RESET */ 895 1.1 rumble if (console) { 896 1.1 rumble ch_base[CH_CR] = CR_ENA_TX; 897 1.1 rumble RECOVER(); 898 1.1 rumble } 899 1.1 rumble ch_base[CH_CR] = CR_CMD_MR1; 900 1.1 rumble RECOVER(); 901 1.1 rumble ch_base[CH_MR] = mr1; 902 1.1 rumble ch_base[CH_MR] = mr2; 903 1.1 rumble splx(s); 904 1.1 rumble 905 1.1 rumble /* 906 1.1 rumble * On IP6 the console chip is duart1. The keyboard/mouse 907 1.1 rumble * is duart0. Each chip has two channels and the channels 908 1.1 rumble * share an interrupt. Duart0 is interrupt 0, duart1 is 909 1.1 rumble * interrupt 1. 910 1.1 rumble */ 911 1.1 rumble if (duartno != 0 && duartno != 1) 912 1.1 rumble panic("scn_attach: bad duartno: %d", duartno); 913 1.1 rumble cpu_intr_establish(duartno, IPL_TTY, scnintr, duart); 914 1.1 rumble 915 1.1 rumble printf("%c %s", delim, duart_type); 916 1.1 rumble delim = ','; 917 1.1 rumble 918 1.1 rumble duart->base = duart_base; 919 1.1 rumble duart->type = scntype; 920 1.1 rumble } 921 1.1 rumble /* Record channel, uart */ 922 1.1 rumble sc->sc_channel = channel; 923 1.1 rumble sc->sc_chbase = ch_base; 924 1.1 rumble 925 1.1 rumble /* Initialize modem/interrupt bit masks */ 926 1.1 rumble if (channel == 0) { 927 1.1 rumble sc->sc_op_rts = OP_RTSA; 928 1.1 rumble sc->sc_op_dtr = OP_DTRA; 929 1.1 rumble sc->sc_ip_cts = IP_CTSA; 930 1.1 rumble sc->sc_ip_dcd = IP_DCDA; 931 1.1 rumble 932 1.1 rumble sc->sc_tx_int = INT_TXA; 933 1.1 rumble sc->sc_rx_int = INT_RXA; 934 1.1 rumble } else { 935 1.1 rumble sc->sc_op_rts = OP_RTSB; 936 1.1 rumble sc->sc_op_dtr = OP_DTRB; 937 1.1 rumble sc->sc_ip_cts = IP_CTSB; 938 1.1 rumble sc->sc_ip_dcd = IP_DCDB; 939 1.1 rumble 940 1.1 rumble sc->sc_tx_int = INT_TXB; 941 1.1 rumble sc->sc_rx_int = INT_RXB; 942 1.1 rumble } 943 1.1 rumble 944 1.1 rumble /* Initialize counters */ 945 1.1 rumble sc->sc_framing_errors = 0; 946 1.1 rumble sc->sc_fifo_overruns = 0; 947 1.1 rumble sc->sc_parity_errors = 0; 948 1.1 rumble sc->sc_breaks = 0; 949 1.1 rumble 950 1.1 rumble if (console) { 951 1.1 rumble DELAY(5 * 10000); /* Let the output go out.... */ 952 1.1 rumble } 953 1.1 rumble 954 1.1 rumble /* 955 1.1 rumble * Set up the hardware to a base state, in particular: 956 1.1 rumble * o reset transmitter and receiver 957 1.1 rumble * o set speeds and configurations 958 1.1 rumble * o receiver interrupts only (RxRDY and BREAK) 959 1.1 rumble */ 960 1.1 rumble 961 1.1 rumble s = spltty(); 962 1.1 rumble /* RTS off... */ 963 1.1 rumble SCN_OP_BIC(sc, sc->sc_op_rts); /* "istop" */ 964 1.1 rumble 965 1.1 rumble ch_base[CH_CR] = CR_DIS_RX | CR_DIS_TX; 966 1.1 rumble RECOVER(); 967 1.1 rumble ch_base[CH_CR] = CR_CMD_RESET_RX; 968 1.1 rumble RECOVER(); 969 1.1 rumble ch_base[CH_CR] = CR_CMD_RESET_TX; 970 1.1 rumble RECOVER(); 971 1.1 rumble ch_base[CH_CR] = CR_CMD_RESET_ERR; 972 1.1 rumble RECOVER(); 973 1.1 rumble ch_base[CH_CR] = CR_CMD_RESET_BRK; 974 1.1 rumble RECOVER(); 975 1.1 rumble ch_base[CH_CR] = CR_CMD_MR1; 976 1.1 rumble RECOVER(); 977 1.1 rumble 978 1.1 rumble /* No receiver control of RTS. */ 979 1.1 rumble ch_base[CH_MR] = 0; 980 1.1 rumble ch_base[CH_MR] = 0; 981 1.1 rumble 982 1.1 rumble /* Initialize the uart structure if this is channel A. */ 983 1.1 rumble if (first) { 984 1.1 rumble /* Disable all interrupts. */ 985 1.1 rumble duart_base[DU_IMR] = duart->imr = 0; 986 1.1 rumble 987 1.1 rumble /* Output port config */ 988 1.1 rumble duart_base[DU_OPCR] = duart->opcr = 0; 989 1.1 rumble 990 1.1 rumble /* Speeds... */ 991 1.1 rumble duart->mode = 0; 992 1.1 rumble 993 1.1 rumble /* 994 1.1 rumble * Set initial speed to an illegal code that can be changed to 995 1.1 rumble * any other baud. 996 1.1 rumble */ 997 1.1 rumble duart->chan[0].icode = duart->chan[0].ocode = 0x2f; 998 1.1 rumble duart->chan[1].icode = duart->chan[1].ocode = 0x2f; 999 1.1 rumble duart->chan[0].ispeed = duart->chan[0].ospeed = 0; 1000 1.1 rumble duart->chan[1].ispeed = duart->chan[1].ospeed = 0; 1001 1.1 rumble 1002 1.1 rumble duart->acr = 0; 1003 1.1 rumble duart->acr |= ACR_CT_TCLK1; /* timer mode 1x clk */ 1004 1.1 rumble } 1005 1.1 rumble 1006 1.1 rumble if (channel == 0) { 1007 1.1 rumble duart->acr |= ACR_DELTA_DCDA; /* Set CD int */ 1008 1.1 rumble } else { 1009 1.1 rumble duart->acr |= ACR_DELTA_DCDB; /* Set CD int */ 1010 1.1 rumble } 1011 1.1 rumble 1012 1.1 rumble if (scnsir == NULL) { 1013 1.1 rumble /* software intr: calls tty code, hence IPL_TTY */ 1014 1.1 rumble scnsir = softint_establish(SOFTINT_SERIAL, scnsoft, NULL); 1015 1.1 rumble } 1016 1.1 rumble 1017 1.1 rumble duart_base[DU_ACR] = (duart->mode & ACR_BRG) | duart->acr; 1018 1.1 rumble 1019 1.1 rumble if (console) 1020 1.1 rumble speed = scnconsrate; 1021 1.1 rumble else 1022 1.1 rumble speed = scndefaultrate; 1023 1.1 rumble 1024 1.1 rumble scn_config(unit, channel, speed, speed, MR1_PNONE | MR1_CS8, MR2_STOP1); 1025 1.1 rumble if (console) { 1026 1.1 rumble maj = cdevsw_lookup_major(&scn_cdevsw); 1027 1.1 rumble KASSERT(maj != NODEVMAJOR); 1028 1.1 rumble shutdownhook_establish(scncnreinit, NULL); 1029 1.1 rumble /* Make sure console can do scncngetc */ 1030 1.1 rumble duart_base[DU_OPSET] = channel ? (OP_RTSB | OP_DTRB) : 1031 1.1 rumble (OP_RTSA | OP_DTRA); 1032 1.1 rumble } 1033 1.1 rumble 1034 1.1 rumble /* Turn on the receiver and transmitters */ 1035 1.1 rumble ch_base[CH_CR] = CR_ENA_RX | CR_ENA_TX; 1036 1.1 rumble 1037 1.1 rumble /* Set up the interrupts. */ 1038 1.1 rumble duart->imr |= INT_IP; 1039 1.1 rumble scn_rxdisable(sc); 1040 1.1 rumble splx(s); 1041 1.1 rumble 1042 1.1 rumble if (sc->sc_swflags) { 1043 1.1 rumble printf("%c flags %d", delim, sc->sc_swflags); 1044 1.1 rumble delim = ','; 1045 1.1 rumble } 1046 1.1 rumble 1047 1.1 rumble #ifdef KGDB 1048 1.1 rumble major = cdevsw_lookup_major(&scn_cdevsw); 1049 1.1 rumble KASSERT(major != NODEVMAJOR); 1050 1.1 rumble if (kgdb_dev == makedev(major, unit)) { 1051 1.1 rumble if (console) 1052 1.1 rumble kgdb_dev = NODEV; /* can't debug over console port */ 1053 1.1 rumble else { 1054 1.1 rumble scninit(kgdb_dev, kgdb_rate); 1055 1.1 rumble scn_rxenable(sc); 1056 1.1 rumble scn->sc_iskgdb = 1; 1057 1.1 rumble kgdb_attach(scncngetc, scncnputc, kgdb_dev); 1058 1.1 rumble if (kgdb_debug_init) { 1059 1.1 rumble printf("%c ", delim); 1060 1.1 rumble kgdb_connect(1); 1061 1.1 rumble } else 1062 1.1 rumble printf("%c kgdb enabled", delim); 1063 1.1 rumble delim = ','; 1064 1.1 rumble } 1065 1.1 rumble } 1066 1.1 rumble #endif 1067 1.1 rumble printf("\n"); 1068 1.1 rumble } 1069 1.1 rumble 1070 1.1 rumble /* ARGSUSED */ 1071 1.1 rumble int 1072 1.1 rumble scnopen(dev_t dev, int flags, int mode, struct lwp *l) 1073 1.1 rumble { 1074 1.1 rumble struct tty *tp; 1075 1.1 rumble int unit = DEV_UNIT(dev); 1076 1.1 rumble struct scn_softc *sc; 1077 1.1 rumble int error = 0; 1078 1.1 rumble 1079 1.1 rumble if (unit >= scn_cd.cd_ndevs) 1080 1.1 rumble return ENXIO; 1081 1.1 rumble sc = SOFTC(unit); 1082 1.1 rumble if (!sc) 1083 1.1 rumble return ENXIO; 1084 1.1 rumble 1085 1.1 rumble tp = sc->sc_tty; 1086 1.1 rumble if (!tp) { 1087 1.3 rmind tp = tty_alloc(); 1088 1.1 rumble sc->sc_tty = sc->sc_duart->chan[sc->sc_channel].tty = tp; 1089 1.1 rumble tty_attach(tp); 1090 1.1 rumble } 1091 1.1 rumble 1092 1.1 rumble tp->t_oproc = scnstart; 1093 1.1 rumble tp->t_param = scnparam; 1094 1.1 rumble tp->t_hwiflow = scnhwiflow; 1095 1.1 rumble tp->t_dev = dev; 1096 1.1 rumble 1097 1.1 rumble if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 1098 1.1 rumble return (EBUSY); 1099 1.1 rumble 1100 1.10 riastrad ttylock(tp); 1101 1.1 rumble 1102 1.1 rumble if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { 1103 1.1 rumble ttychars(tp); 1104 1.1 rumble tp->t_iflag = TTYDEF_IFLAG; 1105 1.1 rumble tp->t_oflag = TTYDEF_OFLAG; 1106 1.1 rumble tp->t_cflag = SCNDEF_CFLAG; 1107 1.1 rumble 1108 1.1 rumble sc->sc_rx_blocked = 0; 1109 1.1 rumble 1110 1.1 rumble if (sc->sc_swflags & SCN_SW_CLOCAL) 1111 1.1 rumble tp->t_cflag |= CLOCAL; 1112 1.1 rumble if (sc->sc_swflags & SCN_SW_CRTSCTS) 1113 1.1 rumble tp->t_cflag |= CCTS_OFLOW | CRTS_IFLOW; 1114 1.1 rumble tp->t_lflag = TTYDEF_LFLAG; 1115 1.1 rumble if (sc->sc_isconsole) 1116 1.1 rumble tp->t_ispeed = tp->t_ospeed = scnconsrate; 1117 1.1 rumble else 1118 1.1 rumble tp->t_ispeed = tp->t_ospeed = scndefaultrate; 1119 1.1 rumble scnparam(tp, &tp->t_termios); 1120 1.1 rumble ttsetwater(tp); 1121 1.1 rumble 1122 1.1 rumble /* Turn on DTR and RTS. */ 1123 1.1 rumble SCN_OP_BIS(sc, sc->sc_op_rts | sc->sc_op_dtr); 1124 1.1 rumble 1125 1.1 rumble /* enable receiver interrupts */ 1126 1.1 rumble scn_rxenable(sc); 1127 1.1 rumble 1128 1.1 rumble /* set carrier state; */ 1129 1.1 rumble if ((sc->sc_swflags & SCN_SW_SOFTCAR) || /* check ttyflags */ 1130 1.1 rumble SCN_DCD(sc) || /* check h/w */ 1131 1.1 rumble DEV_DIALOUT(dev)) 1132 1.1 rumble tp->t_state |= TS_CARR_ON; 1133 1.1 rumble else 1134 1.1 rumble tp->t_state &= ~TS_CARR_ON; 1135 1.1 rumble } 1136 1.1 rumble 1137 1.10 riastrad ttyunlock(tp); 1138 1.1 rumble 1139 1.1 rumble error = ttyopen(tp, SCN_DIALOUT(sc), flags & O_NONBLOCK); 1140 1.1 rumble if (error) printf("ttyopen failed line %d, error %d\n", __LINE__, error); 1141 1.1 rumble if (error) 1142 1.1 rumble goto bad; 1143 1.1 rumble 1144 1.1 rumble error = (*tp->t_linesw->l_open) (dev, tp); 1145 1.1 rumble if (error) printf("l_open failed line %d, error %d\n", __LINE__, error); 1146 1.1 rumble if (error) 1147 1.1 rumble goto bad; 1148 1.1 rumble 1149 1.1 rumble return (0); 1150 1.1 rumble 1151 1.1 rumble bad: 1152 1.1 rumble if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { 1153 1.1 rumble scn_rxdisable(sc); 1154 1.1 rumble SCN_OP_BIC(sc, sc->sc_op_rts | sc->sc_op_dtr); 1155 1.1 rumble } 1156 1.1 rumble 1157 1.1 rumble return (error); 1158 1.1 rumble } 1159 1.1 rumble 1160 1.1 rumble 1161 1.1 rumble /*ARGSUSED*/ 1162 1.1 rumble int 1163 1.1 rumble scnclose(dev_t dev, int flags, int mode, struct lwp *l) 1164 1.1 rumble { 1165 1.1 rumble int unit = DEV_UNIT(dev); 1166 1.1 rumble struct scn_softc *sc = SOFTC(unit); 1167 1.1 rumble struct tty *tp = sc->sc_tty; 1168 1.1 rumble devmajor_t major; 1169 1.1 rumble 1170 1.1 rumble (void)major; 1171 1.1 rumble 1172 1.1 rumble if ((tp->t_state & TS_ISOPEN) == 0) 1173 1.1 rumble return 0; 1174 1.1 rumble 1175 1.1 rumble (*tp->t_linesw->l_close) (tp, flags); 1176 1.1 rumble 1177 1.1 rumble #ifdef KGDB 1178 1.1 rumble /* do not disable interrupts if debugging */ 1179 1.1 rumble major = cdevsw_lookup_major(&scn_devsw); 1180 1.1 rumble KASSERT(major != cdevsw_lookup_major); 1181 1.1 rumble if (kgdb_dev != makedev(major, unit)) 1182 1.1 rumble #endif 1183 1.1 rumble if ((tp->t_state & TS_ISOPEN) == 0) { 1184 1.1 rumble scn_rxdisable(sc); 1185 1.1 rumble } 1186 1.1 rumble if ((tp->t_cflag & HUPCL) && (sc->sc_swflags & SCN_SW_SOFTCAR) == 0) { 1187 1.1 rumble SCN_OP_BIC(sc, sc->sc_op_dtr); 1188 1.1 rumble /* hold low for 1 second */ 1189 1.1 rumble tsleep(sc, TTIPRI, ttclos, hz); 1190 1.1 rumble } 1191 1.1 rumble SCN_CLRDIALOUT(sc); 1192 1.1 rumble ttyclose(tp); 1193 1.1 rumble 1194 1.1 rumble #if 0 1195 1.1 rumble if ((tp->t_state & TS_ISOPEN) == 0) { 1196 1.3 rmind tty_free(tp); 1197 1.1 rumble sc->sc_tty = (struct tty *) NULL; 1198 1.1 rumble } 1199 1.1 rumble #endif 1200 1.1 rumble 1201 1.1 rumble return (0); 1202 1.1 rumble } 1203 1.1 rumble 1204 1.1 rumble int 1205 1.1 rumble scnread(dev_t dev, struct uio *uio, int flags) 1206 1.1 rumble { 1207 1.1 rumble struct scn_softc *sc = SOFTC(DEV_UNIT(dev)); 1208 1.1 rumble struct tty *tp = sc->sc_tty; 1209 1.1 rumble 1210 1.1 rumble return ((*tp->t_linesw->l_read) (tp, uio, flags)); 1211 1.1 rumble } 1212 1.1 rumble 1213 1.1 rumble int 1214 1.1 rumble scnwrite(dev_t dev, struct uio *uio, int flags) 1215 1.1 rumble { 1216 1.1 rumble struct scn_softc *sc = SOFTC(DEV_UNIT(dev)); 1217 1.1 rumble struct tty *tp = sc->sc_tty; 1218 1.1 rumble 1219 1.1 rumble return ((*tp->t_linesw->l_write) (tp, uio, flags)); 1220 1.1 rumble } 1221 1.1 rumble 1222 1.1 rumble int 1223 1.1 rumble scnpoll(dev_t dev, int events, struct lwp *l) 1224 1.1 rumble { 1225 1.1 rumble struct scn_softc *sc = SOFTC(DEV_UNIT(dev)); 1226 1.1 rumble struct tty *tp = sc->sc_tty; 1227 1.1 rumble 1228 1.1 rumble return ((*tp->t_linesw->l_poll)(tp, events, l)); 1229 1.1 rumble } 1230 1.1 rumble 1231 1.1 rumble struct tty * 1232 1.1 rumble scntty(dev_t dev) 1233 1.1 rumble { 1234 1.1 rumble struct scn_softc *sc = SOFTC(DEV_UNIT(dev)); 1235 1.1 rumble 1236 1.1 rumble return sc->sc_tty; 1237 1.1 rumble } 1238 1.1 rumble 1239 1.1 rumble /* Worker routines for interrupt processing */ 1240 1.1 rumble static inline void 1241 1.1 rumble dcd_int(struct scn_softc *sc, struct tty *tp, u_char new) 1242 1.1 rumble { 1243 1.1 rumble 1244 1.1 rumble if (sc->sc_swflags & SCN_SW_SOFTCAR) 1245 1.1 rumble return; 1246 1.1 rumble 1247 1.1 rumble #if 0 1248 1.1 rumble printf("scn%d: dcd_int ip %x SCN_DCD %x new %x ipcr %x\n", 1249 1.1 rumble sc->unit, 1250 1.1 rumble sc->sc_duart->base[DU_IP], 1251 1.1 rumble SCN_DCD(sc), 1252 1.1 rumble new, 1253 1.1 rumble sc->sc_duart->base[DU_IPCR] 1254 1.1 rumble ); 1255 1.1 rumble #endif 1256 1.1 rumble 1257 1.1 rumble /* XXX set some flag to have some lower (soft) int call line discipline? */ 1258 1.1 rumble if (!(*tp->t_linesw->l_modem) (tp, new == 0? 1: 0)) { 1259 1.1 rumble SCN_OP_BIC(sc, sc->sc_op_rts | sc->sc_op_dtr); 1260 1.1 rumble } 1261 1.1 rumble } 1262 1.1 rumble 1263 1.1 rumble /* 1264 1.1 rumble * Print out a ring or fifo overrun error message. 1265 1.1 rumble */ 1266 1.1 rumble static void 1267 1.1 rumble scnoverrun(int unit, long *ptime, const char *what) 1268 1.1 rumble { 1269 1.1 rumble 1270 1.1 rumble if (*ptime != time_second) { 1271 1.1 rumble *ptime = time_second; 1272 1.1 rumble log(LOG_WARNING, "scn%d: %s overrun\n", unit, what); 1273 1.1 rumble } 1274 1.1 rumble } 1275 1.1 rumble 1276 1.1 rumble /* 1277 1.1 rumble * Try to block or unblock input using hardware flow-control. 1278 1.1 rumble * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and 1279 1.1 rumble * if this function returns non-zero, the TS_TBLOCK flag will 1280 1.1 rumble * be set or cleared according to the "stop" arg passed. 1281 1.1 rumble */ 1282 1.1 rumble int 1283 1.1 rumble scnhwiflow(struct tty *tp, int stop) 1284 1.1 rumble { 1285 1.1 rumble int unit = DEV_UNIT(tp->t_dev); 1286 1.1 rumble struct scn_softc *sc = SOFTC(unit); 1287 1.1 rumble int s; 1288 1.1 rumble 1289 1.1 rumble s = splrtty(); 1290 1.1 rumble if (!stop) { 1291 1.1 rumble if (sc->sc_rbput - sc->sc_rbget - 1) { 1292 1.1 rumble setsoftscn(); 1293 1.1 rumble } 1294 1.1 rumble } 1295 1.1 rumble splx(s); 1296 1.1 rumble return 1; 1297 1.1 rumble } 1298 1.1 rumble 1299 1.1 rumble static int 1300 1.1 rumble scnintr(void *arg) 1301 1.1 rumble { 1302 1.1 rumble struct duart *duart = arg; 1303 1.1 rumble struct scn_softc *sc0 = duart->chan[0].sc; 1304 1.1 rumble struct scn_softc *sc1 = duart->chan[1].sc; 1305 1.1 rumble 1306 1.1 rumble struct tty *tp0 = (sc0 != NULL) ? sc0->sc_tty : NULL; 1307 1.1 rumble struct tty *tp1 = (sc1 != NULL) ? sc1->sc_tty : NULL; 1308 1.1 rumble 1309 1.1 rumble char rs_work; 1310 1.1 rumble u_char rs_stat; 1311 1.1 rumble u_char rs_ipcr; 1312 1.1 rumble 1313 1.1 rumble /* Check for RX interrupts first, since we cannot distinguish by irq. */ 1314 1.1 rumble scnrxintr(duart); 1315 1.1 rumble 1316 1.1 rumble do { 1317 1.1 rumble /* Loop to pick up ALL pending interrupts for device. */ 1318 1.1 rumble rs_work = false; 1319 1.1 rumble rs_stat = duart->base[DU_ISR]; 1320 1.1 rumble 1321 1.1 rumble /* channel a */ 1322 1.1 rumble if (tp0 != NULL) { 1323 1.1 rumble if ((rs_stat & INT_TXA) && (tp0->t_state & TS_BUSY)) { 1324 1.1 rumble /* output char done. */ 1325 1.1 rumble tp0->t_state &= ~(TS_BUSY | TS_FLUSH); 1326 1.1 rumble 1327 1.1 rumble /* disable tx ints */ 1328 1.1 rumble duart->imr &= ~sc0->sc_tx_int; 1329 1.1 rumble duart->base[DU_IMR] = duart->imr; 1330 1.1 rumble 1331 1.1 rumble if (sc0->sc_heldchanges) { 1332 1.1 rumble scn_setchip(sc0); 1333 1.1 rumble } 1334 1.1 rumble 1335 1.1 rumble (*tp0->t_linesw->l_start) (tp0); 1336 1.1 rumble rs_work = true; 1337 1.1 rumble } 1338 1.1 rumble } 1339 1.1 rumble /* channel b */ 1340 1.1 rumble if (tp1 != NULL) { 1341 1.1 rumble if ((rs_stat & INT_TXB) && (tp1->t_state & TS_BUSY)) { 1342 1.1 rumble /* output char done. */ 1343 1.1 rumble tp1->t_state &= ~(TS_BUSY | TS_FLUSH); 1344 1.1 rumble 1345 1.1 rumble /* disable tx ints */ 1346 1.1 rumble duart->imr &= ~sc1->sc_tx_int; 1347 1.1 rumble duart->base[DU_IMR] = duart->imr; 1348 1.1 rumble 1349 1.1 rumble if (sc1->sc_heldchanges) { 1350 1.1 rumble scn_setchip(sc1); 1351 1.1 rumble } 1352 1.1 rumble 1353 1.1 rumble (*tp1->t_linesw->l_start) (tp1); 1354 1.1 rumble rs_work = true; 1355 1.1 rumble } 1356 1.1 rumble } 1357 1.1 rumble if (rs_stat & INT_IP) { 1358 1.1 rumble rs_work = true; 1359 1.1 rumble rs_ipcr = duart->base[DU_IPCR]; 1360 1.1 rumble 1361 1.1 rumble if (rs_ipcr & IPCR_DELTA_DCDA && tp0 != NULL) { 1362 1.1 rumble dcd_int(sc0, tp0, rs_ipcr & IPCR_DCDA); 1363 1.1 rumble } 1364 1.1 rumble if (rs_ipcr & IPCR_DELTA_DCDB && tp1 != NULL) { 1365 1.1 rumble dcd_int(sc1, tp1, rs_ipcr & IPCR_DCDB); 1366 1.1 rumble } 1367 1.1 rumble } 1368 1.1 rumble } while (rs_work); 1369 1.1 rumble 1370 1.1 rumble return (1); /* ? */ 1371 1.1 rumble } 1372 1.1 rumble 1373 1.1 rumble /* 1374 1.1 rumble * Handle rxrdy/ffull interrupt: QUICKLY poll both channels (checking 1375 1.1 rumble * status first) and stash data in a ring buffer. Ring buffer scheme 1376 1.1 rumble * borowed from sparc/zs.c requires NO interlock on data! 1377 1.1 rumble * 1378 1.1 rumble * This interrupt should NOT be included in spltty() mask since it 1379 1.1 rumble * invokes NO tty code! The whole point is to allow tty input as much 1380 1.1 rumble * of the time as possible, while deferring "heavy" character 1381 1.1 rumble * processing until later. 1382 1.1 rumble * 1383 1.1 rumble * see scn.hw.README and scnsoft() for more info. 1384 1.1 rumble * 1385 1.1 rumble * THIS ROUTINE SHOULD BE KEPT AS CLEAN AS POSSIBLE!! 1386 1.1 rumble * IT'S A CANDIDATE FOR RECODING IN ASSEMBLER!! 1387 1.1 rumble */ 1388 1.1 rumble static inline int 1389 1.1 rumble scn_rxintr(struct scn_softc *sc) 1390 1.1 rumble { 1391 1.1 rumble char sr; 1392 1.1 rumble int i, n; 1393 1.1 rumble int work; 1394 1.1 rumble 1395 1.1 rumble work = 0; 1396 1.1 rumble i = sc->sc_rbput; 1397 1.1 rumble while (work <= 10) { 1398 1.1 rumble #define SCN_GETCH(SC) \ 1399 1.1 rumble sr = (SC)->sc_chbase[CH_SR]; \ 1400 1.1 rumble if ((sr & SR_RX_RDY) == 0) \ 1401 1.1 rumble break; \ 1402 1.1 rumble if (sr & (SR_PARITY | SR_FRAME | SR_BREAK | SR_OVERRUN)) \ 1403 1.1 rumble goto exception; \ 1404 1.1 rumble work++; \ 1405 1.1 rumble (SC)->sc_rbuf[i++ & SCN_RING_MASK] = (SC)->sc_chbase[CH_DAT] 1406 1.1 rumble 1407 1.1 rumble SCN_GETCH(sc); SCN_GETCH(sc); SCN_GETCH(sc); 1408 1.1 rumble /* XXX more here if 26C92? -plb */ 1409 1.1 rumble continue; 1410 1.1 rumble exception: 1411 1.1 rumble #if defined(DDB) 1412 1.1 rumble if (sc->sc_isconsole && (sr & SR_BREAK)) { 1413 1.1 rumble Debugger(); 1414 1.1 rumble sr = sc->sc_chbase[CH_SR]; 1415 1.1 rumble } 1416 1.1 rumble #endif 1417 1.1 rumble #if defined(KGDB) 1418 1.1 rumble if (sc->sc_iskgdb && (sr & SR_RX_RDY)) { 1419 1.1 rumble kgdb_connect(1); 1420 1.1 rumble sr = sc->sc_chbase[CH_SR]; 1421 1.1 rumble } 1422 1.1 rumble #endif 1423 1.1 rumble work++; 1424 1.1 rumble sc->sc_rbuf[i++ & SCN_RING_MASK] = (sr << 8) | sc->sc_chbase[CH_DAT]; 1425 1.1 rumble sc->sc_chbase[CH_CR] = CR_CMD_RESET_ERR; /* resets break? */ 1426 1.1 rumble RECOVER(); 1427 1.1 rumble } 1428 1.1 rumble /* 1429 1.1 rumble * If ring is getting too full, try to block input. 1430 1.1 rumble */ 1431 1.1 rumble n = i - sc->sc_rbget; 1432 1.1 rumble if (sc->sc_rbhiwat && (n > sc->sc_rbhiwat)) { 1433 1.1 rumble /* If not CRTSCTS sc_rbhiwat is such that this 1434 1.1 rumble * never happens. 1435 1.1 rumble * Clear RTS 1436 1.1 rumble */ 1437 1.1 rumble SCN_OP_BIC(sc, sc->sc_op_rts); 1438 1.1 rumble sc->sc_rx_blocked = 1; 1439 1.1 rumble } 1440 1.1 rumble sc->sc_rbput = i; 1441 1.1 rumble 1442 1.1 rumble return work; 1443 1.1 rumble } 1444 1.1 rumble 1445 1.1 rumble static void 1446 1.1 rumble scnrxintr(void *arg) 1447 1.1 rumble { 1448 1.1 rumble struct duart *duart = arg; 1449 1.1 rumble int work = 0; 1450 1.1 rumble 1451 1.1 rumble if (duart->chan[0].sc != NULL) 1452 1.1 rumble work += scn_rxintr(duart->chan[0].sc); 1453 1.1 rumble if (duart->chan[1].sc != NULL) 1454 1.1 rumble work += scn_rxintr(duart->chan[1].sc); 1455 1.1 rumble if (work > 0) { 1456 1.1 rumble setsoftscn(); /* trigger s/w intr */ 1457 1.1 rumble #ifdef SCN_TIMING 1458 1.1 rumble microtime(&tstart); 1459 1.1 rumble #endif 1460 1.1 rumble } 1461 1.1 rumble } 1462 1.1 rumble 1463 1.1 rumble /* 1464 1.1 rumble * Here on soft interrupt (at spltty) to empty ring buffers. 1465 1.1 rumble * 1466 1.1 rumble * Dave's original scheme was to use the DUART receiver timeout 1467 1.1 rumble * interrupt. This requires 2692's (which my board doesn't have), and 1468 1.1 rumble * I also liked the idea of using the C/T to generate alternate and/or 1469 1.1 rumble * arbitrary bauds. -plb 1470 1.1 rumble * 1471 1.1 rumble * The ringbuffer code comes from Chris Torek's SPARC 44bsd zs driver 1472 1.1 rumble * (hence the LBL notice on top of this file), DOES NOT require 1473 1.1 rumble * interlocking with interrupt levels! 1474 1.1 rumble * 1475 1.1 rumble * The 44bsd sparc/zs driver reads the ring buffer from a separate 1476 1.1 rumble * zssoftint, while the SunOS 4.x zs driver appears to use 1477 1.1 rumble * timeout()'s. timeouts seem to be too slow to deal with high data 1478 1.1 rumble * rates. I know, I tried them. 1479 1.1 rumble * -plb. 1480 1.1 rumble */ 1481 1.1 rumble static void 1482 1.1 rumble scnsoft(void *arg) 1483 1.1 rumble { 1484 1.1 rumble int s, unit; 1485 1.1 rumble #ifdef SCN_TIMING 1486 1.1 rumble struct timeval tend; 1487 1.1 rumble u_long t; 1488 1.1 rumble 1489 1.1 rumble microtime(&tend); 1490 1.1 rumble t = (tend.tv_sec - tstart.tv_sec) * 1000000 + (tend.tv_usec - tstart.tv_usec); 1491 1.1 rumble t = (t + tick / 20) / (tick / 10); 1492 1.1 rumble if (t >= NJITTER - 1) { 1493 1.1 rumble t = NJITTER - 1; 1494 1.1 rumble } 1495 1.1 rumble scn_jitter[t]++; 1496 1.1 rumble #endif 1497 1.1 rumble 1498 1.1 rumble for (unit = 0; unit < scn_cd.cd_ndevs; unit++) { 1499 1.1 rumble struct scn_softc *sc; 1500 1.1 rumble struct tty *tp; 1501 1.1 rumble int n, get; 1502 1.1 rumble 1503 1.1 rumble sc = SOFTC(unit); 1504 1.1 rumble if (sc == NULL) { 1505 1.1 rumble continue; 1506 1.1 rumble } 1507 1.1 rumble tp = sc->sc_tty; 1508 1.1 rumble #ifdef KGDB 1509 1.1 rumble if (tp == NULL) { 1510 1.1 rumble sc->sc_rbget = sc->sc_rbput; 1511 1.1 rumble continue; 1512 1.1 rumble } 1513 1.1 rumble #endif 1514 1.1 rumble if (tp == NULL || tp->t_state & TS_TBLOCK) { 1515 1.1 rumble continue; 1516 1.1 rumble } 1517 1.1 rumble 1518 1.1 rumble 1519 1.1 rumble get = sc->sc_rbget; 1520 1.1 rumble 1521 1.1 rumble /* NOTE: fetch from rbput is atomic */ 1522 1.1 rumble while (get != (n = sc->sc_rbput)) { 1523 1.1 rumble /* 1524 1.1 rumble * Compute the number of interrupts in the receive ring. 1525 1.1 rumble * If the count is overlarge, we lost some events, and 1526 1.1 rumble * must advance to the first valid one. It may get 1527 1.1 rumble * overwritten if more data are arriving, but this is 1528 1.1 rumble * too expensive to check and gains nothing (we already 1529 1.1 rumble * lost out; all we can do at this point is trade one 1530 1.1 rumble * kind of loss for another). 1531 1.1 rumble */ 1532 1.1 rumble n -= get; 1533 1.1 rumble if (n > SCN_RING_SIZE) { 1534 1.1 rumble scnoverrun(unit, &sc->sc_rotime, "ring"); 1535 1.1 rumble get += n - SCN_RING_SIZE; 1536 1.1 rumble n = SCN_RING_SIZE; 1537 1.1 rumble sc->sc_ring_overruns++; 1538 1.1 rumble } 1539 1.1 rumble while (--n >= 0) { 1540 1.1 rumble int c, sr; 1541 1.1 rumble 1542 1.1 rumble if (tp->t_state & TS_TBLOCK) { 1543 1.1 rumble sc->sc_rbget = get; 1544 1.1 rumble goto done; 1545 1.1 rumble } 1546 1.1 rumble /* Race to keep ahead of incoming interrupts. */ 1547 1.1 rumble c = sc->sc_rbuf[get++ & SCN_RING_MASK]; 1548 1.1 rumble 1549 1.1 rumble sr = c >> 8; /* extract status */ 1550 1.1 rumble c &= 0xff; /* leave just character */ 1551 1.1 rumble 1552 1.1 rumble if (sr & SR_OVERRUN) { 1553 1.1 rumble scnoverrun(unit, &sc->sc_fotime, "fifo"); 1554 1.1 rumble sc->sc_fifo_overruns++; 1555 1.1 rumble } 1556 1.1 rumble if (sr & SR_PARITY) { 1557 1.1 rumble c |= TTY_PE; 1558 1.1 rumble sc->sc_parity_errors++; 1559 1.1 rumble } 1560 1.1 rumble if (sr & SR_FRAME) { 1561 1.1 rumble c |= TTY_FE; 1562 1.1 rumble sc->sc_framing_errors++; 1563 1.1 rumble } 1564 1.1 rumble if (sr & SR_BREAK) { 1565 1.1 rumble #if 0 1566 1.1 rumble /* 1567 1.1 rumble * See DDB_CHECK() comments in 1568 1.1 rumble * scnrxintr() 1569 1.1 rumble */ 1570 1.1 rumble if (sc->sc_isconsole) 1571 1.1 rumble Debugger(); 1572 1.1 rumble #endif 1573 1.1 rumble c = TTY_FE | 0; 1574 1.1 rumble sc->sc_breaks++; 1575 1.1 rumble } 1576 1.1 rumble 1577 1.1 rumble (*tp->t_linesw->l_rint) (c, tp); 1578 1.1 rumble 1579 1.1 rumble if (sc->sc_rx_blocked && n < SCN_RING_THRESH) { 1580 1.1 rumble s = splrtty(); 1581 1.1 rumble sc->sc_rx_blocked = 0; 1582 1.1 rumble SCN_OP_BIS(sc, sc->sc_op_rts); 1583 1.1 rumble splx(s); 1584 1.1 rumble } 1585 1.1 rumble 1586 1.1 rumble } 1587 1.1 rumble sc->sc_rbget = get; 1588 1.1 rumble } 1589 1.1 rumble done: ; 1590 1.1 rumble } 1591 1.1 rumble } 1592 1.1 rumble 1593 1.1 rumble /* Convert TIOCM_xxx bits to output port bits. */ 1594 1.1 rumble static unsigned char 1595 1.1 rumble opbits(struct scn_softc *sc, int tioc_bits) 1596 1.1 rumble { 1597 1.1 rumble 1598 1.1 rumble return ((((tioc_bits) & TIOCM_DTR) ? sc->sc_op_dtr : 0) | 1599 1.1 rumble (((tioc_bits) & TIOCM_RTS) ? sc->sc_op_rts : 0)); 1600 1.1 rumble } 1601 1.1 rumble 1602 1.1 rumble int 1603 1.1 rumble scnioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 1604 1.1 rumble { 1605 1.1 rumble int unit = DEV_UNIT(dev); 1606 1.1 rumble struct scn_softc *sc = SOFTC(unit); 1607 1.1 rumble struct tty *tp = sc->sc_tty; 1608 1.1 rumble int error; 1609 1.1 rumble 1610 1.1 rumble error = (*tp->t_linesw->l_ioctl) (tp, cmd, data, flags, l); 1611 1.1 rumble if (error != EPASSTHROUGH) 1612 1.1 rumble return (error); 1613 1.1 rumble 1614 1.1 rumble error = ttioctl(tp, cmd, data, flags, l); 1615 1.1 rumble if (error != EPASSTHROUGH) 1616 1.1 rumble return (error); 1617 1.1 rumble 1618 1.1 rumble switch (cmd) { 1619 1.1 rumble case TIOCSBRK: 1620 1.1 rumble sc->sc_chbase[CH_CR] = CR_CMD_START_BRK; 1621 1.1 rumble break; 1622 1.1 rumble 1623 1.1 rumble case TIOCCBRK: 1624 1.1 rumble sc->sc_chbase[CH_CR] = CR_CMD_STOP_BRK; 1625 1.1 rumble break; 1626 1.1 rumble 1627 1.1 rumble case TIOCSDTR: 1628 1.1 rumble SCN_OP_BIS(sc, sc->sc_op_dtr | sc->sc_op_rts); 1629 1.1 rumble break; 1630 1.1 rumble 1631 1.1 rumble case TIOCCDTR: 1632 1.1 rumble SCN_OP_BIC(sc, sc->sc_op_dtr | sc->sc_op_rts); 1633 1.1 rumble break; 1634 1.1 rumble 1635 1.1 rumble case TIOCMSET: { 1636 1.1 rumble int s; 1637 1.1 rumble unsigned char sbits, cbits; 1638 1.1 rumble 1639 1.1 rumble /* set bits */ 1640 1.1 rumble sbits = opbits(sc, *(int *) data); 1641 1.1 rumble 1642 1.1 rumble /* get bits to clear */ 1643 1.1 rumble cbits = ~sbits & (sc->sc_op_dtr | sc->sc_op_rts); 1644 1.1 rumble 1645 1.1 rumble s = spltty(); 1646 1.1 rumble if (sbits) { 1647 1.1 rumble SCN_OP_BIS(sc, sbits); 1648 1.1 rumble } 1649 1.1 rumble if (cbits) { 1650 1.1 rumble SCN_OP_BIC(sc, cbits); 1651 1.1 rumble } 1652 1.1 rumble splx(s); 1653 1.1 rumble break; 1654 1.1 rumble } 1655 1.1 rumble 1656 1.1 rumble case TIOCMBIS: 1657 1.1 rumble SCN_OP_BIS(sc, opbits(sc, *(int *) data)); 1658 1.1 rumble break; 1659 1.1 rumble 1660 1.1 rumble case TIOCMBIC: 1661 1.1 rumble SCN_OP_BIC(sc, opbits(sc, *(int *) data)); 1662 1.1 rumble break; 1663 1.1 rumble 1664 1.1 rumble case TIOCMGET: { 1665 1.1 rumble int bits; 1666 1.6 christos unsigned char ip; 1667 1.1 rumble 1668 1.1 rumble /* s = spltty(); */ 1669 1.1 rumble ip = sc->sc_duart->base[DU_IP]; 1670 1.1 rumble /* splx(s); */ 1671 1.1 rumble 1672 1.1 rumble bits = 0; 1673 1.1 rumble if (ip & sc->sc_ip_dcd) 1674 1.1 rumble bits |= TIOCM_CD; 1675 1.1 rumble if (ip & sc->sc_ip_cts) 1676 1.1 rumble bits |= TIOCM_CTS; 1677 1.1 rumble 1678 1.1 rumble #if 0 1679 1.6 christos /* 1680 1.6 christos * XXX sigh; cannot get op current state!! even if 1681 1.6 christos * maintained in private, RTS is done in h/w!! 1682 1.6 christos */ 1683 1.6 christos unsigned char op = 0; 1684 1.1 rumble if (op & sc->sc_op_dtr) 1685 1.1 rumble bits |= TIOCM_DTR; 1686 1.1 rumble if (op & sc->sc_op_rts) 1687 1.1 rumble bits |= TIOCM_RTS; 1688 1.1 rumble #endif 1689 1.1 rumble 1690 1.1 rumble *(int *) data = bits; 1691 1.1 rumble break; 1692 1.1 rumble } 1693 1.1 rumble 1694 1.1 rumble case TIOCGFLAGS:{ 1695 1.1 rumble int bits = 0; 1696 1.1 rumble 1697 1.1 rumble if (sc->sc_swflags & SCN_SW_SOFTCAR) 1698 1.1 rumble bits |= TIOCFLAG_SOFTCAR; 1699 1.1 rumble if (sc->sc_swflags & SCN_SW_CLOCAL) 1700 1.1 rumble bits |= TIOCFLAG_CLOCAL; 1701 1.1 rumble if (sc->sc_swflags & SCN_SW_CRTSCTS) 1702 1.1 rumble bits |= TIOCFLAG_CRTSCTS; 1703 1.1 rumble if (sc->sc_swflags & SCN_SW_MDMBUF) 1704 1.1 rumble bits |= TIOCFLAG_MDMBUF; 1705 1.1 rumble 1706 1.1 rumble *(int *) data = bits; 1707 1.1 rumble break; 1708 1.1 rumble } 1709 1.1 rumble case TIOCSFLAGS:{ 1710 1.1 rumble int userbits, driverbits = 0; 1711 1.1 rumble 1712 1.1 rumble error = kauth_authorize_device_tty(l->l_cred, 1713 1.1 rumble KAUTH_DEVICE_TTY_PRIVSET, tp); 1714 1.1 rumble if (error != 0) 1715 1.1 rumble return (EPERM); 1716 1.1 rumble 1717 1.1 rumble userbits = *(int *) data; 1718 1.1 rumble if (userbits & TIOCFLAG_SOFTCAR) 1719 1.1 rumble driverbits |= SCN_SW_SOFTCAR; 1720 1.1 rumble if (userbits & TIOCFLAG_CLOCAL) 1721 1.1 rumble driverbits |= SCN_SW_CLOCAL; 1722 1.1 rumble if (userbits & TIOCFLAG_CRTSCTS) 1723 1.1 rumble driverbits |= SCN_SW_CRTSCTS; 1724 1.1 rumble if (userbits & TIOCFLAG_MDMBUF) 1725 1.1 rumble driverbits |= SCN_SW_MDMBUF; 1726 1.1 rumble 1727 1.1 rumble sc->sc_swflags = driverbits; 1728 1.1 rumble 1729 1.1 rumble break; 1730 1.1 rumble } 1731 1.1 rumble 1732 1.1 rumble default: 1733 1.1 rumble return (EPASSTHROUGH); 1734 1.1 rumble } 1735 1.1 rumble return (0); 1736 1.1 rumble } 1737 1.1 rumble 1738 1.1 rumble int 1739 1.1 rumble scnparam(struct tty *tp, struct termios *t) 1740 1.1 rumble { 1741 1.1 rumble int cflag = t->c_cflag; 1742 1.1 rumble int unit = DEV_UNIT(tp->t_dev); 1743 1.1 rumble char mr1, mr2; 1744 1.1 rumble int error; 1745 1.1 rumble struct scn_softc *sc = SOFTC(unit); 1746 1.1 rumble 1747 1.1 rumble /* Is this a hang up? */ 1748 1.1 rumble if (t->c_ospeed == B0) { 1749 1.1 rumble SCN_OP_BIC(sc, sc->sc_op_dtr); 1750 1.1 rumble /* leave DTR down. see comment in scnclose() -plb */ 1751 1.1 rumble return (0); 1752 1.1 rumble } 1753 1.1 rumble mr1 = mr2 = 0; 1754 1.1 rumble 1755 1.1 rumble /* Parity? */ 1756 1.1 rumble if (cflag & PARENB) { 1757 1.1 rumble if ((cflag & PARODD) == 0) 1758 1.1 rumble mr1 |= MR1_PEVEN; 1759 1.1 rumble else 1760 1.1 rumble mr1 |= MR1_PODD; 1761 1.1 rumble } else 1762 1.1 rumble mr1 |= MR1_PNONE; 1763 1.1 rumble 1764 1.1 rumble /* Stop bits. */ 1765 1.1 rumble if (cflag & CSTOPB) 1766 1.1 rumble mr2 |= MR2_STOP2; 1767 1.1 rumble else 1768 1.1 rumble mr2 |= MR2_STOP1; 1769 1.1 rumble 1770 1.1 rumble /* Data bits. */ 1771 1.1 rumble switch (cflag & CSIZE) { 1772 1.1 rumble case CS5: 1773 1.1 rumble mr1 |= MR1_CS5; 1774 1.1 rumble break; 1775 1.1 rumble case CS6: 1776 1.1 rumble mr1 |= MR1_CS6; 1777 1.1 rumble break; 1778 1.1 rumble case CS7: 1779 1.1 rumble mr1 |= MR1_CS7; 1780 1.1 rumble break; 1781 1.1 rumble case CS8: 1782 1.1 rumble default: 1783 1.1 rumble mr1 |= MR1_CS8; 1784 1.1 rumble break; 1785 1.1 rumble } 1786 1.1 rumble 1787 1.1 rumble if (cflag & CCTS_OFLOW) 1788 1.1 rumble mr2 |= MR2_TXCTS; 1789 1.1 rumble 1790 1.1 rumble if (cflag & CRTS_IFLOW) { 1791 1.1 rumble mr1 |= MR1_RXRTS; 1792 1.1 rumble sc->sc_rbhiwat = SCN_RING_HIWAT; 1793 1.1 rumble } else { 1794 1.1 rumble sc->sc_rbhiwat = 0; 1795 1.1 rumble } 1796 1.1 rumble 1797 1.1 rumble error = scn_config(unit, sc->sc_channel, t->c_ispeed, 1798 1.1 rumble t->c_ospeed, mr1, mr2); 1799 1.1 rumble 1800 1.1 rumble /* If successful, copy to tty */ 1801 1.1 rumble if (!error) { 1802 1.1 rumble tp->t_ispeed = t->c_ispeed; 1803 1.1 rumble tp->t_ospeed = t->c_ospeed; 1804 1.1 rumble tp->t_cflag = cflag; 1805 1.1 rumble } 1806 1.1 rumble return (error); 1807 1.1 rumble } 1808 1.1 rumble 1809 1.1 rumble /* 1810 1.1 rumble * Start or restart a transmission. 1811 1.1 rumble */ 1812 1.1 rumble void 1813 1.1 rumble scnstart(struct tty *tp) 1814 1.1 rumble { 1815 1.1 rumble int s, c; 1816 1.1 rumble int unit = DEV_UNIT(tp->t_dev); 1817 1.1 rumble struct scn_softc *sc = SOFTC(unit); 1818 1.1 rumble 1819 1.1 rumble s = spltty(); 1820 1.1 rumble if (tp->t_state & (TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 1821 1.1 rumble goto out; 1822 1.1 rumble if (!ttypull(tp)) 1823 1.1 rumble goto out; 1824 1.1 rumble 1825 1.1 rumble tp->t_state |= TS_BUSY; 1826 1.1 rumble 1827 1.1 rumble while (sc->sc_chbase[CH_SR] & SR_TX_RDY) { 1828 1.1 rumble if ((c = getc(&tp->t_outq)) == -1) 1829 1.1 rumble break; 1830 1.1 rumble sc->sc_chbase[CH_DAT] = c; 1831 1.1 rumble } 1832 1.1 rumble sc->sc_duart->imr |= (sc->sc_tx_int | sc->sc_rx_int); 1833 1.1 rumble sc->sc_duart->base[DU_IMR] = sc->sc_duart->imr; 1834 1.1 rumble 1835 1.1 rumble out: 1836 1.1 rumble splx(s); 1837 1.1 rumble } 1838 1.1 rumble 1839 1.1 rumble /* 1840 1.1 rumble * Stop output on a line. 1841 1.1 rumble */ 1842 1.1 rumble /*ARGSUSED*/ 1843 1.1 rumble void 1844 1.1 rumble scnstop(struct tty *tp, int flags) 1845 1.1 rumble { 1846 1.1 rumble int s; 1847 1.1 rumble 1848 1.1 rumble s = spltty(); 1849 1.1 rumble if (tp->t_state & TS_BUSY) { 1850 1.1 rumble if ((tp->t_state & TS_TTSTOP) == 0) 1851 1.1 rumble tp->t_state |= TS_FLUSH; 1852 1.1 rumble } 1853 1.1 rumble splx(s); 1854 1.1 rumble } 1855 1.1 rumble 1856 1.1 rumble /* 1857 1.1 rumble * Following are all routines needed for SCN to act as console. 1858 1.1 rumble */ 1859 1.1 rumble 1860 1.1 rumble void 1861 1.1 rumble scncnprobe(struct consdev *cn) 1862 1.1 rumble { 1863 1.1 rumble } 1864 1.1 rumble 1865 1.1 rumble void 1866 1.1 rumble scncnreinit(void *v) 1867 1.1 rumble { 1868 1.1 rumble volatile u_char *du_base = 1869 1.1 rumble (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004); 1870 1.1 rumble 1871 1.1 rumble du_base[DU_OPSET] = 1872 1.1 rumble SCN_CONSCHAN ? (OP_RTSB | OP_DTRB) : (OP_RTSA | OP_DTRA); 1873 1.1 rumble } 1874 1.1 rumble 1875 1.1 rumble void 1876 1.1 rumble scncninit(struct consdev *cn) 1877 1.1 rumble { 1878 1.1 rumble devmajor_t major; 1879 1.1 rumble 1880 1.1 rumble /* initialize required fields */ 1881 1.1 rumble major = cdevsw_lookup_major(&scn_cdevsw); 1882 1.1 rumble KASSERT(major != NODEV); 1883 1.1 rumble cn->cn_dev = makedev(major, SCN_CONSOLE); 1884 1.1 rumble cn->cn_pri = CN_REMOTE; 1885 1.1 rumble 1886 1.1 rumble scninit(cn->cn_dev, scnconsrate); 1887 1.1 rumble } 1888 1.1 rumble 1889 1.1 rumble /* Used by scncninit and kgdb startup. */ 1890 1.1 rumble int 1891 1.1 rumble scninit(dev_t dev, int rate) 1892 1.1 rumble { 1893 1.1 rumble /* XXX - maintain PROM's settings */ 1894 1.1 rumble #if 0 1895 1.1 rumble volatile u_char *du_base = 1896 1.1 rumble (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004); 1897 1.1 rumble int unit = DEV_UNIT(dev); 1898 1.1 rumble 1899 1.1 rumble du_base[DU_OPSET] = 1900 1.1 rumble SCN_CONSCHAN ? (OP_RTSB | OP_DTRB) : (OP_RTSA | OP_DTRA); 1901 1.1 rumble scn_config(unit, SCN_CONSCHAN, rate, rate, 1902 1.1 rumble MR1_PNONE | MR1_CS8, MR2_STOP1); 1903 1.1 rumble #endif 1904 1.1 rumble return (0); 1905 1.1 rumble } 1906 1.1 rumble 1907 1.1 rumble /* 1908 1.1 rumble * Console kernel input character routine. 1909 1.1 rumble */ 1910 1.1 rumble int 1911 1.1 rumble scncngetc(dev_t dev) 1912 1.1 rumble { 1913 1.1 rumble volatile u_char *ch_base = 1914 1.1 rumble (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004); 1915 1.1 rumble char c; 1916 1.1 rumble int s; 1917 1.1 rumble 1918 1.1 rumble s = spltty(); 1919 1.1 rumble 1920 1.1 rumble while ((ch_base[CH_SR] & SR_RX_RDY) == 0) 1921 1.1 rumble ; 1922 1.1 rumble c = ch_base[CH_DAT]; 1923 1.1 rumble 1924 1.1 rumble splx(s); 1925 1.1 rumble return c; 1926 1.1 rumble } 1927 1.1 rumble 1928 1.1 rumble void 1929 1.1 rumble scncnpollc(dev_t dev, int on) 1930 1.1 rumble { 1931 1.1 rumble } 1932 1.1 rumble 1933 1.1 rumble /* 1934 1.1 rumble * Console kernel output character routine. 1935 1.1 rumble */ 1936 1.1 rumble void 1937 1.1 rumble scncnputc(dev_t dev, int c) 1938 1.1 rumble { 1939 1.1 rumble volatile u_char *ch_base = 1940 1.1 rumble (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004); 1941 1.1 rumble volatile u_char *du_base = 1942 1.1 rumble (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004); 1943 1.1 rumble int s; 1944 1.1 rumble 1945 1.1 rumble s = spltty(); 1946 1.1 rumble 1947 1.1 rumble if (c == '\n') 1948 1.1 rumble scncnputc(dev, '\r'); 1949 1.1 rumble 1950 1.1 rumble while ((ch_base[CH_SR] & SR_TX_RDY) == 0) 1951 1.1 rumble ; 1952 1.1 rumble ch_base[CH_DAT] = c; 1953 1.1 rumble while ((ch_base[CH_SR] & SR_TX_RDY) == 0) 1954 1.1 rumble ; 1955 1.1 rumble du_base[DU_ISR]; 1956 1.1 rumble 1957 1.1 rumble splx(s); 1958 1.1 rumble } 1959