1*3ba91b05She /* $NetBSD: ite_cv.c,v 1.8 2007/03/05 20:29:07 he Exp $ */
239aeb2aaSveego
339aeb2aaSveego /*
439aeb2aaSveego * Copyright (c) 1995 Michael Teske
539aeb2aaSveego * All rights reserved.
639aeb2aaSveego *
739aeb2aaSveego * Redistribution and use in source and binary forms, with or without
839aeb2aaSveego * modification, are permitted provided that the following conditions
939aeb2aaSveego * are met:
1039aeb2aaSveego * 1. Redistributions of source code must retain the above copyright
1139aeb2aaSveego * notice, this list of conditions and the following disclaimer.
1239aeb2aaSveego * 2. Redistributions in binary form must reproduce the above copyright
1339aeb2aaSveego * notice, this list of conditions and the following disclaimer in the
1439aeb2aaSveego * documentation and/or other materials provided with the distribution.
1539aeb2aaSveego * 3. All advertising materials mentioning features or use of this software
1639aeb2aaSveego * must display the following acknowledgement:
17974e9f6eSveego * This product includes software developed by Christian E. Hopps,
18974e9f6eSveego * Ezra Story, Kari Mettinen, Markus Wild, Lutz Vieweg
1939aeb2aaSveego * and Michael Teske.
2039aeb2aaSveego * 4. The name of the author may not be used to endorse or promote products
2139aeb2aaSveego * derived from this software without specific prior written permission
2239aeb2aaSveego *
2339aeb2aaSveego * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2439aeb2aaSveego * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2539aeb2aaSveego * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2639aeb2aaSveego * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2739aeb2aaSveego * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2839aeb2aaSveego * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2939aeb2aaSveego * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3039aeb2aaSveego * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3139aeb2aaSveego * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3239aeb2aaSveego * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3339aeb2aaSveego */
3439aeb2aaSveego
3539aeb2aaSveego /*
367212a830Sveego * This code is based on ite_cl.c and ite_rh.c by
37974e9f6eSveego * Ezra Story, Kari Mettinen, Markus Wild, Lutz Vieweg.
3839aeb2aaSveego */
3939aeb2aaSveego
40d19d45b8Sis #include "opt_amigacons.h"
411ea4df81Saymeric
421ea4df81Saymeric #include <sys/cdefs.h>
43*3ba91b05She __KERNEL_RCSID(0, "$NetBSD: ite_cv.c,v 1.8 2007/03/05 20:29:07 he Exp $");
441ea4df81Saymeric
4539aeb2aaSveego #include "grfcv.h"
4639aeb2aaSveego #if NGRFCV > 0
4739aeb2aaSveego
4839aeb2aaSveego #include <sys/param.h>
4939aeb2aaSveego #include <sys/conf.h>
5039aeb2aaSveego #include <sys/proc.h>
5139aeb2aaSveego #include <sys/device.h>
5239aeb2aaSveego #include <sys/ioctl.h>
5339aeb2aaSveego #include <sys/tty.h>
5439aeb2aaSveego #include <sys/systm.h>
5539aeb2aaSveego #include <sys/queue.h>
5639aeb2aaSveego #include <sys/termios.h>
5739aeb2aaSveego #include <sys/malloc.h>
5839aeb2aaSveego #include <dev/cons.h>
5939aeb2aaSveego #include <machine/cpu.h>
6039aeb2aaSveego #include <amiga/dev/itevar.h>
6139aeb2aaSveego #include <amiga/dev/iteioctl.h>
6239aeb2aaSveego #include <amiga/amiga/device.h>
6339aeb2aaSveego #include <amiga/dev/grfioctl.h>
6439aeb2aaSveego #include <amiga/dev/grfvar.h>
6539aeb2aaSveego #include <amiga/dev/grf_cvreg.h>
6639aeb2aaSveego
679382c873Saymeric void cv_ite_init(struct ite_softc *);
689382c873Saymeric void cv_ite_deinit(struct ite_softc *);
699382c873Saymeric static void cv_cursor(struct ite_softc *, int);
709382c873Saymeric static void cv_putc(struct ite_softc *, int, int, int, int);
719382c873Saymeric static void cv_clear(struct ite_softc *, int, int, int, int);
729382c873Saymeric static void cv_scroll(struct ite_softc *, int, int, int, int);
7339aeb2aaSveego
7439aeb2aaSveego /*
7539aeb2aaSveego * called from grf_cv to return console priority
7639aeb2aaSveego */
7739aeb2aaSveego int
grfcv_cnprobe(void)789382c873Saymeric grfcv_cnprobe(void)
7939aeb2aaSveego {
8039aeb2aaSveego static int done;
8139aeb2aaSveego int rv;
8239aeb2aaSveego
8339aeb2aaSveego if (done == 0)
8439aeb2aaSveego #ifdef CV64CONSOLE
8539aeb2aaSveego rv = CN_INTERNAL;
8639aeb2aaSveego #else
8739aeb2aaSveego rv = CN_DEAD;
8839aeb2aaSveego #endif
8939aeb2aaSveego else
9039aeb2aaSveego #ifdef CV64CONSOLE
9139aeb2aaSveego rv = CN_NORMAL;
9239aeb2aaSveego #else
9339aeb2aaSveego rv = CN_DEAD;
9439aeb2aaSveego #endif
9539aeb2aaSveego done = 1;
9639aeb2aaSveego return(rv);
9739aeb2aaSveego }
9839aeb2aaSveego
9939aeb2aaSveego
10039aeb2aaSveego /*
10139aeb2aaSveego * called from grf_cv to init ite portion of
10239aeb2aaSveego * grf_softc struct
10339aeb2aaSveego */
10439aeb2aaSveego void
grfcv_iteinit(struct grf_softc * gp)1059382c873Saymeric grfcv_iteinit(struct grf_softc *gp)
10639aeb2aaSveego {
10739aeb2aaSveego gp->g_itecursor = cv_cursor;
10839aeb2aaSveego gp->g_iteputc = cv_putc;
10939aeb2aaSveego gp->g_iteclear = cv_clear;
11039aeb2aaSveego gp->g_itescroll = cv_scroll;
11139aeb2aaSveego gp->g_iteinit = cv_ite_init;
11239aeb2aaSveego gp->g_itedeinit = cv_ite_deinit;
11339aeb2aaSveego }
11439aeb2aaSveego
11539aeb2aaSveego
11639aeb2aaSveego void
cv_ite_deinit(struct ite_softc * ip)1179382c873Saymeric cv_ite_deinit(struct ite_softc *ip)
11839aeb2aaSveego {
11939aeb2aaSveego ip->flags &= ~ITE_INITED;
12039aeb2aaSveego }
12139aeb2aaSveego
12239aeb2aaSveego
1237212a830Sveego static unsigned short cv_rowc[MAXCOLS*(MAXROWS+1)];
1247212a830Sveego
1257212a830Sveego /*
1267212a830Sveego * Console buffer to avoid the slow reading from gfx mem.
1277212a830Sveego */
1287212a830Sveego
1297212a830Sveego static unsigned short *console_buffer;
1307212a830Sveego
13139aeb2aaSveego void
cv_ite_init(register struct ite_softc * ip)1329382c873Saymeric cv_ite_init(register struct ite_softc *ip)
13339aeb2aaSveego {
134974e9f6eSveego struct grfcvtext_mode *md;
135974e9f6eSveego int i;
1367212a830Sveego static char first = 1;
1377212a830Sveego volatile unsigned short *fb = (volatile unsigned short *)ip->grf->g_fbkva;
1387212a830Sveego unsigned short *buffer;
1397212a830Sveego
14039aeb2aaSveego
141974e9f6eSveego ip->priv = ip->grf->g_data;
142974e9f6eSveego md = (struct grfcvtext_mode *) ip->grf->g_data;
14339aeb2aaSveego
144974e9f6eSveego ip->cols = md->cols;
145974e9f6eSveego ip->rows = md->rows;
1467212a830Sveego
1477212a830Sveego /* alloc buffers */
1487212a830Sveego
1497212a830Sveego #if 0 /* XXX malloc seems not to work in early init :( */
1507212a830Sveego if (cv_rowc)
1517212a830Sveego free(cv_rowc, M_DEVBUF);
1527212a830Sveego
1537212a830Sveego /* alloc all in one */
1547212a830Sveego cv_rowc = malloc(sizeof(short) * (ip->rows + 1) * (ip->cols + 2),
1557212a830Sveego M_DEVBUF, M_WAITOK);
1567212a830Sveego if (!cv_rowc)
1577212a830Sveego panic("No buffers for ite_cv!");
1587212a830Sveego #endif
1597212a830Sveego
1607212a830Sveego console_buffer = cv_rowc + ip->rows + 1;
1617212a830Sveego
162974e9f6eSveego
163974e9f6eSveego for (i = 0; i < ip->rows; i++)
164974e9f6eSveego cv_rowc[i] = i * ip->cols;
1657212a830Sveego
1667212a830Sveego if (first) {
1677212a830Sveego for (i = 0; i < ip->rows * ip->cols; i++)
168974e9f6eSveego console_buffer[i] = 0x2007;
1697212a830Sveego first = 0;
1707212a830Sveego } else { /* restore console */
1717212a830Sveego buffer = console_buffer;
1727212a830Sveego for (i = 0; i < ip->rows * ip->cols; i++) {
1737212a830Sveego *fb++ = *buffer++;
1747212a830Sveego *fb++;
1757212a830Sveego }
1767212a830Sveego }
17739aeb2aaSveego }
17839aeb2aaSveego
17939aeb2aaSveego
180974e9f6eSveego void
cv_cursor(struct ite_softc * ip,int flag)1819382c873Saymeric cv_cursor(struct ite_softc *ip, int flag)
18239aeb2aaSveego {
18353524e44Schristos volatile void *ba = ip->grf->g_regkva;
18439aeb2aaSveego
185974e9f6eSveego switch (flag) {
186974e9f6eSveego case DRAW_CURSOR:
187974e9f6eSveego /*WCrt(ba, CRT_ID_CURSOR_START, & ~0x20); */
188974e9f6eSveego case MOVE_CURSOR:
189974e9f6eSveego flag = ip->curx + ip->cury * ip->cols;
190974e9f6eSveego WCrt(ba, CRT_ID_CURSOR_LOC_LOW, flag & 0xff);
191974e9f6eSveego WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, flag >> 8);
192974e9f6eSveego ip->cursorx = ip->curx;
19339aeb2aaSveego ip->cursory = ip->cury;
194974e9f6eSveego break;
195974e9f6eSveego case ERASE_CURSOR:
196974e9f6eSveego /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20); */
197974e9f6eSveego case START_CURSOROPT:
198974e9f6eSveego case END_CURSOROPT:
199974e9f6eSveego default:
200974e9f6eSveego break;
20139aeb2aaSveego }
20239aeb2aaSveego }
20339aeb2aaSveego
20439aeb2aaSveego
20539aeb2aaSveego void
cv_putc(struct ite_softc * ip,int c,int dy,int dx,int mode)2069382c873Saymeric cv_putc(struct ite_softc *ip, int c, int dy, int dx, int mode)
20739aeb2aaSveego {
208*3ba91b05She volatile char *fb = ip->grf->g_fbkva;
209974e9f6eSveego unsigned char attr;
210*3ba91b05She volatile unsigned char *cp;
21139aeb2aaSveego
212974e9f6eSveego attr = (unsigned char) ((mode & ATTR_INV) ? (0x70) : (0x07));
213974e9f6eSveego if (mode & ATTR_UL) attr = 0x01;
214974e9f6eSveego if (mode & ATTR_BOLD) attr |= 0x08;
215974e9f6eSveego if (mode & ATTR_BLINK) attr |= 0x80;
216974e9f6eSveego
217974e9f6eSveego cp = fb + ((cv_rowc[dy] + dx) << 2); /* *4 */
218974e9f6eSveego *cp++ = (unsigned char) c;
219974e9f6eSveego *cp = (unsigned char) attr;
2207212a830Sveego
221974e9f6eSveego cp = (unsigned char *) &console_buffer[cv_rowc[dy]+dx];
222974e9f6eSveego *cp++ = (unsigned char) c;
223974e9f6eSveego *cp = (unsigned char) attr;
22439aeb2aaSveego }
22539aeb2aaSveego
22639aeb2aaSveego
22739aeb2aaSveego void
cv_clear(struct ite_softc * ip,int sy,int sx,int h,int w)2289382c873Saymeric cv_clear(struct ite_softc *ip, int sy, int sx, int h, int w)
22939aeb2aaSveego {
230974e9f6eSveego /* cv_clear and cv_scroll both rely on ite passing arguments
231974e9f6eSveego * which describe continuous regions. For a VT200 terminal,
232974e9f6eSveego * this is safe behavior.
233974e9f6eSveego */
234*3ba91b05She volatile unsigned short *dst;
235974e9f6eSveego int len;
23639aeb2aaSveego
237*3ba91b05She dst = (volatile unsigned short *)
238*3ba91b05She ((volatile char*)ip->grf->g_fbkva +
239*3ba91b05She (((sy * ip->cols) + sx) << 2));
240974e9f6eSveego
241974e9f6eSveego for (len = w * h; len > 0 ; len--) {
242974e9f6eSveego *dst = 0x2007;
243974e9f6eSveego dst +=2;
24439aeb2aaSveego }
24539aeb2aaSveego
246974e9f6eSveego dst = &console_buffer[(sy * ip->cols) + sx];
247974e9f6eSveego for (len = w * h; len > 0 ; len--) {
248974e9f6eSveego *dst++ = 0x2007;
249974e9f6eSveego }
250974e9f6eSveego }
25139aeb2aaSveego
25239aeb2aaSveego void
cv_scroll(struct ite_softc * ip,int sy,int sx,int count,int dir)2539382c873Saymeric cv_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir)
25439aeb2aaSveego {
255*3ba91b05She volatile unsigned short *src, *dst, *dst2;
256974e9f6eSveego int i;
257974e9f6eSveego int len;
25839aeb2aaSveego
259*3ba91b05She src = (volatile unsigned short *)
260*3ba91b05She ((volatile char*)ip->grf->g_fbkva + (cv_rowc[sy] << 2));
261974e9f6eSveego
26239aeb2aaSveego switch (dir) {
26339aeb2aaSveego case SCROLL_UP:
2647212a830Sveego dst = src - ((cv_rowc[count])<<1);
2657212a830Sveego
2667212a830Sveego len = cv_rowc[(ip->bottom_margin + 1 - sy)];
2677212a830Sveego src = &console_buffer[cv_rowc[sy]];
2687212a830Sveego
269974e9f6eSveego if (count > sy) { /* boundary checks */
270974e9f6eSveego dst2 = console_buffer;
271*3ba91b05She dst = (volatile unsigned short *)(ip->grf->g_fbkva);
2727212a830Sveego len -= cv_rowc[(count - sy)];
2737212a830Sveego src += cv_rowc[(count - sy)];
274974e9f6eSveego } else
2757212a830Sveego dst2 = &console_buffer[cv_rowc[(sy-count)]];
2767212a830Sveego
277*3ba91b05She bcopy (__UNVOLATILE(src), __UNVOLATILE(dst2), len << 1);
27839aeb2aaSveego
279974e9f6eSveego for (i = 0; i < len; i++) {
280974e9f6eSveego *dst++ = *dst2++;
281974e9f6eSveego dst++;
282974e9f6eSveego }
28339aeb2aaSveego break;
28439aeb2aaSveego case SCROLL_DOWN:
2857212a830Sveego dst = src + ((cv_rowc[count]) << 1);
2867212a830Sveego
2877212a830Sveego len = cv_rowc[(ip->bottom_margin + 1 - (sy + count))];
2887212a830Sveego src = &console_buffer[cv_rowc[sy]];
2897212a830Sveego dst2 = &console_buffer[cv_rowc[(sy + count)]];
2907212a830Sveego
2917212a830Sveego if (len < 0)
2927212a830Sveego return; /* do some boundary check */
2937212a830Sveego
294*3ba91b05She bcopy (__UNVOLATILE(src), __UNVOLATILE(dst2), len << 1);
29539aeb2aaSveego
296974e9f6eSveego for (i = 0; i < len; i++) {
297974e9f6eSveego *dst++ = *dst2++;
298974e9f6eSveego dst++;
299974e9f6eSveego }
30039aeb2aaSveego break;
301974e9f6eSveego case SCROLL_RIGHT:
302974e9f6eSveego dst = src + ((sx+count)<<1);
3037212a830Sveego src = &console_buffer[cv_rowc[sy] + sx];
304974e9f6eSveego len = ip->cols - (sx + count);
3057212a830Sveego dst2 = &console_buffer[cv_rowc[sy] + sx + count];
306*3ba91b05She bcopy (__UNVOLATILE(src), __UNVOLATILE(dst2), len << 1);
307974e9f6eSveego
308974e9f6eSveego for (i = 0; i < len; i++) {
309974e9f6eSveego *dst++ = *dst2++;
310974e9f6eSveego dst++;
311974e9f6eSveego }
31239aeb2aaSveego break;
31339aeb2aaSveego case SCROLL_LEFT:
314974e9f6eSveego dst = src + ((sx - count)<<1);
3157212a830Sveego src = &console_buffer[cv_rowc[sy] + sx];
316974e9f6eSveego len = ip->cols - sx;
3177212a830Sveego dst2 = &console_buffer[cv_rowc[sy] + sx - count];
318*3ba91b05She bcopy (__UNVOLATILE(src), __UNVOLATILE(dst2), len << 1);
319974e9f6eSveego
320974e9f6eSveego for (i = 0; i < len; i++) {
321974e9f6eSveego *dst++ = *dst2++;
322974e9f6eSveego dst++;
323974e9f6eSveego }
32439aeb2aaSveego }
32539aeb2aaSveego }
32639aeb2aaSveego
32739aeb2aaSveego #endif /* NGRFCV */
328