ite_cc.c revision 1.20 1 /* $NetBSD: ite_cc.c,v 1.20 1994/10/26 02:03:57 cgd Exp $ */
2
3 #include "grfcc.h"
4 #if NGRFCC > 0
5
6 #include <sys/param.h>
7 #include <sys/conf.h>
8 #include <sys/proc.h>
9 #include <sys/device.h>
10 #include <sys/ioctl.h>
11 #include <sys/tty.h>
12 #include <sys/systm.h>
13 #include <sys/queue.h>
14 #include <sys/termios.h>
15 #include <dev/cons.h>
16 #include <machine/cpu.h>
17 #include <amiga/dev/itevar.h>
18 #include <amiga/dev/iteioctl.h>
19 #include <amiga/amiga/cc.h>
20 #include <amiga/amiga/device.h>
21 #include <amiga/dev/grfabs_reg.h>
22 #include <amiga/dev/grfioctl.h>
23 #include <amiga/dev/grfvar.h>
24 #include <amiga/dev/grf_ccreg.h>
25 #include <amiga/dev/viewioctl.h>
26 #include <amiga/dev/viewvar.h>
27
28 #ifndef KFONT_CUSTOM
29 #ifdef KFONT_8X11
30 #define kernel_font_width kernel_font_width_8x11
31 #define kernel_font_height kernel_font_height_8x11
32 #define kernel_font_baseline kernel_font_baseline_8x11
33 #define kernel_font_boldsmear kernel_font_boldsmear_8x11
34 #define kernel_font_lo kernel_font_lo_8x11
35 #define kernel_font_hi kernel_font_hi_8x11
36 #define kernel_font kernel_font_8x11
37 #define kernel_cursor kernel_cursor_8x11
38 #else
39 #define kernel_font_width kernel_font_width_8x8
40 #define kernel_font_height kernel_font_height_8x8
41 #define kernel_font_baseline kernel_font_baseline_8x8
42 #define kernel_font_boldsmear kernel_font_boldsmear_8x8
43 #define kernel_font_lo kernel_font_lo_8x8
44 #define kernel_font_hi kernel_font_hi_8x8
45 #define kernel_font kernel_font_8x8
46 #define kernel_cursor kernel_cursor_8x8
47 #endif
48 #endif
49
50 extern u_char kernel_font_width, kernel_font_height, kernel_font_baseline;
51 extern short kernel_font_boldsmear;
52 extern u_char kernel_font_lo, kernel_font_hi;
53 extern u_char kernel_font[], kernel_cursor[];
54
55 /*
56 * This is what ip->priv points to;
57 * it contains local variables for custom-chip ites.
58 */
59 struct ite_priv {
60 view_t *view; /* the view for this ite. */
61 u_char **row_ptr; /* array of pointers into the bitmap */
62 u_long row_bytes;
63 u_long cursor_opt;
64 u_int *column_offset; /* array of offsets for columns */
65 u_int row_offset; /* the row offset */
66 u_short width; /* the bitmap width */
67 u_short underline; /* where the underline goes */
68 u_short ft_x; /* the font width */
69 u_short ft_y; /* the font height */
70 u_char *font_cell[256]; /* the font pointer */
71 };
72 typedef struct ite_priv ipriv_t;
73
74 void view_deinit __P((struct ite_softc *));
75 void view_init __P((struct ite_softc *));
76
77 static void putc8 __P((struct ite_softc *, int, int, int, int));
78 static void clear8 __P((struct ite_softc *, int, int, int, int));
79 static void scroll8 __P((struct ite_softc *, int, int, int, int));
80 static void cursor32 __P((struct ite_softc *, int));
81 static void scrollbmap __P((bmap_t *, u_short, u_short, u_short, u_short,
82 short, short, u_char));
83
84 /* patchable */
85 int ite_default_x = 0; /* def leftedge offset */
86 int ite_default_y = 0; /* def topedge offset */
87 int ite_default_width = 640; /* def width */
88 int ite_default_depth = 2; /* def depth */
89 #if defined (GRF_NTSC)
90 int ite_default_height = 400; /* def NTSC height */
91 #elif defined (GRF_PAL)
92 int ite_default_height = 512; /* def PAL height */
93 #else
94 int ite_default_height = 400; /* def NON-PAL/NTSC height (?) */
95 #endif
96
97 /* audio bell stuff */
98 u_int bvolume = 10;
99 u_int bpitch = 660;
100 u_int bmsec = 75;
101
102 static char *bsamplep;
103 static char sample[20] = {
104 0,39,75,103,121,127,121,103,75,39,0,
105 -39,-75,-103,-121,-127,-121,-103,-75,-39
106 };
107
108 /*
109 * called from grf_cc to return console priority
110 */
111 int
112 grfcc_cnprobe()
113 {
114 return(CN_INTERNAL);
115 }
116
117 /*
118 * called from grf_cc to init ite portion of
119 * grf_softc struct
120 */
121 void
122 grfcc_iteinit(gp)
123 struct grf_softc *gp;
124 {
125 gp->g_itecursor = cursor32;
126 gp->g_iteputc = putc8;
127 gp->g_iteclear = clear8;
128 gp->g_itescroll = scroll8;
129 gp->g_iteinit = view_init;
130 gp->g_itedeinit = view_deinit;
131 }
132
133 void
134 init_bell()
135 {
136 short i;
137
138 if (bsamplep != NULL)
139 return;
140 bsamplep = alloc_chipmem(20);
141 if (bsamplep == NULL)
142 panic("no chipmem for ccbell");
143
144 bcopy(sample, bsamplep, 20);
145 }
146
147 void
148 cc_bell()
149 {
150 u_int clock;
151 u_int period;
152 u_int count;
153
154 clock = 3579545; /* PAL 3546895 */
155
156 /*
157 * the number of clock ticks per sample byte must be > 124
158 * ergo bpitch must be < clock / 124*20
159 * i.e. ~1443, 1300 to be safe (PAL etc.). also not zero obviously
160 */
161 period = clock / (bpitch * 20);
162 count = bmsec * bpitch / 1000;
163
164 play_sample(10, PREP_DMA_MEM(bsamplep), period, bvolume, 0x3, count);
165 }
166
167
168 int
169 ite_newsize(ip, winsz)
170 struct ite_softc *ip;
171 struct itewinsize *winsz;
172 {
173 extern struct view_softc views[];
174 struct view_size vs;
175 ipriv_t *cci = ip->priv;
176 u_long fbp, i;
177 int error;
178
179 vs.x = winsz->x;
180 vs.y = winsz->y;
181 vs.width = winsz->width;
182 vs.height = winsz->height;
183 vs.depth = winsz->depth;
184 error = viewioctl(0, VIOCSSIZE, &vs, 0, -1);
185
186 /*
187 * Reinitialize our structs
188 */
189 cci->view = views[0].view;
190
191 /* -1 for bold. */
192 ip->cols = (cci->view->display.width - 1) / ip->ftwidth;
193 ip->rows = cci->view->display.height / ip->ftheight;
194
195 /*
196 * save new values so that future opens use them
197 * this may not be correct when we implement Virtual Consoles
198 */
199 ite_default_height = cci->view->display.height;
200 ite_default_width = cci->view->display.width;
201 ite_default_x = cci->view->display.x;
202 ite_default_y = cci->view->display.y;
203 ite_default_depth = cci->view->bitmap->depth;
204
205 if (cci->row_ptr)
206 free_chipmem(cci->row_ptr);
207 if (cci->column_offset)
208 free_chipmem(cci->column_offset);
209
210 cci->row_ptr = alloc_chipmem(sizeof(u_char *) * ip->rows);
211 cci->column_offset = alloc_chipmem(sizeof(u_int) * ip->cols);
212
213 if (cci->row_ptr == NULL || cci->column_offset == NULL)
214 panic("no chipmem for itecc data");
215
216
217 cci->width = cci->view->bitmap->bytes_per_row << 3;
218 cci->underline = ip->ftbaseline + 1;
219 cci->row_offset = cci->view->bitmap->bytes_per_row
220 + cci->view->bitmap->row_mod;
221 cci->ft_x = ip->ftwidth;
222 cci->ft_y = ip->ftheight;
223
224 cci->row_bytes = cci->row_offset * ip->ftheight;
225
226 cci->row_ptr[0] = VDISPLAY_LINE (cci->view, 0, 0);
227 for (i = 1; i < ip->rows; i++)
228 cci->row_ptr[i] = cci->row_ptr[i-1] + cci->row_bytes;
229
230 /* initialize the column offsets */
231 cci->column_offset[0] = 0;
232 for (i = 1; i < ip->cols; i++)
233 cci->column_offset[i] = cci->column_offset[i - 1] + cci->ft_x;
234
235 /* initialize the font cell pointers */
236 cci->font_cell[ip->font_lo] = ip->font;
237 for (i=ip->font_lo+1; i<=ip->font_hi; i++)
238 cci->font_cell[i] = cci->font_cell[i-1] + ip->ftheight;
239
240 return (error);
241 }
242
243 void
244 view_init(ip)
245 register struct ite_softc *ip;
246 {
247 struct itewinsize wsz;
248 ipriv_t *cci;
249
250 cci = ip->priv;
251
252 if (cci)
253 return;
254
255 init_bell();
256
257 ip->font = kernel_font;
258 ip->font_lo = kernel_font_lo;
259 ip->font_hi = kernel_font_hi;
260 ip->ftwidth = kernel_font_width;
261 ip->ftheight = kernel_font_height;
262 ip->ftbaseline = kernel_font_baseline;
263 ip->ftboldsmear = kernel_font_boldsmear;
264
265 /* Find the correct set of rendering routines for this font. */
266 if (ip->ftwidth > 8)
267 panic("kernel font size not supported");
268 cci = alloc_chipmem(sizeof (*cci));
269 if (cci == NULL)
270 panic("no memory for console device.");
271
272 ip->priv = cci;
273 cci->cursor_opt = 0;
274 cci->view = NULL;
275 cci->row_ptr = NULL;
276 cci->column_offset = NULL;
277
278 wsz.x = ite_default_x;
279 wsz.y = ite_default_y;
280 wsz.width = ite_default_width;
281 wsz.height = ite_default_height;
282 wsz.depth = ite_default_depth;
283
284 ite_newsize (ip, &wsz);
285 cc_mode(ip->grf, GM_GRFON, NULL, 0, 0);
286 }
287
288 int
289 ite_grf_ioctl (ip, cmd, addr, flag, p)
290 struct ite_softc *ip;
291 caddr_t addr;
292 struct proc *p;
293 {
294 struct winsize ws;
295 struct itewinsize *is;
296 struct itebell *ib;
297 ipriv_t *cci;
298 int error;
299
300 cci = ip->priv;
301 error = 0;
302
303 switch (cmd) {
304 case ITEIOCGWINSZ:
305 is = (struct itewinsize *)addr;
306 is->x = cci->view->display.x;
307 is->y = cci->view->display.y;
308 is->width = cci->view->display.width;
309 is->height = cci->view->display.height;
310 is->depth = cci->view->bitmap->depth;
311 break;
312 case ITEIOCSWINSZ:
313 is = (struct itewinsize *)addr;
314
315 if (ite_newsize(ip, is))
316 error = ENOMEM;
317 else {
318 ws.ws_row = ip->rows;
319 ws.ws_col = ip->cols;
320 ws.ws_xpixel = cci->view->display.width;
321 ws.ws_ypixel = cci->view->display.height;
322 ite_reset (ip);
323 /*
324 * XXX tell tty about the change
325 * XXX this is messy, but works
326 */
327 iteioctl(0, TIOCSWINSZ, (caddr_t)&ws, 0, p);
328 }
329 break;
330 case ITEIOCDSPWIN:
331 cc_mode(ip->grf, GM_GRFON, NULL, 0, 0);
332 break;
333 case ITEIOCREMWIN:
334 cc_mode(ip->grf, GM_GRFOFF, NULL, 0, 0);
335 break;
336 case ITEIOCGBELL:
337 ib = (struct itebell *)addr;
338 ib->volume = bvolume;
339 ib->pitch = bpitch;
340 ib->msec = bmsec;
341 break;
342 case ITEIOCSBELL:
343 ib = (struct itebell *)addr;
344 /* bounds check */
345 if (ib->pitch > MAXBPITCH || ib->pitch < MINBPITCH ||
346 ib->volume > MAXBVOLUME || ib->msec > MAXBTIME)
347 error = EINVAL;
348 else {
349 bvolume = ib->volume;
350 bpitch = ib->pitch;
351 bmsec = ib->msec;
352 }
353 break;
354 case VIOCSCMAP:
355 case VIOCGCMAP:
356 /*
357 * XXX needs to be fixed when multiple console implemented
358 * XXX watchout for that -1 its not really the kernel talking
359 * XXX these two commands don't use the proc pointer though
360 */
361 error = viewioctl(0, cmd, addr, flag, -1);
362 break;
363 default:
364 error = -1;
365 break;
366 }
367 return (error);
368 }
369
370 void
371 view_deinit(ip)
372 struct ite_softc *ip;
373 {
374 ip->flags &= ~ITE_INITED;
375 }
376
377 /*** (M<8)-by-N routines ***/
378
379 static void
380 cursor32(struct ite_softc *ip, int flag)
381 {
382 int cend, ofs, h, cstart, dr_plane;
383 u_char *pl, opclr, opset;
384 ipriv_t *cci;
385 bmap_t *bm;
386 view_t *v;
387
388 cci = ip->priv;
389 v = cci->view;
390 bm = v->bitmap;
391 dr_plane = (bm->depth > 1 ? bm->depth-1 : 0);
392
393 if (flag == END_CURSOROPT)
394 cci->cursor_opt--;
395 else if (flag == START_CURSOROPT) {
396 if (!cci->cursor_opt)
397 cursor32 (ip, ERASE_CURSOR);
398 cci->cursor_opt++;
399 return; /* if we are already opted. */
400 }
401
402 if (cci->cursor_opt)
403 return; /* if we are still nested. */
404 /* else we draw the cursor. */
405 cstart = 0;
406 cend = ip->ftheight-1;
407 pl = VDISPLAY_LINE(v, dr_plane, (ip->cursory * ip->ftheight + cstart));
408 ofs = (ip->cursorx * ip->ftwidth);
409
410 if (flag != DRAW_CURSOR && flag != END_CURSOROPT) {
411 /*
412 * erase the cursor
413 */
414 int h;
415
416 if (dr_plane) {
417 for (h = cend; h >= 0; h--) {
418 asm("bfclr %0@{%1:%2}" : : "a" (pl),
419 "d" (ofs), "d" (ip->ftwidth));
420 pl += cci->row_offset;
421 }
422 } else {
423 for (h = cend; h >= 0; h--) {
424 asm("bfchg %0@{%1:%2}" : : "a" (pl),
425 "d" (ofs), "d" (ip->ftwidth));
426 pl += cci->row_offset;
427 }
428 }
429 }
430
431 if (flag != DRAW_CURSOR && flag != MOVE_CURSOR &&
432 flag != END_CURSOROPT)
433 return;
434
435 /*
436 * draw the cursor
437 */
438
439 ip->cursorx = min(ip->curx, ip->cols-1);
440 ip->cursory = ip->cury;
441 cstart = 0;
442 cend = ip->ftheight-1;
443 pl = VDISPLAY_LINE(v, dr_plane, ip->cursory * ip->ftheight + cstart);
444 ofs = ip->cursorx * ip->ftwidth;
445
446 if (dr_plane) {
447 for (h = cend; h >= 0; h--) {
448 asm("bfset %0@{%1:%2}" : : "a" (pl),
449 "d" (ofs), "d" (ip->ftwidth));
450 pl += cci->row_offset;
451 }
452 } else {
453 for (h = cend; h >= 0; h--) {
454 asm("bfchg %0@{%1:%2}" : : "a" (pl),
455 "d" (ofs), "d" (ip->ftwidth));
456 pl += cci->row_offset;
457 }
458 }
459 }
460
461
462 static inline
463 int expbits (int data)
464 {
465 int i, nd = 0;
466
467 if (data & 1)
468 nd |= 0x02;
469 for (i=1; i < 32; i++) {
470 if (data & (1 << i))
471 nd |= 0x5 << (i-1);
472 }
473 nd &= ~data;
474 return(~nd);
475 }
476
477
478 /* Notes: optimizations given the kernel_font_(width|height) #define'd.
479 * the dbra loops could be elminated and unrolled using height,
480 * the :width in the bfxxx instruction could be made immediate instead
481 * of a data register as it now is.
482 * the underline could be added when the loop is unrolled
483 *
484 * It would look like hell but be very fast.*/
485
486 static void
487 putc_nm (cci,p,f,co,ro,fw,fh)
488 register ipriv_t *cci;
489 register u_char *p;
490 register u_char *f;
491 register u_int co;
492 register u_int ro;
493 register u_int fw;
494 register u_int fh;
495 {
496 while (fh--) {
497 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
498 "d" (*f++), "a" (p), "d" (co), "d" (fw));
499 p += ro;
500 }
501 }
502
503 static void
504 putc_in (cci,p,f,co,ro,fw,fh)
505 register ipriv_t *cci;
506 register u_char *p;
507 register u_char *f;
508 register u_int co;
509 register u_int ro;
510 register u_int fw;
511 register u_int fh;
512 {
513 while (fh--) {
514 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
515 "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
516 p += ro;
517 }
518 }
519
520
521 static void
522 putc_ul (cci,p,f,co,ro,fw,fh)
523 register ipriv_t *cci;
524 register u_char *p;
525 register u_char *f;
526 register u_int co;
527 register u_int ro;
528 register u_int fw;
529 register u_int fh;
530 {
531 int underline = cci->underline;
532 while (underline--) {
533 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
534 "d" (*f++), "a" (p), "d" (co), "d" (fw));
535 p += ro;
536 }
537
538 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
539 "d" (expbits(*f++)), "a" (p), "d" (co), "d" (fw));
540 p += ro;
541
542 underline = fh - cci->underline - 1;
543 while (underline--) {
544 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
545 "d" (*f++), "a" (p), "d" (co), "d" (fw));
546 p += ro;
547 }
548 }
549
550
551 static void
552 putc_ul_in (cci,p,f,co,ro,fw,fh)
553 register ipriv_t *cci;
554 register u_char *p;
555 register u_char *f;
556 register u_int co;
557 register u_int ro;
558 register u_int fw;
559 register u_int fh;
560 {
561 int underline = cci->underline;
562 while (underline--) {
563 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
564 "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
565 p += ro;
566 }
567
568 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
569 "d" (~expbits(*f++)), "a" (p), "d" (co), "d" (fw));
570 p += ro;
571
572 underline = fh - cci->underline - 1;
573 while (underline--) {
574 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
575 "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
576 p += ro;
577 }
578 }
579
580 /* bold */
581 static void
582 putc_bd (cci,p,f,co,ro,fw,fh)
583 register ipriv_t *cci;
584 register u_char *p;
585 register u_char *f;
586 register u_int co;
587 register u_int ro;
588 register u_int fw;
589 register u_int fh;
590 {
591 u_short ch;
592
593 while (fh--) {
594 ch = *f++;
595 ch |= ch << 1;
596 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
597 "d" (ch), "a" (p), "d" (co), "d" (fw+1));
598 p += ro;
599 }
600 }
601
602 static void
603 putc_bd_in (cci,p,f,co,ro,fw,fh)
604 register ipriv_t *cci;
605 register u_char *p;
606 register u_char *f;
607 register u_int co;
608 register u_int ro;
609 register u_int fw;
610 register u_int fh;
611 {
612 u_short ch;
613
614 while (fh--) {
615 ch = *f++;
616 ch |= ch << 1;
617 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
618 "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
619 p += ro;
620 }
621 }
622
623
624 static void
625 putc_bd_ul (cci,p,f,co,ro,fw,fh)
626 register ipriv_t *cci;
627 register u_char *p;
628 register u_char *f;
629 register u_int co;
630 register u_int ro;
631 register u_int fw;
632 register u_int fh;
633 {
634 int underline = cci->underline;
635 u_short ch;
636
637 while (underline--) {
638 ch = *f++;
639 ch |= ch << 1;
640 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
641 "d" (ch), "a" (p), "d" (co), "d" (fw+1));
642 p += ro;
643 }
644
645 ch = *f++;
646 ch |= ch << 1;
647 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
648 "d" (expbits(ch)), "a" (p), "d" (co), "d" (fw+1));
649 p += ro;
650
651 underline = fh - cci->underline - 1;
652 while (underline--) {
653 ch = *f++;
654 ch |= ch << 1;
655 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
656 "d" (ch), "a" (p), "d" (co), "d" (fw+1));
657 p += ro;
658 }
659 }
660
661
662 static void
663 putc_bd_ul_in (cci,p,f,co,ro,fw,fh)
664 register ipriv_t *cci;
665 register u_char *p;
666 register u_char *f;
667 register u_int co;
668 register u_int ro;
669 register u_int fw;
670 register u_int fh;
671 {
672 int underline = cci->underline;
673 u_short ch;
674
675 while (underline--) {
676 ch = *f++;
677 ch |= ch << 1;
678 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
679 "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
680 p += ro;
681 }
682
683 ch = *f++;
684 ch |= ch << 1;
685 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
686 "d" (~expbits(ch)), "a" (p), "d" (co), "d" (fw+1));
687 p += ro;
688
689 underline = fh - cci->underline - 1;
690 while (underline--) {
691 ch = *f++;
692 ch |= ch << 1;
693 asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
694 "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
695 p += ro;
696 }
697 }
698
699
700 typedef void cc_putc_func ();
701
702 cc_putc_func *put_func[ATTR_ALL+1] = {
703 putc_nm,
704 putc_in,
705 putc_ul,
706 putc_ul_in,
707 putc_bd,
708 putc_bd_in,
709 putc_bd_ul,
710 putc_bd_ul_in,
711 /* no support for blink */
712 putc_nm,
713 putc_in,
714 putc_ul,
715 putc_ul_in,
716 putc_bd,
717 putc_bd_in,
718 putc_bd_ul,
719 putc_bd_ul_in
720 };
721
722
723 /* FIX: shouldn't this advance the cursor even if the character to
724 be output is not available in the font? -ch */
725
726 static void
727 putc8(struct ite_softc *ip, int c, int dy, int dx, int mode)
728 {
729 register ipriv_t *cci = (ipriv_t *) ip->priv;
730 if (c < ip->font_lo || c > ip->font_hi)
731 return;
732
733 put_func[mode](cci,
734 cci->row_ptr[dy],
735 cci->font_cell[c],
736 cci->column_offset[dx],
737 cci->row_offset,
738 cci->ft_x,
739 cci->ft_y);
740 }
741
742 static void
743 clear8(struct ite_softc *ip, int sy, int sx, int h, int w)
744 {
745 ipriv_t *cci = (ipriv_t *) ip->priv;
746 view_t *v = cci->view;
747 bmap_t *bm = cci->view->bitmap;
748
749 if ((sx == 0) && (w == ip->cols))
750 {
751 /* common case: clearing whole lines */
752 while (h--)
753 {
754 int i;
755 u_char *ptr = cci->row_ptr[sy];
756 for (i=0; i < ip->ftheight; i++) {
757 bzero(ptr, bm->bytes_per_row);
758 ptr += bm->bytes_per_row + bm->row_mod; /* don't get any smart
759 ideas, becuase this is for
760 interleaved bitmaps */
761 }
762 sy++;
763 }
764 }
765 else
766 {
767 /* clearing only part of a line */
768 /* XXX could be optimized MUCH better, but is it worth the trouble? */
769 while (h--)
770 {
771 u_char *pl = cci->row_ptr[sy];
772 int ofs = sx * ip->ftwidth;
773 int i, j;
774 for (i = w-1; i >= 0; i--)
775 {
776 u_char *ppl = pl;
777 for (j = ip->ftheight-1; j >= 0; j--)
778 {
779 asm("bfclr %0@{%1:%2}"
780 : : "a" (ppl), "d" (ofs), "d" (ip->ftwidth));
781 ppl += bm->row_mod + bm->bytes_per_row;
782 }
783 ofs += ip->ftwidth;
784 }
785 sy++;
786 }
787 }
788 }
789
790 /* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT. */
791 static void
792 scroll8(ip, sy, sx, count, dir)
793 register struct ite_softc *ip;
794 register int sy;
795 int dir, sx, count;
796 {
797 bmap_t *bm = ((ipriv_t *)ip->priv)->view->bitmap;
798 u_char *pl = ((ipriv_t *)ip->priv)->row_ptr[sy];
799
800 if (dir == SCROLL_UP)
801 {
802 int dy = sy - count;
803 int height = ip->bottom_margin - sy + 1;
804 int i;
805
806 /*FIX: add scroll bitmap call */
807 cursor32(ip, ERASE_CURSOR);
808 scrollbmap (bm, 0, dy*ip->ftheight,
809 bm->bytes_per_row >> 3, (ip->bottom_margin-dy+1)*ip->ftheight,
810 0, -(count*ip->ftheight), 0x1);
811 /* if (ip->cursory <= bot || ip->cursory >= dy) {
812 ip->cursory -= count;
813 } */
814 }
815 else if (dir == SCROLL_DOWN)
816 {
817 int dy = sy + count;
818 int height = ip->bottom_margin - dy + 1;
819 int i;
820
821 /* FIX: add scroll bitmap call */
822 cursor32(ip, ERASE_CURSOR);
823 scrollbmap (bm, 0, sy*ip->ftheight,
824 bm->bytes_per_row >> 3, (ip->bottom_margin-sy+1)*ip->ftheight,
825 0, count*ip->ftheight, 0x1);
826 /* if (ip->cursory <= bot || ip->cursory >= sy) {
827 ip->cursory += count;
828 } */
829 }
830 else if (dir == SCROLL_RIGHT)
831 {
832 int sofs = (ip->cols - count) * ip->ftwidth;
833 int dofs = (ip->cols) * ip->ftwidth;
834 int i, j;
835
836 cursor32(ip, ERASE_CURSOR);
837 for (j = ip->ftheight-1; j >= 0; j--)
838 {
839 int sofs2 = sofs, dofs2 = dofs;
840 for (i = (ip->cols - (sx + count))-1; i >= 0; i--)
841 {
842 int t;
843 sofs2 -= ip->ftwidth;
844 dofs2 -= ip->ftwidth;
845 asm("bfextu %1@{%2:%3},%0"
846 : "=d" (t)
847 : "a" (pl), "d" (sofs2), "d" (ip->ftwidth));
848 asm("bfins %3,%0@{%1:%2}"
849 : : "a" (pl), "d" (dofs2), "d" (ip->ftwidth), "d" (t));
850 }
851 pl += bm->row_mod + bm->bytes_per_row;
852 }
853 }
854 else /* SCROLL_LEFT */
855 {
856 int sofs = (sx) * ip->ftwidth;
857 int dofs = (sx - count) * ip->ftwidth;
858 int i, j;
859
860 cursor32(ip, ERASE_CURSOR);
861 for (j = ip->ftheight-1; j >= 0; j--)
862 {
863 int sofs2 = sofs, dofs2 = dofs;
864 for (i = (ip->cols - sx)-1; i >= 0; i--)
865 {
866 int t;
867 asm("bfextu %1@{%2:%3},%0"
868 : "=d" (t)
869 : "a" (pl), "d" (sofs2), "d" (ip->ftwidth));
870 asm("bfins %3,%0@{%1:%2}"
871 : : "a" (pl), "d" (dofs2), "d" (ip->ftwidth), "d" (t));
872 sofs2 += ip->ftwidth;
873 dofs2 += ip->ftwidth;
874 }
875 pl += bm->row_mod + bm->bytes_per_row;
876 }
877 }
878 }
879
880 void
881 scrollbmap (bmap_t *bm, u_short x, u_short y, u_short width, u_short height, short dx, short dy, u_char mask)
882 {
883 u_short depth = bm->depth;
884 u_short lwpr = bm->bytes_per_row >> 2;
885 if (dx) {
886 /* FIX: */ panic ("delta x not supported in scroll bitmap yet.");
887 }
888 if (bm->flags & BMF_INTERLEAVED) {
889 height *= depth;
890 depth = 1;
891 }
892 if (dy == 0) {
893 return;
894 }
895 if (dy > 0) {
896 int i;
897 for (i=0; i < depth && mask; i++, mask >>= 1) {
898 if (0x1 & mask) {
899 u_long *pl = (u_long *)bm->plane[i];
900 u_long *src_y = pl + (lwpr*y);
901 u_long *dest_y = pl + (lwpr*(y+dy));
902 u_long count = lwpr*(height-dy);
903 u_long *clr_y = src_y;
904 u_long clr_count = dest_y - src_y;
905 u_long bc, cbc;
906
907 src_y += count - 1;
908 dest_y += count - 1;
909
910 bc = count >> 4;
911 count &= 0xf;
912
913 while (bc--) {
914 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
915 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
916 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
917 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
918 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
919 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
920 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
921 *dest_y-- = *src_y--; *dest_y-- = *src_y--;
922 }
923 while (count--) {
924 *dest_y-- = *src_y--;
925 }
926
927 cbc = clr_count >> 4;
928 clr_count &= 0xf;
929
930 while (cbc--) {
931 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
932 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
933 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
934 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
935 }
936 while (clr_count--) {
937 *clr_y++ = 0;
938 }
939 }
940 }
941 } else if (dy < 0) {
942 int i;
943 for (i=0; i < depth && mask; i++, mask >>= 1) {
944 if (0x1 & mask) {
945 u_long *pl = (u_long *)bm->plane[i];
946 u_long *src_y = pl + (lwpr*(y-dy));
947 u_long *dest_y = pl + (lwpr*y);
948 long count = lwpr*(height + dy);
949 u_long *clr_y = dest_y + count;
950 u_long clr_count = src_y - dest_y;
951 u_long bc, cbc;
952
953 bc = count >> 4;
954 count &= 0xf;
955
956 while (bc--) {
957 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
958 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
959 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
960 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
961 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
962 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
963 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
964 *dest_y++ = *src_y++; *dest_y++ = *src_y++;
965 }
966 while (count--) {
967 *dest_y++ = *src_y++;
968 }
969
970 cbc = clr_count >> 4;
971 clr_count &= 0xf;
972
973 while (cbc--) {
974 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
975 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
976 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
977 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
978 }
979 while (clr_count--) {
980 *clr_y++ = 0;
981 }
982 }
983 }
984 }
985 }
986
987 #endif /* NGRFCC */
988