- patches.arch/x86_mce_intel_decode_physical_address.patch:
[linux-flexiantxendom0-3.2.10.git] / sound / pci / asihpi / hpicmn.c
1 /******************************************************************************
2
3     AudioScience HPI driver
4     Copyright (C) 1997-2010  AudioScience Inc. <support@audioscience.com>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of version 2 of the GNU General Public License as
8     published by the Free Software Foundation;
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19 \file hpicmn.c
20
21  Common functions used by hpixxxx.c modules
22
23 (C) Copyright AudioScience Inc. 1998-2003
24 *******************************************************************************/
25 #define SOURCEFILE_NAME "hpicmn.c"
26
27 #include "hpi_internal.h"
28 #include "hpidebug.h"
29 #include "hpicmn.h"
30
31 struct hpi_adapters_list {
32         struct hpios_spinlock list_lock;
33         struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
34         u16 gw_num_adapters;
35 };
36
37 static struct hpi_adapters_list adapters;
38
39 /**
40 * Given an HPI Message that was sent out and a response that was received,
41 * validate that the response has the correct fields filled in,
42 * i.e ObjectType, Function etc
43 **/
44 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
45 {
46         u16 error = 0;
47
48         if ((phr->type != HPI_TYPE_RESPONSE)
49                 || (phr->object != phm->object)
50                 || (phr->function != phm->function))
51                 error = HPI_ERROR_INVALID_RESPONSE;
52
53         return error;
54 }
55
56 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
57 {
58         u16 retval = 0;
59         /*HPI_ASSERT(pao->wAdapterType); */
60
61         hpios_alistlock_lock(&adapters);
62
63         if (pao->index >= HPI_MAX_ADAPTERS) {
64                 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
65                 goto unlock;
66         }
67
68         if (adapters.adapter[pao->index].adapter_type) {
69                 {
70                         retval = HPI_DUPLICATE_ADAPTER_NUMBER;
71                         goto unlock;
72                 }
73         }
74         adapters.adapter[pao->index] = *pao;
75         hpios_dsplock_init(&adapters.adapter[pao->index]);
76         adapters.gw_num_adapters++;
77
78 unlock:
79         hpios_alistlock_un_lock(&adapters);
80         return retval;
81 }
82
83 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
84 {
85         memset(pao, 0, sizeof(struct hpi_adapter_obj));
86
87         hpios_alistlock_lock(&adapters);
88         adapters.gw_num_adapters--;     /* dec the number of adapters */
89         hpios_alistlock_un_lock(&adapters);
90 }
91
92 /**
93 * FindAdapter returns a pointer to the struct hpi_adapter_obj with
94 * index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
95 *
96 */
97 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
98 {
99         struct hpi_adapter_obj *pao = NULL;
100
101         if (adapter_index >= HPI_MAX_ADAPTERS) {
102                 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ",
103                         adapter_index);
104                 return NULL;
105         }
106
107         pao = &adapters.adapter[adapter_index];
108         if (pao->adapter_type != 0) {
109                 /*
110                    HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
111                    wAdapterIndex);
112                  */
113                 return pao;
114         } else {
115                 /*
116                    HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
117                    wAdapterIndex);
118                  */
119                 return NULL;
120         }
121 }
122
123 /**
124 *
125 * wipe an HPI_ADAPTERS_LIST structure.
126 *
127 **/
128 static void wipe_adapter_list(void
129         )
130 {
131         memset(&adapters, 0, sizeof(adapters));
132 }
133
134 /**
135 * SubSysGetAdapters fills awAdapterList in an struct hpi_response structure
136 * with all adapters in the given HPI_ADAPTERS_LIST.
137 *
138 */
139 static void subsys_get_adapters(struct hpi_response *phr)
140 {
141         /* fill in the response adapter array with the position */
142         /* identified by the adapter number/index of the adapters in */
143         /* this HPI */
144         /* i.e. if we have an A120 with it's jumper set to */
145         /* Adapter Number 2 then put an Adapter type A120 in the */
146         /* array in position 1 */
147         /* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */
148
149         /* input:  NONE */
150         /* output: wNumAdapters */
151         /*                 awAdapter[] */
152         /* */
153
154         short i;
155         struct hpi_adapter_obj *pao = NULL;
156
157         HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n");
158
159         /* for each adapter, place it's type in the position of the array */
160         /* corresponding to it's adapter number */
161         for (i = 0; i < adapters.gw_num_adapters; i++) {
162                 pao = &adapters.adapter[i];
163                 if (phr->u.s.aw_adapter_list[pao->index] != 0) {
164                         phr->error = HPI_DUPLICATE_ADAPTER_NUMBER;
165                         phr->specific_error = pao->index;
166                         return;
167                 }
168                 phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type;
169         }
170
171         phr->u.s.num_adapters = adapters.gw_num_adapters;
172         phr->error = 0; /* the function completed OK; */
173 }
174
175 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
176 {
177         unsigned int i;
178         int cached = 0;
179         if (!pC)
180                 return 0;
181         if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count)
182                 && (pC->cache_size_in_bytes)
183                 ) {
184                 u32 *p_master_cache;
185                 pC->init = 1;
186
187                 p_master_cache = (u32 *)pC->p_cache;
188                 HPI_DEBUG_LOG(VERBOSE, "check %d controls\n",
189                         pC->control_count);
190                 for (i = 0; i < pC->control_count; i++) {
191                         struct hpi_control_cache_info *info =
192                                 (struct hpi_control_cache_info *)
193                                 p_master_cache;
194
195                         if (info->control_type) {
196                                 pC->p_info[i] = info;
197                                 cached++;
198                         } else
199                                 pC->p_info[i] = NULL;
200
201                         if (info->size_in32bit_words)
202                                 p_master_cache += info->size_in32bit_words;
203                         else
204                                 p_master_cache +=
205                                         sizeof(struct
206                                         hpi_control_cache_single) /
207                                         sizeof(u32);
208
209                         HPI_DEBUG_LOG(VERBOSE,
210                                 "cached %d, pinfo %p index %d type %d\n",
211                                 cached, pC->p_info[i], info->control_index,
212                                 info->control_type);
213                 }
214                 /*
215                    We didn't find anything to cache, so try again later !
216                  */
217                 if (!cached)
218                         pC->init = 0;
219         }
220         return pC->init;
221 }
222
223 /** Find a control.
224 */
225 static short find_control(struct hpi_message *phm,
226         struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI,
227         u16 *pw_control_index)
228 {
229         *pw_control_index = phm->obj_index;
230
231         if (!control_cache_alloc_check(p_cache)) {
232                 HPI_DEBUG_LOG(VERBOSE,
233                         "control_cache_alloc_check() failed. adap%d ci%d\n",
234                         phm->adapter_index, *pw_control_index);
235                 return 0;
236         }
237
238         *pI = p_cache->p_info[*pw_control_index];
239         if (!*pI) {
240                 HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n",
241                         phm->adapter_index, *pw_control_index);
242                 return 0;
243         } else {
244                 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
245                         (*pI)->control_type);
246         }
247         return 1;
248 }
249
250 /** Used by the kernel driver to figure out if a buffer needs mapping.
251  */
252 short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
253         struct hpi_message *phm, void **p, unsigned int *pN)
254 {
255         *pN = 0;
256         *p = NULL;
257         if ((phm->function == HPI_CONTROL_GET_STATE)
258                 && (phm->object == HPI_OBJ_CONTROLEX)
259                 ) {
260                 u16 control_index;
261                 struct hpi_control_cache_info *pI;
262
263                 if (!find_control(phm, p_cache, &pI, &control_index))
264                         return 0;
265         }
266         return 0;
267 }
268
269 /* allow unified treatment of several string fields within struct */
270 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
271         offsetof(struct hpi_control_cache_pad, m), \
272         sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
273
274 struct pad_ofs_size {
275         unsigned int offset;
276         unsigned int field_size;
277 };
278
279 static struct pad_ofs_size pad_desc[] = {
280         HPICMN_PAD_OFS_AND_SIZE(c_channel),     /* HPI_PAD_CHANNEL_NAME */
281         HPICMN_PAD_OFS_AND_SIZE(c_artist),      /* HPI_PAD_ARTIST */
282         HPICMN_PAD_OFS_AND_SIZE(c_title),       /* HPI_PAD_TITLE */
283         HPICMN_PAD_OFS_AND_SIZE(c_comment),     /* HPI_PAD_COMMENT */
284 };
285
286 /** CheckControlCache checks the cache and fills the struct hpi_response
287  * accordingly. It returns one if a cache hit occurred, zero otherwise.
288  */
289 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
290         struct hpi_message *phm, struct hpi_response *phr)
291 {
292         short found = 1;
293         u16 control_index;
294         struct hpi_control_cache_info *pI;
295         struct hpi_control_cache_single *pC;
296         struct hpi_control_cache_pad *p_pad;
297
298         if (!find_control(phm, p_cache, &pI, &control_index))
299                 return 0;
300
301         phr->error = 0;
302
303         /* pC is the default cached control strucure. May be cast to
304            something else in the following switch statement.
305          */
306         pC = (struct hpi_control_cache_single *)pI;
307         p_pad = (struct hpi_control_cache_pad *)pI;
308
309         switch (pI->control_type) {
310
311         case HPI_CONTROL_METER:
312                 if (phm->u.c.attribute == HPI_METER_PEAK) {
313                         phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0];
314                         phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1];
315                 } else if (phm->u.c.attribute == HPI_METER_RMS) {
316                         phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0];
317                         phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1];
318                 } else
319                         found = 0;
320                 break;
321         case HPI_CONTROL_VOLUME:
322                 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
323                         phr->u.c.an_log_value[0] = pC->u.v.an_log[0];
324                         phr->u.c.an_log_value[1] = pC->u.v.an_log[1];
325                 } else
326                         found = 0;
327                 break;
328         case HPI_CONTROL_MULTIPLEXER:
329                 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
330                         phr->u.c.param1 = pC->u.x.source_node_type;
331                         phr->u.c.param2 = pC->u.x.source_node_index;
332                 } else {
333                         found = 0;
334                 }
335                 break;
336         case HPI_CONTROL_CHANNEL_MODE:
337                 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
338                         phr->u.c.param1 = pC->u.m.mode;
339                 else
340                         found = 0;
341                 break;
342         case HPI_CONTROL_LEVEL:
343                 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
344                         phr->u.c.an_log_value[0] = pC->u.l.an_log[0];
345                         phr->u.c.an_log_value[1] = pC->u.l.an_log[1];
346                 } else
347                         found = 0;
348                 break;
349         case HPI_CONTROL_TUNER:
350                 if (phm->u.c.attribute == HPI_TUNER_FREQ)
351                         phr->u.c.param1 = pC->u.t.freq_ink_hz;
352                 else if (phm->u.c.attribute == HPI_TUNER_BAND)
353                         phr->u.c.param1 = pC->u.t.band;
354                 else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
355                         && (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
356                         phr->u.c.param1 = pC->u.t.level;
357                 else
358                         found = 0;
359                 break;
360         case HPI_CONTROL_AESEBU_RECEIVER:
361                 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
362                         phr->u.c.param1 = pC->u.aes3rx.error_status;
363                 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
364                         phr->u.c.param1 = pC->u.aes3rx.source;
365                 else
366                         found = 0;
367                 break;
368         case HPI_CONTROL_AESEBU_TRANSMITTER:
369                 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
370                         phr->u.c.param1 = pC->u.aes3tx.format;
371                 else
372                         found = 0;
373                 break;
374         case HPI_CONTROL_TONEDETECTOR:
375                 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
376                         phr->u.c.param1 = pC->u.tone.state;
377                 else
378                         found = 0;
379                 break;
380         case HPI_CONTROL_SILENCEDETECTOR:
381                 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
382                         phr->u.c.param1 = pC->u.silence.state;
383                         phr->u.c.param2 = pC->u.silence.count;
384                 } else
385                         found = 0;
386                 break;
387         case HPI_CONTROL_MICROPHONE:
388                 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
389                         phr->u.c.param1 = pC->u.phantom_power.state;
390                 else
391                         found = 0;
392                 break;
393         case HPI_CONTROL_SAMPLECLOCK:
394                 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
395                         phr->u.c.param1 = pC->u.clk.source;
396                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
397                         if (pC->u.clk.source_index ==
398                                 HPI_ERROR_ILLEGAL_CACHE_VALUE) {
399                                 phr->u.c.param1 = 0;
400                                 phr->error = HPI_ERROR_INVALID_OPERATION;
401                         } else
402                                 phr->u.c.param1 = pC->u.clk.source_index;
403                 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
404                         phr->u.c.param1 = pC->u.clk.sample_rate;
405                 else
406                         found = 0;
407                 break;
408         case HPI_CONTROL_PAD:
409
410                 if (!(p_pad->field_valid_flags & (1 <<
411                                         HPI_CTL_ATTR_INDEX(phm->u.c.
412                                                 attribute)))) {
413                         phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
414                         break;
415                 }
416
417                 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
418                         phr->u.c.param1 = p_pad->pI;
419                 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
420                         phr->u.c.param1 = p_pad->pTY;
421                 else {
422                         unsigned int index =
423                                 HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1;
424                         unsigned int offset = phm->u.c.param1;
425                         unsigned int pad_string_len, field_size;
426                         char *pad_string;
427                         unsigned int tocopy;
428
429                         HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n",
430                                 phm->u.c.attribute);
431
432                         if (index > ARRAY_SIZE(pad_desc) - 1) {
433                                 phr->error =
434                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
435                                 break;
436                         }
437
438                         pad_string = ((char *)p_pad) + pad_desc[index].offset;
439                         field_size = pad_desc[index].field_size;
440                         /* Ensure null terminator */
441                         pad_string[field_size - 1] = 0;
442
443                         pad_string_len = strlen(pad_string) + 1;
444
445                         if (offset > pad_string_len) {
446                                 phr->error = HPI_ERROR_INVALID_CONTROL_VALUE;
447                                 break;
448                         }
449
450                         tocopy = pad_string_len - offset;
451                         if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
452                                 tocopy = sizeof(phr->u.cu.chars8.sz_data);
453
454                         HPI_DEBUG_LOG(VERBOSE,
455                                 "PADS memcpy(%d), offset %d \n", tocopy,
456                                 offset);
457                         memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset],
458                                 tocopy);
459
460                         phr->u.cu.chars8.remaining_chars =
461                                 pad_string_len - offset - tocopy;
462                 }
463                 break;
464         default:
465                 found = 0;
466                 break;
467         }
468
469         if (found)
470                 HPI_DEBUG_LOG(VERBOSE,
471                         "cached adap %d, ctl %d, type %d, attr %d\n",
472                         phm->adapter_index, pI->control_index,
473                         pI->control_type, phm->u.c.attribute);
474         else
475                 HPI_DEBUG_LOG(VERBOSE,
476                         "uncached adap %d, ctl %d, ctl type %d\n",
477                         phm->adapter_index, pI->control_index,
478                         pI->control_type);
479
480         if (found)
481                 phr->size =
482                         sizeof(struct hpi_response_header) +
483                         sizeof(struct hpi_control_res);
484
485         return found;
486 }
487
488 /** Updates the cache with Set values.
489
490 Only update if no error.
491 Volume and Level return the limited values in the response, so use these
492 Multiplexer does so use sent values
493 */
494 void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
495         struct hpi_message *phm, struct hpi_response *phr)
496 {
497         u16 control_index;
498         struct hpi_control_cache_single *pC;
499         struct hpi_control_cache_info *pI;
500
501         if (phr->error)
502                 return;
503
504         if (!find_control(phm, p_cache, &pI, &control_index))
505                 return;
506
507         /* pC is the default cached control strucure.
508            May be cast to something else in the following switch statement.
509          */
510         pC = (struct hpi_control_cache_single *)pI;
511
512         switch (pI->control_type) {
513         case HPI_CONTROL_VOLUME:
514                 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
515                         pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
516                         pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
517                 }
518                 break;
519         case HPI_CONTROL_MULTIPLEXER:
520                 /* mux does not return its setting on Set command. */
521                 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
522                         pC->u.x.source_node_type = (u16)phm->u.c.param1;
523                         pC->u.x.source_node_index = (u16)phm->u.c.param2;
524                 }
525                 break;
526         case HPI_CONTROL_CHANNEL_MODE:
527                 /* mode does not return its setting on Set command. */
528                 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
529                         pC->u.m.mode = (u16)phm->u.c.param1;
530                 break;
531         case HPI_CONTROL_LEVEL:
532                 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
533                         pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
534                         pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
535                 }
536                 break;
537         case HPI_CONTROL_MICROPHONE:
538                 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
539                         pC->u.phantom_power.state = (u16)phm->u.c.param1;
540                 break;
541         case HPI_CONTROL_AESEBU_TRANSMITTER:
542                 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
543                         pC->u.aes3tx.format = phm->u.c.param1;
544                 break;
545         case HPI_CONTROL_AESEBU_RECEIVER:
546                 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
547                         pC->u.aes3rx.source = phm->u.c.param1;
548                 break;
549         case HPI_CONTROL_SAMPLECLOCK:
550                 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
551                         pC->u.clk.source = (u16)phm->u.c.param1;
552                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
553                         pC->u.clk.source_index = (u16)phm->u.c.param1;
554                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
555                         pC->u.clk.sample_rate = phm->u.c.param1;
556                 break;
557         default:
558                 break;
559         }
560 }
561
562 struct hpi_control_cache *hpi_alloc_control_cache(const u32
563         number_of_controls, const u32 size_in_bytes,
564         struct hpi_control_cache_info *pDSP_control_buffer)
565 {
566         struct hpi_control_cache *p_cache =
567                 kmalloc(sizeof(*p_cache), GFP_KERNEL);
568         p_cache->cache_size_in_bytes = size_in_bytes;
569         p_cache->control_count = number_of_controls;
570         p_cache->p_cache =
571                 (struct hpi_control_cache_single *)pDSP_control_buffer;
572         p_cache->init = 0;
573         p_cache->p_info =
574                 kmalloc(sizeof(*p_cache->p_info) * p_cache->control_count,
575                 GFP_KERNEL);
576         return p_cache;
577 }
578
579 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
580 {
581         if (p_cache->init) {
582                 kfree(p_cache->p_info);
583                 p_cache->p_info = NULL;
584                 p_cache->init = 0;
585                 kfree(p_cache);
586         }
587 }
588
589 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
590 {
591
592         switch (phm->function) {
593         case HPI_SUBSYS_OPEN:
594         case HPI_SUBSYS_CLOSE:
595         case HPI_SUBSYS_DRIVER_UNLOAD:
596                 phr->error = 0;
597                 break;
598         case HPI_SUBSYS_DRIVER_LOAD:
599                 wipe_adapter_list();
600                 hpios_alistlock_init(&adapters);
601                 phr->error = 0;
602                 break;
603         case HPI_SUBSYS_GET_INFO:
604                 subsys_get_adapters(phr);
605                 break;
606         case HPI_SUBSYS_CREATE_ADAPTER:
607         case HPI_SUBSYS_DELETE_ADAPTER:
608                 phr->error = 0;
609                 break;
610         default:
611                 phr->error = HPI_ERROR_INVALID_FUNC;
612                 break;
613         }
614 }
615
616 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
617 {
618         switch (phm->type) {
619         case HPI_TYPE_MESSAGE:
620                 switch (phm->object) {
621                 case HPI_OBJ_SUBSYSTEM:
622                         subsys_message(phm, phr);
623                         break;
624                 }
625                 break;
626
627         default:
628                 phr->error = HPI_ERROR_INVALID_TYPE;
629                 break;
630         }
631 }