]> bbs.cooldavid.org Git - net-next-2.6.git/blob - sound/pci/emu10k1/io.c
[ALSA] Changed Jaroslav Kysela's e-mail from perex@suse.cz to perex@perex.cz
[net-next-2.6.git] / sound / pci / emu10k1 / io.c
1 /*
2  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3  *                   Creative Labs, Inc.
4  *  Routines for control of EMU10K1 chips
5  *
6  *  BUGS:
7  *    --
8  *
9  *  TODO:
10  *    --
11  *
12  *   This program is free software; you can redistribute it and/or modify
13  *   it under the terms of the GNU General Public License as published by
14  *   the Free Software Foundation; either version 2 of the License, or
15  *   (at your option) any later version.
16  *
17  *   This program is distributed in the hope that it will be useful,
18  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *   GNU General Public License for more details.
21  *
22  *   You should have received a copy of the GNU General Public License
23  *   along with this program; if not, write to the Free Software
24  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
25  *
26  */
27
28 #include <sound/driver.h>
29 #include <linux/time.h>
30 #include <sound/core.h>
31 #include <sound/emu10k1.h>
32 #include <linux/delay.h>
33 #include "p17v.h"
34
35 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
36 {
37         unsigned long flags;
38         unsigned int regptr, val;
39         unsigned int mask;
40
41         mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
42         regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
43
44         if (reg & 0xff000000) {
45                 unsigned char size, offset;
46                 
47                 size = (reg >> 24) & 0x3f;
48                 offset = (reg >> 16) & 0x1f;
49                 mask = ((1 << size) - 1) << offset;
50                 
51                 spin_lock_irqsave(&emu->emu_lock, flags);
52                 outl(regptr, emu->port + PTR);
53                 val = inl(emu->port + DATA);
54                 spin_unlock_irqrestore(&emu->emu_lock, flags);
55                 
56                 return (val & mask) >> offset;
57         } else {
58                 spin_lock_irqsave(&emu->emu_lock, flags);
59                 outl(regptr, emu->port + PTR);
60                 val = inl(emu->port + DATA);
61                 spin_unlock_irqrestore(&emu->emu_lock, flags);
62                 return val;
63         }
64 }
65
66 EXPORT_SYMBOL(snd_emu10k1_ptr_read);
67
68 void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
69 {
70         unsigned int regptr;
71         unsigned long flags;
72         unsigned int mask;
73
74         mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
75         regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
76
77         if (reg & 0xff000000) {
78                 unsigned char size, offset;
79
80                 size = (reg >> 24) & 0x3f;
81                 offset = (reg >> 16) & 0x1f;
82                 mask = ((1 << size) - 1) << offset;
83                 data = (data << offset) & mask;
84
85                 spin_lock_irqsave(&emu->emu_lock, flags);
86                 outl(regptr, emu->port + PTR);
87                 data |= inl(emu->port + DATA) & ~mask;
88                 outl(data, emu->port + DATA);
89                 spin_unlock_irqrestore(&emu->emu_lock, flags);          
90         } else {
91                 spin_lock_irqsave(&emu->emu_lock, flags);
92                 outl(regptr, emu->port + PTR);
93                 outl(data, emu->port + DATA);
94                 spin_unlock_irqrestore(&emu->emu_lock, flags);
95         }
96 }
97
98 EXPORT_SYMBOL(snd_emu10k1_ptr_write);
99
100 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, 
101                                           unsigned int reg, 
102                                           unsigned int chn)
103 {
104         unsigned long flags;
105         unsigned int regptr, val;
106   
107         regptr = (reg << 16) | chn;
108
109         spin_lock_irqsave(&emu->emu_lock, flags);
110         outl(regptr, emu->port + 0x20 + PTR);
111         val = inl(emu->port + 0x20 + DATA);
112         spin_unlock_irqrestore(&emu->emu_lock, flags);
113         return val;
114 }
115
116 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, 
117                                    unsigned int reg, 
118                                    unsigned int chn, 
119                                    unsigned int data)
120 {
121         unsigned int regptr;
122         unsigned long flags;
123
124         regptr = (reg << 16) | chn;
125
126         spin_lock_irqsave(&emu->emu_lock, flags);
127         outl(regptr, emu->port + 0x20 + PTR);
128         outl(data, emu->port + 0x20 + DATA);
129         spin_unlock_irqrestore(&emu->emu_lock, flags);
130 }
131
132 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
133                                    unsigned int data)
134 {
135         unsigned int reset, set;
136         unsigned int reg, tmp;
137         int n, result;
138         if (emu->card_capabilities->ca0108_chip)
139                 reg = 0x3c; /* PTR20, reg 0x3c */
140         else {
141                 /* For other chip types the SPI register
142                  * is currently unknown. */
143                 return 1;
144         }
145         if (data > 0xffff) /* Only 16bit values allowed */
146                 return 1;
147
148         tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
149         reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
150         set = reset | 0x10000; /* Set xxx1xxxx */
151         snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
152         tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */
153         snd_emu10k1_ptr20_write(emu, reg, 0, set | data);
154         result = 1;
155         /* Wait for status bit to return to 0 */
156         for (n = 0; n < 100; n++) {
157                 udelay(10);
158                 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
159                 if (!(tmp & 0x10000)) {
160                         result = 0;
161                         break;
162                 }
163         }
164         if (result) /* Timed out */
165                 return 1;
166         snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
167         tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */
168         return 0;
169 }
170
171 /* The ADC does not support i2c read, so only write is implemented */
172 int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
173                                 u32 reg,
174                                 u32 value)
175 {
176         u32 tmp;
177         int timeout = 0;
178         int status;
179         int retry;
180         if ((reg > 0x7f) || (value > 0x1ff)) {
181                 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
182                 return -EINVAL;
183         }
184
185         tmp = reg << 25 | value << 16;
186         // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
187         /* Not sure what this I2C channel controls. */
188         /* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */
189
190         /* This controls the I2C connected to the WM8775 ADC Codec */
191         snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
192         tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */
193
194         for (retry = 0; retry < 10; retry++) {
195                 /* Send the data to i2c */
196                 //tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0);
197                 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
198                 tmp = 0;
199                 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
200                 snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
201
202                 /* Wait till the transaction ends */
203                 while (1) {
204                         udelay(10);
205                         status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
206                         // snd_printk("I2C:status=0x%x\n", status);
207                         timeout++;
208                         if ((status & I2C_A_ADC_START) == 0)
209                                 break;
210
211                         if (timeout > 1000) {
212                                 snd_printk("emu10k1:I2C:timeout status=0x%x\n", status);
213                                 break;
214                         }
215                 }
216                 //Read back and see if the transaction is successful
217                 if ((status & I2C_A_ADC_ABORT) == 0)
218                         break;
219         }
220
221         if (retry == 10) {
222                 snd_printk(KERN_ERR "Writing to ADC failed!\n");
223                 return -EINVAL;
224         }
225     
226         return 0;
227 }
228
229 int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value)
230 {
231         if (reg > 0x3f)
232                 return 1;
233         reg += 0x40; /* 0x40 upwards are registers. */
234         if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */
235                 return 1;
236         outl(reg, emu->port + A_IOCFG);
237         udelay(10);
238         outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
239         udelay(10);
240         outl(value, emu->port + A_IOCFG);
241         udelay(10);
242         outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
243
244         return 0;
245 }
246
247 int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value)
248 {
249         if (reg > 0x3f)
250                 return 1;
251         reg += 0x40; /* 0x40 upwards are registers. */
252         outl(reg, emu->port + A_IOCFG);
253         udelay(10);
254         outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
255         udelay(10);
256         *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
257
258         return 0;
259 }
260
261 /* Each Destination has one and only one Source,
262  * but one Source can feed any number of Destinations simultaneously.
263  */
264 int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src)
265 {
266         snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
267         snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
268         snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
269         snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
270
271         return 0;
272 }
273
274 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
275 {
276         unsigned long flags;
277         unsigned int enable;
278
279         spin_lock_irqsave(&emu->emu_lock, flags);
280         enable = inl(emu->port + INTE) | intrenb;
281         outl(enable, emu->port + INTE);
282         spin_unlock_irqrestore(&emu->emu_lock, flags);
283 }
284
285 void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
286 {
287         unsigned long flags;
288         unsigned int enable;
289
290         spin_lock_irqsave(&emu->emu_lock, flags);
291         enable = inl(emu->port + INTE) & ~intrenb;
292         outl(enable, emu->port + INTE);
293         spin_unlock_irqrestore(&emu->emu_lock, flags);
294 }
295
296 void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
297 {
298         unsigned long flags;
299         unsigned int val;
300
301         spin_lock_irqsave(&emu->emu_lock, flags);
302         /* voice interrupt */
303         if (voicenum >= 32) {
304                 outl(CLIEH << 16, emu->port + PTR);
305                 val = inl(emu->port + DATA);
306                 val |= 1 << (voicenum - 32);
307         } else {
308                 outl(CLIEL << 16, emu->port + PTR);
309                 val = inl(emu->port + DATA);
310                 val |= 1 << voicenum;
311         }
312         outl(val, emu->port + DATA);
313         spin_unlock_irqrestore(&emu->emu_lock, flags);
314 }
315
316 void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
317 {
318         unsigned long flags;
319         unsigned int val;
320
321         spin_lock_irqsave(&emu->emu_lock, flags);
322         /* voice interrupt */
323         if (voicenum >= 32) {
324                 outl(CLIEH << 16, emu->port + PTR);
325                 val = inl(emu->port + DATA);
326                 val &= ~(1 << (voicenum - 32));
327         } else {
328                 outl(CLIEL << 16, emu->port + PTR);
329                 val = inl(emu->port + DATA);
330                 val &= ~(1 << voicenum);
331         }
332         outl(val, emu->port + DATA);
333         spin_unlock_irqrestore(&emu->emu_lock, flags);
334 }
335
336 void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
337 {
338         unsigned long flags;
339
340         spin_lock_irqsave(&emu->emu_lock, flags);
341         /* voice interrupt */
342         if (voicenum >= 32) {
343                 outl(CLIPH << 16, emu->port + PTR);
344                 voicenum = 1 << (voicenum - 32);
345         } else {
346                 outl(CLIPL << 16, emu->port + PTR);
347                 voicenum = 1 << voicenum;
348         }
349         outl(voicenum, emu->port + DATA);
350         spin_unlock_irqrestore(&emu->emu_lock, flags);
351 }
352
353 void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
354 {
355         unsigned long flags;
356         unsigned int val;
357
358         spin_lock_irqsave(&emu->emu_lock, flags);
359         /* voice interrupt */
360         if (voicenum >= 32) {
361                 outl(HLIEH << 16, emu->port + PTR);
362                 val = inl(emu->port + DATA);
363                 val |= 1 << (voicenum - 32);
364         } else {
365                 outl(HLIEL << 16, emu->port + PTR);
366                 val = inl(emu->port + DATA);
367                 val |= 1 << voicenum;
368         }
369         outl(val, emu->port + DATA);
370         spin_unlock_irqrestore(&emu->emu_lock, flags);
371 }
372
373 void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
374 {
375         unsigned long flags;
376         unsigned int val;
377
378         spin_lock_irqsave(&emu->emu_lock, flags);
379         /* voice interrupt */
380         if (voicenum >= 32) {
381                 outl(HLIEH << 16, emu->port + PTR);
382                 val = inl(emu->port + DATA);
383                 val &= ~(1 << (voicenum - 32));
384         } else {
385                 outl(HLIEL << 16, emu->port + PTR);
386                 val = inl(emu->port + DATA);
387                 val &= ~(1 << voicenum);
388         }
389         outl(val, emu->port + DATA);
390         spin_unlock_irqrestore(&emu->emu_lock, flags);
391 }
392
393 void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
394 {
395         unsigned long flags;
396
397         spin_lock_irqsave(&emu->emu_lock, flags);
398         /* voice interrupt */
399         if (voicenum >= 32) {
400                 outl(HLIPH << 16, emu->port + PTR);
401                 voicenum = 1 << (voicenum - 32);
402         } else {
403                 outl(HLIPL << 16, emu->port + PTR);
404                 voicenum = 1 << voicenum;
405         }
406         outl(voicenum, emu->port + DATA);
407         spin_unlock_irqrestore(&emu->emu_lock, flags);
408 }
409
410 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
411 {
412         unsigned long flags;
413         unsigned int sol;
414
415         spin_lock_irqsave(&emu->emu_lock, flags);
416         /* voice interrupt */
417         if (voicenum >= 32) {
418                 outl(SOLEH << 16, emu->port + PTR);
419                 sol = inl(emu->port + DATA);
420                 sol |= 1 << (voicenum - 32);
421         } else {
422                 outl(SOLEL << 16, emu->port + PTR);
423                 sol = inl(emu->port + DATA);
424                 sol |= 1 << voicenum;
425         }
426         outl(sol, emu->port + DATA);
427         spin_unlock_irqrestore(&emu->emu_lock, flags);
428 }
429
430 void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
431 {
432         unsigned long flags;
433         unsigned int sol;
434
435         spin_lock_irqsave(&emu->emu_lock, flags);
436         /* voice interrupt */
437         if (voicenum >= 32) {
438                 outl(SOLEH << 16, emu->port + PTR);
439                 sol = inl(emu->port + DATA);
440                 sol &= ~(1 << (voicenum - 32));
441         } else {
442                 outl(SOLEL << 16, emu->port + PTR);
443                 sol = inl(emu->port + DATA);
444                 sol &= ~(1 << voicenum);
445         }
446         outl(sol, emu->port + DATA);
447         spin_unlock_irqrestore(&emu->emu_lock, flags);
448 }
449
450 void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)
451 {
452         volatile unsigned count;
453         unsigned int newtime = 0, curtime;
454
455         curtime = inl(emu->port + WC) >> 6;
456         while (wait-- > 0) {
457                 count = 0;
458                 while (count++ < 16384) {
459                         newtime = inl(emu->port + WC) >> 6;
460                         if (newtime != curtime)
461                                 break;
462                 }
463                 if (count >= 16384)
464                         break;
465                 curtime = newtime;
466         }
467 }
468
469 unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
470 {
471         struct snd_emu10k1 *emu = ac97->private_data;
472         unsigned long flags;
473         unsigned short val;
474
475         spin_lock_irqsave(&emu->emu_lock, flags);
476         outb(reg, emu->port + AC97ADDRESS);
477         val = inw(emu->port + AC97DATA);
478         spin_unlock_irqrestore(&emu->emu_lock, flags);
479         return val;
480 }
481
482 void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data)
483 {
484         struct snd_emu10k1 *emu = ac97->private_data;
485         unsigned long flags;
486
487         spin_lock_irqsave(&emu->emu_lock, flags);
488         outb(reg, emu->port + AC97ADDRESS);
489         outw(data, emu->port + AC97DATA);
490         spin_unlock_irqrestore(&emu->emu_lock, flags);
491 }
492
493 /*
494  *  convert rate to pitch
495  */
496
497 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)
498 {
499         static u32 logMagTable[128] = {
500                 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
501                 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
502                 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
503                 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
504                 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
505                 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
506                 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
507                 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
508                 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
509                 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
510                 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
511                 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
512                 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
513                 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
514                 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
515                 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
516         };
517         static char logSlopeTable[128] = {
518                 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
519                 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
520                 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
521                 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
522                 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
523                 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
524                 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
525                 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
526                 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
527                 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
528                 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
529                 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
530                 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
531                 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
532                 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
533                 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
534         };
535         int i;
536
537         if (rate == 0)
538                 return 0;       /* Bail out if no leading "1" */
539         rate *= 11185;          /* Scale 48000 to 0x20002380 */
540         for (i = 31; i > 0; i--) {
541                 if (rate & 0x80000000) {        /* Detect leading "1" */
542                         return (((unsigned int) (i - 15) << 20) +
543                                logMagTable[0x7f & (rate >> 24)] +
544                                         (0x7f & (rate >> 17)) *
545                                         logSlopeTable[0x7f & (rate >> 24)]);
546                 }
547                 rate <<= 1;
548         }
549
550         return 0;               /* Should never reach this point */
551 }
552