1 /* $NetBSD: ite_cv3d.c,v 1.5 2002/01/28 09:57:00 aymeric Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Michael Teske 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Christian E. Hopps, 18 * Ezra Story, Kari Mettinen, Markus Wild, Lutz Vieweg 19 * and Michael Teske. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * This code is based on ite_cl.c and ite_rh.c by 37 * Ezra Story, Kari Mettinen, Markus Wild, Lutz Vieweg. 38 */ 39 40 #include "opt_amigacons.h" 41 42 #include <sys/cdefs.h> 43 __KERNEL_RCSID(0, "$NetBSD: ite_cv3d.c,v 1.5 2002/01/28 09:57:00 aymeric Exp $"); 44 45 #include "grfcv3d.h" 46 #if NGRFCV3D > 0 47 48 #include <sys/param.h> 49 #include <sys/conf.h> 50 #include <sys/proc.h> 51 #include <sys/device.h> 52 #include <sys/ioctl.h> 53 #include <sys/tty.h> 54 #include <sys/systm.h> 55 #include <sys/queue.h> 56 #include <sys/termios.h> 57 #include <sys/malloc.h> 58 #include <dev/cons.h> 59 #include <machine/cpu.h> 60 #include <amiga/dev/itevar.h> 61 #include <amiga/dev/iteioctl.h> 62 #include <amiga/amiga/device.h> 63 #include <amiga/dev/grfioctl.h> 64 #include <amiga/dev/grfvar.h> 65 #include <amiga/dev/grf_cv3dreg.h> 66 67 void cv3d_ite_init(struct ite_softc *); 68 void cv3d_ite_deinit(struct ite_softc *); 69 static void cv3d_cursor(struct ite_softc *, int); 70 static void cv3d_putc(struct ite_softc *, int, int, int, int); 71 static void cv3d_clear(struct ite_softc *, int, int, int, int); 72 static void cv3d_scroll(struct ite_softc *, int, int, int, int); 73 74 /* 75 * called from grf_cv3d to return console priority 76 */ 77 int 78 grfcv3d_cnprobe(void) 79 { 80 static int done; 81 int rv; 82 83 if (done == 0) 84 #ifdef CV3DCONSOLE 85 rv = CN_INTERNAL; 86 #else 87 rv = CN_DEAD; 88 #endif 89 else 90 #ifdef CV3DCONSOLE 91 rv = CN_NORMAL; 92 #else 93 rv = CN_DEAD; 94 #endif 95 done = 1; 96 return(rv); 97 } 98 99 100 /* 101 * called from grf_cv3d to init ite portion of 102 * grf_softc struct 103 */ 104 void 105 grfcv3d_iteinit(struct grf_softc *gp) 106 { 107 gp->g_itecursor = cv3d_cursor; 108 gp->g_iteputc = cv3d_putc; 109 gp->g_iteclear = cv3d_clear; 110 gp->g_itescroll = cv3d_scroll; 111 gp->g_iteinit = cv3d_ite_init; 112 gp->g_itedeinit = cv3d_ite_deinit; 113 } 114 115 116 void 117 cv3d_ite_deinit(struct ite_softc *ip) 118 { 119 ip->flags &= ~ITE_INITED; 120 } 121 122 123 static unsigned short cv3d_rowc[MAXCOLS*(MAXROWS+1)]; 124 125 /* 126 * Console buffer to avoid the slow reading from gfx mem. 127 */ 128 129 static unsigned short *console_buffer; 130 131 void 132 cv3d_ite_init(register struct ite_softc *ip) 133 { 134 struct grfcv3dtext_mode *md; 135 int i; 136 static char first = 1; 137 volatile unsigned short *fb = (volatile unsigned short *)ip->grf->g_fbkva; 138 unsigned short *buffer; 139 140 141 ip->priv = ip->grf->g_data; 142 md = (struct grfcv3dtext_mode *) ip->grf->g_data; 143 144 ip->cols = md->cols; 145 ip->rows = md->rows; 146 147 /* alloc buffers */ 148 149 #if 0 /* XXX malloc seems not to work in early init :( */ 150 if (cv3d_rowc) 151 free(cv3d_rowc, M_DEVBUF); 152 153 /* alloc all in one */ 154 cv3d_rowc = malloc(sizeof(short) * (ip->rows + 1) * (ip->cols + 2), 155 M_DEVBUF, M_WAITOK); 156 if (!cv3d_rowc) 157 panic("No buffers for ite_cv3d!"); 158 #endif 159 160 console_buffer = cv3d_rowc + ip->rows + 1; 161 162 163 for (i = 0; i < ip->rows; i++) 164 cv3d_rowc[i] = i * ip->cols; 165 166 if (first) { 167 for (i = 0; i < ip->rows * ip->cols; i++) 168 console_buffer[i] = 0x2007; 169 first = 0; 170 } else { /* restore console */ 171 buffer = console_buffer; 172 for (i = 0; i < ip->rows * ip->cols; i++) { 173 *fb++ = *buffer++; 174 *fb++; 175 } 176 } 177 } 178 179 180 void 181 cv3d_cursor(struct ite_softc *ip, int flag) 182 { 183 volatile caddr_t ba = ip->grf->g_regkva; 184 185 switch (flag) { 186 case DRAW_CURSOR: 187 /*WCrt(ba, CRT_ID_CURSOR_START, & ~0x20); */ 188 case MOVE_CURSOR: 189 flag = ip->curx + ip->cury * ip->cols; 190 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, flag & 0xff); 191 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, flag >> 8); 192 ip->cursorx = ip->curx; 193 ip->cursory = ip->cury; 194 break; 195 case ERASE_CURSOR: 196 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20); */ 197 case START_CURSOROPT: 198 case END_CURSOROPT: 199 default: 200 break; 201 } 202 } 203 204 205 void 206 cv3d_putc(struct ite_softc *ip, int c, int dy, int dx, int mode) 207 { 208 caddr_t fb = ip->grf->g_fbkva; 209 unsigned char attr; 210 unsigned char *cp; 211 212 attr = (unsigned char) ((mode & ATTR_INV) ? (0x70) : (0x07)); 213 if (mode & ATTR_UL) attr = 0x01; 214 if (mode & ATTR_BOLD) attr |= 0x08; 215 if (mode & ATTR_BLINK) attr |= 0x80; 216 217 cp = fb + ((cv3d_rowc[dy] + dx) << 2); /* *4 */ 218 *cp++ = (unsigned char) c; 219 *cp = (unsigned char) attr; 220 221 cp = (unsigned char *) &console_buffer[cv3d_rowc[dy]+dx]; 222 *cp++ = (unsigned char) c; 223 *cp = (unsigned char) attr; 224 } 225 226 227 void 228 cv3d_clear(struct ite_softc *ip, int sy, int sx, int h, int w) 229 { 230 /* cv3d_clear and cv3d_scroll both rely on ite passing arguments 231 * which describe continuous regions. For a VT200 terminal, 232 * this is safe behavior. 233 */ 234 unsigned short *dst; 235 int len; 236 237 dst = (unsigned short *) (ip->grf->g_fbkva + (((sy * ip->cols) + sx) << 2)); 238 239 for (len = w * h; len > 0 ; len--) { 240 *dst = 0x2007; 241 dst +=2; 242 } 243 244 dst = &console_buffer[(sy * ip->cols) + sx]; 245 for (len = w * h; len > 0 ; len--) { 246 *dst++ = 0x2007; 247 } 248 } 249 250 void 251 cv3d_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir) 252 { 253 unsigned short *src, *dst, *dst2; 254 int i; 255 int len; 256 257 src = (unsigned short *)(ip->grf->g_fbkva + (cv3d_rowc[sy] << 2)); 258 259 switch (dir) { 260 case SCROLL_UP: 261 dst = src - ((cv3d_rowc[count])<<1); 262 263 len = cv3d_rowc[(ip->bottom_margin + 1 - sy)]; 264 src = &console_buffer[cv3d_rowc[sy]]; 265 266 if (count > sy) { /* boundary checks */ 267 dst2 = console_buffer; 268 dst = (unsigned short *)(ip->grf->g_fbkva); 269 len -= cv3d_rowc[(count - sy)]; 270 src += cv3d_rowc[(count - sy)]; 271 } else 272 dst2 = &console_buffer[cv3d_rowc[(sy-count)]]; 273 274 bcopy (src, dst2, len << 1); 275 276 for (i = 0; i < len; i++) { 277 *dst++ = *dst2++; 278 dst++; 279 } 280 break; 281 case SCROLL_DOWN: 282 dst = src + ((cv3d_rowc[count]) << 1); 283 284 len = cv3d_rowc[(ip->bottom_margin + 1 - (sy + count))]; 285 src = &console_buffer[cv3d_rowc[sy]]; 286 dst2 = &console_buffer[cv3d_rowc[(sy + count)]]; 287 288 if (len < 0) 289 return; /* do some boundary check */ 290 291 bcopy (src, dst2, len << 1); 292 293 for (i = 0; i < len; i++) { 294 *dst++ = *dst2++; 295 dst++; 296 } 297 break; 298 case SCROLL_RIGHT: 299 dst = src + ((sx+count)<<1); 300 src = &console_buffer[cv3d_rowc[sy] + sx]; 301 len = ip->cols - (sx + count); 302 dst2 = &console_buffer[cv3d_rowc[sy] + sx + count]; 303 bcopy (src, dst2, len << 1); 304 305 for (i = 0; i < len; i++) { 306 *dst++ = *dst2++; 307 dst++; 308 } 309 break; 310 case SCROLL_LEFT: 311 dst = src + ((sx - count)<<1); 312 src = &console_buffer[cv3d_rowc[sy] + sx]; 313 len = ip->cols - sx; 314 dst2 = &console_buffer[cv3d_rowc[sy] + sx - count]; 315 bcopy (src, dst2, len << 1); 316 317 for (i = 0; i < len; i++) { 318 *dst++ = *dst2++; 319 dst++; 320 } 321 } 322 } 323 324 #endif /* NGRFCV3D */ 325