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