~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/irda/qos.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*********************************************************************
  2  *                                
  3  * Filename:      qos.c
  4  * Version:       1.0
  5  * Description:   IrLAP QoS parameter negotiation
  6  * Status:        Stable
  7  * Author:        Dag Brattli <dagb@cs.uit.no>
  8  * Created at:    Tue Sep  9 00:00:26 1997
  9  * Modified at:   Sun Jan 30 14:29:16 2000
 10  * Modified by:   Dag Brattli <dagb@cs.uit.no>
 11  * 
 12  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
 13  *     All Rights Reserved.
 14  *     
 15  *     This program is free software; you can redistribute it and/or 
 16  *     modify it under the terms of the GNU General Public License as 
 17  *     published by the Free Software Foundation; either version 2 of 
 18  *     the License, or (at your option) any later version.
 19  * 
 20  *     This program is distributed in the hope that it will be useful,
 21  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 22  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 23  *     GNU General Public License for more details.
 24  * 
 25  *     You should have received a copy of the GNU General Public License 
 26  *     along with this program; if not, write to the Free Software 
 27  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 28  *     MA 02111-1307 USA
 29  *     
 30  ********************************************************************/
 31 
 32 #include <linux/config.h>
 33 #include <asm/byteorder.h>
 34 
 35 #include <net/irda/irda.h>
 36 #include <net/irda/parameters.h>
 37 #include <net/irda/qos.h>
 38 #include <net/irda/irlap.h>
 39 #ifdef CONFIG_IRDA_COMPRESSION
 40 #include <net/irda/irlap_comp.h>
 41 #include "../../drivers/net/zlib.h"
 42 
 43 #define CI_BZIP2  27 /* Random pick */
 44 #endif
 45 
 46 /*
 47  * Maximum values of the baud rate we negociate with the other end.
 48  * Most often, you don't have to change that, because Linux-IrDA will
 49  * use the maximum offered by the link layer, which usually works fine.
 50  * In some very rare cases, you may want to limit it to lower speeds...
 51  */
 52 int sysctl_max_baud_rate = 16000000;
 53 /*
 54  * Maximum value of the lap disconnect timer we negociate with the other end.
 55  * Most often, the value below represent the best compromise, but some user
 56  * may want to keep the LAP alive longuer or shorter in case of link failure.
 57  * Remember that the threshold time (early warning) is fixed to 3s...
 58  */
 59 int sysctl_max_inactive_time = 12;
 60 
 61 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
 62 static int irlap_param_link_disconnect(void *instance, irda_param_t *parm, 
 63                                        int get);
 64 static int irlap_param_max_turn_time(void *instance, irda_param_t *param, 
 65                                      int get);
 66 static int irlap_param_data_size(void *instance, irda_param_t *param, int get);
 67 static int irlap_param_window_size(void *instance, irda_param_t *param, 
 68                                    int get);
 69 static int irlap_param_additional_bofs(void *instance, irda_param_t *parm, 
 70                                        int get);
 71 static int irlap_param_min_turn_time(void *instance, irda_param_t *param, 
 72                                      int get);
 73 static int value_index(__u32 value, __u32 *array, int size);
 74 static __u32 byte_value(__u8 byte, __u32 *array);
 75 static __u32 index_value(int index, __u32 *array);
 76 static int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field);
 77 
 78 __u32 min_turn_times[]  = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
 79 __u32 baud_rates[]      = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 
 80                             1152000, 4000000, 16000000 };           /* bps */
 81 __u32 data_sizes[]      = { 64, 128, 256, 512, 1024, 2048 };        /* bytes */
 82 __u32 add_bofs[]        = { 48, 24, 12, 5, 3, 2, 1, 0 };            /* bytes */
 83 __u32 max_turn_times[]  = { 500, 250, 100, 50 };                    /* ms */
 84 __u32 link_disc_times[] = { 3, 8, 12, 16, 20, 25, 30, 40 };         /* secs */
 85 
 86 #ifdef CONFIG_IRDA_COMPRESSION
 87 __u32 compressions[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
 88 #endif
 89 
 90 __u32 max_line_capacities[10][4] = {
 91        /* 500 ms     250 ms  100 ms  50 ms (max turn time) */
 92         {    100,      0,      0,     0 }, /*     2400 bps */
 93         {    400,      0,      0,     0 }, /*     9600 bps */
 94         {    800,      0,      0,     0 }, /*    19200 bps */
 95         {   1600,      0,      0,     0 }, /*    38400 bps */
 96         {   2360,      0,      0,     0 }, /*    57600 bps */
 97         {   4800,   2400,    960,   480 }, /*   115200 bps */
 98         {  28800,  11520,   5760,  2880 }, /*   576000 bps */
 99         {  57600,  28800,  11520,  5760 }, /*  1152000 bps */
100         { 200000, 100000,  40000, 20000 }, /*  4000000 bps */
101         { 800000, 400000, 160000, 80000 }, /* 16000000 bps */
102 };
103 
104 static pi_minor_info_t pi_minor_call_table_type_0[] = {
105         { NULL, 0 },
106 /* 01 */{ irlap_param_baud_rate,       PV_INTEGER | PV_LITTLE_ENDIAN },
107         { NULL, 0 },
108         { NULL, 0 },
109         { NULL, 0 },
110         { NULL, 0 },
111         { NULL, 0 },
112         { NULL, 0 },
113 /* 08 */{ irlap_param_link_disconnect, PV_INT_8_BITS }
114 };
115 
116 static pi_minor_info_t pi_minor_call_table_type_1[] = {
117         { NULL, 0 },
118         { NULL, 0 },
119 /* 82 */{ irlap_param_max_turn_time,   PV_INT_8_BITS },
120 /* 83 */{ irlap_param_data_size,       PV_INT_8_BITS },
121 /* 84 */{ irlap_param_window_size,     PV_INT_8_BITS },
122 /* 85 */{ irlap_param_additional_bofs, PV_INT_8_BITS },
123 /* 86 */{ irlap_param_min_turn_time,   PV_INT_8_BITS },
124 };
125 
126 static pi_major_info_t pi_major_call_table[] = {
127         { pi_minor_call_table_type_0, 9 },
128         { pi_minor_call_table_type_1, 7 },
129 };
130 
131 static pi_param_info_t irlap_param_info = { pi_major_call_table, 2, 0x7f, 7 };
132 
133 /*
134  * Function irda_qos_compute_intersection (qos, new)
135  *
136  *    Compute the intersection of the old QoS capabilites with new ones
137  *
138  */
139 void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new)
140 {
141         ASSERT(qos != NULL, return;);
142         ASSERT(new != NULL, return;);
143 
144         /* Apply */
145         qos->baud_rate.bits       &= new->baud_rate.bits;
146         qos->window_size.bits     &= new->window_size.bits;
147         qos->min_turn_time.bits   &= new->min_turn_time.bits;
148         qos->max_turn_time.bits   &= new->max_turn_time.bits;
149         qos->data_size.bits       &= new->data_size.bits;
150         qos->link_disc_time.bits  &= new->link_disc_time.bits;
151         qos->additional_bofs.bits &= new->additional_bofs.bits;
152 
153 #ifdef CONFIG_IRDA_COMPRESSION
154         qos->compression.bits     &= new->compression.bits;
155 #endif
156 
157         irda_qos_bits_to_value(qos);
158 }
159 
160 /*
161  * Function irda_init_max_qos_capabilies (qos)
162  *
163  *    The purpose of this function is for layers and drivers to be able to
164  *    set the maximum QoS possible and then "and in" their own limitations
165  * 
166  */
167 void irda_init_max_qos_capabilies(struct qos_info *qos)
168 {
169         int i;
170         /* 
171          *  These are the maximum supported values as specified on pages
172          *  39-43 in IrLAP
173          */
174 
175         /* Use sysctl to set some configurable values... */
176         /* Set configured max speed */
177         i = value_lower_bits(sysctl_max_baud_rate, baud_rates, 10,
178                              &qos->baud_rate.bits);
179         sysctl_max_baud_rate = index_value(i, baud_rates);
180 
181         /* Set configured max disc time */
182         i = value_lower_bits(sysctl_max_inactive_time, link_disc_times, 8,
183                              &qos->link_disc_time.bits);
184         sysctl_max_inactive_time = index_value(i, link_disc_times);
185 
186         /* LSB is first byte, MSB is second byte */
187         qos->baud_rate.bits    &= 0x03ff;
188 
189         qos->window_size.bits     = 0x7f;
190         qos->min_turn_time.bits   = 0xff;
191         qos->max_turn_time.bits   = 0x0f;
192         qos->data_size.bits       = 0x3f;
193         qos->link_disc_time.bits &= 0xff;
194         qos->additional_bofs.bits = 0xff;
195 
196 #ifdef CONFIG_IRDA_COMPRESSION  
197         qos->compression.bits     = 0x03;
198 #endif
199 }
200 
201 /*
202  * Function irlap_adjust_qos_settings (qos)
203  *
204  *     Adjust QoS settings in case some values are not possible to use because
205  *     of other settings
206  */
207 void irlap_adjust_qos_settings(struct qos_info *qos)
208 {
209         __u32 line_capacity;
210         int index;
211 
212         IRDA_DEBUG(2, __FUNCTION__ "()\n");
213 
214         /* 
215          * Not allowed to use a max turn time less than 500 ms if the baudrate
216          * is less than 115200
217          */
218         if ((qos->baud_rate.value < 115200) && 
219             (qos->max_turn_time.value < 500))
220         {
221                 IRDA_DEBUG(0, __FUNCTION__ 
222                            "(), adjusting max turn time from %d to 500 ms\n",
223                            qos->max_turn_time.value);
224                 qos->max_turn_time.value = 500;
225         }
226         
227         /*
228          * The data size must be adjusted according to the baud rate and max 
229          * turn time
230          */
231         index = value_index(qos->data_size.value, data_sizes, 6);
232         line_capacity = irlap_max_line_capacity(qos->baud_rate.value, 
233                                                 qos->max_turn_time.value);
234 
235 #ifdef CONFIG_IRDA_DYNAMIC_WINDOW
236         while ((qos->data_size.value > line_capacity) && (index > 0)) {
237                 qos->data_size.value = data_sizes[index--];
238                 IRDA_DEBUG(2, __FUNCTION__ 
239                            "(), redusing data size to %d\n",
240                            qos->data_size.value);
241         }
242 #else /* Use method descibed in section 6.6.11 of IrLAP */
243         while (irlap_requested_line_capacity(qos) > line_capacity) {
244                 ASSERT(index != 0, return;);
245 
246                 /* Must be able to send at least one frame */
247                 if (qos->window_size.value > 1) {
248                         qos->window_size.value--;
249                         IRDA_DEBUG(2, __FUNCTION__ 
250                                    "(), redusing window size to %d\n",
251                                    qos->window_size.value);
252                 } else if (index > 1) {
253                         qos->data_size.value = data_sizes[index--];
254                         IRDA_DEBUG(2, __FUNCTION__ 
255                                    "(), redusing data size to %d\n",
256                                    qos->data_size.value);
257                 } else {
258                         WARNING(__FUNCTION__ "(), nothing more we can do!\n");
259                 }
260         }
261 #endif CONFIG_IRDA_DYNAMIC_WINDOW
262 }
263 
264 /*
265  * Function irlap_negotiate (qos_device, qos_session, skb)
266  *
267  *    Negotiate QoS values, not really that much negotiation :-)
268  *    We just set the QoS capabilities for the peer station
269  *
270  */
271 int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb) 
272 {
273         int ret;
274 #ifdef CONFIG_IRDA_COMPRESSION
275         int comp_seen = FALSE;
276 #endif
277         ret = irda_param_extract_all(self, skb->data, skb->len, 
278                                      &irlap_param_info);
279         
280 #ifdef CONFIG_IRDA_COMPRESSION
281         if (!comp_seen) {
282                 IRDA_DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n");
283                 self->qos_tx.compression.bits = 0x00;
284                 self->qos_rx.compression.bits = 0x00;
285         }
286 #endif
287 
288         /* Convert the negotiated bits to values */
289         irda_qos_bits_to_value(&self->qos_tx);
290         irda_qos_bits_to_value(&self->qos_rx);
291 
292         irlap_adjust_qos_settings(&self->qos_tx);
293 
294         IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n", 
295                    self->qos_tx.baud_rate.value);
296         IRDA_DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
297                    self->qos_tx.data_size.value);
298         IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n", 
299                    self->qos_tx.window_size.value);
300         IRDA_DEBUG(2, "Setting XBOFS to %d\n", 
301                    self->qos_tx.additional_bofs.value);
302         IRDA_DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
303                    self->qos_tx.max_turn_time.value);
304         IRDA_DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
305                    self->qos_tx.min_turn_time.value);
306         IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n", 
307                    self->qos_tx.link_disc_time.value);
308 #ifdef CONFIG_IRDA_COMPRESSION
309         IRDA_DEBUG(2, "Setting COMPRESSION to %d\n", 
310                    self->qos_tx.compression.value);
311 #endif  
312         return ret;
313 }
314 
315 /*
316  * Function irlap_insert_negotiation_params (qos, fp)
317  *
318  *    Insert QoS negotiaion pararameters into frame
319  *
320  */
321 int irlap_insert_qos_negotiation_params(struct irlap_cb *self, 
322                                         struct sk_buff *skb)
323 {
324         int ret;
325 
326         /* Insert data rate */
327         ret = irda_param_insert(self, PI_BAUD_RATE, skb->tail, 
328                                 skb_tailroom(skb), &irlap_param_info);
329         if (ret < 0)
330                 return ret;
331         skb_put(skb, ret);
332 
333         /* Insert max turnaround time */
334         ret = irda_param_insert(self, PI_MAX_TURN_TIME, skb->tail, 
335                                 skb_tailroom(skb), &irlap_param_info);
336         if (ret < 0)
337                 return ret;
338         skb_put(skb, ret);
339 
340         /* Insert data size */
341         ret = irda_param_insert(self, PI_DATA_SIZE, skb->tail, 
342                                 skb_tailroom(skb), &irlap_param_info);
343         if (ret < 0)
344                 return ret;
345         skb_put(skb, ret);
346 
347         /* Insert window size */
348         ret = irda_param_insert(self, PI_WINDOW_SIZE, skb->tail, 
349                                 skb_tailroom(skb), &irlap_param_info);
350         if (ret < 0)
351                 return ret;
352         skb_put(skb, ret);
353 
354         /* Insert additional BOFs */
355         ret = irda_param_insert(self, PI_ADD_BOFS, skb->tail, 
356                                 skb_tailroom(skb), &irlap_param_info);
357         if (ret < 0)
358                 return ret;
359         skb_put(skb, ret);
360 
361         /* Insert minimum turnaround time */
362         ret = irda_param_insert(self, PI_MIN_TURN_TIME, skb->tail, 
363                                 skb_tailroom(skb), &irlap_param_info);
364         if (ret < 0)
365                 return ret;
366         skb_put(skb, ret);
367 
368         /* Insert link disconnect/threshold time */
369         ret = irda_param_insert(self, PI_LINK_DISC, skb->tail, 
370                                 skb_tailroom(skb), &irlap_param_info);
371         if (ret < 0)
372                 return ret;
373         skb_put(skb, ret);
374 
375         return 0;
376 }
377 
378 /*
379  * Function irlap_param_baud_rate (instance, param, get)
380  *
381  *    Negotiate data-rate
382  *
383  */
384 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get)
385 {
386         __u16 final;
387 
388         struct irlap_cb *self = (struct irlap_cb *) instance;
389 
390         ASSERT(self != NULL, return -1;);
391         ASSERT(self->magic == LAP_MAGIC, return -1;);
392 
393         if (get) {
394                 param->pv.i = self->qos_rx.baud_rate.bits;
395                 IRDA_DEBUG(2, __FUNCTION__ "(), baud rate = 0x%02x\n", 
396                            param->pv.i);                
397         } else {
398                 /* 
399                  *  Stations must agree on baud rate, so calculate
400                  *  intersection 
401                  */
402                 IRDA_DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", param->pv.s);
403                 final = param->pv.s & self->qos_rx.baud_rate.bits;
404 
405                 IRDA_DEBUG(2, "Final BAUD_RATE: 0x%04x\n", final);
406                 self->qos_tx.baud_rate.bits = final;
407                 self->qos_rx.baud_rate.bits = final;
408         }
409 
410         return 0;
411 }
412 
413 /*
414  * Function irlap_param_link_disconnect (instance, param, get)
415  *
416  *    Negotiate link disconnect/threshold time. 
417  *
418  */
419 static int irlap_param_link_disconnect(void *instance, irda_param_t *param, 
420                                        int get)
421 {
422         __u16 final;
423         
424         struct irlap_cb *self = (struct irlap_cb *) instance;
425         
426         ASSERT(self != NULL, return -1;);
427         ASSERT(self->magic == LAP_MAGIC, return -1;);
428         
429         if (get)
430                 param->pv.b = self->qos_rx.link_disc_time.bits;
431         else {
432                 /*  
433                  *  Stations must agree on link disconnect/threshold 
434                  *  time.
435                  */
436                 IRDA_DEBUG(2, "LINK_DISC: %02x\n", param->pv.b);
437                 final = param->pv.b & self->qos_rx.link_disc_time.bits;
438 
439                 IRDA_DEBUG(2, "Final LINK_DISC: %02x\n", final);
440                 self->qos_tx.link_disc_time.bits = final;
441                 self->qos_rx.link_disc_time.bits = final;
442         }
443         return 0;
444 }
445 
446 /*
447  * Function irlap_param_max_turn_time (instance, param, get)
448  *
449  *    Negotiate the maximum turnaround time. This is a type 1 parameter and
450  *    will be negotiated independently for each station
451  *
452  */
453 static int irlap_param_max_turn_time(void *instance, irda_param_t *param, 
454                                      int get)
455 {
456         struct irlap_cb *self = (struct irlap_cb *) instance;
457         
458         ASSERT(self != NULL, return -1;);
459         ASSERT(self->magic == LAP_MAGIC, return -1;);
460         
461         if (get)
462                 param->pv.b = self->qos_rx.max_turn_time.bits;
463         else
464                 self->qos_tx.max_turn_time.bits = param->pv.b;
465 
466         return 0;
467 }
468 
469 /*
470  * Function irlap_param_data_size (instance, param, get)
471  *
472  *    Negotiate the data size. This is a type 1 parameter and
473  *    will be negotiated independently for each station
474  *
475  */
476 static int irlap_param_data_size(void *instance, irda_param_t *param, int get)
477 {
478         struct irlap_cb *self = (struct irlap_cb *) instance;
479         
480         ASSERT(self != NULL, return -1;);
481         ASSERT(self->magic == LAP_MAGIC, return -1;);
482         
483         if (get)
484                 param->pv.b = self->qos_rx.data_size.bits;
485         else
486                 self->qos_tx.data_size.bits = param->pv.b;
487 
488         return 0;
489 }
490 
491 /*
492  * Function irlap_param_window_size (instance, param, get)
493  *
494  *    Negotiate the window size. This is a type 1 parameter and
495  *    will be negotiated independently for each station
496  *
497  */
498 static int irlap_param_window_size(void *instance, irda_param_t *param, 
499                                    int get)
500 {
501         struct irlap_cb *self = (struct irlap_cb *) instance;
502         
503         ASSERT(self != NULL, return -1;);
504         ASSERT(self->magic == LAP_MAGIC, return -1;);
505         
506         if (get)
507                 param->pv.b = self->qos_rx.window_size.bits;
508         else
509                 self->qos_tx.window_size.bits = param->pv.b;
510 
511         return 0;
512 }
513 
514 /*
515  * Function irlap_param_additional_bofs (instance, param, get)
516  *
517  *    Negotiate additional BOF characters. This is a type 1 parameter and
518  *    will be negotiated independently for each station.
519  */
520 static int irlap_param_additional_bofs(void *instance, irda_param_t *param, int get)
521 {
522         struct irlap_cb *self = (struct irlap_cb *) instance;
523         
524         ASSERT(self != NULL, return -1;);
525         ASSERT(self->magic == LAP_MAGIC, return -1;);
526         
527         if (get)
528                 param->pv.b = self->qos_rx.additional_bofs.bits;
529         else
530                 self->qos_tx.additional_bofs.bits = param->pv.b;
531 
532         return 0;
533 }
534 
535 /*
536  * Function irlap_param_min_turn_time (instance, param, get)
537  *
538  *    Negotiate the minimum turn around time. This is a type 1 parameter and
539  *    will be negotiated independently for each station
540  */
541 static int irlap_param_min_turn_time(void *instance, irda_param_t *param, 
542                                      int get)
543 {
544         struct irlap_cb *self = (struct irlap_cb *) instance;
545         
546         ASSERT(self != NULL, return -1;);
547         ASSERT(self->magic == LAP_MAGIC, return -1;);
548         
549         if (get)
550                 param->pv.b = self->qos_rx.min_turn_time.bits;
551         else
552                 self->qos_tx.min_turn_time.bits = param->pv.b;
553 
554         return 0;
555 }
556 
557 /*
558  * Function irlap_max_line_capacity (speed, max_turn_time, min_turn_time)
559  *
560  *    Calculate the maximum line capacity
561  *
562  */
563 __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
564 {
565         __u32 line_capacity;
566         int i,j;
567 
568         IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, max_turn_time=%d\n",
569                    speed, max_turn_time);
570 
571         i = value_index(speed, baud_rates, 10);
572         j = value_index(max_turn_time, max_turn_times, 4);
573 
574         ASSERT(((i >=0) && (i <=10)), return 0;);
575         ASSERT(((j >=0) && (j <=4)), return 0;);
576 
577         line_capacity = max_line_capacities[i][j];
578 
579         IRDA_DEBUG(2, __FUNCTION__ "(), line capacity=%d bytes\n", 
580                    line_capacity);
581         
582         return line_capacity;
583 }
584 
585 __u32 irlap_requested_line_capacity(struct qos_info *qos)
586 {       __u32 line_capacity;
587         
588         line_capacity = qos->window_size.value * 
589                 (qos->data_size.value + 6 + qos->additional_bofs.value) +
590                 irlap_min_turn_time_in_bytes(qos->baud_rate.value, 
591                                              qos->min_turn_time.value);
592         
593         IRDA_DEBUG(2, __FUNCTION__ "(), requested line capacity=%d\n",
594                    line_capacity);
595         
596         return line_capacity;                                     
597 }
598 
599 __u32 irlap_min_turn_time_in_bytes(__u32 speed, __u32 min_turn_time)
600 {
601         __u32 bytes;
602         
603         bytes = speed * min_turn_time / 10000000;
604         
605         return bytes;
606 }
607 
608 static __u32 byte_value(__u8 byte, __u32 *array) 
609 {
610         int index;
611 
612         ASSERT(array != NULL, return -1;);
613 
614         index = msb_index(byte);
615 
616         return index_value(index, array);
617 }
618 
619 /*
620  * Function msb_index (word)
621  *
622  *    Returns index to most significant bit (MSB) in word
623  *
624  */
625 int msb_index (__u16 word) 
626 {
627         __u16 msb = 0x8000;
628         int index = 15;   /* Current MSB */
629         
630         while (msb) {
631                 if (word & msb)
632                         break;   /* Found it! */
633                 msb >>=1;
634                 index--;
635         }
636         return index;
637 }
638 
639 /*
640  * Function value_index (value, array, size)
641  *
642  *    Returns the index to the value in the specified array
643  */
644 static int value_index(__u32 value, __u32 *array, int size)
645 {
646         int i;
647         
648         for (i=0; i < size; i++)
649                 if (array[i] == value)
650                         break;
651         return i;
652 }
653 
654 /*
655  * Function index_value (index, array)
656  *
657  *    Returns value to index in array, easy!
658  *
659  */
660 static __u32 index_value(int index, __u32 *array) 
661 {
662         return array[index];
663 }
664 
665 /*
666  * Function value_lower_bits (value, array)
667  *
668  *    Returns a bit field marking all possibility lower than value.
669  *    We may need a "value_higher_bits" in the future...
670  */
671 static int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field)
672 {
673         int     i;
674         __u16   mask = 0x1;
675         __u16   result = 0x0;
676 
677         for (i=0; i < size; i++) {
678                 /* Add the current value to the bit field, shift mask */
679                 result |= mask;
680                 mask <<= 1;
681                 /* Finished ? */
682                 if (array[i] >= value)
683                         break;
684         }
685         /* Send back a valid index */
686         if(i >= size)
687           i = size - 1; /* Last item */
688         *field = result;
689         return i;
690 }
691 
692 void irda_qos_bits_to_value(struct qos_info *qos)
693 {
694         int index;
695 
696         ASSERT(qos != NULL, return;);
697         
698         index = msb_index(qos->baud_rate.bits);
699         qos->baud_rate.value = baud_rates[index];
700 
701         index = msb_index(qos->data_size.bits);
702         qos->data_size.value = data_sizes[index];
703 
704         index = msb_index(qos->window_size.bits);
705         qos->window_size.value = index+1;
706 
707         index = msb_index(qos->min_turn_time.bits);
708         qos->min_turn_time.value = min_turn_times[index];
709         
710         index = msb_index(qos->max_turn_time.bits);
711         qos->max_turn_time.value = max_turn_times[index];
712 
713         index = msb_index(qos->link_disc_time.bits);
714         qos->link_disc_time.value = link_disc_times[index];
715         
716         index = msb_index(qos->additional_bofs.bits);
717         qos->additional_bofs.value = add_bofs[index];
718 
719 #ifdef CONFIG_IRDA_COMPRESSION
720         index = msb_index(qos->compression.bits);
721         if (index >= 0)
722                 qos->compression.value = compressions[index];
723         else 
724                 qos->compression.value = 0;
725 #endif
726 }
727 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.