1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)cons.c 7.5 (Berkeley) 05/07/88 7 */ 8 9 /* 10 * VAX console driver (and floppy interface) 11 */ 12 #include "param.h" 13 #include "conf.h" 14 #include "dir.h" 15 #include "user.h" 16 #include "proc.h" 17 #include "ioctl.h" 18 #include "tty.h" 19 #include "systm.h" 20 #include "uio.h" 21 22 #include "cpu.h" 23 #include "cons.h" 24 #include "mtpr.h" 25 26 /* 27 * On some machines (e.g. MicroVAX), a secondary console 28 * such as a display may supercede the standard serial console. 29 * On such machines, consops will be set to point to the cdevsw 30 * entry for the secondary console, and the standard console device 31 * (minor number 0) will be redirected. Other minor numbers still 32 * refer to the standard console serial line. 33 * 34 * Also, console output may be redirected to another tty 35 * (e.g. a window); if so, constty will point to the current 36 * virtual console. 37 */ 38 struct cdevsw *consops = 0; 39 struct tty *constty = 0; 40 struct tty cons; 41 int cnstart(); 42 int ttrstrt(); 43 char partab[]; 44 45 /*ARGSUSED*/ 46 cnopen(dev, flag) 47 dev_t dev; 48 { 49 register struct tty *tp = &cons; 50 51 if (consops && minor(dev) == 0) 52 return ((*consops->d_open)(dev, flag)); 53 tp->t_oproc = cnstart; 54 if ((tp->t_state&TS_ISOPEN) == 0) { 55 ttychars(tp); 56 tp->t_state = TS_ISOPEN|TS_CARR_ON; 57 tp->t_flags = EVENP|ECHO|XTABS|CRMOD; 58 } 59 if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 60 return (EBUSY); 61 mtpr(RXCS, mfpr(RXCS)|RXCS_IE); 62 mtpr(TXCS, mfpr(TXCS)|TXCS_IE); 63 return ((*linesw[tp->t_line].l_open)(dev, tp)); 64 } 65 66 /*ARGSUSED*/ 67 cnclose(dev) 68 dev_t dev; 69 { 70 register struct tty *tp = &cons; 71 72 if (consops && minor(dev) == 0) 73 return ((*consops->d_close)(dev)); 74 (*linesw[tp->t_line].l_close)(tp); 75 ttyclose(tp); 76 return (0); 77 } 78 79 /*ARGSUSED*/ 80 cnread(dev, uio) 81 dev_t dev; 82 struct uio *uio; 83 { 84 register struct tty *tp = &cons; 85 86 if (consops && minor(dev) == 0) 87 return ((*consops->d_read)(dev, uio)); 88 return ((*linesw[tp->t_line].l_read)(tp, uio)); 89 } 90 91 /*ARGSUSED*/ 92 cnwrite(dev, uio) 93 dev_t dev; 94 struct uio *uio; 95 { 96 register struct tty *tp = &cons; 97 98 if (minor(dev) == 0) { 99 if (constty && (constty->t_state & (TS_CARR_ON | TS_ISOPEN)) == 100 (TS_CARR_ON | TS_ISOPEN)) 101 tp = constty; 102 else if (consops) 103 return ((*consops->d_write)(dev, uio)); 104 } 105 return ((*linesw[tp->t_line].l_write)(tp, uio)); 106 } 107 108 static int cnpolling = 0; 109 /* 110 * Got a level-20 receive interrupt - 111 * the LSI wants to give us a character. 112 * Catch the character, and see who it goes to. 113 */ 114 /*ARGSUSED*/ 115 cnrint(dev) 116 dev_t dev; 117 { 118 register int c; 119 register struct tty *tp; 120 121 if (cnpolling) 122 return; 123 c = mfpr(RXDB); 124 if (c&RXDB_ID) { 125 #if VAX780 126 if (cpu == VAX_780) 127 cnrfl(c); 128 #endif 129 return; 130 } 131 tp = &cons; 132 #ifdef KADB 133 if (!kdbrintr(c, tp)) 134 #endif 135 (*linesw[tp->t_line].l_rint)(c, tp); 136 } 137 138 /*ARGSUSED*/ 139 cnioctl(dev, cmd, addr, flag) 140 dev_t dev; 141 caddr_t addr; 142 { 143 register struct tty *tp = &cons; 144 int error; 145 146 if (consops && minor(dev) == 0) 147 return ((*consops->d_ioctl)(dev, cmd, addr, flag)); 148 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 149 if (error >= 0) 150 return (error); 151 error = ttioctl(tp, cmd, addr, flag); 152 if (error < 0) 153 error = ENOTTY; 154 return (error); 155 } 156 157 int consdone = 1; 158 /* 159 * Got a level-20 transmission interrupt - 160 * the LSI wants another character. First, 161 * see if we can send something to the typewriter. 162 * If not, try the floppy. 163 */ 164 /*ARGSUSED*/ 165 cnxint(dev) 166 dev_t dev; 167 { 168 register struct tty *tp = &cons; 169 170 consdone++; 171 tp->t_state &= ~TS_BUSY; 172 if (tp->t_line) 173 (*linesw[tp->t_line].l_start)(tp); 174 else 175 cnstart(tp); 176 #if VAX780 177 if (cpu==VAX_780 && (tp->t_state & TS_BUSY) == 0) 178 conxfl(); 179 #endif 180 } 181 182 cnstart(tp) 183 register struct tty *tp; 184 { 185 register int c, s; 186 187 s = spl5(); 188 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 189 goto out; 190 if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 191 if (tp->t_state&TS_ASLEEP) { 192 tp->t_state &= ~TS_ASLEEP; 193 wakeup((caddr_t)&tp->t_outq); 194 } 195 if (tp->t_wsel) { 196 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 197 tp->t_wsel = 0; 198 tp->t_state &= ~TS_WCOLL; 199 } 200 } 201 if (tp->t_outq.c_cc == 0) 202 goto out; 203 if (consdone == 0) 204 goto out; 205 c = getc(&tp->t_outq) & 0xff; 206 if ((tp->t_flags & (RAW|LITOUT)) == 0) { 207 if (c <= 0177) 208 c |= (partab[c] & 0200); 209 else { 210 timeout(ttrstrt, (caddr_t)tp, (c&0177)); 211 tp->t_state |= TS_TIMEOUT; 212 goto out; 213 } 214 } 215 mtpr(TXDB, c); 216 consdone = 0; 217 tp->t_state |= TS_BUSY; 218 out: 219 splx(s); 220 } 221 222 /* 223 * Print a character on console. 224 * Attempts to save and restore device 225 * status. 226 */ 227 cnputc(c) 228 register int c; 229 { 230 register int s, timo; 231 232 timo = 30000; 233 /* 234 * Try waiting for the console tty to come ready, 235 * otherwise give up after a reasonable time. 236 */ 237 while ((mfpr(TXCS)&TXCS_RDY) == 0) 238 if(--timo == 0) 239 break; 240 if (c == 0) 241 return; 242 s = mfpr(TXCS); 243 mtpr(TXCS, 0); 244 mtpr(TXDB, c&0xff); 245 if (c == '\n') 246 cnputc('\r'); 247 cnputc(0); 248 mtpr(TXCS, s); 249 } 250 251 #if (defined(KADB) || defined(GENERIC)) && !defined(lint) 252 /* 253 * Get character from console. 254 */ 255 cngetc() 256 { 257 register int c, s; 258 259 s = splhigh(); 260 while ((mfpr(RXCS)&RXCS_DONE) == 0 || (c = mfpr(RXDB)&0177) <= 0) 261 ; 262 if (c == '\r') 263 c = '\n'; 264 (void) splx(s); 265 return (c); 266 } 267 #endif 268 269 #ifdef KADB 270 cnpoll(onoff) 271 int onoff; 272 { 273 274 cnpolling = onoff; 275 } 276 #endif 277