ite_rt.c revision 1.7 1 /*
2 * $Id: ite_rt.c,v 1.7 1994/02/17 09:10:49 chopps Exp $
3 */
4
5 #include "ite.h"
6 #if NITE > 0
7
8 #include <sys/param.h>
9 #include <sys/conf.h>
10 #include <sys/proc.h>
11 #include <sys/ioctl.h>
12 #include <sys/tty.h>
13 #include <sys/systm.h>
14 #include <dev/cons.h>
15
16 #include <amiga/dev/itevar.h>
17
18 #include <machine/cpu.h>
19
20 /* XXX */
21 #include <amiga/dev/grfioctl.h>
22 #include <amiga/dev/grfvar.h>
23 #include <amiga/dev/grf_rtreg.h>
24
25
26 /*
27 * retina_cnprobe is called when the console is being initialized
28 * i.e. very early. grfconfig() has been called, so this implies
29 * that rt_init() was called. If we are functioning retina_inited
30 * will be true.
31 */
32 int
33 retina_cnprobe(min)
34 int min;
35 {
36 extern int retina_inited; /* in grf_rt.c */
37 return (retina_inited ? CN_INTERNAL : CN_DEAD);
38 }
39
40 void retina_init(struct ite_softc *ip)
41 {
42 struct MonDef *md;
43
44 if (ip->grf == 0)
45 ip->grf = &grf_softc[ip - ite_softc];
46
47 ip->priv = ip->grf->g_data;
48 md = (struct MonDef *) ip->priv;
49
50 ip->cols = md->TX;
51 ip->rows = md->TY;
52 }
53
54
55 void retina_cursor(struct ite_softc *ip, int flag)
56 {
57 volatile u_char *ba = ip->grf->g_regkva;
58
59 if (flag == ERASE_CURSOR)
60 {
61 /* disable cursor */
62 WCrt (ba, CRT_ID_CURSOR_START, RCrt (ba, CRT_ID_CURSOR_START) | 0x20);
63 }
64 else
65 {
66 int pos = ip->curx + ip->cury * ip->cols;
67
68 /* make sure to enable cursor */
69 WCrt (ba, CRT_ID_CURSOR_START, RCrt (ba, CRT_ID_CURSOR_START) & ~0x20);
70
71 /* and position it */
72 WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, (u_char) (pos >> 8));
73 WCrt (ba, CRT_ID_CURSOR_LOC_LOW, (u_char) pos);
74
75 ip->cursorx = ip->curx;
76 ip->cursory = ip->cury;
77 }
78 }
79
80
81
82 static void screen_up (struct ite_softc *ip, int top, int bottom, int lines)
83 {
84 volatile u_char * ba = ip->grf->g_regkva;
85 volatile u_char * fb = ip->grf->g_fbkva;
86 const struct MonDef * md = (struct MonDef *) ip->priv;
87 #ifdef BANKEDDEVPAGER
88 int bank;
89 #endif
90
91 /* do some bounds-checking here.. */
92 if (top >= bottom)
93 return;
94
95 if (top + lines >= bottom)
96 {
97 retina_clear (ip, top, 0, bottom - top, ip->cols);
98 return;
99 }
100
101
102 #ifdef BANKEDDEVPAGER
103 /* make sure to save/restore active bank (and if it's only
104 for tests of the feature in text-mode..) */
105 bank = (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO)
106 | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8));
107 #endif
108
109 /* the trick here is to use a feature of the NCR chip. It can
110 optimize data access in various read/write modes. One of
111 the modes is able to read/write from/to different zones.
112
113 Thus, by setting the read-offset to lineN, and the write-offset
114 to line0, we just cause read/write cycles for all characters
115 up to the last line, and have the chip transfer the data. The
116 `addqb' are the cheapest way to cause read/write cycles (DONT
117 use `tas' on the Amiga!), their results are completely ignored
118 by the NCR chip, it just replicates what it just read. */
119
120 /* write to primary, read from secondary */
121 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
122 /* clear extended chain4 mode */
123 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02);
124
125 /* set write mode 1, "[...] data in the read latches is written
126 to memory during CPU memory write cycles. [...]" */
127 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
128
129 {
130 /* write to line TOP */
131 long toploc = top * (md->TX / 16);
132 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, ((unsigned char)toploc));
133 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, ((unsigned char)(toploc >> 8)));
134 }
135 {
136 /* read from line TOP + LINES */
137 long fromloc = (top+lines) * (md->TX / 16);
138 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, ((unsigned char)fromloc)) ;
139 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, ((unsigned char)(fromloc >> 8))) ;
140 }
141 {
142 unsigned char * p = (unsigned char *) fb;
143 /* transfer all characters but LINES lines, unroll by 16 */
144 short x = (1 + bottom - (top + lines)) * (md->TX / 16) - 1;
145 do {
146 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
147 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
148 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
149 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
150 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
151 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
152 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
153 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
154 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
155 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
156 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
157 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
158 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
159 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
160 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
161 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p));
162 } while (x--);
163 }
164
165 /* reset to default values */
166 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0);
167 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0);
168 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0);
169 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0);
170 /* write mode 0 */
171 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 0);
172 /* extended chain4 enable */
173 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR , RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
174 /* read/write to primary on A0, secondary on B0 */
175 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0x40 );
176
177
178 /* fill the free lines with spaces */
179
180 { /* feed latches with value */
181 unsigned short * f = (unsigned short *) fb;
182
183 f += (1 + bottom - lines) * md->TX * 2;
184 *f = 0x2010;
185 {
186 volatile unsigned short dummy = *((volatile unsigned short *)f);
187 }
188 }
189
190 /* clear extended chain4 mode */
191 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02);
192 /* set write mode 1, "[...] data in the read latches is written
193 to memory during CPU memory write cycles. [...]" */
194 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
195
196 {
197 unsigned long * p = (unsigned long *) fb;
198 short x = (lines * (md->TX/16)) - 1;
199 const unsigned long dummyval = 0;
200
201 p += (1 + bottom - lines) * (md->TX/4);
202
203 do {
204 *p++ = dummyval;
205 *p++ = dummyval;
206 *p++ = dummyval;
207 *p++ = dummyval;
208 } while (x--);
209 }
210
211 /* write mode 0 */
212 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 0);
213 /* extended chain4 enable */
214 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR , RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
215
216 #ifdef BANKEDDEVPAGER
217 /* restore former bank */
218 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
219 bank >>= 8;
220 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
221 #endif
222 };
223
224 static void screen_down (struct ite_softc *ip, int top, int bottom, int lines)
225 {
226 volatile u_char * ba = ip->grf->g_regkva;
227 volatile u_char * fb = ip->grf->g_fbkva;
228 const struct MonDef * md = (struct MonDef *) ip->priv;
229 #ifdef BANKEDDEVPAGER
230 int bank;
231 #endif
232
233 /* do some bounds-checking here.. */
234 if (top >= bottom)
235 return;
236
237 if (top + lines >= bottom)
238 {
239 retina_clear (ip, top, 0, bottom - top, ip->cols);
240 return;
241 }
242
243 #ifdef BANKEDDEVPAGER
244 /* make sure to save/restore active bank (and if it's only
245 for tests of the feature in text-mode..) */
246 bank = (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO)
247 | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8));
248 #endif
249 /* see screen_up() for explanation of chip-tricks */
250
251 /* write to primary, read from secondary */
252 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
253 /* clear extended chain4 mode */
254 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02);
255
256 /* set write mode 1, "[...] data in the read latches is written
257 to memory during CPU memory write cycles. [...]" */
258 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
259
260 {
261 /* write to line TOP + LINES */
262 long toloc = (top + lines) * (md->TX / 16);
263 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, ((unsigned char)toloc));
264 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, ((unsigned char)(toloc >> 8)));
265 }
266 {
267 /* read from line TOP */
268 long fromloc = top * (md->TX / 16);
269 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, ((unsigned char)fromloc));
270 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, ((unsigned char)(fromloc >> 8))) ;
271 }
272
273 {
274 unsigned char * p = (unsigned char *) fb;
275 short x = (1 + bottom - (top + lines)) * (md->TX / 16) - 1;
276 p += (1 + bottom - (top + lines)) * md->TX;
277 do {
278 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
279 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
280 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
281 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
282 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
283 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
284 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
285 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
286 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
287 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
288 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
289 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
290 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
291 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
292 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
293 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p));
294 } while (x--);
295 }
296
297 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0);
298 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0);
299 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0);
300 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0);
301
302 /* write mode 0 */
303 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 0);
304 /* extended chain4 enable */
305 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR , RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
306 /* read/write to primary on A0, secondary on B0 */
307 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0x40 );
308
309 /* fill the free lines with spaces */
310
311 { /* feed latches with value */
312 unsigned short * f = (unsigned short *) fb;
313
314 f += top * md->TX * 2;
315 *f = 0x2010;
316 {
317 volatile unsigned short dummy = *((volatile unsigned short *)f);
318 }
319 }
320
321 /* clear extended chain4 mode */
322 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02);
323 /* set write mode 1, "[...] data in the read latches is written
324 to memory during CPU memory write cycles. [...]" */
325 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
326
327 {
328 unsigned long * p = (unsigned long *) fb;
329 short x = (lines * (md->TX/16)) - 1;
330 const unsigned long dummyval = 0;
331
332 p += top * (md->TX/4);
333
334 do {
335 *p++ = dummyval;
336 *p++ = dummyval;
337 *p++ = dummyval;
338 *p++ = dummyval;
339 } while (x--);
340 }
341
342 /* write mode 0 */
343 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 0);
344 /* extended chain4 enable */
345 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR , RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
346
347 #ifdef BANKEDDEVPAGER
348 /* restore former bank */
349 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
350 bank >>= 8;
351 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
352 #endif
353 };
354
355 void retina_deinit(struct ite_softc *ip)
356 {
357 ip->flags &= ~ITE_INITED;
358 }
359
360
361 void retina_putc(struct ite_softc *ip, int c, int dy, int dx, int mode)
362 {
363 volatile u_char * ba = ip->grf->g_regkva;
364 volatile u_char * fb = ip->grf->g_fbkva;
365 register u_char attr;
366
367 attr = (mode & ATTR_INV) ? 0x21 : 0x10;
368 if (mode & ATTR_UL) attr = 0x01; /* ???????? */
369 if (mode & ATTR_BOLD) attr |= 0x08;
370 if (mode & ATTR_BLINK) attr |= 0x80;
371
372 fb += 4 * (dy * ip->cols + dx);
373 *fb++ = c; *fb = attr;
374 }
375
376 void retina_clear(struct ite_softc *ip, int sy, int sx, int h, int w)
377 {
378 volatile u_char * ba = ip->grf->g_regkva;
379 u_short * fb = (u_short *) ip->grf->g_fbkva;
380 short x;
381 const u_short fillval = 0x2010;
382 /* could probably be optimized just like the scrolling functions !! */
383 fb += 2 * (sy * ip->cols + sx);
384 while (h--)
385 {
386 for (x = 2 * (w - 1); x >= 0; x -= 2)
387 fb[x] = fillval;
388 fb += 2 * ip->cols;
389 }
390 }
391
392 void retina_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir)
393 {
394 volatile u_char * ba = ip->grf->g_regkva;
395 u_long * fb = (u_long *) ip->grf->g_fbkva;
396 register int height, dy, i;
397
398 retina_cursor(ip, ERASE_CURSOR);
399
400 if (dir == SCROLL_UP)
401 {
402 screen_up (ip, sy - count, ip->bottom_margin, count);
403 /* bcopy (fb + sy * ip->cols, fb + (sy - count) * ip->cols, 4 * (ip->bottom_margin - sy + 1) * ip->cols); */
404 /* retina_clear (ip, ip->bottom_margin + 1 - count, 0, count, ip->cols); */
405 }
406 else if (dir == SCROLL_DOWN)
407 {
408 screen_down (ip, sy, ip->bottom_margin, count);
409 /* bcopy (fb + sy * ip->cols, fb + (sy + count) * ip->cols, 4 * (ip->bottom_margin - sy - count + 1) * ip->cols); */
410 /* retina_clear (ip, sy, 0, count, ip->cols); */
411 }
412 else if (dir == SCROLL_RIGHT)
413 {
414 bcopy (fb + sx + sy * ip->cols, fb + sx + sy * ip->cols + count, 4 * (ip->cols - (sx + count)));
415 retina_clear (ip, sy, sx, 1, count);
416 }
417 else
418 {
419 bcopy (fb + sx + sy * ip->cols, fb + sx - count + sy * ip->cols, 4 * (ip->cols - sx));
420 retina_clear (ip, sy, ip->cols - count, 1, count);
421 }
422 }
423
424 #endif
425
426
427
428