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