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