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