0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 #include "remote_node_table.h"
0061 #include "remote_node_context.h"
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 static u32 sci_remote_node_table_get_group_index(
0076 struct sci_remote_node_table *remote_node_table,
0077 u32 group_table_index)
0078 {
0079 u32 dword_index;
0080 u32 *group_table;
0081 u32 bit_index;
0082
0083 group_table = remote_node_table->remote_node_groups[group_table_index];
0084
0085 for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++) {
0086 if (group_table[dword_index] != 0) {
0087 for (bit_index = 0; bit_index < 32; bit_index++) {
0088 if ((group_table[dword_index] & (1 << bit_index)) != 0) {
0089 return (dword_index * 32) + bit_index;
0090 }
0091 }
0092 }
0093 }
0094
0095 return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX;
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 static void sci_remote_node_table_clear_group_index(
0110 struct sci_remote_node_table *remote_node_table,
0111 u32 group_table_index,
0112 u32 group_index)
0113 {
0114 u32 dword_index;
0115 u32 bit_index;
0116 u32 *group_table;
0117
0118 BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT);
0119 BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32));
0120
0121 dword_index = group_index / 32;
0122 bit_index = group_index % 32;
0123 group_table = remote_node_table->remote_node_groups[group_table_index];
0124
0125 group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index);
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 static void sci_remote_node_table_set_group_index(
0140 struct sci_remote_node_table *remote_node_table,
0141 u32 group_table_index,
0142 u32 group_index)
0143 {
0144 u32 dword_index;
0145 u32 bit_index;
0146 u32 *group_table;
0147
0148 BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT);
0149 BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32));
0150
0151 dword_index = group_index / 32;
0152 bit_index = group_index % 32;
0153 group_table = remote_node_table->remote_node_groups[group_table_index];
0154
0155 group_table[dword_index] = group_table[dword_index] | (1 << bit_index);
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168 static void sci_remote_node_table_set_node_index(
0169 struct sci_remote_node_table *remote_node_table,
0170 u32 remote_node_index)
0171 {
0172 u32 dword_location;
0173 u32 dword_remainder;
0174 u32 slot_normalized;
0175 u32 slot_position;
0176
0177 BUG_ON(
0178 (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
0179 <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
0180 );
0181
0182 dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
0183 dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
0184 slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32);
0185 slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
0186
0187 remote_node_table->available_remote_nodes[dword_location] |=
0188 1 << (slot_normalized + slot_position);
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 static void sci_remote_node_table_clear_node_index(
0202 struct sci_remote_node_table *remote_node_table,
0203 u32 remote_node_index)
0204 {
0205 u32 dword_location;
0206 u32 dword_remainder;
0207 u32 slot_position;
0208 u32 slot_normalized;
0209
0210 BUG_ON(
0211 (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
0212 <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
0213 );
0214
0215 dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
0216 dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
0217 slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32);
0218 slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
0219
0220 remote_node_table->available_remote_nodes[dword_location] &=
0221 ~(1 << (slot_normalized + slot_position));
0222 }
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 static void sci_remote_node_table_clear_group(
0233 struct sci_remote_node_table *remote_node_table,
0234 u32 group_index)
0235 {
0236 u32 dword_location;
0237 u32 dword_remainder;
0238 u32 dword_value;
0239
0240 BUG_ON(
0241 (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
0242 <= (group_index / SCU_STP_REMOTE_NODE_COUNT)
0243 );
0244
0245 dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
0246 dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
0247
0248 dword_value = remote_node_table->available_remote_nodes[dword_location];
0249 dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
0250 remote_node_table->available_remote_nodes[dword_location] = dword_value;
0251 }
0252
0253
0254
0255
0256
0257
0258 static void sci_remote_node_table_set_group(
0259 struct sci_remote_node_table *remote_node_table,
0260 u32 group_index)
0261 {
0262 u32 dword_location;
0263 u32 dword_remainder;
0264 u32 dword_value;
0265
0266 BUG_ON(
0267 (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
0268 <= (group_index / SCU_STP_REMOTE_NODE_COUNT)
0269 );
0270
0271 dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
0272 dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
0273
0274 dword_value = remote_node_table->available_remote_nodes[dword_location];
0275 dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
0276 remote_node_table->available_remote_nodes[dword_location] = dword_value;
0277 }
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288 static u8 sci_remote_node_table_get_group_value(
0289 struct sci_remote_node_table *remote_node_table,
0290 u32 group_index)
0291 {
0292 u32 dword_location;
0293 u32 dword_remainder;
0294 u32 dword_value;
0295
0296 dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
0297 dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
0298
0299 dword_value = remote_node_table->available_remote_nodes[dword_location];
0300 dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
0301 dword_value = dword_value >> (dword_remainder * 4);
0302
0303 return (u8)dword_value;
0304 }
0305
0306
0307
0308
0309
0310
0311
0312
0313 void sci_remote_node_table_initialize(
0314 struct sci_remote_node_table *remote_node_table,
0315 u32 remote_node_entries)
0316 {
0317 u32 index;
0318
0319
0320
0321
0322 memset(
0323 remote_node_table->available_remote_nodes,
0324 0x00,
0325 sizeof(remote_node_table->available_remote_nodes)
0326 );
0327
0328 memset(
0329 remote_node_table->remote_node_groups,
0330 0x00,
0331 sizeof(remote_node_table->remote_node_groups)
0332 );
0333
0334
0335 remote_node_table->available_nodes_array_size = (u16)
0336 (remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD)
0337 + ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0);
0338
0339
0340
0341 for (index = 0; index < remote_node_entries; index++) {
0342 sci_remote_node_table_set_node_index(remote_node_table, index);
0343 }
0344
0345 remote_node_table->group_array_size = (u16)
0346 (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32))
0347 + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0);
0348
0349 for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++) {
0350
0351
0352
0353 sci_remote_node_table_set_group_index(remote_node_table, 2, index);
0354 }
0355
0356
0357 if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) {
0358 sci_remote_node_table_set_group_index(remote_node_table, 1, index);
0359 } else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) {
0360 sci_remote_node_table_set_group_index(remote_node_table, 0, index);
0361 }
0362 }
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379 static u16 sci_remote_node_table_allocate_single_remote_node(
0380 struct sci_remote_node_table *remote_node_table,
0381 u32 group_table_index)
0382 {
0383 u8 index;
0384 u8 group_value;
0385 u32 group_index;
0386 u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
0387
0388 group_index = sci_remote_node_table_get_group_index(
0389 remote_node_table, group_table_index);
0390
0391
0392 if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) {
0393 group_value = sci_remote_node_table_get_group_value(
0394 remote_node_table, group_index);
0395
0396 for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) {
0397 if (((1 << index) & group_value) != 0) {
0398
0399 remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT
0400 + index);
0401
0402 sci_remote_node_table_clear_group_index(
0403 remote_node_table, group_table_index, group_index
0404 );
0405
0406 sci_remote_node_table_clear_node_index(
0407 remote_node_table, remote_node_index
0408 );
0409
0410 if (group_table_index > 0) {
0411 sci_remote_node_table_set_group_index(
0412 remote_node_table, group_table_index - 1, group_index
0413 );
0414 }
0415
0416 break;
0417 }
0418 }
0419 }
0420
0421 return remote_node_index;
0422 }
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436 static u16 sci_remote_node_table_allocate_triple_remote_node(
0437 struct sci_remote_node_table *remote_node_table,
0438 u32 group_table_index)
0439 {
0440 u32 group_index;
0441 u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
0442
0443 group_index = sci_remote_node_table_get_group_index(
0444 remote_node_table, group_table_index);
0445
0446 if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) {
0447 remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT;
0448
0449 sci_remote_node_table_clear_group_index(
0450 remote_node_table, group_table_index, group_index
0451 );
0452
0453 sci_remote_node_table_clear_group(
0454 remote_node_table, group_index
0455 );
0456 }
0457
0458 return remote_node_index;
0459 }
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473 u16 sci_remote_node_table_allocate_remote_node(
0474 struct sci_remote_node_table *remote_node_table,
0475 u32 remote_node_count)
0476 {
0477 u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
0478
0479 if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) {
0480 remote_node_index =
0481 sci_remote_node_table_allocate_single_remote_node(
0482 remote_node_table, 0);
0483
0484 if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
0485 remote_node_index =
0486 sci_remote_node_table_allocate_single_remote_node(
0487 remote_node_table, 1);
0488 }
0489
0490 if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
0491 remote_node_index =
0492 sci_remote_node_table_allocate_single_remote_node(
0493 remote_node_table, 2);
0494 }
0495 } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) {
0496 remote_node_index =
0497 sci_remote_node_table_allocate_triple_remote_node(
0498 remote_node_table, 2);
0499 }
0500
0501 return remote_node_index;
0502 }
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512 static void sci_remote_node_table_release_single_remote_node(
0513 struct sci_remote_node_table *remote_node_table,
0514 u16 remote_node_index)
0515 {
0516 u32 group_index;
0517 u8 group_value;
0518
0519 group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
0520
0521 group_value = sci_remote_node_table_get_group_value(remote_node_table, group_index);
0522
0523
0524
0525
0526 BUG_ON(group_value == SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE);
0527
0528 if (group_value == 0x00) {
0529
0530
0531
0532 sci_remote_node_table_set_group_index(remote_node_table, 0, group_index);
0533 } else if ((group_value & (group_value - 1)) == 0) {
0534
0535
0536
0537 sci_remote_node_table_clear_group_index(remote_node_table, 0, group_index);
0538 sci_remote_node_table_set_group_index(remote_node_table, 1, group_index);
0539 } else {
0540
0541
0542
0543 sci_remote_node_table_clear_group_index(remote_node_table, 1, group_index);
0544 sci_remote_node_table_set_group_index(remote_node_table, 2, group_index);
0545 }
0546
0547 sci_remote_node_table_set_node_index(remote_node_table, remote_node_index);
0548 }
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559 static void sci_remote_node_table_release_triple_remote_node(
0560 struct sci_remote_node_table *remote_node_table,
0561 u16 remote_node_index)
0562 {
0563 u32 group_index;
0564
0565 group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
0566
0567 sci_remote_node_table_set_group_index(
0568 remote_node_table, 2, group_index
0569 );
0570
0571 sci_remote_node_table_set_group(remote_node_table, group_index);
0572 }
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585 void sci_remote_node_table_release_remote_node_index(
0586 struct sci_remote_node_table *remote_node_table,
0587 u32 remote_node_count,
0588 u16 remote_node_index)
0589 {
0590 if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) {
0591 sci_remote_node_table_release_single_remote_node(
0592 remote_node_table, remote_node_index);
0593 } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) {
0594 sci_remote_node_table_release_triple_remote_node(
0595 remote_node_table, remote_node_index);
0596 }
0597 }
0598