diff options
Diffstat (limited to 'drivers/video/sis/sis_accel.h')
-rw-r--r-- | drivers/video/sis/sis_accel.h | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/drivers/video/sis/sis_accel.h b/drivers/video/sis/sis_accel.h new file mode 100644 index 000000000000..bb28f331d60d --- /dev/null +++ b/drivers/video/sis/sis_accel.h | |||
@@ -0,0 +1,409 @@ | |||
1 | /* | ||
2 | * SiS 300/630/730/540/315/550/650/740 frame buffer driver | ||
3 | * for Linux kernels 2.4.x and 2.5.x | ||
4 | * | ||
5 | * 2D acceleration part | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the named License, | ||
10 | * or any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA | ||
20 | * | ||
21 | * Based on the X driver's sis300_accel.h which is | ||
22 | * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria | ||
23 | * and sis310_accel.h which is | ||
24 | * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria | ||
25 | * | ||
26 | * Author: Thomas Winischhofer <thomas@winischhofer.net>: | ||
27 | * (see http://www.winischhofer.net/ | ||
28 | * for more information and updates) | ||
29 | */ | ||
30 | |||
31 | #ifndef _SISFB_ACCEL_H | ||
32 | #define _SISFB_ACCEL_H | ||
33 | |||
34 | /* Guard accelerator accesses with spin_lock_irqsave? Works well without. */ | ||
35 | #undef SISFB_USE_SPINLOCKS | ||
36 | |||
37 | #ifdef SISFB_USE_SPINLOCKS | ||
38 | #include <linux/spinlock.h> | ||
39 | #define CRITBEGIN spin_lock_irqsave(&ivideo->lockaccel, critflags); | ||
40 | #define CRITEND spin_unlock_irqrestore(&ivideo->lockaccel, critflags); | ||
41 | #define CRITFLAGS unsigned long critflags; | ||
42 | #else | ||
43 | #define CRITBEGIN | ||
44 | #define CRITEND | ||
45 | #define CRITFLAGS | ||
46 | #endif | ||
47 | |||
48 | /* Definitions for the SIS engine communication. */ | ||
49 | |||
50 | #define PATREGSIZE 384 /* Pattern register size. 384 bytes @ 0x8300 */ | ||
51 | #define BR(x) (0x8200 | (x) << 2) | ||
52 | #define PBR(x) (0x8300 | (x) << 2) | ||
53 | |||
54 | /* SiS300 engine commands */ | ||
55 | #define BITBLT 0x00000000 /* Blit */ | ||
56 | #define COLOREXP 0x00000001 /* Color expand */ | ||
57 | #define ENCOLOREXP 0x00000002 /* Enhanced color expand */ | ||
58 | #define MULTIPLE_SCANLINE 0x00000003 /* ? */ | ||
59 | #define LINE 0x00000004 /* Draw line */ | ||
60 | #define TRAPAZOID_FILL 0x00000005 /* Fill trapezoid */ | ||
61 | #define TRANSPARENT_BITBLT 0x00000006 /* Transparent Blit */ | ||
62 | |||
63 | /* Additional engine commands for 315 */ | ||
64 | #define ALPHA_BLEND 0x00000007 /* Alpha blend ? */ | ||
65 | #define A3D_FUNCTION 0x00000008 /* 3D command ? */ | ||
66 | #define CLEAR_Z_BUFFER 0x00000009 /* ? */ | ||
67 | #define GRADIENT_FILL 0x0000000A /* Gradient fill */ | ||
68 | |||
69 | /* source select */ | ||
70 | #define SRCVIDEO 0x00000000 /* source is video RAM */ | ||
71 | #define SRCSYSTEM 0x00000010 /* source is system memory */ | ||
72 | #define SRCCPUBLITBUF SRCSYSTEM /* source is CPU-driven BitBuffer (for color expand) */ | ||
73 | #define SRCAGP 0x00000020 /* source is AGP memory (?) */ | ||
74 | |||
75 | /* Pattern flags */ | ||
76 | #define PATFG 0x00000000 /* foreground color */ | ||
77 | #define PATPATREG 0x00000040 /* pattern in pattern buffer (0x8300) */ | ||
78 | #define PATMONO 0x00000080 /* mono pattern */ | ||
79 | |||
80 | /* blitting direction (300 series only) */ | ||
81 | #define X_INC 0x00010000 | ||
82 | #define X_DEC 0x00000000 | ||
83 | #define Y_INC 0x00020000 | ||
84 | #define Y_DEC 0x00000000 | ||
85 | |||
86 | /* Clipping flags */ | ||
87 | #define NOCLIP 0x00000000 | ||
88 | #define NOMERGECLIP 0x04000000 | ||
89 | #define CLIPENABLE 0x00040000 | ||
90 | #define CLIPWITHOUTMERGE 0x04040000 | ||
91 | |||
92 | /* Transparency */ | ||
93 | #define OPAQUE 0x00000000 | ||
94 | #define TRANSPARENT 0x00100000 | ||
95 | |||
96 | /* ? */ | ||
97 | #define DSTAGP 0x02000000 | ||
98 | #define DSTVIDEO 0x02000000 | ||
99 | |||
100 | /* Subfunctions for Color/Enhanced Color Expansion (315 only) */ | ||
101 | #define COLOR_TO_MONO 0x00100000 | ||
102 | #define AA_TEXT 0x00200000 | ||
103 | |||
104 | /* Some general registers for 315 series */ | ||
105 | #define SRC_ADDR 0x8200 | ||
106 | #define SRC_PITCH 0x8204 | ||
107 | #define AGP_BASE 0x8206 /* color-depth dependent value */ | ||
108 | #define SRC_Y 0x8208 | ||
109 | #define SRC_X 0x820A | ||
110 | #define DST_Y 0x820C | ||
111 | #define DST_X 0x820E | ||
112 | #define DST_ADDR 0x8210 | ||
113 | #define DST_PITCH 0x8214 | ||
114 | #define DST_HEIGHT 0x8216 | ||
115 | #define RECT_WIDTH 0x8218 | ||
116 | #define RECT_HEIGHT 0x821A | ||
117 | #define PAT_FGCOLOR 0x821C | ||
118 | #define PAT_BGCOLOR 0x8220 | ||
119 | #define SRC_FGCOLOR 0x8224 | ||
120 | #define SRC_BGCOLOR 0x8228 | ||
121 | #define MONO_MASK 0x822C | ||
122 | #define LEFT_CLIP 0x8234 | ||
123 | #define TOP_CLIP 0x8236 | ||
124 | #define RIGHT_CLIP 0x8238 | ||
125 | #define BOTTOM_CLIP 0x823A | ||
126 | #define COMMAND_READY 0x823C | ||
127 | #define FIRE_TRIGGER 0x8240 | ||
128 | |||
129 | #define PATTERN_REG 0x8300 /* 384 bytes pattern buffer */ | ||
130 | |||
131 | /* Transparent bitblit registers */ | ||
132 | #define TRANS_DST_KEY_HIGH PAT_FGCOLOR | ||
133 | #define TRANS_DST_KEY_LOW PAT_BGCOLOR | ||
134 | #define TRANS_SRC_KEY_HIGH SRC_FGCOLOR | ||
135 | #define TRANS_SRC_KEY_LOW SRC_BGCOLOR | ||
136 | |||
137 | /* Store queue length in par */ | ||
138 | #define CmdQueLen ivideo->cmdqueuelength | ||
139 | |||
140 | /* ------------- SiS 300 series -------------- */ | ||
141 | |||
142 | /* BR(16) (0x8240): | ||
143 | |||
144 | bit 31 2D engine: 1 is idle, | ||
145 | bit 30 3D engine: 1 is idle, | ||
146 | bit 29 Command queue: 1 is empty | ||
147 | bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0] | ||
148 | bits 15:0: Current command queue length | ||
149 | |||
150 | */ | ||
151 | |||
152 | #define SiS300Idle \ | ||
153 | { \ | ||
154 | while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ | ||
155 | while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ | ||
156 | while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ | ||
157 | CmdQueLen = MMIO_IN16(ivideo->mmio_vbase, 0x8240); \ | ||
158 | } | ||
159 | /* (do three times, because 2D engine seems quite unsure about whether or not it's idle) */ | ||
160 | |||
161 | #define SiS300SetupSRCBase(base) \ | ||
162 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
163 | MMIO_OUT32(ivideo->mmio_vbase, BR(0), base);\ | ||
164 | CmdQueLen--; | ||
165 | |||
166 | #define SiS300SetupSRCPitch(pitch) \ | ||
167 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
168 | MMIO_OUT16(ivideo->mmio_vbase, BR(1), pitch);\ | ||
169 | CmdQueLen--; | ||
170 | |||
171 | #define SiS300SetupSRCXY(x,y) \ | ||
172 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
173 | MMIO_OUT32(ivideo->mmio_vbase, BR(2), (x)<<16 | (y) );\ | ||
174 | CmdQueLen--; | ||
175 | |||
176 | #define SiS300SetupDSTBase(base) \ | ||
177 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
178 | MMIO_OUT32(ivideo->mmio_vbase, BR(4), base);\ | ||
179 | CmdQueLen--; | ||
180 | |||
181 | #define SiS300SetupDSTXY(x,y) \ | ||
182 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
183 | MMIO_OUT32(ivideo->mmio_vbase, BR(3), (x)<<16 | (y) );\ | ||
184 | CmdQueLen--; | ||
185 | |||
186 | #define SiS300SetupDSTRect(x,y) \ | ||
187 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
188 | MMIO_OUT32(ivideo->mmio_vbase, BR(5), (y)<<16 | (x) );\ | ||
189 | CmdQueLen--; | ||
190 | |||
191 | #define SiS300SetupDSTColorDepth(bpp) \ | ||
192 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
193 | MMIO_OUT16(ivideo->mmio_vbase, BR(1)+2, bpp);\ | ||
194 | CmdQueLen--; | ||
195 | |||
196 | #define SiS300SetupRect(w,h) \ | ||
197 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
198 | MMIO_OUT32(ivideo->mmio_vbase, BR(6), (h)<<16 | (w) );\ | ||
199 | CmdQueLen--; | ||
200 | |||
201 | #define SiS300SetupPATFG(color) \ | ||
202 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
203 | MMIO_OUT32(ivideo->mmio_vbase, BR(7), color);\ | ||
204 | CmdQueLen--; | ||
205 | |||
206 | #define SiS300SetupPATBG(color) \ | ||
207 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
208 | MMIO_OUT32(ivideo->mmio_vbase, BR(8), color);\ | ||
209 | CmdQueLen--; | ||
210 | |||
211 | #define SiS300SetupSRCFG(color) \ | ||
212 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
213 | MMIO_OUT32(ivideo->mmio_vbase, BR(9), color);\ | ||
214 | CmdQueLen--; | ||
215 | |||
216 | #define SiS300SetupSRCBG(color) \ | ||
217 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
218 | MMIO_OUT32(ivideo->mmio_vbase, BR(10), color);\ | ||
219 | CmdQueLen--; | ||
220 | |||
221 | /* 0x8224 src colorkey high */ | ||
222 | /* 0x8228 src colorkey low */ | ||
223 | /* 0x821c dest colorkey high */ | ||
224 | /* 0x8220 dest colorkey low */ | ||
225 | #define SiS300SetupSRCTrans(color) \ | ||
226 | if(CmdQueLen <= 1) SiS300Idle;\ | ||
227 | MMIO_OUT32(ivideo->mmio_vbase, 0x8224, color);\ | ||
228 | MMIO_OUT32(ivideo->mmio_vbase, 0x8228, color);\ | ||
229 | CmdQueLen -= 2; | ||
230 | |||
231 | #define SiS300SetupDSTTrans(color) \ | ||
232 | if(CmdQueLen <= 1) SiS300Idle;\ | ||
233 | MMIO_OUT32(ivideo->mmio_vbase, 0x821C, color); \ | ||
234 | MMIO_OUT32(ivideo->mmio_vbase, 0x8220, color); \ | ||
235 | CmdQueLen -= 2; | ||
236 | |||
237 | #define SiS300SetupMONOPAT(p0,p1) \ | ||
238 | if(CmdQueLen <= 1) SiS300Idle;\ | ||
239 | MMIO_OUT32(ivideo->mmio_vbase, BR(11), p0);\ | ||
240 | MMIO_OUT32(ivideo->mmio_vbase, BR(12), p1);\ | ||
241 | CmdQueLen -= 2; | ||
242 | |||
243 | #define SiS300SetupClipLT(left,top) \ | ||
244 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
245 | MMIO_OUT32(ivideo->mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\ | ||
246 | CmdQueLen--; | ||
247 | |||
248 | #define SiS300SetupClipRB(right,bottom) \ | ||
249 | if(CmdQueLen <= 0) SiS300Idle;\ | ||
250 | MMIO_OUT32(ivideo->mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\ | ||
251 | CmdQueLen--; | ||
252 | |||
253 | /* General */ | ||
254 | #define SiS300SetupROP(rop) \ | ||
255 | ivideo->CommandReg = (rop) << 8; | ||
256 | |||
257 | #define SiS300SetupCMDFlag(flags) \ | ||
258 | ivideo->CommandReg |= (flags); | ||
259 | |||
260 | #define SiS300DoCMD \ | ||
261 | if(CmdQueLen <= 1) SiS300Idle;\ | ||
262 | MMIO_OUT32(ivideo->mmio_vbase, BR(15), ivideo->CommandReg); \ | ||
263 | MMIO_OUT32(ivideo->mmio_vbase, BR(16), 0);\ | ||
264 | CmdQueLen -= 2; | ||
265 | |||
266 | /* -------------- SiS 315/330 series --------------- */ | ||
267 | |||
268 | /* Q_STATUS: | ||
269 | bit 31 = 1: All engines idle and all queues empty | ||
270 | bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty | ||
271 | bit 29 = 1: 2D engine is idle | ||
272 | bit 28 = 1: 3D engine is idle | ||
273 | bit 27 = 1: HW command queue empty | ||
274 | bit 26 = 1: 2D queue empty | ||
275 | bit 25 = 1: 3D queue empty | ||
276 | bit 24 = 1: SW command queue empty | ||
277 | bits 23:16: 2D counter 3 | ||
278 | bits 15:8: 2D counter 2 | ||
279 | bits 7:0: 2D counter 1 | ||
280 | */ | ||
281 | |||
282 | #define SiS310Idle \ | ||
283 | { \ | ||
284 | while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ | ||
285 | while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ | ||
286 | CmdQueLen = 0; \ | ||
287 | } | ||
288 | |||
289 | #define SiS310SetupSRCBase(base) \ | ||
290 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
291 | MMIO_OUT32(ivideo->mmio_vbase, SRC_ADDR, base);\ | ||
292 | CmdQueLen--; | ||
293 | |||
294 | #define SiS310SetupSRCPitch(pitch) \ | ||
295 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
296 | MMIO_OUT16(ivideo->mmio_vbase, SRC_PITCH, pitch);\ | ||
297 | CmdQueLen--; | ||
298 | |||
299 | #define SiS310SetupSRCXY(x,y) \ | ||
300 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
301 | MMIO_OUT32(ivideo->mmio_vbase, SRC_Y, (x)<<16 | (y) );\ | ||
302 | CmdQueLen--; | ||
303 | |||
304 | #define SiS310SetupDSTBase(base) \ | ||
305 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
306 | MMIO_OUT32(ivideo->mmio_vbase, DST_ADDR, base);\ | ||
307 | CmdQueLen--; | ||
308 | |||
309 | #define SiS310SetupDSTXY(x,y) \ | ||
310 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
311 | MMIO_OUT32(ivideo->mmio_vbase, DST_Y, (x)<<16 | (y) );\ | ||
312 | CmdQueLen--; | ||
313 | |||
314 | #define SiS310SetupDSTRect(x,y) \ | ||
315 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
316 | MMIO_OUT32(ivideo->mmio_vbase, DST_PITCH, (y)<<16 | (x) );\ | ||
317 | CmdQueLen--; | ||
318 | |||
319 | #define SiS310SetupDSTColorDepth(bpp) \ | ||
320 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
321 | MMIO_OUT16(ivideo->mmio_vbase, AGP_BASE, bpp);\ | ||
322 | CmdQueLen--; | ||
323 | |||
324 | #define SiS310SetupRect(w,h) \ | ||
325 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
326 | MMIO_OUT32(ivideo->mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\ | ||
327 | CmdQueLen--; | ||
328 | |||
329 | #define SiS310SetupPATFG(color) \ | ||
330 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
331 | MMIO_OUT32(ivideo->mmio_vbase, PAT_FGCOLOR, color);\ | ||
332 | CmdQueLen--; | ||
333 | |||
334 | #define SiS310SetupPATBG(color) \ | ||
335 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
336 | MMIO_OUT32(ivideo->mmio_vbase, PAT_BGCOLOR, color);\ | ||
337 | CmdQueLen--; | ||
338 | |||
339 | #define SiS310SetupSRCFG(color) \ | ||
340 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
341 | MMIO_OUT32(ivideo->mmio_vbase, SRC_FGCOLOR, color);\ | ||
342 | CmdQueLen--; | ||
343 | |||
344 | #define SiS310SetupSRCBG(color) \ | ||
345 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
346 | MMIO_OUT32(ivideo->mmio_vbase, SRC_BGCOLOR, color);\ | ||
347 | CmdQueLen--; | ||
348 | |||
349 | #define SiS310SetupSRCTrans(color) \ | ||
350 | if(CmdQueLen <= 1) SiS310Idle;\ | ||
351 | MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_HIGH, color);\ | ||
352 | MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_LOW, color);\ | ||
353 | CmdQueLen -= 2; | ||
354 | |||
355 | #define SiS310SetupDSTTrans(color) \ | ||
356 | if(CmdQueLen <= 1) SiS310Idle;\ | ||
357 | MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_HIGH, color); \ | ||
358 | MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_LOW, color); \ | ||
359 | CmdQueLen -= 2; | ||
360 | |||
361 | #define SiS310SetupMONOPAT(p0,p1) \ | ||
362 | if(CmdQueLen <= 1) SiS310Idle;\ | ||
363 | MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK, p0);\ | ||
364 | MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK+4, p1);\ | ||
365 | CmdQueLen -= 2; | ||
366 | |||
367 | #define SiS310SetupClipLT(left,top) \ | ||
368 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
369 | MMIO_OUT32(ivideo->mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\ | ||
370 | CmdQueLen--; | ||
371 | |||
372 | #define SiS310SetupClipRB(right,bottom) \ | ||
373 | if(CmdQueLen <= 0) SiS310Idle;\ | ||
374 | MMIO_OUT32(ivideo->mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\ | ||
375 | CmdQueLen--; | ||
376 | |||
377 | #define SiS310SetupROP(rop) \ | ||
378 | ivideo->CommandReg = (rop) << 8; | ||
379 | |||
380 | #define SiS310SetupCMDFlag(flags) \ | ||
381 | ivideo->CommandReg |= (flags); | ||
382 | |||
383 | #define SiS310DoCMD \ | ||
384 | if(CmdQueLen <= 1) SiS310Idle;\ | ||
385 | MMIO_OUT32(ivideo->mmio_vbase, COMMAND_READY, ivideo->CommandReg); \ | ||
386 | MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \ | ||
387 | CmdQueLen -= 2; | ||
388 | |||
389 | |||
390 | int sisfb_initaccel(struct sis_video_info *ivideo); | ||
391 | void sisfb_syncaccel(struct sis_video_info *ivideo); | ||
392 | |||
393 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) | ||
394 | void fbcon_sis_bmove(struct display *p, int srcy, int srcx, int dsty, | ||
395 | int dstx, int height, int width); | ||
396 | void fbcon_sis_revc(struct display *p, int srcy, int srcx); | ||
397 | void fbcon_sis_clear8(struct vc_data *conp, struct display *p, int srcy, | ||
398 | int srcx, int height, int width); | ||
399 | void fbcon_sis_clear16(struct vc_data *conp, struct display *p, int srcy, | ||
400 | int srcx, int height, int width); | ||
401 | void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy, | ||
402 | int srcx, int height, int width); | ||
403 | #endif | ||
404 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) | ||
405 | void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect); | ||
406 | void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area); | ||
407 | #endif | ||
408 | |||
409 | #endif | ||