xref: /netbsd-src/sys/arch/luna68k/stand/boot/bmd.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: bmd.c,v 1.7 2015/02/14 06:31:31 tsutsui 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 
83 /*
84  *  RFCNT register
85  */
86 
87 union bmd_rfcnt {
88 	struct {
89 		int16_t	rfc_hcnt;
90 		int16_t	rfc_vcnt;
91 	} p;
92 	uint32_t u;
93 };
94 
95 #define isprint(c)	((c) >= 0x20 && (c) < 0x7f)
96 
97 /*
98  *  Width & Height
99  */
100 
101 #define PB_WIDTH	2048			/* Plane Width   (Bit) */
102 #define PB_HEIGHT	1024			/* Plane Hight   (Bit) */
103 #define PL_WIDTH	64			/* Plane Width  (long) */
104 #define PS_WIDTH	128			/* Plane Width  (long) */
105 #define P_WIDTH		256			/* Plane Width  (Byte) */
106 
107 #define SB_WIDTH	1280			/* Screen Width  (Bit) */
108 #define SB_HEIGHT	1024			/* Screen Hight  (Bit) */
109 #define SL_WIDTH	40			/* Screen Width (Long) */
110 #define S_WIDTH		160			/* Screen Width (Byte) */
111 
112 #define FB_WIDTH	12			/* Font Width    (Bit) */
113 #define FB_HEIGHT	20			/* Font Hight    (Bit) */
114 
115 
116 #define NEXT_LINE(addr)			(addr +  (PL_WIDTH * FB_HEIGHT))
117 #define SKIP_NEXT_LINE(addr)		(addr += (PL_WIDTH - SL_WIDTH))
118 
119 
120 static void	bmd_draw_char(uint8_t *, uint8_t *, int, int, int);
121 static void	bmd_reverse_char(uint8_t *, uint8_t *, int, int);
122 static void	bmd_erase_char(uint8_t *, uint8_t *, int, int);
123 static void	bmd_erase_screen(volatile uint32_t *);
124 static void	bmd_scroll_screen(volatile uint32_t *, volatile uint32_t *,
125 		    int, int, int, int);
126 
127 
128 struct bmd_linec {
129 	struct bmd_linec *bl_next;
130 	struct bmd_linec *bl_prev;
131 	int	bl_col;
132 	int	bl_end;
133 	uint8_t	bl_line[128];
134 };
135 
136 struct bmd_softc {
137 	int	bc_stat;
138 	uint8_t *bc_raddr;
139 	uint8_t *bc_waddr;
140 	int	bc_xmin;
141 	int	bc_xmax;
142 	int	bc_ymin;
143 	int	bc_ymax;
144 	int	bc_col;
145 	int	bc_row;
146 	struct bmd_linec *bc_bl;
147 	char	bc_escseq[8];
148 	char   *bc_esc;
149 	void  (*bc_escape)(int);
150 };
151 
152 #define STAT_NORMAL	0x0000
153 #define STAT_ESCAPE	0x0001
154 #define STAT_INSERT	0x0100
155 
156 static struct	bmd_softc bmd_softc;
157 static struct	bmd_linec bmd_linec[52];
158 
159 static void	bmd_escape(int);
160 static void	bmd_escape_0(int);
161 #if 0
162 static void	bmd_escape_1(int);
163 #endif
164 
165 
166 /*
167  * Escape-Sequence
168  */
169 
170 static void
171 bmd_escape(int c)
172 {
173 	struct bmd_softc *bp = &bmd_softc;
174 
175 	switch (c) {
176 
177 	case '[':
178 		bp->bc_escape = bmd_escape_0;
179 		break;
180 
181 	default:
182 		bp->bc_stat &= ~STAT_ESCAPE;
183 		bp->bc_esc = &bp->bc_escseq[0];
184 		bp->bc_escape = bmd_escape;
185 		break;
186 	}
187 }
188 
189 static void
190 bmd_escape_0(int c)
191 {
192 	struct bmd_softc *bp = &bmd_softc;
193 	struct bmd_linec *bq = bp->bc_bl;
194 
195 	switch (c) {
196 
197 	case 'A':
198 		if (bp->bc_row > bp->bc_ymin) {
199 			bp->bc_row--;
200 		}
201 		break;
202 
203 	case 'C':
204 		if (bq->bl_col < bp->bc_xmax - 1) {
205 			bq->bl_col++;
206 		}
207 		break;
208 
209 	case 'K':
210 		if (bq->bl_col < bp->bc_xmax) {
211 			int col;
212 			for (col = bq->bl_col; col < bp->bc_xmax; col++)
213 				bmd_erase_char(bp->bc_raddr,
214 					       bp->bc_waddr,
215 					       col, bp->bc_row);
216 		}
217 		bq->bl_end = bq->bl_col;
218 		break;
219 
220 	case 'H':
221 		bq->bl_col = bq->bl_end = bp->bc_xmin;
222 		bp->bc_row = bp->bc_ymin;
223 		break;
224 
225 	default:
226 #if 0
227 		*bp->bc_esc++ = c;
228 		bp->bc_escape = bmd_escape_1;
229 		return;
230 #endif
231 		break;
232 	}
233 
234 	bp->bc_stat &= ~STAT_ESCAPE;
235 	bp->bc_esc = &bp->bc_escseq[0];
236 	bp->bc_escape = bmd_escape;
237 }
238 
239 #if 0
240 static void
241 bmd_escape_1(int c)
242 {
243 	struct bmd_softc *bp = &bmd_softc;
244 	struct bmd_linec *bq = bp->bc_bl;
245 	int col = 0, row = 0;
246 	char *p;
247 
248 	switch (c) {
249 
250 	case 'J':
251 		bp->bc_stat &= ~STAT_ESCAPE;
252 		bp->bc_esc = &bp->bc_escseq[0];
253 		bp->bc_escape = bmd_escape;
254 		break;
255 
256 	case 'H':
257 		for (p = &bp->bc_escseq[0]; *p != ';'; p++)
258 			row = (row * 10) + (*p - 0x30);
259 		p++;
260 		for (p = &bp->bc_escseq[0]; p != bp->bc_esc; p++)
261 			col = (col * 10) + (*p - 0x30);
262 
263 		bq->bl_col = col + bp->bc_xmin;
264 		bp->bc_row = row + bp->bc_ymin;
265 
266 		bp->bc_stat &= ~STAT_ESCAPE;
267 		bp->bc_esc = &bp->bc_escseq[0];
268 		bp->bc_escape = bmd_escape;
269 		break;
270 
271 	default:
272 		*bp->bc_esc++ = c;
273 		break;
274 	}
275 }
276 #endif
277 
278 /*
279  * Entry Routine
280  */
281 
282 void
283 bmdinit(void)
284 {
285 	volatile uint32_t *bmd_rfcnt = (uint32_t *)0xB1000000;
286 	volatile uint32_t *bmd_bmsel = (uint32_t *)0xB1040000;
287 	struct bmd_softc *bp = &bmd_softc;
288 	struct bmd_linec *bq;
289 	int i;
290 	union bmd_rfcnt rfcnt;
291 
292 	/*
293 	 *  adjust plane position
294 	 */
295 
296 	/* plane-0 hardware address */
297 	bp->bc_raddr = (uint8_t *)0xB10C0008;
298 	/* common bitmap hardware address */
299 	bp->bc_waddr = (uint8_t *)0xB1080008;
300 
301 	rfcnt.p.rfc_hcnt = 7;			/* shift left   16 dot */
302 	rfcnt.p.rfc_vcnt = -27;			/* shift down    1 dot */
303 	*bmd_rfcnt = rfcnt.u;
304 
305 	bp->bc_stat  = STAT_NORMAL;
306 
307 	bp->bc_xmin  = 8;
308 	bp->bc_xmax  = 96;
309 	bp->bc_ymin  = 2;
310 	bp->bc_ymax  = 48;
311 
312 	bp->bc_row = bp->bc_ymin;
313 
314 	for (i = bp->bc_ymin; i < bp->bc_ymax; i++) {
315 		bmd_linec[i].bl_next = &bmd_linec[i + 1];
316 		bmd_linec[i].bl_prev = &bmd_linec[i - 1];
317 	}
318 	bmd_linec[bp->bc_ymax - 1].bl_next = &bmd_linec[bp->bc_ymin];
319 	bmd_linec[bp->bc_ymin].bl_prev = &bmd_linec[bp->bc_ymax - 1];
320 
321 	bq = bp->bc_bl = &bmd_linec[bp->bc_ymin];
322 	bq->bl_col = bq->bl_end = bp->bc_xmin;
323 
324 	bp->bc_col = bp->bc_xmin;
325 
326 	bp->bc_esc = &bp->bc_escseq[0];
327 	bp->bc_escape = bmd_escape;
328 
329 	*bmd_bmsel = 0xff;				/* all planes */
330 	bmd_erase_screen((uint32_t *)bp->bc_waddr);	/* clear screen */
331 	*bmd_bmsel = 0x01;				/* 1 plane */
332 
333 	/* turn on cursor */
334 	bmd_reverse_char(bp->bc_raddr,
335 			 bp->bc_waddr,
336 			 bq->bl_col, bp->bc_row);
337 }
338 
339 void
340 bmdadjust(int16_t hcnt, int16_t vcnt)
341 {
342 	volatile uint32_t *bmd_rfcnt = (uint32_t *)0xB1000000;
343 	union bmd_rfcnt rfcnt;
344 
345 	printf("bmdadjust: hcnt = %d, vcnt = %d\n", hcnt, vcnt);
346 
347 	rfcnt.p.rfc_hcnt = hcnt;		/* shift left   16 dot */
348 	rfcnt.p.rfc_vcnt = vcnt;		/* shift down    1 dot */
349 
350 	*bmd_rfcnt = rfcnt.u;
351 }
352 
353 int
354 bmdputc(int c)
355 {
356 	struct bmd_softc *bp = &bmd_softc;
357 	struct bmd_linec *bq = bp->bc_bl;
358 	int i;
359 
360 	c &= 0x7F;
361 
362 	/* turn off cursor */
363 	bmd_reverse_char(bp->bc_raddr,
364 			 bp->bc_waddr,
365 			 bq->bl_col, bp->bc_row);
366 
367 	/* do escape-sequence */
368 	if (bp->bc_stat & STAT_ESCAPE) {
369 		*bp->bc_esc++ = c;
370 		(*bp->bc_escape)(c);
371 		goto done;
372 	}
373 
374 	if (isprint(c)) {
375 		bmd_draw_char(bp->bc_raddr, bp->bc_waddr,
376 			      bq->bl_col, bp->bc_row, c);
377 		bq->bl_col++;
378 		bq->bl_end++;
379 		if (bq->bl_col >= bp->bc_xmax) {
380 			bq->bl_col = bq->bl_end = bp->bc_xmin;
381 			bp->bc_row++;
382 			if (bp->bc_row >= bp->bc_ymax) {
383 				bmd_scroll_screen((uint32_t *)bp->bc_raddr,
384 						  (uint32_t *)bp->bc_waddr,
385 						  bp->bc_xmin, bp->bc_xmax,
386 						  bp->bc_ymin, bp->bc_ymax);
387 
388 				bp->bc_row = bp->bc_ymax - 1;
389 			}
390 		}
391 	} else {
392 		switch (c) {
393 		case 0x08:				/* BS */
394 			if (bq->bl_col > bp->bc_xmin) {
395 				bq->bl_col--;
396 			}
397 			break;
398 
399 		case 0x09:				/* HT */
400 		case 0x0B:				/* VT */
401 			i = ((bq->bl_col / 8) + 1) * 8;
402 			if (i < bp->bc_xmax) {
403 				bq->bl_col = bq->bl_end = i;
404 			}
405 			break;
406 
407 		case 0x0A:				/* NL */
408 			bp->bc_row++;
409 			if (bp->bc_row >= bp->bc_ymax) {
410 				bmd_scroll_screen((uint32_t *)bp->bc_raddr,
411 						  (uint32_t *)bp->bc_waddr,
412 						  bp->bc_xmin, bp->bc_xmax,
413 						  bp->bc_ymin, bp->bc_ymax);
414 
415 				bp->bc_row = bp->bc_ymax - 1;
416 			}
417 			break;
418 
419 		case 0x0D:				/* CR */
420 			bq->bl_col = bp->bc_xmin;
421 			break;
422 
423 		case 0x1B:				/* ESC */
424 			bp->bc_stat |= STAT_ESCAPE;
425 			*bp->bc_esc++ = 0x1b;
426 			break;
427 
428 		case 0x7F:				/* DEL */
429 			if (bq->bl_col > bp->bc_xmin) {
430 				bq->bl_col--;
431 				bmd_erase_char(bp->bc_raddr,
432 					       bp->bc_waddr,
433 					       bq->bl_col, bp->bc_row);
434 			}
435 			break;
436 
437 		default:
438 			break;
439 		}
440 	}
441 
442  done:
443 	/* turn on  cursor */
444 	bmd_reverse_char(bp->bc_raddr,
445 			 bp->bc_waddr,
446 			 bq->bl_col, bp->bc_row);
447 
448 	return c;
449 }
450 
451 void
452 bmdclear(void)
453 {
454 	struct bmd_softc *bp = &bmd_softc;
455 	struct bmd_linec *bq = bp->bc_bl;
456 
457 	/* clear screen */
458 	bmd_erase_screen((uint32_t *)bp->bc_waddr);
459 
460 	bq->bl_col = bq->bl_end = bp->bc_xmin;
461 	bp->bc_row = bp->bc_ymin;
462 
463 	/* turn on cursor */
464 	bmd_reverse_char(bp->bc_raddr,
465 			 bp->bc_waddr,
466 			 bq->bl_col, bp->bc_row);
467 }
468 
469 
470 /*
471  *  charactor operation routines
472  */
473 
474 static void
475 bmd_draw_char(uint8_t *raddr, uint8_t *waddr, int col, int row, int c)
476 {
477 	volatile uint16_t *p, *q;
478 	volatile uint32_t *lp, *lq;
479 	const uint16_t *fp;
480 	int i;
481 
482 	fp = &bmdfont[c][0];
483 
484 	switch (col % 4) {
485 
486 	case 0:
487 		p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
488 		    + ((col / 4) * 6));
489 		q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
490 		    + ((col / 4) * 6));
491 		for (i = 0; i < FB_HEIGHT; i++) {
492 			*q = (*p & 0x000F) | (*fp & 0xFFF0);
493 			p += 128;
494 			q += 128;
495 			fp++;
496 		}
497 		break;
498 
499 	case 1:
500 		lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
501 		    + ((col / 4) * 6));
502 		lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
503 		    + ((col / 4) * 6));
504 		for (i = 0; i < FB_HEIGHT; i++) {
505 			*lq = (*lp & 0xFFF000FF) |
506 			    ((uint32_t)(*fp & 0xFFF0) << 4);
507 			lp += 64;
508 			lq += 64;
509 			fp++;
510 		}
511 		break;
512 
513 	case 2:
514 		lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
515 		    + ((col / 4) * 6) + 2);
516 		lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
517 		    + ((col / 4) * 6) + 2);
518 		for (i = 0; i < FB_HEIGHT; i++) {
519 			*lq = (*lp & 0xFF000FFF) |
520 			    ((uint32_t)(*fp & 0xFFF0) << 8);
521 			lp += 64;
522 			lq += 64;
523 			fp++;
524 		}
525 		break;
526 
527 	case 3:
528 		p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
529 		    + ((col / 4) * 6) + 4);
530 		q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
531 		    + ((col / 4) * 6) + 4);
532 		for (i = 0; i < FB_HEIGHT; i++) {
533 			*q = (*p & 0xF000) | ((*fp & 0xFFF0) >> 4);
534 			p += 128;
535 			q += 128;
536 			fp++;
537 		}
538 		break;
539 
540 	default:
541 		break;
542 	}
543 }
544 
545 static void
546 bmd_reverse_char(uint8_t *raddr, uint8_t *waddr, int col, int row)
547 {
548 	volatile uint16_t *p, *q;
549 	volatile uint32_t *lp, *lq;
550 	int i;
551 
552 	switch (col % 4) {
553 
554 	case 0:
555 		p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
556 		    + ((col / 4) * 6));
557 		q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
558 		    + ((col / 4) * 6));
559 		for (i = 0; i < FB_HEIGHT; i++) {
560 			*q = (*p & 0x000F) | (~(*p) & 0xFFF0);
561 			p += 128;
562 			q += 128;
563 		}
564 		break;
565 
566 	case 1:
567 		lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
568 		    + ((col / 4) * 6));
569 		lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
570 		    + ((col / 4) * 6));
571 		for (i = 0; i < FB_HEIGHT; i++) {
572 			*lq = (*lp & 0xFFF000FF) | (~(*lp) & 0x000FFF00);
573 			lp += 64;
574 			lq += 64;
575 		}
576 		break;
577 
578 	case 2:
579 		lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
580 		    + ((col / 4) * 6) + 2);
581 		lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
582 		    + ((col / 4) * 6) + 2);
583 		for (i = 0; i < FB_HEIGHT; i++) {
584 			*lq = (*lp & 0xFF000FFF) | (~(*lp) & 0x00FFF000);
585 			lp += 64;
586 			lq += 64;
587 		}
588 		break;
589 
590 	case 3:
591 		p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
592 		    + ((col / 4) * 6) + 4);
593 		q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
594 		    + ((col / 4) * 6) + 4);
595 		for (i = 0; i < FB_HEIGHT; i++) {
596 			*q = (*p & 0xF000) | (~(*p) & 0x0FFF);
597 			p += 128;
598 			q += 128;
599 		}
600 		break;
601 
602 	default:
603 		break;
604 	}
605 }
606 
607 static void
608 bmd_erase_char(uint8_t *raddr, uint8_t *waddr, int col, int row)
609 {
610 
611 	bmd_draw_char(raddr, waddr, col, row, 0);
612 }
613 
614 
615 /*
616  * screen operation routines
617  */
618 
619 static void
620 bmd_erase_screen(volatile uint32_t *lp)
621 {
622 	int i, j;
623 
624 	for (i = 0; i < SB_HEIGHT; i++) {
625 		for (j = 0; j < SL_WIDTH; j++)
626 			*lp++ = 0;
627 		SKIP_NEXT_LINE(lp);
628 	}
629 }
630 
631 static void
632 bmd_scroll_screen(volatile uint32_t *lp, volatile uint32_t *lq,
633     int xmin, int xmax, int ymin, int ymax)
634 {
635 	int i, j;
636 
637 	lp += ((PL_WIDTH * FB_HEIGHT) * (ymin + 1));
638 	lq += ((PL_WIDTH * FB_HEIGHT) *  ymin);
639 
640 	for (i = 0; i < ((ymax - ymin -1) * FB_HEIGHT); i++) {
641 		for (j = 0; j < SL_WIDTH; j++) {
642 			*lq++ = *lp++;
643 		}
644 		lp += (PL_WIDTH - SL_WIDTH);
645 		lq += (PL_WIDTH - SL_WIDTH);
646 	}
647 
648 	for (i = 0; i < FB_HEIGHT; i++) {
649 		for (j = 0; j < SL_WIDTH; j++) {
650 			*lq++ = 0;
651 		}
652 		lq += (PL_WIDTH - SL_WIDTH);
653 	}
654 }
655