1 /* $NetBSD: arcbios_tty.c,v 1.11 2005/12/11 12:21:14 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: arcbios_tty.c,v 1.11 2005/12/11 12:21:14 christos Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/user.h> 35 #include <sys/uio.h> 36 #include <sys/systm.h> 37 #include <sys/callout.h> 38 #include <sys/kernel.h> 39 #include <sys/conf.h> 40 #include <sys/proc.h> 41 #include <sys/tty.h> 42 #include <sys/termios.h> 43 44 #include <dev/cons.h> 45 46 #include <dev/arcbios/arcbios.h> 47 #include <dev/arcbios/arcbiosvar.h> 48 49 struct callout arcbios_tty_ch = CALLOUT_INITIALIZER; 50 51 static struct tty *arcbios_tty[1]; 52 53 void arcbios_tty_start(struct tty *); 54 void arcbios_tty_poll(void *); 55 int arcbios_tty_param(struct tty *, struct termios *); 56 57 dev_type_open(arcbios_ttyopen); 58 dev_type_close(arcbios_ttyclose); 59 dev_type_read(arcbios_ttyread); 60 dev_type_write(arcbios_ttywrite); 61 dev_type_ioctl(arcbios_ttyioctl); 62 dev_type_stop(arcbios_ttystop); 63 dev_type_tty(arcbios_ttytty); 64 dev_type_poll(arcbios_ttypoll); 65 66 const struct cdevsw arcbios_cdevsw = { 67 arcbios_ttyopen, arcbios_ttyclose, arcbios_ttyread, arcbios_ttywrite, 68 arcbios_ttyioctl, arcbios_ttystop, arcbios_ttytty, arcbios_ttypoll, 69 nommap, ttykqfilter, D_TTY, 70 }; 71 72 int 73 arcbios_ttyopen(dev_t dev, int flag, int mode, struct lwp *l) 74 { 75 int unit = minor(dev); 76 struct tty *tp; 77 int s, error = 0, setuptimeout = 0; 78 79 if (unit != 0) 80 return (ENODEV); 81 82 s = spltty(); 83 84 if (arcbios_tty[unit] == NULL) { 85 tp = arcbios_tty[unit] = ttymalloc(); 86 tty_attach(tp); 87 } else 88 tp = arcbios_tty[unit]; 89 90 tp->t_oproc = arcbios_tty_start; 91 tp->t_param = arcbios_tty_param; 92 tp->t_dev = dev; 93 if ((tp->t_state & TS_ISOPEN) == 0) { 94 tp->t_state |= TS_CARR_ON; 95 ttychars(tp); 96 tp->t_iflag = TTYDEF_IFLAG; 97 tp->t_oflag = TTYDEF_OFLAG; 98 tp->t_cflag = TTYDEF_CFLAG | CLOCAL; 99 tp->t_lflag = TTYDEF_LFLAG; 100 tp->t_ispeed = tp->t_ospeed = 9600; 101 ttsetwater(tp); 102 103 setuptimeout = 1; 104 } else if (tp->t_state & TS_XCLUDE && 105 suser(l->l_proc->p_ucred, &l->l_proc->p_acflag) != 0) { 106 splx(s); 107 return (EBUSY); 108 } 109 110 splx(s); 111 112 error = (*tp->t_linesw->l_open)(dev, tp); 113 if (error == 0 && setuptimeout) 114 callout_reset(&arcbios_tty_ch, 1, arcbios_tty_poll, tp); 115 116 return (error); 117 } 118 119 int 120 arcbios_ttyclose(dev_t dev, int flag, int mode, struct lwp *l) 121 { 122 int unit = minor(dev); 123 struct tty *tp = arcbios_tty[unit]; 124 125 callout_stop(&arcbios_tty_ch); 126 (*tp->t_linesw->l_close)(tp, flag); 127 ttyclose(tp); 128 return (0); 129 } 130 131 int 132 arcbios_ttyread(dev_t dev, struct uio *uio, int flag) 133 { 134 struct tty *tp = arcbios_tty[minor(dev)]; 135 136 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 137 } 138 139 int 140 arcbios_ttywrite(dev_t dev, struct uio *uio, int flag) 141 { 142 struct tty *tp = arcbios_tty[minor(dev)]; 143 144 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 145 } 146 147 int 148 arcbios_ttypoll(dev_t dev, int events, struct lwp *l) 149 { 150 struct tty *tp = arcbios_tty[minor(dev)]; 151 152 return ((*tp->t_linesw->l_poll)(tp, events, l)); 153 } 154 155 int 156 arcbios_ttyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l) 157 { 158 int unit = minor(dev); 159 struct tty *tp = arcbios_tty[unit]; 160 int error; 161 162 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 163 if (error != EPASSTHROUGH) 164 return (error); 165 return (ttioctl(tp, cmd, data, flag, l)); 166 } 167 168 int 169 arcbios_tty_param(struct tty *tp, struct termios *t) 170 { 171 172 return (0); 173 } 174 175 void 176 arcbios_tty_start(struct tty *tp) 177 { 178 u_long count; 179 int s; 180 181 s = spltty(); 182 if (tp->t_state & (TS_TTSTOP | TS_BUSY)) 183 goto out; 184 if (tp->t_outq.c_cc <= tp->t_lowat) { 185 if (tp->t_state & TS_ASLEEP) { 186 tp->t_state &= ~TS_ASLEEP; 187 wakeup((caddr_t)&tp->t_outq); 188 } 189 selwakeup(&tp->t_wsel); 190 } 191 tp->t_state |= TS_BUSY; 192 while (tp->t_outq.c_cc != 0) { 193 (*ARCBIOS->Write)(ARCBIOS_STDOUT, tp->t_outq.c_cf, 194 ndqb(&tp->t_outq, 0), &count); 195 ndflush(&tp->t_outq, count); 196 } 197 tp->t_state &= ~TS_BUSY; 198 out: 199 splx(s); 200 } 201 202 void 203 arcbios_ttystop(struct tty *tp, int flag) 204 { 205 int s; 206 207 s = spltty(); 208 if (tp->t_state & TS_BUSY) 209 if ((tp->t_state & TS_TTSTOP) == 0) 210 tp->t_state |= TS_FLUSH; 211 splx(s); 212 } 213 214 static int 215 arcbios_tty_getchar(int *cp) 216 { 217 char c; 218 int32_t q; 219 u_long count; 220 221 q = ARCBIOS->GetReadStatus(ARCBIOS_STDIN); 222 223 if (q == 0) { 224 ARCBIOS->Read(ARCBIOS_STDIN, &c, 1, &count); 225 *cp = c; 226 227 return 1; 228 } 229 230 return 0; 231 } 232 233 void 234 arcbios_tty_poll(void *v) 235 { 236 struct tty *tp = v; 237 int c, l_r; 238 239 while (arcbios_tty_getchar(&c)) { 240 if (tp->t_state & TS_ISOPEN) 241 l_r = (*tp->t_linesw->l_rint)(c, tp); 242 } 243 callout_reset(&arcbios_tty_ch, 1, arcbios_tty_poll, tp); 244 } 245 246 struct tty * 247 arcbios_ttytty(dev_t dev) 248 { 249 250 if (minor(dev) != 0) 251 panic("arcbios_ttytty: bogus"); 252 253 return (arcbios_tty[0]); 254 } 255