1 /* $NetBSD: arcbios_tty.c,v 1.4 2002/03/17 19:40:54 atatat 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.4 2002/03/17 19:40:54 atatat 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 cdev_decl(arcbios_tty); 58 59 int 60 arcbios_ttyopen(dev_t dev, int flag, int mode, struct proc *p) 61 { 62 int unit = minor(dev); 63 struct tty *tp; 64 int s, error = 0, setuptimeout = 0; 65 66 if (unit != 0) 67 return (ENODEV); 68 69 s = spltty(); 70 71 if (arcbios_tty[unit] == NULL) { 72 tp = arcbios_tty[unit] = ttymalloc(); 73 tty_attach(tp); 74 } else 75 tp = arcbios_tty[unit]; 76 77 tp->t_oproc = arcbios_tty_start; 78 tp->t_param = arcbios_tty_param; 79 tp->t_dev = dev; 80 if ((tp->t_state & TS_ISOPEN) == 0) { 81 tp->t_state |= TS_CARR_ON; 82 ttychars(tp); 83 tp->t_iflag = TTYDEF_IFLAG; 84 tp->t_oflag = TTYDEF_OFLAG; 85 tp->t_cflag = TTYDEF_CFLAG | CLOCAL; 86 tp->t_lflag = TTYDEF_LFLAG; 87 tp->t_ispeed = tp->t_ospeed = 9600; 88 ttsetwater(tp); 89 90 setuptimeout = 1; 91 } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 92 splx(s); 93 return (EBUSY); 94 } 95 96 splx(s); 97 98 error = (*tp->t_linesw->l_open)(dev, tp); 99 if (error == 0 && setuptimeout) 100 callout_reset(&arcbios_tty_ch, 1, arcbios_tty_poll, tp); 101 102 return (error); 103 } 104 105 int 106 arcbios_ttyclose(dev_t dev, int flag, int mode, struct proc *p) 107 { 108 int unit = minor(dev); 109 struct tty *tp = arcbios_tty[unit]; 110 111 callout_stop(&arcbios_tty_ch); 112 (*tp->t_linesw->l_close)(tp, flag); 113 ttyclose(tp); 114 return (0); 115 } 116 117 int 118 arcbios_ttyread(dev_t dev, struct uio *uio, int flag) 119 { 120 struct tty *tp = arcbios_tty[minor(dev)]; 121 122 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 123 } 124 125 int 126 arcbios_ttywrite(dev_t dev, struct uio *uio, int flag) 127 { 128 struct tty *tp = arcbios_tty[minor(dev)]; 129 130 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 131 } 132 133 int 134 arcbios_ttypoll(dev_t dev, int events, struct proc *p) 135 { 136 struct tty *tp = arcbios_tty[minor(dev)]; 137 138 return ((*tp->t_linesw->l_poll)(tp, events, p)); 139 } 140 141 int 142 arcbios_ttyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 143 { 144 int unit = minor(dev); 145 struct tty *tp = arcbios_tty[unit]; 146 int error; 147 148 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 149 if (error != EPASSTHROUGH) 150 return (error); 151 return (ttioctl(tp, cmd, data, flag, p)); 152 } 153 154 int 155 arcbios_tty_param(struct tty *tp, struct termios *t) 156 { 157 158 return (0); 159 } 160 161 void 162 arcbios_tty_start(struct tty *tp) 163 { 164 uint32_t count; 165 int s; 166 167 s = spltty(); 168 if (tp->t_state & (TS_TTSTOP | TS_BUSY)) 169 goto out; 170 if (tp->t_outq.c_cc <= tp->t_lowat) { 171 if (tp->t_state & TS_ASLEEP) { 172 tp->t_state &= ~TS_ASLEEP; 173 wakeup((caddr_t)&tp->t_outq); 174 } 175 selwakeup(&tp->t_wsel); 176 } 177 tp->t_state |= TS_BUSY; 178 while (tp->t_outq.c_cc != 0) { 179 (*ARCBIOS->Write)(ARCBIOS_STDOUT, tp->t_outq.c_cf, 180 ndqb(&tp->t_outq, 0), &count); 181 ndflush(&tp->t_outq, count); 182 } 183 tp->t_state &= ~TS_BUSY; 184 out: 185 splx(s); 186 } 187 188 void 189 arcbios_ttystop(struct tty *tp, int flag) 190 { 191 int s; 192 193 s = spltty(); 194 if (tp->t_state & TS_BUSY) 195 if ((tp->t_state & TS_TTSTOP) == 0) 196 tp->t_state |= TS_FLUSH; 197 splx(s); 198 } 199 200 static int 201 arcbios_tty_getchar(int *cp) 202 { 203 char c; 204 int32_t q; 205 u_int32_t count; 206 207 q = ARCBIOS->GetReadStatus(ARCBIOS_STDIN); 208 209 if (q == 0) { 210 ARCBIOS->Read(ARCBIOS_STDIN, &c, 1, &count); 211 *cp = c; 212 213 return 1; 214 } 215 216 return 0; 217 } 218 219 void 220 arcbios_tty_poll(void *v) 221 { 222 struct tty *tp = v; 223 int c, l_r; 224 225 while (arcbios_tty_getchar(&c)) { 226 if (tp->t_state & TS_ISOPEN) 227 l_r = (*tp->t_linesw->l_rint)(c, tp); 228 } 229 callout_reset(&arcbios_tty_ch, 1, arcbios_tty_poll, tp); 230 } 231 232 struct tty * 233 arcbios_ttytty(dev_t dev) 234 { 235 236 if (minor(dev) != 0) 237 panic("arcbios_ttytty: bogus"); 238 239 return (arcbios_tty[0]); 240 } 241