Commit d3e9db933f416c9f1c04df4834d36e2315952e42
1 parent
01dbbdf1
initial support for up to 255 CPUs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1707 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
160 additions
and
100 deletions
hw/apic.c
| @@ -60,6 +60,9 @@ | @@ -60,6 +60,9 @@ | ||
| 60 | 60 | ||
| 61 | #define APIC_SV_ENABLE (1 << 8) | 61 | #define APIC_SV_ENABLE (1 << 8) |
| 62 | 62 | ||
| 63 | +#define MAX_APICS 255 | ||
| 64 | +#define MAX_APIC_WORDS 8 | ||
| 65 | + | ||
| 63 | typedef struct APICState { | 66 | typedef struct APICState { |
| 64 | CPUState *cpu_env; | 67 | CPUState *cpu_env; |
| 65 | uint32_t apicbase; | 68 | uint32_t apicbase; |
| @@ -81,8 +84,6 @@ typedef struct APICState { | @@ -81,8 +84,6 @@ typedef struct APICState { | ||
| 81 | uint32_t initial_count; | 84 | uint32_t initial_count; |
| 82 | int64_t initial_count_load_time, next_time; | 85 | int64_t initial_count_load_time, next_time; |
| 83 | QEMUTimer *timer; | 86 | QEMUTimer *timer; |
| 84 | - | ||
| 85 | - struct APICState *next_apic; | ||
| 86 | } APICState; | 87 | } APICState; |
| 87 | 88 | ||
| 88 | struct IOAPICState { | 89 | struct IOAPICState { |
| @@ -94,14 +95,95 @@ struct IOAPICState { | @@ -94,14 +95,95 @@ struct IOAPICState { | ||
| 94 | }; | 95 | }; |
| 95 | 96 | ||
| 96 | static int apic_io_memory; | 97 | static int apic_io_memory; |
| 97 | -static APICState *first_local_apic = NULL; | 98 | +static APICState *local_apics[MAX_APICS + 1]; |
| 98 | static int last_apic_id = 0; | 99 | static int last_apic_id = 0; |
| 99 | 100 | ||
| 100 | static void apic_init_ipi(APICState *s); | 101 | static void apic_init_ipi(APICState *s); |
| 101 | static void apic_set_irq(APICState *s, int vector_num, int trigger_mode); | 102 | static void apic_set_irq(APICState *s, int vector_num, int trigger_mode); |
| 102 | static void apic_update_irq(APICState *s); | 103 | static void apic_update_irq(APICState *s); |
| 103 | 104 | ||
| 104 | -static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | 105 | +/* Find first bit starting from msb. Return 0 if value = 0 */ |
| 106 | +static int fls_bit(uint32_t value) | ||
| 107 | +{ | ||
| 108 | + unsigned int ret = 0; | ||
| 109 | + | ||
| 110 | +#if defined(HOST_I386) | ||
| 111 | + __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value)); | ||
| 112 | + return ret; | ||
| 113 | +#else | ||
| 114 | + if (value > 0xffff) | ||
| 115 | + value >>= 16, ret = 16; | ||
| 116 | + if (value > 0xff) | ||
| 117 | + value >>= 8, ret += 8; | ||
| 118 | + if (value > 0xf) | ||
| 119 | + value >>= 4, ret += 4; | ||
| 120 | + if (value > 0x3) | ||
| 121 | + value >>= 2, ret += 2; | ||
| 122 | + return ret + (value >> 1); | ||
| 123 | +#endif | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +/* Find first bit starting from lsb. Return 0 if value = 0 */ | ||
| 127 | +static int ffs_bit(uint32_t value) | ||
| 128 | +{ | ||
| 129 | + unsigned int ret = 0; | ||
| 130 | + | ||
| 131 | +#if defined(HOST_I386) | ||
| 132 | + __asm__ __volatile__ ("bsf %1, %0\n" : "+r" (ret) : "rm" (value)); | ||
| 133 | + return ret; | ||
| 134 | +#else | ||
| 135 | + if (!value) | ||
| 136 | + return 0; | ||
| 137 | + if (!(value & 0xffff)) | ||
| 138 | + value >>= 16, ret = 16; | ||
| 139 | + if (!(value & 0xff)) | ||
| 140 | + value >>= 8, ret += 8; | ||
| 141 | + if (!(value & 0xf)) | ||
| 142 | + value >>= 4, ret += 4; | ||
| 143 | + if (!(value & 0x3)) | ||
| 144 | + value >>= 2, ret += 2; | ||
| 145 | + if (!(value & 0x1)) | ||
| 146 | + ret++; | ||
| 147 | + return ret; | ||
| 148 | +#endif | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +static inline void set_bit(uint32_t *tab, int index) | ||
| 152 | +{ | ||
| 153 | + int i, mask; | ||
| 154 | + i = index >> 5; | ||
| 155 | + mask = 1 << (index & 0x1f); | ||
| 156 | + tab[i] |= mask; | ||
| 157 | +} | ||
| 158 | + | ||
| 159 | +static inline void reset_bit(uint32_t *tab, int index) | ||
| 160 | +{ | ||
| 161 | + int i, mask; | ||
| 162 | + i = index >> 5; | ||
| 163 | + mask = 1 << (index & 0x1f); | ||
| 164 | + tab[i] &= ~mask; | ||
| 165 | +} | ||
| 166 | + | ||
| 167 | +#define foreach_apic(apic, deliver_bitmask, code) \ | ||
| 168 | +{\ | ||
| 169 | + int __i, __j, __mask;\ | ||
| 170 | + for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\ | ||
| 171 | + __mask = deliver_bitmask[__i];\ | ||
| 172 | + if (__mask) {\ | ||
| 173 | + for(__j = 0; __j < 32; __j++) {\ | ||
| 174 | + if (__mask & (1 << __j)) {\ | ||
| 175 | + apic = local_apics[__i * 32 + __j];\ | ||
| 176 | + if (apic) {\ | ||
| 177 | + code;\ | ||
| 178 | + }\ | ||
| 179 | + }\ | ||
| 180 | + }\ | ||
| 181 | + }\ | ||
| 182 | + }\ | ||
| 183 | +} | ||
| 184 | + | ||
| 185 | +static void apic_bus_deliver(const uint32_t *deliver_bitmask, | ||
| 186 | + uint8_t delivery_mode, | ||
| 105 | uint8_t vector_num, uint8_t polarity, | 187 | uint8_t vector_num, uint8_t polarity, |
| 106 | uint8_t trigger_mode) | 188 | uint8_t trigger_mode) |
| 107 | { | 189 | { |
| @@ -110,13 +192,23 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | @@ -110,13 +192,23 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | ||
| 110 | switch (delivery_mode) { | 192 | switch (delivery_mode) { |
| 111 | case APIC_DM_LOWPRI: | 193 | case APIC_DM_LOWPRI: |
| 112 | /* XXX: search for focus processor, arbitration */ | 194 | /* XXX: search for focus processor, arbitration */ |
| 113 | - if (deliver_bitmask) { | ||
| 114 | - uint32_t m = 1; | ||
| 115 | - while ((deliver_bitmask & m) == 0) | ||
| 116 | - m <<= 1; | ||
| 117 | - deliver_bitmask = m; | 195 | + { |
| 196 | + int i, d; | ||
| 197 | + d = -1; | ||
| 198 | + for(i = 0; i < MAX_APIC_WORDS; i++) { | ||
| 199 | + if (deliver_bitmask[i]) { | ||
| 200 | + d = i * 32 + ffs_bit(deliver_bitmask[i]); | ||
| 201 | + break; | ||
| 202 | + } | ||
| 203 | + } | ||
| 204 | + if (d >= 0) { | ||
| 205 | + apic_iter = local_apics[d]; | ||
| 206 | + if (apic_iter) { | ||
| 207 | + apic_set_irq(apic_iter, vector_num, trigger_mode); | ||
| 208 | + } | ||
| 209 | + } | ||
| 118 | } | 210 | } |
| 119 | - break; | 211 | + return; |
| 120 | 212 | ||
| 121 | case APIC_DM_FIXED: | 213 | case APIC_DM_FIXED: |
| 122 | break; | 214 | break; |
| @@ -127,11 +219,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | @@ -127,11 +219,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | ||
| 127 | 219 | ||
| 128 | case APIC_DM_INIT: | 220 | case APIC_DM_INIT: |
| 129 | /* normal INIT IPI sent to processors */ | 221 | /* normal INIT IPI sent to processors */ |
| 130 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
| 131 | - apic_iter = apic_iter->next_apic) { | ||
| 132 | - if (deliver_bitmask & (1 << apic_iter->id)) | ||
| 133 | - apic_init_ipi(apic_iter); | ||
| 134 | - } | 222 | + foreach_apic(apic_iter, deliver_bitmask, |
| 223 | + apic_init_ipi(apic_iter) ); | ||
| 135 | return; | 224 | return; |
| 136 | 225 | ||
| 137 | case APIC_DM_EXTINT: | 226 | case APIC_DM_EXTINT: |
| @@ -142,11 +231,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | @@ -142,11 +231,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | ||
| 142 | return; | 231 | return; |
| 143 | } | 232 | } |
| 144 | 233 | ||
| 145 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
| 146 | - apic_iter = apic_iter->next_apic) { | ||
| 147 | - if (deliver_bitmask & (1 << apic_iter->id)) | ||
| 148 | - apic_set_irq(apic_iter, vector_num, trigger_mode); | ||
| 149 | - } | 234 | + foreach_apic(apic_iter, deliver_bitmask, |
| 235 | + apic_set_irq(apic_iter, vector_num, trigger_mode) ); | ||
| 150 | } | 236 | } |
| 151 | 237 | ||
| 152 | void cpu_set_apic_base(CPUState *env, uint64_t val) | 238 | void cpu_set_apic_base(CPUState *env, uint64_t val) |
| @@ -187,42 +273,6 @@ uint8_t cpu_get_apic_tpr(CPUX86State *env) | @@ -187,42 +273,6 @@ uint8_t cpu_get_apic_tpr(CPUX86State *env) | ||
| 187 | return s->tpr >> 4; | 273 | return s->tpr >> 4; |
| 188 | } | 274 | } |
| 189 | 275 | ||
| 190 | -static int fls_bit(int value) | ||
| 191 | -{ | ||
| 192 | - unsigned int ret = 0; | ||
| 193 | - | ||
| 194 | -#ifdef HOST_I386 | ||
| 195 | - __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value)); | ||
| 196 | - return ret; | ||
| 197 | -#else | ||
| 198 | - if (value > 0xffff) | ||
| 199 | - value >>= 16, ret = 16; | ||
| 200 | - if (value > 0xff) | ||
| 201 | - value >>= 8, ret += 8; | ||
| 202 | - if (value > 0xf) | ||
| 203 | - value >>= 4, ret += 4; | ||
| 204 | - if (value > 0x3) | ||
| 205 | - value >>= 2, ret += 2; | ||
| 206 | - return ret + (value >> 1); | ||
| 207 | -#endif | ||
| 208 | -} | ||
| 209 | - | ||
| 210 | -static inline void set_bit(uint32_t *tab, int index) | ||
| 211 | -{ | ||
| 212 | - int i, mask; | ||
| 213 | - i = index >> 5; | ||
| 214 | - mask = 1 << (index & 0x1f); | ||
| 215 | - tab[i] |= mask; | ||
| 216 | -} | ||
| 217 | - | ||
| 218 | -static inline void reset_bit(uint32_t *tab, int index) | ||
| 219 | -{ | ||
| 220 | - int i, mask; | ||
| 221 | - i = index >> 5; | ||
| 222 | - mask = 1 << (index & 0x1f); | ||
| 223 | - tab[i] &= ~mask; | ||
| 224 | -} | ||
| 225 | - | ||
| 226 | /* return -1 if no bit is set */ | 276 | /* return -1 if no bit is set */ |
| 227 | static int get_highest_priority_int(uint32_t *tab) | 277 | static int get_highest_priority_int(uint32_t *tab) |
| 228 | { | 278 | { |
| @@ -294,26 +344,37 @@ static void apic_eoi(APICState *s) | @@ -294,26 +344,37 @@ static void apic_eoi(APICState *s) | ||
| 294 | apic_update_irq(s); | 344 | apic_update_irq(s); |
| 295 | } | 345 | } |
| 296 | 346 | ||
| 297 | -static uint32_t apic_get_delivery_bitmask(uint8_t dest, uint8_t dest_mode) | 347 | +static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, |
| 348 | + uint8_t dest, uint8_t dest_mode) | ||
| 298 | { | 349 | { |
| 299 | - uint32_t mask = 0; | ||
| 300 | APICState *apic_iter; | 350 | APICState *apic_iter; |
| 351 | + int i; | ||
| 301 | 352 | ||
| 302 | if (dest_mode == 0) { | 353 | if (dest_mode == 0) { |
| 303 | - if (dest == 0xff) | ||
| 304 | - mask = 0xff; | ||
| 305 | - else | ||
| 306 | - mask = 1 << dest; | 354 | + if (dest == 0xff) { |
| 355 | + memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t)); | ||
| 356 | + } else { | ||
| 357 | + memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); | ||
| 358 | + set_bit(deliver_bitmask, dest); | ||
| 359 | + } | ||
| 307 | } else { | 360 | } else { |
| 308 | /* XXX: cluster mode */ | 361 | /* XXX: cluster mode */ |
| 309 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
| 310 | - apic_iter = apic_iter->next_apic) { | ||
| 311 | - if (dest & apic_iter->log_dest) | ||
| 312 | - mask |= (1 << apic_iter->id); | 362 | + memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); |
| 363 | + for(i = 0; i < MAX_APICS; i++) { | ||
| 364 | + apic_iter = local_apics[i]; | ||
| 365 | + if (apic_iter) { | ||
| 366 | + if (apic_iter->dest_mode == 0xf) { | ||
| 367 | + if (dest & apic_iter->log_dest) | ||
| 368 | + set_bit(deliver_bitmask, i); | ||
| 369 | + } else if (apic_iter->dest_mode == 0x0) { | ||
| 370 | + if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) && | ||
| 371 | + (dest & apic_iter->log_dest & 0x0f)) { | ||
| 372 | + set_bit(deliver_bitmask, i); | ||
| 373 | + } | ||
| 374 | + } | ||
| 375 | + } | ||
| 313 | } | 376 | } |
| 314 | } | 377 | } |
| 315 | - | ||
| 316 | - return mask; | ||
| 317 | } | 378 | } |
| 318 | 379 | ||
| 319 | 380 | ||
| @@ -356,23 +417,25 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | @@ -356,23 +417,25 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | ||
| 356 | uint8_t delivery_mode, uint8_t vector_num, | 417 | uint8_t delivery_mode, uint8_t vector_num, |
| 357 | uint8_t polarity, uint8_t trigger_mode) | 418 | uint8_t polarity, uint8_t trigger_mode) |
| 358 | { | 419 | { |
| 359 | - uint32_t deliver_bitmask = 0; | 420 | + uint32_t deliver_bitmask[MAX_APIC_WORDS]; |
| 360 | int dest_shorthand = (s->icr[0] >> 18) & 3; | 421 | int dest_shorthand = (s->icr[0] >> 18) & 3; |
| 361 | APICState *apic_iter; | 422 | APICState *apic_iter; |
| 362 | 423 | ||
| 363 | switch (dest_shorthand) { | 424 | switch (dest_shorthand) { |
| 364 | - case 0: | ||
| 365 | - deliver_bitmask = apic_get_delivery_bitmask(dest, dest_mode); | ||
| 366 | - break; | ||
| 367 | - case 1: | ||
| 368 | - deliver_bitmask = (1 << s->id); | ||
| 369 | - break; | ||
| 370 | - case 2: | ||
| 371 | - deliver_bitmask = 0xffffffff; | ||
| 372 | - break; | ||
| 373 | - case 3: | ||
| 374 | - deliver_bitmask = 0xffffffff & ~(1 << s->id); | ||
| 375 | - break; | 425 | + case 0: |
| 426 | + apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); | ||
| 427 | + break; | ||
| 428 | + case 1: | ||
| 429 | + memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask)); | ||
| 430 | + set_bit(deliver_bitmask, s->id); | ||
| 431 | + break; | ||
| 432 | + case 2: | ||
| 433 | + memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); | ||
| 434 | + break; | ||
| 435 | + case 3: | ||
| 436 | + memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); | ||
| 437 | + reset_bit(deliver_bitmask, s->id); | ||
| 438 | + break; | ||
| 376 | } | 439 | } |
| 377 | 440 | ||
| 378 | switch (delivery_mode) { | 441 | switch (delivery_mode) { |
| @@ -381,24 +444,16 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | @@ -381,24 +444,16 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | ||
| 381 | int trig_mode = (s->icr[0] >> 15) & 1; | 444 | int trig_mode = (s->icr[0] >> 15) & 1; |
| 382 | int level = (s->icr[0] >> 14) & 1; | 445 | int level = (s->icr[0] >> 14) & 1; |
| 383 | if (level == 0 && trig_mode == 1) { | 446 | if (level == 0 && trig_mode == 1) { |
| 384 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
| 385 | - apic_iter = apic_iter->next_apic) { | ||
| 386 | - if (deliver_bitmask & (1 << apic_iter->id)) { | ||
| 387 | - apic_iter->arb_id = apic_iter->id; | ||
| 388 | - } | ||
| 389 | - } | 447 | + foreach_apic(apic_iter, deliver_bitmask, |
| 448 | + apic_iter->arb_id = apic_iter->id ); | ||
| 390 | return; | 449 | return; |
| 391 | } | 450 | } |
| 392 | } | 451 | } |
| 393 | break; | 452 | break; |
| 394 | 453 | ||
| 395 | case APIC_DM_SIPI: | 454 | case APIC_DM_SIPI: |
| 396 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
| 397 | - apic_iter = apic_iter->next_apic) { | ||
| 398 | - if (deliver_bitmask & (1 << apic_iter->id)) { | ||
| 399 | - apic_startup(apic_iter, vector_num); | ||
| 400 | - } | ||
| 401 | - } | 455 | + foreach_apic(apic_iter, deliver_bitmask, |
| 456 | + apic_startup(apic_iter, vector_num) ); | ||
| 402 | return; | 457 | return; |
| 403 | } | 458 | } |
| 404 | 459 | ||
| @@ -749,6 +804,8 @@ int apic_init(CPUState *env) | @@ -749,6 +804,8 @@ int apic_init(CPUState *env) | ||
| 749 | { | 804 | { |
| 750 | APICState *s; | 805 | APICState *s; |
| 751 | 806 | ||
| 807 | + if (last_apic_id >= MAX_APICS) | ||
| 808 | + return -1; | ||
| 752 | s = qemu_mallocz(sizeof(APICState)); | 809 | s = qemu_mallocz(sizeof(APICState)); |
| 753 | if (!s) | 810 | if (!s) |
| 754 | return -1; | 811 | return -1; |
| @@ -772,10 +829,8 @@ int apic_init(CPUState *env) | @@ -772,10 +829,8 @@ int apic_init(CPUState *env) | ||
| 772 | 829 | ||
| 773 | register_savevm("apic", 0, 1, apic_save, apic_load, s); | 830 | register_savevm("apic", 0, 1, apic_save, apic_load, s); |
| 774 | qemu_register_reset(apic_reset, s); | 831 | qemu_register_reset(apic_reset, s); |
| 775 | - | ||
| 776 | - s->next_apic = first_local_apic; | ||
| 777 | - first_local_apic = s; | ||
| 778 | 832 | ||
| 833 | + local_apics[s->id] = s; | ||
| 779 | return 0; | 834 | return 0; |
| 780 | } | 835 | } |
| 781 | 836 | ||
| @@ -790,6 +845,7 @@ static void ioapic_service(IOAPICState *s) | @@ -790,6 +845,7 @@ static void ioapic_service(IOAPICState *s) | ||
| 790 | uint8_t dest; | 845 | uint8_t dest; |
| 791 | uint8_t dest_mode; | 846 | uint8_t dest_mode; |
| 792 | uint8_t polarity; | 847 | uint8_t polarity; |
| 848 | + uint32_t deliver_bitmask[MAX_APIC_WORDS]; | ||
| 793 | 849 | ||
| 794 | for (i = 0; i < IOAPIC_NUM_PINS; i++) { | 850 | for (i = 0; i < IOAPIC_NUM_PINS; i++) { |
| 795 | mask = 1 << i; | 851 | mask = 1 << i; |
| @@ -807,8 +863,10 @@ static void ioapic_service(IOAPICState *s) | @@ -807,8 +863,10 @@ static void ioapic_service(IOAPICState *s) | ||
| 807 | vector = pic_read_irq(isa_pic); | 863 | vector = pic_read_irq(isa_pic); |
| 808 | else | 864 | else |
| 809 | vector = entry & 0xff; | 865 | vector = entry & 0xff; |
| 810 | - apic_bus_deliver(apic_get_delivery_bitmask(dest, dest_mode), | ||
| 811 | - delivery_mode, vector, polarity, trig_mode); | 866 | + |
| 867 | + apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); | ||
| 868 | + apic_bus_deliver(deliver_bitmask, delivery_mode, | ||
| 869 | + vector, polarity, trig_mode); | ||
| 812 | } | 870 | } |
| 813 | } | 871 | } |
| 814 | } | 872 | } |
vl.c
| @@ -153,10 +153,12 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; | @@ -153,10 +153,12 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; | ||
| 153 | USBDevice *vm_usb_hub; | 153 | USBDevice *vm_usb_hub; |
| 154 | static VLANState *first_vlan; | 154 | static VLANState *first_vlan; |
| 155 | int smp_cpus = 1; | 155 | int smp_cpus = 1; |
| 156 | -#ifdef TARGET_SPARC | 156 | +#if defined(TARGET_SPARC) |
| 157 | #define MAX_CPUS 16 | 157 | #define MAX_CPUS 16 |
| 158 | +#elif defined(TARGET_I386) | ||
| 159 | +#define MAX_CPUS 255 | ||
| 158 | #else | 160 | #else |
| 159 | -#define MAX_CPUS 8 | 161 | +#define MAX_CPUS 1 |
| 160 | #endif | 162 | #endif |
| 161 | 163 | ||
| 162 | /***********************************************************/ | 164 | /***********************************************************/ |