| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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); | 
| Adrian Bunk | 7aa55fc | 2005-06-21 01:47:06 -0700 | [diff] [blame] | 105 | static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 138 | 		return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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); | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 150 | 		 return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 178 | 				return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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]) { | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 183 | 					return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 202 | 				return fs | I_INDICATOR; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 203 |  | 
 | 204 | 			if (!(db = smt_get_mbuf(smc))) | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 205 | 				return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 215 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 224 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 244 | 			DB_ESS("ESS: Allocation Response not accepted\n",0,0) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 245 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 271 | 		return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 283 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 291 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 303 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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)) | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 322 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 323 |  | 
 | 324 | 		/* | 
 | 325 | 		 * send an RAF Change Reply | 
 | 326 | 		 */ | 
 | 327 | 		ess_send_response(smc,sm,CHANGE_ALLOCATION) ; | 
 | 328 |  | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 329 | 		return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 341 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 352 | 			return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 353 | 		} | 
 | 354 |  | 
 | 355 | 		/* | 
 | 356 | 		 * send an RAF Change Reply | 
 | 357 | 		 */ | 
 | 358 | 		ess_send_response(smc,sm,REPORT_ALLOCATION) ; | 
 | 359 |  | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 360 | 		return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 371 | 	return fs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 372 | } | 
 | 373 |  | 
 | 374 | /* | 
 | 375 |  * determines the synchronous bandwidth, set the TSYNC register and the | 
 | 376 |  * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG. | 
 | 377 |  */ | 
| Adrian Bunk | 7aa55fc | 2005-06-21 01:47:06 -0700 | [diff] [blame] | 378 | static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  	 * | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 396 | 	 * T-NEG is described by the equation: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 421 | 		return FALSE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 425 | 		return FALSE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 426 | 	} */ | 
 | 427 |  | 
 | 428 | 	/* premliminary */ | 
 | 429 | 	if (payload > MAX_PAYLOAD || overhead > 5000) { | 
 | 430 | 		DB_ESS("ESS: payload / overhead not accepted\n",0,0) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 431 | 		return FALSE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) ; | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 471 | 	return TRUE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 	/* | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 482 | 	 * get and initialize the response frame | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 ; | 
| Takashi Iwai | c22ce6d | 2008-08-20 16:34:35 -0700 | [diff] [blame] | 513 | 	chg->path.path_pad = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 
| Daniel Mack | 551e378 | 2010-01-28 16:11:51 +0800 | [diff] [blame] | 560 | 	 * overhead is zero or deallocate bandwidth when no bandwidth is | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 	/* | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 581 | 	 * get and initialize the response frame | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 	/* | 
| Paulius Zaleckas | efad798b | 2008-02-03 15:42:53 +0200 | [diff] [blame] | 601 | 	 * set the parameter type and parameter length of all used | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 ; | 
| Takashi Iwai | c22ce6d | 2008-08-20 16:34:35 -0700 | [diff] [blame] | 609 | 	req->path.path_pad = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 ; | 
| Takashi Iwai | c22ce6d | 2008-08-20 16:34:35 -0700 | [diff] [blame] | 639 | 	req->a_addr.sba_pad = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  |