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