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 #include "h/types.h"
0033 #include "h/fddi.h"
0034 #include "h/smc.h"
0035 #include "h/smt_p.h"
0036
0037
0038 #ifndef SLIM_SMT
0039
0040 #ifdef ESS
0041
0042 #ifndef lint
0043 #define LINT_USE(x)
0044 #else
0045 #define LINT_USE(x) (x)=(x)
0046 #endif
0047 #define MS2BCLK(x) ((x)*12500L)
0048
0049
0050
0051
0052
0053
0054
0055 static const u_short plist_raf_alc_res[] = { SMT_P0012, SMT_P320B, SMT_P320F,
0056 SMT_P3210, SMT_P0019, SMT_P001A,
0057 SMT_P001D, 0 } ;
0058
0059 static const u_short plist_raf_chg_req[] = { SMT_P320B, SMT_P320F, SMT_P3210,
0060 SMT_P001A, 0 } ;
0061
0062 static const struct fddi_addr smt_sba_da = {{0x80,0x01,0x43,0x00,0x80,0x0C}} ;
0063 static const struct fddi_addr null_addr = {{0,0,0,0,0,0}} ;
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
0079 int sba_cmd);
0080 static void ess_config_fifo(struct s_smc *smc);
0081 static void ess_send_alc_req(struct s_smc *smc);
0082 static void ess_send_frame(struct s_smc *smc, SMbuf *mb);
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 void ess_timer_poll(struct s_smc *smc);
0097 void ess_para_change(struct s_smc *smc);
0098 int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
0099 int fs);
0100 static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead);
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
0113 int fs)
0114 {
0115 void *p ;
0116 struct smt_p_0016 *cmd ;
0117 SMbuf *db ;
0118 u_long msg_res_type ;
0119 u_long payload, overhead ;
0120 int local ;
0121 int i ;
0122
0123
0124
0125
0126 local = ((fs & L_INDICATOR) != 0) ;
0127
0128
0129
0130
0131 if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {
0132 DB_ESS("ESS: RAF frame error, parameter type not found");
0133 return fs;
0134 }
0135 msg_res_type = ((struct smt_p_0015 *)p)->res_type ;
0136
0137
0138
0139
0140 if (!(cmd = (struct smt_p_0016 *) sm_to_para(smc,sm,SMT_P0016))) {
0141
0142
0143
0144 DB_ESS("ESS: RAF frame error, parameter command not found");
0145 return fs;
0146 }
0147
0148 DB_ESSN(2, "fc %x ft %x", sm->smt_class, sm->smt_type);
0149 DB_ESSN(2, "ver %x tran %x", sm->smt_version, sm->smt_tid);
0150 DB_ESSN(2, "stn_id %pM", &sm->smt_source);
0151
0152 DB_ESSN(2, "infolen %x res %lx", sm->smt_len, msg_res_type);
0153 DB_ESSN(2, "sbacmd %x", cmd->sba_cmd);
0154
0155
0156
0157
0158 switch (cmd->sba_cmd) {
0159
0160
0161
0162
0163 case REQUEST_ALLOCATION :
0164
0165
0166
0167 if (sm->smt_type == SMT_REQUEST) {
0168
0169
0170
0171
0172 if (!local || smc->mib.fddiESSPayload)
0173 return fs;
0174
0175 p = (void *) sm_to_para(smc,sm,SMT_P0019) ;
0176 for (i = 0; i < 5; i++) {
0177 if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {
0178 return fs;
0179 }
0180 }
0181
0182
0183
0184
0185
0186 smc->ess.alloc_trans_id = sm->smt_tid ;
0187 DB_ESS("ESS: save Alloc Req Trans ID %x", sm->smt_tid);
0188 p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
0189 ((struct smt_p_320f *)p)->mib_payload =
0190 smc->mib.a[PATH0].fddiPATHSbaPayload ;
0191 p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
0192 ((struct smt_p_3210 *)p)->mib_overhead =
0193 smc->mib.a[PATH0].fddiPATHSbaOverhead ;
0194 sm->smt_dest = smt_sba_da ;
0195
0196 if (smc->ess.local_sba_active)
0197 return fs | I_INDICATOR;
0198
0199 if (!(db = smt_get_mbuf(smc)))
0200 return fs;
0201
0202 db->sm_len = mb->sm_len ;
0203 db->sm_off = mb->sm_off ;
0204 memcpy(((char *)(db->sm_data+db->sm_off)),(char *)sm,
0205 (int)db->sm_len) ;
0206 dump_smt(smc,
0207 (struct smt_header *)(db->sm_data+db->sm_off),
0208 "RAF") ;
0209 smt_send_frame(smc,db,FC_SMT_INFO,0) ;
0210 return fs;
0211 }
0212
0213
0214
0215
0216
0217 if (smt_check_para(smc,sm,plist_raf_alc_res)) {
0218 DB_ESS("ESS: RAF with para problem, ignoring");
0219 return fs;
0220 }
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
0233 != PRIMARY_RING) ||
0234 (msg_res_type != SYNC_BW) ||
0235 (((struct smt_p_reason *)sm_to_para(smc,sm,SMT_P0012))->rdf_reason
0236 != SMT_RDF_SUCCESS) ||
0237 (sm->smt_tid != smc->ess.alloc_trans_id)) {
0238
0239 DB_ESS("ESS: Allocation Response not accepted");
0240 return fs;
0241 }
0242
0243
0244
0245
0246 p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
0247 if (!p) {
0248 printk(KERN_ERR "ESS: sm_to_para failed");
0249 return fs;
0250 }
0251 payload = ((struct smt_p_320f *)p)->mib_payload ;
0252 p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
0253 if (!p) {
0254 printk(KERN_ERR "ESS: sm_to_para failed");
0255 return fs;
0256 }
0257 overhead = ((struct smt_p_3210 *)p)->mib_overhead ;
0258
0259 DB_ESSN(2, "payload= %lx overhead= %lx",
0260 payload, overhead);
0261
0262
0263
0264
0265 (void)process_bw_alloc(smc,(long)payload,(long)overhead) ;
0266
0267 return fs;
0268
0269
0270
0271
0272
0273 case CHANGE_ALLOCATION :
0274
0275
0276
0277 if (sm->smt_type != SMT_REQUEST) {
0278 DB_ESS("ESS: Do not process Change Responses");
0279 return fs;
0280 }
0281
0282
0283
0284
0285 if (smt_check_para(smc,sm,plist_raf_chg_req)) {
0286 DB_ESS("ESS: RAF with para problem, ignoring");
0287 return fs;
0288 }
0289
0290
0291
0292
0293
0294
0295
0296 if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
0297 != PRIMARY_RING) || (msg_res_type != SYNC_BW)) {
0298 DB_ESS("ESS: RAF frame with para problem, ignoring");
0299 return fs;
0300 }
0301
0302
0303
0304
0305 p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
0306 payload = ((struct smt_p_320f *)p)->mib_payload ;
0307 p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
0308 overhead = ((struct smt_p_3210 *)p)->mib_overhead ;
0309
0310 DB_ESSN(2, "ESS: Change Request from %pM",
0311 &sm->smt_source);
0312 DB_ESSN(2, "payload= %lx overhead= %lx",
0313 payload, overhead);
0314
0315
0316
0317
0318 if(!process_bw_alloc(smc,(long)payload,(long)overhead))
0319 return fs;
0320
0321
0322
0323
0324 ess_send_response(smc,sm,CHANGE_ALLOCATION) ;
0325
0326 return fs;
0327
0328
0329
0330
0331
0332 case REPORT_ALLOCATION :
0333
0334
0335
0336 if (sm->smt_type != SMT_REQUEST) {
0337 DB_ESS("ESS: Do not process a Report Reply");
0338 return fs;
0339 }
0340
0341 DB_ESSN(2, "ESS: Report Request from %pM",
0342 &sm->smt_source);
0343
0344
0345
0346
0347 if (msg_res_type != SYNC_BW) {
0348 DB_ESS("ESS: ignoring RAF with para problem");
0349 return fs;
0350 }
0351
0352
0353
0354
0355 ess_send_response(smc,sm,REPORT_ALLOCATION) ;
0356
0357 return fs;
0358
0359
0360 default:
0361
0362
0363
0364 DB_ESS("ESS: ignoring RAF with bad sba_cmd");
0365 break ;
0366 }
0367
0368 return fs;
0369 }
0370
0371
0372
0373
0374
0375 static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead)
0376 {
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426 if (payload > MAX_PAYLOAD || overhead > 5000) {
0427 DB_ESS("ESS: payload / overhead not accepted");
0428 return FALSE;
0429 }
0430
0431
0432
0433
0434
0435 if (smc->mib.fddiESSPayload &&
0436 ((u_long)payload != smc->mib.fddiESSPayload ||
0437 (u_long)overhead != smc->mib.fddiESSOverhead)) {
0438 smc->ess.raf_act_timer_poll = TRUE ;
0439 smc->ess.timer_count = 0 ;
0440 }
0441
0442
0443
0444
0445 if (payload) {
0446 DB_ESSN(2, "ESS: turn SMT_ST_SYNC_SERVICE bit on");
0447 smc->ess.sync_bw_available = TRUE ;
0448
0449 smc->ess.sync_bw = overhead -
0450 (long)smc->mib.m[MAC0].fddiMACT_Neg *
0451 payload / 1562 ;
0452 }
0453 else {
0454 DB_ESSN(2, "ESS: turn SMT_ST_SYNC_SERVICE bit off");
0455 smc->ess.sync_bw_available = FALSE ;
0456 smc->ess.sync_bw = 0 ;
0457 overhead = 0 ;
0458 }
0459
0460 smc->mib.a[PATH0].fddiPATHSbaPayload = payload ;
0461 smc->mib.a[PATH0].fddiPATHSbaOverhead = overhead ;
0462
0463
0464 DB_ESSN(2, "tsync = %lx", smc->ess.sync_bw);
0465
0466 ess_config_fifo(smc) ;
0467 set_formac_tsync(smc,smc->ess.sync_bw) ;
0468 return TRUE;
0469 }
0470
0471 static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
0472 int sba_cmd)
0473 {
0474 struct smt_sba_chg *chg ;
0475 SMbuf *mb ;
0476 void *p ;
0477
0478
0479
0480
0481 if (sba_cmd == CHANGE_ALLOCATION) {
0482 if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
0483 sizeof(struct smt_sba_chg))))
0484 return ;
0485 }
0486 else {
0487 if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
0488 sizeof(struct smt_sba_rep_res))))
0489 return ;
0490 }
0491
0492 chg = smtod(mb,struct smt_sba_chg *) ;
0493 chg->smt.smt_tid = sm->smt_tid ;
0494 chg->smt.smt_dest = sm->smt_source ;
0495
0496
0497 chg->s_type.para.p_type = SMT_P0015 ;
0498 chg->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;
0499 chg->s_type.res_type = SYNC_BW ;
0500
0501
0502 chg->cmd.para.p_type = SMT_P0016 ;
0503 chg->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;
0504 chg->cmd.sba_cmd = sba_cmd ;
0505
0506
0507 chg->path.para.p_type = SMT_P320B ;
0508 chg->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;
0509 chg->path.mib_index = SBAPATHINDEX ;
0510 chg->path.path_pad = 0;
0511 chg->path.path_index = PRIMARY_RING ;
0512
0513
0514 chg->payload.para.p_type = SMT_P320F ;
0515 chg->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;
0516 chg->payload.mib_index = SBAPATHINDEX ;
0517 chg->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;
0518
0519
0520 chg->overhead.para.p_type = SMT_P3210 ;
0521 chg->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;
0522 chg->overhead.mib_index = SBAPATHINDEX ;
0523 chg->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;
0524
0525 if (sba_cmd == CHANGE_ALLOCATION) {
0526
0527 chg->cat.para.p_type = SMT_P001A ;
0528 chg->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;
0529 p = (void *) sm_to_para(smc,sm,SMT_P001A) ;
0530 chg->cat.category = ((struct smt_p_001a *)p)->category ;
0531 }
0532 dump_smt(smc,(struct smt_header *)chg,"RAF") ;
0533 ess_send_frame(smc,mb) ;
0534 }
0535
0536 void ess_timer_poll(struct s_smc *smc)
0537 {
0538 if (!smc->ess.raf_act_timer_poll)
0539 return ;
0540
0541 DB_ESSN(2, "ESS: timer_poll");
0542
0543 smc->ess.timer_count++ ;
0544 if (smc->ess.timer_count == 10) {
0545 smc->ess.timer_count = 0 ;
0546 ess_send_alc_req(smc) ;
0547 }
0548 }
0549
0550 static void ess_send_alc_req(struct s_smc *smc)
0551 {
0552 struct smt_sba_alc_req *req ;
0553 SMbuf *mb ;
0554
0555
0556
0557
0558
0559
0560 if (!smc->mib.fddiESSPayload) {
0561 smc->mib.fddiESSOverhead = 0 ;
0562 }
0563 else {
0564 if (!smc->mib.fddiESSOverhead)
0565 smc->mib.fddiESSOverhead = DEFAULT_OV ;
0566 }
0567
0568 if (smc->mib.fddiESSOverhead ==
0569 smc->mib.a[PATH0].fddiPATHSbaOverhead &&
0570 smc->mib.fddiESSPayload ==
0571 smc->mib.a[PATH0].fddiPATHSbaPayload){
0572 smc->ess.raf_act_timer_poll = FALSE ;
0573 smc->ess.timer_count = 7 ;
0574 return ;
0575 }
0576
0577
0578
0579
0580 if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REQUEST,
0581 sizeof(struct smt_sba_alc_req))))
0582 return ;
0583 req = smtod(mb,struct smt_sba_alc_req *) ;
0584 req->smt.smt_tid = smc->ess.alloc_trans_id = smt_get_tid(smc) ;
0585 req->smt.smt_dest = smt_sba_da ;
0586
0587
0588 req->s_type.para.p_type = SMT_P0015 ;
0589 req->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;
0590 req->s_type.res_type = SYNC_BW ;
0591
0592
0593 req->cmd.para.p_type = SMT_P0016 ;
0594 req->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;
0595 req->cmd.sba_cmd = REQUEST_ALLOCATION ;
0596
0597
0598
0599
0600
0601
0602
0603 req->path.para.p_type = SMT_P320B ;
0604 req->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;
0605 req->path.mib_index = SBAPATHINDEX ;
0606 req->path.path_pad = 0;
0607 req->path.path_index = PRIMARY_RING ;
0608
0609
0610 req->pl_req.para.p_type = SMT_P0017 ;
0611 req->pl_req.para.p_len = sizeof(struct smt_p_0017) - PARA_LEN ;
0612 req->pl_req.sba_pl_req = smc->mib.fddiESSPayload -
0613 smc->mib.a[PATH0].fddiPATHSbaPayload ;
0614
0615
0616 req->ov_req.para.p_type = SMT_P0018 ;
0617 req->ov_req.para.p_len = sizeof(struct smt_p_0018) - PARA_LEN ;
0618 req->ov_req.sba_ov_req = smc->mib.fddiESSOverhead -
0619 smc->mib.a[PATH0].fddiPATHSbaOverhead ;
0620
0621
0622 req->payload.para.p_type = SMT_P320F ;
0623 req->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;
0624 req->payload.mib_index = SBAPATHINDEX ;
0625 req->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;
0626
0627
0628 req->overhead.para.p_type = SMT_P3210 ;
0629 req->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;
0630 req->overhead.mib_index = SBAPATHINDEX ;
0631 req->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;
0632
0633
0634 req->a_addr.para.p_type = SMT_P0019 ;
0635 req->a_addr.para.p_len = sizeof(struct smt_p_0019) - PARA_LEN ;
0636 req->a_addr.sba_pad = 0;
0637 req->a_addr.alloc_addr = null_addr ;
0638
0639
0640 req->cat.para.p_type = SMT_P001A ;
0641 req->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;
0642 req->cat.category = smc->mib.fddiESSCategory ;
0643
0644
0645 req->tneg.para.p_type = SMT_P001B ;
0646 req->tneg.para.p_len = sizeof(struct smt_p_001b) - PARA_LEN ;
0647 req->tneg.max_t_neg = smc->mib.fddiESSMaxTNeg ;
0648
0649
0650 req->segm.para.p_type = SMT_P001C ;
0651 req->segm.para.p_len = sizeof(struct smt_p_001c) - PARA_LEN ;
0652 req->segm.min_seg_siz = smc->mib.fddiESSMinSegmentSize ;
0653
0654 dump_smt(smc,(struct smt_header *)req,"RAF") ;
0655 ess_send_frame(smc,mb) ;
0656 }
0657
0658 static void ess_send_frame(struct s_smc *smc, SMbuf *mb)
0659 {
0660
0661
0662
0663 if (smc->ess.local_sba_active) {
0664
0665
0666
0667 DB_ESS("ESS:Send to the local SBA");
0668 if (!smc->ess.sba_reply_pend)
0669 smc->ess.sba_reply_pend = mb ;
0670 else {
0671 DB_ESS("Frame is lost - another frame was pending");
0672 smt_free_mbuf(smc,mb) ;
0673 }
0674 }
0675 else {
0676
0677
0678
0679 DB_ESS("ESS:Send to the network");
0680 smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
0681 }
0682 }
0683
0684 void ess_para_change(struct s_smc *smc)
0685 {
0686 (void)process_bw_alloc(smc,(long)smc->mib.a[PATH0].fddiPATHSbaPayload,
0687 (long)smc->mib.a[PATH0].fddiPATHSbaOverhead) ;
0688 }
0689
0690 static void ess_config_fifo(struct s_smc *smc)
0691 {
0692
0693
0694
0695 if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
0696 if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON &&
0697 (smc->hw.fp.fifo.fifo_config_mode&SEND_ASYNC_AS_SYNC) ==
0698 smc->mib.fddiESSSynchTxMode) {
0699 return ;
0700 }
0701 }
0702 else {
0703 if (!(smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON)) {
0704 return ;
0705 }
0706 }
0707
0708
0709
0710
0711 formac_reinit_tx(smc) ;
0712 }
0713
0714 #endif
0715
0716 #endif
0717