1/* $NetBSD: ite_cv3d.c,v 1.6 2007/03/04 05:59:22 christos 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.6 2007/03/04 05:59:22 christos 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 67void cv3d_ite_init(struct ite_softc *); 68void cv3d_ite_deinit(struct ite_softc *); 69static void cv3d_cursor(struct ite_softc *, int); 70static void cv3d_putc(struct ite_softc *, int, int, int, int); 71static void cv3d_clear(struct ite_softc *, int, int, int, int); 72static void cv3d_scroll(struct ite_softc *, int, int, int, int); 73 74/* 75 * called from grf_cv3d to return console priority 76 */ 77int 78grfcv3d_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 */ 104void 105grfcv3d_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 116void 117cv3d_ite_deinit(struct ite_softc *ip) 118{ 119 ip->flags &= ~ITE_INITED; 120} 121 122 123static unsigned short cv3d_rowc[MAXCOLS*(MAXROWS+1)]; 124 125/* 126 * Console buffer to avoid the slow reading from gfx mem. 127 */ 128 129static unsigned short *console_buffer; 130 131void 132cv3d_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 180void 181cv3d_cursor(struct ite_softc *ip, int flag) 182{ 183 volatile void *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 205void 206cv3d_putc(struct ite_softc *ip, int c, int dy, int dx, int mode) 207{ 208 volatile void *fb = ip->grf->g_fbkva; 209 unsigned char attr; 210 volatile 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 = (volatile char*)fb + ((cv3d_rowc[dy] + dx) << 2); /* *4 */ 218 *cp++ = (unsigned char) c; 219 *cp = (unsigned char) attr; 220 221 cp = (volatile unsigned char *) &console_buffer[cv3d_rowc[dy]+dx]; 222 *cp++ = (unsigned char) c; 223 *cp = (unsigned char) attr; 224} 225 226 227void 228cv3d_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 volatile unsigned short *dst; 235 int len; 236 237 dst = (volatile unsigned short *) 238 ((volatile char*)ip->grf->g_fbkva + 239 (((sy * ip->cols) + sx) << 2)); 240 241 for (len = w * h; len > 0 ; len--) { 242 *dst = 0x2007; 243 dst +=2; 244 } 245 246 dst = &console_buffer[(sy * ip->cols) + sx]; 247 for (len = w * h; len > 0 ; len--) { 248 *dst++ = 0x2007; 249 } 250} 251 252void 253cv3d_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir) 254{ 255 volatile unsigned short *src, *dst, *dst2; 256 int i; 257 int len; 258 259 src = (volatile unsigned short *) 260 ((volatile char*)ip->grf->g_fbkva + (cv3d_rowc[sy] << 2)); 261 262 switch (dir) { 263 case SCROLL_UP: 264 dst = src - ((cv3d_rowc[count])<<1); 265 266 len = cv3d_rowc[(ip->bottom_margin + 1 - sy)]; 267 src = &console_buffer[cv3d_rowc[sy]]; 268 269 if (count > sy) { /* boundary checks */ 270 dst2 = console_buffer; 271 dst = (volatile unsigned short *)(ip->grf->g_fbkva); 272 len -= cv3d_rowc[(count - sy)]; 273 src += cv3d_rowc[(count - sy)]; 274 } else 275 dst2 = &console_buffer[cv3d_rowc[(sy-count)]]; 276 277 bcopy (__UNVOLATILE(src), __UNVOLATILE(dst2), len << 1); 278 279 for (i = 0; i < len; i++) { 280 *dst++ = *dst2++; 281 dst++; 282 } 283 break; 284 case SCROLL_DOWN: 285 dst = src + ((cv3d_rowc[count]) << 1); 286 287 len = cv3d_rowc[(ip->bottom_margin + 1 - (sy + count))]; 288 src = &console_buffer[cv3d_rowc[sy]]; 289 dst2 = &console_buffer[cv3d_rowc[(sy + count)]]; 290 291 if (len < 0) 292 return; /* do some boundary check */ 293 294 bcopy (__UNVOLATILE(src), __UNVOLATILE(dst2), len << 1); 295 296 for (i = 0; i < len; i++) { 297 *dst++ = *dst2++; 298 dst++; 299 } 300 break; 301 case SCROLL_RIGHT: 302 dst = src + ((sx+count)<<1); 303 src = &console_buffer[cv3d_rowc[sy] + sx]; 304 len = ip->cols - (sx + count); 305 dst2 = &console_buffer[cv3d_rowc[sy] + sx + count]; 306 bcopy (__UNVOLATILE(src), __UNVOLATILE(dst2), len << 1); 307 308 for (i = 0; i < len; i++) { 309 *dst++ = *dst2++; 310 dst++; 311 } 312 break; 313 case SCROLL_LEFT: 314 dst = src + ((sx - count)<<1); 315 src = &console_buffer[cv3d_rowc[sy] + sx]; 316 len = ip->cols - sx; 317 dst2 = &console_buffer[cv3d_rowc[sy] + sx - count]; 318 bcopy (__UNVOLATILE(src), __UNVOLATILE(dst2), len << 1); 319 320 for (i = 0; i < len; i++) { 321 *dst++ = *dst2++; 322 dst++; 323 } 324 } 325} 326 327#endif /* NGRFCV3D */ 328