1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#ifndef SCSI_TRANSPORT_FC_H
28#define SCSI_TRANSPORT_FC_H
29
30#include <linux/sched.h>
31#include <linux/bsg-lib.h>
32#include <asm/unaligned.h>
33#include <scsi/scsi.h>
34#include <scsi/scsi_netlink.h>
35#include <scsi/scsi_host.h>
36
37struct scsi_transport_template;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59enum fc_port_type {
60 FC_PORTTYPE_UNKNOWN,
61 FC_PORTTYPE_OTHER,
62 FC_PORTTYPE_NOTPRESENT,
63 FC_PORTTYPE_NPORT,
64 FC_PORTTYPE_NLPORT,
65 FC_PORTTYPE_LPORT,
66 FC_PORTTYPE_PTP,
67 FC_PORTTYPE_NPIV,
68};
69
70
71
72
73
74
75enum fc_port_state {
76 FC_PORTSTATE_UNKNOWN,
77 FC_PORTSTATE_NOTPRESENT,
78 FC_PORTSTATE_ONLINE,
79 FC_PORTSTATE_OFFLINE,
80 FC_PORTSTATE_BLOCKED,
81 FC_PORTSTATE_BYPASSED,
82 FC_PORTSTATE_DIAGNOSTICS,
83 FC_PORTSTATE_LINKDOWN,
84 FC_PORTSTATE_ERROR,
85 FC_PORTSTATE_LOOPBACK,
86 FC_PORTSTATE_DELETED,
87};
88
89
90
91
92
93
94enum fc_vport_state {
95 FC_VPORT_UNKNOWN,
96 FC_VPORT_ACTIVE,
97 FC_VPORT_DISABLED,
98 FC_VPORT_LINKDOWN,
99 FC_VPORT_INITIALIZING,
100 FC_VPORT_NO_FABRIC_SUPP,
101 FC_VPORT_NO_FABRIC_RSCS,
102 FC_VPORT_FABRIC_LOGOUT,
103 FC_VPORT_FABRIC_REJ_WWN,
104 FC_VPORT_FAILED,
105};
106
107
108
109
110
111
112
113
114
115#define FC_COS_UNSPECIFIED 0
116#define FC_COS_CLASS1 2
117#define FC_COS_CLASS2 4
118#define FC_COS_CLASS3 8
119#define FC_COS_CLASS4 0x10
120#define FC_COS_CLASS6 0x40
121
122
123
124
125
126
127
128#define FC_PORTSPEED_UNKNOWN 0
129
130#define FC_PORTSPEED_1GBIT 1
131#define FC_PORTSPEED_2GBIT 2
132#define FC_PORTSPEED_10GBIT 4
133#define FC_PORTSPEED_4GBIT 8
134#define FC_PORTSPEED_8GBIT 0x10
135#define FC_PORTSPEED_16GBIT 0x20
136#define FC_PORTSPEED_32GBIT 0x40
137#define FC_PORTSPEED_20GBIT 0x80
138#define FC_PORTSPEED_40GBIT 0x100
139#define FC_PORTSPEED_50GBIT 0x200
140#define FC_PORTSPEED_100GBIT 0x400
141#define FC_PORTSPEED_25GBIT 0x800
142#define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15)
143
144
145
146
147
148enum fc_tgtid_binding_type {
149 FC_TGTID_BIND_NONE,
150 FC_TGTID_BIND_BY_WWPN,
151 FC_TGTID_BIND_BY_WWNN,
152 FC_TGTID_BIND_BY_ID,
153};
154
155
156
157
158
159
160
161#define FC_PORT_ROLE_UNKNOWN 0x00
162#define FC_PORT_ROLE_FCP_TARGET 0x01
163#define FC_PORT_ROLE_FCP_INITIATOR 0x02
164#define FC_PORT_ROLE_IP_PORT 0x04
165
166
167#define FC_RPORT_ROLE_UNKNOWN FC_PORT_ROLE_UNKNOWN
168#define FC_RPORT_ROLE_FCP_TARGET FC_PORT_ROLE_FCP_TARGET
169#define FC_RPORT_ROLE_FCP_INITIATOR FC_PORT_ROLE_FCP_INITIATOR
170#define FC_RPORT_ROLE_IP_PORT FC_PORT_ROLE_IP_PORT
171
172
173
174#define FC_VPORT_ATTR(_name,_mode,_show,_store) \
175struct device_attribute dev_attr_vport_##_name = \
176 __ATTR(_name,_mode,_show,_store)
177
178
179
180
181
182
183
184
185
186
187
188
189#define FC_VPORT_SYMBOLIC_NAMELEN 64
190struct fc_vport_identifiers {
191 u64 node_name;
192 u64 port_name;
193 u32 roles;
194 bool disable;
195 enum fc_port_type vport_type;
196 char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
197};
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228struct fc_vport {
229
230
231
232
233
234 enum fc_vport_state vport_state;
235 enum fc_vport_state vport_last_state;
236 u64 node_name;
237 u64 port_name;
238 u32 roles;
239 u32 vport_id;
240 enum fc_port_type vport_type;
241 char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
242
243
244 void *dd_data;
245
246
247 struct Scsi_Host *shost;
248 unsigned int channel;
249 u32 number;
250 u8 flags;
251 struct list_head peers;
252 struct device dev;
253 struct work_struct vport_delete_work;
254} __attribute__((aligned(sizeof(unsigned long))));
255
256
257#define FC_VPORT_CREATING 0x01
258#define FC_VPORT_DELETING 0x02
259#define FC_VPORT_DELETED 0x04
260#define FC_VPORT_DEL 0x06
261
262#define dev_to_vport(d) \
263 container_of(d, struct fc_vport, dev)
264#define transport_class_to_vport(dev) \
265 dev_to_vport(dev->parent)
266#define vport_to_shost(v) \
267 (v->shost)
268#define vport_to_shost_channel(v) \
269 (v->channel)
270#define vport_to_parent(v) \
271 (v->dev.parent)
272
273
274
275#define VPCERR_UNSUPPORTED -ENOSYS
276
277#define VPCERR_BAD_WWN -ENOTUNIQ
278
279#define VPCERR_NO_FABRIC_SUPP -EOPNOTSUPP
280
281
282
283
284
285
286
287
288
289
290
291struct fc_rport_identifiers {
292 u64 node_name;
293 u64 port_name;
294 u32 port_id;
295 u32 roles;
296};
297
298
299
300#define FC_RPORT_ATTR(_name,_mode,_show,_store) \
301struct device_attribute dev_attr_rport_##_name = \
302 __ATTR(_name,_mode,_show,_store)
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332struct fc_rport {
333
334 u32 maxframe_size;
335 u32 supported_classes;
336
337
338 u32 dev_loss_tmo;
339
340
341 u64 node_name;
342 u64 port_name;
343 u32 port_id;
344 u32 roles;
345 enum fc_port_state port_state;
346 u32 scsi_target_id;
347 u32 fast_io_fail_tmo;
348
349
350 void *dd_data;
351
352
353 unsigned int channel;
354 u32 number;
355 u8 flags;
356 struct list_head peers;
357 struct device dev;
358 struct delayed_work dev_loss_work;
359 struct work_struct scan_work;
360 struct delayed_work fail_io_work;
361 struct work_struct stgt_delete_work;
362 struct work_struct rport_delete_work;
363 struct request_queue *rqst_q;
364} __attribute__((aligned(sizeof(unsigned long))));
365
366
367#define FC_RPORT_DEVLOSS_PENDING 0x01
368#define FC_RPORT_SCAN_PENDING 0x02
369#define FC_RPORT_FAST_FAIL_TIMEDOUT 0x04
370#define FC_RPORT_DEVLOSS_CALLBK_DONE 0x08
371
372#define dev_to_rport(d) \
373 container_of(d, struct fc_rport, dev)
374#define transport_class_to_rport(dev) \
375 dev_to_rport(dev->parent)
376#define rport_to_shost(r) \
377 dev_to_shost(r->dev.parent)
378
379
380
381
382
383
384
385
386
387
388
389
390
391struct fc_starget_attrs {
392
393 u64 node_name;
394 u64 port_name;
395 u32 port_id;
396};
397
398#define fc_starget_node_name(x) \
399 (((struct fc_starget_attrs *)&(x)->starget_data)->node_name)
400#define fc_starget_port_name(x) \
401 (((struct fc_starget_attrs *)&(x)->starget_data)->port_name)
402#define fc_starget_port_id(x) \
403 (((struct fc_starget_attrs *)&(x)->starget_data)->port_id)
404
405#define starget_to_rport(s) \
406 scsi_is_fc_rport(s->dev.parent) ? dev_to_rport(s->dev.parent) : NULL
407
408
409
410
411
412
413
414struct fc_host_statistics {
415
416 u64 seconds_since_last_reset;
417 u64 tx_frames;
418 u64 tx_words;
419 u64 rx_frames;
420 u64 rx_words;
421 u64 lip_count;
422 u64 nos_count;
423 u64 error_frames;
424 u64 dumped_frames;
425 u64 link_failure_count;
426 u64 loss_of_sync_count;
427 u64 loss_of_signal_count;
428 u64 prim_seq_protocol_err_count;
429 u64 invalid_tx_word_count;
430 u64 invalid_crc_count;
431
432
433 u64 fcp_input_requests;
434 u64 fcp_output_requests;
435 u64 fcp_control_requests;
436 u64 fcp_input_megabytes;
437 u64 fcp_output_megabytes;
438 u64 fcp_packet_alloc_failures;
439 u64 fcp_packet_aborts;
440 u64 fcp_frame_alloc_failures;
441
442
443 u64 fc_no_free_exch;
444 u64 fc_no_free_exch_xid;
445 u64 fc_xid_not_found;
446 u64 fc_xid_busy;
447 u64 fc_seq_not_found;
448 u64 fc_non_bls_resp;
449
450};
451
452
453
454
455
456
457
458
459
460
461enum fc_host_event_code {
462 FCH_EVT_LIP = 0x1,
463 FCH_EVT_LINKUP = 0x2,
464 FCH_EVT_LINKDOWN = 0x3,
465 FCH_EVT_LIPRESET = 0x4,
466 FCH_EVT_RSCN = 0x5,
467 FCH_EVT_ADAPTER_CHANGE = 0x103,
468 FCH_EVT_PORT_UNKNOWN = 0x200,
469 FCH_EVT_PORT_OFFLINE = 0x201,
470 FCH_EVT_PORT_ONLINE = 0x202,
471 FCH_EVT_PORT_FABRIC = 0x204,
472 FCH_EVT_LINK_UNKNOWN = 0x500,
473 FCH_EVT_VENDOR_UNIQUE = 0xffff,
474};
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494#define FC_FC4_LIST_SIZE 32
495#define FC_SYMBOLIC_NAME_SIZE 256
496#define FC_VERSION_STRING_SIZE 64
497#define FC_SERIAL_NUMBER_SIZE 80
498
499struct fc_host_attrs {
500
501 u64 node_name;
502 u64 port_name;
503 u64 permanent_port_name;
504 u32 supported_classes;
505 u8 supported_fc4s[FC_FC4_LIST_SIZE];
506 u32 supported_speeds;
507 u32 maxframe_size;
508 u16 max_npiv_vports;
509 char serial_number[FC_SERIAL_NUMBER_SIZE];
510 char manufacturer[FC_SERIAL_NUMBER_SIZE];
511 char model[FC_SYMBOLIC_NAME_SIZE];
512 char model_description[FC_SYMBOLIC_NAME_SIZE];
513 char hardware_version[FC_VERSION_STRING_SIZE];
514 char driver_version[FC_VERSION_STRING_SIZE];
515 char firmware_version[FC_VERSION_STRING_SIZE];
516 char optionrom_version[FC_VERSION_STRING_SIZE];
517
518
519 u32 port_id;
520 enum fc_port_type port_type;
521 enum fc_port_state port_state;
522 u8 active_fc4s[FC_FC4_LIST_SIZE];
523 u32 speed;
524 u64 fabric_name;
525 char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
526 char system_hostname[FC_SYMBOLIC_NAME_SIZE];
527 u32 dev_loss_tmo;
528
529
530 enum fc_tgtid_binding_type tgtid_bind_type;
531
532
533 struct list_head rports;
534 struct list_head rport_bindings;
535 struct list_head vports;
536 u32 next_rport_number;
537 u32 next_target_id;
538 u32 next_vport_number;
539 u16 npiv_vports_inuse;
540
541
542 char work_q_name[20];
543 struct workqueue_struct *work_q;
544 char devloss_work_q_name[20];
545 struct workqueue_struct *devloss_work_q;
546
547
548 struct request_queue *rqst_q;
549};
550
551#define shost_to_fc_host(x) \
552 ((struct fc_host_attrs *)(x)->shost_data)
553
554#define fc_host_node_name(x) \
555 (((struct fc_host_attrs *)(x)->shost_data)->node_name)
556#define fc_host_port_name(x) \
557 (((struct fc_host_attrs *)(x)->shost_data)->port_name)
558#define fc_host_permanent_port_name(x) \
559 (((struct fc_host_attrs *)(x)->shost_data)->permanent_port_name)
560#define fc_host_supported_classes(x) \
561 (((struct fc_host_attrs *)(x)->shost_data)->supported_classes)
562#define fc_host_supported_fc4s(x) \
563 (((struct fc_host_attrs *)(x)->shost_data)->supported_fc4s)
564#define fc_host_supported_speeds(x) \
565 (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
566#define fc_host_maxframe_size(x) \
567 (((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
568#define fc_host_max_npiv_vports(x) \
569 (((struct fc_host_attrs *)(x)->shost_data)->max_npiv_vports)
570#define fc_host_serial_number(x) \
571 (((struct fc_host_attrs *)(x)->shost_data)->serial_number)
572#define fc_host_manufacturer(x) \
573 (((struct fc_host_attrs *)(x)->shost_data)->manufacturer)
574#define fc_host_model(x) \
575 (((struct fc_host_attrs *)(x)->shost_data)->model)
576#define fc_host_model_description(x) \
577 (((struct fc_host_attrs *)(x)->shost_data)->model_description)
578#define fc_host_hardware_version(x) \
579 (((struct fc_host_attrs *)(x)->shost_data)->hardware_version)
580#define fc_host_driver_version(x) \
581 (((struct fc_host_attrs *)(x)->shost_data)->driver_version)
582#define fc_host_firmware_version(x) \
583 (((struct fc_host_attrs *)(x)->shost_data)->firmware_version)
584#define fc_host_optionrom_version(x) \
585 (((struct fc_host_attrs *)(x)->shost_data)->optionrom_version)
586#define fc_host_port_id(x) \
587 (((struct fc_host_attrs *)(x)->shost_data)->port_id)
588#define fc_host_port_type(x) \
589 (((struct fc_host_attrs *)(x)->shost_data)->port_type)
590#define fc_host_port_state(x) \
591 (((struct fc_host_attrs *)(x)->shost_data)->port_state)
592#define fc_host_active_fc4s(x) \
593 (((struct fc_host_attrs *)(x)->shost_data)->active_fc4s)
594#define fc_host_speed(x) \
595 (((struct fc_host_attrs *)(x)->shost_data)->speed)
596#define fc_host_fabric_name(x) \
597 (((struct fc_host_attrs *)(x)->shost_data)->fabric_name)
598#define fc_host_symbolic_name(x) \
599 (((struct fc_host_attrs *)(x)->shost_data)->symbolic_name)
600#define fc_host_system_hostname(x) \
601 (((struct fc_host_attrs *)(x)->shost_data)->system_hostname)
602#define fc_host_tgtid_bind_type(x) \
603 (((struct fc_host_attrs *)(x)->shost_data)->tgtid_bind_type)
604#define fc_host_rports(x) \
605 (((struct fc_host_attrs *)(x)->shost_data)->rports)
606#define fc_host_rport_bindings(x) \
607 (((struct fc_host_attrs *)(x)->shost_data)->rport_bindings)
608#define fc_host_vports(x) \
609 (((struct fc_host_attrs *)(x)->shost_data)->vports)
610#define fc_host_next_rport_number(x) \
611 (((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
612#define fc_host_next_target_id(x) \
613 (((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
614#define fc_host_next_vport_number(x) \
615 (((struct fc_host_attrs *)(x)->shost_data)->next_vport_number)
616#define fc_host_npiv_vports_inuse(x) \
617 (((struct fc_host_attrs *)(x)->shost_data)->npiv_vports_inuse)
618#define fc_host_work_q_name(x) \
619 (((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
620#define fc_host_work_q(x) \
621 (((struct fc_host_attrs *)(x)->shost_data)->work_q)
622#define fc_host_devloss_work_q_name(x) \
623 (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
624#define fc_host_devloss_work_q(x) \
625 (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
626#define fc_host_dev_loss_tmo(x) \
627 (((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
628
629
630struct fc_function_template {
631 void (*get_rport_dev_loss_tmo)(struct fc_rport *);
632 void (*set_rport_dev_loss_tmo)(struct fc_rport *, u32);
633
634 void (*get_starget_node_name)(struct scsi_target *);
635 void (*get_starget_port_name)(struct scsi_target *);
636 void (*get_starget_port_id)(struct scsi_target *);
637
638 void (*get_host_port_id)(struct Scsi_Host *);
639 void (*get_host_port_type)(struct Scsi_Host *);
640 void (*get_host_port_state)(struct Scsi_Host *);
641 void (*get_host_active_fc4s)(struct Scsi_Host *);
642 void (*get_host_speed)(struct Scsi_Host *);
643 void (*get_host_fabric_name)(struct Scsi_Host *);
644 void (*get_host_symbolic_name)(struct Scsi_Host *);
645 void (*set_host_system_hostname)(struct Scsi_Host *);
646
647 struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
648 void (*reset_fc_host_stats)(struct Scsi_Host *);
649
650 int (*issue_fc_host_lip)(struct Scsi_Host *);
651
652 void (*dev_loss_tmo_callbk)(struct fc_rport *);
653 void (*terminate_rport_io)(struct fc_rport *);
654
655 void (*set_vport_symbolic_name)(struct fc_vport *);
656 int (*vport_create)(struct fc_vport *, bool);
657 int (*vport_disable)(struct fc_vport *, bool);
658 int (*vport_delete)(struct fc_vport *);
659
660
661 int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
662 int (* it_nexus_response)(struct Scsi_Host *, u64, int);
663
664
665 int (*bsg_request)(struct bsg_job *);
666 int (*bsg_timeout)(struct bsg_job *);
667
668
669 u32 dd_fcrport_size;
670 u32 dd_fcvport_size;
671 u32 dd_bsg_size;
672
673
674
675
676
677
678
679
680
681 unsigned long show_rport_maxframe_size:1;
682 unsigned long show_rport_supported_classes:1;
683 unsigned long show_rport_dev_loss_tmo:1;
684
685
686
687
688
689
690 unsigned long show_starget_node_name:1;
691 unsigned long show_starget_port_name:1;
692 unsigned long show_starget_port_id:1;
693
694
695 unsigned long show_host_node_name:1;
696 unsigned long show_host_port_name:1;
697 unsigned long show_host_permanent_port_name:1;
698 unsigned long show_host_supported_classes:1;
699 unsigned long show_host_supported_fc4s:1;
700 unsigned long show_host_supported_speeds:1;
701 unsigned long show_host_maxframe_size:1;
702 unsigned long show_host_serial_number:1;
703 unsigned long show_host_manufacturer:1;
704 unsigned long show_host_model:1;
705 unsigned long show_host_model_description:1;
706 unsigned long show_host_hardware_version:1;
707 unsigned long show_host_driver_version:1;
708 unsigned long show_host_firmware_version:1;
709 unsigned long show_host_optionrom_version:1;
710
711 unsigned long show_host_port_id:1;
712 unsigned long show_host_port_type:1;
713 unsigned long show_host_port_state:1;
714 unsigned long show_host_active_fc4s:1;
715 unsigned long show_host_speed:1;
716 unsigned long show_host_fabric_name:1;
717 unsigned long show_host_symbolic_name:1;
718 unsigned long show_host_system_hostname:1;
719
720 unsigned long disable_target_scan:1;
721};
722
723
724
725
726
727
728
729
730
731
732static inline int
733fc_remote_port_chkready(struct fc_rport *rport)
734{
735 int result;
736
737 switch (rport->port_state) {
738 case FC_PORTSTATE_ONLINE:
739 if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
740 result = 0;
741 else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
742 result = DID_IMM_RETRY << 16;
743 else
744 result = DID_NO_CONNECT << 16;
745 break;
746 case FC_PORTSTATE_BLOCKED:
747 if (rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)
748 result = DID_TRANSPORT_FAILFAST << 16;
749 else
750 result = DID_IMM_RETRY << 16;
751 break;
752 default:
753 result = DID_NO_CONNECT << 16;
754 break;
755 }
756 return result;
757}
758
759static inline u64 wwn_to_u64(u8 *wwn)
760{
761 return get_unaligned_be64(wwn);
762}
763
764static inline void u64_to_wwn(u64 inm, u8 *wwn)
765{
766 put_unaligned_be64(inm, wwn);
767}
768
769
770
771
772
773
774
775
776
777
778
779
780static inline void
781fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state)
782{
783 if ((new_state != FC_VPORT_UNKNOWN) &&
784 (new_state != FC_VPORT_INITIALIZING))
785 vport->vport_last_state = vport->vport_state;
786 vport->vport_state = new_state;
787}
788
789struct scsi_transport_template *fc_attach_transport(
790 struct fc_function_template *);
791void fc_release_transport(struct scsi_transport_template *);
792void fc_remove_host(struct Scsi_Host *);
793struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost,
794 int channel, struct fc_rport_identifiers *ids);
795void fc_remote_port_delete(struct fc_rport *rport);
796void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles);
797int scsi_is_fc_rport(const struct device *);
798u32 fc_get_event_number(void);
799void fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
800 enum fc_host_event_code event_code, u32 event_data);
801void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
802 u32 data_len, char * data_buf, u64 vendor_id);
803
804
805
806
807struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel,
808 struct fc_vport_identifiers *);
809int fc_vport_terminate(struct fc_vport *vport);
810int fc_block_scsi_eh(struct scsi_cmnd *cmnd);
811enum blk_eh_timer_return fc_eh_timed_out(struct scsi_cmnd *scmd);
812
813static inline struct Scsi_Host *fc_bsg_to_shost(struct bsg_job *job)
814{
815 if (scsi_is_host_device(job->dev))
816 return dev_to_shost(job->dev);
817 return rport_to_shost(dev_to_rport(job->dev));
818}
819
820static inline struct fc_rport *fc_bsg_to_rport(struct bsg_job *job)
821{
822 if (scsi_is_fc_rport(job->dev))
823 return dev_to_rport(job->dev);
824 return NULL;
825}
826
827#endif
828