1 /* $NetBSD: pcons.c,v 1.1 2000/05/20 14:23:12 eeh Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Eduardo E. Horvath 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * Default console driver. Uses the PROM or whatever 33 * driver(s) are appropriate. 34 */ 35 36 #include "opt_ddb.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/conf.h> 41 #include <sys/device.h> 42 #include <sys/file.h> 43 #include <sys/ioctl.h> 44 #include <sys/kernel.h> 45 #include <sys/proc.h> 46 #include <sys/tty.h> 47 #include <sys/time.h> 48 #include <sys/syslog.h> 49 50 #include <machine/autoconf.h> 51 #include <machine/openfirm.h> 52 #include <machine/bsd_openprom.h> 53 #include <machine/conf.h> 54 #include <machine/cpu.h> 55 #include <machine/eeprom.h> 56 #include <machine/psl.h> 57 #include <machine/z8530var.h> 58 59 #include <dev/cons.h> 60 61 #include <sparc64/sparc64/vaddrs.h> 62 #include <sparc64/dev/cons.h> 63 64 static int pconsmatch __P((struct device *, struct cfdata *, void *)); 65 static void pconsattach __P((struct device *, struct device *, void *)); 66 67 struct cfattach pcons_ca = { 68 sizeof(struct pconssoftc), pconsmatch, pconsattach 69 }; 70 71 extern struct cfdriver pcons_cd; 72 73 static int pconsprobe __P((void)); 74 75 static int 76 pconsmatch(parent, match, aux) 77 struct device *parent; 78 struct cfdata *match; 79 void *aux; 80 { 81 struct mainbus_attach_args *ma = aux; 82 extern struct consdev *cn_tab; 83 extern int prom_cngetc __P((dev_t)); 84 85 /* Only attach if no other console has attached. */ 86 return ((strcmp("pcons", ma->ma_name) == 0) && 87 (cn_tab->cn_getc == prom_cngetc)); 88 89 } 90 91 static void 92 pconsattach(parent, self, aux) 93 struct device *parent, *self; 94 void *aux; 95 { 96 struct pconssoftc *sc = (struct pconssoftc *) self; 97 98 printf("\n"); 99 if (!pconsprobe()) 100 return; 101 102 callout_init(&sc->sc_poll_ch); 103 } 104 105 static void pconsstart __P((struct tty *)); 106 static int pconsparam __P((struct tty *, struct termios *)); 107 static void pcons_poll __P((void *)); 108 109 int 110 pconsopen(dev, flag, mode, p) 111 dev_t dev; 112 int flag, mode; 113 struct proc *p; 114 { 115 struct pconssoftc *sc; 116 int unit = minor(dev); 117 struct tty *tp; 118 119 if (unit >= pcons_cd.cd_ndevs) 120 return ENXIO; 121 sc = pcons_cd.cd_devs[unit]; 122 if (!sc) 123 return ENXIO; 124 if (!(tp = sc->of_tty)) 125 sc->of_tty = tp = ttymalloc(); 126 tp->t_oproc = pconsstart; 127 tp->t_param = pconsparam; 128 tp->t_dev = dev; 129 if (!(tp->t_state & TS_ISOPEN)) { 130 ttychars(tp); 131 tp->t_iflag = TTYDEF_IFLAG; 132 tp->t_oflag = TTYDEF_OFLAG; 133 tp->t_cflag = TTYDEF_CFLAG; 134 tp->t_lflag = TTYDEF_LFLAG; 135 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 136 pconsparam(tp, &tp->t_termios); 137 ttsetwater(tp); 138 } else if ((tp->t_state&TS_XCLUDE) && suser(p->p_ucred, &p->p_acflag)) 139 return EBUSY; 140 tp->t_state |= TS_CARR_ON; 141 142 if (!(sc->of_flags & OFPOLL)) { 143 sc->of_flags |= OFPOLL; 144 callout_reset(&sc->sc_poll_ch, 1, pcons_poll, sc); 145 } 146 147 return (*linesw[tp->t_line].l_open)(dev, tp); 148 } 149 150 int 151 pconsclose(dev, flag, mode, p) 152 dev_t dev; 153 int flag, mode; 154 struct proc *p; 155 { 156 struct pconssoftc *sc = pcons_cd.cd_devs[minor(dev)]; 157 struct tty *tp = sc->of_tty; 158 159 callout_stop(&sc->sc_poll_ch); 160 sc->of_flags &= ~OFPOLL; 161 (*linesw[tp->t_line].l_close)(tp, flag); 162 ttyclose(tp); 163 return 0; 164 } 165 166 int 167 pconsread(dev, uio, flag) 168 dev_t dev; 169 struct uio *uio; 170 int flag; 171 { 172 struct pconssoftc *sc = pcons_cd.cd_devs[minor(dev)]; 173 struct tty *tp = sc->of_tty; 174 175 return (*linesw[tp->t_line].l_read)(tp, uio, flag); 176 } 177 178 int 179 pconswrite(dev, uio, flag) 180 dev_t dev; 181 struct uio *uio; 182 int flag; 183 { 184 struct pconssoftc *sc = pcons_cd.cd_devs[minor(dev)]; 185 struct tty *tp = sc->of_tty; 186 187 return (*linesw[tp->t_line].l_write)(tp, uio, flag); 188 } 189 190 int 191 pconsioctl(dev, cmd, data, flag, p) 192 dev_t dev; 193 u_long cmd; 194 caddr_t data; 195 int flag; 196 struct proc *p; 197 { 198 struct pconssoftc *sc = pcons_cd.cd_devs[minor(dev)]; 199 struct tty *tp = sc->of_tty; 200 int error; 201 202 if ((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p)) >= 0) 203 return error; 204 if ((error = ttioctl(tp, cmd, data, flag, p)) >= 0) 205 return error; 206 return ENOTTY; 207 } 208 209 struct tty * 210 pconstty(dev) 211 dev_t dev; 212 { 213 struct pconssoftc *sc = pcons_cd.cd_devs[minor(dev)]; 214 215 return sc->of_tty; 216 } 217 218 void 219 pconsstop(tp, flag) 220 struct tty *tp; 221 int flag; 222 { 223 } 224 225 static void 226 pconsstart(tp) 227 struct tty *tp; 228 { 229 struct clist *cl; 230 int s, len; 231 u_char buf[OFBURSTLEN]; 232 233 s = spltty(); 234 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { 235 splx(s); 236 return; 237 } 238 tp->t_state |= TS_BUSY; 239 splx(s); 240 cl = &tp->t_outq; 241 len = q_to_b(cl, buf, OFBURSTLEN); 242 OF_write(stdout, buf, len); 243 s = spltty(); 244 tp->t_state &= ~TS_BUSY; 245 if (cl->c_cc) { 246 tp->t_state |= TS_TIMEOUT; 247 callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, (void *)tp); 248 } 249 if (cl->c_cc <= tp->t_lowat) { 250 if (tp->t_state & TS_ASLEEP) { 251 tp->t_state &= ~TS_ASLEEP; 252 wakeup(cl); 253 } 254 selwakeup(&tp->t_wsel); 255 } 256 splx(s); 257 } 258 259 static int 260 pconsparam(tp, t) 261 struct tty *tp; 262 struct termios *t; 263 { 264 tp->t_ispeed = t->c_ispeed; 265 tp->t_ospeed = t->c_ospeed; 266 tp->t_cflag = t->c_cflag; 267 return 0; 268 } 269 270 static void 271 pcons_poll(aux) 272 void *aux; 273 { 274 struct pconssoftc *sc = aux; 275 struct tty *tp = sc->of_tty; 276 char ch; 277 278 while (OF_read(stdin, &ch, 1) > 0) { 279 if (tp && (tp->t_state & TS_ISOPEN)) 280 (*linesw[tp->t_line].l_rint)(ch, tp); 281 } 282 callout_reset(&sc->sc_poll_ch, 1, pcons_poll, sc); 283 } 284 285 int 286 pconsprobe() 287 { 288 if (!stdin) stdin = OF_stdin(); 289 if (!stdout) stdout = OF_stdout(); 290 291 return (stdin && stdout); 292 } 293 294 void 295 pcons_cnpollc(dev, on) 296 dev_t dev; 297 int on; 298 { 299 struct pconssoftc *sc = NULL; 300 301 if (pcons_cd.cd_devs) 302 sc = pcons_cd.cd_devs[minor(dev)]; 303 304 if (on) { 305 if (!sc) return; 306 if (sc->of_flags & OFPOLL) 307 callout_stop(&sc->sc_poll_ch); 308 sc->of_flags &= ~OFPOLL; 309 } else { 310 /* Resuming kernel. */ 311 if (sc && !(sc->of_flags & OFPOLL)) { 312 sc->of_flags |= OFPOLL; 313 callout_reset(&sc->sc_poll_ch, 1, pcons_poll, sc); 314 } 315 } 316 } 317