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