1 /* 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)rcons_kern.c 7.1 (Berkeley) 07/13/92 12 * 13 * from: $Header: rcons_kern.c,v 1.26 92/07/09 08:01:28 torek Exp $ 14 */ 15 16 #include "sys/param.h" 17 #include "sys/device.h" 18 #include "sys/fbio.h" 19 #include "sys/kernel.h" 20 #include "sys/systm.h" 21 #include "sys/ioctl.h" 22 #include "sys/tty.h" 23 24 #include "machine/fbvar.h" 25 #include "machine/autoconf.h" 26 27 #include "../dev/kbd.h" 28 29 #include "raster.h" 30 31 extern struct tty *fbconstty; 32 33 static void rcons_belltmr(void *); 34 35 extern void rcons_puts(struct fbdevice *, char *, int); 36 extern void rcons_font(struct fbdevice *); 37 38 extern int (*v_putc)(); 39 extern void ttrstrt(void *); 40 41 static struct fbdevice *myfbdevicep; 42 43 static void 44 rcons_cnputc(c) 45 int c; 46 { 47 char buf[1]; 48 49 if (c == '\n') 50 rcons_puts(myfbdevicep, "\r\n", 2); 51 else { 52 buf[0] = c; 53 rcons_puts(myfbdevicep, buf, 1); 54 } 55 } 56 57 static void 58 rcons_output(tp) 59 register struct tty *tp; 60 { 61 register int s, n, i; 62 char buf[OBUFSIZ]; 63 64 s = spltty(); 65 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { 66 splx(s); 67 return; 68 } 69 tp->t_state |= TS_BUSY; 70 splx(s); 71 n = q_to_b(&tp->t_outq, buf, sizeof(buf)); 72 for (i = 0; i < n; ++i) 73 buf[i] &= 0177; /* strip parity (argh) */ 74 rcons_puts(myfbdevicep, buf, n); 75 76 s = spltty(); 77 tp->t_state &= ~TS_BUSY; 78 /* Come back if there's more to do */ 79 if (tp->t_outq.c_cc) { 80 tp->t_state |= TS_TIMEOUT; 81 timeout(ttrstrt, tp, 1); 82 } 83 if (tp->t_outq.c_cc <= tp->t_lowat) { 84 if (tp->t_state&TS_ASLEEP) { 85 tp->t_state &= ~TS_ASLEEP; 86 wakeup((caddr_t)&tp->t_outq); 87 } 88 selwakeup(&tp->t_wsel); 89 } 90 splx(s); 91 } 92 93 /* Ring the console bell */ 94 void 95 rcons_bell(fb) 96 register struct fbdevice *fb; 97 { 98 register int i, s; 99 100 if (fb->fb_bits & FB_VISBELL) { 101 /* invert the screen twice */ 102 for (i = 0; i < 2; ++i) 103 raster_op(fb->fb_sp, 0, 0, 104 fb->fb_sp->width, fb->fb_sp->height, 105 RAS_INVERT, (struct raster *) 0, 0, 0); 106 } 107 108 s = splhigh(); 109 if (fb->fb_belldepth++) { 110 if (fb->fb_belldepth > 3) 111 fb->fb_belldepth = 3; 112 splx(s); 113 } else { 114 fb->fb_ringing = 1; 115 splx(s); 116 (void) kbd_docmd(KBD_CMD_BELL, 0); 117 /* XXX Chris doesn't like the following divide */ 118 timeout(rcons_belltmr, fb, hz/10); 119 } 120 } 121 122 /* Bell timer service routine */ 123 static void 124 rcons_belltmr(p) 125 void *p; 126 { 127 register struct fbdevice *fb = p; 128 register int s = splhigh(), i; 129 130 if (fb->fb_ringing) { 131 fb->fb_ringing = 0; 132 i = --fb->fb_belldepth; 133 splx(s); 134 (void) kbd_docmd(KBD_CMD_NOBELL, 0); 135 if (i != 0) 136 /* XXX Chris doesn't like the following divide */ 137 timeout(rcons_belltmr, fb, hz/30); 138 } else { 139 fb->fb_ringing = 1; 140 splx(s); 141 (void) kbd_docmd(KBD_CMD_BELL, 0); 142 timeout(rcons_belltmr, fb, hz/10); 143 } 144 } 145 146 static int 147 rcons_a2int(cp, deflt) 148 register char *cp; 149 register int deflt; 150 { 151 register int i = 0; 152 153 if (*cp == '\0') 154 return (deflt); 155 while (*cp != '\0') 156 i = i * 10 + *cp++ - '0'; 157 return (i); 158 } 159 160 void 161 rcons_init(fb) 162 register struct fbdevice *fb; 163 { 164 /* XXX this should go away */ 165 static struct raster xxxraster; 166 register struct raster *rp = fb->fb_sp = &xxxraster; 167 register struct fbtype *ft = &fb->fb_type; 168 register struct winsize *ws; 169 register int i; 170 static int row, col; 171 char buf[100]; 172 173 myfbdevicep = fb; 174 175 fb->fb_maxcol = 176 rcons_a2int(getpropstring(optionsnode, "screen-#columns"), 80); 177 fb->fb_maxrow = 178 rcons_a2int(getpropstring(optionsnode, "screen-#rows"), 34); 179 180 /* XXX mostly duplicates of data in other places */ 181 rp->width = ft->fb_width; 182 rp->height = ft->fb_height; 183 rp->depth = ft->fb_depth; 184 if (fb->fb_linebytes & 0x3) { 185 printf("rcons_init: linebytes assumption botched (0x%x)\n", 186 fb->fb_linebytes); 187 return; 188 } 189 rp->linelongs = fb->fb_linebytes >> 2; 190 rp->pixels = (u_long *)fb->fb_pixels; 191 192 fb->fb_ras_blank = RAS_CLEAR; 193 194 /* Setup the static font */ 195 rcons_font(fb); 196 197 /* Impose upper bounds on fb_max{row,col} */ 198 i = ft->fb_height / fb->fb_font->height; 199 if (fb->fb_maxrow > i) 200 fb->fb_maxrow = i; 201 i = ft->fb_width / fb->fb_font->width; 202 if (fb->fb_maxcol > i) 203 fb->fb_maxcol = i; 204 205 /* Let the system know how big the console is */ 206 ws = &fbconstty->t_winsize; 207 ws->ws_row = fb->fb_maxrow; 208 ws->ws_col = fb->fb_maxcol; 209 ws->ws_xpixel = ft->fb_width; 210 ws->ws_ypixel = ft->fb_height; 211 212 /* Center emulator screen (but align x origin to 32 bits) */ 213 fb->fb_xorigin = 214 ((ft->fb_width - fb->fb_maxcol * fb->fb_font->width) / 2) & ~0x1f; 215 fb->fb_yorigin = 216 (ft->fb_height - fb->fb_maxrow * fb->fb_font->height) / 2; 217 218 /* Emulator width and height used for scrolling */ 219 fb->fb_emuwidth = fb->fb_maxcol * fb->fb_font->width; 220 if (fb->fb_emuwidth & 0x1f) { 221 /* Pad to 32 bits */ 222 i = (fb->fb_emuwidth + 0x1f) & ~0x1f; 223 /* Make sure emulator width isn't too wide */ 224 if (fb->fb_xorigin + i <= ft->fb_width) 225 fb->fb_emuwidth = i; 226 } 227 fb->fb_emuheight = fb->fb_maxrow * fb->fb_font->height; 228 229 /* Determine addresses of prom emulator row and column */ 230 fb->fb_row = fb->fb_col = NULL; 231 sprintf(buf, "' line# >body >user %x !", &fb->fb_row); 232 rominterpret(buf); 233 sprintf(buf, "' column# >body >user %x !", &fb->fb_col); 234 rominterpret(buf); 235 if (fb->fb_row == NULL || fb->fb_col == NULL) { 236 /* Can't find addresses; use private copies */ 237 fb->fb_row = &row; 238 fb->fb_col = &col; 239 row = col = 0; 240 rcons_clear2eop(fb); /* clear the display */ 241 rcons_cursor(fb); /* and draw the initial cursor */ 242 } else { 243 /* Prom emulator cursor is currently visible */ 244 fb->fb_bits |= FB_CURSOR; 245 } 246 247 /* Initialization done; hook us up */ 248 v_putc = (int (*)())rcons_cnputc; 249 fbconstty->t_oproc = rcons_output; 250 fbconstty->t_stop = (void (*)()) nullop; 251 } 252