More nv30 exa cleaning up.
[nouveau] / src / nv_accel_common.c
1 /*
2  * Copyright 2007 Ben Skeggs
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 #include "nv_include.h"
24
25 static Bool
26 NVAccelInitNullObject(ScrnInfoPtr pScrn)
27 {
28         NVPtr pNv = NVPTR(pScrn);
29         static int have_object = FALSE;
30
31         if (!have_object) {
32                 if (!NVDmaCreateContextObject(pNv, NvNullObject, NV01_NULL))
33                         return FALSE;
34                 have_object = TRUE;
35         }
36
37         return TRUE;
38 }
39
40 uint32_t
41 NVAccelGetPixmapOffset(PixmapPtr pPix)
42 {
43         ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
44         NVPtr pNv = NVPTR(pScrn);
45         unsigned long offset;
46
47         offset = exaGetPixmapOffset(pPix);
48         if (offset >= pNv->FB->size) {
49                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
50                            "AII, passed bad pixmap: offset 0x%lx\n", offset);
51                 return pNv->FB->offset;
52         }
53         offset += pNv->FB->offset;
54
55         return offset;
56 }
57
58 static Bool
59 NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn)
60 {
61         NVPtr pNv = NVPTR(pScrn);
62         static int have_object = FALSE;
63
64         if (!have_object) {
65                 pNv->Notifier0 = NVNotifierAlloc(pScrn, NvDmaNotifier0);
66                 if (!pNv->Notifier0)
67                         return FALSE;
68                 have_object = TRUE;
69         }
70
71         return TRUE;
72 }
73
74 /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */
75 static Bool
76 NVAccelInitContextSurfaces(ScrnInfoPtr pScrn)
77 {
78         NVPtr pNv = NVPTR(pScrn);
79         static int have_object = FALSE;
80         uint32_t   class;
81
82         class = (pNv->Architecture >= NV_10) ? NV10_CONTEXT_SURFACES_2D :
83                                                NV04_CONTEXT_SURFACES_2D;
84
85         if (!have_object) {
86                 if (!NVDmaCreateContextObject(pNv, NvContextSurfaces, class))
87                         return FALSE;
88                 have_object = TRUE;
89         }
90
91         BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_DMA_NOTIFY, 1);
92         OUT_RING  (NvNullObject);
93         BEGIN_RING(NvContextSurfaces,
94                    NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
95         OUT_RING  (NvDmaFB);
96         OUT_RING  (NvDmaFB);
97
98         return TRUE;
99 }
100
101 /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */
102 static Bool
103 NVAccelInitContextBeta1(ScrnInfoPtr pScrn)
104 {
105         NVPtr pNv = NVPTR(pScrn);
106         static int have_object = FALSE;
107         uint32_t   class;
108
109         class = 0x12;
110
111         if (!have_object) {
112                 if (!NVDmaCreateContextObject(pNv, NvContextBeta1, class))
113                         return FALSE;
114                 have_object = TRUE;
115         }
116
117         BEGIN_RING(NvContextBeta1, 0x300, 1); /*alpha factor*/
118         OUT_RING  (0xff << 23);
119
120         return TRUE;
121 }
122
123
124 static Bool
125 NVAccelInitContextBeta4(ScrnInfoPtr pScrn)
126 {
127         NVPtr pNv = NVPTR(pScrn);
128         static int have_object = FALSE;
129         uint32_t   class;
130         
131         class = 0x72;
132
133         if (!have_object) {
134                 if (!NVDmaCreateContextObject(pNv, NvContextBeta4, class))
135                         return FALSE;
136                 have_object = TRUE;
137         }
138
139         BEGIN_RING(NvContextBeta4, 0x300, 1); /*RGBA factor*/
140         OUT_RING  (0xffff0000);
141         return TRUE;
142 }
143
144 Bool
145 NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret)
146 {
147         switch (pPix->drawable.bitsPerPixel) {
148         case 32:
149                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
150                 break;
151         case 24:
152                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8;
153                 break;
154         case 16:
155                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
156                 break;
157         case 8:
158                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
159                 break;
160         default:
161                 return FALSE;
162         }
163
164         return TRUE;
165 }
166
167 Bool
168 NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPict, int *fmt_ret)
169 {
170         switch (pPict->format) {
171         case PICT_a8r8g8b8:
172                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
173                 break;
174         case PICT_x8r8g8b8:
175                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8;
176                 break;
177         case PICT_r5g6b5:
178                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
179                 break;
180         case PICT_a8:
181                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
182                 break;
183         default:
184                 return FALSE;
185         }
186
187         return TRUE;
188 }
189
190 Bool
191 NVAccelSetCtxSurf2D(PixmapPtr psPix, PixmapPtr pdPix, int format)
192 {
193         ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum];
194         NVPtr pNv = NVPTR(pScrn);
195
196         BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
197         OUT_RING  (format);
198         OUT_RING  (((uint32_t)exaGetPixmapPitch(pdPix) << 16) |
199                          (uint32_t)exaGetPixmapPitch(psPix));
200         OUT_RING  (NVAccelGetPixmapOffset(psPix));
201         OUT_RING  (NVAccelGetPixmapOffset(pdPix));
202
203         return TRUE;
204 }
205
206 static Bool
207 NVAccelInitImagePattern(ScrnInfoPtr pScrn)
208 {
209         NVPtr pNv = NVPTR(pScrn);
210         static int have_object = FALSE;
211         uint32_t   class;
212
213         class = NV04_IMAGE_PATTERN;
214
215         if (!have_object) {
216                 if (!NVDmaCreateContextObject(pNv, NvImagePattern, class))
217                         return FALSE;
218                 have_object = TRUE;
219         }
220
221         BEGIN_RING(NvImagePattern, NV04_IMAGE_PATTERN_DMA_NOTIFY, 1);
222         OUT_RING  (NvNullObject);
223         BEGIN_RING(NvImagePattern, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT, 3);
224 #if X_BYTE_ORDER == X_BIG_ENDIAN
225         OUT_RING  (NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
226 #else
227         OUT_RING  (NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_CGA6);
228 #endif
229         OUT_RING  (NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
230         OUT_RING  (NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
231
232         return TRUE;
233 }
234
235 static Bool
236 NVAccelInitRasterOp(ScrnInfoPtr pScrn)
237 {
238         NVPtr pNv = NVPTR(pScrn);
239         static int have_object = FALSE;
240         uint32_t   class;
241
242         class = NV03_CONTEXT_ROP;
243
244         if (!have_object) {
245                 if (!NVDmaCreateContextObject(pNv, NvRop, class))
246                         return FALSE;
247                 have_object = TRUE;
248         }
249
250         BEGIN_RING(NvRop, NV03_CONTEXT_ROP_DMA_NOTIFY, 1);
251         OUT_RING  (NvNullObject);
252
253         pNv->currentRop = ~0;
254         return TRUE;
255 }
256
257 static Bool
258 NVAccelInitRectangle(ScrnInfoPtr pScrn)
259 {
260         NVPtr pNv = NVPTR(pScrn);
261         static int have_object = FALSE;
262         uint32_t   class;
263
264         class = NV04_GDI_RECTANGLE_TEXT;
265
266         if (!have_object) {
267                 if (!NVDmaCreateContextObject(pNv, NvRectangle, class))
268                         return FALSE;
269                 have_object = TRUE;
270         }
271
272         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
273         OUT_RING  (NvDmaNotifier0);
274         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_DMA_FONTS, 1);
275         OUT_RING  (NvNullObject);
276         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
277         OUT_RING  (NvContextSurfaces);
278         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_ROP, 1);
279         OUT_RING  (NvRop);
280         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_PATTERN, 1);
281         OUT_RING  (NvImagePattern);
282         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
283         OUT_RING  (NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
284         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
285         /* XXX why putting 1 like renouveau dump, swap the text */
286 #if 1 || X_BYTE_ORDER == X_BIG_ENDIAN
287         OUT_RING  (NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
288 #else
289         OUT_RING  (NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_CGA6);
290 #endif
291
292         return TRUE;
293 }
294
295 static Bool
296 NVAccelInitImageBlit(ScrnInfoPtr pScrn)
297 {
298         NVPtr pNv = NVPTR(pScrn);
299         static int have_object = FALSE;
300         uint32_t   class;
301
302         class = (pNv->WaitVSyncPossible) ? NV12_IMAGE_BLIT : NV_IMAGE_BLIT;
303
304         if (!have_object) {
305                 if (!NVDmaCreateContextObject(pNv, NvImageBlit, class))
306                         return FALSE;
307                 have_object = TRUE;
308         }
309
310         BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_DMA_NOTIFY, 1);
311         OUT_RING  (NvDmaNotifier0);
312         BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_COLOR_KEY, 1);
313         OUT_RING  (NvNullObject);
314         BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_SURFACE, 1);
315         OUT_RING  (NvContextSurfaces);
316         BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_CLIP_RECTANGLE, 3);
317         OUT_RING  (NvNullObject);
318         OUT_RING  (NvImagePattern);
319         OUT_RING  (NvRop);
320         BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
321         OUT_RING  (NV_IMAGE_BLIT_OPERATION_ROP_AND);
322
323         if (pNv->WaitVSyncPossible) {
324                 BEGIN_RING(NvImageBlit, 0x0120, 3);
325                 OUT_RING  (0);
326                 OUT_RING  (1);
327                 OUT_RING  (2);
328         }
329
330         return TRUE;
331 }
332
333 static Bool
334 NVAccelInitScaledImage(ScrnInfoPtr pScrn)
335 {
336         NVPtr pNv = NVPTR(pScrn);
337         static int have_object = FALSE;
338         uint32_t   class;
339
340         switch (pNv->Architecture) {
341         case NV_ARCH_04:
342                 class = NV04_SCALED_IMAGE_FROM_MEMORY;
343                 break;
344         case NV_ARCH_10:
345         case NV_ARCH_20:
346         case NV_ARCH_30:
347                 class = NV10_SCALED_IMAGE_FROM_MEMORY;
348                 break;
349         case NV_ARCH_40:
350         default:
351                 class = NV10_SCALED_IMAGE_FROM_MEMORY | 0x3000;
352                 break;
353         }
354
355         if (!have_object) {
356                 if (!NVDmaCreateContextObject(pNv, NvScaledImage, class))
357                         return FALSE;
358                 have_object = TRUE;
359         }
360
361         BEGIN_RING(NvScaledImage,
362                         NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY, 7);
363         OUT_RING  (NvDmaNotifier0);
364         OUT_RING  (NvDmaFB);
365         OUT_RING  (NvNullObject);
366         OUT_RING  (NvNullObject);
367         OUT_RING  (NvContextBeta1);
368         OUT_RING  (NvContextBeta4);
369         OUT_RING  (NvContextSurfaces);
370         if (pNv->Architecture>=NV_ARCH_10) {
371         BEGIN_RING(NvScaledImage,
372                    NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 1);
373         OUT_RING  (NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_DITHER);
374         }
375         BEGIN_RING(NvScaledImage, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION, 1);
376         OUT_RING  (NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
377
378         return TRUE;
379 }
380
381 static Bool
382 NVAccelInitClipRectangle(ScrnInfoPtr pScrn)
383 {
384         NVPtr pNv = NVPTR(pScrn);
385         static int have_object = FALSE;
386         int class = NV01_CONTEXT_CLIP_RECTANGLE;
387
388         if (!have_object) {
389                 if (!NVDmaCreateContextObject(pNv, NvClipRectangle, class))
390                         return FALSE;
391                 have_object = TRUE;
392         }
393
394         BEGIN_RING(NvClipRectangle, NV01_CONTEXT_CLIP_RECTANGLE_DMA_NOTIFY, 1);
395         OUT_RING  (NvNullObject);
396
397         return TRUE;
398 }
399
400 static Bool
401 NVAccelInitSolidLine(ScrnInfoPtr pScrn)
402 {
403         NVPtr pNv = NVPTR(pScrn);
404         static int have_object = FALSE;
405         int class = NV04_RENDER_SOLID_LINE;
406
407         if (!have_object) {
408                 if (!NVDmaCreateContextObject(pNv, NvSolidLine, class))
409                         return FALSE;
410                 have_object = TRUE;
411         }
412
413         BEGIN_RING(NvSolidLine, NV01_RENDER_SOLID_LINE_CLIP_RECTANGLE, 3);
414         OUT_RING  (NvClipRectangle);
415         OUT_RING  (NvImagePattern);
416         OUT_RING  (NvRop);
417         BEGIN_RING(NvSolidLine, NV04_RENDER_SOLID_LINE_SURFACE, 1);
418         OUT_RING  (NvContextSurfaces);
419         BEGIN_RING(NvSolidLine, NV01_RENDER_SOLID_LINE_OPERATION, 1);
420         OUT_RING  (NV01_RENDER_SOLID_LINE_OPERATION_ROP_AND);
421
422         return TRUE;
423 }
424
425 /* FLAGS_NONE, NvDmaFB, NvDmaAGP, NvDmaNotifier0 */
426 static Bool
427 NVAccelInitMemFormat(ScrnInfoPtr pScrn)
428 {
429         NVPtr pNv = NVPTR(pScrn);
430         static int have_object = FALSE;
431         uint32_t   class;
432
433         if (pNv->Architecture < NV_ARCH_50)
434                 class = NV_MEMORY_TO_MEMORY_FORMAT;
435         else
436                 class = NV50_MEMORY_TO_MEMORY_FORMAT;
437
438         if (!have_object) {
439                 if (!NVDmaCreateContextObject(pNv, NvMemFormat, class))
440                                 return FALSE;
441                 have_object = TRUE;
442         }
443
444         BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
445         OUT_RING  (NvDmaNotifier0);
446         BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
447         OUT_RING  (NvDmaFB);
448         OUT_RING  (NvDmaFB);
449
450         pNv->M2MFDirection = -1;
451         return TRUE;
452 }
453
454 static Bool
455 NVAccelInitImageFromCpu(ScrnInfoPtr pScrn)
456 {
457         NVPtr pNv = NVPTR(pScrn);
458         static int have_object = FALSE;
459         uint32_t   class;
460
461         switch (pNv->Architecture) {
462         case NV_ARCH_04:
463                 class = NV05_IMAGE_FROM_CPU;
464                 break;
465         case NV_ARCH_10:
466         case NV_ARCH_20:
467         case NV_ARCH_30:
468         case NV_ARCH_40:
469         default:
470                 class = NV10_IMAGE_FROM_CPU;
471                 break;
472         }
473
474         if (!have_object) {
475                 if (!NVDmaCreateContextObject(pNv, NvImageFromCpu, class))
476                         return FALSE;
477                 have_object = TRUE;
478         }
479
480         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_DMA_NOTIFY, 1);
481         OUT_RING  (NvDmaNotifier0);
482         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_CLIP_RECTANGLE, 1);
483         OUT_RING  (NvNullObject);
484         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_PATTERN, 1);
485         OUT_RING  (NvNullObject);
486         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_ROP, 1);
487         OUT_RING  (NvNullObject);
488         if (pNv->Architecture >= NV_ARCH_10)
489         {
490                 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_BETA1, 1);
491                 OUT_RING  (NvNullObject);
492                 BEGIN_RING(NvImageFromCpu, NV05_IMAGE_FROM_CPU_BETA4, 1);
493                 OUT_RING  (NvNullObject);
494         }
495         BEGIN_RING(NvImageFromCpu, NV05_IMAGE_FROM_CPU_SURFACE, 1);
496         OUT_RING  (NvContextSurfaces);
497         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_OPERATION, 1);
498         OUT_RING  (NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
499         return TRUE;
500 }
501
502 static Bool
503 NVAccelInit2D_NV50(ScrnInfoPtr pScrn)
504 {
505         NVPtr pNv = NVPTR(pScrn);
506         static int have_object = FALSE;
507
508         if (!have_object) {
509                 if (!NVDmaCreateContextObject(pNv, Nv2D, 0x502d))
510                                 return FALSE;
511                 have_object = TRUE;
512         }
513
514         BEGIN_RING(Nv2D, 0x180, 3);
515         OUT_RING  (NvDmaNotifier0);
516         OUT_RING  (NvDmaFB);
517         OUT_RING  (NvDmaFB);
518
519         /* Magics from nv, no clue what they do, but at least some
520          * of them are needed to avoid crashes.
521          */
522         BEGIN_RING(Nv2D, 0x260, 1);
523         OUT_RING  (1);
524         BEGIN_RING(Nv2D, 0x290, 1);
525         OUT_RING  (1);
526         BEGIN_RING(Nv2D, 0x29c, 1);
527         OUT_RING  (0);
528         BEGIN_RING(Nv2D, 0x58c, 1);
529         OUT_RING  (0x111);
530
531         pNv->currentRop = 0xfffffffa;
532         return TRUE;
533 }
534
535 #define INIT_CONTEXT_OBJECT(name) do {                                        \
536         ret = NVAccelInit##name(pScrn);                                       \
537         if (!ret) {                                                           \
538                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,                         \
539                            "Failed to initialise context object: "#name       \
540                            " (%d)\n", ret);                                   \
541                 return FALSE;                                                 \
542         }                                                                     \
543 } while(0)
544
545 Bool
546 NVAccelCommonInit(ScrnInfoPtr pScrn)
547 {
548         NVPtr pNv = NVPTR(pScrn);
549         Bool ret;
550         if(pNv->NoAccel) return TRUE;
551
552         /* General engine objects */
553         INIT_CONTEXT_OBJECT(NullObject);
554         INIT_CONTEXT_OBJECT(DmaNotifier0);
555
556         /* 2D engine */
557         if (pNv->Architecture < NV_ARCH_50) {
558                 INIT_CONTEXT_OBJECT(ContextSurfaces);
559                 INIT_CONTEXT_OBJECT(ContextBeta1);
560                 INIT_CONTEXT_OBJECT(ContextBeta4);
561                 INIT_CONTEXT_OBJECT(ImagePattern);
562                 INIT_CONTEXT_OBJECT(RasterOp);
563                 INIT_CONTEXT_OBJECT(Rectangle);
564                 INIT_CONTEXT_OBJECT(ImageBlit);
565                 INIT_CONTEXT_OBJECT(ScaledImage);
566                 INIT_CONTEXT_OBJECT(ClipRectangle);
567                 INIT_CONTEXT_OBJECT(SolidLine);
568                 INIT_CONTEXT_OBJECT(ImageFromCpu);
569         } else {
570                 INIT_CONTEXT_OBJECT(2D_NV50);
571         }
572         INIT_CONTEXT_OBJECT(MemFormat);
573
574         /* 3D init */
575         switch (pNv->Architecture) {
576         case NV_ARCH_40:
577                 INIT_CONTEXT_OBJECT(NV40TCL);
578                 break;
579         case NV_ARCH_30:
580                 INIT_CONTEXT_OBJECT(NV30TCL);
581                 break;
582         case NV_ARCH_20:
583         case NV_ARCH_10:
584                 INIT_CONTEXT_OBJECT(NV10TCL);
585                 break;
586         default:
587                 break;
588         }
589
590         return TRUE;
591 }
592