1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2016-2018, NXP Semiconductors 3 * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> 4 */ 5 #ifndef _SJA1105_STATIC_CONFIG_H 6 #define _SJA1105_STATIC_CONFIG_H 7 8 #include <linux/packing.h> 9 #include <linux/types.h> 10 #include <asm/types.h> 11 12 #define SJA1105_NUM_PORTS 5 13 #define SJA1110_NUM_PORTS 11 14 #define SJA1105_MAX_NUM_PORTS SJA1110_NUM_PORTS 15 #define SJA1105_NUM_TC 8 16 17 #define SJA1105_SIZE_SPI_MSG_HEADER 4 18 #define SJA1105_SIZE_SPI_MSG_MAXLEN (64 * 4) 19 #define SJA1105_SIZE_DEVICE_ID 4 20 #define SJA1105_SIZE_TABLE_HEADER 12 21 #define SJA1105_SIZE_SCHEDULE_ENTRY 8 22 #define SJA1110_SIZE_SCHEDULE_ENTRY 12 23 #define SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY 4 24 #define SJA1110_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY 8 25 #define SJA1105_SIZE_VL_LOOKUP_ENTRY 12 26 #define SJA1105_SIZE_VL_POLICING_ENTRY 8 27 #define SJA1105_SIZE_VL_FORWARDING_ENTRY 4 28 #define SJA1105_SIZE_L2_POLICING_ENTRY 8 29 #define SJA1105_SIZE_VLAN_LOOKUP_ENTRY 8 30 #define SJA1110_SIZE_VLAN_LOOKUP_ENTRY 12 31 #define SJA1105_SIZE_L2_FORWARDING_ENTRY 8 32 #define SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY 12 33 #define SJA1105_SIZE_RETAGGING_ENTRY 8 34 #define SJA1105_SIZE_XMII_PARAMS_ENTRY 4 35 #define SJA1110_SIZE_XMII_PARAMS_ENTRY 8 36 #define SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY 12 37 #define SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY 4 38 #define SJA1105_SIZE_VL_FORWARDING_PARAMS_ENTRY 12 39 #define SJA1105ET_SIZE_L2_LOOKUP_ENTRY 12 40 #define SJA1105ET_SIZE_MAC_CONFIG_ENTRY 28 41 #define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY 4 42 #define SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY 40 43 #define SJA1105ET_SIZE_AVB_PARAMS_ENTRY 12 44 #define SJA1105ET_SIZE_CBS_ENTRY 16 45 #define SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY 20 46 #define SJA1110_SIZE_L2_LOOKUP_ENTRY 24 47 #define SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY 32 48 #define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY 16 49 #define SJA1110_SIZE_L2_LOOKUP_PARAMS_ENTRY 28 50 #define SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY 44 51 #define SJA1110_SIZE_GENERAL_PARAMS_ENTRY 56 52 #define SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY 16 53 #define SJA1105PQRS_SIZE_CBS_ENTRY 20 54 #define SJA1110_SIZE_PCP_REMAPPING_ENTRY 4 55 56 /* UM10944.pdf Page 11, Table 2. Configuration Blocks */ 57 enum { 58 BLKID_SCHEDULE = 0x00, 59 BLKID_SCHEDULE_ENTRY_POINTS = 0x01, 60 BLKID_VL_LOOKUP = 0x02, 61 BLKID_VL_POLICING = 0x03, 62 BLKID_VL_FORWARDING = 0x04, 63 BLKID_L2_LOOKUP = 0x05, 64 BLKID_L2_POLICING = 0x06, 65 BLKID_VLAN_LOOKUP = 0x07, 66 BLKID_L2_FORWARDING = 0x08, 67 BLKID_MAC_CONFIG = 0x09, 68 BLKID_SCHEDULE_PARAMS = 0x0A, 69 BLKID_SCHEDULE_ENTRY_POINTS_PARAMS = 0x0B, 70 BLKID_VL_FORWARDING_PARAMS = 0x0C, 71 BLKID_L2_LOOKUP_PARAMS = 0x0D, 72 BLKID_L2_FORWARDING_PARAMS = 0x0E, 73 BLKID_AVB_PARAMS = 0x10, 74 BLKID_GENERAL_PARAMS = 0x11, 75 BLKID_RETAGGING = 0x12, 76 BLKID_CBS = 0x13, 77 BLKID_PCP_REMAPPING = 0x1C, 78 BLKID_XMII_PARAMS = 0x4E, 79 }; 80 81 enum sja1105_blk_idx { 82 BLK_IDX_SCHEDULE = 0, 83 BLK_IDX_SCHEDULE_ENTRY_POINTS, 84 BLK_IDX_VL_LOOKUP, 85 BLK_IDX_VL_POLICING, 86 BLK_IDX_VL_FORWARDING, 87 BLK_IDX_L2_LOOKUP, 88 BLK_IDX_L2_POLICING, 89 BLK_IDX_VLAN_LOOKUP, 90 BLK_IDX_L2_FORWARDING, 91 BLK_IDX_MAC_CONFIG, 92 BLK_IDX_SCHEDULE_PARAMS, 93 BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS, 94 BLK_IDX_VL_FORWARDING_PARAMS, 95 BLK_IDX_L2_LOOKUP_PARAMS, 96 BLK_IDX_L2_FORWARDING_PARAMS, 97 BLK_IDX_AVB_PARAMS, 98 BLK_IDX_GENERAL_PARAMS, 99 BLK_IDX_RETAGGING, 100 BLK_IDX_CBS, 101 BLK_IDX_XMII_PARAMS, 102 BLK_IDX_PCP_REMAPPING, 103 BLK_IDX_MAX, 104 /* Fake block indices that are only valid for dynamic access */ 105 BLK_IDX_MGMT_ROUTE, 106 BLK_IDX_MAX_DYN, 107 BLK_IDX_INVAL = -1, 108 }; 109 110 #define SJA1105_MAX_SCHEDULE_COUNT 1024 111 #define SJA1110_MAX_SCHEDULE_COUNT 4096 112 #define SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT 2048 113 #define SJA1105_MAX_VL_LOOKUP_COUNT 1024 114 #define SJA1110_MAX_VL_LOOKUP_COUNT 4096 115 #define SJA1105_MAX_VL_POLICING_COUNT 1024 116 #define SJA1110_MAX_VL_POLICING_COUNT 4096 117 #define SJA1105_MAX_VL_FORWARDING_COUNT 1024 118 #define SJA1110_MAX_VL_FORWARDING_COUNT 4096 119 #define SJA1105_MAX_L2_LOOKUP_COUNT 1024 120 #define SJA1105_MAX_L2_POLICING_COUNT 45 121 #define SJA1110_MAX_L2_POLICING_COUNT 110 122 #define SJA1105_MAX_VLAN_LOOKUP_COUNT 4096 123 #define SJA1105_MAX_L2_FORWARDING_COUNT 13 124 #define SJA1110_MAX_L2_FORWARDING_COUNT 19 125 #define SJA1105_MAX_MAC_CONFIG_COUNT 5 126 #define SJA1110_MAX_MAC_CONFIG_COUNT 11 127 #define SJA1105_MAX_SCHEDULE_PARAMS_COUNT 1 128 #define SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT 1 129 #define SJA1105_MAX_VL_FORWARDING_PARAMS_COUNT 1 130 #define SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT 1 131 #define SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT 1 132 #define SJA1105_MAX_GENERAL_PARAMS_COUNT 1 133 #define SJA1105_MAX_RETAGGING_COUNT 32 134 #define SJA1105_MAX_XMII_PARAMS_COUNT 1 135 #define SJA1105_MAX_AVB_PARAMS_COUNT 1 136 #define SJA1105ET_MAX_CBS_COUNT 10 137 #define SJA1105PQRS_MAX_CBS_COUNT 16 138 #define SJA1110_MAX_CBS_COUNT 80 139 #define SJA1110_MAX_PCP_REMAPPING_COUNT 11 140 141 #define SJA1105_MAX_FRAME_MEMORY 929 142 #define SJA1110_MAX_FRAME_MEMORY 1820 143 #define SJA1105_FRAME_MEMORY_RETAGGING_OVERHEAD 19 144 #define SJA1105_VL_FRAME_MEMORY 100 145 146 #define SJA1105E_DEVICE_ID 0x9C00000Cull 147 #define SJA1105T_DEVICE_ID 0x9E00030Eull 148 #define SJA1105PR_DEVICE_ID 0xAF00030Eull 149 #define SJA1105QS_DEVICE_ID 0xAE00030Eull 150 #define SJA1110_DEVICE_ID 0xB700030Full 151 152 #define SJA1105ET_PART_NO 0x9A83 153 #define SJA1105P_PART_NO 0x9A84 154 #define SJA1105Q_PART_NO 0x9A85 155 #define SJA1105R_PART_NO 0x9A86 156 #define SJA1105S_PART_NO 0x9A87 157 #define SJA1110A_PART_NO 0x1110 158 #define SJA1110B_PART_NO 0x1111 159 #define SJA1110C_PART_NO 0x1112 160 #define SJA1110D_PART_NO 0x1113 161 162 #define SJA1110_ACU 0x1c4400 163 #define SJA1110_RGU 0x1c6000 164 #define SJA1110_CGU 0x1c6400 165 166 #define SJA1110_SPI_ADDR(x) ((x) / 4) 167 #define SJA1110_ACU_ADDR(x) (SJA1110_ACU + SJA1110_SPI_ADDR(x)) 168 #define SJA1110_CGU_ADDR(x) (SJA1110_CGU + SJA1110_SPI_ADDR(x)) 169 #define SJA1110_RGU_ADDR(x) (SJA1110_RGU + SJA1110_SPI_ADDR(x)) 170 171 #define SJA1105_RSV_ADDR 0xffffffffffffffffull 172 173 struct sja1105_schedule_entry { 174 u64 winstindex; 175 u64 winend; 176 u64 winst; 177 u64 destports; 178 u64 setvalid; 179 u64 txen; 180 u64 resmedia_en; 181 u64 resmedia; 182 u64 vlindex; 183 u64 delta; 184 }; 185 186 struct sja1105_schedule_params_entry { 187 u64 subscheind[8]; 188 }; 189 190 struct sja1105_general_params_entry { 191 u64 vllupformat; 192 u64 mirr_ptacu; 193 u64 switchid; 194 u64 hostprio; 195 u64 mac_fltres1; 196 u64 mac_fltres0; 197 u64 mac_flt1; 198 u64 mac_flt0; 199 u64 incl_srcpt1; 200 u64 incl_srcpt0; 201 u64 send_meta1; 202 u64 send_meta0; 203 u64 casc_port; 204 u64 host_port; 205 u64 mirr_port; 206 u64 vlmarker; 207 u64 vlmask; 208 u64 tpid; 209 u64 ignore2stf; 210 u64 tpid2; 211 /* P/Q/R/S only */ 212 u64 queue_ts; 213 u64 egrmirrvid; 214 u64 egrmirrpcp; 215 u64 egrmirrdei; 216 u64 replay_port; 217 /* SJA1110 only */ 218 u64 tte_en; 219 u64 tdmaconfigidx; 220 u64 header_type; 221 }; 222 223 struct sja1105_schedule_entry_points_entry { 224 u64 subschindx; 225 u64 delta; 226 u64 address; 227 }; 228 229 struct sja1105_schedule_entry_points_params_entry { 230 u64 clksrc; 231 u64 actsubsch; 232 }; 233 234 struct sja1105_vlan_lookup_entry { 235 u64 ving_mirr; 236 u64 vegr_mirr; 237 u64 vmemb_port; 238 u64 vlan_bc; 239 u64 tag_port; 240 u64 vlanid; 241 u64 type_entry; /* SJA1110 only */ 242 }; 243 244 struct sja1105_l2_lookup_entry { 245 u64 vlanid; 246 u64 macaddr; 247 u64 destports; 248 u64 enfport; 249 u64 index; 250 /* P/Q/R/S only */ 251 u64 mask_iotag; 252 u64 mask_vlanid; 253 u64 mask_macaddr; 254 u64 mask_srcport; 255 u64 iotag; 256 u64 srcport; 257 u64 lockeds; 258 union { 259 /* LOCKEDS=1: Static FDB entries */ 260 struct { 261 /* TSREG is deprecated in SJA1110, TRAP is supported only 262 * in SJA1110. 263 */ 264 u64 trap; 265 u64 tsreg; 266 u64 mirrvlan; 267 u64 takets; 268 u64 mirr; 269 u64 retag; 270 }; 271 /* LOCKEDS=0: Dynamically learned FDB entries */ 272 struct { 273 u64 touched; 274 u64 age; 275 }; 276 }; 277 }; 278 279 struct sja1105_l2_lookup_params_entry { 280 u64 maxaddrp[SJA1105_MAX_NUM_PORTS]; /* P/Q/R/S only */ 281 u64 start_dynspc; /* P/Q/R/S only */ 282 u64 drpnolearn; /* P/Q/R/S only */ 283 u64 use_static; /* P/Q/R/S only */ 284 u64 owr_dyn; /* P/Q/R/S only */ 285 u64 learn_once; /* P/Q/R/S only */ 286 u64 maxage; /* Shared */ 287 u64 dyn_tbsz; /* E/T only */ 288 u64 poly; /* E/T only */ 289 u64 shared_learn; /* Shared */ 290 u64 no_enf_hostprt; /* Shared */ 291 u64 no_mgmt_learn; /* Shared */ 292 }; 293 294 struct sja1105_l2_forwarding_entry { 295 u64 bc_domain; 296 u64 reach_port; 297 u64 fl_domain; 298 /* This is actually max(SJA1105_NUM_TC, SJA1105_MAX_NUM_PORTS) */ 299 u64 vlan_pmap[SJA1105_MAX_NUM_PORTS]; 300 bool type_egrpcp2outputq; 301 }; 302 303 struct sja1105_l2_forwarding_params_entry { 304 u64 max_dynp; 305 u64 part_spc[8]; 306 }; 307 308 struct sja1105_l2_policing_entry { 309 u64 sharindx; 310 u64 smax; 311 u64 rate; 312 u64 maxlen; 313 u64 partition; 314 }; 315 316 struct sja1105_avb_params_entry { 317 u64 cas_master; 318 u64 destmeta; 319 u64 srcmeta; 320 }; 321 322 struct sja1105_mac_config_entry { 323 u64 top[8]; 324 u64 base[8]; 325 u64 enabled[8]; 326 u64 ifg; 327 u64 speed; 328 u64 tp_delin; 329 u64 tp_delout; 330 u64 maxage; 331 u64 vlanprio; 332 u64 vlanid; 333 u64 ing_mirr; 334 u64 egr_mirr; 335 u64 drpnona664; 336 u64 drpdtag; 337 u64 drpuntag; 338 u64 retag; 339 u64 dyn_learn; 340 u64 egress; 341 u64 ingress; 342 }; 343 344 struct sja1105_retagging_entry { 345 u64 egr_port; 346 u64 ing_port; 347 u64 vlan_ing; 348 u64 vlan_egr; 349 u64 do_not_learn; 350 u64 use_dest_ports; 351 u64 destports; 352 }; 353 354 struct sja1105_cbs_entry { 355 u64 port; /* Not used for SJA1110 */ 356 u64 prio; /* Not used for SJA1110 */ 357 u64 credit_hi; 358 u64 credit_lo; 359 u64 send_slope; 360 u64 idle_slope; 361 }; 362 363 struct sja1105_xmii_params_entry { 364 u64 phy_mac[SJA1105_MAX_NUM_PORTS]; 365 u64 xmii_mode[SJA1105_MAX_NUM_PORTS]; 366 /* The SJA1110 insists being a snowflake, and requires SGMII, 367 * 2500base-x and internal MII ports connected to the 100base-TX PHY to 368 * set this bit. We set it unconditionally from the high-level logic, 369 * and only sja1110_xmii_params_entry_packing writes it to the static 370 * config. I have no better name for it than "special". 371 */ 372 u64 special[SJA1105_MAX_NUM_PORTS]; 373 }; 374 375 struct sja1110_pcp_remapping_entry { 376 u64 egrpcp[SJA1105_NUM_TC]; 377 }; 378 379 enum { 380 SJA1105_VL_FORMAT_PSFP = 0, 381 SJA1105_VL_FORMAT_ARINC664 = 1, 382 }; 383 384 struct sja1105_vl_lookup_entry { 385 u64 format; 386 u64 port; 387 union { 388 /* SJA1105_VL_FORMAT_PSFP */ 389 struct { 390 u64 destports; 391 u64 iscritical; 392 u64 macaddr; 393 u64 vlanid; 394 u64 vlanprior; 395 }; 396 /* SJA1105_VL_FORMAT_ARINC664 */ 397 struct { 398 u64 egrmirr; 399 u64 ingrmirr; 400 u64 vlid; 401 }; 402 }; 403 /* Not part of hardware structure */ 404 unsigned long flow_cookie; 405 }; 406 407 struct sja1105_vl_policing_entry { 408 u64 type; 409 u64 maxlen; 410 u64 sharindx; 411 u64 bag; 412 u64 jitter; 413 }; 414 415 struct sja1105_vl_forwarding_entry { 416 u64 type; 417 u64 priority; 418 u64 partition; 419 u64 destports; 420 }; 421 422 struct sja1105_vl_forwarding_params_entry { 423 u64 partspc[8]; 424 u64 debugen; 425 }; 426 427 struct sja1105_table_header { 428 u64 block_id; 429 u64 len; 430 u64 crc; 431 }; 432 433 struct sja1105_table_ops { 434 size_t (*packing)(void *buf, void *entry_ptr, enum packing_op op); 435 size_t unpacked_entry_size; 436 size_t packed_entry_size; 437 size_t max_entry_count; 438 }; 439 440 struct sja1105_table { 441 const struct sja1105_table_ops *ops; 442 size_t entry_count; 443 void *entries; 444 }; 445 446 struct sja1105_static_config { 447 u64 device_id; 448 struct sja1105_table tables[BLK_IDX_MAX]; 449 }; 450 451 extern const struct sja1105_table_ops sja1105e_table_ops[BLK_IDX_MAX]; 452 extern const struct sja1105_table_ops sja1105t_table_ops[BLK_IDX_MAX]; 453 extern const struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX]; 454 extern const struct sja1105_table_ops sja1105q_table_ops[BLK_IDX_MAX]; 455 extern const struct sja1105_table_ops sja1105r_table_ops[BLK_IDX_MAX]; 456 extern const struct sja1105_table_ops sja1105s_table_ops[BLK_IDX_MAX]; 457 extern const struct sja1105_table_ops sja1110_table_ops[BLK_IDX_MAX]; 458 459 size_t sja1105_table_header_packing(void *buf, void *hdr, enum packing_op op); 460 void 461 sja1105_table_header_pack_with_crc(void *buf, struct sja1105_table_header *hdr); 462 size_t 463 sja1105_static_config_get_length(const struct sja1105_static_config *config); 464 465 typedef enum { 466 SJA1105_CONFIG_OK = 0, 467 SJA1105_TTETHERNET_NOT_SUPPORTED, 468 SJA1105_INCORRECT_TTETHERNET_CONFIGURATION, 469 SJA1105_INCORRECT_VIRTUAL_LINK_CONFIGURATION, 470 SJA1105_MISSING_L2_POLICING_TABLE, 471 SJA1105_MISSING_L2_FORWARDING_TABLE, 472 SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE, 473 SJA1105_MISSING_GENERAL_PARAMS_TABLE, 474 SJA1105_MISSING_VLAN_TABLE, 475 SJA1105_MISSING_XMII_TABLE, 476 SJA1105_MISSING_MAC_TABLE, 477 SJA1105_OVERCOMMITTED_FRAME_MEMORY, 478 } sja1105_config_valid_t; 479 480 extern const char *sja1105_static_config_error_msg[]; 481 482 sja1105_config_valid_t 483 sja1105_static_config_check_valid(const struct sja1105_static_config *config, 484 int max_mem); 485 void 486 sja1105_static_config_pack(void *buf, struct sja1105_static_config *config); 487 int sja1105_static_config_init(struct sja1105_static_config *config, 488 const struct sja1105_table_ops *static_ops, 489 u64 device_id); 490 void sja1105_static_config_free(struct sja1105_static_config *config); 491 492 int sja1105_table_delete_entry(struct sja1105_table *table, int i); 493 int sja1105_table_resize(struct sja1105_table *table, size_t new_count); 494 495 u32 sja1105_crc32(const void *buf, size_t len); 496 497 void sja1105_pack(void *buf, const u64 *val, int start, int end, size_t len); 498 void sja1105_unpack(const void *buf, u64 *val, int start, int end, size_t len); 499 void sja1105_packing(void *buf, u64 *val, int start, int end, 500 size_t len, enum packing_op op); 501 502 /* Common implementations for the static and dynamic configs */ 503 size_t sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr, 504 enum packing_op op); 505 size_t sja1110_general_params_entry_packing(void *buf, void *entry_ptr, 506 enum packing_op op); 507 size_t sja1105pqrs_l2_lookup_params_entry_packing(void *buf, void *entry_ptr, 508 enum packing_op op); 509 size_t sja1110_l2_lookup_params_entry_packing(void *buf, void *entry_ptr, 510 enum packing_op op); 511 size_t sja1105_l2_forwarding_entry_packing(void *buf, void *entry_ptr, 512 enum packing_op op); 513 size_t sja1110_l2_forwarding_entry_packing(void *buf, void *entry_ptr, 514 enum packing_op op); 515 size_t sja1105pqrs_l2_lookup_entry_packing(void *buf, void *entry_ptr, 516 enum packing_op op); 517 size_t sja1105et_l2_lookup_entry_packing(void *buf, void *entry_ptr, 518 enum packing_op op); 519 size_t sja1110_l2_lookup_entry_packing(void *buf, void *entry_ptr, 520 enum packing_op op); 521 size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr, 522 enum packing_op op); 523 size_t sja1110_vlan_lookup_entry_packing(void *buf, void *entry_ptr, 524 enum packing_op op); 525 size_t sja1105_retagging_entry_packing(void *buf, void *entry_ptr, 526 enum packing_op op); 527 size_t sja1110_retagging_entry_packing(void *buf, void *entry_ptr, 528 enum packing_op op); 529 size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr, 530 enum packing_op op); 531 size_t sja1110_mac_config_entry_packing(void *buf, void *entry_ptr, 532 enum packing_op op); 533 size_t sja1105pqrs_avb_params_entry_packing(void *buf, void *entry_ptr, 534 enum packing_op op); 535 size_t sja1105_vl_lookup_entry_packing(void *buf, void *entry_ptr, 536 enum packing_op op); 537 size_t sja1110_vl_lookup_entry_packing(void *buf, void *entry_ptr, 538 enum packing_op op); 539 size_t sja1110_vl_policing_entry_packing(void *buf, void *entry_ptr, 540 enum packing_op op); 541 size_t sja1110_xmii_params_entry_packing(void *buf, void *entry_ptr, 542 enum packing_op op); 543 size_t sja1110_l2_policing_entry_packing(void *buf, void *entry_ptr, 544 enum packing_op op); 545 size_t sja1110_l2_forwarding_params_entry_packing(void *buf, void *entry_ptr, 546 enum packing_op op); 547 548 #endif 549