718 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/******************************************************************************3 *4 * (C)Copyright 1998,1999 SysKonnect,5 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.6 *7 * See the file "skfddi.c" for further information.8 *9 * The information in this file is provided "AS IS" without warranty.10 *11 ******************************************************************************/12 13/*14 * *******************************************************************15 * This SBA code implements the Synchronous Bandwidth Allocation16 * functions described in the "FDDI Synchronous Forum Implementer's17 * Agreement" dated December 1th, 1993.18 * *******************************************************************19 *20 * PURPOSE: The purpose of this function is to control21 * synchronous allocations on a single FDDI segment.22 * Allocations are limited to the primary FDDI ring.23 * The SBM provides recovery mechanisms to recover24 * unused bandwidth also resolves T_Neg and25 * reconfiguration changes. Many of the SBM state26 * machine inputs are sourced by the underlying27 * FDDI sub-system supporting the SBA application.28 *29 * *******************************************************************30 */31 32#include "h/types.h"33#include "h/fddi.h"34#include "h/smc.h"35#include "h/smt_p.h"36 37 38#ifndef SLIM_SMT39 40#ifdef ESS41 42#ifndef lint43#define LINT_USE(x)44#else45#define LINT_USE(x) (x)=(x)46#endif47#define MS2BCLK(x) ((x)*12500L)48 49/*50 -------------------------------------------------------------51 LOCAL VARIABLES:52 -------------------------------------------------------------53*/54 55static const u_short plist_raf_alc_res[] = { SMT_P0012, SMT_P320B, SMT_P320F,56 SMT_P3210, SMT_P0019, SMT_P001A,57 SMT_P001D, 0 } ;58 59static const u_short plist_raf_chg_req[] = { SMT_P320B, SMT_P320F, SMT_P3210,60 SMT_P001A, 0 } ;61 62static const struct fddi_addr smt_sba_da = {{0x80,0x01,0x43,0x00,0x80,0x0C}} ;63static const struct fddi_addr null_addr = {{0,0,0,0,0,0}} ;64 65/*66 -------------------------------------------------------------67 GLOBAL VARIABLES:68 -------------------------------------------------------------69*/70 71 72/*73 -------------------------------------------------------------74 LOCAL FUNCTIONS:75 -------------------------------------------------------------76*/77 78static void ess_send_response(struct s_smc *smc, struct smt_header *sm,79 int sba_cmd);80static void ess_config_fifo(struct s_smc *smc);81static void ess_send_alc_req(struct s_smc *smc);82static void ess_send_frame(struct s_smc *smc, SMbuf *mb);83 84/*85 -------------------------------------------------------------86 EXTERNAL FUNCTIONS:87 -------------------------------------------------------------88*/89 90/*91 -------------------------------------------------------------92 PUBLIC FUNCTIONS:93 -------------------------------------------------------------94*/95 96void ess_timer_poll(struct s_smc *smc);97void ess_para_change(struct s_smc *smc);98int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,99 int fs);100static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead);101 102 103/*104 * --------------------------------------------------------------------------105 * End Station Support (ESS)106 * --------------------------------------------------------------------------107 */108 109/*110 * evaluate the RAF frame111 */112int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,113 int fs)114{115 void *p ; /* universal pointer */116 struct smt_p_0016 *cmd ; /* para: command for the ESS */117 SMbuf *db ;118 u_long msg_res_type ; /* recource type */119 u_long payload, overhead ;120 int local ;121 int i ;122 123 /*124 * Message Processing Code125 */126 local = ((fs & L_INDICATOR) != 0) ;127 128 /*129 * get the resource type130 */131 if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {132 DB_ESS("ESS: RAF frame error, parameter type not found");133 return fs;134 }135 msg_res_type = ((struct smt_p_0015 *)p)->res_type ;136 137 /*138 * get the pointer to the ESS command139 */140 if (!(cmd = (struct smt_p_0016 *) sm_to_para(smc,sm,SMT_P0016))) {141 /*142 * error in frame: para ESS command was not found143 */144 DB_ESS("ESS: RAF frame error, parameter command not found");145 return fs;146 }147 148 DB_ESSN(2, "fc %x ft %x", sm->smt_class, sm->smt_type);149 DB_ESSN(2, "ver %x tran %x", sm->smt_version, sm->smt_tid);150 DB_ESSN(2, "stn_id %pM", &sm->smt_source);151 152 DB_ESSN(2, "infolen %x res %lx", sm->smt_len, msg_res_type);153 DB_ESSN(2, "sbacmd %x", cmd->sba_cmd);154 155 /*156 * evaluate the ESS command157 */158 switch (cmd->sba_cmd) {159 160 /*161 * Process an ESS Allocation Request162 */163 case REQUEST_ALLOCATION :164 /*165 * check for an RAF Request (Allocation Request)166 */167 if (sm->smt_type == SMT_REQUEST) {168 /*169 * process the Allocation request only if the frame is170 * local and no static allocation is used171 */172 if (!local || smc->mib.fddiESSPayload)173 return fs;174 175 p = (void *) sm_to_para(smc,sm,SMT_P0019) ;176 for (i = 0; i < 5; i++) {177 if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {178 return fs;179 }180 }181 182 /*183 * Note: The Application should send a LAN_LOC_FRAME.184 * The ESS do not send the Frame to the network!185 */186 smc->ess.alloc_trans_id = sm->smt_tid ;187 DB_ESS("ESS: save Alloc Req Trans ID %x", sm->smt_tid);188 p = (void *) sm_to_para(smc,sm,SMT_P320F) ;189 ((struct smt_p_320f *)p)->mib_payload =190 smc->mib.a[PATH0].fddiPATHSbaPayload ;191 p = (void *) sm_to_para(smc,sm,SMT_P3210) ;192 ((struct smt_p_3210 *)p)->mib_overhead =193 smc->mib.a[PATH0].fddiPATHSbaOverhead ;194 sm->smt_dest = smt_sba_da ;195 196 if (smc->ess.local_sba_active)197 return fs | I_INDICATOR;198 199 if (!(db = smt_get_mbuf(smc)))200 return fs;201 202 db->sm_len = mb->sm_len ;203 db->sm_off = mb->sm_off ;204 memcpy(((char *)(db->sm_data+db->sm_off)),(char *)sm,205 (int)db->sm_len) ;206 dump_smt(smc,207 (struct smt_header *)(db->sm_data+db->sm_off),208 "RAF") ;209 smt_send_frame(smc,db,FC_SMT_INFO,0) ;210 return fs;211 }212 213 /*214 * The RAF frame is an Allocation Response !215 * check the parameters216 */217 if (smt_check_para(smc,sm,plist_raf_alc_res)) {218 DB_ESS("ESS: RAF with para problem, ignoring");219 return fs;220 }221 222 /*223 * VERIFY THE FRAME IS WELL BUILT:224 *225 * 1. path index = primary ring only226 * 2. resource type = sync bw only227 * 3. trans action id = alloc_trans_id228 * 4. reason code = success229 *230 * If any are violated, discard the RAF frame231 */232 if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index233 != PRIMARY_RING) ||234 (msg_res_type != SYNC_BW) ||235 (((struct smt_p_reason *)sm_to_para(smc,sm,SMT_P0012))->rdf_reason236 != SMT_RDF_SUCCESS) ||237 (sm->smt_tid != smc->ess.alloc_trans_id)) {238 239 DB_ESS("ESS: Allocation Response not accepted");240 return fs;241 }242 243 /*244 * Extract message parameters245 */246 p = (void *) sm_to_para(smc,sm,SMT_P320F) ;247 if (!p) {248 printk(KERN_ERR "ESS: sm_to_para failed");249 return fs;250 } 251 payload = ((struct smt_p_320f *)p)->mib_payload ;252 p = (void *) sm_to_para(smc,sm,SMT_P3210) ;253 if (!p) {254 printk(KERN_ERR "ESS: sm_to_para failed");255 return fs;256 } 257 overhead = ((struct smt_p_3210 *)p)->mib_overhead ;258 259 DB_ESSN(2, "payload= %lx overhead= %lx",260 payload, overhead);261 262 /*263 * process the bandwidth allocation264 */265 (void)process_bw_alloc(smc,(long)payload,(long)overhead) ;266 267 return fs;268 /* end of Process Allocation Request */269 270 /*271 * Process an ESS Change Request272 */273 case CHANGE_ALLOCATION :274 /*275 * except only replies276 */277 if (sm->smt_type != SMT_REQUEST) {278 DB_ESS("ESS: Do not process Change Responses");279 return fs;280 }281 282 /*283 * check the para for the Change Request284 */285 if (smt_check_para(smc,sm,plist_raf_chg_req)) {286 DB_ESS("ESS: RAF with para problem, ignoring");287 return fs;288 }289 290 /*291 * Verify the path index and resource292 * type are correct. If any of293 * these are false, don't process this294 * change request frame.295 */296 if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index297 != PRIMARY_RING) || (msg_res_type != SYNC_BW)) {298 DB_ESS("ESS: RAF frame with para problem, ignoring");299 return fs;300 }301 302 /*303 * Extract message queue parameters304 */305 p = (void *) sm_to_para(smc,sm,SMT_P320F) ;306 payload = ((struct smt_p_320f *)p)->mib_payload ;307 p = (void *) sm_to_para(smc,sm,SMT_P3210) ;308 overhead = ((struct smt_p_3210 *)p)->mib_overhead ;309 310 DB_ESSN(2, "ESS: Change Request from %pM",311 &sm->smt_source);312 DB_ESSN(2, "payload= %lx overhead= %lx",313 payload, overhead);314 315 /*316 * process the bandwidth allocation317 */318 if(!process_bw_alloc(smc,(long)payload,(long)overhead))319 return fs;320 321 /*322 * send an RAF Change Reply323 */324 ess_send_response(smc,sm,CHANGE_ALLOCATION) ;325 326 return fs;327 /* end of Process Change Request */328 329 /*330 * Process Report Response331 */332 case REPORT_ALLOCATION :333 /*334 * except only requests335 */336 if (sm->smt_type != SMT_REQUEST) {337 DB_ESS("ESS: Do not process a Report Reply");338 return fs;339 }340 341 DB_ESSN(2, "ESS: Report Request from %pM",342 &sm->smt_source);343 344 /*345 * verify that the resource type is sync bw only346 */347 if (msg_res_type != SYNC_BW) {348 DB_ESS("ESS: ignoring RAF with para problem");349 return fs;350 }351 352 /*353 * send an RAF Change Reply354 */355 ess_send_response(smc,sm,REPORT_ALLOCATION) ;356 357 return fs;358 /* end of Process Report Request */359 360 default:361 /*362 * error in frame363 */364 DB_ESS("ESS: ignoring RAF with bad sba_cmd");365 break ;366 }367 368 return fs;369}370 371/*372 * determines the synchronous bandwidth, set the TSYNC register and the373 * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG.374 */375static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead)376{377 /*378 * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG,379 * if the payload is greater than zero.380 * For the SBAPayload and the SBAOverhead we have the following381 * unite quations382 * _ _383 * | bytes |384 * SBAPayload = | 8000 ------ |385 * | s |386 * - -387 * _ _388 * | bytes |389 * SBAOverhead = | ------ |390 * | T-NEG |391 * - -392 *393 * T-NEG is described by the equation:394 *395 * (-) fddiMACT-NEG396 * T-NEG = -------------------397 * 12500000 1/s398 *399 * The number of bytes we are able to send is the payload400 * plus the overhead.401 *402 * bytes T-NEG SBAPayload 8000 bytes/s403 * sync_bw = SBAOverhead ------ + -----------------------------404 * T-NEG T-NEG405 *406 *407 * 1408 * sync_bw = SBAOverhead + ---- (-)fddiMACT-NEG * SBAPayload409 * 1562410 *411 */412 413 /*414 * set the mib attributes fddiPATHSbaOverhead, fddiPATHSbaPayload415 */416/* if (smt_set_obj(smc,SMT_P320F,payload,S_SET)) {417 DB_ESS("ESS: SMT does not accept the payload value");418 return FALSE;419 }420 if (smt_set_obj(smc,SMT_P3210,overhead,S_SET)) {421 DB_ESS("ESS: SMT does not accept the overhead value");422 return FALSE;423 } */424 425 /* premliminary */426 if (payload > MAX_PAYLOAD || overhead > 5000) {427 DB_ESS("ESS: payload / overhead not accepted");428 return FALSE;429 }430 431 /*432 * start the iterative allocation process if the payload or the overhead433 * are smaller than the parsed values434 */435 if (smc->mib.fddiESSPayload &&436 ((u_long)payload != smc->mib.fddiESSPayload ||437 (u_long)overhead != smc->mib.fddiESSOverhead)) {438 smc->ess.raf_act_timer_poll = TRUE ;439 smc->ess.timer_count = 0 ;440 }441 442 /*443 * evulate the Payload444 */445 if (payload) {446 DB_ESSN(2, "ESS: turn SMT_ST_SYNC_SERVICE bit on");447 smc->ess.sync_bw_available = TRUE ;448 449 smc->ess.sync_bw = overhead -450 (long)smc->mib.m[MAC0].fddiMACT_Neg *451 payload / 1562 ;452 }453 else {454 DB_ESSN(2, "ESS: turn SMT_ST_SYNC_SERVICE bit off");455 smc->ess.sync_bw_available = FALSE ;456 smc->ess.sync_bw = 0 ;457 overhead = 0 ;458 }459 460 smc->mib.a[PATH0].fddiPATHSbaPayload = payload ;461 smc->mib.a[PATH0].fddiPATHSbaOverhead = overhead ;462 463 464 DB_ESSN(2, "tsync = %lx", smc->ess.sync_bw);465 466 ess_config_fifo(smc) ;467 set_formac_tsync(smc,smc->ess.sync_bw) ;468 return TRUE;469}470 471static void ess_send_response(struct s_smc *smc, struct smt_header *sm,472 int sba_cmd)473{474 struct smt_sba_chg *chg ;475 SMbuf *mb ;476 void *p ;477 478 /*479 * get and initialize the response frame480 */481 if (sba_cmd == CHANGE_ALLOCATION) {482 if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,483 sizeof(struct smt_sba_chg))))484 return ;485 }486 else {487 if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,488 sizeof(struct smt_sba_rep_res))))489 return ;490 }491 492 chg = smtod(mb,struct smt_sba_chg *) ;493 chg->smt.smt_tid = sm->smt_tid ;494 chg->smt.smt_dest = sm->smt_source ;495 496 /* set P15 */497 chg->s_type.para.p_type = SMT_P0015 ;498 chg->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;499 chg->s_type.res_type = SYNC_BW ;500 501 /* set P16 */502 chg->cmd.para.p_type = SMT_P0016 ;503 chg->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;504 chg->cmd.sba_cmd = sba_cmd ;505 506 /* set P320B */507 chg->path.para.p_type = SMT_P320B ;508 chg->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;509 chg->path.mib_index = SBAPATHINDEX ;510 chg->path.path_pad = 0;511 chg->path.path_index = PRIMARY_RING ;512 513 /* set P320F */514 chg->payload.para.p_type = SMT_P320F ;515 chg->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;516 chg->payload.mib_index = SBAPATHINDEX ;517 chg->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;518 519 /* set P3210 */520 chg->overhead.para.p_type = SMT_P3210 ;521 chg->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;522 chg->overhead.mib_index = SBAPATHINDEX ;523 chg->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;524 525 if (sba_cmd == CHANGE_ALLOCATION) {526 /* set P1A */527 chg->cat.para.p_type = SMT_P001A ;528 chg->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;529 p = (void *) sm_to_para(smc,sm,SMT_P001A) ;530 chg->cat.category = ((struct smt_p_001a *)p)->category ;531 }532 dump_smt(smc,(struct smt_header *)chg,"RAF") ;533 ess_send_frame(smc,mb) ;534}535 536void ess_timer_poll(struct s_smc *smc)537{538 if (!smc->ess.raf_act_timer_poll)539 return ;540 541 DB_ESSN(2, "ESS: timer_poll");542 543 smc->ess.timer_count++ ;544 if (smc->ess.timer_count == 10) {545 smc->ess.timer_count = 0 ;546 ess_send_alc_req(smc) ;547 }548}549 550static void ess_send_alc_req(struct s_smc *smc)551{552 struct smt_sba_alc_req *req ;553 SMbuf *mb ;554 555 /*556 * send never allocation request where the requested payload and557 * overhead is zero or deallocate bandwidth when no bandwidth is558 * parsed559 */560 if (!smc->mib.fddiESSPayload) {561 smc->mib.fddiESSOverhead = 0 ;562 }563 else {564 if (!smc->mib.fddiESSOverhead)565 smc->mib.fddiESSOverhead = DEFAULT_OV ;566 }567 568 if (smc->mib.fddiESSOverhead ==569 smc->mib.a[PATH0].fddiPATHSbaOverhead &&570 smc->mib.fddiESSPayload ==571 smc->mib.a[PATH0].fddiPATHSbaPayload){572 smc->ess.raf_act_timer_poll = FALSE ;573 smc->ess.timer_count = 7 ; /* next RAF alc req after 3 s */574 return ;575 }576 577 /*578 * get and initialize the response frame579 */580 if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REQUEST,581 sizeof(struct smt_sba_alc_req))))582 return ;583 req = smtod(mb,struct smt_sba_alc_req *) ;584 req->smt.smt_tid = smc->ess.alloc_trans_id = smt_get_tid(smc) ;585 req->smt.smt_dest = smt_sba_da ;586 587 /* set P15 */588 req->s_type.para.p_type = SMT_P0015 ;589 req->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;590 req->s_type.res_type = SYNC_BW ;591 592 /* set P16 */593 req->cmd.para.p_type = SMT_P0016 ;594 req->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;595 req->cmd.sba_cmd = REQUEST_ALLOCATION ;596 597 /*598 * set the parameter type and parameter length of all used599 * parameters600 */601 602 /* set P320B */603 req->path.para.p_type = SMT_P320B ;604 req->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;605 req->path.mib_index = SBAPATHINDEX ;606 req->path.path_pad = 0;607 req->path.path_index = PRIMARY_RING ;608 609 /* set P0017 */610 req->pl_req.para.p_type = SMT_P0017 ;611 req->pl_req.para.p_len = sizeof(struct smt_p_0017) - PARA_LEN ;612 req->pl_req.sba_pl_req = smc->mib.fddiESSPayload -613 smc->mib.a[PATH0].fddiPATHSbaPayload ;614 615 /* set P0018 */616 req->ov_req.para.p_type = SMT_P0018 ;617 req->ov_req.para.p_len = sizeof(struct smt_p_0018) - PARA_LEN ;618 req->ov_req.sba_ov_req = smc->mib.fddiESSOverhead -619 smc->mib.a[PATH0].fddiPATHSbaOverhead ;620 621 /* set P320F */622 req->payload.para.p_type = SMT_P320F ;623 req->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;624 req->payload.mib_index = SBAPATHINDEX ;625 req->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;626 627 /* set P3210 */628 req->overhead.para.p_type = SMT_P3210 ;629 req->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;630 req->overhead.mib_index = SBAPATHINDEX ;631 req->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;632 633 /* set P19 */634 req->a_addr.para.p_type = SMT_P0019 ;635 req->a_addr.para.p_len = sizeof(struct smt_p_0019) - PARA_LEN ;636 req->a_addr.sba_pad = 0;637 req->a_addr.alloc_addr = null_addr ;638 639 /* set P1A */640 req->cat.para.p_type = SMT_P001A ;641 req->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;642 req->cat.category = smc->mib.fddiESSCategory ;643 644 /* set P1B */645 req->tneg.para.p_type = SMT_P001B ;646 req->tneg.para.p_len = sizeof(struct smt_p_001b) - PARA_LEN ;647 req->tneg.max_t_neg = smc->mib.fddiESSMaxTNeg ;648 649 /* set P1C */650 req->segm.para.p_type = SMT_P001C ;651 req->segm.para.p_len = sizeof(struct smt_p_001c) - PARA_LEN ;652 req->segm.min_seg_siz = smc->mib.fddiESSMinSegmentSize ;653 654 dump_smt(smc,(struct smt_header *)req,"RAF") ;655 ess_send_frame(smc,mb) ;656}657 658static void ess_send_frame(struct s_smc *smc, SMbuf *mb)659{660 /*661 * check if the frame must be send to the own ESS662 */663 if (smc->ess.local_sba_active) {664 /*665 * Send the Change Reply to the local SBA666 */667 DB_ESS("ESS:Send to the local SBA");668 if (!smc->ess.sba_reply_pend)669 smc->ess.sba_reply_pend = mb ;670 else {671 DB_ESS("Frame is lost - another frame was pending");672 smt_free_mbuf(smc,mb) ;673 }674 }675 else {676 /*677 * Send the SBA RAF Change Reply to the network678 */679 DB_ESS("ESS:Send to the network");680 smt_send_frame(smc,mb,FC_SMT_INFO,0) ;681 }682}683 684void ess_para_change(struct s_smc *smc)685{686 (void)process_bw_alloc(smc,(long)smc->mib.a[PATH0].fddiPATHSbaPayload,687 (long)smc->mib.a[PATH0].fddiPATHSbaOverhead) ;688}689 690static void ess_config_fifo(struct s_smc *smc)691{692 /*693 * if nothing to do exit 694 */695 if (smc->mib.a[PATH0].fddiPATHSbaPayload) {696 if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON &&697 (smc->hw.fp.fifo.fifo_config_mode&SEND_ASYNC_AS_SYNC) ==698 smc->mib.fddiESSSynchTxMode) {699 return ;700 }701 }702 else {703 if (!(smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON)) {704 return ;705 }706 }707 708 /*709 * split up the FIFO and reinitialize the queues710 */711 formac_reinit_tx(smc) ;712}713 714#endif /* ESS */715 716#endif /* no SLIM_SMT */717 718