1 /*        $NetBSD: bmd.c,v 1.10 2024/07/05 19:28:36 andvar Exp $      */
2 
3 /*
4  * Copyright (c) 1992 OMRON Corporation.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * OMRON Corporation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *        This product includes software developed by the University of
20  *        California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *        @(#)bmd.c 8.2 (Berkeley) 8/15/93
38  */
39 /*
40  * Copyright (c) 1992, 1993
41  *        The Regents of the University of California.  All rights reserved.
42  *
43  * This code is derived from software contributed to Berkeley by
44  * OMRON Corporation.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. Neither the name of the University nor the names of its contributors
55  *    may be used to endorse or promote products derived from this software
56  *    without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68  * SUCH DAMAGE.
69  *
70  *        @(#)bmd.c 8.2 (Berkeley) 8/15/93
71  */
72 /*
73 
74  * bmd.c --- Bitmap-Display raw-level driver routines
75  *
76  *        by A.Fujita, SEP-09-1992
77  */
78 
79 
80 #include <sys/param.h>
81 #include <luna68k/stand/boot/samachdep.h>
82 #include <machine/board.h>
83 
84 /*
85  *  RFCNT register
86  */
87 
88 union bmd_rfcnt {
89           struct {
90                     int16_t   rfc_hcnt;
91                     int16_t   rfc_vcnt;
92           } p;
93           uint32_t u;
94 };
95 
96 #define isprint(c)  ((c) >= 0x20 && (c) < 0x7f)
97 
98 /*
99  *  Width & Height
100  */
101 
102 #define BMAP_OFFSET 8
103 
104 #define PB_WIDTH    2048                          /* Plane Width   (Bit) */
105 #define PB_HEIGHT   1024                          /* Plane Height  (Bit) */
106 #define PL_WIDTH    64                            /* Plane Width  (long) */
107 #define PS_WIDTH    128                           /* Plane Width  (long) */
108 #define P_WIDTH               256                           /* Plane Width  (Byte) */
109 
110 #define SB_WIDTH    1280                          /* Screen Width  (Bit) */
111 #define SB_HEIGHT   1024                          /* Screen Height (Bit) */
112 #define SL_WIDTH    40                            /* Screen Width (Long) */
113 #define S_WIDTH               160                           /* Screen Width (Byte) */
114 
115 #define FB_WIDTH    12                            /* Font Width    (Bit) */
116 #define FB_HEIGHT   20                            /* Font Height   (Bit) */
117 
118 
119 #define NEXT_LINE(addr)                           (addr +  (PL_WIDTH * FB_HEIGHT))
120 #define SKIP_NEXT_LINE(addr)            (addr += (PL_WIDTH - SL_WIDTH))
121 
122 
123 static void         bmd_draw_char(uint8_t *, uint8_t *, int, int, int);
124 static void         bmd_reverse_char(uint8_t *, uint8_t *, int, int);
125 static void         bmd_erase_char(uint8_t *, uint8_t *, int, int);
126 static void         bmd_erase_screen(volatile uint32_t *);
127 static void         bmd_scroll_screen(volatile uint32_t *, volatile uint32_t *,
128                         int, int, int, int);
129 
130 
131 struct bmd_linec {
132           struct bmd_linec *bl_next;
133           struct bmd_linec *bl_prev;
134           int       bl_col;
135           int       bl_end;
136           uint8_t   bl_line[128];
137 };
138 
139 struct bmd_softc {
140           int       bc_stat;
141           uint8_t *bc_raddr;
142           uint8_t *bc_waddr;
143           int       bc_xmin;
144           int       bc_xmax;
145           int       bc_ymin;
146           int       bc_ymax;
147           int       bc_col;
148           int       bc_row;
149           struct bmd_linec *bc_bl;
150           char      bc_escseq[8];
151           char   *bc_esc;
152           void  (*bc_escape)(int);
153 };
154 
155 #define STAT_NORMAL 0x0000
156 #define STAT_ESCAPE 0x0001
157 #define STAT_INSERT 0x0100
158 
159 static struct       bmd_softc bmd_softc;
160 static struct       bmd_linec bmd_linec[52];
161 
162 static void         bmd_escape(int);
163 static void         bmd_escape_0(int);
164 #if 0
165 static void         bmd_escape_1(int);
166 #endif
167 
168 
169 /*
170  * Escape-Sequence
171  */
172 
173 static void
bmd_escape(int c)174 bmd_escape(int c)
175 {
176           struct bmd_softc *bp = &bmd_softc;
177 
178           switch (c) {
179 
180           case '[':
181                     bp->bc_escape = bmd_escape_0;
182                     break;
183 
184           default:
185                     bp->bc_stat &= ~STAT_ESCAPE;
186                     bp->bc_esc = &bp->bc_escseq[0];
187                     bp->bc_escape = bmd_escape;
188                     break;
189           }
190 }
191 
192 static void
bmd_escape_0(int c)193 bmd_escape_0(int c)
194 {
195           struct bmd_softc *bp = &bmd_softc;
196           struct bmd_linec *bq = bp->bc_bl;
197 
198           switch (c) {
199 
200           case 'A':
201                     if (bp->bc_row > bp->bc_ymin) {
202                               bp->bc_row--;
203                     }
204                     break;
205 
206           case 'C':
207                     if (bq->bl_col < bp->bc_xmax - 1) {
208                               bq->bl_col++;
209                     }
210                     break;
211 
212           case 'K':
213                     if (bq->bl_col < bp->bc_xmax) {
214                               int col;
215                               for (col = bq->bl_col; col < bp->bc_xmax; col++)
216                                         bmd_erase_char(bp->bc_raddr,
217                                                          bp->bc_waddr,
218                                                          col, bp->bc_row);
219                     }
220                     bq->bl_end = bq->bl_col;
221                     break;
222 
223           case 'H':
224                     bq->bl_col = bq->bl_end = bp->bc_xmin;
225                     bp->bc_row = bp->bc_ymin;
226                     break;
227 
228           default:
229 #if 0
230                     *bp->bc_esc++ = c;
231                     bp->bc_escape = bmd_escape_1;
232                     return;
233 #endif
234                     break;
235           }
236 
237           bp->bc_stat &= ~STAT_ESCAPE;
238           bp->bc_esc = &bp->bc_escseq[0];
239           bp->bc_escape = bmd_escape;
240 }
241 
242 #if 0
243 static void
244 bmd_escape_1(int c)
245 {
246           struct bmd_softc *bp = &bmd_softc;
247           struct bmd_linec *bq = bp->bc_bl;
248           int col = 0, row = 0;
249           char *p;
250 
251           switch (c) {
252 
253           case 'J':
254                     bp->bc_stat &= ~STAT_ESCAPE;
255                     bp->bc_esc = &bp->bc_escseq[0];
256                     bp->bc_escape = bmd_escape;
257                     break;
258 
259           case 'H':
260                     for (p = &bp->bc_escseq[0]; *p != ';'; p++)
261                               row = (row * 10) + (*p - 0x30);
262                     p++;
263                     for (p = &bp->bc_escseq[0]; p != bp->bc_esc; p++)
264                               col = (col * 10) + (*p - 0x30);
265 
266                     bq->bl_col = col + bp->bc_xmin;
267                     bp->bc_row = row + bp->bc_ymin;
268 
269                     bp->bc_stat &= ~STAT_ESCAPE;
270                     bp->bc_esc = &bp->bc_escseq[0];
271                     bp->bc_escape = bmd_escape;
272                     break;
273 
274           default:
275                     *bp->bc_esc++ = c;
276                     break;
277           }
278 }
279 #endif
280 
281 /*
282  * Entry Routine
283  */
284 
285 void
bmdinit(void)286 bmdinit(void)
287 {
288           volatile uint32_t *bmd_rfcnt = (uint32_t *)BMAP_RFCNT;
289           volatile uint32_t *bmd_bmsel = (uint32_t *)BMAP_BMSEL;
290           struct bmd_softc *bp = &bmd_softc;
291           struct bmd_linec *bq;
292           int i;
293           union bmd_rfcnt rfcnt;
294 
295           /*
296            *  adjust plane position
297            */
298 
299           /* plane-0 hardware address */
300           bp->bc_raddr = (uint8_t *)(BMAP_BMAP0 + BMAP_OFFSET);
301           /* common bitmap hardware address */
302           bp->bc_waddr = (uint8_t *)(BMAP_BMP   + BMAP_OFFSET);
303 
304           rfcnt.p.rfc_hcnt = 7;                             /* shift left   16 dot */
305           rfcnt.p.rfc_vcnt = -27;                           /* shift down    1 dot */
306           *bmd_rfcnt = rfcnt.u;
307 
308           bp->bc_stat  = STAT_NORMAL;
309 
310           bp->bc_xmin  = 8;
311           bp->bc_xmax  = 96;
312           bp->bc_ymin  = 2;
313           bp->bc_ymax  = 48;
314 
315           bp->bc_row = bp->bc_ymin;
316 
317           for (i = bp->bc_ymin; i < bp->bc_ymax; i++) {
318                     bmd_linec[i].bl_next = &bmd_linec[i + 1];
319                     bmd_linec[i].bl_prev = &bmd_linec[i - 1];
320           }
321           bmd_linec[bp->bc_ymax - 1].bl_next = &bmd_linec[bp->bc_ymin];
322           bmd_linec[bp->bc_ymin].bl_prev = &bmd_linec[bp->bc_ymax - 1];
323 
324           bq = bp->bc_bl = &bmd_linec[bp->bc_ymin];
325           bq->bl_col = bq->bl_end = bp->bc_xmin;
326 
327           bp->bc_col = bp->bc_xmin;
328 
329           bp->bc_esc = &bp->bc_escseq[0];
330           bp->bc_escape = bmd_escape;
331 
332           *bmd_bmsel = 0xff;                                /* all planes */
333           bmd_erase_screen((uint32_t *)bp->bc_waddr);       /* clear screen */
334           *bmd_bmsel = 0x01;                                /* 1 plane */
335 
336           /* turn on cursor */
337           bmd_reverse_char(bp->bc_raddr,
338                                bp->bc_waddr,
339                                bq->bl_col, bp->bc_row);
340 }
341 
342 void
bmdadjust(int16_t hcnt,int16_t vcnt)343 bmdadjust(int16_t hcnt, int16_t vcnt)
344 {
345           volatile uint32_t *bmd_rfcnt = (uint32_t *)BMAP_RFCNT;
346           union bmd_rfcnt rfcnt;
347 
348           printf("bmdadjust: hcnt = %d, vcnt = %d\n", hcnt, vcnt);
349 
350           rfcnt.p.rfc_hcnt = hcnt;                /* shift left   16 dot */
351           rfcnt.p.rfc_vcnt = vcnt;                /* shift down    1 dot */
352 
353           *bmd_rfcnt = rfcnt.u;
354 }
355 
356 int
bmdputc(int c)357 bmdputc(int c)
358 {
359           struct bmd_softc *bp = &bmd_softc;
360           struct bmd_linec *bq = bp->bc_bl;
361           int i;
362 
363           c &= 0x7F;
364 
365           /* turn off cursor */
366           bmd_reverse_char(bp->bc_raddr,
367                                bp->bc_waddr,
368                                bq->bl_col, bp->bc_row);
369 
370           /* do escape-sequence */
371           if (bp->bc_stat & STAT_ESCAPE) {
372                     *bp->bc_esc++ = c;
373                     (*bp->bc_escape)(c);
374                     goto done;
375           }
376 
377           if (isprint(c)) {
378                     bmd_draw_char(bp->bc_raddr, bp->bc_waddr,
379                                     bq->bl_col, bp->bc_row, c);
380                     bq->bl_col++;
381                     bq->bl_end++;
382                     if (bq->bl_col >= bp->bc_xmax) {
383                               bq->bl_col = bq->bl_end = bp->bc_xmin;
384                               bp->bc_row++;
385                               if (bp->bc_row >= bp->bc_ymax) {
386                                         bmd_scroll_screen((uint32_t *)bp->bc_raddr,
387                                                               (uint32_t *)bp->bc_waddr,
388                                                               bp->bc_xmin, bp->bc_xmax,
389                                                               bp->bc_ymin, bp->bc_ymax);
390 
391                                         bp->bc_row = bp->bc_ymax - 1;
392                               }
393                     }
394           } else {
395                     switch (c) {
396                     case 0x08:                                        /* BS */
397                               if (bq->bl_col > bp->bc_xmin) {
398                                         bq->bl_col--;
399                               }
400                               break;
401 
402                     case 0x09:                                        /* HT */
403                     case 0x0B:                                        /* VT */
404                               i = ((bq->bl_col / 8) + 1) * 8;
405                               if (i < bp->bc_xmax) {
406                                         bq->bl_col = bq->bl_end = i;
407                               }
408                               break;
409 
410                     case 0x0A:                                        /* NL */
411                               bp->bc_row++;
412                               if (bp->bc_row >= bp->bc_ymax) {
413                                         bmd_scroll_screen((uint32_t *)bp->bc_raddr,
414                                                               (uint32_t *)bp->bc_waddr,
415                                                               bp->bc_xmin, bp->bc_xmax,
416                                                               bp->bc_ymin, bp->bc_ymax);
417 
418                                         bp->bc_row = bp->bc_ymax - 1;
419                               }
420                               break;
421 
422                     case 0x0D:                                        /* CR */
423                               bq->bl_col = bp->bc_xmin;
424                               break;
425 
426                     case 0x1B:                                        /* ESC */
427                               bp->bc_stat |= STAT_ESCAPE;
428                               *bp->bc_esc++ = 0x1b;
429                               break;
430 
431                     case 0x7F:                                        /* DEL */
432                               if (bq->bl_col > bp->bc_xmin) {
433                                         bq->bl_col--;
434                                         bmd_erase_char(bp->bc_raddr,
435                                                          bp->bc_waddr,
436                                                          bq->bl_col, bp->bc_row);
437                               }
438                               break;
439 
440                     default:
441                               break;
442                     }
443           }
444 
445  done:
446           /* turn on  cursor */
447           bmd_reverse_char(bp->bc_raddr,
448                                bp->bc_waddr,
449                                bq->bl_col, bp->bc_row);
450 
451           return c;
452 }
453 
454 void
bmdclear(void)455 bmdclear(void)
456 {
457           struct bmd_softc *bp = &bmd_softc;
458           struct bmd_linec *bq = bp->bc_bl;
459 
460           /* clear screen */
461           bmd_erase_screen((uint32_t *)bp->bc_waddr);
462 
463           bq->bl_col = bq->bl_end = bp->bc_xmin;
464           bp->bc_row = bp->bc_ymin;
465 
466           /* turn on cursor */
467           bmd_reverse_char(bp->bc_raddr,
468                                bp->bc_waddr,
469                                bq->bl_col, bp->bc_row);
470 }
471 
472 
473 /*
474  *  character operation routines
475  */
476 
477 static void
bmd_draw_char(uint8_t * raddr,uint8_t * waddr,int col,int row,int c)478 bmd_draw_char(uint8_t *raddr, uint8_t *waddr, int col, int row, int c)
479 {
480           volatile uint16_t *p, *q;
481           volatile uint32_t *lp, *lq;
482           const uint16_t *fp;
483           int i;
484 
485           fp = &bmdfont[c][0];
486 
487           switch (col % 4) {
488 
489           case 0:
490                     p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
491                         + ((col / 4) * 6));
492                     q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
493                         + ((col / 4) * 6));
494                     for (i = 0; i < FB_HEIGHT; i++) {
495                               *q = (*p & 0x000F) | (*fp & 0xFFF0);
496                               p += 128;
497                               q += 128;
498                               fp++;
499                     }
500                     break;
501 
502           case 1:
503                     lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
504                         + ((col / 4) * 6));
505                     lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
506                         + ((col / 4) * 6));
507                     for (i = 0; i < FB_HEIGHT; i++) {
508                               *lq = (*lp & 0xFFF000FF) |
509                                   ((uint32_t)(*fp & 0xFFF0) << 4);
510                               lp += 64;
511                               lq += 64;
512                               fp++;
513                     }
514                     break;
515 
516           case 2:
517                     lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
518                         + ((col / 4) * 6) + 2);
519                     lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
520                         + ((col / 4) * 6) + 2);
521                     for (i = 0; i < FB_HEIGHT; i++) {
522                               *lq = (*lp & 0xFF000FFF) |
523                                   ((uint32_t)(*fp & 0xFFF0) << 8);
524                               lp += 64;
525                               lq += 64;
526                               fp++;
527                     }
528                     break;
529 
530           case 3:
531                     p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
532                         + ((col / 4) * 6) + 4);
533                     q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
534                         + ((col / 4) * 6) + 4);
535                     for (i = 0; i < FB_HEIGHT; i++) {
536                               *q = (*p & 0xF000) | ((*fp & 0xFFF0) >> 4);
537                               p += 128;
538                               q += 128;
539                               fp++;
540                     }
541                     break;
542 
543           default:
544                     break;
545           }
546 }
547 
548 static void
bmd_reverse_char(uint8_t * raddr,uint8_t * waddr,int col,int row)549 bmd_reverse_char(uint8_t *raddr, uint8_t *waddr, int col, int row)
550 {
551           volatile uint16_t *p, *q;
552           volatile uint32_t *lp, *lq;
553           int i;
554 
555           switch (col % 4) {
556 
557           case 0:
558                     p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
559                         + ((col / 4) * 6));
560                     q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
561                         + ((col / 4) * 6));
562                     for (i = 0; i < FB_HEIGHT; i++) {
563                               *q = (*p & 0x000F) | (~(*p) & 0xFFF0);
564                               p += 128;
565                               q += 128;
566                     }
567                     break;
568 
569           case 1:
570                     lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
571                         + ((col / 4) * 6));
572                     lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
573                         + ((col / 4) * 6));
574                     for (i = 0; i < FB_HEIGHT; i++) {
575                               *lq = (*lp & 0xFFF000FF) | (~(*lp) & 0x000FFF00);
576                               lp += 64;
577                               lq += 64;
578                     }
579                     break;
580 
581           case 2:
582                     lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
583                         + ((col / 4) * 6) + 2);
584                     lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
585                         + ((col / 4) * 6) + 2);
586                     for (i = 0; i < FB_HEIGHT; i++) {
587                               *lq = (*lp & 0xFF000FFF) | (~(*lp) & 0x00FFF000);
588                               lp += 64;
589                               lq += 64;
590                     }
591                     break;
592 
593           case 3:
594                     p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
595                         + ((col / 4) * 6) + 4);
596                     q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
597                         + ((col / 4) * 6) + 4);
598                     for (i = 0; i < FB_HEIGHT; i++) {
599                               *q = (*p & 0xF000) | (~(*p) & 0x0FFF);
600                               p += 128;
601                               q += 128;
602                     }
603                     break;
604 
605           default:
606                     break;
607           }
608 }
609 
610 static void
bmd_erase_char(uint8_t * raddr,uint8_t * waddr,int col,int row)611 bmd_erase_char(uint8_t *raddr, uint8_t *waddr, int col, int row)
612 {
613 
614           bmd_draw_char(raddr, waddr, col, row, 0);
615 }
616 
617 
618 /*
619  * screen operation routines
620  */
621 
622 static void
bmd_erase_screen(volatile uint32_t * lp)623 bmd_erase_screen(volatile uint32_t *lp)
624 {
625           int i, j;
626 
627           for (i = 0; i < SB_HEIGHT; i++) {
628                     for (j = 0; j < SL_WIDTH; j++)
629                               *lp++ = 0;
630                     SKIP_NEXT_LINE(lp);
631           }
632 }
633 
634 static void
bmd_scroll_screen(volatile uint32_t * lp,volatile uint32_t * lq,int xmin,int xmax,int ymin,int ymax)635 bmd_scroll_screen(volatile uint32_t *lp, volatile uint32_t *lq,
636     int xmin, int xmax, int ymin, int ymax)
637 {
638           int i, j;
639 
640           lp += ((PL_WIDTH * FB_HEIGHT) * (ymin + 1));
641           lq += ((PL_WIDTH * FB_HEIGHT) *  ymin);
642 
643           for (i = 0; i < ((ymax - ymin -1) * FB_HEIGHT); i++) {
644                     for (j = 0; j < SL_WIDTH; j++) {
645                               *lq++ = *lp++;
646                     }
647                     lp += (PL_WIDTH - SL_WIDTH);
648                     lq += (PL_WIDTH - SL_WIDTH);
649           }
650 
651           for (i = 0; i < FB_HEIGHT; i++) {
652                     for (j = 0; j < SL_WIDTH; j++) {
653                               *lq++ = 0;
654                     }
655                     lq += (PL_WIDTH - SL_WIDTH);
656           }
657 }
658